summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/app
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/dpdk/app
parentInitial commit. (diff)
downloadceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz
ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/dpdk/app')
-rw-r--r--src/spdk/dpdk/app/Makefile32
-rw-r--r--src/spdk/dpdk/app/meson.build68
-rw-r--r--src/spdk/dpdk/app/pdump/Makefile18
-rw-r--r--src/spdk/dpdk/app/pdump/main.c1022
-rw-r--r--src/spdk/dpdk/app/pdump/meson.build5
-rw-r--r--src/spdk/dpdk/app/proc-info/Makefile14
-rw-r--r--src/spdk/dpdk/app/proc-info/main.c1356
-rw-r--r--src/spdk/dpdk/app/proc-info/meson.build5
-rw-r--r--src/spdk/dpdk/app/test-acl/Makefile17
-rw-r--r--src/spdk/dpdk/app/test-acl/main.c1097
-rw-r--r--src/spdk/dpdk/app/test-acl/meson.build5
-rw-r--r--src/spdk/dpdk/app/test-bbdev/Makefile30
l---------src/spdk/dpdk/app/test-bbdev/ldpc_dec_default.data1
l---------src/spdk/dpdk/app/test-bbdev/ldpc_enc_default.data1
-rw-r--r--src/spdk/dpdk/app/test-bbdev/main.c362
-rw-r--r--src/spdk/dpdk/app/test-bbdev/main.h128
-rw-r--r--src/spdk/dpdk/app/test-bbdev/meson.build14
-rwxr-xr-xsrc/spdk/dpdk/app/test-bbdev/test-bbdev.py118
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_bbdev.c1371
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_bbdev_perf.c4933
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.c1434
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.h79
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/bbdev_null.data5
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_0.data353
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_1.data684
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_2.data902
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v11835.data49
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v2342_drop.data745
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v7813.data48
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8480.data74
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8568.data255
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v9503.data1215
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v11835.data41
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v2342.data151
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v7813.data43
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v8568.data70
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v9503.data197
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k40_r0_e17280_sbd_negllr.data57
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data643
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_low_snr.data643
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_posllr.data645
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_negllr.data1224
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_posllr.data1225
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c2_k3136_r0_e4920_sbd_negllr_crc24b.data680
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1190_rm.data36
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1194_rm.data36
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1196_rm.data36
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e272_rm.data33
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e120_rm_rvidx.data63
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18444.data156
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18448_crc24a.data159
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e32256_crc24b_rm.data180
-rw-r--r--src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c3_k4800_r2_e14412_crc24b.data153
l---------src/spdk/dpdk/app/test-bbdev/turbo_dec_default.data1
l---------src/spdk/dpdk/app/test-bbdev/turbo_enc_default.data1
-rw-r--r--src/spdk/dpdk/app/test-cmdline/Makefile24
-rw-r--r--src/spdk/dpdk/app/test-cmdline/cmdline_test.c37
-rw-r--r--src/spdk/dpdk/app/test-cmdline/cmdline_test.h10
-rwxr-xr-xsrc/spdk/dpdk/app/test-cmdline/cmdline_test.py89
-rw-r--r--src/spdk/dpdk/app/test-cmdline/cmdline_test_data.py282
-rw-r--r--src/spdk/dpdk/app/test-cmdline/commands.c362
-rw-r--r--src/spdk/dpdk/app/test-cmdline/meson.build5
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/Makefile19
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf.h50
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_options.h86
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_options_parse.c675
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.c569
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.h54
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.c614
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.h24
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.c408
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.h36
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.c442
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.h33
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/main.c548
-rw-r--r--src/spdk/dpdk/app/test-compress-perf/meson.build10
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/Makefile28
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf.h34
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_ops.c777
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_ops.h37
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_options.h163
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_options_parsing.c1239
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.c232
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.h24
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.c376
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.h33
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c495
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.h34
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.c339
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.h34
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c591
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h45
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.c591
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.h86
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.c435
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.h34
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data502
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data504
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data504
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/main.c758
-rw-r--r--src/spdk/dpdk/app/test-crypto-perf/meson.build14
-rw-r--r--src/spdk/dpdk/app/test-eventdev/Makefile32
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_common.h183
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_main.c214
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_options.c450
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_options.h289
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_test.c42
-rw-r--r--src/spdk/dpdk/app/test-eventdev/evt_test.h96
-rw-r--r--src/spdk/dpdk/app/test-eventdev/meson.build17
-rw-r--r--src/spdk/dpdk/app/test-eventdev/parser.c359
-rw-r--r--src/spdk/dpdk/app/test-eventdev/parser.h50
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_order_atq.c205
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_order_common.c361
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_order_common.h125
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_order_queue.c215
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_perf_atq.c308
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_perf_common.c839
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_perf_common.h159
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_perf_queue.c323
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_pipeline_atq.c518
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_pipeline_common.c534
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_pipeline_common.h173
-rw-r--r--src/spdk/dpdk/app/test-eventdev/test_pipeline_queue.c533
-rw-r--r--src/spdk/dpdk/app/test-fib/Makefile18
-rw-r--r--src/spdk/dpdk/app/test-fib/main.c1264
-rw-r--r--src/spdk/dpdk/app/test-fib/meson.build5
-rw-r--r--src/spdk/dpdk/app/test-pipeline/Makefile33
-rw-r--r--src/spdk/dpdk/app/test-pipeline/config.c231
-rw-r--r--src/spdk/dpdk/app/test-pipeline/init.c257
-rw-r--r--src/spdk/dpdk/app/test-pipeline/main.c157
-rw-r--r--src/spdk/dpdk/app/test-pipeline/main.h130
-rw-r--r--src/spdk/dpdk/app/test-pipeline/meson.build14
-rw-r--r--src/spdk/dpdk/app/test-pipeline/pipeline_acl.c249
-rw-r--r--src/spdk/dpdk/app/test-pipeline/pipeline_hash.c469
-rw-r--r--src/spdk/dpdk/app/test-pipeline/pipeline_lpm.c173
-rw-r--r--src/spdk/dpdk/app/test-pipeline/pipeline_lpm_ipv6.c171
-rw-r--r--src/spdk/dpdk/app/test-pipeline/pipeline_stub.c135
-rw-r--r--src/spdk/dpdk/app/test-pipeline/runtime.c155
-rw-r--r--src/spdk/dpdk/app/test-pmd/Makefile76
-rw-r--r--src/spdk/dpdk/app/test-pmd/bpf_cmd.c198
-rw-r--r--src/spdk/dpdk/app/test-pmd/bpf_cmd.h16
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline.c19763
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline_flow.c6888
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline_mtr.c1467
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline_mtr.h24
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline_tm.c2463
-rw-r--r--src/spdk/dpdk/app/test-pmd/cmdline_tm.h32
-rw-r--r--src/spdk/dpdk/app/test-pmd/config.c4318
-rw-r--r--src/spdk/dpdk/app/test-pmd/csumonly.c1112
-rw-r--r--src/spdk/dpdk/app/test-pmd/flowgen.c222
-rw-r--r--src/spdk/dpdk/app/test-pmd/icmpecho.c535
-rw-r--r--src/spdk/dpdk/app/test-pmd/ieee1588fwd.c218
-rw-r--r--src/spdk/dpdk/app/test-pmd/iofwd.c111
-rw-r--r--src/spdk/dpdk/app/test-pmd/macfwd.c141
-rw-r--r--src/spdk/dpdk/app/test-pmd/macswap.c120
-rw-r--r--src/spdk/dpdk/app/test-pmd/macswap.h40
-rw-r--r--src/spdk/dpdk/app/test-pmd/macswap_common.h46
-rw-r--r--src/spdk/dpdk/app/test-pmd/macswap_neon.h97
-rw-r--r--src/spdk/dpdk/app/test-pmd/macswap_sse.h94
-rw-r--r--src/spdk/dpdk/app/test-pmd/meson.build49
-rw-r--r--src/spdk/dpdk/app/test-pmd/noisy_vnf.c279
-rw-r--r--src/spdk/dpdk/app/test-pmd/parameters.c1413
-rw-r--r--src/spdk/dpdk/app/test-pmd/rxonly.c88
-rw-r--r--src/spdk/dpdk/app/test-pmd/softnicfwd.c686
-rw-r--r--src/spdk/dpdk/app/test-pmd/testpmd.c3859
-rw-r--r--src/spdk/dpdk/app/test-pmd/testpmd.h938
-rw-r--r--src/spdk/dpdk/app/test-pmd/txonly.c361
-rw-r--r--src/spdk/dpdk/app/test-pmd/util.c377
-rw-r--r--src/spdk/dpdk/app/test-sad/Makefile17
-rw-r--r--src/spdk/dpdk/app/test-sad/main.c671
-rw-r--r--src/spdk/dpdk/app/test-sad/meson.build5
-rw-r--r--src/spdk/dpdk/app/test/Makefile307
-rw-r--r--src/spdk/dpdk/app/test/autotest.py51
-rw-r--r--src/spdk/dpdk/app/test/autotest_data.py796
-rw-r--r--src/spdk/dpdk/app/test/autotest_runner.py439
-rw-r--r--src/spdk/dpdk/app/test/autotest_test_funcs.py342
-rw-r--r--src/spdk/dpdk/app/test/commands.c383
-rwxr-xr-xsrc/spdk/dpdk/app/test/get-coremask.sh13
-rwxr-xr-xsrc/spdk/dpdk/app/test/has-hugepage.sh11
-rw-r--r--src/spdk/dpdk/app/test/meson.build497
-rw-r--r--src/spdk/dpdk/app/test/packet_burst_generator.c457
-rw-r--r--src/spdk/dpdk/app/test/packet_burst_generator.h78
-rw-r--r--src/spdk/dpdk/app/test/process.h171
-rw-r--r--src/spdk/dpdk/app/test/resource.c276
-rw-r--r--src/spdk/dpdk/app/test/resource.h106
-rw-r--r--src/spdk/dpdk/app/test/sample_packet_forward.c114
-rw-r--r--src/spdk/dpdk/app/test/sample_packet_forward.h47
-rw-r--r--src/spdk/dpdk/app/test/test.c311
-rw-r--r--src/spdk/dpdk/app/test/test.h184
-rw-r--r--src/spdk/dpdk/app/test/test_acl.c1743
-rw-r--r--src/spdk/dpdk/app/test/test_acl.h712
-rw-r--r--src/spdk/dpdk/app/test/test_alarm.c234
-rw-r--r--src/spdk/dpdk/app/test/test_atomic.c634
-rw-r--r--src/spdk/dpdk/app/test/test_barrier.c289
-rw-r--r--src/spdk/dpdk/app/test/test_bitmap.c240
-rw-r--r--src/spdk/dpdk/app/test/test_bitratestats.c240
-rw-r--r--src/spdk/dpdk/app/test/test_bpf.c2783
-rw-r--r--src/spdk/dpdk/app/test/test_byteorder.c66
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfile.c334
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/empty.ini0
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/empty_key_value.ini3
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/invalid_section.ini3
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/line_too_long.ini3
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/missing_section.ini2
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/realloc_sections.ini128
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/sample1.ini12
-rw-r--r--src/spdk/dpdk/app/test/test_cfgfiles/etc/sample2.ini12
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline.c63
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline.h44
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_cirbuf.c1301
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_etheraddr.c208
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_ipaddr.c671
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_lib.c236
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_num.c580
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_portlist.c213
-rw-r--r--src/spdk/dpdk/app/test/test_cmdline_string.c370
-rw-r--r--src/spdk/dpdk/app/test/test_common.c327
-rw-r--r--src/spdk/dpdk/app/test/test_compressdev.c4273
-rw-r--r--src/spdk/dpdk/app/test/test_compressdev_test_buffer.h297
-rw-r--r--src/spdk/dpdk/app/test/test_cpuflags.c176
-rw-r--r--src/spdk/dpdk/app/test/test_crc.c164
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev.c13265
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev.h212
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_aead_test_vectors.h3826
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_aes_test_vectors.h2298
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_asym.c2404
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_asym_util.h60
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_blockcipher.c793
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_blockcipher.h100
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_des_test_vectors.h1189
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_dh_test_vectors.h80
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_dsa_test_vectors.h117
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_ecdsa_test_vectors.h505
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_ecpm_test_vectors.h353
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_hash_test_vectors.h582
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_hmac_test_vectors.h93
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_kasumi_hash_test_vectors.h220
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_kasumi_test_vectors.h437
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_mixed_test_vectors.h1488
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_mod_test_vectors.h1070
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_rsa_test_vectors.h407
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_security_pdcp.c590
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_func.h48
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_vectors.h6323
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_snow3g_hash_test_vectors.h498
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_snow3g_test_vectors.h739
-rw-r--r--src/spdk/dpdk/app/test/test_cryptodev_zuc_test_vectors.h1132
-rw-r--r--src/spdk/dpdk/app/test/test_cycles.c131
-rw-r--r--src/spdk/dpdk/app/test/test_debug.c126
-rw-r--r--src/spdk/dpdk/app/test/test_distributor.c704
-rw-r--r--src/spdk/dpdk/app/test/test_distributor_perf.c268
-rw-r--r--src/spdk/dpdk/app/test/test_eal_flags.c1552
-rw-r--r--src/spdk/dpdk/app/test/test_eal_fs.c177
-rw-r--r--src/spdk/dpdk/app/test/test_efd.c469
-rw-r--r--src/spdk/dpdk/app/test/test_efd_perf.c385
-rw-r--r--src/spdk/dpdk/app/test/test_errno.c87
-rw-r--r--src/spdk/dpdk/app/test/test_event_crypto_adapter.c979
-rw-r--r--src/spdk/dpdk/app/test/test_event_eth_rx_adapter.c721
-rw-r--r--src/spdk/dpdk/app/test/test_event_eth_tx_adapter.c703
-rw-r--r--src/spdk/dpdk/app/test/test_event_ring.c247
-rw-r--r--src/spdk/dpdk/app/test/test_event_timer_adapter.c1844
-rw-r--r--src/spdk/dpdk/app/test/test_eventdev.c1039
-rw-r--r--src/spdk/dpdk/app/test/test_external_mem.c576
-rw-r--r--src/spdk/dpdk/app/test/test_fbarray.c736
-rw-r--r--src/spdk/dpdk/app/test/test_fib.c414
-rw-r--r--src/spdk/dpdk/app/test/test_fib6.c423
-rw-r--r--src/spdk/dpdk/app/test/test_fib6_perf.c157
-rw-r--r--src/spdk/dpdk/app/test/test_fib_perf.c411
-rw-r--r--src/spdk/dpdk/app/test/test_flow_classify.c876
-rw-r--r--src/spdk/dpdk/app/test/test_flow_classify.h26
-rw-r--r--src/spdk/dpdk/app/test/test_func_reentrancy.c498
-rw-r--r--src/spdk/dpdk/app/test/test_graph.c821
-rw-r--r--src/spdk/dpdk/app/test/test_graph_perf.c1063
-rw-r--r--src/spdk/dpdk/app/test/test_hash.c1873
-rw-r--r--src/spdk/dpdk/app/test/test_hash_functions.c293
-rw-r--r--src/spdk/dpdk/app/test/test_hash_multiwriter.c293
-rw-r--r--src/spdk/dpdk/app/test/test_hash_perf.c752
-rw-r--r--src/spdk/dpdk/app/test/test_hash_readwrite.c767
-rw-r--r--src/spdk/dpdk/app/test/test_hash_readwrite_lf_perf.c1435
-rw-r--r--src/spdk/dpdk/app/test/test_interrupts.c562
-rw-r--r--src/spdk/dpdk/app/test/test_ipfrag.c262
-rw-r--r--src/spdk/dpdk/app/test/test_ipsec.c2539
-rw-r--r--src/spdk/dpdk/app/test/test_ipsec_perf.c614
-rw-r--r--src/spdk/dpdk/app/test/test_ipsec_sad.c887
-rw-r--r--src/spdk/dpdk/app/test/test_kni.c765
-rw-r--r--src/spdk/dpdk/app/test/test_kvargs.c261
-rw-r--r--src/spdk/dpdk/app/test/test_latencystats.c209
-rw-r--r--src/spdk/dpdk/app/test/test_link_bonding.c5153
-rw-r--r--src/spdk/dpdk/app/test/test_link_bonding_mode4.c1675
-rw-r--r--src/spdk/dpdk/app/test/test_link_bonding_rssconf.c662
-rw-r--r--src/spdk/dpdk/app/test/test_logs.c109
-rw-r--r--src/spdk/dpdk/app/test/test_lpm.c1289
-rw-r--r--src/spdk/dpdk/app/test/test_lpm6.c1795
-rw-r--r--src/spdk/dpdk/app/test/test_lpm6_data.h1158
-rw-r--r--src/spdk/dpdk/app/test/test_lpm6_perf.c163
-rw-r--r--src/spdk/dpdk/app/test/test_lpm_perf.c484
-rw-r--r--src/spdk/dpdk/app/test/test_malloc.c1080
-rw-r--r--src/spdk/dpdk/app/test/test_mbuf.c2877
-rw-r--r--src/spdk/dpdk/app/test/test_mcslock.c250
-rw-r--r--src/spdk/dpdk/app/test/test_member.c715
-rw-r--r--src/spdk/dpdk/app/test/test_member_perf.c625
-rw-r--r--src/spdk/dpdk/app/test/test_memcpy.c132
-rw-r--r--src/spdk/dpdk/app/test/test_memcpy_perf.c350
-rw-r--r--src/spdk/dpdk/app/test/test_memory.c107
-rw-r--r--src/spdk/dpdk/app/test/test_mempool.c668
-rw-r--r--src/spdk/dpdk/app/test/test_mempool_perf.c399
-rw-r--r--src/spdk/dpdk/app/test/test_memzone.c1129
-rw-r--r--src/spdk/dpdk/app/test/test_meter.c716
-rw-r--r--src/spdk/dpdk/app/test/test_metrics.c329
-rw-r--r--src/spdk/dpdk/app/test/test_mp_secondary.c208
-rw-r--r--src/spdk/dpdk/app/test/test_pdump.c214
-rw-r--r--src/spdk/dpdk/app/test/test_pdump.h31
-rw-r--r--src/spdk/dpdk/app/test/test_per_lcore.c108
-rw-r--r--src/spdk/dpdk/app/test/test_pmd_perf.c888
-rw-r--r--src/spdk/dpdk/app/test/test_pmd_ring.c579
-rw-r--r--src/spdk/dpdk/app/test/test_pmd_ring_perf.c165
-rw-r--r--src/spdk/dpdk/app/test/test_power.c174
-rw-r--r--src/spdk/dpdk/app/test/test_power_cpufreq.c644
-rw-r--r--src/spdk/dpdk/app/test/test_power_kvm_vm.c302
-rw-r--r--src/spdk/dpdk/app/test/test_prefetch.c32
-rw-r--r--src/spdk/dpdk/app/test/test_rand_perf.c92
-rw-r--r--src/spdk/dpdk/app/test/test_rawdev.c47
-rw-r--r--src/spdk/dpdk/app/test/test_rcu_qsbr.c1411
-rw-r--r--src/spdk/dpdk/app/test/test_rcu_qsbr_perf.c690
-rw-r--r--src/spdk/dpdk/app/test/test_reciprocal_division.c167
-rw-r--r--src/spdk/dpdk/app/test/test_reciprocal_division_perf.c201
-rw-r--r--src/spdk/dpdk/app/test/test_red.c1856
-rw-r--r--src/spdk/dpdk/app/test/test_reorder.c393
-rw-r--r--src/spdk/dpdk/app/test/test_resource.c104
-rw-r--r--src/spdk/dpdk/app/test/test_rib.c367
-rw-r--r--src/spdk/dpdk/app/test/test_rib6.c372
-rw-r--r--src/spdk/dpdk/app/test/test_ring.c922
-rw-r--r--src/spdk/dpdk/app/test/test_ring.h187
-rw-r--r--src/spdk/dpdk/app/test/test_ring_hts_stress.c32
-rw-r--r--src/spdk/dpdk/app/test/test_ring_mpmc_stress.c31
-rw-r--r--src/spdk/dpdk/app/test/test_ring_peek_stress.c43
-rw-r--r--src/spdk/dpdk/app/test/test_ring_perf.c582
-rw-r--r--src/spdk/dpdk/app/test/test_ring_rts_stress.c32
-rw-r--r--src/spdk/dpdk/app/test/test_ring_stress.c57
-rw-r--r--src/spdk/dpdk/app/test/test_ring_stress.h38
-rw-r--r--src/spdk/dpdk/app/test/test_ring_stress_impl.h396
-rw-r--r--src/spdk/dpdk/app/test/test_rwlock.c555
-rw-r--r--src/spdk/dpdk/app/test/test_sched.c198
-rw-r--r--src/spdk/dpdk/app/test/test_security.c2427
-rw-r--r--src/spdk/dpdk/app/test/test_service_cores.c944
-rw-r--r--src/spdk/dpdk/app/test/test_spinlock.c306
-rw-r--r--src/spdk/dpdk/app/test/test_stack.c426
-rw-r--r--src/spdk/dpdk/app/test/test_stack_perf.c356
-rw-r--r--src/spdk/dpdk/app/test/test_string_fns.c185
-rw-r--r--src/spdk/dpdk/app/test/test_table.c197
-rw-r--r--src/spdk/dpdk/app/test/test_table.h184
-rw-r--r--src/spdk/dpdk/app/test/test_table_acl.c730
-rw-r--r--src/spdk/dpdk/app/test/test_table_acl.h6
-rw-r--r--src/spdk/dpdk/app/test/test_table_combined.c842
-rw-r--r--src/spdk/dpdk/app/test/test_table_combined.h27
-rw-r--r--src/spdk/dpdk/app/test/test_table_pipeline.c571
-rw-r--r--src/spdk/dpdk/app/test/test_table_pipeline.h6
-rw-r--r--src/spdk/dpdk/app/test/test_table_ports.c191
-rw-r--r--src/spdk/dpdk/app/test/test_table_ports.h13
-rw-r--r--src/spdk/dpdk/app/test/test_table_tables.c1053
-rw-r--r--src/spdk/dpdk/app/test/test_table_tables.h22
-rw-r--r--src/spdk/dpdk/app/test/test_tailq.c128
-rw-r--r--src/spdk/dpdk/app/test/test_telemetry_json.c136
-rw-r--r--src/spdk/dpdk/app/test/test_thash.c143
-rw-r--r--src/spdk/dpdk/app/test/test_ticketlock.c319
-rw-r--r--src/spdk/dpdk/app/test/test_timer.c600
-rw-r--r--src/spdk/dpdk/app/test/test_timer_perf.c134
-rw-r--r--src/spdk/dpdk/app/test/test_timer_racecond.c206
-rw-r--r--src/spdk/dpdk/app/test/test_timer_secondary.c216
-rw-r--r--src/spdk/dpdk/app/test/test_trace.c213
-rw-r--r--src/spdk/dpdk/app/test/test_trace.h15
-rw-r--r--src/spdk/dpdk/app/test/test_trace_perf.c183
-rw-r--r--src/spdk/dpdk/app/test/test_trace_register.c18
-rw-r--r--src/spdk/dpdk/app/test/test_version.c28
-rw-r--r--src/spdk/dpdk/app/test/test_xmmt_ops.h54
-rw-r--r--src/spdk/dpdk/app/test/virtual_pmd.c612
-rw-r--r--src/spdk/dpdk/app/test/virtual_pmd.h77
377 files changed, 223678 insertions, 0 deletions
diff --git a/src/spdk/dpdk/app/Makefile b/src/spdk/dpdk/app/Makefile
new file mode 100644
index 000000000..823771c5f
--- /dev/null
+++ b/src/spdk/dpdk/app/Makefile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+DIRS-$(CONFIG_RTE_APP_TEST) += test
+DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd
+DIRS-$(CONFIG_RTE_PROC_INFO) += proc-info
+DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += pdump
+DIRS-$(CONFIG_RTE_LIBRTE_ACL) += test-acl
+DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test-cmdline
+DIRS-$(CONFIG_RTE_LIBRTE_FIB) += test-fib
+DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test-pipeline
+DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += test-sad
+
+ifeq ($(CONFIG_RTE_LIBRTE_BBDEV),y)
+DIRS-$(CONFIG_RTE_TEST_BBDEV) += test-bbdev
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_COMPRESSDEV),y)
+DIRS-$(CONFIG_RTE_APP_COMPRESS_PERF) += test-compress-perf
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_CRYPTODEV),y)
+DIRS-$(CONFIG_RTE_APP_CRYPTO_PERF) += test-crypto-perf
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y)
+DIRS-$(CONFIG_RTE_APP_EVENTDEV) += test-eventdev
+endif
+
+include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/src/spdk/dpdk/app/meson.build b/src/spdk/dpdk/app/meson.build
new file mode 100644
index 000000000..0f7fe9464
--- /dev/null
+++ b/src/spdk/dpdk/app/meson.build
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017-2019 Intel Corporation
+
+if is_windows
+ subdir_done()
+endif
+
+apps = [
+ 'pdump',
+ 'proc-info',
+ 'test-acl',
+ 'test-bbdev',
+ 'test-cmdline',
+ 'test-compress-perf',
+ 'test-crypto-perf',
+ 'test-eventdev',
+ 'test-fib',
+ 'test-pipeline',
+ 'test-pmd',
+ 'test-sad']
+
+# for BSD only
+lib_execinfo = cc.find_library('execinfo', required: false)
+
+default_cflags = machine_args + ['-DALLOW_EXPERIMENTAL_API']
+
+foreach app:apps
+ build = true
+ name = app
+ sources = []
+ includes = []
+ cflags = default_cflags
+ objs = [] # other object files to link against, used e.g. for
+ # instruction-set optimized versions of code
+
+ # use "deps" for internal DPDK dependencies, and "ext_deps" for
+ # external package/library requirements
+ ext_deps = []
+ deps = dpdk_app_link_libraries
+
+ subdir(name)
+
+ if build
+ dep_objs = []
+ foreach d:deps
+ dep_objs += get_variable(get_option('default_library')
+ + '_rte_' + d)
+ endforeach
+ dep_objs += lib_execinfo
+
+ link_libs = []
+ if get_option('default_library') == 'static'
+ link_libs = dpdk_static_libraries + dpdk_drivers
+ endif
+
+ executable('dpdk-' + name,
+ sources,
+ c_args: cflags,
+ link_whole: link_libs,
+ dependencies: dep_objs,
+ install_rpath: join_paths(get_option('prefix'),
+ driver_install_path),
+ install: true)
+ endif
+endforeach
+
+# special case the autotests
+subdir('test')
diff --git a/src/spdk/dpdk/app/pdump/Makefile b/src/spdk/dpdk/app/pdump/Makefile
new file mode 100644
index 000000000..e6b9eea91
--- /dev/null
+++ b/src/spdk/dpdk/app/pdump/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2016 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_PDUMP),y)
+
+APP = dpdk-pdump
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/pdump/main.c b/src/spdk/dpdk/app/pdump/main.c
new file mode 100644
index 000000000..c38c53719
--- /dev/null
+++ b/src/spdk/dpdk/app/pdump/main.c
@@ -0,0 +1,1022 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <net/if.h>
+
+#include <rte_eal.h>
+#include <rte_alarm.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_memory.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_errno.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+#include <rte_mempool.h>
+#include <rte_ring.h>
+#include <rte_string_fns.h>
+#include <rte_pdump.h>
+
+#define CMD_LINE_OPT_PDUMP "pdump"
+#define CMD_LINE_OPT_PDUMP_NUM 256
+#define CMD_LINE_OPT_MULTI "multi"
+#define CMD_LINE_OPT_MULTI_NUM 257
+#define PDUMP_PORT_ARG "port"
+#define PDUMP_PCI_ARG "device_id"
+#define PDUMP_QUEUE_ARG "queue"
+#define PDUMP_DIR_ARG "dir"
+#define PDUMP_RX_DEV_ARG "rx-dev"
+#define PDUMP_TX_DEV_ARG "tx-dev"
+#define PDUMP_RING_SIZE_ARG "ring-size"
+#define PDUMP_MSIZE_ARG "mbuf-size"
+#define PDUMP_NUM_MBUFS_ARG "total-num-mbufs"
+
+#define VDEV_NAME_FMT "net_pcap_%s_%d"
+#define VDEV_PCAP_ARGS_FMT "tx_pcap=%s"
+#define VDEV_IFACE_ARGS_FMT "tx_iface=%s"
+#define TX_STREAM_SIZE 64
+
+#define MP_NAME "pdump_pool_%d"
+
+#define RX_RING "rx_ring_%d"
+#define TX_RING "tx_ring_%d"
+
+#define RX_STR "rx"
+#define TX_STR "tx"
+
+/* Maximum long option length for option parsing. */
+#define APP_ARG_TCPDUMP_MAX_TUPLES 54
+#define MBUF_POOL_CACHE_SIZE 250
+#define TX_DESC_PER_QUEUE 512
+#define RX_DESC_PER_QUEUE 128
+#define MBUFS_PER_POOL 65535
+#define MAX_LONG_OPT_SZ 64
+#define RING_SIZE 16384
+#define SIZE 256
+#define BURST_SIZE 32
+#define NUM_VDEVS 2
+/* Maximum delay for exiting after primary process. */
+#define MONITOR_INTERVAL (500 * 1000)
+
+/* true if x is a power of 2 */
+#define POWEROF2(x) ((((x)-1) & (x)) == 0)
+
+enum pdump_en_dis {
+ DISABLE = 1,
+ ENABLE = 2
+};
+
+enum pcap_stream {
+ IFACE = 1,
+ PCAP = 2
+};
+
+enum pdump_by {
+ PORT_ID = 1,
+ DEVICE_ID = 2
+};
+
+static const char * const valid_pdump_arguments[] = {
+ PDUMP_PORT_ARG,
+ PDUMP_PCI_ARG,
+ PDUMP_QUEUE_ARG,
+ PDUMP_DIR_ARG,
+ PDUMP_RX_DEV_ARG,
+ PDUMP_TX_DEV_ARG,
+ PDUMP_RING_SIZE_ARG,
+ PDUMP_MSIZE_ARG,
+ PDUMP_NUM_MBUFS_ARG,
+ NULL
+};
+
+struct pdump_stats {
+ uint64_t dequeue_pkts;
+ uint64_t tx_pkts;
+ uint64_t freed_pkts;
+};
+
+struct pdump_tuples {
+ /* cli params */
+ uint16_t port;
+ char *device_id;
+ uint16_t queue;
+ char rx_dev[TX_STREAM_SIZE];
+ char tx_dev[TX_STREAM_SIZE];
+ uint32_t ring_size;
+ uint16_t mbuf_data_size;
+ uint32_t total_num_mbufs;
+
+ /* params for library API call */
+ uint32_t dir;
+ struct rte_mempool *mp;
+ struct rte_ring *rx_ring;
+ struct rte_ring *tx_ring;
+
+ /* params for packet dumping */
+ enum pdump_by dump_by_type;
+ uint16_t rx_vdev_id;
+ uint16_t tx_vdev_id;
+ enum pcap_stream rx_vdev_stream_type;
+ enum pcap_stream tx_vdev_stream_type;
+ bool single_pdump_dev;
+
+ /* stats */
+ struct pdump_stats stats;
+} __rte_cache_aligned;
+static struct pdump_tuples pdump_t[APP_ARG_TCPDUMP_MAX_TUPLES];
+
+struct parse_val {
+ uint64_t min;
+ uint64_t max;
+ uint64_t val;
+};
+
+static int num_tuples;
+static struct rte_eth_conf port_conf_default;
+static volatile uint8_t quit_signal;
+static uint8_t multiple_core_capture;
+
+/**< display usage */
+static void
+pdump_usage(const char *prgname)
+{
+ printf("usage: %s [EAL options] --"
+ " --["CMD_LINE_OPT_MULTI"]\n"
+ " --"CMD_LINE_OPT_PDUMP" "
+ "'(port=<port id> | device_id=<pci id or vdev name>),"
+ "(queue=<queue_id>),"
+ "(rx-dev=<iface or pcap file> |"
+ " tx-dev=<iface or pcap file>,"
+ "[ring-size=<ring size>default:16384],"
+ "[mbuf-size=<mbuf data size>default:2176],"
+ "[total-num-mbufs=<number of mbufs>default:65535]'\n",
+ prgname);
+}
+
+static int
+parse_device_id(const char *key __rte_unused, const char *value,
+ void *extra_args)
+{
+ struct pdump_tuples *pt = extra_args;
+
+ pt->device_id = strdup(value);
+ pt->dump_by_type = DEVICE_ID;
+
+ return 0;
+}
+
+static int
+parse_queue(const char *key __rte_unused, const char *value, void *extra_args)
+{
+ unsigned long n;
+ struct pdump_tuples *pt = extra_args;
+
+ if (!strcmp(value, "*"))
+ pt->queue = RTE_PDUMP_ALL_QUEUES;
+ else {
+ n = strtoul(value, NULL, 10);
+ pt->queue = (uint16_t) n;
+ }
+ return 0;
+}
+
+static int
+parse_rxtxdev(const char *key, const char *value, void *extra_args)
+{
+
+ struct pdump_tuples *pt = extra_args;
+
+ if (!strcmp(key, PDUMP_RX_DEV_ARG)) {
+ strlcpy(pt->rx_dev, value, sizeof(pt->rx_dev));
+ /* identify the tx stream type for pcap vdev */
+ if (if_nametoindex(pt->rx_dev))
+ pt->rx_vdev_stream_type = IFACE;
+ } else if (!strcmp(key, PDUMP_TX_DEV_ARG)) {
+ strlcpy(pt->tx_dev, value, sizeof(pt->tx_dev));
+ /* identify the tx stream type for pcap vdev */
+ if (if_nametoindex(pt->tx_dev))
+ pt->tx_vdev_stream_type = IFACE;
+ }
+
+ return 0;
+}
+
+static int
+parse_uint_value(const char *key, const char *value, void *extra_args)
+{
+ struct parse_val *v;
+ unsigned long t;
+ char *end;
+ int ret = 0;
+
+ errno = 0;
+ v = extra_args;
+ t = strtoul(value, &end, 10);
+
+ if (errno != 0 || end[0] != 0 || t < v->min || t > v->max) {
+ printf("invalid value:\"%s\" for key:\"%s\", "
+ "value must be >= %"PRIu64" and <= %"PRIu64"\n",
+ value, key, v->min, v->max);
+ ret = -EINVAL;
+ }
+ if (!strcmp(key, PDUMP_RING_SIZE_ARG) && !POWEROF2(t)) {
+ printf("invalid value:\"%s\" for key:\"%s\", "
+ "value must be power of 2\n", value, key);
+ ret = -EINVAL;
+ }
+
+ if (ret != 0)
+ return ret;
+
+ v->val = t;
+ return 0;
+}
+
+static int
+parse_pdump(const char *optarg)
+{
+ struct rte_kvargs *kvlist;
+ int ret = 0, cnt1, cnt2;
+ struct pdump_tuples *pt;
+ struct parse_val v = {0};
+
+ pt = &pdump_t[num_tuples];
+
+ /* initial check for invalid arguments */
+ kvlist = rte_kvargs_parse(optarg, valid_pdump_arguments);
+ if (kvlist == NULL) {
+ printf("--pdump=\"%s\": invalid argument passed\n", optarg);
+ return -1;
+ }
+
+ /* port/device_id parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_PORT_ARG);
+ cnt2 = rte_kvargs_count(kvlist, PDUMP_PCI_ARG);
+ if (!((cnt1 == 1 && cnt2 == 0) || (cnt1 == 0 && cnt2 == 1))) {
+ printf("--pdump=\"%s\": must have either port or "
+ "device_id argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ } else if (cnt1 == 1) {
+ v.min = 0;
+ v.max = RTE_MAX_ETHPORTS-1;
+ ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->port = (uint16_t) v.val;
+ pt->dump_by_type = PORT_ID;
+ } else if (cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
+ &parse_device_id, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ }
+
+ /* queue parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_QUEUE_ARG);
+ if (cnt1 != 1) {
+ printf("--pdump=\"%s\": must have queue argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ }
+ ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, &parse_queue, pt);
+ if (ret < 0)
+ goto free_kvlist;
+
+ /* rx-dev and tx-dev parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_RX_DEV_ARG);
+ cnt2 = rte_kvargs_count(kvlist, PDUMP_TX_DEV_ARG);
+ if (cnt1 == 0 && cnt2 == 0) {
+ printf("--pdump=\"%s\": must have either rx-dev or "
+ "tx-dev argument\n", optarg);
+ ret = -1;
+ goto free_kvlist;
+ } else if (cnt1 == 1 && cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ /* if captured packets has to send to the same vdev */
+ if (!strcmp(pt->rx_dev, pt->tx_dev))
+ pt->single_pdump_dev = true;
+ pt->dir = RTE_PDUMP_FLAG_RXTX;
+ } else if (cnt1 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->dir = RTE_PDUMP_FLAG_RX;
+ } else if (cnt2 == 1) {
+ ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+ &parse_rxtxdev, pt);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->dir = RTE_PDUMP_FLAG_TX;
+ }
+
+ /* optional */
+ /* ring_size parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_RING_SIZE_ARG);
+ if (cnt1 == 1) {
+ v.min = 2;
+ v.max = RTE_RING_SZ_MASK-1;
+ ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->ring_size = (uint32_t) v.val;
+ } else
+ pt->ring_size = RING_SIZE;
+
+ /* mbuf_data_size parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_MSIZE_ARG);
+ if (cnt1 == 1) {
+ v.min = 1;
+ v.max = UINT16_MAX;
+ ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->mbuf_data_size = (uint16_t) v.val;
+ } else
+ pt->mbuf_data_size = RTE_MBUF_DEFAULT_BUF_SIZE;
+
+ /* total_num_mbufs parsing and validation */
+ cnt1 = rte_kvargs_count(kvlist, PDUMP_NUM_MBUFS_ARG);
+ if (cnt1 == 1) {
+ v.min = 1025;
+ v.max = UINT16_MAX;
+ ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG,
+ &parse_uint_value, &v);
+ if (ret < 0)
+ goto free_kvlist;
+ pt->total_num_mbufs = (uint16_t) v.val;
+ } else
+ pt->total_num_mbufs = MBUFS_PER_POOL;
+
+ num_tuples++;
+
+free_kvlist:
+ rte_kvargs_free(kvlist);
+ return ret;
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+launch_args_parse(int argc, char **argv, char *prgname)
+{
+ int opt, ret;
+ int option_index;
+ static struct option long_option[] = {
+ {CMD_LINE_OPT_PDUMP, 1, 0, CMD_LINE_OPT_PDUMP_NUM},
+ {CMD_LINE_OPT_MULTI, 0, 0, CMD_LINE_OPT_MULTI_NUM},
+ {NULL, 0, 0, 0}
+ };
+
+ if (argc == 1)
+ pdump_usage(prgname);
+
+ /* Parse command line */
+ while ((opt = getopt_long(argc, argv, " ",
+ long_option, &option_index)) != EOF) {
+ switch (opt) {
+ case CMD_LINE_OPT_PDUMP_NUM:
+ ret = parse_pdump(optarg);
+ if (ret) {
+ pdump_usage(prgname);
+ return -1;
+ }
+ break;
+ case CMD_LINE_OPT_MULTI_NUM:
+ multiple_core_capture = 1;
+ break;
+ default:
+ pdump_usage(prgname);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+monitor_primary(void *arg __rte_unused)
+{
+ if (quit_signal)
+ return;
+
+ if (rte_eal_primary_proc_alive(NULL)) {
+ rte_eal_alarm_set(MONITOR_INTERVAL, monitor_primary, NULL);
+ return;
+ }
+
+ printf("Primary process is no longer active, exiting...\n");
+ quit_signal = 1;
+}
+
+static void
+print_pdump_stats(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ for (i = 0; i < num_tuples; i++) {
+ printf("##### PDUMP DEBUG STATS #####\n");
+ pt = &pdump_t[i];
+ printf(" -packets dequeued: %"PRIu64"\n",
+ pt->stats.dequeue_pkts);
+ printf(" -packets transmitted to vdev: %"PRIu64"\n",
+ pt->stats.tx_pkts);
+ printf(" -packets freed: %"PRIu64"\n",
+ pt->stats.freed_pkts);
+ }
+}
+
+static inline void
+disable_pdump(struct pdump_tuples *pt)
+{
+ if (pt->dump_by_type == DEVICE_ID)
+ rte_pdump_disable_by_deviceid(pt->device_id, pt->queue,
+ pt->dir);
+ else if (pt->dump_by_type == PORT_ID)
+ rte_pdump_disable(pt->port, pt->queue, pt->dir);
+}
+
+static inline void
+pdump_rxtx(struct rte_ring *ring, uint16_t vdev_id, struct pdump_stats *stats)
+{
+ /* write input packets of port to vdev for pdump */
+ struct rte_mbuf *rxtx_bufs[BURST_SIZE];
+
+ /* first dequeue packets from ring of primary process */
+ const uint16_t nb_in_deq = rte_ring_dequeue_burst(ring,
+ (void *)rxtx_bufs, BURST_SIZE, NULL);
+ stats->dequeue_pkts += nb_in_deq;
+
+ if (nb_in_deq) {
+ /* then sent on vdev */
+ uint16_t nb_in_txd = rte_eth_tx_burst(
+ vdev_id,
+ 0, rxtx_bufs, nb_in_deq);
+ stats->tx_pkts += nb_in_txd;
+
+ if (unlikely(nb_in_txd < nb_in_deq)) {
+ do {
+ rte_pktmbuf_free(rxtx_bufs[nb_in_txd]);
+ stats->freed_pkts++;
+ } while (++nb_in_txd < nb_in_deq);
+ }
+ }
+}
+
+static void
+free_ring_data(struct rte_ring *ring, uint16_t vdev_id,
+ struct pdump_stats *stats)
+{
+ while (rte_ring_count(ring))
+ pdump_rxtx(ring, vdev_id, stats);
+}
+
+static void
+cleanup_rings(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+
+ if (pt->device_id)
+ free(pt->device_id);
+
+ /* free the rings */
+ if (pt->rx_ring)
+ rte_ring_free(pt->rx_ring);
+ if (pt->tx_ring)
+ rte_ring_free(pt->tx_ring);
+ }
+}
+
+static void
+cleanup_pdump_resources(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+ char name[RTE_ETH_NAME_MAX_LEN];
+
+ /* disable pdump and free the pdump_tuple resources */
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+
+ /* remove callbacks */
+ disable_pdump(pt);
+
+ /*
+ * transmit rest of the enqueued packets of the rings on to
+ * the vdev, in order to release mbufs to the mepool.
+ **/
+ if (pt->dir & RTE_PDUMP_FLAG_RX)
+ free_ring_data(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
+ if (pt->dir & RTE_PDUMP_FLAG_TX)
+ free_ring_data(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
+
+ /* Remove the vdev(s) created */
+ if (pt->dir & RTE_PDUMP_FLAG_RX) {
+ rte_eth_dev_get_name_by_port(pt->rx_vdev_id, name);
+ rte_eal_hotplug_remove("vdev", name);
+ }
+
+ if (pt->single_pdump_dev)
+ continue;
+
+ if (pt->dir & RTE_PDUMP_FLAG_TX) {
+ rte_eth_dev_get_name_by_port(pt->tx_vdev_id, name);
+ rte_eal_hotplug_remove("vdev", name);
+ }
+
+ }
+ cleanup_rings();
+}
+
+static void
+disable_primary_monitor(void)
+{
+ int ret;
+
+ /*
+ * Cancel monitoring of primary process.
+ * There will be no error if no alarm is set
+ * (in case primary process kill was detected earlier).
+ */
+ ret = rte_eal_alarm_cancel(monitor_primary, NULL);
+ if (ret < 0)
+ printf("Fail to disable monitor:%d\n", ret);
+}
+
+static void
+signal_handler(int sig_num)
+{
+ if (sig_num == SIGINT) {
+ printf("\n\nSignal %d received, preparing to exit...\n",
+ sig_num);
+ quit_signal = 1;
+ }
+}
+
+static inline int
+configure_vdev(uint16_t port_id)
+{
+ struct rte_ether_addr addr;
+ const uint16_t rxRings = 0, txRings = 1;
+ int ret;
+ uint16_t q;
+
+ if (!rte_eth_dev_is_valid_port(port_id))
+ return -1;
+
+ ret = rte_eth_dev_configure(port_id, rxRings, txRings,
+ &port_conf_default);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE, "dev config failed\n");
+
+ for (q = 0; q < txRings; q++) {
+ ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE,
+ rte_eth_dev_socket_id(port_id), NULL);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "queue setup failed\n");
+ }
+
+ ret = rte_eth_dev_start(port_id);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "dev start failed\n");
+
+ ret = rte_eth_macaddr_get(port_id, &addr);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE, "macaddr get failed\n");
+
+ printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
+ " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
+ port_id,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ ret = rte_eth_promiscuous_enable(port_id);
+ if (ret != 0) {
+ rte_exit(EXIT_FAILURE,
+ "promiscuous mode enable failed: %s\n",
+ rte_strerror(-ret));
+ return ret;
+ }
+
+ return 0;
+}
+
+static void
+create_mp_ring_vdev(void)
+{
+ int i;
+ uint16_t portid;
+ struct pdump_tuples *pt = NULL;
+ struct rte_mempool *mbuf_pool = NULL;
+ char vdev_name[SIZE];
+ char vdev_args[SIZE];
+ char ring_name[SIZE];
+ char mempool_name[SIZE];
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+ snprintf(mempool_name, SIZE, MP_NAME, i);
+ mbuf_pool = rte_mempool_lookup(mempool_name);
+ if (mbuf_pool == NULL) {
+ /* create mempool */
+ mbuf_pool = rte_pktmbuf_pool_create_by_ops(mempool_name,
+ pt->total_num_mbufs,
+ MBUF_POOL_CACHE_SIZE, 0,
+ pt->mbuf_data_size,
+ rte_socket_id(), "ring_mp_mc");
+ if (mbuf_pool == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "Mempool creation failed: %s\n",
+ rte_strerror(rte_errno));
+ }
+ }
+ pt->mp = mbuf_pool;
+
+ if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
+ /* if captured packets has to send to the same vdev */
+ /* create rx_ring */
+ snprintf(ring_name, SIZE, RX_RING, i);
+ pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->rx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
+ rte_strerror(rte_errno),
+ __func__, __LINE__);
+ }
+
+ /* create tx_ring */
+ snprintf(ring_name, SIZE, TX_RING, i);
+ pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->tx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s:%s:%d\n",
+ rte_strerror(rte_errno),
+ __func__, __LINE__);
+ }
+
+ /* create vdevs */
+ snprintf(vdev_name, sizeof(vdev_name),
+ VDEV_NAME_FMT, RX_STR, i);
+ (pt->rx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_PCAP_ARGS_FMT, pt->rx_dev);
+ if (rte_eal_hotplug_add("vdev", vdev_name,
+ vdev_args) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:%s:%d\n",
+ __func__, __LINE__);
+ }
+ if (rte_eth_dev_get_port_by_name(vdev_name,
+ &portid) != 0) {
+ rte_eal_hotplug_remove("vdev", vdev_name);
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "cannot find added vdev %s:%s:%d\n",
+ vdev_name, __func__, __LINE__);
+ }
+ pt->rx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->rx_vdev_id);
+
+ if (pt->single_pdump_dev)
+ pt->tx_vdev_id = portid;
+ else {
+ snprintf(vdev_name, sizeof(vdev_name),
+ VDEV_NAME_FMT, TX_STR, i);
+ (pt->rx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_PCAP_ARGS_FMT, pt->tx_dev);
+ if (rte_eal_hotplug_add("vdev", vdev_name,
+ vdev_args) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:"
+ "%s:%d\n", __func__, __LINE__);
+ }
+ if (rte_eth_dev_get_port_by_name(vdev_name,
+ &portid) != 0) {
+ rte_eal_hotplug_remove("vdev",
+ vdev_name);
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "cannot find added vdev %s:%s:%d\n",
+ vdev_name, __func__, __LINE__);
+ }
+ pt->tx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->tx_vdev_id);
+ }
+ } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
+
+ /* create rx_ring */
+ snprintf(ring_name, SIZE, RX_RING, i);
+ pt->rx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->rx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s\n",
+ rte_strerror(rte_errno));
+ }
+
+ snprintf(vdev_name, sizeof(vdev_name),
+ VDEV_NAME_FMT, RX_STR, i);
+ (pt->rx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_IFACE_ARGS_FMT, pt->rx_dev) :
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_PCAP_ARGS_FMT, pt->rx_dev);
+ if (rte_eal_hotplug_add("vdev", vdev_name,
+ vdev_args) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed:%s:%d\n",
+ __func__, __LINE__);
+ }
+ if (rte_eth_dev_get_port_by_name(vdev_name,
+ &portid) != 0) {
+ rte_eal_hotplug_remove("vdev", vdev_name);
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "cannot find added vdev %s:%s:%d\n",
+ vdev_name, __func__, __LINE__);
+ }
+ pt->rx_vdev_id = portid;
+ /* configure vdev */
+ configure_vdev(pt->rx_vdev_id);
+ } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
+
+ /* create tx_ring */
+ snprintf(ring_name, SIZE, TX_RING, i);
+ pt->tx_ring = rte_ring_create(ring_name, pt->ring_size,
+ rte_socket_id(), 0);
+ if (pt->tx_ring == NULL) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE, "%s\n",
+ rte_strerror(rte_errno));
+ }
+
+ snprintf(vdev_name, sizeof(vdev_name),
+ VDEV_NAME_FMT, TX_STR, i);
+ (pt->tx_vdev_stream_type == IFACE) ?
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_IFACE_ARGS_FMT, pt->tx_dev) :
+ snprintf(vdev_args, sizeof(vdev_args),
+ VDEV_PCAP_ARGS_FMT, pt->tx_dev);
+ if (rte_eal_hotplug_add("vdev", vdev_name,
+ vdev_args) < 0) {
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "vdev creation failed\n");
+ }
+ if (rte_eth_dev_get_port_by_name(vdev_name,
+ &portid) != 0) {
+ rte_eal_hotplug_remove("vdev", vdev_name);
+ cleanup_rings();
+ rte_exit(EXIT_FAILURE,
+ "cannot find added vdev %s:%s:%d\n",
+ vdev_name, __func__, __LINE__);
+ }
+ pt->tx_vdev_id = portid;
+
+ /* configure vdev */
+ configure_vdev(pt->tx_vdev_id);
+ }
+ }
+}
+
+static void
+enable_pdump(void)
+{
+ int i;
+ struct pdump_tuples *pt;
+ int ret = 0, ret1 = 0;
+
+ for (i = 0; i < num_tuples; i++) {
+ pt = &pdump_t[i];
+ if (pt->dir == RTE_PDUMP_FLAG_RXTX) {
+ if (pt->dump_by_type == DEVICE_ID) {
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ RTE_PDUMP_FLAG_RX,
+ pt->rx_ring,
+ pt->mp, NULL);
+ ret1 = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ RTE_PDUMP_FLAG_TX,
+ pt->tx_ring,
+ pt->mp, NULL);
+ } else if (pt->dump_by_type == PORT_ID) {
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ RTE_PDUMP_FLAG_RX,
+ pt->rx_ring, pt->mp, NULL);
+ ret1 = rte_pdump_enable(pt->port, pt->queue,
+ RTE_PDUMP_FLAG_TX,
+ pt->tx_ring, pt->mp, NULL);
+ }
+ } else if (pt->dir == RTE_PDUMP_FLAG_RX) {
+ if (pt->dump_by_type == DEVICE_ID)
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ pt->dir, pt->rx_ring,
+ pt->mp, NULL);
+ else if (pt->dump_by_type == PORT_ID)
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ pt->dir,
+ pt->rx_ring, pt->mp, NULL);
+ } else if (pt->dir == RTE_PDUMP_FLAG_TX) {
+ if (pt->dump_by_type == DEVICE_ID)
+ ret = rte_pdump_enable_by_deviceid(
+ pt->device_id,
+ pt->queue,
+ pt->dir,
+ pt->tx_ring, pt->mp, NULL);
+ else if (pt->dump_by_type == PORT_ID)
+ ret = rte_pdump_enable(pt->port, pt->queue,
+ pt->dir,
+ pt->tx_ring, pt->mp, NULL);
+ }
+ if (ret < 0 || ret1 < 0) {
+ cleanup_pdump_resources();
+ rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno));
+ }
+ }
+}
+
+static inline void
+pdump_packets(struct pdump_tuples *pt)
+{
+ if (pt->dir & RTE_PDUMP_FLAG_RX)
+ pdump_rxtx(pt->rx_ring, pt->rx_vdev_id, &pt->stats);
+ if (pt->dir & RTE_PDUMP_FLAG_TX)
+ pdump_rxtx(pt->tx_ring, pt->tx_vdev_id, &pt->stats);
+}
+
+static int
+dump_packets_core(void *arg)
+{
+ struct pdump_tuples *pt = (struct pdump_tuples *) arg;
+
+ printf(" core (%u); port %u device (%s) queue %u\n",
+ rte_lcore_id(), pt->port, pt->device_id, pt->queue);
+ fflush(stdout);
+
+ while (!quit_signal)
+ pdump_packets(pt);
+
+ return 0;
+}
+
+static inline void
+dump_packets(void)
+{
+ int i;
+ uint32_t lcore_id = 0;
+
+ if (!multiple_core_capture) {
+ printf(" core (%u), capture for (%d) tuples\n",
+ rte_lcore_id(), num_tuples);
+
+ for (i = 0; i < num_tuples; i++)
+ printf(" - port %u device (%s) queue %u\n",
+ pdump_t[i].port,
+ pdump_t[i].device_id,
+ pdump_t[i].queue);
+
+ while (!quit_signal) {
+ for (i = 0; i < num_tuples; i++)
+ pdump_packets(&pdump_t[i]);
+ }
+
+ return;
+ }
+
+ /* check if there enough core */
+ if ((uint32_t)num_tuples >= rte_lcore_count()) {
+ printf("Insufficient cores to run parallel!\n");
+ return;
+ }
+
+ lcore_id = rte_get_next_lcore(lcore_id, 1, 0);
+
+ for (i = 0; i < num_tuples; i++) {
+ rte_eal_remote_launch(dump_packets_core,
+ &pdump_t[i], lcore_id);
+ lcore_id = rte_get_next_lcore(lcore_id, 1, 0);
+
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ rte_exit(EXIT_FAILURE, "failed to wait\n");
+ }
+
+ /* master core */
+ while (!quit_signal)
+ ;
+}
+
+static void
+enable_primary_monitor(void)
+{
+ int ret;
+
+ /* Once primary exits, so will pdump. */
+ ret = rte_eal_alarm_set(MONITOR_INTERVAL, monitor_primary, NULL);
+ if (ret < 0)
+ printf("Fail to enable monitor:%d\n", ret);
+}
+
+int
+main(int argc, char **argv)
+{
+ int diag;
+ int ret;
+ int i;
+
+ char n_flag[] = "-n4";
+ char mp_flag[] = "--proc-type=secondary";
+ char *argp[argc + 2];
+
+ /* catch ctrl-c so we can print on exit */
+ signal(SIGINT, signal_handler);
+
+ argp[0] = argv[0];
+ argp[1] = n_flag;
+ argp[2] = mp_flag;
+
+ for (i = 1; i < argc; i++)
+ argp[i + 2] = argv[i];
+
+ argc += 2;
+
+ diag = rte_eal_init(argc, argp);
+ if (diag < 0)
+ rte_panic("Cannot init EAL\n");
+
+ if (rte_eth_dev_count_avail() == 0)
+ rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
+
+ argc -= diag;
+ argv += (diag - 2);
+
+ /* parse app arguments */
+ if (argc > 1) {
+ ret = launch_args_parse(argc, argv, argp[0]);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid argument\n");
+ }
+
+ /* create mempool, ring and vdevs info */
+ create_mp_ring_vdev();
+ enable_pdump();
+ enable_primary_monitor();
+ dump_packets();
+
+ disable_primary_monitor();
+ cleanup_pdump_resources();
+ /* dump debug stats */
+ print_pdump_stats();
+
+ ret = rte_eal_cleanup();
+ if (ret)
+ printf("Error from rte_eal_cleanup(), %d\n", ret);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/pdump/meson.build b/src/spdk/dpdk/app/pdump/meson.build
new file mode 100644
index 000000000..7bb908e04
--- /dev/null
+++ b/src/spdk/dpdk/app/pdump/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+sources = files('main.c')
+deps += ['ethdev', 'kvargs', 'pdump']
diff --git a/src/spdk/dpdk/app/proc-info/Makefile b/src/spdk/dpdk/app/proc-info/Makefile
new file mode 100644
index 000000000..214f3f54a
--- /dev/null
+++ b/src/spdk/dpdk/app/proc-info/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2015 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+APP = dpdk-procinfo
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/spdk/dpdk/app/proc-info/main.c b/src/spdk/dpdk/app/proc-info/main.c
new file mode 100644
index 000000000..abeca4aab
--- /dev/null
+++ b/src/spdk/dpdk/app/proc-info/main.c
@@ -0,0 +1,1356 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_log.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_string_fns.h>
+#include <rte_metrics.h>
+#include <rte_cycles.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
+#include <rte_cryptodev.h>
+#include <rte_tm.h>
+#include <rte_hexdump.h>
+
+/* Maximum long option length for option parsing. */
+#define MAX_LONG_OPT_SZ 64
+#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
+
+#define MAX_STRING_LEN 256
+
+#define STATS_BDR_FMT "========================================"
+#define STATS_BDR_STR(w, s) printf("%.*s%s%.*s\n", w, \
+ STATS_BDR_FMT, s, w, STATS_BDR_FMT)
+
+/**< mask of enabled ports */
+static uint32_t enabled_port_mask;
+/**< Enable stats. */
+static uint32_t enable_stats;
+/**< Enable xstats. */
+static uint32_t enable_xstats;
+/**< Enable collectd format*/
+static uint32_t enable_collectd_format;
+/**< FD to send collectd format messages to STDOUT*/
+static int stdout_fd;
+/**< Host id process is running on */
+static char host_id[MAX_LONG_OPT_SZ];
+/**< Enable metrics. */
+static uint32_t enable_metrics;
+/**< Enable stats reset. */
+static uint32_t reset_stats;
+/**< Enable xstats reset. */
+static uint32_t reset_xstats;
+/**< Enable memory info. */
+static uint32_t mem_info;
+/**< Enable displaying xstat name. */
+static uint32_t enable_xstats_name;
+static char *xstats_name;
+
+/**< Enable xstats by ids. */
+#define MAX_NB_XSTATS_IDS 1024
+static uint32_t nb_xstats_ids;
+static uint64_t xstats_ids[MAX_NB_XSTATS_IDS];
+
+/* show border */
+static char bdr_str[MAX_STRING_LEN];
+
+/**< Enable show port. */
+static uint32_t enable_shw_port;
+/**< Enable show tm. */
+static uint32_t enable_shw_tm;
+/**< Enable show crypto. */
+static uint32_t enable_shw_crypto;
+/**< Enable show ring. */
+static uint32_t enable_shw_ring;
+static char *ring_name;
+/**< Enable show mempool. */
+static uint32_t enable_shw_mempool;
+static char *mempool_name;
+/**< Enable iter mempool. */
+static uint32_t enable_iter_mempool;
+static char *mempool_iter_name;
+
+/**< display usage */
+static void
+proc_info_usage(const char *prgname)
+{
+ printf("%s [EAL options] -- -p PORTMASK\n"
+ " -m to display DPDK memory zones, segments and TAILQ information\n"
+ " -p PORTMASK: hexadecimal bitmask of ports to retrieve stats for\n"
+ " --stats: to display port statistics, enabled by default\n"
+ " --xstats: to display extended port statistics, disabled by "
+ "default\n"
+ " --metrics: to display derived metrics of the ports, disabled by "
+ "default\n"
+ " --xstats-name NAME: to display single xstat id by NAME\n"
+ " --xstats-ids IDLIST: to display xstat values by id. "
+ "The argument is comma-separated list of xstat ids to print out.\n"
+ " --stats-reset: to reset port statistics\n"
+ " --xstats-reset: to reset port extended statistics\n"
+ " --collectd-format: to print statistics to STDOUT in expected by collectd format\n"
+ " --host-id STRING: host id used to identify the system process is running on\n"
+ " --show-port: to display ports information\n"
+ " --show-tm: to display traffic manager information for ports\n"
+ " --show-crypto: to display crypto information\n"
+ " --show-ring[=name]: to display ring information\n"
+ " --show-mempool[=name]: to display mempool information\n"
+ " --iter-mempool=name: iterate mempool elements to display content\n",
+ prgname);
+}
+
+/*
+ * Parse the portmask provided at run time.
+ */
+static int
+parse_portmask(const char *portmask)
+{
+ char *end = NULL;
+ unsigned long pm;
+
+ errno = 0;
+
+ /* parse hexadecimal string */
+ pm = strtoul(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') ||
+ (errno != 0)) {
+ printf("%s ERROR parsing the port mask\n", __func__);
+ return -1;
+ }
+
+ if (pm == 0)
+ return -1;
+
+ return pm;
+
+}
+
+/*
+ * Parse ids value list into array
+ */
+static int
+parse_xstats_ids(char *list, uint64_t *ids, int limit) {
+ int length;
+ char *token;
+ char *ctx = NULL;
+ char *endptr;
+
+ length = 0;
+ token = strtok_r(list, ",", &ctx);
+ while (token != NULL) {
+ ids[length] = strtoull(token, &endptr, 10);
+ if (*endptr != '\0')
+ return -EINVAL;
+
+ length++;
+ if (length >= limit)
+ return -E2BIG;
+
+ token = strtok_r(NULL, ",", &ctx);
+ }
+
+ return length;
+}
+
+static int
+proc_info_preparse_args(int argc, char **argv)
+{
+ char *prgname = argv[0];
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ /* Print stats or xstats to STDOUT in collectd format */
+ if (!strncmp(argv[i], "--collectd-format", MAX_LONG_OPT_SZ)) {
+ enable_collectd_format = 1;
+ stdout_fd = dup(STDOUT_FILENO);
+ close(STDOUT_FILENO);
+ }
+ if (!strncmp(argv[i], "--host-id", MAX_LONG_OPT_SZ)) {
+ if ((i + 1) == argc) {
+ printf("Invalid host id or not specified\n");
+ proc_info_usage(prgname);
+ return -1;
+ }
+ strlcpy(host_id, argv[i + 1], sizeof(host_id));
+ }
+ }
+
+ if (!strlen(host_id)) {
+ int err = gethostname(host_id, MAX_LONG_OPT_SZ-1);
+
+ if (err)
+ strlcpy(host_id, "unknown", sizeof(host_id));
+ }
+
+ return 0;
+}
+
+/* Parse the argument given in the command line of the application */
+static int
+proc_info_parse_args(int argc, char **argv)
+{
+ int opt;
+ int option_index;
+ char *prgname = argv[0];
+ static struct option long_option[] = {
+ {"stats", 0, NULL, 0},
+ {"stats-reset", 0, NULL, 0},
+ {"xstats", 0, NULL, 0},
+ {"metrics", 0, NULL, 0},
+ {"xstats-reset", 0, NULL, 0},
+ {"xstats-name", required_argument, NULL, 1},
+ {"collectd-format", 0, NULL, 0},
+ {"xstats-ids", 1, NULL, 1},
+ {"host-id", 0, NULL, 0},
+ {"show-port", 0, NULL, 0},
+ {"show-tm", 0, NULL, 0},
+ {"show-crypto", 0, NULL, 0},
+ {"show-ring", optional_argument, NULL, 0},
+ {"show-mempool", optional_argument, NULL, 0},
+ {"iter-mempool", required_argument, NULL, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ if (argc == 1)
+ proc_info_usage(prgname);
+
+ /* Parse command line */
+ while ((opt = getopt_long(argc, argv, "p:m",
+ long_option, &option_index)) != EOF) {
+ switch (opt) {
+ /* portmask */
+ case 'p':
+ enabled_port_mask = parse_portmask(optarg);
+ if (enabled_port_mask == 0) {
+ printf("invalid portmask\n");
+ proc_info_usage(prgname);
+ return -1;
+ }
+ break;
+ case 'm':
+ mem_info = 1;
+ break;
+ case 0:
+ /* Print stats */
+ if (!strncmp(long_option[option_index].name, "stats",
+ MAX_LONG_OPT_SZ))
+ enable_stats = 1;
+ /* Print xstats */
+ else if (!strncmp(long_option[option_index].name, "xstats",
+ MAX_LONG_OPT_SZ))
+ enable_xstats = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "metrics",
+ MAX_LONG_OPT_SZ))
+ enable_metrics = 1;
+ /* Reset stats */
+ if (!strncmp(long_option[option_index].name, "stats-reset",
+ MAX_LONG_OPT_SZ))
+ reset_stats = 1;
+ /* Reset xstats */
+ else if (!strncmp(long_option[option_index].name, "xstats-reset",
+ MAX_LONG_OPT_SZ))
+ reset_xstats = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "show-port", MAX_LONG_OPT_SZ))
+ enable_shw_port = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "show-tm", MAX_LONG_OPT_SZ))
+ enable_shw_tm = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "show-crypto", MAX_LONG_OPT_SZ))
+ enable_shw_crypto = 1;
+ else if (!strncmp(long_option[option_index].name,
+ "show-ring", MAX_LONG_OPT_SZ)) {
+ enable_shw_ring = 1;
+ ring_name = optarg;
+ } else if (!strncmp(long_option[option_index].name,
+ "show-mempool", MAX_LONG_OPT_SZ)) {
+ enable_shw_mempool = 1;
+ mempool_name = optarg;
+ } else if (!strncmp(long_option[option_index].name,
+ "iter-mempool", MAX_LONG_OPT_SZ)) {
+ enable_iter_mempool = 1;
+ mempool_iter_name = optarg;
+ }
+ break;
+ case 1:
+ /* Print xstat single value given by name*/
+ if (!strncmp(long_option[option_index].name,
+ "xstats-name", MAX_LONG_OPT_SZ)) {
+ enable_xstats_name = 1;
+ xstats_name = optarg;
+ printf("name:%s:%s\n",
+ long_option[option_index].name,
+ optarg);
+ } else if (!strncmp(long_option[option_index].name,
+ "xstats-ids",
+ MAX_LONG_OPT_SZ)) {
+ nb_xstats_ids = parse_xstats_ids(optarg,
+ xstats_ids, MAX_NB_XSTATS_IDS);
+
+ if (nb_xstats_ids <= 0) {
+ printf("xstats-id list parse error.\n");
+ return -1;
+ }
+
+ }
+ break;
+ default:
+ proc_info_usage(prgname);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void
+meminfo_display(void)
+{
+ printf("----------- MEMORY_SEGMENTS -----------\n");
+ rte_dump_physmem_layout(stdout);
+ printf("--------- END_MEMORY_SEGMENTS ---------\n");
+
+ printf("------------ MEMORY_ZONES -------------\n");
+ rte_memzone_dump(stdout);
+ printf("---------- END_MEMORY_ZONES -----------\n");
+
+ printf("------------- TAIL_QUEUES -------------\n");
+ rte_dump_tailq(stdout);
+ printf("---------- END_TAIL_QUEUES ------------\n");
+}
+
+static void
+nic_stats_display(uint16_t port_id)
+{
+ struct rte_eth_stats stats;
+ uint8_t i;
+
+ static const char *nic_stats_border = "########################";
+
+ rte_eth_stats_get(port_id, &stats);
+ printf("\n %s NIC statistics for port %-2d %s\n",
+ nic_stats_border, port_id, nic_stats_border);
+
+ printf(" RX-packets: %-10"PRIu64" RX-errors: %-10"PRIu64
+ " RX-bytes: %-10"PRIu64"\n", stats.ipackets, stats.ierrors,
+ stats.ibytes);
+ printf(" RX-nombuf: %-10"PRIu64"\n", stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64
+ " TX-bytes: %-10"PRIu64"\n", stats.opackets, stats.oerrors,
+ stats.obytes);
+
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d RX-packets: %-10"PRIu64
+ " RX-errors: %-10"PRIu64
+ " RX-bytes: %-10"PRIu64"\n",
+ i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
+ }
+
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d TX-packets: %-10"PRIu64
+ " TX-bytes: %-10"PRIu64"\n",
+ i, stats.q_opackets[i], stats.q_obytes[i]);
+ }
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+static void
+nic_stats_clear(uint16_t port_id)
+{
+ printf("\n Clearing NIC stats for port %d\n", port_id);
+ rte_eth_stats_reset(port_id);
+ printf("\n NIC statistics for port %d cleared\n", port_id);
+}
+
+static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len,
+ const char *cnt_name) {
+ char *type_end = strrchr(cnt_name, '_');
+
+ if ((type_end != NULL) &&
+ (strncmp(cnt_name, "rx_", strlen("rx_")) == 0)) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
+ strlcpy(cnt_type, "if_rx_dropped", cnt_type_len);
+ else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
+ strlcpy(cnt_type, "if_rx_octets", cnt_type_len);
+ else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
+ strlcpy(cnt_type, "if_rx_packets", cnt_type_len);
+ else if (strncmp(type_end, "_placement",
+ strlen("_placement")) == 0)
+ strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_buff", strlen("_buff")) == 0)
+ strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
+ else
+ /* Does not fit obvious type: use a more generic one */
+ strlcpy(cnt_type, "derive", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "tx_", strlen("tx_"))) == 0) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strlcpy(cnt_type, "if_tx_errors", cnt_type_len);
+ else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
+ strlcpy(cnt_type, "if_tx_dropped", cnt_type_len);
+ else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
+ strlcpy(cnt_type, "if_tx_octets", cnt_type_len);
+ else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
+ strlcpy(cnt_type, "if_tx_packets", cnt_type_len);
+ else
+ /* Does not fit obvious type: use a more generic one */
+ strlcpy(cnt_type, "derive", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "flow_", strlen("flow_"))) == 0) {
+ if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
+ strlcpy(cnt_type, "operations", cnt_type_len);
+ else if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strlcpy(cnt_type, "errors", cnt_type_len);
+ else if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
+ strlcpy(cnt_type, "filter_result", cnt_type_len);
+ } else if ((type_end != NULL) &&
+ (strncmp(cnt_name, "mac_", strlen("mac_"))) == 0) {
+ if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
+ strlcpy(cnt_type, "errors", cnt_type_len);
+ } else {
+ /* Does not fit obvious type, or strrchr error: */
+ /* use a more generic type */
+ strlcpy(cnt_type, "derive", cnt_type_len);
+ }
+}
+
+static void
+nic_xstats_by_name_display(uint16_t port_id, char *name)
+{
+ uint64_t id;
+
+ printf("###### NIC statistics for port %-2d, statistic name '%s':\n",
+ port_id, name);
+
+ if (rte_eth_xstats_get_id_by_name(port_id, name, &id) == 0)
+ printf("%s: %"PRIu64"\n", name, id);
+ else
+ printf("Statistic not found...\n");
+
+}
+
+static void
+nic_xstats_by_ids_display(uint16_t port_id, uint64_t *ids, int len)
+{
+ struct rte_eth_xstat_name *xstats_names;
+ uint64_t *values;
+ int ret, i;
+ static const char *nic_stats_border = "########################";
+
+ values = malloc(sizeof(*values) * len);
+ if (values == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ return;
+ }
+
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstat names\n");
+ free(values);
+ return;
+ }
+
+ if (len != rte_eth_xstats_get_names_by_id(
+ port_id, xstats_names, len, ids)) {
+ printf("Cannot get xstat names\n");
+ goto err;
+ }
+
+ printf("###### NIC extended statistics for port %-2d #########\n",
+ port_id);
+ printf("%s############################\n", nic_stats_border);
+ ret = rte_eth_xstats_get_by_id(port_id, ids, values, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get xstats\n");
+ goto err;
+ }
+
+ for (i = 0; i < len; i++)
+ printf("%s: %"PRIu64"\n",
+ xstats_names[i].name,
+ values[i]);
+
+ printf("%s############################\n", nic_stats_border);
+err:
+ free(values);
+ free(xstats_names);
+}
+
+static void
+nic_xstats_display(uint16_t port_id)
+{
+ struct rte_eth_xstat_name *xstats_names;
+ uint64_t *values;
+ int len, ret, i;
+ static const char *nic_stats_border = "########################";
+
+ len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
+ if (len < 0) {
+ printf("Cannot get xstats count\n");
+ return;
+ }
+ values = malloc(sizeof(*values) * len);
+ if (values == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ return;
+ }
+
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstat names\n");
+ free(values);
+ return;
+ }
+ if (len != rte_eth_xstats_get_names_by_id(
+ port_id, xstats_names, len, NULL)) {
+ printf("Cannot get xstat names\n");
+ goto err;
+ }
+
+ printf("###### NIC extended statistics for port %-2d #########\n",
+ port_id);
+ printf("%s############################\n",
+ nic_stats_border);
+ ret = rte_eth_xstats_get_by_id(port_id, NULL, values, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get xstats\n");
+ goto err;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (enable_collectd_format) {
+ char counter_type[MAX_STRING_LEN];
+ char buf[MAX_STRING_LEN];
+ size_t n;
+
+ collectd_resolve_cnt_type(counter_type,
+ sizeof(counter_type),
+ xstats_names[i].name);
+ n = snprintf(buf, MAX_STRING_LEN,
+ "PUTVAL %s/dpdkstat-port.%u/%s-%s N:%"
+ PRIu64"\n", host_id, port_id, counter_type,
+ xstats_names[i].name, values[i]);
+ if (n > sizeof(buf) - 1)
+ n = sizeof(buf) - 1;
+ ret = write(stdout_fd, buf, n);
+ if (ret < 0)
+ goto err;
+ } else {
+ printf("%s: %"PRIu64"\n", xstats_names[i].name,
+ values[i]);
+ }
+ }
+
+ printf("%s############################\n",
+ nic_stats_border);
+err:
+ free(values);
+ free(xstats_names);
+}
+
+static void
+nic_xstats_clear(uint16_t port_id)
+{
+ int ret;
+
+ printf("\n Clearing NIC xstats for port %d\n", port_id);
+ ret = rte_eth_xstats_reset(port_id);
+ if (ret != 0) {
+ printf("\n Error clearing xstats for port %d: %s\n", port_id,
+ strerror(-ret));
+ return;
+ }
+
+ printf("\n NIC extended statistics for port %d cleared\n", port_id);
+}
+
+static void
+metrics_display(int port_id)
+{
+ struct rte_metric_value *metrics;
+ struct rte_metric_name *names;
+ int len, ret;
+ static const char *nic_stats_border = "########################";
+
+ len = rte_metrics_get_names(NULL, 0);
+ if (len < 0) {
+ printf("Cannot get metrics count\n");
+ return;
+ }
+ if (len == 0) {
+ printf("No metrics to display (none have been registered)\n");
+ return;
+ }
+
+ metrics = rte_malloc("proc_info_metrics",
+ sizeof(struct rte_metric_value) * len, 0);
+ if (metrics == NULL) {
+ printf("Cannot allocate memory for metrics\n");
+ return;
+ }
+
+ names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
+ if (names == NULL) {
+ printf("Cannot allocate memory for metrcis names\n");
+ rte_free(metrics);
+ return;
+ }
+
+ if (len != rte_metrics_get_names(names, len)) {
+ printf("Cannot get metrics names\n");
+ rte_free(metrics);
+ rte_free(names);
+ return;
+ }
+
+ if (port_id == RTE_METRICS_GLOBAL)
+ printf("###### Non port specific metrics #########\n");
+ else
+ printf("###### metrics for port %-2d #########\n", port_id);
+ printf("%s############################\n", nic_stats_border);
+ ret = rte_metrics_get_values(port_id, metrics, len);
+ if (ret < 0 || ret > len) {
+ printf("Cannot get metrics values\n");
+ rte_free(metrics);
+ rte_free(names);
+ return;
+ }
+
+ int i;
+ for (i = 0; i < len; i++)
+ printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
+
+ printf("%s############################\n", nic_stats_border);
+ rte_free(metrics);
+ rte_free(names);
+}
+
+static void
+show_port(void)
+{
+ uint16_t i = 0;
+ int ret = 0, j, k;
+
+ snprintf(bdr_str, MAX_STRING_LEN, " show - Port PMD %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ RTE_ETH_FOREACH_DEV(i) {
+ uint16_t mtu = 0;
+ struct rte_eth_link link;
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rxq_info queue_info;
+ struct rte_eth_rss_conf rss_conf;
+
+ memset(&rss_conf, 0, sizeof(rss_conf));
+
+ snprintf(bdr_str, MAX_STRING_LEN, " Port (%u)", i);
+ STATS_BDR_STR(5, bdr_str);
+ printf(" - generic config\n");
+
+ printf("\t -- Socket %d\n", rte_eth_dev_socket_id(i));
+ ret = rte_eth_link_get(i, &link);
+ if (ret < 0) {
+ printf("Link get failed (port %u): %s\n",
+ i, rte_strerror(-ret));
+ } else {
+ printf("\t -- link speed %d duplex %d,"
+ " auto neg %d status %d\n",
+ link.link_speed,
+ link.link_duplex,
+ link.link_autoneg,
+ link.link_status);
+ }
+ printf("\t -- promiscuous (%d)\n",
+ rte_eth_promiscuous_get(i));
+ ret = rte_eth_dev_get_mtu(i, &mtu);
+ if (ret == 0)
+ printf("\t -- mtu (%d)\n", mtu);
+
+ ret = rte_eth_dev_info_get(i, &dev_info);
+ if (ret != 0) {
+ printf("Error during getting device (port %u) info: %s\n",
+ i, strerror(-ret));
+ return;
+ }
+
+ printf(" - queue\n");
+ for (j = 0; j < dev_info.nb_rx_queues; j++) {
+ ret = rte_eth_rx_queue_info_get(i, j, &queue_info);
+ if (ret == 0) {
+ printf("\t -- queue %d rx scatter %d"
+ " descriptors %d"
+ " offloads 0x%"PRIx64
+ " mempool socket %d\n",
+ j,
+ queue_info.scattered_rx,
+ queue_info.nb_desc,
+ queue_info.conf.offloads,
+ queue_info.mp->socket_id);
+ }
+ }
+
+ ret = rte_eth_dev_rss_hash_conf_get(i, &rss_conf);
+ if (ret == 0) {
+ if (rss_conf.rss_key) {
+ printf(" - RSS\n");
+ printf("\t -- RSS len %u key (hex):",
+ rss_conf.rss_key_len);
+ for (k = 0; k < rss_conf.rss_key_len; k++)
+ printf(" %x", rss_conf.rss_key[k]);
+ printf("\t -- hf 0x%"PRIx64"\n",
+ rss_conf.rss_hf);
+ }
+ }
+
+ printf(" - cyrpto context\n");
+#ifdef RTE_LIBRTE_SECURITY
+ void *p_ctx = rte_eth_dev_get_sec_ctx(i);
+ printf("\t -- security context - %p\n", p_ctx);
+
+ if (p_ctx) {
+ printf("\t -- size %u\n",
+ rte_security_session_get_size(p_ctx));
+ const struct rte_security_capability *s_cap =
+ rte_security_capabilities_get(p_ctx);
+ if (s_cap) {
+ printf("\t -- action (0x%x), protocol (0x%x),"
+ " offload flags (0x%x)\n",
+ s_cap->action,
+ s_cap->protocol,
+ s_cap->ol_flags);
+ printf("\t -- capabilities - oper type %x\n",
+ s_cap->crypto_capabilities->op);
+ }
+ }
+#endif
+ }
+
+ STATS_BDR_STR(50, "");
+}
+
+static void
+display_nodecap_info(int is_leaf, struct rte_tm_node_capabilities *cap)
+{
+ if (cap == NULL)
+ return;
+
+ if (!is_leaf) {
+ printf("\t -- nonleaf sched max:\n"
+ "\t\t + children (%u)\n"
+ "\t\t + sp priorities (%u)\n"
+ "\t\t + wfq children per group (%u)\n"
+ "\t\t + wfq groups (%u)\n"
+ "\t\t + wfq weight (%u)\n",
+ cap->nonleaf.sched_n_children_max,
+ cap->nonleaf.sched_sp_n_priorities_max,
+ cap->nonleaf.sched_wfq_n_children_per_group_max,
+ cap->nonleaf.sched_wfq_n_groups_max,
+ cap->nonleaf.sched_wfq_weight_max);
+ } else {
+ printf("\t -- leaf cman support:\n"
+ "\t\t + wred pkt mode (%d)\n"
+ "\t\t + wred byte mode (%d)\n"
+ "\t\t + head drop (%d)\n"
+ "\t\t + wred context private (%d)\n"
+ "\t\t + wred context shared (%u)\n",
+ cap->leaf.cman_wred_packet_mode_supported,
+ cap->leaf.cman_wred_byte_mode_supported,
+ cap->leaf.cman_head_drop_supported,
+ cap->leaf.cman_wred_context_private_supported,
+ cap->leaf.cman_wred_context_shared_n_max);
+ }
+}
+
+static void
+display_levelcap_info(int is_leaf, struct rte_tm_level_capabilities *cap)
+{
+ if (cap == NULL)
+ return;
+
+ if (!is_leaf) {
+ printf("\t -- shaper private: (%d) dual rate (%d)\n",
+ cap->nonleaf.shaper_private_supported,
+ cap->nonleaf.shaper_private_dual_rate_supported);
+ printf("\t -- shaper share: (%u)\n",
+ cap->nonleaf.shaper_shared_n_max);
+ printf("\t -- non leaf sched MAX:\n"
+ "\t\t + children (%u)\n"
+ "\t\t + sp (%u)\n"
+ "\t\t + wfq children per group (%u)\n"
+ "\t\t + wfq groups (%u)\n"
+ "\t\t + wfq weight (%u)\n",
+ cap->nonleaf.sched_n_children_max,
+ cap->nonleaf.sched_sp_n_priorities_max,
+ cap->nonleaf.sched_wfq_n_children_per_group_max,
+ cap->nonleaf.sched_wfq_n_groups_max,
+ cap->nonleaf.sched_wfq_weight_max);
+ } else {
+ printf("\t -- shaper private: (%d) dual rate (%d)\n",
+ cap->leaf.shaper_private_supported,
+ cap->leaf.shaper_private_dual_rate_supported);
+ printf("\t -- shaper share: (%u)\n",
+ cap->leaf.shaper_shared_n_max);
+ printf(" -- leaf cman support:\n"
+ "\t\t + wred pkt mode (%d)\n"
+ "\t\t + wred byte mode (%d)\n"
+ "\t\t + head drop (%d)\n"
+ "\t\t + wred context private (%d)\n"
+ "\t\t + wred context shared (%u)\n",
+ cap->leaf.cman_wred_packet_mode_supported,
+ cap->leaf.cman_wred_byte_mode_supported,
+ cap->leaf.cman_head_drop_supported,
+ cap->leaf.cman_wred_context_private_supported,
+ cap->leaf.cman_wred_context_shared_n_max);
+ }
+}
+
+static void
+show_tm(void)
+{
+ int ret = 0, check_for_leaf = 0, is_leaf = 0;
+ unsigned int j, k;
+ uint16_t i = 0;
+
+ snprintf(bdr_str, MAX_STRING_LEN, " show - TM PMD %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ RTE_ETH_FOREACH_DEV(i) {
+ struct rte_eth_dev_info dev_info;
+ struct rte_tm_capabilities cap;
+ struct rte_tm_error error;
+ struct rte_tm_node_capabilities capnode;
+ struct rte_tm_level_capabilities caplevel;
+ uint32_t n_leaf_nodes = 0;
+
+ memset(&cap, 0, sizeof(cap));
+ memset(&error, 0, sizeof(error));
+
+ ret = rte_eth_dev_info_get(i, &dev_info);
+ if (ret != 0) {
+ printf("Error during getting device (port %u) info: %s\n",
+ i, strerror(-ret));
+ return;
+ }
+
+ printf(" - Generic for port (%u)\n"
+ "\t -- driver name %s\n"
+ "\t -- max vf (%u)\n"
+ "\t -- max tx queues (%u)\n"
+ "\t -- number of tx queues (%u)\n",
+ i,
+ dev_info.driver_name,
+ dev_info.max_vfs,
+ dev_info.max_tx_queues,
+ dev_info.nb_tx_queues);
+
+ ret = rte_tm_capabilities_get(i, &cap, &error);
+ if (ret)
+ continue;
+
+ printf(" - MAX: nodes (%u) levels (%u) children (%u)\n",
+ cap.n_nodes_max,
+ cap.n_levels_max,
+ cap.sched_n_children_max);
+
+ printf(" - identical nodes: non leaf (%d) leaf (%d)\n",
+ cap.non_leaf_nodes_identical,
+ cap.leaf_nodes_identical);
+
+ printf(" - Shaper MAX:\n"
+ "\t -- total (%u)\n"
+ "\t -- private (%u) private dual (%d)\n"
+ "\t -- shared (%u) shared dual (%u)\n",
+ cap.shaper_n_max,
+ cap.shaper_private_n_max,
+ cap.shaper_private_dual_rate_n_max,
+ cap.shaper_shared_n_max,
+ cap.shaper_shared_dual_rate_n_max);
+
+ printf(" - mark support:\n");
+ printf("\t -- vlan dei: GREEN (%d) YELLOW (%d) RED (%d)\n",
+ cap.mark_vlan_dei_supported[RTE_COLOR_GREEN],
+ cap.mark_vlan_dei_supported[RTE_COLOR_YELLOW],
+ cap.mark_vlan_dei_supported[RTE_COLOR_RED]);
+ printf("\t -- ip ecn tcp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+ cap.mark_ip_ecn_tcp_supported[RTE_COLOR_GREEN],
+ cap.mark_ip_ecn_tcp_supported[RTE_COLOR_YELLOW],
+ cap.mark_ip_ecn_tcp_supported[RTE_COLOR_RED]);
+ printf("\t -- ip ecn sctp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+ cap.mark_ip_ecn_sctp_supported[RTE_COLOR_GREEN],
+ cap.mark_ip_ecn_sctp_supported[RTE_COLOR_YELLOW],
+ cap.mark_ip_ecn_sctp_supported[RTE_COLOR_RED]);
+ printf("\t -- ip dscp: GREEN (%d) YELLOW (%d) RED (%d)\n",
+ cap.mark_ip_dscp_supported[RTE_COLOR_GREEN],
+ cap.mark_ip_dscp_supported[RTE_COLOR_YELLOW],
+ cap.mark_ip_dscp_supported[RTE_COLOR_RED]);
+
+ printf(" - mask stats (0x%"PRIx64")"
+ " dynamic update (0x%"PRIx64")\n",
+ cap.stats_mask,
+ cap.dynamic_update_mask);
+
+ printf(" - sched MAX:\n"
+ "\t -- total (%u)\n"
+ "\t -- sp levels (%u)\n"
+ "\t -- wfq children per group (%u)\n"
+ "\t -- wfq groups (%u)\n"
+ "\t -- wfq weight (%u)\n",
+ cap.sched_sp_n_priorities_max,
+ cap.sched_sp_n_priorities_max,
+ cap.sched_wfq_n_children_per_group_max,
+ cap.sched_wfq_n_groups_max,
+ cap.sched_wfq_weight_max);
+
+ printf(" - CMAN support:\n"
+ "\t -- WRED mode: pkt (%d) byte (%d)\n"
+ "\t -- head drop (%d)\n",
+ cap.cman_wred_packet_mode_supported,
+ cap.cman_wred_byte_mode_supported,
+ cap.cman_head_drop_supported);
+ printf("\t -- MAX WRED CONTEXT:"
+ " total (%u) private (%u) shared (%u)\n",
+ cap.cman_wred_context_n_max,
+ cap.cman_wred_context_private_n_max,
+ cap.cman_wred_context_shared_n_max);
+
+ for (j = 0; j < cap.n_nodes_max; j++) {
+ memset(&capnode, 0, sizeof(capnode));
+ ret = rte_tm_node_capabilities_get(i, j,
+ &capnode, &error);
+ if (ret)
+ continue;
+
+ check_for_leaf = 1;
+
+ printf(" NODE %u\n", j);
+ printf("\t - shaper private: (%d) dual rate (%d)\n",
+ capnode.shaper_private_supported,
+ capnode.shaper_private_dual_rate_supported);
+ printf("\t - shaper shared max: (%u)\n",
+ capnode.shaper_shared_n_max);
+ printf("\t - stats mask %"PRIx64"\n",
+ capnode.stats_mask);
+
+ ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
+ if (ret)
+ continue;
+
+ display_nodecap_info(is_leaf, &capnode);
+ }
+
+ for (j = 0; j < cap.n_levels_max; j++) {
+ memset(&caplevel, 0, sizeof(caplevel));
+ ret = rte_tm_level_capabilities_get(i, j,
+ &caplevel, &error);
+ if (ret)
+ continue;
+
+ printf(" - Level %u\n", j);
+ printf("\t -- node MAX: %u non leaf %u leaf %u\n",
+ caplevel.n_nodes_max,
+ caplevel.n_nodes_nonleaf_max,
+ caplevel.n_nodes_leaf_max);
+ printf("\t -- indetical: non leaf %u leaf %u\n",
+ caplevel.non_leaf_nodes_identical,
+ caplevel.leaf_nodes_identical);
+
+ for (k = 0; k < caplevel.n_nodes_max; k++) {
+ ret = rte_tm_node_type_get(i, k,
+ &is_leaf, &error);
+ if (ret)
+ continue;
+
+ display_levelcap_info(is_leaf, &caplevel);
+ }
+ }
+
+ if (check_for_leaf) {
+ ret = rte_tm_get_number_of_leaf_nodes(i,
+ &n_leaf_nodes, &error);
+ if (ret == 0)
+ printf(" - leaf nodes (%u)\n", n_leaf_nodes);
+ }
+
+ for (j = 0; j < n_leaf_nodes; j++) {
+ struct rte_tm_node_stats stats;
+ memset(&stats, 0, sizeof(stats));
+
+ ret = rte_tm_node_stats_read(i, j,
+ &stats, &cap.stats_mask, 0, &error);
+ if (ret)
+ continue;
+
+ printf(" - STATS for node (%u)\n", j);
+ printf(" -- pkts (%"PRIu64") bytes (%"PRIu64")\n",
+ stats.n_pkts, stats.n_bytes);
+
+ ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
+ if (ret || (!is_leaf))
+ continue;
+
+ printf(" -- leaf queued:"
+ " pkts (%"PRIu64") bytes (%"PRIu64")\n",
+ stats.leaf.n_pkts_queued,
+ stats.leaf.n_bytes_queued);
+ printf(" - dropped:\n"
+ "\t -- GREEN:"
+ " pkts (%"PRIu64") bytes (%"PRIu64")\n"
+ "\t -- YELLOW:"
+ " pkts (%"PRIu64") bytes (%"PRIu64")\n"
+ "\t -- RED:"
+ " pkts (%"PRIu64") bytes (%"PRIu64")\n",
+ stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN],
+ stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN],
+ stats.leaf.n_pkts_dropped[RTE_COLOR_YELLOW],
+ stats.leaf.n_bytes_dropped[RTE_COLOR_YELLOW],
+ stats.leaf.n_pkts_dropped[RTE_COLOR_RED],
+ stats.leaf.n_bytes_dropped[RTE_COLOR_RED]);
+ }
+ }
+
+ STATS_BDR_STR(50, "");
+}
+
+static void
+display_crypto_feature_info(uint64_t x)
+{
+ if (x == 0)
+ return;
+
+ printf("\t -- feature flags\n");
+ printf("\t\t + symmetric (%c), asymmetric (%c)\n"
+ "\t\t + symmetric operation chaining (%c)\n",
+ (x & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING) ? 'y' : 'n');
+ printf("\t\t + CPU: SSE (%c), AVX (%c), AVX2 (%c), AVX512 (%c)\n",
+ (x & RTE_CRYPTODEV_FF_CPU_SSE) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_CPU_AVX) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_CPU_AVX2) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_CPU_AVX512) ? 'y' : 'n');
+ printf("\t\t + AESNI: CPU (%c), HW (%c)\n",
+ (x & RTE_CRYPTODEV_FF_CPU_AESNI) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_HW_ACCELERATED) ? 'y' : 'n');
+ printf("\t\t + INLINE (%c)\n",
+ (x & RTE_CRYPTODEV_FF_SECURITY) ? 'y' : 'n');
+ printf("\t\t + ARM: NEON (%c), CE (%c)\n",
+ (x & RTE_CRYPTODEV_FF_CPU_NEON) ? 'y' : 'n',
+ (x & RTE_CRYPTODEV_FF_CPU_ARM_CE) ? 'y' : 'n');
+ printf("\t -- buffer offload\n");
+ printf("\t\t + IN_PLACE_SGL (%c)\n",
+ (x & RTE_CRYPTODEV_FF_IN_PLACE_SGL) ? 'y' : 'n');
+ printf("\t\t + OOP_SGL_IN_SGL_OUT (%c)\n",
+ (x & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT) ? 'y' : 'n');
+ printf("\t\t + OOP_SGL_IN_LB_OUT (%c)\n",
+ (x & RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT) ? 'y' : 'n');
+ printf("\t\t + OOP_LB_IN_SGL_OUT (%c)\n",
+ (x & RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT) ? 'y' : 'n');
+ printf("\t\t + OOP_LB_IN_LB_OUT (%c)\n",
+ (x & RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT) ? 'y' : 'n');
+}
+
+static void
+show_crypto(void)
+{
+ uint8_t crypto_dev_count = rte_cryptodev_count(), i;
+
+ snprintf(bdr_str, MAX_STRING_LEN, " show - CRYPTO PMD %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ for (i = 0; i < crypto_dev_count; i++) {
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_stats stats;
+
+ rte_cryptodev_info_get(i, &dev_info);
+
+ printf(" - device (%u)\n", i);
+ printf("\t -- name (%s)\n"
+ "\t -- driver (%s)\n"
+ "\t -- id (%u) on socket (%d)\n"
+ "\t -- queue pairs (%d)\n",
+ rte_cryptodev_name_get(i),
+ dev_info.driver_name,
+ dev_info.driver_id,
+ dev_info.device->numa_node,
+ rte_cryptodev_queue_pair_count(i));
+
+ display_crypto_feature_info(dev_info.feature_flags);
+
+ memset(&stats, 0, sizeof(0));
+ if (rte_cryptodev_stats_get(i, &stats) == 0) {
+ printf("\t -- stats\n");
+ printf("\t\t + enqueue count (%"PRIu64")"
+ " error (%"PRIu64")\n",
+ stats.enqueued_count,
+ stats.enqueue_err_count);
+ printf("\t\t + dequeue count (%"PRIu64")"
+ " error (%"PRIu64")\n",
+ stats.dequeued_count,
+ stats.dequeue_err_count);
+ }
+ }
+
+ STATS_BDR_STR(50, "");
+}
+
+static void
+show_ring(char *name)
+{
+ snprintf(bdr_str, MAX_STRING_LEN, " show - RING %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ if (name != NULL) {
+ struct rte_ring *ptr = rte_ring_lookup(name);
+ if (ptr != NULL) {
+ printf(" - Name (%s) on socket (%d)\n"
+ " - flags:\n"
+ "\t -- Single Producer Enqueue (%u)\n"
+ "\t -- Single Consmer Dequeue (%u)\n",
+ ptr->name,
+ ptr->memzone->socket_id,
+ ptr->flags & RING_F_SP_ENQ,
+ ptr->flags & RING_F_SC_DEQ);
+ printf(" - size (%u) mask (0x%x) capacity (%u)\n",
+ ptr->size,
+ ptr->mask,
+ ptr->capacity);
+ printf(" - count (%u) free count (%u)\n",
+ rte_ring_count(ptr),
+ rte_ring_free_count(ptr));
+ printf(" - full (%d) empty (%d)\n",
+ rte_ring_full(ptr),
+ rte_ring_empty(ptr));
+
+ STATS_BDR_STR(50, "");
+ return;
+ }
+ }
+
+ rte_ring_list_dump(stdout);
+ STATS_BDR_STR(50, "");
+}
+
+static void
+show_mempool(char *name)
+{
+ uint64_t flags = 0;
+
+ snprintf(bdr_str, MAX_STRING_LEN, " show - MEMPOOL %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ if (name != NULL) {
+ struct rte_mempool *ptr = rte_mempool_lookup(name);
+ if (ptr != NULL) {
+ flags = ptr->flags;
+ printf(" - Name: %s on socket %d\n"
+ " - flags:\n"
+ "\t -- No spread (%c)\n"
+ "\t -- No cache align (%c)\n"
+ "\t -- SP put (%c), SC get (%c)\n"
+ "\t -- Pool created (%c)\n"
+ "\t -- No IOVA config (%c)\n",
+ ptr->name,
+ ptr->socket_id,
+ (flags & MEMPOOL_F_NO_SPREAD) ? 'y' : 'n',
+ (flags & MEMPOOL_F_NO_CACHE_ALIGN) ? 'y' : 'n',
+ (flags & MEMPOOL_F_SP_PUT) ? 'y' : 'n',
+ (flags & MEMPOOL_F_SC_GET) ? 'y' : 'n',
+ (flags & MEMPOOL_F_POOL_CREATED) ? 'y' : 'n',
+ (flags & MEMPOOL_F_NO_IOVA_CONTIG) ? 'y' : 'n');
+ printf(" - Size %u Cache %u element %u\n"
+ " - header %u trailer %u\n"
+ " - private data size %u\n",
+ ptr->size,
+ ptr->cache_size,
+ ptr->elt_size,
+ ptr->header_size,
+ ptr->trailer_size,
+ ptr->private_data_size);
+ printf(" - memezone - socket %d\n",
+ ptr->mz->socket_id);
+ printf(" - Count: avail (%u), in use (%u)\n",
+ rte_mempool_avail_count(ptr),
+ rte_mempool_in_use_count(ptr));
+
+ STATS_BDR_STR(50, "");
+ return;
+ }
+ }
+
+ rte_mempool_list_dump(stdout);
+ STATS_BDR_STR(50, "");
+}
+
+static void
+mempool_itr_obj(struct rte_mempool *mp, void *opaque,
+ void *obj, unsigned int obj_idx)
+{
+ printf(" - obj_idx %u opaque %p obj %p\n",
+ obj_idx, opaque, obj);
+
+ if (obj)
+ rte_hexdump(stdout, " Obj Content",
+ obj, (mp->elt_size > 256)?256:mp->elt_size);
+}
+
+static void
+iter_mempool(char *name)
+{
+ snprintf(bdr_str, MAX_STRING_LEN, " iter - MEMPOOL %"PRIu64,
+ rte_get_tsc_hz());
+ STATS_BDR_STR(10, bdr_str);
+
+ if (name != NULL) {
+ struct rte_mempool *ptr = rte_mempool_lookup(name);
+ if (ptr != NULL) {
+ /* iterate each object */
+ uint32_t ret = rte_mempool_obj_iter(ptr,
+ mempool_itr_obj, NULL);
+ printf("\n - iterated %u objects\n", ret);
+ STATS_BDR_STR(50, "");
+ return;
+ }
+ }
+
+ STATS_BDR_STR(50, "");
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ int i;
+ char c_flag[] = "-c1";
+ char n_flag[] = "-n4";
+ char mp_flag[] = "--proc-type=secondary";
+ char *argp[argc + 3];
+ uint16_t nb_ports;
+
+ /* preparse app arguments */
+ ret = proc_info_preparse_args(argc, argv);
+ if (ret < 0) {
+ printf("Failed to parse arguments\n");
+ return -1;
+ }
+
+ argp[0] = argv[0];
+ argp[1] = c_flag;
+ argp[2] = n_flag;
+ argp[3] = mp_flag;
+
+ for (i = 1; i < argc; i++)
+ argp[i + 3] = argv[i];
+
+ argc += 3;
+
+ ret = rte_eal_init(argc, argp);
+ if (ret < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= ret;
+ argv += (ret - 3);
+
+ if (!rte_eal_primary_proc_alive(NULL))
+ rte_exit(EXIT_FAILURE, "No primary DPDK process is running.\n");
+
+ /* parse app arguments */
+ ret = proc_info_parse_args(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid argument\n");
+
+ if (mem_info) {
+ meminfo_display();
+ return 0;
+ }
+
+ nb_ports = rte_eth_dev_count_avail();
+ if (nb_ports == 0)
+ rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
+
+ /* If no port mask was specified*/
+ if (enabled_port_mask == 0)
+ enabled_port_mask = 0xffff;
+
+ RTE_ETH_FOREACH_DEV(i) {
+ if (enabled_port_mask & (1 << i)) {
+ if (enable_stats)
+ nic_stats_display(i);
+ else if (enable_xstats)
+ nic_xstats_display(i);
+ else if (reset_stats)
+ nic_stats_clear(i);
+ else if (reset_xstats)
+ nic_xstats_clear(i);
+ else if (enable_xstats_name)
+ nic_xstats_by_name_display(i, xstats_name);
+ else if (nb_xstats_ids > 0)
+ nic_xstats_by_ids_display(i, xstats_ids,
+ nb_xstats_ids);
+ else if (enable_metrics)
+ metrics_display(i);
+ }
+ }
+
+ /* print port independent stats */
+ if (enable_metrics)
+ metrics_display(RTE_METRICS_GLOBAL);
+
+ /* show information for PMD */
+ if (enable_shw_port)
+ show_port();
+ if (enable_shw_tm)
+ show_tm();
+ if (enable_shw_crypto)
+ show_crypto();
+ if (enable_shw_ring)
+ show_ring(ring_name);
+ if (enable_shw_mempool)
+ show_mempool(mempool_name);
+ if (enable_iter_mempool)
+ iter_mempool(mempool_iter_name);
+
+ ret = rte_eal_cleanup();
+ if (ret)
+ printf("Error from rte_eal_cleanup(), %d\n", ret);
+
+ strlcpy(bdr_str, " ", MAX_STRING_LEN);
+ STATS_BDR_STR(50, bdr_str);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/proc-info/meson.build b/src/spdk/dpdk/app/proc-info/meson.build
new file mode 100644
index 000000000..f050c4a9b
--- /dev/null
+++ b/src/spdk/dpdk/app/proc-info/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+sources = files('main.c')
+deps += ['ethdev', 'metrics', 'security']
diff --git a/src/spdk/dpdk/app/test-acl/Makefile b/src/spdk/dpdk/app/test-acl/Makefile
new file mode 100644
index 000000000..5f26294cf
--- /dev/null
+++ b/src/spdk/dpdk/app/test-acl/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_ACL),y)
+
+APP = testacl
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-acl/main.c b/src/spdk/dpdk/app/test-acl/main.c
new file mode 100644
index 000000000..0a5dfb621
--- /dev/null
+++ b/src/spdk/dpdk/app/test-acl/main.c
@@ -0,0 +1,1097 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_string_fns.h>
+#include <rte_acl.h>
+#include <getopt.h>
+#include <string.h>
+
+#include <rte_cycles.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_ip.h>
+
+#define PRINT_USAGE_START "%s [EAL options] --\n"
+
+#define RTE_LOGTYPE_TESTACL RTE_LOGTYPE_USER1
+
+#define APP_NAME "TESTACL"
+
+#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \
+ unsigned long val; \
+ char *end_fld; \
+ errno = 0; \
+ val = strtoul((in), &end_fld, (base)); \
+ if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \
+ return -EINVAL; \
+ (fd) = (typeof(fd))val; \
+ (in) = end_fld + 1; \
+} while (0)
+
+#define OPT_RULE_FILE "rulesf"
+#define OPT_TRACE_FILE "tracef"
+#define OPT_RULE_NUM "rulenum"
+#define OPT_TRACE_NUM "tracenum"
+#define OPT_TRACE_STEP "tracestep"
+#define OPT_SEARCH_ALG "alg"
+#define OPT_BLD_CATEGORIES "bldcat"
+#define OPT_RUN_CATEGORIES "runcat"
+#define OPT_MAX_SIZE "maxsize"
+#define OPT_ITER_NUM "iter"
+#define OPT_VERBOSE "verbose"
+#define OPT_IPV6 "ipv6"
+
+#define TRACE_DEFAULT_NUM 0x10000
+#define TRACE_STEP_MAX 0x1000
+#define TRACE_STEP_DEF 0x100
+
+#define RULE_NUM 0x10000
+
+enum {
+ DUMP_NONE,
+ DUMP_SEARCH,
+ DUMP_PKT,
+ DUMP_MAX
+};
+
+struct acl_alg {
+ const char *name;
+ enum rte_acl_classify_alg alg;
+};
+
+static const struct acl_alg acl_alg[] = {
+ {
+ .name = "scalar",
+ .alg = RTE_ACL_CLASSIFY_SCALAR,
+ },
+ {
+ .name = "sse",
+ .alg = RTE_ACL_CLASSIFY_SSE,
+ },
+ {
+ .name = "avx2",
+ .alg = RTE_ACL_CLASSIFY_AVX2,
+ },
+ {
+ .name = "neon",
+ .alg = RTE_ACL_CLASSIFY_NEON,
+ },
+ {
+ .name = "altivec",
+ .alg = RTE_ACL_CLASSIFY_ALTIVEC,
+ },
+};
+
+static struct {
+ const char *prgname;
+ const char *rule_file;
+ const char *trace_file;
+ size_t max_size;
+ uint32_t bld_categories;
+ uint32_t run_categories;
+ uint32_t nb_rules;
+ uint32_t nb_traces;
+ uint32_t trace_step;
+ uint32_t trace_sz;
+ uint32_t iter_num;
+ uint32_t verbose;
+ uint32_t ipv6;
+ struct acl_alg alg;
+ uint32_t used_traces;
+ void *traces;
+ struct rte_acl_ctx *acx;
+} config = {
+ .bld_categories = 3,
+ .run_categories = 1,
+ .nb_rules = RULE_NUM,
+ .nb_traces = TRACE_DEFAULT_NUM,
+ .trace_step = TRACE_STEP_DEF,
+ .iter_num = 1,
+ .verbose = DUMP_MAX,
+ .alg = {
+ .name = "default",
+ .alg = RTE_ACL_CLASSIFY_DEFAULT,
+ },
+ .ipv6 = 0
+};
+
+static struct rte_acl_param prm = {
+ .name = APP_NAME,
+ .socket_id = SOCKET_ID_ANY,
+};
+
+/*
+ * Rule and trace formats definitions.
+ */
+
+struct ipv4_5tuple {
+ uint8_t proto;
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+};
+
+enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+};
+
+/*
+ * That effectively defines order of IPV4VLAN classifications:
+ * - PROTO
+ * - VLAN (TAG and DOMAIN)
+ * - SRC IP ADDRESS
+ * - DST IP ADDRESS
+ * - PORTS (SRC and DST)
+ */
+enum {
+ RTE_ACL_IPV4VLAN_PROTO,
+ RTE_ACL_IPV4VLAN_VLAN,
+ RTE_ACL_IPV4VLAN_SRC,
+ RTE_ACL_IPV4VLAN_DST,
+ RTE_ACL_IPV4VLAN_PORTS,
+ RTE_ACL_IPV4VLAN_NUM
+};
+
+struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = RTE_ACL_IPV4VLAN_PROTO,
+ .offset = offsetof(struct ipv4_5tuple, proto),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = RTE_ACL_IPV4VLAN_SRC,
+ .offset = offsetof(struct ipv4_5tuple, ip_src),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = RTE_ACL_IPV4VLAN_DST,
+ .offset = offsetof(struct ipv4_5tuple, ip_dst),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ .offset = offsetof(struct ipv4_5tuple, port_src),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ .offset = offsetof(struct ipv4_5tuple, port_dst),
+ },
+};
+
+#define IPV6_ADDR_LEN 16
+#define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t))
+#define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t))
+
+struct ipv6_5tuple {
+ uint8_t proto;
+ uint32_t ip_src[IPV6_ADDR_U32];
+ uint32_t ip_dst[IPV6_ADDR_U32];
+ uint16_t port_src;
+ uint16_t port_dst;
+};
+
+enum {
+ PROTO_FIELD_IPV6,
+ SRC1_FIELD_IPV6,
+ SRC2_FIELD_IPV6,
+ SRC3_FIELD_IPV6,
+ SRC4_FIELD_IPV6,
+ DST1_FIELD_IPV6,
+ DST2_FIELD_IPV6,
+ DST3_FIELD_IPV6,
+ DST4_FIELD_IPV6,
+ SRCP_FIELD_IPV6,
+ DSTP_FIELD_IPV6,
+ NUM_FIELDS_IPV6
+};
+
+struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV6,
+ .input_index = PROTO_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, proto),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC1_FIELD_IPV6,
+ .input_index = SRC1_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_src[0]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC2_FIELD_IPV6,
+ .input_index = SRC2_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_src[1]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC3_FIELD_IPV6,
+ .input_index = SRC3_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_src[2]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC4_FIELD_IPV6,
+ .input_index = SRC4_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_src[3]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST1_FIELD_IPV6,
+ .input_index = DST1_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_dst[0]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST2_FIELD_IPV6,
+ .input_index = DST2_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_dst[1]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST3_FIELD_IPV6,
+ .input_index = DST3_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_dst[2]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST4_FIELD_IPV6,
+ .input_index = DST4_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, ip_dst[3]),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV6,
+ .input_index = SRCP_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, port_src),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV6,
+ .input_index = SRCP_FIELD_IPV6,
+ .offset = offsetof(struct ipv6_5tuple, port_dst),
+ },
+};
+
+
+enum {
+ CB_FLD_SRC_ADDR,
+ CB_FLD_DST_ADDR,
+ CB_FLD_SRC_PORT_LOW,
+ CB_FLD_SRC_PORT_DLM,
+ CB_FLD_SRC_PORT_HIGH,
+ CB_FLD_DST_PORT_LOW,
+ CB_FLD_DST_PORT_DLM,
+ CB_FLD_DST_PORT_HIGH,
+ CB_FLD_PROTO,
+ CB_FLD_NUM,
+};
+
+enum {
+ CB_TRC_SRC_ADDR,
+ CB_TRC_DST_ADDR,
+ CB_TRC_SRC_PORT,
+ CB_TRC_DST_PORT,
+ CB_TRC_PROTO,
+ CB_TRC_NUM,
+};
+
+RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS);
+
+static const char cb_port_delim[] = ":";
+
+static char line[LINE_MAX];
+
+#define dump_verbose(lvl, fh, fmt, args...) do { \
+ if ((lvl) <= (int32_t)config.verbose) \
+ fprintf(fh, fmt, ##args); \
+} while (0)
+
+
+/*
+ * Parse ClassBench input trace (test vectors and expected results) file.
+ * Expected format:
+ * <src_ipv4_addr> <space> <dst_ipv4_addr> <space> \
+ * <src_port> <space> <dst_port> <space> <proto>
+ */
+static int
+parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v)
+{
+ int i;
+ char *s, *sp, *in[CB_TRC_NUM];
+ static const char *dlm = " \t\n";
+
+ s = str;
+ for (i = 0; i != RTE_DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ GET_CB_FIELD(in[CB_TRC_SRC_ADDR], v->ip_src, 0, UINT32_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_DST_ADDR], v->ip_dst, 0, UINT32_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0);
+
+ /* convert to network byte order. */
+ v->ip_src = rte_cpu_to_be_32(v->ip_src);
+ v->ip_dst = rte_cpu_to_be_32(v->ip_dst);
+ v->port_src = rte_cpu_to_be_16(v->port_src);
+ v->port_dst = rte_cpu_to_be_16(v->port_dst);
+
+ return 0;
+}
+
+/*
+ * Parses IPV6 address, exepcts the following format:
+ * XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX (where X - is a hexedecimal digit).
+ */
+static int
+parse_ipv6_addr(const char *in, const char **end, uint32_t v[IPV6_ADDR_U32],
+ char dlm)
+{
+ uint32_t addr[IPV6_ADDR_U16];
+
+ GET_CB_FIELD(in, addr[0], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[1], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[2], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[3], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[4], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[5], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[6], 16, UINT16_MAX, ':');
+ GET_CB_FIELD(in, addr[7], 16, UINT16_MAX, dlm);
+
+ *end = in;
+
+ v[0] = (addr[0] << 16) + addr[1];
+ v[1] = (addr[2] << 16) + addr[3];
+ v[2] = (addr[4] << 16) + addr[5];
+ v[3] = (addr[6] << 16) + addr[7];
+
+ return 0;
+}
+
+static int
+parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32])
+{
+ int32_t rc;
+ const char *end;
+
+ rc = parse_ipv6_addr(in, &end, v, 0);
+ if (rc != 0)
+ return rc;
+
+ v[0] = rte_cpu_to_be_32(v[0]);
+ v[1] = rte_cpu_to_be_32(v[1]);
+ v[2] = rte_cpu_to_be_32(v[2]);
+ v[3] = rte_cpu_to_be_32(v[3]);
+
+ return 0;
+}
+
+/*
+ * Parse ClassBench input trace (test vectors and expected results) file.
+ * Expected format:
+ * <src_ipv6_addr> <space> <dst_ipv6_addr> <space> \
+ * <src_port> <space> <dst_port> <space> <proto>
+ */
+static int
+parse_cb_ipv6_trace(char *str, struct ipv6_5tuple *v)
+{
+ int32_t i, rc;
+ char *s, *sp, *in[CB_TRC_NUM];
+ static const char *dlm = " \t\n";
+
+ s = str;
+ for (i = 0; i != RTE_DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ /* get ip6 src address. */
+ rc = parse_cb_ipv6_addr_trace(in[CB_TRC_SRC_ADDR], v->ip_src);
+ if (rc != 0)
+ return rc;
+
+ /* get ip6 dst address. */
+ rc = parse_cb_ipv6_addr_trace(in[CB_TRC_DST_ADDR], v->ip_dst);
+ if (rc != 0)
+ return rc;
+
+ GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0);
+
+ /* convert to network byte order. */
+ v->port_src = rte_cpu_to_be_16(v->port_src);
+ v->port_dst = rte_cpu_to_be_16(v->port_dst);
+
+ return 0;
+}
+
+static void
+tracef_init(void)
+{
+ static const char name[] = APP_NAME;
+ FILE *f;
+ size_t sz;
+ uint32_t n;
+ struct ipv4_5tuple *v;
+ struct ipv6_5tuple *w;
+
+ sz = config.nb_traces * (config.ipv6 ? sizeof(*w) : sizeof(*v));
+ config.traces = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE,
+ SOCKET_ID_ANY);
+ if (config.traces == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot allocate %zu bytes for "
+ "requested %u number of trace records\n",
+ sz, config.nb_traces);
+
+ f = fopen(config.trace_file, "r");
+ if (f == NULL)
+ rte_exit(-EINVAL, "failed to open file: %s\n",
+ config.trace_file);
+
+ v = config.traces;
+ w = config.traces;
+ for (n = 0; n != config.nb_traces; n++) {
+
+ if (fgets(line, sizeof(line), f) == NULL)
+ break;
+
+ if (config.ipv6) {
+ if (parse_cb_ipv6_trace(line, w + n) != 0)
+ rte_exit(EXIT_FAILURE,
+ "%s: failed to parse ipv6 trace "
+ "record at line %u\n",
+ config.trace_file, n + 1);
+ } else {
+ if (parse_cb_ipv4_trace(line, v + n) != 0)
+ rte_exit(EXIT_FAILURE,
+ "%s: failed to parse ipv4 trace "
+ "record at line %u\n",
+ config.trace_file, n + 1);
+ }
+ }
+
+ config.used_traces = n;
+ fclose(f);
+}
+
+static int
+parse_ipv6_net(const char *in, struct rte_acl_field field[4])
+{
+ int32_t rc;
+ const char *mp;
+ uint32_t i, m, v[4];
+ const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
+
+ /* get address. */
+ rc = parse_ipv6_addr(in, &mp, v, '/');
+ if (rc != 0)
+ return rc;
+
+ /* get mask. */
+ GET_CB_FIELD(mp, m, 0, CHAR_BIT * sizeof(v), 0);
+
+ /* put all together. */
+ for (i = 0; i != RTE_DIM(v); i++) {
+ if (m >= (i + 1) * nbu32)
+ field[i].mask_range.u32 = nbu32;
+ else
+ field[i].mask_range.u32 = m > (i * nbu32) ?
+ m - (i * 32) : 0;
+
+ field[i].value.u32 = v[i];
+ }
+
+ return 0;
+}
+
+
+static int
+parse_cb_ipv6_rule(char *str, struct acl_rule *v)
+{
+ int i, rc;
+ char *s, *sp, *in[CB_FLD_NUM];
+ static const char *dlm = " \t\n";
+
+ /*
+ * Skip leading '@'
+ */
+ if (strchr(str, '@') != str)
+ return -EINVAL;
+
+ s = str + 1;
+
+ for (i = 0; i != RTE_DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ rc = parse_ipv6_net(in[CB_FLD_SRC_ADDR], v->field + SRC1_FIELD_IPV6);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL,
+ "failed to read source address/mask: %s\n",
+ in[CB_FLD_SRC_ADDR]);
+ return rc;
+ }
+
+ rc = parse_ipv6_net(in[CB_FLD_DST_ADDR], v->field + DST1_FIELD_IPV6);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL,
+ "failed to read destination address/mask: %s\n",
+ in[CB_FLD_DST_ADDR]);
+ return rc;
+ }
+
+ /* source port. */
+ GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
+ v->field[SRCP_FIELD_IPV6].value.u16,
+ 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
+ v->field[SRCP_FIELD_IPV6].mask_range.u16,
+ 0, UINT16_MAX, 0);
+
+ if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
+ sizeof(cb_port_delim)) != 0)
+ return -EINVAL;
+
+ /* destination port. */
+ GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
+ v->field[DSTP_FIELD_IPV6].value.u16,
+ 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
+ v->field[DSTP_FIELD_IPV6].mask_range.u16,
+ 0, UINT16_MAX, 0);
+
+ if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
+ sizeof(cb_port_delim)) != 0)
+ return -EINVAL;
+
+ GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].value.u8,
+ 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV6].mask_range.u8,
+ 0, UINT8_MAX, 0);
+
+ return 0;
+}
+
+static int
+parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
+{
+ uint8_t a, b, c, d, m;
+
+ GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
+
+ addr[0] = RTE_IPV4(a, b, c, d);
+ mask_len[0] = m;
+
+ return 0;
+}
+/*
+ * Parse ClassBench rules file.
+ * Expected format:
+ * '@'<src_ipv4_addr>'/'<masklen> <space> \
+ * <dst_ipv4_addr>'/'<masklen> <space> \
+ * <src_port_low> <space> ":" <src_port_high> <space> \
+ * <dst_port_low> <space> ":" <dst_port_high> <space> \
+ * <proto>'/'<mask>
+ */
+static int
+parse_cb_ipv4_rule(char *str, struct acl_rule *v)
+{
+ int i, rc;
+ char *s, *sp, *in[CB_FLD_NUM];
+ static const char *dlm = " \t\n";
+
+ /*
+ * Skip leading '@'
+ */
+ if (strchr(str, '@') != str)
+ return -EINVAL;
+
+ s = str + 1;
+
+ for (i = 0; i != RTE_DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
+ &v->field[SRC_FIELD_IPV4].value.u32,
+ &v->field[SRC_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL,
+ "failed to read source address/mask: %s\n",
+ in[CB_FLD_SRC_ADDR]);
+ return rc;
+ }
+
+ rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
+ &v->field[DST_FIELD_IPV4].value.u32,
+ &v->field[DST_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL,
+ "failed to read destination address/mask: %s\n",
+ in[CB_FLD_DST_ADDR]);
+ return rc;
+ }
+
+ /* source port. */
+ GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
+ v->field[SRCP_FIELD_IPV4].value.u16,
+ 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
+ v->field[SRCP_FIELD_IPV4].mask_range.u16,
+ 0, UINT16_MAX, 0);
+
+ if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
+ sizeof(cb_port_delim)) != 0)
+ return -EINVAL;
+
+ /* destination port. */
+ GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
+ v->field[DSTP_FIELD_IPV4].value.u16,
+ 0, UINT16_MAX, 0);
+ GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
+ v->field[DSTP_FIELD_IPV4].mask_range.u16,
+ 0, UINT16_MAX, 0);
+
+ if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
+ sizeof(cb_port_delim)) != 0)
+ return -EINVAL;
+
+ GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,
+ 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,
+ 0, UINT8_MAX, 0);
+
+ return 0;
+}
+
+typedef int (*parse_5tuple)(char *text, struct acl_rule *rule);
+
+static int
+add_cb_rules(FILE *f, struct rte_acl_ctx *ctx)
+{
+ int rc;
+ uint32_t n;
+ struct acl_rule v;
+ parse_5tuple parser;
+
+ memset(&v, 0, sizeof(v));
+ parser = (config.ipv6 != 0) ? parse_cb_ipv6_rule : parse_cb_ipv4_rule;
+
+ for (n = 1; fgets(line, sizeof(line), f) != NULL; n++) {
+
+ rc = parser(line, &v);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL, "line %u: parse_cb_ipv4vlan_rule"
+ " failed, error code: %d (%s)\n",
+ n, rc, strerror(-rc));
+ return rc;
+ }
+
+ v.data.category_mask = RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES,
+ typeof(v.data.category_mask));
+ v.data.priority = RTE_ACL_MAX_PRIORITY - n;
+ v.data.userdata = n;
+
+ rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&v, 1);
+ if (rc != 0) {
+ RTE_LOG(ERR, TESTACL, "line %u: failed to add rules "
+ "into ACL context, error code: %d (%s)\n",
+ n, rc, strerror(-rc));
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void
+acx_init(void)
+{
+ int ret;
+ FILE *f;
+ struct rte_acl_config cfg;
+
+ memset(&cfg, 0, sizeof(cfg));
+
+ /* setup ACL build config. */
+ if (config.ipv6) {
+ cfg.num_fields = RTE_DIM(ipv6_defs);
+ memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs));
+ } else {
+ cfg.num_fields = RTE_DIM(ipv4_defs);
+ memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs));
+ }
+ cfg.num_categories = config.bld_categories;
+ cfg.max_size = config.max_size;
+
+ /* setup ACL creation parameters. */
+ prm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields);
+ prm.max_rule_num = config.nb_rules;
+
+ config.acx = rte_acl_create(&prm);
+ if (config.acx == NULL)
+ rte_exit(rte_errno, "failed to create ACL context\n");
+
+ /* set default classify method for this context. */
+ if (config.alg.alg != RTE_ACL_CLASSIFY_DEFAULT) {
+ ret = rte_acl_set_ctx_classify(config.acx, config.alg.alg);
+ if (ret != 0)
+ rte_exit(ret, "failed to setup %s method "
+ "for ACL context\n", config.alg.name);
+ }
+
+ /* add ACL rules. */
+ f = fopen(config.rule_file, "r");
+ if (f == NULL)
+ rte_exit(-EINVAL, "failed to open file %s\n",
+ config.rule_file);
+
+ ret = add_cb_rules(f, config.acx);
+ if (ret != 0)
+ rte_exit(ret, "failed to add rules into ACL context\n");
+
+ fclose(f);
+
+ /* perform build. */
+ ret = rte_acl_build(config.acx, &cfg);
+
+ dump_verbose(DUMP_NONE, stdout,
+ "rte_acl_build(%u) finished with %d\n",
+ config.bld_categories, ret);
+
+ rte_acl_dump(config.acx);
+
+ if (ret != 0)
+ rte_exit(ret, "failed to build search context\n");
+}
+
+static uint32_t
+search_ip5tuples_once(uint32_t categories, uint32_t step, const char *alg)
+{
+ int ret;
+ uint32_t i, j, k, n, r;
+ const uint8_t *data[step], *v;
+ uint32_t results[step * categories];
+
+ v = config.traces;
+ for (i = 0; i != config.used_traces; i += n) {
+
+ n = RTE_MIN(step, config.used_traces - i);
+
+ for (j = 0; j != n; j++) {
+ data[j] = v;
+ v += config.trace_sz;
+ }
+
+ ret = rte_acl_classify(config.acx, data, results,
+ n, categories);
+
+ if (ret != 0)
+ rte_exit(ret, "classify for ipv%c_5tuples returns %d\n",
+ config.ipv6 ? '6' : '4', ret);
+
+ for (r = 0, j = 0; j != n; j++) {
+ for (k = 0; k != categories; k++, r++) {
+ dump_verbose(DUMP_PKT, stdout,
+ "ipv%c_5tuple: %u, category: %u, "
+ "result: %u\n",
+ config.ipv6 ? '6' : '4',
+ i + j + 1, k, results[r] - 1);
+ }
+
+ }
+ }
+
+ dump_verbose(DUMP_SEARCH, stdout,
+ "%s(%u, %u, %s) returns %u\n", __func__,
+ categories, step, alg, i);
+ return i;
+}
+
+static int
+search_ip5tuples(__rte_unused void *arg)
+{
+ uint64_t pkt, start, tm;
+ uint32_t i, lcore;
+
+ lcore = rte_lcore_id();
+ start = rte_rdtsc();
+ pkt = 0;
+
+ for (i = 0; i != config.iter_num; i++) {
+ pkt += search_ip5tuples_once(config.run_categories,
+ config.trace_step, config.alg.name);
+ }
+
+ tm = rte_rdtsc() - start;
+ dump_verbose(DUMP_NONE, stdout,
+ "%s @lcore %u: %" PRIu32 " iterations, %" PRIu64 " pkts, %"
+ PRIu32 " categories, %" PRIu64 " cycles, %#Lf cycles/pkt\n",
+ __func__, lcore, i, pkt, config.run_categories,
+ tm, (pkt == 0) ? 0 : (long double)tm / pkt);
+
+ return 0;
+}
+
+static unsigned long
+get_ulong_opt(const char *opt, const char *name, size_t min, size_t max)
+{
+ unsigned long val;
+ char *end;
+
+ errno = 0;
+ val = strtoul(opt, &end, 0);
+ if (errno != 0 || end[0] != 0 || val > max || val < min)
+ rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n",
+ opt, name);
+ return val;
+}
+
+static void
+get_alg_opt(const char *opt, const char *name)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(acl_alg); i++) {
+ if (strcmp(opt, acl_alg[i].name) == 0) {
+ config.alg = acl_alg[i];
+ return;
+ }
+ }
+
+ rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n",
+ opt, name);
+}
+
+static void
+print_usage(const char *prgname)
+{
+ uint32_t i, n, rc;
+ char buf[PATH_MAX];
+
+ n = 0;
+ buf[0] = 0;
+
+ for (i = 0; i < RTE_DIM(acl_alg) - 1; i++) {
+ rc = snprintf(buf + n, sizeof(buf) - n, "%s|",
+ acl_alg[i].name);
+ if (rc > sizeof(buf) - n)
+ break;
+ n += rc;
+ }
+
+ strlcpy(buf + n, acl_alg[i].name, sizeof(buf) - n);
+
+ fprintf(stdout,
+ PRINT_USAGE_START
+ "--" OPT_RULE_FILE "=<rules set file>\n"
+ "[--" OPT_TRACE_FILE "=<input traces file>]\n"
+ "[--" OPT_RULE_NUM
+ "=<maximum number of rules for ACL context>]\n"
+ "[--" OPT_TRACE_NUM
+ "=<number of traces to read binary file in>]\n"
+ "[--" OPT_TRACE_STEP
+ "=<number of traces to classify per one call>]\n"
+ "[--" OPT_BLD_CATEGORIES
+ "=<number of categories to build with>]\n"
+ "[--" OPT_RUN_CATEGORIES
+ "=<number of categories to run with> "
+ "should be either 1 or multiple of %zu, "
+ "but not greater then %u]\n"
+ "[--" OPT_MAX_SIZE
+ "=<size limit (in bytes) for runtime ACL strucutures> "
+ "leave 0 for default behaviour]\n"
+ "[--" OPT_ITER_NUM "=<number of iterations to perform>]\n"
+ "[--" OPT_VERBOSE "=<verbose level>]\n"
+ "[--" OPT_SEARCH_ALG "=%s]\n"
+ "[--" OPT_IPV6 "=<IPv6 rules and trace files>]\n",
+ prgname, RTE_ACL_RESULTS_MULTIPLIER,
+ (uint32_t)RTE_ACL_MAX_CATEGORIES,
+ buf);
+}
+
+static void
+dump_config(FILE *f)
+{
+ fprintf(f, "%s:\n", __func__);
+ fprintf(f, "%s:%s\n", OPT_RULE_FILE, config.rule_file);
+ fprintf(f, "%s:%s\n", OPT_TRACE_FILE, config.trace_file);
+ fprintf(f, "%s:%u\n", OPT_RULE_NUM, config.nb_rules);
+ fprintf(f, "%s:%u\n", OPT_TRACE_NUM, config.nb_traces);
+ fprintf(f, "%s:%u\n", OPT_TRACE_STEP, config.trace_step);
+ fprintf(f, "%s:%u\n", OPT_BLD_CATEGORIES, config.bld_categories);
+ fprintf(f, "%s:%u\n", OPT_RUN_CATEGORIES, config.run_categories);
+ fprintf(f, "%s:%zu\n", OPT_MAX_SIZE, config.max_size);
+ fprintf(f, "%s:%u\n", OPT_ITER_NUM, config.iter_num);
+ fprintf(f, "%s:%u\n", OPT_VERBOSE, config.verbose);
+ fprintf(f, "%s:%u(%s)\n", OPT_SEARCH_ALG, config.alg.alg,
+ config.alg.name);
+ fprintf(f, "%s:%u\n", OPT_IPV6, config.ipv6);
+}
+
+static void
+check_config(void)
+{
+ if (config.rule_file == NULL) {
+ print_usage(config.prgname);
+ rte_exit(-EINVAL, "mandatory option %s is not specified\n",
+ OPT_RULE_FILE);
+ }
+}
+
+
+static void
+get_input_opts(int argc, char **argv)
+{
+ static struct option lgopts[] = {
+ {OPT_RULE_FILE, 1, 0, 0},
+ {OPT_TRACE_FILE, 1, 0, 0},
+ {OPT_TRACE_NUM, 1, 0, 0},
+ {OPT_RULE_NUM, 1, 0, 0},
+ {OPT_MAX_SIZE, 1, 0, 0},
+ {OPT_TRACE_STEP, 1, 0, 0},
+ {OPT_BLD_CATEGORIES, 1, 0, 0},
+ {OPT_RUN_CATEGORIES, 1, 0, 0},
+ {OPT_ITER_NUM, 1, 0, 0},
+ {OPT_VERBOSE, 1, 0, 0},
+ {OPT_SEARCH_ALG, 1, 0, 0},
+ {OPT_IPV6, 0, 0, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ int opt, opt_idx;
+
+ while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
+
+ if (opt != 0) {
+ print_usage(config.prgname);
+ rte_exit(-EINVAL, "unknown option: %c", opt);
+ }
+
+ if (strcmp(lgopts[opt_idx].name, OPT_RULE_FILE) == 0) {
+ config.rule_file = optarg;
+ } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) {
+ config.trace_file = optarg;
+ } else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) {
+ config.nb_rules = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1, RTE_ACL_MAX_INDEX + 1);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) {
+ config.max_size = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 0, SIZE_MAX);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) {
+ config.nb_traces = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1, UINT32_MAX);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) {
+ config.trace_step = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1, TRACE_STEP_MAX);
+ } else if (strcmp(lgopts[opt_idx].name,
+ OPT_BLD_CATEGORIES) == 0) {
+ config.bld_categories = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1,
+ RTE_ACL_MAX_CATEGORIES);
+ } else if (strcmp(lgopts[opt_idx].name,
+ OPT_RUN_CATEGORIES) == 0) {
+ config.run_categories = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1,
+ RTE_ACL_MAX_CATEGORIES);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) {
+ config.iter_num = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, 1, INT32_MAX);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) {
+ config.verbose = get_ulong_opt(optarg,
+ lgopts[opt_idx].name, DUMP_NONE, DUMP_MAX);
+ } else if (strcmp(lgopts[opt_idx].name,
+ OPT_SEARCH_ALG) == 0) {
+ get_alg_opt(optarg, lgopts[opt_idx].name);
+ } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) {
+ config.ipv6 = 1;
+ }
+ }
+ config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) :
+ sizeof(struct ipv4_5tuple);
+
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ uint32_t lcore;
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= ret;
+ argv += ret;
+
+ config.prgname = argv[0];
+
+ get_input_opts(argc, argv);
+ dump_config(stdout);
+ check_config();
+
+ acx_init();
+
+ if (config.trace_file != NULL)
+ tracef_init();
+
+ RTE_LCORE_FOREACH_SLAVE(lcore)
+ rte_eal_remote_launch(search_ip5tuples, NULL, lcore);
+
+ search_ip5tuples(NULL);
+
+ rte_eal_mp_wait_lcore();
+
+ rte_acl_free(config.acx);
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-acl/meson.build b/src/spdk/dpdk/app/test-acl/meson.build
new file mode 100644
index 000000000..d5c2581b4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-acl/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+sources = files('main.c')
+deps += ['acl', 'net']
diff --git a/src/spdk/dpdk/app/test-bbdev/Makefile b/src/spdk/dpdk/app/test-bbdev/Makefile
new file mode 100644
index 000000000..dc29557f3
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/Makefile
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+APP = testbbdev
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all sources are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_TEST_BBDEV) += main.c
+SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev.c
+SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev_perf.c
+SRCS-$(CONFIG_RTE_TEST_BBDEV) += test_bbdev_vector.c
+
+LDLIBS += -lm
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC),y)
+LDLIBS += -lrte_pmd_bbdev_fpga_lte_fec
+endif
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC),y)
+LDLIBS += -lrte_pmd_bbdev_fpga_5gnr_fec
+endif
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/spdk/dpdk/app/test-bbdev/ldpc_dec_default.data b/src/spdk/dpdk/app/test-bbdev/ldpc_dec_default.data
new file mode 120000
index 000000000..e53aa1b90
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/ldpc_dec_default.data
@@ -0,0 +1 @@
+test_vectors/ldpc_dec_v2342_drop.data \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/ldpc_enc_default.data b/src/spdk/dpdk/app/test-bbdev/ldpc_enc_default.data
new file mode 120000
index 000000000..371cbc692
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/ldpc_enc_default.data
@@ -0,0 +1 @@
+test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/main.c b/src/spdk/dpdk/app/test-bbdev/main.c
new file mode 100644
index 000000000..ff65173fd
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/main.c
@@ -0,0 +1,362 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+
+#include "main.h"
+
+
+/* Defines how many testcases can be specified as cmdline args */
+#define MAX_CMDLINE_TESTCASES 8
+
+static const char tc_sep = ',';
+
+/* Declare structure for command line test parameters and options */
+static struct test_params {
+ struct test_command *test_to_run[MAX_CMDLINE_TESTCASES];
+ unsigned int num_tests;
+ unsigned int num_ops;
+ unsigned int burst_sz;
+ unsigned int num_lcores;
+ double snr;
+ unsigned int iter_max;
+ char test_vector_filename[PATH_MAX];
+ bool init_device;
+} test_params;
+
+static struct test_commands_list commands_list =
+ TAILQ_HEAD_INITIALIZER(commands_list);
+
+void
+add_test_command(struct test_command *t)
+{
+ TAILQ_INSERT_TAIL(&commands_list, t, next);
+}
+
+int
+unit_test_suite_runner(struct unit_test_suite *suite)
+{
+ int test_result = TEST_SUCCESS;
+ unsigned int total = 0, skipped = 0, succeeded = 0, failed = 0;
+ uint64_t start, end;
+
+ printf("\n===========================================================\n");
+ printf("Starting Test Suite : %s\n", suite->suite_name);
+
+ start = rte_rdtsc_precise();
+
+ if (suite->setup) {
+ test_result = suite->setup();
+ if (test_result == TEST_FAILED) {
+ printf(" + Test suite setup %s failed!\n",
+ suite->suite_name);
+ printf(" + ------------------------------------------------------- +\n");
+ return 1;
+ }
+ if (test_result == TEST_SKIPPED) {
+ printf(" + Test suite setup %s skipped!\n",
+ suite->suite_name);
+ printf(" + ------------------------------------------------------- +\n");
+ return 0;
+ }
+ }
+
+ while (suite->unit_test_cases[total].testcase) {
+ if (suite->unit_test_cases[total].setup)
+ test_result = suite->unit_test_cases[total].setup();
+
+ if (test_result == TEST_SUCCESS)
+ test_result = suite->unit_test_cases[total].testcase();
+
+ if (suite->unit_test_cases[total].teardown)
+ suite->unit_test_cases[total].teardown();
+
+ if (test_result == TEST_SUCCESS) {
+ succeeded++;
+ printf("TestCase [%2d] : %s passed\n", total,
+ suite->unit_test_cases[total].name);
+ } else if (test_result == TEST_SKIPPED) {
+ skipped++;
+ printf("TestCase [%2d] : %s skipped\n", total,
+ suite->unit_test_cases[total].name);
+ } else {
+ failed++;
+ printf("TestCase [%2d] : %s failed\n", total,
+ suite->unit_test_cases[total].name);
+ }
+
+ total++;
+ }
+
+ /* Run test suite teardown */
+ if (suite->teardown)
+ suite->teardown();
+
+ end = rte_rdtsc_precise();
+
+ printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
+ printf(" + Test Suite Summary : %s\n", suite->suite_name);
+ printf(" + Tests Total : %2d\n", total);
+ printf(" + Tests Skipped : %2d\n", skipped);
+ printf(" + Tests Passed : %2d\n", succeeded);
+ printf(" + Tests Failed : %2d\n", failed);
+ printf(" + Tests Lasted : %lg ms\n",
+ ((end - start) * 1000) / (double)rte_get_tsc_hz());
+ printf(" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +\n");
+
+ return (failed > 0) ? 1 : 0;
+}
+
+const char *
+get_vector_filename(void)
+{
+ return test_params.test_vector_filename;
+}
+
+unsigned int
+get_num_ops(void)
+{
+ return test_params.num_ops;
+}
+
+unsigned int
+get_burst_sz(void)
+{
+ return test_params.burst_sz;
+}
+
+unsigned int
+get_num_lcores(void)
+{
+ return test_params.num_lcores;
+}
+
+double
+get_snr(void)
+{
+ return test_params.snr;
+}
+
+unsigned int
+get_iter_max(void)
+{
+ return test_params.iter_max;
+}
+
+bool
+get_init_device(void)
+{
+ return test_params.init_device;
+}
+
+static void
+print_usage(const char *prog_name)
+{
+ struct test_command *t;
+
+ printf("***Usage: %s [EAL params] [-- [-n/--num-ops NUM_OPS]\n"
+ "\t[-b/--burst-size BURST_SIZE]\n"
+ "\t[-v/--test-vector VECTOR_FILE]\n"
+ "\t[-c/--test-cases TEST_CASE[,TEST_CASE,...]]]\n",
+ prog_name);
+
+ printf("Available testcases: ");
+ TAILQ_FOREACH(t, &commands_list, next)
+ printf("%s ", t->command);
+ printf("\n");
+}
+
+static int
+parse_args(int argc, char **argv, struct test_params *tp)
+{
+ int opt, option_index;
+ unsigned int num_tests = 0;
+ bool test_cases_present = false;
+ bool test_vector_present = false;
+ struct test_command *t;
+ char *tokens[MAX_CMDLINE_TESTCASES];
+ int tc, ret;
+
+ static struct option lgopts[] = {
+ { "num-ops", 1, 0, 'n' },
+ { "burst-size", 1, 0, 'b' },
+ { "test-cases", 1, 0, 'c' },
+ { "test-vector", 1, 0, 'v' },
+ { "lcores", 1, 0, 'l' },
+ { "snr", 1, 0, 's' },
+ { "iter_max", 6, 0, 't' },
+ { "init-device", 0, 0, 'i'},
+ { "help", 0, 0, 'h' },
+ { NULL, 0, 0, 0 }
+ };
+ tp->iter_max = DEFAULT_ITER;
+
+ while ((opt = getopt_long(argc, argv, "hin:b:c:v:l:s:t:", lgopts,
+ &option_index)) != EOF)
+ switch (opt) {
+ case 'n':
+ TEST_ASSERT(strlen(optarg) > 0,
+ "Num of operations is not provided");
+ tp->num_ops = strtol(optarg, NULL, 10);
+ break;
+ case 'b':
+ TEST_ASSERT(strlen(optarg) > 0,
+ "Burst size is not provided");
+ tp->burst_sz = strtol(optarg, NULL, 10);
+ TEST_ASSERT(tp->burst_sz <= MAX_BURST,
+ "Burst size mustn't be greater than %u",
+ MAX_BURST);
+ break;
+ case 'c':
+ TEST_ASSERT(test_cases_present == false,
+ "Test cases provided more than once");
+ test_cases_present = true;
+
+ ret = rte_strsplit(optarg, strlen(optarg),
+ tokens, MAX_CMDLINE_TESTCASES, tc_sep);
+
+ TEST_ASSERT(ret <= MAX_CMDLINE_TESTCASES,
+ "Too many test cases (max=%d)",
+ MAX_CMDLINE_TESTCASES);
+
+ for (tc = 0; tc < ret; ++tc) {
+ /* Find matching test case */
+ TAILQ_FOREACH(t, &commands_list, next)
+ if (!strcmp(tokens[tc], t->command))
+ tp->test_to_run[num_tests] = t;
+
+ TEST_ASSERT(tp->test_to_run[num_tests] != NULL,
+ "Unknown test case: %s",
+ tokens[tc]);
+ ++num_tests;
+ }
+ break;
+ case 'v':
+ TEST_ASSERT(test_vector_present == false,
+ "Test vector provided more than once");
+ test_vector_present = true;
+
+ TEST_ASSERT(strlen(optarg) > 0,
+ "Config file name is null");
+
+ snprintf(tp->test_vector_filename,
+ sizeof(tp->test_vector_filename),
+ "%s", optarg);
+ break;
+ case 's':
+ TEST_ASSERT(strlen(optarg) > 0,
+ "SNR is not provided");
+ tp->snr = strtod(optarg, NULL);
+ break;
+ case 't':
+ TEST_ASSERT(strlen(optarg) > 0,
+ "Iter_max is not provided");
+ tp->iter_max = strtol(optarg, NULL, 10);
+ break;
+ case 'l':
+ TEST_ASSERT(strlen(optarg) > 0,
+ "Num of lcores is not provided");
+ tp->num_lcores = strtol(optarg, NULL, 10);
+ TEST_ASSERT(tp->num_lcores <= RTE_MAX_LCORE,
+ "Num of lcores mustn't be greater than %u",
+ RTE_MAX_LCORE);
+ break;
+ case 'i':
+ /* indicate fpga fec config required */
+ tp->init_device = true;
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ return 0;
+ default:
+ printf("ERROR: Unknown option: -%c\n", opt);
+ return -1;
+ }
+
+ if (tp->num_ops == 0) {
+ printf(
+ "WARNING: Num of operations was not provided or was set 0. Set to default (%u)\n",
+ DEFAULT_OPS);
+ tp->num_ops = DEFAULT_OPS;
+ }
+ if (tp->burst_sz == 0) {
+ printf(
+ "WARNING: Burst size was not provided or was set 0. Set to default (%u)\n",
+ DEFAULT_BURST);
+ tp->burst_sz = DEFAULT_BURST;
+ }
+ if (tp->num_lcores == 0) {
+ printf(
+ "WARNING: Num of lcores was not provided or was set 0. Set to value from RTE config (%u)\n",
+ rte_lcore_count());
+ tp->num_lcores = rte_lcore_count();
+ }
+
+ TEST_ASSERT(tp->burst_sz <= tp->num_ops,
+ "Burst size (%u) mustn't be greater than num ops (%u)",
+ tp->burst_sz, tp->num_ops);
+
+ tp->num_tests = num_tests;
+ return 0;
+}
+
+static int
+run_all_tests(void)
+{
+ int ret = TEST_SUCCESS;
+ struct test_command *t;
+
+ TAILQ_FOREACH(t, &commands_list, next)
+ ret |= (int) t->callback();
+
+ return ret;
+}
+
+static int
+run_parsed_tests(struct test_params *tp)
+{
+ int ret = TEST_SUCCESS;
+ unsigned int i;
+
+ for (i = 0; i < tp->num_tests; ++i)
+ ret |= (int) tp->test_to_run[i]->callback();
+
+ return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+
+ /* Init EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ return 1;
+ argc -= ret;
+ argv += ret;
+
+ /* Parse application arguments (after the EAL ones) */
+ ret = parse_args(argc, argv, &test_params);
+ if (ret < 0) {
+ print_usage(argv[0]);
+ return 1;
+ }
+
+ /* If no argument provided - run all tests */
+ if (test_params.num_tests == 0)
+ return run_all_tests();
+ else
+ return run_parsed_tests(&test_params);
+}
diff --git a/src/spdk/dpdk/app/test-bbdev/main.h b/src/spdk/dpdk/app/test-bbdev/main.h
new file mode 100644
index 000000000..fb3dec832
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/main.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include <stddef.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_log.h>
+
+#define TEST_SUCCESS 0
+#define TEST_FAILED -1
+#define TEST_SKIPPED 1
+
+#define MAX_BURST 512U
+#define DEFAULT_BURST 32U
+#define DEFAULT_OPS 64U
+#define DEFAULT_ITER 6U
+
+
+
+#define TEST_ASSERT(cond, msg, ...) do { \
+ if (!(cond)) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+/* Compare two buffers (length in bytes) */
+#define TEST_ASSERT_BUFFERS_ARE_EQUAL(a, b, len, msg, ...) do { \
+ if (memcmp((a), (b), len)) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ rte_memdump(stdout, "Buffer A", (a), len); \
+ rte_memdump(stdout, "Buffer B", (b), len); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+#define TEST_ASSERT_SUCCESS(val, msg, ...) do { \
+ typeof(val) _val = (val); \
+ if (!(_val == 0)) { \
+ printf("TestCase %s() line %d failed (err %d): " \
+ msg "\n", __func__, __LINE__, _val, \
+ ##__VA_ARGS__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+#define TEST_ASSERT_FAIL(val, msg, ...) \
+ TEST_ASSERT_SUCCESS(!(val), msg, ##__VA_ARGS__)
+
+#define TEST_ASSERT_NOT_NULL(val, msg, ...) do { \
+ if ((val) == NULL) { \
+ printf("TestCase %s() line %d failed (null): " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+struct unit_test_case {
+ int (*setup)(void);
+ void (*teardown)(void);
+ int (*testcase)(void);
+ const char *name;
+};
+
+#define TEST_CASE(testcase) {NULL, NULL, testcase, #testcase}
+
+#define TEST_CASE_ST(setup, teardown, testcase) \
+ {setup, teardown, testcase, #testcase}
+
+#define TEST_CASES_END() {NULL, NULL, NULL, NULL}
+
+struct unit_test_suite {
+ const char *suite_name;
+ int (*setup)(void);
+ void (*teardown)(void);
+ struct unit_test_case unit_test_cases[];
+};
+
+int unit_test_suite_runner(struct unit_test_suite *suite);
+
+typedef int (test_callback)(void);
+TAILQ_HEAD(test_commands_list, test_command);
+struct test_command {
+ TAILQ_ENTRY(test_command) next;
+ const char *command;
+ test_callback *callback;
+};
+
+void add_test_command(struct test_command *t);
+
+/* Register a test function */
+#define REGISTER_TEST_COMMAND(name, testsuite) \
+ static int test_func_##name(void) \
+ { \
+ return unit_test_suite_runner(&testsuite); \
+ } \
+ static struct test_command test_struct_##name = { \
+ .command = RTE_STR(name), \
+ .callback = test_func_##name, \
+ }; \
+ RTE_INIT(test_register_##name) \
+ { \
+ add_test_command(&test_struct_##name); \
+ }
+
+const char *get_vector_filename(void);
+
+unsigned int get_num_ops(void);
+
+unsigned int get_burst_sz(void);
+
+unsigned int get_num_lcores(void);
+
+double get_snr(void);
+
+unsigned int get_iter_max(void);
+
+bool get_init_device(void);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-bbdev/meson.build b/src/spdk/dpdk/app/test-bbdev/meson.build
new file mode 100644
index 000000000..18ab6a8c6
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+sources = files('main.c',
+ 'test_bbdev.c',
+ 'test_bbdev_perf.c',
+ 'test_bbdev_vector.c')
+deps += ['bbdev', 'bus_vdev']
+if dpdk_conf.has('RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC')
+ deps += ['pmd_bbdev_fpga_lte_fec']
+endif
+if dpdk_conf.has('RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC')
+ deps += ['pmd_bbdev_fpga_5gnr_fec']
+endif
diff --git a/src/spdk/dpdk/app/test-bbdev/test-bbdev.py b/src/spdk/dpdk/app/test-bbdev/test-bbdev.py
new file mode 100755
index 000000000..0194be046
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test-bbdev.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+import sys
+import os
+import argparse
+import subprocess
+import shlex
+
+from threading import Timer
+
+def kill(process):
+ print "ERROR: Test app timed out"
+ process.kill()
+
+if "RTE_SDK" in os.environ:
+ dpdk_path = os.environ["RTE_SDK"]
+else:
+ dpdk_path = "../.."
+
+if "RTE_TARGET" in os.environ:
+ dpdk_target = os.environ["RTE_TARGET"]
+else:
+ dpdk_target = "x86_64-native-linux-gcc"
+
+parser = argparse.ArgumentParser(
+ description='BBdev Unit Test Application',
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+parser.add_argument("-p", "--testapp-path",
+ help="specifies path to the bbdev test app",
+ default=dpdk_path + "/" + dpdk_target + "/app/testbbdev")
+parser.add_argument("-e", "--eal-params",
+ help="EAL arguments which are passed to the test app",
+ default="--vdev=baseband_null0")
+parser.add_argument("-t", "--timeout",
+ type=int,
+ help="Timeout in seconds",
+ default=300)
+parser.add_argument("-c", "--test-cases",
+ nargs="+",
+ help="Defines test cases to run. Run all if not specified")
+parser.add_argument("-v", "--test-vector",
+ nargs="+",
+ help="Specifies paths to the test vector files.",
+ default=[dpdk_path +
+ "/app/test-bbdev/test_vectors/bbdev_null.data"])
+parser.add_argument("-n", "--num-ops",
+ type=int,
+ help="Number of operations to process on device.",
+ default=32)
+parser.add_argument("-b", "--burst-size",
+ nargs="+",
+ type=int,
+ help="Operations enqueue/dequeue burst size.",
+ default=[32])
+parser.add_argument("-l", "--num-lcores",
+ type=int,
+ help="Number of lcores to run.",
+ default=16)
+parser.add_argument("-i", "--init-device",
+ action='store_true',
+ help="Initialise PF device with default values.")
+
+args = parser.parse_args()
+
+if not os.path.exists(args.testapp_path):
+ print "No such file: " + args.testapp_path
+ sys.exit(1)
+
+params = [args.testapp_path]
+if args.eal_params:
+ params.extend(shlex.split(args.eal_params))
+
+params.extend(["--"])
+
+if args.num_ops:
+ params.extend(["-n", str(args.num_ops)])
+
+if args.num_lcores:
+ params.extend(["-l", str(args.num_lcores)])
+
+if args.test_cases:
+ params.extend(["-c"])
+ params.extend([",".join(args.test_cases)])
+
+if args.init_device:
+ params.extend(["-i"])
+
+
+exit_status = 0
+for vector in args.test_vector:
+ for burst_size in args.burst_size:
+ call_params = params[:]
+ call_params.extend(["-v", vector])
+ call_params.extend(["-b", str(burst_size)])
+ params_string = " ".join(call_params)
+
+ print("Executing: {}".format(params_string))
+ app_proc = subprocess.Popen(call_params)
+ if args.timeout > 0:
+ timer = Timer(args.timeout, kill, [app_proc])
+ timer.start()
+
+ try:
+ app_proc.communicate()
+ except:
+ print("Error: failed to execute: {}".format(params_string))
+ finally:
+ timer.cancel()
+
+ if app_proc.returncode != 0:
+ exit_status = 1
+ print("ERROR TestCase failed. Failed test for vector {}. Return code: {}".format(
+ vector, app_proc.returncode))
+
+sys.exit(exit_status)
diff --git a/src/spdk/dpdk/app/test-bbdev/test_bbdev.c b/src/spdk/dpdk/app/test-bbdev/test_bbdev.c
new file mode 100644
index 000000000..ac06d7320
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_bbdev.c
@@ -0,0 +1,1371 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_cycles.h>
+
+#include <rte_bus_vdev.h>
+
+#include <rte_bbdev.h>
+#include <rte_bbdev_op.h>
+#include <rte_bbdev_pmd.h>
+
+#include "main.h"
+
+
+#define BBDEV_NAME_NULL ("bbdev_null")
+
+struct bbdev_testsuite_params {
+ struct rte_bbdev_queue_conf qconf;
+};
+
+static struct bbdev_testsuite_params testsuite_params;
+
+static uint8_t null_dev_id;
+
+static int
+testsuite_setup(void)
+{
+ uint8_t nb_devs;
+ int ret;
+ char buf[RTE_BBDEV_NAME_MAX_LEN];
+
+ /* Create test device */
+ snprintf(buf, sizeof(buf), "%s_unittest", BBDEV_NAME_NULL);
+ ret = rte_vdev_init(buf, NULL);
+ TEST_ASSERT(ret == 0, "Failed to create instance of pmd: %s", buf);
+
+ nb_devs = rte_bbdev_count();
+ TEST_ASSERT(nb_devs != 0, "No devices found");
+
+ /* Most recently created device is our device */
+ null_dev_id = nb_devs - 1;
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ char buf[RTE_BBDEV_NAME_MAX_LEN];
+
+ snprintf(buf, sizeof(buf), "%s_unittest", BBDEV_NAME_NULL);
+ rte_vdev_uninit(buf);
+}
+
+static int
+ut_setup(void)
+{
+ struct bbdev_testsuite_params *ts_params = &testsuite_params;
+ uint8_t num_queues;
+
+ /* Valid queue configuration */
+ ts_params->qconf.priority = 0;
+ ts_params->qconf.socket = SOCKET_ID_ANY;
+ ts_params->qconf.deferred_start = 1;
+
+ num_queues = 1;
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(null_dev_id, num_queues,
+ SOCKET_ID_ANY), "Failed to setup queues for bbdev %u",
+ 0);
+
+ /* Start the device */
+ TEST_ASSERT_SUCCESS(rte_bbdev_start(null_dev_id),
+ "Failed to start bbdev %u", 0);
+
+ return TEST_SUCCESS;
+}
+
+static void
+ut_teardown(void)
+{
+ rte_bbdev_close(null_dev_id);
+}
+
+static int
+test_bbdev_configure_invalid_dev_id(void)
+{
+ uint8_t dev_id;
+ uint8_t num_queues;
+
+ num_queues = 1;
+ for (dev_id = 0; dev_id < RTE_BBDEV_MAX_DEVS; dev_id++) {
+ if (!rte_bbdev_is_valid(dev_id)) {
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id,
+ num_queues, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "invalid dev_num %u", dev_id);
+ TEST_ASSERT(rte_bbdev_intr_enable(dev_id) == -ENODEV,
+ "Failed test for rte_bbdev_intr_enable: "
+ "invalid dev_num %u", dev_id);
+ break;
+ }
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_configure_invalid_num_queues(void)
+{
+ struct rte_bbdev_info info;
+ uint8_t dev_id, num_devs;
+ uint8_t num_queues;
+ int return_value;
+
+ TEST_ASSERT((num_devs = rte_bbdev_count()) >= 1,
+ "Need at least %d devices for test", 1);
+
+ /* valid num_queues values */
+ num_queues = 8;
+
+ /* valid dev_id values */
+ dev_id = null_dev_id;
+
+ /* Stop the device in case it's started so it can be configured */
+ rte_bbdev_stop(dev_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id, 0, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "invalid num_queues %d", 0);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(dev_id, num_queues,
+ SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "invalid dev_num %u", dev_id);
+
+ TEST_ASSERT_FAIL(return_value = rte_bbdev_info_get(dev_id, NULL),
+ "Failed test for rte_bbdev_info_get: "
+ "returned value:%i", return_value);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value:%i", return_value);
+
+ TEST_ASSERT(info.num_queues == num_queues,
+ "Failed test for rte_bbdev_info_get: "
+ "invalid num_queues:%u", info.num_queues);
+
+ num_queues = info.drv.max_num_queues;
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(dev_id, num_queues,
+ SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "invalid num_queues: %u", num_queues);
+
+ num_queues++;
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id, num_queues,
+ SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "invalid num_queues: %u", num_queues);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_configure_stop_device(void)
+{
+ struct rte_bbdev_info info;
+ uint8_t dev_id;
+ int return_value;
+
+ /* valid dev_id values */
+ dev_id = null_dev_id;
+
+ /* Stop the device so it can be configured */
+ rte_bbdev_stop(dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_info_get function: %i", return_value);
+
+ TEST_ASSERT_SUCCESS(info.started, "Failed test for rte_bbdev_info_get: "
+ "started value: %u", info.started);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(dev_id,
+ info.drv.max_num_queues, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "device should be stopped, dev_id: %u", dev_id);
+
+ return_value = rte_bbdev_intr_enable(dev_id);
+ TEST_ASSERT(return_value != -EBUSY,
+ "Failed test for rte_bbdev_intr_enable: device should be stopped, dev_id: %u",
+ dev_id);
+
+ /* Start the device so it cannot be configured */
+ TEST_ASSERT_FAIL(rte_bbdev_start(RTE_BBDEV_MAX_DEVS),
+ "Failed to start bbdev %u", dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
+ "Failed to start bbdev %u", dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_info_get function: %i", return_value);
+
+ TEST_ASSERT_FAIL(info.started, "Failed test for rte_bbdev_info_get: "
+ "started value: %u", info.started);
+
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id,
+ info.drv.max_num_queues, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "device should be started, dev_id: %u", dev_id);
+
+ return_value = rte_bbdev_intr_enable(dev_id);
+ TEST_ASSERT(return_value == -EBUSY,
+ "Failed test for rte_bbdev_intr_enable: device should be started, dev_id: %u",
+ dev_id);
+
+ /* Stop again the device so it can be once again configured */
+ TEST_ASSERT_FAIL(rte_bbdev_stop(RTE_BBDEV_MAX_DEVS),
+ "Failed to start bbdev %u", dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stop(dev_id), "Failed to stop bbdev %u",
+ dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_info_get function: %i", return_value);
+
+ TEST_ASSERT_SUCCESS(info.started, "Failed test for rte_bbdev_info_get: "
+ "started value: %u", info.started);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(dev_id,
+ info.drv.max_num_queues, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "device should be stopped, dev_id: %u", dev_id);
+
+ return_value = rte_bbdev_intr_enable(dev_id);
+ TEST_ASSERT(return_value != -EBUSY,
+ "Failed test for rte_bbdev_intr_enable: device should be stopped, dev_id: %u",
+ dev_id);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_configure_stop_queue(void)
+{
+ struct bbdev_testsuite_params *ts_params = &testsuite_params;
+ struct rte_bbdev_info info;
+ struct rte_bbdev_queue_info qinfo;
+ uint8_t dev_id;
+ uint16_t queue_id;
+ int return_value;
+
+ /* Valid dev_id values */
+ dev_id = null_dev_id;
+
+ /* Valid queue_id values */
+ queue_id = 0;
+
+ rte_bbdev_stop(dev_id);
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value:%i", return_value);
+
+ /* Valid queue configuration */
+ ts_params->qconf.queue_size = info.drv.queue_size_lim;
+ ts_params->qconf.priority = info.drv.max_ul_queue_priority;
+
+ /* Device - started; queue - started */
+ rte_bbdev_start(dev_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "queue:%u on device:%u should be stopped",
+ queue_id, dev_id);
+
+ /* Device - stopped; queue - started */
+ rte_bbdev_stop(dev_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "queue:%u on device:%u should be stopped",
+ queue_id, dev_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_stop(RTE_BBDEV_MAX_DEVS, queue_id),
+ "Failed test for rte_bbdev_queue_stop "
+ "invalid dev_id ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_stop(dev_id, RTE_MAX_QUEUES_PER_PORT),
+ "Failed test for rte_bbdev_queue_stop "
+ "invalid queue_id ");
+
+ /* Device - stopped; queue - stopped */
+ rte_bbdev_queue_stop(dev_id, queue_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "queue:%u on device:%u should be stopped", queue_id,
+ dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_queue_info_get(dev_id,
+ queue_id, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_queue_info_get function: %i", return_value);
+
+ TEST_ASSERT(qinfo.conf.socket == ts_params->qconf.socket,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid queue_size:%u", qinfo.conf.socket);
+
+ TEST_ASSERT(qinfo.conf.queue_size == ts_params->qconf.queue_size,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid queue_size:%u", qinfo.conf.queue_size);
+
+ TEST_ASSERT(qinfo.conf.priority == ts_params->qconf.priority,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid queue_size:%u", qinfo.conf.priority);
+
+ TEST_ASSERT(qinfo.conf.deferred_start ==
+ ts_params->qconf.deferred_start,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid queue_size:%u", qinfo.conf.deferred_start);
+
+ /* Device - started; queue - stopped */
+ rte_bbdev_start(dev_id);
+ rte_bbdev_queue_stop(dev_id, queue_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "queue:%u on device:%u should be stopped", queue_id,
+ dev_id);
+
+ rte_bbdev_stop(dev_id);
+
+ /* After rte_bbdev_start(dev_id):
+ * - queue should be still stopped if deferred_start ==
+ */
+ rte_bbdev_start(dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_queue_info_get(dev_id,
+ queue_id, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_queue_info_get function: %i", return_value);
+
+ TEST_ASSERT(qinfo.started == 0,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid value for qinfo.started:%u", qinfo.started);
+
+ rte_bbdev_stop(dev_id);
+
+ /* After rte_bbdev_start(dev_id):
+ * - queue should be started if deferred_start ==
+ */
+ ts_params->qconf.deferred_start = 0;
+ rte_bbdev_queue_configure(dev_id, queue_id, &ts_params->qconf);
+ rte_bbdev_start(dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_queue_info_get(dev_id,
+ queue_id, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value from "
+ "rte_bbdev_queue_info_get function: %i", return_value);
+
+ TEST_ASSERT(qinfo.started == 1,
+ "Failed test for rte_bbdev_queue_info_get: "
+ "invalid value for qinfo.started:%u", qinfo.started);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_configure_invalid_queue_configure(void)
+{
+ struct bbdev_testsuite_params *ts_params = &testsuite_params;
+ int return_value;
+ struct rte_bbdev_info info;
+ uint8_t dev_id;
+ uint16_t queue_id;
+
+ /* Valid dev_id values */
+ dev_id = null_dev_id;
+
+ /* Valid queue_id values */
+ queue_id = 0;
+
+ rte_bbdev_stop(dev_id);
+
+ TEST_ASSERT_SUCCESS(return_value = rte_bbdev_info_get(dev_id, &info),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid return value:%i", return_value);
+
+ rte_bbdev_queue_stop(dev_id, queue_id);
+
+ ts_params->qconf.queue_size = info.drv.queue_size_lim + 1;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid value qconf.queue_size: %u",
+ ts_params->qconf.queue_size);
+
+ ts_params->qconf.queue_size = info.drv.queue_size_lim;
+ ts_params->qconf.priority = info.drv.max_ul_queue_priority;
+ queue_id = info.num_queues;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid value queue_id: %u", queue_id);
+
+ queue_id = 0;
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id, NULL),
+ "Failed test for rte_bbdev_queue_configure: "
+ "NULL qconf structure ");
+
+ ts_params->qconf.socket = RTE_MAX_NUMA_NODES;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid socket number ");
+
+ ts_params->qconf.socket = SOCKET_ID_ANY;
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid value qconf.queue_size: %u",
+ ts_params->qconf.queue_size);
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(RTE_BBDEV_MAX_DEVS, queue_id,
+ &ts_params->qconf),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid dev_id");
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id, NULL),
+ "Failed test for rte_bbdev_queue_configure: "
+ "invalid value qconf.queue_size: %u",
+ ts_params->qconf.queue_size);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_op_pool(void)
+{
+ struct rte_mempool *mp;
+
+ unsigned int dec_size = sizeof(struct rte_bbdev_dec_op);
+ unsigned int enc_size = sizeof(struct rte_bbdev_enc_op);
+
+ const char *pool_dec = "Test_DEC";
+ const char *pool_enc = "Test_ENC";
+
+ /* Valid pool configuration */
+ uint32_t size = 256;
+ uint32_t cache_size = 128;
+
+ TEST_ASSERT(rte_bbdev_op_pool_create(NULL,
+ RTE_BBDEV_OP_TURBO_DEC, size, cache_size, 0) == NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "NULL name parameter");
+
+ TEST_ASSERT((mp = rte_bbdev_op_pool_create(pool_dec,
+ RTE_BBDEV_OP_TURBO_DEC, size, cache_size, 0)) != NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "returned value is empty");
+
+ TEST_ASSERT(mp->size == size,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid size of the mempool, mp->size: %u", mp->size);
+
+ TEST_ASSERT(mp->cache_size == cache_size,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid size of the mempool, mp->size: %u",
+ mp->cache_size);
+
+ TEST_ASSERT_SUCCESS(strcmp(mp->name, pool_dec),
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid name of mempool, mp->name: %s", mp->name);
+
+ TEST_ASSERT(mp->elt_size == dec_size,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid element size for RTE_BBDEV_OP_TURBO_DEC, "
+ "mp->elt_size: %u", mp->elt_size);
+
+ rte_mempool_free(mp);
+
+ TEST_ASSERT((mp = rte_bbdev_op_pool_create(pool_enc,
+ RTE_BBDEV_OP_TURBO_ENC, size, cache_size, 0)) != NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "returned value is empty");
+
+ TEST_ASSERT(mp->elt_size == enc_size,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid element size for RTE_BBDEV_OP_TURBO_ENC, "
+ "mp->elt_size: %u", mp->elt_size);
+
+ rte_mempool_free(mp);
+
+ TEST_ASSERT((mp = rte_bbdev_op_pool_create("Test_NONE",
+ RTE_BBDEV_OP_NONE, size, cache_size, 0)) != NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "returned value is empty for RTE_BBDEV_OP_NONE");
+
+ TEST_ASSERT(mp->elt_size == (enc_size > dec_size ? enc_size : dec_size),
+ "Failed test for rte_bbdev_op_pool_create: "
+ "invalid size for RTE_BBDEV_OP_NONE, mp->elt_size: %u",
+ mp->elt_size);
+
+ rte_mempool_free(mp);
+
+ TEST_ASSERT((mp = rte_bbdev_op_pool_create("Test_INV",
+ RTE_BBDEV_OP_TYPE_COUNT, size, cache_size, 0)) == NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "returned value is not NULL for invalid type");
+
+ /* Invalid pool configuration */
+ size = 128;
+ cache_size = 256;
+
+ TEST_ASSERT((mp = rte_bbdev_op_pool_create("Test_InvSize",
+ RTE_BBDEV_OP_NONE, size, cache_size, 0)) == NULL,
+ "Failed test for rte_bbdev_op_pool_create: "
+ "returned value should be empty "
+ "because size of per-lcore local cache "
+ "is greater than size of the mempool.");
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Create pool of OP types RTE_BBDEV_OP_NONE, RTE_BBDEV_OP_TURBO_DEC and
+ * RTE_BBDEV_OP_TURBO_ENC and check that only ops of that type can be
+ * allocated
+ */
+static int
+test_bbdev_op_type(void)
+{
+ struct rte_mempool *mp_dec;
+
+ const unsigned int OPS_COUNT = 32;
+ struct rte_bbdev_dec_op *dec_ops_arr[OPS_COUNT];
+ struct rte_bbdev_enc_op *enc_ops_arr[OPS_COUNT];
+
+ const char *pool_dec = "Test_op_dec";
+
+ /* Valid pool configuration */
+ uint32_t num_elements = 256;
+ uint32_t cache_size = 128;
+
+ /* mempool type : RTE_BBDEV_OP_TURBO_DEC */
+ mp_dec = rte_bbdev_op_pool_create(pool_dec,
+ RTE_BBDEV_OP_TURBO_DEC, num_elements, cache_size, 0);
+ TEST_ASSERT(mp_dec != NULL, "Failed to create %s mempool", pool_dec);
+
+ TEST_ASSERT(rte_bbdev_dec_op_alloc_bulk(mp_dec, dec_ops_arr, 1) == 0,
+ "Failed test for rte_bbdev_op_alloc_bulk TURBO_DEC: "
+ "OPs type: RTE_BBDEV_OP_TURBO_DEC");
+
+ TEST_ASSERT(rte_bbdev_enc_op_alloc_bulk(mp_dec, enc_ops_arr, 1) != 0,
+ "Failed test for rte_bbdev_op_alloc_bulk TURBO_DEC: "
+ "OPs type: RTE_BBDEV_OP_TURBO_ENC");
+
+ rte_mempool_free(mp_dec);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_op_pool_size(void)
+{
+ struct rte_mempool *mp_none;
+
+ const unsigned int OPS_COUNT = 128;
+ struct rte_bbdev_enc_op *ops_enc_arr[OPS_COUNT];
+ struct rte_bbdev_enc_op *ops_ext_arr[OPS_COUNT];
+ struct rte_bbdev_enc_op *ops_ext2_arr[OPS_COUNT];
+
+ const char *pool_none = "Test_pool_size";
+
+ /* Valid pool configuration */
+ uint32_t num_elements = 256;
+ uint32_t cache_size = 0;
+
+ /* Create mempool type : RTE_BBDEV_OP_TURBO_ENC, size : 256 */
+ mp_none = rte_bbdev_op_pool_create(pool_none, RTE_BBDEV_OP_TURBO_ENC,
+ num_elements, cache_size, 0);
+ TEST_ASSERT(mp_none != NULL, "Failed to create %s mempool", pool_none);
+
+ /* Add 128 RTE_BBDEV_OP_TURBO_ENC ops */
+ rte_bbdev_enc_op_alloc_bulk(mp_none, ops_enc_arr, OPS_COUNT);
+
+ /* Add 128 RTE_BBDEV_OP_TURBO_ENC ops */
+ TEST_ASSERT(rte_bbdev_enc_op_alloc_bulk(mp_none, ops_ext_arr,
+ OPS_COUNT) == 0,
+ "Failed test for allocating bbdev ops: "
+ "Mempool size: 256, Free : 128, Attempted to add: 128");
+
+ /* Try adding 128 more RTE_BBDEV_OP_TURBO_ENC ops, this should fail */
+ TEST_ASSERT(rte_bbdev_enc_op_alloc_bulk(mp_none, ops_ext2_arr,
+ OPS_COUNT) != 0,
+ "Failed test for allocating bbdev ops: "
+ "Mempool size: 256, Free : 0, Attempted to add: 128");
+
+ /* Free-up 128 RTE_BBDEV_OP_TURBO_ENC ops */
+ rte_bbdev_enc_op_free_bulk(ops_enc_arr, OPS_COUNT);
+
+ /* Try adding 128 RTE_BBDEV_OP_TURBO_DEC ops, this should succeed */
+ /* Cache size > 0 causes reallocation of ops size > 127 fail */
+ TEST_ASSERT(rte_bbdev_enc_op_alloc_bulk(mp_none, ops_ext2_arr,
+ OPS_COUNT) == 0,
+ "Failed test for allocating ops after mempool freed: "
+ "Mempool size: 256, Free : 128, Attempted to add: 128");
+
+ rte_mempool_free(mp_none);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_count(void)
+{
+ uint8_t num_devs, num_valid_devs = 0;
+
+ for (num_devs = 0; num_devs < RTE_BBDEV_MAX_DEVS; num_devs++) {
+ if (rte_bbdev_is_valid(num_devs))
+ num_valid_devs++;
+ }
+
+ num_devs = rte_bbdev_count();
+ TEST_ASSERT(num_valid_devs == num_devs,
+ "Failed test for rte_bbdev_is_valid: "
+ "invalid num_devs %u ", num_devs);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_stats(void)
+{
+ uint8_t dev_id = null_dev_id;
+ uint16_t queue_id = 0;
+ struct rte_bbdev_dec_op *dec_ops[4096] = { 0 };
+ struct rte_bbdev_dec_op *dec_proc_ops[4096] = { 0 };
+ struct rte_bbdev_enc_op *enc_ops[4096] = { 0 };
+ struct rte_bbdev_enc_op *enc_proc_ops[4096] = { 0 };
+ uint16_t num_ops = 236;
+ struct rte_bbdev_stats stats;
+ struct bbdev_testsuite_params *ts_params = &testsuite_params;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_stop(dev_id, queue_id),
+ "Failed to stop queue %u on device %u ", queue_id,
+ dev_id);
+ TEST_ASSERT_SUCCESS(rte_bbdev_stop(dev_id),
+ "Failed to stop bbdev %u ", dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed to configure queue %u on device %u ",
+ queue_id, dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
+ "Failed to start bbdev %u ", dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_start(dev_id, queue_id),
+ "Failed to start queue %u on device %u ", queue_id,
+ dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_start(dev_id, queue_id),
+ "Failed to start queue %u on device %u ", queue_id,
+ dev_id);
+
+ /* Tests after enqueue operation */
+ rte_bbdev_enqueue_enc_ops(dev_id, queue_id, enc_ops, num_ops);
+ rte_bbdev_enqueue_dec_ops(dev_id, queue_id, dec_ops, num_ops);
+
+ TEST_ASSERT_FAIL(rte_bbdev_stats_get(RTE_BBDEV_MAX_DEVS, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ TEST_ASSERT_FAIL(rte_bbdev_stats_get(dev_id, NULL),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ TEST_ASSERT(stats.enqueued_count == 2 * num_ops,
+ "Failed test for rte_bbdev_enqueue_ops: "
+ "invalid enqueued_count %" PRIu64 " ",
+ stats.enqueued_count);
+
+ TEST_ASSERT(stats.dequeued_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid dequeued_count %" PRIu64 " ",
+ stats.dequeued_count);
+
+ /* Tests after dequeue operation */
+ rte_bbdev_dequeue_enc_ops(dev_id, queue_id, enc_proc_ops, num_ops);
+ rte_bbdev_dequeue_dec_ops(dev_id, queue_id, dec_proc_ops, num_ops);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ TEST_ASSERT(stats.dequeued_count == 2 * num_ops,
+ "Failed test for rte_bbdev_dequeue_ops: "
+ "invalid enqueued_count %" PRIu64 " ",
+ stats.dequeued_count);
+
+ TEST_ASSERT(stats.enqueue_err_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid enqueue_err_count %" PRIu64 " ",
+ stats.enqueue_err_count);
+
+ TEST_ASSERT(stats.dequeue_err_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid dequeue_err_count %" PRIu64 " ",
+ stats.dequeue_err_count);
+
+ /* Tests after reset operation */
+ TEST_ASSERT_FAIL(rte_bbdev_stats_reset(RTE_BBDEV_MAX_DEVS),
+ "Failed to reset statistic for device %u ", dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
+ "Failed to reset statistic for device %u ", dev_id);
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ TEST_ASSERT(stats.enqueued_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid enqueued_count %" PRIu64 " ",
+ stats.enqueued_count);
+
+ TEST_ASSERT(stats.dequeued_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid dequeued_count %" PRIu64 " ",
+ stats.dequeued_count);
+
+ TEST_ASSERT(stats.enqueue_err_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid enqueue_err_count %" PRIu64 " ",
+ stats.enqueue_err_count);
+
+ TEST_ASSERT(stats.dequeue_err_count == 0,
+ "Failed test for rte_bbdev_stats_reset: "
+ "invalid dequeue_err_count %" PRIu64 " ",
+ stats.dequeue_err_count);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_driver_init(void)
+{
+ struct rte_bbdev *dev1, *dev2;
+ const char *name = "dev_name";
+ char name_tmp[32];
+ int num_devs, num_devs_tmp;
+
+ dev1 = rte_bbdev_allocate(NULL);
+ TEST_ASSERT(dev1 == NULL,
+ "Failed initialize bbdev driver with NULL name");
+
+ dev1 = rte_bbdev_allocate(name);
+ TEST_ASSERT(dev1 != NULL, "Failed to initialize bbdev driver");
+
+ dev2 = rte_bbdev_allocate(name);
+ TEST_ASSERT(dev2 == NULL,
+ "Failed to initialize bbdev driver: "
+ "driver with the same name has been initialized before");
+
+ num_devs = rte_bbdev_count() - 1;
+ num_devs_tmp = num_devs;
+
+ /* Initialize the maximum amount of devices */
+ do {
+ sprintf(name_tmp, "%s%i", "name_", num_devs);
+ dev2 = rte_bbdev_allocate(name_tmp);
+ TEST_ASSERT(dev2 != NULL,
+ "Failed to initialize bbdev driver");
+ ++num_devs;
+ } while (num_devs < (RTE_BBDEV_MAX_DEVS - 1));
+
+ sprintf(name_tmp, "%s%i", "name_", num_devs);
+ dev2 = rte_bbdev_allocate(name_tmp);
+ TEST_ASSERT(dev2 == NULL, "Failed to initialize bbdev driver number %d "
+ "more drivers than RTE_BBDEV_MAX_DEVS: %d ", num_devs,
+ RTE_BBDEV_MAX_DEVS);
+
+ num_devs--;
+
+ while (num_devs >= num_devs_tmp) {
+ sprintf(name_tmp, "%s%i", "name_", num_devs);
+ dev2 = rte_bbdev_get_named_dev(name_tmp);
+ TEST_ASSERT_SUCCESS(rte_bbdev_release(dev2),
+ "Failed to uninitialize bbdev driver %s ",
+ name_tmp);
+ num_devs--;
+ }
+
+ TEST_ASSERT(dev1->data->dev_id < RTE_BBDEV_MAX_DEVS,
+ "Failed test rte_bbdev_allocate: "
+ "invalid dev_id %" PRIu8 ", max number of devices %d ",
+ dev1->data->dev_id, RTE_BBDEV_MAX_DEVS);
+
+ TEST_ASSERT(dev1->state == RTE_BBDEV_INITIALIZED,
+ "Failed test rte_bbdev_allocate: "
+ "invalid state %d (0 - RTE_BBDEV_UNUSED, 1 - RTE_BBDEV_INITIALIZED",
+ dev1->state);
+
+ TEST_ASSERT_FAIL(rte_bbdev_release(NULL),
+ "Failed to uninitialize bbdev driver with NULL bbdev");
+
+ sprintf(name_tmp, "%s", "invalid_name");
+ dev2 = rte_bbdev_get_named_dev(name_tmp);
+ TEST_ASSERT_FAIL(rte_bbdev_release(dev2),
+ "Failed to uninitialize bbdev driver with invalid name");
+
+ dev2 = rte_bbdev_get_named_dev(name);
+ TEST_ASSERT_SUCCESS(rte_bbdev_release(dev2),
+ "Failed to uninitialize bbdev driver: %s ", name);
+
+ return TEST_SUCCESS;
+}
+
+static void
+event_callback(uint16_t dev_id, enum rte_bbdev_event_type type, void *param,
+ void *ret_param)
+{
+ RTE_SET_USED(dev_id);
+ RTE_SET_USED(ret_param);
+
+ if (param == NULL)
+ return;
+
+ if (type == RTE_BBDEV_EVENT_UNKNOWN ||
+ type == RTE_BBDEV_EVENT_ERROR ||
+ type == RTE_BBDEV_EVENT_MAX)
+ *(int *)param = type;
+}
+
+static int
+test_bbdev_callback(void)
+{
+ struct rte_bbdev *dev1, *dev2;
+ const char *name = "dev_name1";
+ const char *name2 = "dev_name2";
+ int event_status;
+ uint8_t invalid_dev_id = RTE_BBDEV_MAX_DEVS;
+ enum rte_bbdev_event_type invalid_event_type = RTE_BBDEV_EVENT_MAX;
+ uint8_t dev_id;
+
+ dev1 = rte_bbdev_allocate(name);
+ TEST_ASSERT(dev1 != NULL, "Failed to initialize bbdev driver");
+
+ /*
+ * RTE_BBDEV_EVENT_UNKNOWN - unregistered
+ * RTE_BBDEV_EVENT_ERROR - unregistered
+ */
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "events were not registered ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_register(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_MAX, event_callback, NULL),
+ "Failed to callback register for RTE_BBDEV_EVENT_MAX ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_unregister(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_MAX, event_callback, NULL),
+ "Failed to unregister RTE_BBDEV_EVENT_MAX ");
+
+ /*
+ * RTE_BBDEV_EVENT_UNKNOWN - registered
+ * RTE_BBDEV_EVENT_ERROR - unregistered
+ */
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, &event_status),
+ "Failed to callback rgstr for RTE_BBDEV_EVENT_UNKNOWN");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process "
+ "for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "event RTE_BBDEV_EVENT_ERROR was not registered ");
+
+ /*
+ * RTE_BBDEV_EVENT_UNKNOWN - registered
+ * RTE_BBDEV_EVENT_ERROR - registered
+ */
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed to callback rgstr for RTE_BBDEV_EVENT_ERROR ");
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed to callback register for RTE_BBDEV_EVENT_ERROR"
+ "(re-registration) ");
+
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process "
+ "for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_ERROR,
+ "Failed test for rte_bbdev_pmd_callback_process "
+ "for RTE_BBDEV_EVENT_ERROR ");
+
+ /*
+ * RTE_BBDEV_EVENT_UNKNOWN - registered
+ * RTE_BBDEV_EVENT_ERROR - unregistered
+ */
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_unregister(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed to unregister RTE_BBDEV_EVENT_ERROR ");
+
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process "
+ "for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "event RTE_BBDEV_EVENT_ERROR was unregistered ");
+
+ /* rte_bbdev_callback_register with invalid inputs */
+ TEST_ASSERT_FAIL(rte_bbdev_callback_register(invalid_dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed test for rte_bbdev_callback_register "
+ "for invalid_dev_id ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_register(dev1->data->dev_id,
+ invalid_event_type, event_callback, &event_status),
+ "Failed to callback register for invalid event type ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_register(dev1->data->dev_id,
+ RTE_BBDEV_EVENT_ERROR, NULL, &event_status),
+ "Failed to callback register - no callback function ");
+
+ /* The impact of devices on each other */
+ dev2 = rte_bbdev_allocate(name2);
+ TEST_ASSERT(dev2 != NULL,
+ "Failed to initialize bbdev driver");
+
+ /*
+ * dev2:
+ * RTE_BBDEV_EVENT_UNKNOWN - unregistered
+ * RTE_BBDEV_EVENT_ERROR - unregistered
+ */
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "events were not registered ");
+
+ /*
+ * dev1: RTE_BBDEV_EVENT_ERROR - unregistered
+ * dev2: RTE_BBDEV_EVENT_ERROR - registered
+ */
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev2->data->dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed to callback rgstr for RTE_BBDEV_EVENT_ERROR");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process in dev1 "
+ "for RTE_BBDEV_EVENT_ERROR ");
+
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_ERROR,
+ "Failed test for rte_bbdev_pmd_callback_process in dev2 "
+ "for RTE_BBDEV_EVENT_ERROR ");
+
+ /*
+ * dev1: RTE_BBDEV_EVENT_UNKNOWN - registered
+ * dev2: RTE_BBDEV_EVENT_UNKNOWN - unregistered
+ */
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev2->data->dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, &event_status),
+ "Failed to callback register for RTE_BBDEV_EVENT_UNKNOWN "
+ "in dev 2 ");
+
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process in dev2"
+ " for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_unregister(dev2->data->dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, &event_status),
+ "Failed to unregister RTE_BBDEV_EVENT_UNKNOWN ");
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_unregister(dev2->data->dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, &event_status),
+ "Failed to unregister RTE_BBDEV_EVENT_UNKNOWN : "
+ "unregister function called once again ");
+
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process in dev2"
+ " for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ TEST_ASSERT(event_status == (int) RTE_BBDEV_EVENT_UNKNOWN,
+ "Failed test for rte_bbdev_pmd_callback_process in dev2 "
+ "for RTE_BBDEV_EVENT_UNKNOWN ");
+
+ /* rte_bbdev_pmd_callback_process with invalid inputs */
+ rte_bbdev_pmd_callback_process(NULL, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev1, invalid_event_type, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "for invalid event type ");
+
+ /* rte_dev_callback_unregister with invalid inputs */
+ TEST_ASSERT_FAIL(rte_bbdev_callback_unregister(invalid_dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, &event_status),
+ "Failed test for rte_dev_callback_unregister "
+ "for invalid_dev_id ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_unregister(dev1->data->dev_id,
+ invalid_event_type, event_callback, &event_status),
+ "Failed rte_dev_callback_unregister "
+ "for invalid event type ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_unregister(dev1->data->dev_id,
+ invalid_event_type, NULL, &event_status),
+ "Failed rte_dev_callback_unregister "
+ "when no callback function ");
+
+ dev_id = dev1->data->dev_id;
+
+ rte_bbdev_release(dev1);
+ rte_bbdev_release(dev2);
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_register(dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed test for rte_bbdev_callback_register: "
+ "function called after rte_bbdev_driver_uninit .");
+
+ TEST_ASSERT_FAIL(rte_bbdev_callback_unregister(dev_id,
+ RTE_BBDEV_EVENT_ERROR, event_callback, &event_status),
+ "Failed test for rte_dev_callback_unregister: "
+ "function called after rte_bbdev_driver_uninit. ");
+
+ event_status = -1;
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ rte_bbdev_pmd_callback_process(dev1, RTE_BBDEV_EVENT_ERROR, NULL);
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_ERROR, NULL);
+ TEST_ASSERT(event_status == -1,
+ "Failed test for rte_bbdev_pmd_callback_process: "
+ "callback function was called after rte_bbdev_driver_uninit");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_invalid_driver(void)
+{
+ struct rte_bbdev dev1, *dev2;
+ uint8_t dev_id = null_dev_id;
+ uint16_t queue_id = 0;
+ struct rte_bbdev_stats stats;
+ struct bbdev_testsuite_params *ts_params = &testsuite_params;
+ struct rte_bbdev_queue_info qinfo;
+ struct rte_bbdev_ops dev_ops_tmp;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stop(dev_id), "Failed to stop bbdev %u ",
+ dev_id);
+
+ dev1 = rte_bbdev_devices[dev_id];
+ dev2 = &rte_bbdev_devices[dev_id];
+
+ /* Tests for rte_bbdev_setup_queues */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id, 1, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "NULL dev_ops structure ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.info_get = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id, 1, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "NULL info_get ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.queue_release = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_FAIL(rte_bbdev_setup_queues(dev_id, 1, SOCKET_ID_ANY),
+ "Failed test for rte_bbdev_setup_queues: "
+ "NULL queue_release ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev2->data->socket_id = SOCKET_ID_ANY;
+ TEST_ASSERT_SUCCESS(rte_bbdev_setup_queues(dev_id, 1,
+ SOCKET_ID_ANY), "Failed to configure bbdev %u", dev_id);
+
+ /* Test for rte_bbdev_queue_configure */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed to configure queue %u on device %u "
+ "with NULL dev_ops structure ", queue_id, dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.queue_setup = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed to configure queue %u on device %u "
+ "with NULL queue_setup ", queue_id, dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.info_get = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed to configure queue %u on device %u "
+ "with NULL info_get ", queue_id, dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_configure(RTE_BBDEV_MAX_DEVS,
+ queue_id, &ts_params->qconf),
+ "Failed to configure queue %u on device %u ",
+ queue_id, dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_configure(dev_id, queue_id,
+ &ts_params->qconf),
+ "Failed to configure queue %u on device %u ",
+ queue_id, dev_id);
+
+ /* Test for rte_bbdev_queue_info_get */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_info_get(dev_id, queue_id, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "NULL dev_ops structure ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_info_get(RTE_BBDEV_MAX_DEVS,
+ queue_id, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid dev_id ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_info_get(dev_id,
+ RTE_MAX_QUEUES_PER_PORT, &qinfo),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid queue_id ");
+
+ TEST_ASSERT_FAIL(rte_bbdev_queue_info_get(dev_id, queue_id, NULL),
+ "Failed test for rte_bbdev_info_get: "
+ "invalid dev_info ");
+
+ /* Test for rte_bbdev_start */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_start(dev_id),
+ "Failed to start bbdev %u "
+ "with NULL dev_ops structure ", dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
+ "Failed to start bbdev %u ", dev_id);
+
+ /* Test for rte_bbdev_queue_start */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_start(dev_id, queue_id),
+ "Failed to start queue %u on device %u: "
+ "NULL dev_ops structure", queue_id, dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_start(dev_id, queue_id),
+ "Failed to start queue %u on device %u ", queue_id,
+ dev_id);
+
+ /* Tests for rte_bbdev_stats_get */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.stats_reset = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get: "
+ "NULL stats_get ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_get(dev_id, &stats),
+ "Failed test for rte_bbdev_stats_get on device %u ",
+ dev_id);
+
+ /*
+ * Tests for:
+ * rte_bbdev_callback_register,
+ * rte_bbdev_pmd_callback_process,
+ * rte_dev_callback_unregister
+ */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_register(dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, NULL),
+ "Failed to callback rgstr for RTE_BBDEV_EVENT_UNKNOWN");
+ rte_bbdev_pmd_callback_process(dev2, RTE_BBDEV_EVENT_UNKNOWN, NULL);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_callback_unregister(dev_id,
+ RTE_BBDEV_EVENT_UNKNOWN, event_callback, NULL),
+ "Failed to unregister RTE_BBDEV_EVENT_ERROR ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ /* Tests for rte_bbdev_stats_reset */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_stats_reset(dev_id),
+ "Failed to reset statistic for device %u ", dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ dev_ops_tmp = *dev2->dev_ops;
+ dev_ops_tmp.stats_reset = NULL;
+ dev2->dev_ops = &dev_ops_tmp;
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
+ "Failed test for rte_bbdev_stats_reset: "
+ "NULL stats_reset ");
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
+ "Failed to reset statistic for device %u ", dev_id);
+
+ /* Tests for rte_bbdev_queue_stop */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_queue_stop(dev_id, queue_id),
+ "Failed to stop queue %u on device %u: "
+ "NULL dev_ops structure", queue_id, dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_stop(dev_id, queue_id),
+ "Failed to stop queue %u on device %u ", queue_id,
+ dev_id);
+
+ /* Tests for rte_bbdev_stop */
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_stop(dev_id),
+ "Failed to stop bbdev %u with NULL dev_ops structure ",
+ dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_stop(dev_id),
+ "Failed to stop bbdev %u ", dev_id);
+
+ /* Tests for rte_bbdev_close */
+ TEST_ASSERT_FAIL(rte_bbdev_close(RTE_BBDEV_MAX_DEVS),
+ "Failed to close bbdev with invalid dev_id");
+
+ dev2->dev_ops = NULL;
+ TEST_ASSERT_FAIL(rte_bbdev_close(dev_id),
+ "Failed to close bbdev %u with NULL dev_ops structure ",
+ dev_id);
+ dev2->dev_ops = dev1.dev_ops;
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_close(dev_id),
+ "Failed to close bbdev %u ", dev_id);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bbdev_get_named_dev(void)
+{
+ struct rte_bbdev *dev, *dev_tmp;
+ const char *name = "name";
+
+ dev = rte_bbdev_allocate(name);
+ TEST_ASSERT(dev != NULL, "Failed to initialize bbdev driver");
+
+ dev_tmp = rte_bbdev_get_named_dev(NULL);
+ TEST_ASSERT(dev_tmp == NULL, "Failed test for rte_bbdev_get_named_dev: "
+ "function called with NULL parameter");
+
+ dev_tmp = rte_bbdev_get_named_dev(name);
+
+ TEST_ASSERT(dev == dev_tmp, "Failed test for rte_bbdev_get_named_dev: "
+ "wrong device was returned ");
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_release(dev),
+ "Failed to uninitialize bbdev driver %s ", name);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite bbdev_null_testsuite = {
+ .suite_name = "BBDEV NULL Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+
+ TEST_CASE(test_bbdev_configure_invalid_dev_id),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_configure_invalid_num_queues),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_configure_stop_device),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_configure_stop_queue),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_configure_invalid_queue_configure),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_op_pool),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_op_type),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_op_pool_size),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_stats),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_driver_init),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_callback),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_invalid_driver),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_bbdev_get_named_dev),
+
+ TEST_CASE(test_bbdev_count),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+REGISTER_TEST_COMMAND(unittest, bbdev_null_testsuite);
diff --git a/src/spdk/dpdk/app/test-bbdev/test_bbdev_perf.c b/src/spdk/dpdk/app/test-bbdev/test_bbdev_perf.c
new file mode 100644
index 000000000..45c0d62ac
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_bbdev_perf.c
@@ -0,0 +1,4933 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+#include <rte_dev.h>
+#include <rte_launch.h>
+#include <rte_bbdev.h>
+#include <rte_cycles.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_hexdump.h>
+#include <rte_interrupts.h>
+
+#include "main.h"
+#include "test_bbdev_vector.h"
+
+#define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
+
+#define MAX_QUEUES RTE_MAX_LCORE
+#define TEST_REPETITIONS 1000
+
+#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC
+#include <fpga_lte_fec.h>
+#define FPGA_LTE_PF_DRIVER_NAME ("intel_fpga_lte_fec_pf")
+#define FPGA_LTE_VF_DRIVER_NAME ("intel_fpga_lte_fec_vf")
+#define VF_UL_4G_QUEUE_VALUE 4
+#define VF_DL_4G_QUEUE_VALUE 4
+#define UL_4G_BANDWIDTH 3
+#define DL_4G_BANDWIDTH 3
+#define UL_4G_LOAD_BALANCE 128
+#define DL_4G_LOAD_BALANCE 128
+#define FLR_4G_TIMEOUT 610
+#endif
+
+#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC
+#include <rte_pmd_fpga_5gnr_fec.h>
+#define FPGA_5GNR_PF_DRIVER_NAME ("intel_fpga_5gnr_fec_pf")
+#define FPGA_5GNR_VF_DRIVER_NAME ("intel_fpga_5gnr_fec_vf")
+#define VF_UL_5G_QUEUE_VALUE 4
+#define VF_DL_5G_QUEUE_VALUE 4
+#define UL_5G_BANDWIDTH 3
+#define DL_5G_BANDWIDTH 3
+#define UL_5G_LOAD_BALANCE 128
+#define DL_5G_LOAD_BALANCE 128
+#define FLR_5G_TIMEOUT 610
+#endif
+
+#define OPS_CACHE_SIZE 256U
+#define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
+
+#define SYNC_WAIT 0
+#define SYNC_START 1
+#define INVALID_OPAQUE -1
+
+#define INVALID_QUEUE_ID -1
+/* Increment for next code block in external HARQ memory */
+#define HARQ_INCR 32768
+/* Headroom for filler LLRs insertion in HARQ buffer */
+#define FILLER_HEADROOM 1024
+/* Constants from K0 computation from 3GPP 38.212 Table 5.4.2.1-2 */
+#define N_ZC_1 66 /* N = 66 Zc for BG 1 */
+#define N_ZC_2 50 /* N = 50 Zc for BG 2 */
+#define K0_1_1 17 /* K0 fraction numerator for rv 1 and BG 1 */
+#define K0_1_2 13 /* K0 fraction numerator for rv 1 and BG 2 */
+#define K0_2_1 33 /* K0 fraction numerator for rv 2 and BG 1 */
+#define K0_2_2 25 /* K0 fraction numerator for rv 2 and BG 2 */
+#define K0_3_1 56 /* K0 fraction numerator for rv 3 and BG 1 */
+#define K0_3_2 43 /* K0 fraction numerator for rv 3 and BG 2 */
+
+static struct test_bbdev_vector test_vector;
+
+/* Switch between PMD and Interrupt for throughput TC */
+static bool intr_enabled;
+
+/* LLR arithmetic representation for numerical conversion */
+static int ldpc_llr_decimals;
+static int ldpc_llr_size;
+/* Keep track of the LDPC decoder device capability flag */
+static uint32_t ldpc_cap_flags;
+
+/* Represents tested active devices */
+static struct active_device {
+ const char *driver_name;
+ uint8_t dev_id;
+ uint16_t supported_ops;
+ uint16_t queue_ids[MAX_QUEUES];
+ uint16_t nb_queues;
+ struct rte_mempool *ops_mempool;
+ struct rte_mempool *in_mbuf_pool;
+ struct rte_mempool *hard_out_mbuf_pool;
+ struct rte_mempool *soft_out_mbuf_pool;
+ struct rte_mempool *harq_in_mbuf_pool;
+ struct rte_mempool *harq_out_mbuf_pool;
+} active_devs[RTE_BBDEV_MAX_DEVS];
+
+static uint8_t nb_active_devs;
+
+/* Data buffers used by BBDEV ops */
+struct test_buffers {
+ struct rte_bbdev_op_data *inputs;
+ struct rte_bbdev_op_data *hard_outputs;
+ struct rte_bbdev_op_data *soft_outputs;
+ struct rte_bbdev_op_data *harq_inputs;
+ struct rte_bbdev_op_data *harq_outputs;
+};
+
+/* Operation parameters specific for given test case */
+struct test_op_params {
+ struct rte_mempool *mp;
+ struct rte_bbdev_dec_op *ref_dec_op;
+ struct rte_bbdev_enc_op *ref_enc_op;
+ uint16_t burst_sz;
+ uint16_t num_to_process;
+ uint16_t num_lcores;
+ int vector_mask;
+ rte_atomic16_t sync;
+ struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
+};
+
+/* Contains per lcore params */
+struct thread_params {
+ uint8_t dev_id;
+ uint16_t queue_id;
+ uint32_t lcore_id;
+ uint64_t start_time;
+ double ops_per_sec;
+ double mbps;
+ uint8_t iter_count;
+ double iter_average;
+ double bler;
+ rte_atomic16_t nb_dequeued;
+ rte_atomic16_t processing_status;
+ rte_atomic16_t burst_sz;
+ struct test_op_params *op_params;
+ struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
+ struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
+};
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+/* Stores time statistics */
+struct test_time_stats {
+ /* Stores software enqueue total working time */
+ uint64_t enq_sw_total_time;
+ /* Stores minimum value of software enqueue working time */
+ uint64_t enq_sw_min_time;
+ /* Stores maximum value of software enqueue working time */
+ uint64_t enq_sw_max_time;
+ /* Stores turbo enqueue total working time */
+ uint64_t enq_acc_total_time;
+ /* Stores minimum value of accelerator enqueue working time */
+ uint64_t enq_acc_min_time;
+ /* Stores maximum value of accelerator enqueue working time */
+ uint64_t enq_acc_max_time;
+ /* Stores dequeue total working time */
+ uint64_t deq_total_time;
+ /* Stores minimum value of dequeue working time */
+ uint64_t deq_min_time;
+ /* Stores maximum value of dequeue working time */
+ uint64_t deq_max_time;
+};
+#endif
+
+typedef int (test_case_function)(struct active_device *ad,
+ struct test_op_params *op_params);
+
+static inline void
+mbuf_reset(struct rte_mbuf *m)
+{
+ m->pkt_len = 0;
+
+ do {
+ m->data_len = 0;
+ m = m->next;
+ } while (m != NULL);
+}
+
+/* Read flag value 0/1 from bitmap */
+static inline bool
+check_bit(uint32_t bitmap, uint32_t bitmask)
+{
+ return bitmap & bitmask;
+}
+
+static inline void
+set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
+{
+ ad->supported_ops |= (1 << op_type);
+}
+
+static inline bool
+is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
+{
+ return ad->supported_ops & (1 << op_type);
+}
+
+static inline bool
+flags_match(uint32_t flags_req, uint32_t flags_present)
+{
+ return (flags_req & flags_present) == flags_req;
+}
+
+static void
+clear_soft_out_cap(uint32_t *op_flags)
+{
+ *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
+ *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
+ *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
+}
+
+static int
+check_dev_cap(const struct rte_bbdev_info *dev_info)
+{
+ unsigned int i;
+ unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs,
+ nb_harq_inputs, nb_harq_outputs;
+ const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
+
+ nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
+ nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
+ nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
+ nb_harq_inputs = test_vector.entries[DATA_HARQ_INPUT].nb_segments;
+ nb_harq_outputs = test_vector.entries[DATA_HARQ_OUTPUT].nb_segments;
+
+ for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
+ if (op_cap->type != test_vector.op_type)
+ continue;
+
+ if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
+ const struct rte_bbdev_op_cap_turbo_dec *cap =
+ &op_cap->cap.turbo_dec;
+ /* Ignore lack of soft output capability, just skip
+ * checking if soft output is valid.
+ */
+ if ((test_vector.turbo_dec.op_flags &
+ RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
+ !(cap->capability_flags &
+ RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
+ printf(
+ "INFO: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
+ dev_info->dev_name);
+ clear_soft_out_cap(
+ &test_vector.turbo_dec.op_flags);
+ }
+
+ if (!flags_match(test_vector.turbo_dec.op_flags,
+ cap->capability_flags))
+ return TEST_FAILED;
+ if (nb_inputs > cap->num_buffers_src) {
+ printf("Too many inputs defined: %u, max: %u\n",
+ nb_inputs, cap->num_buffers_src);
+ return TEST_FAILED;
+ }
+ if (nb_soft_outputs > cap->num_buffers_soft_out &&
+ (test_vector.turbo_dec.op_flags &
+ RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
+ printf(
+ "Too many soft outputs defined: %u, max: %u\n",
+ nb_soft_outputs,
+ cap->num_buffers_soft_out);
+ return TEST_FAILED;
+ }
+ if (nb_hard_outputs > cap->num_buffers_hard_out) {
+ printf(
+ "Too many hard outputs defined: %u, max: %u\n",
+ nb_hard_outputs,
+ cap->num_buffers_hard_out);
+ return TEST_FAILED;
+ }
+ if (intr_enabled && !(cap->capability_flags &
+ RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
+ printf(
+ "Dequeue interrupts are not supported!\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+ } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
+ const struct rte_bbdev_op_cap_turbo_enc *cap =
+ &op_cap->cap.turbo_enc;
+
+ if (!flags_match(test_vector.turbo_enc.op_flags,
+ cap->capability_flags))
+ return TEST_FAILED;
+ if (nb_inputs > cap->num_buffers_src) {
+ printf("Too many inputs defined: %u, max: %u\n",
+ nb_inputs, cap->num_buffers_src);
+ return TEST_FAILED;
+ }
+ if (nb_hard_outputs > cap->num_buffers_dst) {
+ printf(
+ "Too many hard outputs defined: %u, max: %u\n",
+ nb_hard_outputs, cap->num_buffers_dst);
+ return TEST_FAILED;
+ }
+ if (intr_enabled && !(cap->capability_flags &
+ RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
+ printf(
+ "Dequeue interrupts are not supported!\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+ } else if (op_cap->type == RTE_BBDEV_OP_LDPC_ENC) {
+ const struct rte_bbdev_op_cap_ldpc_enc *cap =
+ &op_cap->cap.ldpc_enc;
+
+ if (!flags_match(test_vector.ldpc_enc.op_flags,
+ cap->capability_flags)){
+ printf("Flag Mismatch\n");
+ return TEST_FAILED;
+ }
+ if (nb_inputs > cap->num_buffers_src) {
+ printf("Too many inputs defined: %u, max: %u\n",
+ nb_inputs, cap->num_buffers_src);
+ return TEST_FAILED;
+ }
+ if (nb_hard_outputs > cap->num_buffers_dst) {
+ printf(
+ "Too many hard outputs defined: %u, max: %u\n",
+ nb_hard_outputs, cap->num_buffers_dst);
+ return TEST_FAILED;
+ }
+ if (intr_enabled && !(cap->capability_flags &
+ RTE_BBDEV_LDPC_ENC_INTERRUPTS)) {
+ printf(
+ "Dequeue interrupts are not supported!\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+ } else if (op_cap->type == RTE_BBDEV_OP_LDPC_DEC) {
+ const struct rte_bbdev_op_cap_ldpc_dec *cap =
+ &op_cap->cap.ldpc_dec;
+
+ if (!flags_match(test_vector.ldpc_dec.op_flags,
+ cap->capability_flags)){
+ printf("Flag Mismatch\n");
+ return TEST_FAILED;
+ }
+ if (nb_inputs > cap->num_buffers_src) {
+ printf("Too many inputs defined: %u, max: %u\n",
+ nb_inputs, cap->num_buffers_src);
+ return TEST_FAILED;
+ }
+ if (nb_hard_outputs > cap->num_buffers_hard_out) {
+ printf(
+ "Too many hard outputs defined: %u, max: %u\n",
+ nb_hard_outputs,
+ cap->num_buffers_hard_out);
+ return TEST_FAILED;
+ }
+ if (nb_harq_inputs > cap->num_buffers_hard_out) {
+ printf(
+ "Too many HARQ inputs defined: %u, max: %u\n",
+ nb_hard_outputs,
+ cap->num_buffers_hard_out);
+ return TEST_FAILED;
+ }
+ if (nb_harq_outputs > cap->num_buffers_hard_out) {
+ printf(
+ "Too many HARQ outputs defined: %u, max: %u\n",
+ nb_hard_outputs,
+ cap->num_buffers_hard_out);
+ return TEST_FAILED;
+ }
+ if (intr_enabled && !(cap->capability_flags &
+ RTE_BBDEV_LDPC_DEC_INTERRUPTS)) {
+ printf(
+ "Dequeue interrupts are not supported!\n");
+ return TEST_FAILED;
+ }
+ if (intr_enabled && (test_vector.ldpc_dec.op_flags &
+ (RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
+ RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
+ ))) {
+ printf("Skip loop-back with interrupt\n");
+ return TEST_FAILED;
+ }
+ return TEST_SUCCESS;
+ }
+ }
+
+ if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
+ return TEST_SUCCESS; /* Special case for NULL device */
+
+ return TEST_FAILED;
+}
+
+/* calculates optimal mempool size not smaller than the val */
+static unsigned int
+optimal_mempool_size(unsigned int val)
+{
+ return rte_align32pow2(val + 1) - 1;
+}
+
+/* allocates mbuf mempool for inputs and outputs */
+static struct rte_mempool *
+create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
+ int socket_id, unsigned int mbuf_pool_size,
+ const char *op_type_str)
+{
+ unsigned int i;
+ uint32_t max_seg_sz = 0;
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+
+ /* find max input segment size */
+ for (i = 0; i < entries->nb_segments; ++i)
+ if (entries->segments[i].length > max_seg_sz)
+ max_seg_sz = entries->segments[i].length;
+
+ snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
+ dev_id);
+ return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
+ RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM
+ + FILLER_HEADROOM,
+ (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
+}
+
+static int
+create_mempools(struct active_device *ad, int socket_id,
+ enum rte_bbdev_op_type org_op_type, uint16_t num_ops)
+{
+ struct rte_mempool *mp;
+ unsigned int ops_pool_size, mbuf_pool_size = 0;
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+ const char *op_type_str;
+ enum rte_bbdev_op_type op_type = org_op_type;
+
+ struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
+ struct op_data_entries *hard_out =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+ struct op_data_entries *soft_out =
+ &test_vector.entries[DATA_SOFT_OUTPUT];
+ struct op_data_entries *harq_in =
+ &test_vector.entries[DATA_HARQ_INPUT];
+ struct op_data_entries *harq_out =
+ &test_vector.entries[DATA_HARQ_OUTPUT];
+
+ /* allocate ops mempool */
+ ops_pool_size = optimal_mempool_size(RTE_MAX(
+ /* Ops used plus 1 reference op */
+ RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
+ /* Minimal cache size plus 1 reference op */
+ (unsigned int)(1.5 * rte_lcore_count() *
+ OPS_CACHE_SIZE + 1)),
+ OPS_POOL_SIZE_MIN));
+
+ if (org_op_type == RTE_BBDEV_OP_NONE)
+ op_type = RTE_BBDEV_OP_TURBO_ENC;
+
+ op_type_str = rte_bbdev_op_type_str(op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
+
+ snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
+ ad->dev_id);
+ mp = rte_bbdev_op_pool_create(pool_name, op_type,
+ ops_pool_size, OPS_CACHE_SIZE, socket_id);
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
+ ops_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->ops_mempool = mp;
+
+ /* Do not create inputs and outputs mbufs for BaseBand Null Device */
+ if (org_op_type == RTE_BBDEV_OP_NONE)
+ return TEST_SUCCESS;
+
+ /* Inputs */
+ if (in->nb_segments > 0) {
+ mbuf_pool_size = optimal_mempool_size(ops_pool_size *
+ in->nb_segments);
+ mp = create_mbuf_pool(in, ad->dev_id, socket_id,
+ mbuf_pool_size, "in");
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
+ mbuf_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->in_mbuf_pool = mp;
+ }
+
+ /* Hard outputs */
+ if (hard_out->nb_segments > 0) {
+ mbuf_pool_size = optimal_mempool_size(ops_pool_size *
+ hard_out->nb_segments);
+ mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id,
+ mbuf_pool_size,
+ "hard_out");
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
+ mbuf_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->hard_out_mbuf_pool = mp;
+ }
+
+ /* Soft outputs */
+ if (soft_out->nb_segments > 0) {
+ mbuf_pool_size = optimal_mempool_size(ops_pool_size *
+ soft_out->nb_segments);
+ mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id,
+ mbuf_pool_size,
+ "soft_out");
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
+ mbuf_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->soft_out_mbuf_pool = mp;
+ }
+
+ /* HARQ inputs */
+ if (harq_in->nb_segments > 0) {
+ mbuf_pool_size = optimal_mempool_size(ops_pool_size *
+ harq_in->nb_segments);
+ mp = create_mbuf_pool(harq_in, ad->dev_id, socket_id,
+ mbuf_pool_size,
+ "harq_in");
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %uB harq input pktmbuf pool for dev %u on socket %u.",
+ mbuf_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->harq_in_mbuf_pool = mp;
+ }
+
+ /* HARQ outputs */
+ if (harq_out->nb_segments > 0) {
+ mbuf_pool_size = optimal_mempool_size(ops_pool_size *
+ harq_out->nb_segments);
+ mp = create_mbuf_pool(harq_out, ad->dev_id, socket_id,
+ mbuf_pool_size,
+ "harq_out");
+ TEST_ASSERT_NOT_NULL(mp,
+ "ERROR Failed to create %uB harq output pktmbuf pool for dev %u on socket %u.",
+ mbuf_pool_size,
+ ad->dev_id,
+ socket_id);
+ ad->harq_out_mbuf_pool = mp;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
+ struct test_bbdev_vector *vector)
+{
+ int ret;
+ unsigned int queue_id;
+ struct rte_bbdev_queue_conf qconf;
+ struct active_device *ad = &active_devs[nb_active_devs];
+ unsigned int nb_queues;
+ enum rte_bbdev_op_type op_type = vector->op_type;
+
+/* Configure fpga lte fec with PF & VF values
+ * if '-i' flag is set and using fpga device
+ */
+#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC
+ if ((get_init_device() == true) &&
+ (!strcmp(info->drv.driver_name, FPGA_LTE_PF_DRIVER_NAME))) {
+ struct fpga_lte_fec_conf conf;
+ unsigned int i;
+
+ printf("Configure FPGA LTE FEC Driver %s with default values\n",
+ info->drv.driver_name);
+
+ /* clear default configuration before initialization */
+ memset(&conf, 0, sizeof(struct fpga_lte_fec_conf));
+
+ /* Set PF mode :
+ * true if PF is used for data plane
+ * false for VFs
+ */
+ conf.pf_mode_en = true;
+
+ for (i = 0; i < FPGA_LTE_FEC_NUM_VFS; ++i) {
+ /* Number of UL queues per VF (fpga supports 8 VFs) */
+ conf.vf_ul_queues_number[i] = VF_UL_4G_QUEUE_VALUE;
+ /* Number of DL queues per VF (fpga supports 8 VFs) */
+ conf.vf_dl_queues_number[i] = VF_DL_4G_QUEUE_VALUE;
+ }
+
+ /* UL bandwidth. Needed for schedule algorithm */
+ conf.ul_bandwidth = UL_4G_BANDWIDTH;
+ /* DL bandwidth */
+ conf.dl_bandwidth = DL_4G_BANDWIDTH;
+
+ /* UL & DL load Balance Factor to 64 */
+ conf.ul_load_balance = UL_4G_LOAD_BALANCE;
+ conf.dl_load_balance = DL_4G_LOAD_BALANCE;
+
+ /**< FLR timeout value */
+ conf.flr_time_out = FLR_4G_TIMEOUT;
+
+ /* setup FPGA PF with configuration information */
+ ret = fpga_lte_fec_configure(info->dev_name, &conf);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to configure 4G FPGA PF for bbdev %s",
+ info->dev_name);
+ }
+#endif
+#ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_5GNR_FEC
+ if ((get_init_device() == true) &&
+ (!strcmp(info->drv.driver_name, FPGA_5GNR_PF_DRIVER_NAME))) {
+ struct fpga_5gnr_fec_conf conf;
+ unsigned int i;
+
+ printf("Configure FPGA 5GNR FEC Driver %s with default values\n",
+ info->drv.driver_name);
+
+ /* clear default configuration before initialization */
+ memset(&conf, 0, sizeof(struct fpga_5gnr_fec_conf));
+
+ /* Set PF mode :
+ * true if PF is used for data plane
+ * false for VFs
+ */
+ conf.pf_mode_en = true;
+
+ for (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; ++i) {
+ /* Number of UL queues per VF (fpga supports 8 VFs) */
+ conf.vf_ul_queues_number[i] = VF_UL_5G_QUEUE_VALUE;
+ /* Number of DL queues per VF (fpga supports 8 VFs) */
+ conf.vf_dl_queues_number[i] = VF_DL_5G_QUEUE_VALUE;
+ }
+
+ /* UL bandwidth. Needed for schedule algorithm */
+ conf.ul_bandwidth = UL_5G_BANDWIDTH;
+ /* DL bandwidth */
+ conf.dl_bandwidth = DL_5G_BANDWIDTH;
+
+ /* UL & DL load Balance Factor to 64 */
+ conf.ul_load_balance = UL_5G_LOAD_BALANCE;
+ conf.dl_load_balance = DL_5G_LOAD_BALANCE;
+
+ /**< FLR timeout value */
+ conf.flr_time_out = FLR_5G_TIMEOUT;
+
+ /* setup FPGA PF with configuration information */
+ ret = fpga_5gnr_fec_configure(info->dev_name, &conf);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to configure 5G FPGA PF for bbdev %s",
+ info->dev_name);
+ }
+#endif
+ nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
+ nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES);
+
+ /* setup device */
+ ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
+ if (ret < 0) {
+ printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
+ dev_id, nb_queues, info->socket_id, ret);
+ return TEST_FAILED;
+ }
+
+ /* configure interrupts if needed */
+ if (intr_enabled) {
+ ret = rte_bbdev_intr_enable(dev_id);
+ if (ret < 0) {
+ printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
+ ret);
+ return TEST_FAILED;
+ }
+ }
+
+ /* setup device queues */
+ qconf.socket = info->socket_id;
+ qconf.queue_size = info->drv.default_queue_conf.queue_size;
+ qconf.priority = 0;
+ qconf.deferred_start = 0;
+ qconf.op_type = op_type;
+
+ for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
+ ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
+ if (ret != 0) {
+ printf(
+ "Allocated all queues (id=%u) at prio%u on dev%u\n",
+ queue_id, qconf.priority, dev_id);
+ qconf.priority++;
+ ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
+ &qconf);
+ }
+ if (ret != 0) {
+ printf("All queues on dev %u allocated: %u\n",
+ dev_id, queue_id);
+ break;
+ }
+ ad->queue_ids[queue_id] = queue_id;
+ }
+ TEST_ASSERT(queue_id != 0,
+ "ERROR Failed to configure any queues on dev %u",
+ dev_id);
+ ad->nb_queues = queue_id;
+
+ set_avail_op(ad, op_type);
+
+ return TEST_SUCCESS;
+}
+
+static int
+add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
+ struct test_bbdev_vector *vector)
+{
+ int ret;
+
+ active_devs[nb_active_devs].driver_name = info->drv.driver_name;
+ active_devs[nb_active_devs].dev_id = dev_id;
+
+ ret = add_bbdev_dev(dev_id, info, vector);
+ if (ret == TEST_SUCCESS)
+ ++nb_active_devs;
+ return ret;
+}
+
+static uint8_t
+populate_active_devices(void)
+{
+ int ret;
+ uint8_t dev_id;
+ uint8_t nb_devs_added = 0;
+ struct rte_bbdev_info info;
+
+ RTE_BBDEV_FOREACH(dev_id) {
+ rte_bbdev_info_get(dev_id, &info);
+
+ if (check_dev_cap(&info)) {
+ printf(
+ "Device %d (%s) does not support specified capabilities\n",
+ dev_id, info.dev_name);
+ continue;
+ }
+
+ ret = add_active_device(dev_id, &info, &test_vector);
+ if (ret != 0) {
+ printf("Adding active bbdev %s skipped\n",
+ info.dev_name);
+ continue;
+ }
+ nb_devs_added++;
+ }
+
+ return nb_devs_added;
+}
+
+static int
+read_test_vector(void)
+{
+ int ret;
+
+ memset(&test_vector, 0, sizeof(test_vector));
+ printf("Test vector file = %s\n", get_vector_filename());
+ ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
+ TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
+ get_vector_filename());
+
+ return TEST_SUCCESS;
+}
+
+static int
+testsuite_setup(void)
+{
+ TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
+
+ if (populate_active_devices() == 0) {
+ printf("No suitable devices found!\n");
+ return TEST_SKIPPED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+interrupt_testsuite_setup(void)
+{
+ TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
+
+ /* Enable interrupts */
+ intr_enabled = true;
+
+ /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
+ if (populate_active_devices() == 0 ||
+ test_vector.op_type == RTE_BBDEV_OP_NONE) {
+ intr_enabled = false;
+ printf("No suitable devices found!\n");
+ return TEST_SKIPPED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ uint8_t dev_id;
+
+ /* Unconfigure devices */
+ RTE_BBDEV_FOREACH(dev_id)
+ rte_bbdev_close(dev_id);
+
+ /* Clear active devices structs. */
+ memset(active_devs, 0, sizeof(active_devs));
+ nb_active_devs = 0;
+
+ /* Disable interrupts */
+ intr_enabled = false;
+}
+
+static int
+ut_setup(void)
+{
+ uint8_t i, dev_id;
+
+ for (i = 0; i < nb_active_devs; i++) {
+ dev_id = active_devs[i].dev_id;
+ /* reset bbdev stats */
+ TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
+ "Failed to reset stats of bbdev %u", dev_id);
+ /* start the device */
+ TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
+ "Failed to start bbdev %u", dev_id);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+ut_teardown(void)
+{
+ uint8_t i, dev_id;
+ struct rte_bbdev_stats stats;
+
+ for (i = 0; i < nb_active_devs; i++) {
+ dev_id = active_devs[i].dev_id;
+ /* read stats and print */
+ rte_bbdev_stats_get(dev_id, &stats);
+ /* Stop the device */
+ rte_bbdev_stop(dev_id);
+ }
+}
+
+static int
+init_op_data_objs(struct rte_bbdev_op_data *bufs,
+ struct op_data_entries *ref_entries,
+ struct rte_mempool *mbuf_pool, const uint16_t n,
+ enum op_data_type op_type, uint16_t min_alignment)
+{
+ int ret;
+ unsigned int i, j;
+ bool large_input = false;
+
+ for (i = 0; i < n; ++i) {
+ char *data;
+ struct op_data_buf *seg = &ref_entries->segments[0];
+ struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
+ TEST_ASSERT_NOT_NULL(m_head,
+ "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
+ op_type, n * ref_entries->nb_segments,
+ mbuf_pool->size);
+
+ if (seg->length > RTE_BBDEV_LDPC_E_MAX_MBUF) {
+ /*
+ * Special case when DPDK mbuf cannot handle
+ * the required input size
+ */
+ printf("Warning: Larger input size than DPDK mbuf %d\n",
+ seg->length);
+ large_input = true;
+ }
+ bufs[i].data = m_head;
+ bufs[i].offset = 0;
+ bufs[i].length = 0;
+
+ if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) {
+ if ((op_type == DATA_INPUT) && large_input) {
+ /* Allocate a fake overused mbuf */
+ data = rte_malloc(NULL, seg->length, 0);
+ memcpy(data, seg->addr, seg->length);
+ m_head->buf_addr = data;
+ m_head->buf_iova = rte_malloc_virt2iova(data);
+ m_head->data_off = 0;
+ m_head->data_len = seg->length;
+ } else {
+ data = rte_pktmbuf_append(m_head, seg->length);
+ TEST_ASSERT_NOT_NULL(data,
+ "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
+ seg->length, op_type);
+
+ TEST_ASSERT(data == RTE_PTR_ALIGN(
+ data, min_alignment),
+ "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
+ data, min_alignment);
+ rte_memcpy(data, seg->addr, seg->length);
+ }
+
+ bufs[i].length += seg->length;
+
+ for (j = 1; j < ref_entries->nb_segments; ++j) {
+ struct rte_mbuf *m_tail =
+ rte_pktmbuf_alloc(mbuf_pool);
+ TEST_ASSERT_NOT_NULL(m_tail,
+ "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
+ op_type,
+ n * ref_entries->nb_segments,
+ mbuf_pool->size);
+ seg += 1;
+
+ data = rte_pktmbuf_append(m_tail, seg->length);
+ TEST_ASSERT_NOT_NULL(data,
+ "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
+ seg->length, op_type);
+
+ TEST_ASSERT(data == RTE_PTR_ALIGN(data,
+ min_alignment),
+ "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
+ data, min_alignment);
+ rte_memcpy(data, seg->addr, seg->length);
+ bufs[i].length += seg->length;
+
+ ret = rte_pktmbuf_chain(m_head, m_tail);
+ TEST_ASSERT_SUCCESS(ret,
+ "Couldn't chain mbufs from %d data type mbuf pool",
+ op_type);
+ }
+ } else {
+
+ /* allocate chained-mbuf for output buffer */
+ for (j = 1; j < ref_entries->nb_segments; ++j) {
+ struct rte_mbuf *m_tail =
+ rte_pktmbuf_alloc(mbuf_pool);
+ TEST_ASSERT_NOT_NULL(m_tail,
+ "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
+ op_type,
+ n * ref_entries->nb_segments,
+ mbuf_pool->size);
+
+ ret = rte_pktmbuf_chain(m_head, m_tail);
+ TEST_ASSERT_SUCCESS(ret,
+ "Couldn't chain mbufs from %d data type mbuf pool",
+ op_type);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
+ const int socket)
+{
+ int i;
+
+ *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
+ if (*buffers == NULL) {
+ printf("WARNING: Failed to allocate op_data on socket %d\n",
+ socket);
+ /* try to allocate memory on other detected sockets */
+ for (i = 0; i < socket; i++) {
+ *buffers = rte_zmalloc_socket(NULL, len, 0, i);
+ if (*buffers != NULL)
+ break;
+ }
+ }
+
+ return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
+}
+
+static void
+limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
+ const uint16_t n, const int8_t max_llr_modulus)
+{
+ uint16_t i, byte_idx;
+
+ for (i = 0; i < n; ++i) {
+ struct rte_mbuf *m = input_ops[i].data;
+ while (m != NULL) {
+ int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
+ input_ops[i].offset);
+ for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
+ ++byte_idx)
+ llr[byte_idx] = round((double)max_llr_modulus *
+ llr[byte_idx] / INT8_MAX);
+
+ m = m->next;
+ }
+ }
+}
+
+/*
+ * We may have to insert filler bits
+ * when they are required by the HARQ assumption
+ */
+static void
+ldpc_add_filler(struct rte_bbdev_op_data *input_ops,
+ const uint16_t n, struct test_op_params *op_params)
+{
+ struct rte_bbdev_op_ldpc_dec dec = op_params->ref_dec_op->ldpc_dec;
+
+ if (input_ops == NULL)
+ return;
+ /* No need to add filler if not required by device */
+ if (!(ldpc_cap_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS))
+ return;
+ /* No need to add filler for loopback operation */
+ if (dec.op_flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
+ return;
+
+ uint16_t i, j, parity_offset;
+ for (i = 0; i < n; ++i) {
+ struct rte_mbuf *m = input_ops[i].data;
+ int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
+ input_ops[i].offset);
+ parity_offset = (dec.basegraph == 1 ? 20 : 8)
+ * dec.z_c - dec.n_filler;
+ uint16_t new_hin_size = input_ops[i].length + dec.n_filler;
+ m->data_len = new_hin_size;
+ input_ops[i].length = new_hin_size;
+ for (j = new_hin_size - 1; j >= parity_offset + dec.n_filler;
+ j--)
+ llr[j] = llr[j - dec.n_filler];
+ uint16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
+ for (j = 0; j < dec.n_filler; j++)
+ llr[parity_offset + j] = llr_max_pre_scaling;
+ }
+}
+
+static void
+ldpc_input_llr_scaling(struct rte_bbdev_op_data *input_ops,
+ const uint16_t n, const int8_t llr_size,
+ const int8_t llr_decimals)
+{
+ if (input_ops == NULL)
+ return;
+
+ uint16_t i, byte_idx;
+
+ int16_t llr_max, llr_min, llr_tmp;
+ llr_max = (1 << (llr_size - 1)) - 1;
+ llr_min = -llr_max;
+ for (i = 0; i < n; ++i) {
+ struct rte_mbuf *m = input_ops[i].data;
+ while (m != NULL) {
+ int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
+ input_ops[i].offset);
+ for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
+ ++byte_idx) {
+
+ llr_tmp = llr[byte_idx];
+ if (llr_decimals == 4)
+ llr_tmp *= 8;
+ else if (llr_decimals == 2)
+ llr_tmp *= 2;
+ else if (llr_decimals == 0)
+ llr_tmp /= 2;
+ llr_tmp = RTE_MIN(llr_max,
+ RTE_MAX(llr_min, llr_tmp));
+ llr[byte_idx] = (int8_t) llr_tmp;
+ }
+
+ m = m->next;
+ }
+ }
+}
+
+
+
+static int
+fill_queue_buffers(struct test_op_params *op_params,
+ struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
+ struct rte_mempool *soft_out_mp,
+ struct rte_mempool *harq_in_mp, struct rte_mempool *harq_out_mp,
+ uint16_t queue_id,
+ const struct rte_bbdev_op_cap *capabilities,
+ uint16_t min_alignment, const int socket_id)
+{
+ int ret;
+ enum op_data_type type;
+ const uint16_t n = op_params->num_to_process;
+
+ struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
+ in_mp,
+ soft_out_mp,
+ hard_out_mp,
+ harq_in_mp,
+ harq_out_mp,
+ };
+
+ struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
+ &op_params->q_bufs[socket_id][queue_id].inputs,
+ &op_params->q_bufs[socket_id][queue_id].soft_outputs,
+ &op_params->q_bufs[socket_id][queue_id].hard_outputs,
+ &op_params->q_bufs[socket_id][queue_id].harq_inputs,
+ &op_params->q_bufs[socket_id][queue_id].harq_outputs,
+ };
+
+ for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
+ struct op_data_entries *ref_entries =
+ &test_vector.entries[type];
+ if (ref_entries->nb_segments == 0)
+ continue;
+
+ ret = allocate_buffers_on_socket(queue_ops[type],
+ n * sizeof(struct rte_bbdev_op_data),
+ socket_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Couldn't allocate memory for rte_bbdev_op_data structs");
+
+ ret = init_op_data_objs(*queue_ops[type], ref_entries,
+ mbuf_pools[type], n, type, min_alignment);
+ TEST_ASSERT_SUCCESS(ret,
+ "Couldn't init rte_bbdev_op_data structs");
+ }
+
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
+ limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
+ capabilities->cap.turbo_dec.max_llr_modulus);
+
+ if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
+ bool loopback = op_params->ref_dec_op->ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
+ bool llr_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_LLR_COMPRESSION;
+ bool harq_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ ldpc_llr_decimals = capabilities->cap.ldpc_dec.llr_decimals;
+ ldpc_llr_size = capabilities->cap.ldpc_dec.llr_size;
+ ldpc_cap_flags = capabilities->cap.ldpc_dec.capability_flags;
+ if (!loopback && !llr_comp)
+ ldpc_input_llr_scaling(*queue_ops[DATA_INPUT], n,
+ ldpc_llr_size, ldpc_llr_decimals);
+ if (!loopback && !harq_comp)
+ ldpc_input_llr_scaling(*queue_ops[DATA_HARQ_INPUT], n,
+ ldpc_llr_size, ldpc_llr_decimals);
+ if (!loopback)
+ ldpc_add_filler(*queue_ops[DATA_HARQ_INPUT], n,
+ op_params);
+ }
+
+ return 0;
+}
+
+static void
+free_buffers(struct active_device *ad, struct test_op_params *op_params)
+{
+ unsigned int i, j;
+
+ rte_mempool_free(ad->ops_mempool);
+ rte_mempool_free(ad->in_mbuf_pool);
+ rte_mempool_free(ad->hard_out_mbuf_pool);
+ rte_mempool_free(ad->soft_out_mbuf_pool);
+ rte_mempool_free(ad->harq_in_mbuf_pool);
+ rte_mempool_free(ad->harq_out_mbuf_pool);
+
+ for (i = 0; i < rte_lcore_count(); ++i) {
+ for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
+ rte_free(op_params->q_bufs[j][i].inputs);
+ rte_free(op_params->q_bufs[j][i].hard_outputs);
+ rte_free(op_params->q_bufs[j][i].soft_outputs);
+ rte_free(op_params->q_bufs[j][i].harq_inputs);
+ rte_free(op_params->q_bufs[j][i].harq_outputs);
+ }
+ }
+}
+
+static void
+copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
+ unsigned int start_idx,
+ struct rte_bbdev_op_data *inputs,
+ struct rte_bbdev_op_data *hard_outputs,
+ struct rte_bbdev_op_data *soft_outputs,
+ struct rte_bbdev_dec_op *ref_op)
+{
+ unsigned int i;
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
+
+ for (i = 0; i < n; ++i) {
+ if (turbo_dec->code_block_mode == 0) {
+ ops[i]->turbo_dec.tb_params.ea =
+ turbo_dec->tb_params.ea;
+ ops[i]->turbo_dec.tb_params.eb =
+ turbo_dec->tb_params.eb;
+ ops[i]->turbo_dec.tb_params.k_pos =
+ turbo_dec->tb_params.k_pos;
+ ops[i]->turbo_dec.tb_params.k_neg =
+ turbo_dec->tb_params.k_neg;
+ ops[i]->turbo_dec.tb_params.c =
+ turbo_dec->tb_params.c;
+ ops[i]->turbo_dec.tb_params.c_neg =
+ turbo_dec->tb_params.c_neg;
+ ops[i]->turbo_dec.tb_params.cab =
+ turbo_dec->tb_params.cab;
+ ops[i]->turbo_dec.tb_params.r =
+ turbo_dec->tb_params.r;
+ } else {
+ ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
+ ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
+ }
+
+ ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
+ ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
+ ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
+ ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
+ ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
+ ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
+ ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
+
+ ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
+ ops[i]->turbo_dec.input = inputs[start_idx + i];
+ if (soft_outputs != NULL)
+ ops[i]->turbo_dec.soft_output =
+ soft_outputs[start_idx + i];
+ }
+}
+
+static void
+copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
+ unsigned int start_idx,
+ struct rte_bbdev_op_data *inputs,
+ struct rte_bbdev_op_data *outputs,
+ struct rte_bbdev_enc_op *ref_op)
+{
+ unsigned int i;
+ struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
+ for (i = 0; i < n; ++i) {
+ if (turbo_enc->code_block_mode == 0) {
+ ops[i]->turbo_enc.tb_params.ea =
+ turbo_enc->tb_params.ea;
+ ops[i]->turbo_enc.tb_params.eb =
+ turbo_enc->tb_params.eb;
+ ops[i]->turbo_enc.tb_params.k_pos =
+ turbo_enc->tb_params.k_pos;
+ ops[i]->turbo_enc.tb_params.k_neg =
+ turbo_enc->tb_params.k_neg;
+ ops[i]->turbo_enc.tb_params.c =
+ turbo_enc->tb_params.c;
+ ops[i]->turbo_enc.tb_params.c_neg =
+ turbo_enc->tb_params.c_neg;
+ ops[i]->turbo_enc.tb_params.cab =
+ turbo_enc->tb_params.cab;
+ ops[i]->turbo_enc.tb_params.ncb_pos =
+ turbo_enc->tb_params.ncb_pos;
+ ops[i]->turbo_enc.tb_params.ncb_neg =
+ turbo_enc->tb_params.ncb_neg;
+ ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
+ } else {
+ ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
+ ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
+ ops[i]->turbo_enc.cb_params.ncb =
+ turbo_enc->cb_params.ncb;
+ }
+ ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
+ ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
+ ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
+
+ ops[i]->turbo_enc.output = outputs[start_idx + i];
+ ops[i]->turbo_enc.input = inputs[start_idx + i];
+ }
+}
+
+
+/* Returns a random number drawn from a normal distribution
+ * with mean of 0 and variance of 1
+ * Marsaglia algorithm
+ */
+static double
+randn(int n)
+{
+ double S, Z, U1, U2, u, v, fac;
+
+ do {
+ U1 = (double)rand() / RAND_MAX;
+ U2 = (double)rand() / RAND_MAX;
+ u = 2. * U1 - 1.;
+ v = 2. * U2 - 1.;
+ S = u * u + v * v;
+ } while (S >= 1 || S == 0);
+ fac = sqrt(-2. * log(S) / S);
+ Z = (n % 2) ? u * fac : v * fac;
+ return Z;
+}
+
+static inline double
+maxstar(double A, double B)
+{
+ if (fabs(A - B) > 5)
+ return RTE_MAX(A, B);
+ else
+ return RTE_MAX(A, B) + log1p(exp(-fabs(A - B)));
+}
+
+/*
+ * Generate Qm LLRS for Qm==8
+ * Modulation, AWGN and LLR estimation from max log development
+ */
+static void
+gen_qm8_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
+{
+ int qm = 8;
+ int qam = 256;
+ int m, k;
+ double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
+ /* 5.1.4 of TS38.211 */
+ const double symbols_I[256] = {
+ 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 5,
+ 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 11,
+ 11, 9, 9, 11, 11, 9, 9, 13, 13, 15, 15, 13, 13,
+ 15, 15, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13, 15,
+ 15, 13, 13, 15, 15, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3,
+ 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1,
+ 1, 3, 3, 1, 1, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13,
+ 15, 15, 13, 13, 15, 15, 11, 11, 9, 9, 11, 11, 9, 9,
+ 13, 13, 15, 15, 13, 13, 15, 15, -5, -5, -7, -7, -5,
+ -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -5, -5,
+ -7, -7, -5, -5, -7, -7, -3, -3, -1, -1, -3, -3,
+ -1, -1, -11, -11, -9, -9, -11, -11, -9, -9, -13,
+ -13, -15, -15, -13, -13, -15, -15, -11, -11, -9,
+ -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
+ -13, -15, -15, -5, -5, -7, -7, -5, -5, -7, -7, -3,
+ -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7, -5, -5,
+ -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -11, -11,
+ -9, -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
+ -13, -15, -15, -11, -11, -9, -9, -11, -11, -9, -9,
+ -13, -13, -15, -15, -13, -13, -15, -15};
+ const double symbols_Q[256] = {
+ 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
+ 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15, 13,
+ 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
+ 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13,
+ 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1, -5,
+ -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13,
+ -15, -13, -15, -11, -9, -11, -9, -13, -15, -13,
+ -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7, -5,
+ -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
+ -13, -15, -11, -9, -11, -9, -13, -15, -13, -15, 5,
+ 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
+ 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15,
+ 13, 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1,
+ 3, 1, 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9,
+ 13, 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1,
+ -5, -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9,
+ -13, -15, -13, -15, -11, -9, -11, -9, -13, -15,
+ -13, -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7,
+ -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
+ -13, -15, -11, -9, -11, -9, -13, -15, -13, -15};
+ /* Average constellation point energy */
+ N0 *= 170.0;
+ for (k = 0; k < qm; k++)
+ b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
+ /* 5.1.4 of TS38.211 */
+ I = (1 - 2 * b[0]) * (8 - (1 - 2 * b[2]) *
+ (4 - (1 - 2 * b[4]) * (2 - (1 - 2 * b[6]))));
+ Q = (1 - 2 * b[1]) * (8 - (1 - 2 * b[3]) *
+ (4 - (1 - 2 * b[5]) * (2 - (1 - 2 * b[7]))));
+ /* AWGN channel */
+ I += sqrt(N0 / 2) * randn(0);
+ Q += sqrt(N0 / 2) * randn(1);
+ /*
+ * Calculate the log of the probability that each of
+ * the constellation points was transmitted
+ */
+ for (m = 0; m < qam; m++)
+ log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
+ + pow(Q - symbols_Q[m], 2.0)) / N0;
+ /* Calculate an LLR for each of the k_64QAM bits in the set */
+ for (k = 0; k < qm; k++) {
+ p0 = -999999;
+ p1 = -999999;
+ /* For each constellation point */
+ for (m = 0; m < qam; m++) {
+ if ((m >> (qm - k - 1)) & 1)
+ p1 = maxstar(p1, log_syml_prob[m]);
+ else
+ p0 = maxstar(p0, log_syml_prob[m]);
+ }
+ /* Calculate the LLR */
+ llr_ = p0 - p1;
+ llr_ *= (1 << ldpc_llr_decimals);
+ llr_ = round(llr_);
+ if (llr_ > llr_max)
+ llr_ = llr_max;
+ if (llr_ < -llr_max)
+ llr_ = -llr_max;
+ llrs[qm * i + k] = (int8_t) llr_;
+ }
+}
+
+
+/*
+ * Generate Qm LLRS for Qm==6
+ * Modulation, AWGN and LLR estimation from max log development
+ */
+static void
+gen_qm6_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
+{
+ int qm = 6;
+ int qam = 64;
+ int m, k;
+ double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
+ /* 5.1.4 of TS38.211 */
+ const double symbols_I[64] = {
+ 3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
+ 3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
+ -3, -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7,
+ -5, -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1,
+ -5, -5, -7, -7, -5, -5, -7, -7};
+ const double symbols_Q[64] = {
+ 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7,
+ -3, -1, -3, -1, -5, -7, -5, -7, -3, -1, -3, -1,
+ -5, -7, -5, -7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
+ 5, 7, 5, 7, -3, -1, -3, -1, -5, -7, -5, -7,
+ -3, -1, -3, -1, -5, -7, -5, -7};
+ /* Average constellation point energy */
+ N0 *= 42.0;
+ for (k = 0; k < qm; k++)
+ b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
+ /* 5.1.4 of TS38.211 */
+ I = (1 - 2 * b[0])*(4 - (1 - 2 * b[2]) * (2 - (1 - 2 * b[4])));
+ Q = (1 - 2 * b[1])*(4 - (1 - 2 * b[3]) * (2 - (1 - 2 * b[5])));
+ /* AWGN channel */
+ I += sqrt(N0 / 2) * randn(0);
+ Q += sqrt(N0 / 2) * randn(1);
+ /*
+ * Calculate the log of the probability that each of
+ * the constellation points was transmitted
+ */
+ for (m = 0; m < qam; m++)
+ log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
+ + pow(Q - symbols_Q[m], 2.0)) / N0;
+ /* Calculate an LLR for each of the k_64QAM bits in the set */
+ for (k = 0; k < qm; k++) {
+ p0 = -999999;
+ p1 = -999999;
+ /* For each constellation point */
+ for (m = 0; m < qam; m++) {
+ if ((m >> (qm - k - 1)) & 1)
+ p1 = maxstar(p1, log_syml_prob[m]);
+ else
+ p0 = maxstar(p0, log_syml_prob[m]);
+ }
+ /* Calculate the LLR */
+ llr_ = p0 - p1;
+ llr_ *= (1 << ldpc_llr_decimals);
+ llr_ = round(llr_);
+ if (llr_ > llr_max)
+ llr_ = llr_max;
+ if (llr_ < -llr_max)
+ llr_ = -llr_max;
+ llrs[qm * i + k] = (int8_t) llr_;
+ }
+}
+
+/*
+ * Generate Qm LLRS for Qm==4
+ * Modulation, AWGN and LLR estimation from max log development
+ */
+static void
+gen_qm4_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
+{
+ int qm = 4;
+ int qam = 16;
+ int m, k;
+ double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
+ /* 5.1.4 of TS38.211 */
+ const double symbols_I[16] = {1, 1, 3, 3, 1, 1, 3, 3,
+ -1, -1, -3, -3, -1, -1, -3, -3};
+ const double symbols_Q[16] = {1, 3, 1, 3, -1, -3, -1, -3,
+ 1, 3, 1, 3, -1, -3, -1, -3};
+ /* Average constellation point energy */
+ N0 *= 10.0;
+ for (k = 0; k < qm; k++)
+ b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
+ /* 5.1.4 of TS38.211 */
+ I = (1 - 2 * b[0]) * (2 - (1 - 2 * b[2]));
+ Q = (1 - 2 * b[1]) * (2 - (1 - 2 * b[3]));
+ /* AWGN channel */
+ I += sqrt(N0 / 2) * randn(0);
+ Q += sqrt(N0 / 2) * randn(1);
+ /*
+ * Calculate the log of the probability that each of
+ * the constellation points was transmitted
+ */
+ for (m = 0; m < qam; m++)
+ log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
+ + pow(Q - symbols_Q[m], 2.0)) / N0;
+ /* Calculate an LLR for each of the k_64QAM bits in the set */
+ for (k = 0; k < qm; k++) {
+ p0 = -999999;
+ p1 = -999999;
+ /* For each constellation point */
+ for (m = 0; m < qam; m++) {
+ if ((m >> (qm - k - 1)) & 1)
+ p1 = maxstar(p1, log_syml_prob[m]);
+ else
+ p0 = maxstar(p0, log_syml_prob[m]);
+ }
+ /* Calculate the LLR */
+ llr_ = p0 - p1;
+ llr_ *= (1 << ldpc_llr_decimals);
+ llr_ = round(llr_);
+ if (llr_ > llr_max)
+ llr_ = llr_max;
+ if (llr_ < -llr_max)
+ llr_ = -llr_max;
+ llrs[qm * i + k] = (int8_t) llr_;
+ }
+}
+
+static void
+gen_qm2_llr(int8_t *llrs, uint32_t j, double N0, double llr_max)
+{
+ double b, b1, n;
+ double coeff = 2.0 * sqrt(N0);
+
+ /* Ignore in vectors rare quasi null LLRs not to be saturated */
+ if (llrs[j] < 8 && llrs[j] > -8)
+ return;
+
+ /* Note don't change sign here */
+ n = randn(j % 2);
+ b1 = ((llrs[j] > 0 ? 2.0 : -2.0)
+ + coeff * n) / N0;
+ b = b1 * (1 << ldpc_llr_decimals);
+ b = round(b);
+ if (b > llr_max)
+ b = llr_max;
+ if (b < -llr_max)
+ b = -llr_max;
+ llrs[j] = (int8_t) b;
+}
+
+/* Generate LLR for a given SNR */
+static void
+generate_llr_input(uint16_t n, struct rte_bbdev_op_data *inputs,
+ struct rte_bbdev_dec_op *ref_op)
+{
+ struct rte_mbuf *m;
+ uint16_t qm;
+ uint32_t i, j, e, range;
+ double N0, llr_max;
+
+ e = ref_op->ldpc_dec.cb_params.e;
+ qm = ref_op->ldpc_dec.q_m;
+ llr_max = (1 << (ldpc_llr_size - 1)) - 1;
+ range = e / qm;
+ N0 = 1.0 / pow(10.0, get_snr() / 10.0);
+
+ for (i = 0; i < n; ++i) {
+ m = inputs[i].data;
+ int8_t *llrs = rte_pktmbuf_mtod_offset(m, int8_t *, 0);
+ if (qm == 8) {
+ for (j = 0; j < range; ++j)
+ gen_qm8_llr(llrs, j, N0, llr_max);
+ } else if (qm == 6) {
+ for (j = 0; j < range; ++j)
+ gen_qm6_llr(llrs, j, N0, llr_max);
+ } else if (qm == 4) {
+ for (j = 0; j < range; ++j)
+ gen_qm4_llr(llrs, j, N0, llr_max);
+ } else {
+ for (j = 0; j < e; ++j)
+ gen_qm2_llr(llrs, j, N0, llr_max);
+ }
+ }
+}
+
+static void
+copy_reference_ldpc_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
+ unsigned int start_idx,
+ struct rte_bbdev_op_data *inputs,
+ struct rte_bbdev_op_data *hard_outputs,
+ struct rte_bbdev_op_data *soft_outputs,
+ struct rte_bbdev_op_data *harq_inputs,
+ struct rte_bbdev_op_data *harq_outputs,
+ struct rte_bbdev_dec_op *ref_op)
+{
+ unsigned int i;
+ struct rte_bbdev_op_ldpc_dec *ldpc_dec = &ref_op->ldpc_dec;
+
+ for (i = 0; i < n; ++i) {
+ if (ldpc_dec->code_block_mode == 0) {
+ ops[i]->ldpc_dec.tb_params.ea =
+ ldpc_dec->tb_params.ea;
+ ops[i]->ldpc_dec.tb_params.eb =
+ ldpc_dec->tb_params.eb;
+ ops[i]->ldpc_dec.tb_params.c =
+ ldpc_dec->tb_params.c;
+ ops[i]->ldpc_dec.tb_params.cab =
+ ldpc_dec->tb_params.cab;
+ ops[i]->ldpc_dec.tb_params.r =
+ ldpc_dec->tb_params.r;
+ } else {
+ ops[i]->ldpc_dec.cb_params.e = ldpc_dec->cb_params.e;
+ }
+
+ ops[i]->ldpc_dec.basegraph = ldpc_dec->basegraph;
+ ops[i]->ldpc_dec.z_c = ldpc_dec->z_c;
+ ops[i]->ldpc_dec.q_m = ldpc_dec->q_m;
+ ops[i]->ldpc_dec.n_filler = ldpc_dec->n_filler;
+ ops[i]->ldpc_dec.n_cb = ldpc_dec->n_cb;
+ ops[i]->ldpc_dec.iter_max = ldpc_dec->iter_max;
+ ops[i]->ldpc_dec.rv_index = ldpc_dec->rv_index;
+ ops[i]->ldpc_dec.op_flags = ldpc_dec->op_flags;
+ ops[i]->ldpc_dec.code_block_mode = ldpc_dec->code_block_mode;
+
+ if (hard_outputs != NULL)
+ ops[i]->ldpc_dec.hard_output =
+ hard_outputs[start_idx + i];
+ if (inputs != NULL)
+ ops[i]->ldpc_dec.input =
+ inputs[start_idx + i];
+ if (soft_outputs != NULL)
+ ops[i]->ldpc_dec.soft_output =
+ soft_outputs[start_idx + i];
+ if (harq_inputs != NULL)
+ ops[i]->ldpc_dec.harq_combined_input =
+ harq_inputs[start_idx + i];
+ if (harq_outputs != NULL)
+ ops[i]->ldpc_dec.harq_combined_output =
+ harq_outputs[start_idx + i];
+ }
+}
+
+
+static void
+copy_reference_ldpc_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
+ unsigned int start_idx,
+ struct rte_bbdev_op_data *inputs,
+ struct rte_bbdev_op_data *outputs,
+ struct rte_bbdev_enc_op *ref_op)
+{
+ unsigned int i;
+ struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc;
+ for (i = 0; i < n; ++i) {
+ if (ldpc_enc->code_block_mode == 0) {
+ ops[i]->ldpc_enc.tb_params.ea = ldpc_enc->tb_params.ea;
+ ops[i]->ldpc_enc.tb_params.eb = ldpc_enc->tb_params.eb;
+ ops[i]->ldpc_enc.tb_params.cab =
+ ldpc_enc->tb_params.cab;
+ ops[i]->ldpc_enc.tb_params.c = ldpc_enc->tb_params.c;
+ ops[i]->ldpc_enc.tb_params.r = ldpc_enc->tb_params.r;
+ } else {
+ ops[i]->ldpc_enc.cb_params.e = ldpc_enc->cb_params.e;
+ }
+ ops[i]->ldpc_enc.basegraph = ldpc_enc->basegraph;
+ ops[i]->ldpc_enc.z_c = ldpc_enc->z_c;
+ ops[i]->ldpc_enc.q_m = ldpc_enc->q_m;
+ ops[i]->ldpc_enc.n_filler = ldpc_enc->n_filler;
+ ops[i]->ldpc_enc.n_cb = ldpc_enc->n_cb;
+ ops[i]->ldpc_enc.rv_index = ldpc_enc->rv_index;
+ ops[i]->ldpc_enc.op_flags = ldpc_enc->op_flags;
+ ops[i]->ldpc_enc.code_block_mode = ldpc_enc->code_block_mode;
+ ops[i]->ldpc_enc.output = outputs[start_idx + i];
+ ops[i]->ldpc_enc.input = inputs[start_idx + i];
+ }
+}
+
+static int
+check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
+ unsigned int order_idx, const int expected_status)
+{
+ int status = op->status;
+ /* ignore parity mismatch false alarms for long iterations */
+ if (get_iter_max() >= 10) {
+ if (!(expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
+ (status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
+ printf("WARNING: Ignore Syndrome Check mismatch\n");
+ status -= (1 << RTE_BBDEV_SYNDROME_ERROR);
+ }
+ if ((expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
+ !(status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
+ printf("WARNING: Ignore Syndrome Check mismatch\n");
+ status += (1 << RTE_BBDEV_SYNDROME_ERROR);
+ }
+ }
+
+ TEST_ASSERT(status == expected_status,
+ "op_status (%d) != expected_status (%d)",
+ op->status, expected_status);
+
+ TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
+ "Ordering error, expected %p, got %p",
+ (void *)(uintptr_t)order_idx, op->opaque_data);
+
+ return TEST_SUCCESS;
+}
+
+static int
+check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
+ unsigned int order_idx, const int expected_status)
+{
+ TEST_ASSERT(op->status == expected_status,
+ "op_status (%d) != expected_status (%d)",
+ op->status, expected_status);
+
+ if (op->opaque_data != (void *)(uintptr_t)INVALID_OPAQUE)
+ TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
+ "Ordering error, expected %p, got %p",
+ (void *)(uintptr_t)order_idx, op->opaque_data);
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+validate_op_chain(struct rte_bbdev_op_data *op,
+ struct op_data_entries *orig_op)
+{
+ uint8_t i;
+ struct rte_mbuf *m = op->data;
+ uint8_t nb_dst_segments = orig_op->nb_segments;
+ uint32_t total_data_size = 0;
+
+ TEST_ASSERT(nb_dst_segments == m->nb_segs,
+ "Number of segments differ in original (%u) and filled (%u) op",
+ nb_dst_segments, m->nb_segs);
+
+ /* Validate each mbuf segment length */
+ for (i = 0; i < nb_dst_segments; ++i) {
+ /* Apply offset to the first mbuf segment */
+ uint16_t offset = (i == 0) ? op->offset : 0;
+ uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
+ total_data_size += orig_op->segments[i].length;
+
+ TEST_ASSERT(orig_op->segments[i].length == data_len,
+ "Length of segment differ in original (%u) and filled (%u) op",
+ orig_op->segments[i].length, data_len);
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
+ rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
+ data_len,
+ "Output buffers (CB=%u) are not equal", i);
+ m = m->next;
+ }
+
+ /* Validate total mbuf pkt length */
+ uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
+ TEST_ASSERT(total_data_size == pkt_len,
+ "Length of data differ in original (%u) and filled (%u) op",
+ total_data_size, pkt_len);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Compute K0 for a given configuration for HARQ output length computation
+ * As per definition in 3GPP 38.212 Table 5.4.2.1-2
+ */
+static inline uint16_t
+get_k0(uint16_t n_cb, uint16_t z_c, uint8_t bg, uint8_t rv_index)
+{
+ if (rv_index == 0)
+ return 0;
+ uint16_t n = (bg == 1 ? N_ZC_1 : N_ZC_2) * z_c;
+ if (n_cb == n) {
+ if (rv_index == 1)
+ return (bg == 1 ? K0_1_1 : K0_1_2) * z_c;
+ else if (rv_index == 2)
+ return (bg == 1 ? K0_2_1 : K0_2_2) * z_c;
+ else
+ return (bg == 1 ? K0_3_1 : K0_3_2) * z_c;
+ }
+ /* LBRM case - includes a division by N */
+ if (rv_index == 1)
+ return (((bg == 1 ? K0_1_1 : K0_1_2) * n_cb)
+ / n) * z_c;
+ else if (rv_index == 2)
+ return (((bg == 1 ? K0_2_1 : K0_2_2) * n_cb)
+ / n) * z_c;
+ else
+ return (((bg == 1 ? K0_3_1 : K0_3_2) * n_cb)
+ / n) * z_c;
+}
+
+/* HARQ output length including the Filler bits */
+static inline uint16_t
+compute_harq_len(struct rte_bbdev_op_ldpc_dec *ops_ld)
+{
+ uint16_t k0 = 0;
+ uint8_t max_rv = (ops_ld->rv_index == 1) ? 3 : ops_ld->rv_index;
+ k0 = get_k0(ops_ld->n_cb, ops_ld->z_c, ops_ld->basegraph, max_rv);
+ /* Compute RM out size and number of rows */
+ uint16_t parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
+ * ops_ld->z_c - ops_ld->n_filler;
+ uint16_t deRmOutSize = RTE_MIN(
+ k0 + ops_ld->cb_params.e +
+ ((k0 > parity_offset) ?
+ 0 : ops_ld->n_filler),
+ ops_ld->n_cb);
+ uint16_t numRows = ((deRmOutSize + ops_ld->z_c - 1)
+ / ops_ld->z_c);
+ uint16_t harq_output_len = numRows * ops_ld->z_c;
+ return harq_output_len;
+}
+
+static inline int
+validate_op_harq_chain(struct rte_bbdev_op_data *op,
+ struct op_data_entries *orig_op,
+ struct rte_bbdev_op_ldpc_dec *ops_ld)
+{
+ uint8_t i;
+ uint32_t j, jj, k;
+ struct rte_mbuf *m = op->data;
+ uint8_t nb_dst_segments = orig_op->nb_segments;
+ uint32_t total_data_size = 0;
+ int8_t *harq_orig, *harq_out, abs_harq_origin;
+ uint32_t byte_error = 0, cum_error = 0, error;
+ int16_t llr_max = (1 << (ldpc_llr_size - ldpc_llr_decimals)) - 1;
+ int16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
+ uint16_t parity_offset;
+
+ TEST_ASSERT(nb_dst_segments == m->nb_segs,
+ "Number of segments differ in original (%u) and filled (%u) op",
+ nb_dst_segments, m->nb_segs);
+
+ /* Validate each mbuf segment length */
+ for (i = 0; i < nb_dst_segments; ++i) {
+ /* Apply offset to the first mbuf segment */
+ uint16_t offset = (i == 0) ? op->offset : 0;
+ uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
+ total_data_size += orig_op->segments[i].length;
+
+ TEST_ASSERT(orig_op->segments[i].length <
+ (uint32_t)(data_len + 64),
+ "Length of segment differ in original (%u) and filled (%u) op",
+ orig_op->segments[i].length, data_len);
+ harq_orig = (int8_t *) orig_op->segments[i].addr;
+ harq_out = rte_pktmbuf_mtod_offset(m, int8_t *, offset);
+
+ if (!(ldpc_cap_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS
+ ) || (ops_ld->op_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
+ data_len -= ops_ld->z_c;
+ parity_offset = data_len;
+ } else {
+ /* Compute RM out size and number of rows */
+ parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
+ * ops_ld->z_c - ops_ld->n_filler;
+ uint16_t deRmOutSize = compute_harq_len(ops_ld) -
+ ops_ld->n_filler;
+ if (data_len > deRmOutSize)
+ data_len = deRmOutSize;
+ if (data_len > orig_op->segments[i].length)
+ data_len = orig_op->segments[i].length;
+ }
+ /*
+ * HARQ output can have minor differences
+ * due to integer representation and related scaling
+ */
+ for (j = 0, jj = 0; j < data_len; j++, jj++) {
+ if (j == parity_offset) {
+ /* Special Handling of the filler bits */
+ for (k = 0; k < ops_ld->n_filler; k++) {
+ if (harq_out[jj] !=
+ llr_max_pre_scaling) {
+ printf("HARQ Filler issue %d: %d %d\n",
+ jj, harq_out[jj],
+ llr_max);
+ byte_error++;
+ }
+ jj++;
+ }
+ }
+ if (!(ops_ld->op_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
+ if (ldpc_llr_decimals > 1)
+ harq_out[jj] = (harq_out[jj] + 1)
+ >> (ldpc_llr_decimals - 1);
+ /* Saturated to S7 */
+ if (harq_orig[j] > llr_max)
+ harq_orig[j] = llr_max;
+ if (harq_orig[j] < -llr_max)
+ harq_orig[j] = -llr_max;
+ }
+ if (harq_orig[j] != harq_out[jj]) {
+ error = (harq_orig[j] > harq_out[jj]) ?
+ harq_orig[j] - harq_out[jj] :
+ harq_out[jj] - harq_orig[j];
+ abs_harq_origin = harq_orig[j] > 0 ?
+ harq_orig[j] :
+ -harq_orig[j];
+ /* Residual quantization error */
+ if ((error > 8 && (abs_harq_origin <
+ (llr_max - 16))) ||
+ (error > 16)) {
+ printf("HARQ mismatch %d: exp %d act %d => %d\n",
+ j, harq_orig[j],
+ harq_out[jj], error);
+ byte_error++;
+ cum_error += error;
+ }
+ }
+ }
+ m = m->next;
+ }
+
+ if (byte_error)
+ TEST_ASSERT(byte_error <= 1,
+ "HARQ output mismatch (%d) %d",
+ byte_error, cum_error);
+
+ /* Validate total mbuf pkt length */
+ uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
+ TEST_ASSERT(total_data_size < pkt_len + 64,
+ "Length of data differ in original (%u) and filled (%u) op",
+ total_data_size, pkt_len);
+
+ return TEST_SUCCESS;
+}
+
+static int
+validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
+ struct rte_bbdev_dec_op *ref_op, const int vector_mask)
+{
+ unsigned int i;
+ int ret;
+ struct op_data_entries *hard_data_orig =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+ struct op_data_entries *soft_data_orig =
+ &test_vector.entries[DATA_SOFT_OUTPUT];
+ struct rte_bbdev_op_turbo_dec *ops_td;
+ struct rte_bbdev_op_data *hard_output;
+ struct rte_bbdev_op_data *soft_output;
+ struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
+
+ for (i = 0; i < n; ++i) {
+ ops_td = &ops[i]->turbo_dec;
+ hard_output = &ops_td->hard_output;
+ soft_output = &ops_td->soft_output;
+
+ if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
+ TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
+ "Returned iter_count (%d) > expected iter_count (%d)",
+ ops_td->iter_count, ref_td->iter_count);
+ ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
+ TEST_ASSERT_SUCCESS(ret,
+ "Checking status and ordering for decoder failed");
+
+ TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
+ hard_data_orig),
+ "Hard output buffers (CB=%u) are not equal",
+ i);
+
+ if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
+ TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
+ soft_data_orig),
+ "Soft output buffers (CB=%u) are not equal",
+ i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+/* Check Number of code blocks errors */
+static int
+validate_ldpc_bler(struct rte_bbdev_dec_op **ops, const uint16_t n)
+{
+ unsigned int i;
+ struct op_data_entries *hard_data_orig =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+ struct rte_bbdev_op_ldpc_dec *ops_td;
+ struct rte_bbdev_op_data *hard_output;
+ int errors = 0;
+ struct rte_mbuf *m;
+
+ for (i = 0; i < n; ++i) {
+ ops_td = &ops[i]->ldpc_dec;
+ hard_output = &ops_td->hard_output;
+ m = hard_output->data;
+ if (memcmp(rte_pktmbuf_mtod_offset(m, uint32_t *, 0),
+ hard_data_orig->segments[0].addr,
+ hard_data_orig->segments[0].length))
+ errors++;
+ }
+ return errors;
+}
+
+static int
+validate_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
+ struct rte_bbdev_dec_op *ref_op, const int vector_mask)
+{
+ unsigned int i;
+ int ret;
+ struct op_data_entries *hard_data_orig =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+ struct op_data_entries *soft_data_orig =
+ &test_vector.entries[DATA_SOFT_OUTPUT];
+ struct op_data_entries *harq_data_orig =
+ &test_vector.entries[DATA_HARQ_OUTPUT];
+ struct rte_bbdev_op_ldpc_dec *ops_td;
+ struct rte_bbdev_op_data *hard_output;
+ struct rte_bbdev_op_data *harq_output;
+ struct rte_bbdev_op_data *soft_output;
+ struct rte_bbdev_op_ldpc_dec *ref_td = &ref_op->ldpc_dec;
+
+ for (i = 0; i < n; ++i) {
+ ops_td = &ops[i]->ldpc_dec;
+ hard_output = &ops_td->hard_output;
+ harq_output = &ops_td->harq_combined_output;
+ soft_output = &ops_td->soft_output;
+
+ ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
+ TEST_ASSERT_SUCCESS(ret,
+ "Checking status and ordering for decoder failed");
+ if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
+ TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
+ "Returned iter_count (%d) > expected iter_count (%d)",
+ ops_td->iter_count, ref_td->iter_count);
+ /*
+ * We can ignore output data when the decoding failed to
+ * converge or for loop-back cases
+ */
+ if (!check_bit(ops[i]->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
+ ) && (
+ ops[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR
+ )) == 0)
+ TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
+ hard_data_orig),
+ "Hard output buffers (CB=%u) are not equal",
+ i);
+
+ if (ref_op->ldpc_dec.op_flags & RTE_BBDEV_LDPC_SOFT_OUT_ENABLE)
+ TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
+ soft_data_orig),
+ "Soft output buffers (CB=%u) are not equal",
+ i);
+ if (ref_op->ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE) {
+ TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
+ harq_data_orig, ops_td),
+ "HARQ output buffers (CB=%u) are not equal",
+ i);
+ }
+ if (ref_op->ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
+ TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
+ harq_data_orig, ops_td),
+ "HARQ output buffers (CB=%u) are not equal",
+ i);
+
+ }
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
+ struct rte_bbdev_enc_op *ref_op)
+{
+ unsigned int i;
+ int ret;
+ struct op_data_entries *hard_data_orig =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+
+ for (i = 0; i < n; ++i) {
+ ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
+ TEST_ASSERT_SUCCESS(ret,
+ "Checking status and ordering for encoder failed");
+ TEST_ASSERT_SUCCESS(validate_op_chain(
+ &ops[i]->turbo_enc.output,
+ hard_data_orig),
+ "Output buffers (CB=%u) are not equal",
+ i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+validate_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
+ struct rte_bbdev_enc_op *ref_op)
+{
+ unsigned int i;
+ int ret;
+ struct op_data_entries *hard_data_orig =
+ &test_vector.entries[DATA_HARD_OUTPUT];
+
+ for (i = 0; i < n; ++i) {
+ ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
+ TEST_ASSERT_SUCCESS(ret,
+ "Checking status and ordering for encoder failed");
+ TEST_ASSERT_SUCCESS(validate_op_chain(
+ &ops[i]->ldpc_enc.output,
+ hard_data_orig),
+ "Output buffers (CB=%u) are not equal",
+ i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+create_reference_dec_op(struct rte_bbdev_dec_op *op)
+{
+ unsigned int i;
+ struct op_data_entries *entry;
+
+ op->turbo_dec = test_vector.turbo_dec;
+ entry = &test_vector.entries[DATA_INPUT];
+ for (i = 0; i < entry->nb_segments; ++i)
+ op->turbo_dec.input.length +=
+ entry->segments[i].length;
+}
+
+static void
+create_reference_ldpc_dec_op(struct rte_bbdev_dec_op *op)
+{
+ unsigned int i;
+ struct op_data_entries *entry;
+
+ op->ldpc_dec = test_vector.ldpc_dec;
+ entry = &test_vector.entries[DATA_INPUT];
+ for (i = 0; i < entry->nb_segments; ++i)
+ op->ldpc_dec.input.length +=
+ entry->segments[i].length;
+ if (test_vector.ldpc_dec.op_flags &
+ RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) {
+ entry = &test_vector.entries[DATA_HARQ_INPUT];
+ for (i = 0; i < entry->nb_segments; ++i)
+ op->ldpc_dec.harq_combined_input.length +=
+ entry->segments[i].length;
+ }
+}
+
+
+static void
+create_reference_enc_op(struct rte_bbdev_enc_op *op)
+{
+ unsigned int i;
+ struct op_data_entries *entry;
+
+ op->turbo_enc = test_vector.turbo_enc;
+ entry = &test_vector.entries[DATA_INPUT];
+ for (i = 0; i < entry->nb_segments; ++i)
+ op->turbo_enc.input.length +=
+ entry->segments[i].length;
+}
+
+static void
+create_reference_ldpc_enc_op(struct rte_bbdev_enc_op *op)
+{
+ unsigned int i;
+ struct op_data_entries *entry;
+
+ op->ldpc_enc = test_vector.ldpc_enc;
+ entry = &test_vector.entries[DATA_INPUT];
+ for (i = 0; i < entry->nb_segments; ++i)
+ op->ldpc_enc.input.length +=
+ entry->segments[i].length;
+}
+
+static uint32_t
+calc_dec_TB_size(struct rte_bbdev_dec_op *op)
+{
+ uint8_t i;
+ uint32_t c, r, tb_size = 0;
+
+ if (op->turbo_dec.code_block_mode) {
+ tb_size = op->turbo_dec.tb_params.k_neg;
+ } else {
+ c = op->turbo_dec.tb_params.c;
+ r = op->turbo_dec.tb_params.r;
+ for (i = 0; i < c-r; i++)
+ tb_size += (r < op->turbo_dec.tb_params.c_neg) ?
+ op->turbo_dec.tb_params.k_neg :
+ op->turbo_dec.tb_params.k_pos;
+ }
+ return tb_size;
+}
+
+static uint32_t
+calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op *op)
+{
+ uint8_t i;
+ uint32_t c, r, tb_size = 0;
+ uint16_t sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10;
+
+ if (op->ldpc_dec.code_block_mode) {
+ tb_size = sys_cols * op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
+ } else {
+ c = op->ldpc_dec.tb_params.c;
+ r = op->ldpc_dec.tb_params.r;
+ for (i = 0; i < c-r; i++)
+ tb_size += sys_cols * op->ldpc_dec.z_c
+ - op->ldpc_dec.n_filler;
+ }
+ return tb_size;
+}
+
+static uint32_t
+calc_enc_TB_size(struct rte_bbdev_enc_op *op)
+{
+ uint8_t i;
+ uint32_t c, r, tb_size = 0;
+
+ if (op->turbo_enc.code_block_mode) {
+ tb_size = op->turbo_enc.tb_params.k_neg;
+ } else {
+ c = op->turbo_enc.tb_params.c;
+ r = op->turbo_enc.tb_params.r;
+ for (i = 0; i < c-r; i++)
+ tb_size += (r < op->turbo_enc.tb_params.c_neg) ?
+ op->turbo_enc.tb_params.k_neg :
+ op->turbo_enc.tb_params.k_pos;
+ }
+ return tb_size;
+}
+
+static uint32_t
+calc_ldpc_enc_TB_size(struct rte_bbdev_enc_op *op)
+{
+ uint8_t i;
+ uint32_t c, r, tb_size = 0;
+ uint16_t sys_cols = (op->ldpc_enc.basegraph == 1) ? 22 : 10;
+
+ if (op->turbo_enc.code_block_mode) {
+ tb_size = sys_cols * op->ldpc_enc.z_c - op->ldpc_enc.n_filler;
+ } else {
+ c = op->turbo_enc.tb_params.c;
+ r = op->turbo_enc.tb_params.r;
+ for (i = 0; i < c-r; i++)
+ tb_size += sys_cols * op->ldpc_enc.z_c
+ - op->ldpc_enc.n_filler;
+ }
+ return tb_size;
+}
+
+
+static int
+init_test_op_params(struct test_op_params *op_params,
+ enum rte_bbdev_op_type op_type, const int expected_status,
+ const int vector_mask, struct rte_mempool *ops_mp,
+ uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
+{
+ int ret = 0;
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
+ op_type == RTE_BBDEV_OP_LDPC_DEC)
+ ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
+ &op_params->ref_dec_op, 1);
+ else
+ ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
+ &op_params->ref_enc_op, 1);
+
+ TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
+
+ op_params->mp = ops_mp;
+ op_params->burst_sz = burst_sz;
+ op_params->num_to_process = num_to_process;
+ op_params->num_lcores = num_lcores;
+ op_params->vector_mask = vector_mask;
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
+ op_type == RTE_BBDEV_OP_LDPC_DEC)
+ op_params->ref_dec_op->status = expected_status;
+ else if (op_type == RTE_BBDEV_OP_TURBO_ENC
+ || op_type == RTE_BBDEV_OP_LDPC_ENC)
+ op_params->ref_enc_op->status = expected_status;
+ return 0;
+}
+
+static int
+run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
+ struct test_op_params *op_params)
+{
+ int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
+ unsigned int i;
+ struct active_device *ad;
+ unsigned int burst_sz = get_burst_sz();
+ enum rte_bbdev_op_type op_type = test_vector.op_type;
+ const struct rte_bbdev_op_cap *capabilities = NULL;
+
+ ad = &active_devs[dev_id];
+
+ /* Check if device supports op_type */
+ if (!is_avail_op(ad, test_vector.op_type))
+ return TEST_SUCCESS;
+
+ struct rte_bbdev_info info;
+ rte_bbdev_info_get(ad->dev_id, &info);
+ socket_id = GET_SOCKET(info.socket_id);
+
+ f_ret = create_mempools(ad, socket_id, op_type,
+ get_num_ops());
+ if (f_ret != TEST_SUCCESS) {
+ printf("Couldn't create mempools");
+ goto fail;
+ }
+ if (op_type == RTE_BBDEV_OP_NONE)
+ op_type = RTE_BBDEV_OP_TURBO_ENC;
+
+ f_ret = init_test_op_params(op_params, test_vector.op_type,
+ test_vector.expected_status,
+ test_vector.mask,
+ ad->ops_mempool,
+ burst_sz,
+ get_num_ops(),
+ get_num_lcores());
+ if (f_ret != TEST_SUCCESS) {
+ printf("Couldn't init test op params");
+ goto fail;
+ }
+
+
+ /* Find capabilities */
+ const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
+ for (i = 0; i < RTE_BBDEV_OP_TYPE_COUNT; i++) {
+ if (cap->type == test_vector.op_type) {
+ capabilities = cap;
+ break;
+ }
+ cap++;
+ }
+ TEST_ASSERT_NOT_NULL(capabilities,
+ "Couldn't find capabilities");
+
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
+ create_reference_dec_op(op_params->ref_dec_op);
+ } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
+ create_reference_enc_op(op_params->ref_enc_op);
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
+ create_reference_ldpc_enc_op(op_params->ref_enc_op);
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ create_reference_ldpc_dec_op(op_params->ref_dec_op);
+
+ for (i = 0; i < ad->nb_queues; ++i) {
+ f_ret = fill_queue_buffers(op_params,
+ ad->in_mbuf_pool,
+ ad->hard_out_mbuf_pool,
+ ad->soft_out_mbuf_pool,
+ ad->harq_in_mbuf_pool,
+ ad->harq_out_mbuf_pool,
+ ad->queue_ids[i],
+ capabilities,
+ info.drv.min_alignment,
+ socket_id);
+ if (f_ret != TEST_SUCCESS) {
+ printf("Couldn't init queue buffers");
+ goto fail;
+ }
+ }
+
+ /* Run test case function */
+ t_ret = test_case_func(ad, op_params);
+
+ /* Free active device resources and return */
+ free_buffers(ad, op_params);
+ return t_ret;
+
+fail:
+ free_buffers(ad, op_params);
+ return TEST_FAILED;
+}
+
+/* Run given test function per active device per supported op type
+ * per burst size.
+ */
+static int
+run_test_case(test_case_function *test_case_func)
+{
+ int ret = 0;
+ uint8_t dev;
+
+ /* Alloc op_params */
+ struct test_op_params *op_params = rte_zmalloc(NULL,
+ sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
+ RTE_ALIGN(sizeof(struct test_op_params),
+ RTE_CACHE_LINE_SIZE));
+
+ /* For each device run test case function */
+ for (dev = 0; dev < nb_active_devs; ++dev)
+ ret |= run_test_case_on_device(test_case_func, dev, op_params);
+
+ rte_free(op_params);
+
+ return ret;
+}
+
+
+/* Push back the HARQ output from DDR to host */
+static void
+retrieve_harq_ddr(uint16_t dev_id, uint16_t queue_id,
+ struct rte_bbdev_dec_op **ops,
+ const uint16_t n)
+{
+ uint16_t j;
+ int save_status, ret;
+ uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * 1024;
+ struct rte_bbdev_dec_op *ops_deq[MAX_BURST];
+ uint32_t flags = ops[0]->ldpc_dec.op_flags;
+ bool loopback = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
+ bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+ bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
+ bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ for (j = 0; j < n; ++j) {
+ if ((loopback && mem_out) || hc_out) {
+ save_status = ops[j]->status;
+ ops[j]->ldpc_dec.op_flags =
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
+ if (h_comp)
+ ops[j]->ldpc_dec.op_flags +=
+ RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ ops[j]->ldpc_dec.harq_combined_input.offset =
+ harq_offset;
+ ops[j]->ldpc_dec.harq_combined_output.offset = 0;
+ harq_offset += HARQ_INCR;
+ if (!loopback)
+ ops[j]->ldpc_dec.harq_combined_input.length =
+ ops[j]->ldpc_dec.harq_combined_output.length;
+ rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
+ &ops[j], 1);
+ ret = 0;
+ while (ret == 0)
+ ret = rte_bbdev_dequeue_ldpc_dec_ops(
+ dev_id, queue_id,
+ &ops_deq[j], 1);
+ ops[j]->ldpc_dec.op_flags = flags;
+ ops[j]->status = save_status;
+ }
+ }
+}
+
+/*
+ * Push back the HARQ output from HW DDR to Host
+ * Preload HARQ memory input and adjust HARQ offset
+ */
+static void
+preload_harq_ddr(uint16_t dev_id, uint16_t queue_id,
+ struct rte_bbdev_dec_op **ops, const uint16_t n,
+ bool preload)
+{
+ uint16_t j;
+ int ret;
+ uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * 1024;
+ struct rte_bbdev_op_data save_hc_in, save_hc_out;
+ struct rte_bbdev_dec_op *ops_deq[MAX_BURST];
+ uint32_t flags = ops[0]->ldpc_dec.op_flags;
+ bool mem_in = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
+ bool hc_in = flags & RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
+ bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+ bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
+ bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ for (j = 0; j < n; ++j) {
+ if ((mem_in || hc_in) && preload) {
+ save_hc_in = ops[j]->ldpc_dec.harq_combined_input;
+ save_hc_out = ops[j]->ldpc_dec.harq_combined_output;
+ ops[j]->ldpc_dec.op_flags =
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+ if (h_comp)
+ ops[j]->ldpc_dec.op_flags +=
+ RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ ops[j]->ldpc_dec.harq_combined_output.offset =
+ harq_offset;
+ ops[j]->ldpc_dec.harq_combined_input.offset = 0;
+ rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
+ &ops[j], 1);
+ ret = 0;
+ while (ret == 0)
+ ret = rte_bbdev_dequeue_ldpc_dec_ops(
+ dev_id, queue_id, &ops_deq[j], 1);
+ ops[j]->ldpc_dec.op_flags = flags;
+ ops[j]->ldpc_dec.harq_combined_input = save_hc_in;
+ ops[j]->ldpc_dec.harq_combined_output = save_hc_out;
+ }
+ /* Adjust HARQ offset when we reach external DDR */
+ if (mem_in || hc_in)
+ ops[j]->ldpc_dec.harq_combined_input.offset
+ = harq_offset;
+ if (mem_out || hc_out)
+ ops[j]->ldpc_dec.harq_combined_output.offset
+ = harq_offset;
+ harq_offset += HARQ_INCR;
+ }
+}
+
+static void
+dequeue_event_callback(uint16_t dev_id,
+ enum rte_bbdev_event_type event, void *cb_arg,
+ void *ret_param)
+{
+ int ret;
+ uint16_t i;
+ uint64_t total_time;
+ uint16_t deq, burst_sz, num_ops;
+ uint16_t queue_id = *(uint16_t *) ret_param;
+ struct rte_bbdev_info info;
+ double tb_len_bits;
+ struct thread_params *tp = cb_arg;
+
+ /* Find matching thread params using queue_id */
+ for (i = 0; i < MAX_QUEUES; ++i, ++tp)
+ if (tp->queue_id == queue_id)
+ break;
+
+ if (i == MAX_QUEUES) {
+ printf("%s: Queue_id from interrupt details was not found!\n",
+ __func__);
+ return;
+ }
+
+ if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
+ rte_atomic16_set(&tp->processing_status, TEST_FAILED);
+ printf(
+ "Dequeue interrupt handler called for incorrect event!\n");
+ return;
+ }
+
+ burst_sz = rte_atomic16_read(&tp->burst_sz);
+ num_ops = tp->op_params->num_to_process;
+
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
+ deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
+ &tp->dec_ops[
+ rte_atomic16_read(&tp->nb_dequeued)],
+ burst_sz);
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ deq = rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
+ &tp->dec_ops[
+ rte_atomic16_read(&tp->nb_dequeued)],
+ burst_sz);
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
+ deq = rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
+ &tp->enc_ops[
+ rte_atomic16_read(&tp->nb_dequeued)],
+ burst_sz);
+ else /*RTE_BBDEV_OP_TURBO_ENC*/
+ deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
+ &tp->enc_ops[
+ rte_atomic16_read(&tp->nb_dequeued)],
+ burst_sz);
+
+ if (deq < burst_sz) {
+ printf(
+ "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
+ burst_sz, deq);
+ rte_atomic16_set(&tp->processing_status, TEST_FAILED);
+ return;
+ }
+
+ if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_ops) {
+ rte_atomic16_add(&tp->nb_dequeued, deq);
+ return;
+ }
+
+ total_time = rte_rdtsc_precise() - tp->start_time;
+
+ rte_bbdev_info_get(dev_id, &info);
+
+ ret = TEST_SUCCESS;
+
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ ret = validate_dec_op(tp->dec_ops, num_ops, ref_op,
+ tp->op_params->vector_mask);
+ /* get the max of iter_count for all dequeued ops */
+ for (i = 0; i < num_ops; ++i)
+ tp->iter_count = RTE_MAX(
+ tp->dec_ops[i]->turbo_dec.iter_count,
+ tp->iter_count);
+ rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
+ } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC) {
+ struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
+ ret = validate_enc_op(tp->enc_ops, num_ops, ref_op);
+ rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
+ } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC) {
+ struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
+ ret = validate_ldpc_enc_op(tp->enc_ops, num_ops, ref_op);
+ rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
+ } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ ret = validate_ldpc_dec_op(tp->dec_ops, num_ops, ref_op,
+ tp->op_params->vector_mask);
+ rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
+ }
+
+ if (ret) {
+ printf("Buffers validation failed\n");
+ rte_atomic16_set(&tp->processing_status, TEST_FAILED);
+ }
+
+ switch (test_vector.op_type) {
+ case RTE_BBDEV_OP_TURBO_DEC:
+ tb_len_bits = calc_dec_TB_size(tp->op_params->ref_dec_op);
+ break;
+ case RTE_BBDEV_OP_TURBO_ENC:
+ tb_len_bits = calc_enc_TB_size(tp->op_params->ref_enc_op);
+ break;
+ case RTE_BBDEV_OP_LDPC_DEC:
+ tb_len_bits = calc_ldpc_dec_TB_size(tp->op_params->ref_dec_op);
+ break;
+ case RTE_BBDEV_OP_LDPC_ENC:
+ tb_len_bits = calc_ldpc_enc_TB_size(tp->op_params->ref_enc_op);
+ break;
+ case RTE_BBDEV_OP_NONE:
+ tb_len_bits = 0.0;
+ break;
+ default:
+ printf("Unknown op type: %d\n", test_vector.op_type);
+ rte_atomic16_set(&tp->processing_status, TEST_FAILED);
+ return;
+ }
+
+ tp->ops_per_sec += ((double)num_ops) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps += (((double)(num_ops * tb_len_bits)) / 1000000.0) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+
+ rte_atomic16_add(&tp->nb_dequeued, deq);
+}
+
+static int
+throughput_intr_lcore_ldpc_dec(void *arg)
+{
+ struct thread_params *tp = arg;
+ unsigned int enqueued;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_to_process = tp->op_params->num_to_process;
+ struct rte_bbdev_dec_op *ops[num_to_process];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ int ret, i, j;
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ uint16_t num_to_enq, enq;
+
+ bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
+ bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
+ "Failed to enable interrupts for dev: %u, queue_id: %u",
+ tp->dev_id, queue_id);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ rte_atomic16_clear(&tp->processing_status);
+ rte_atomic16_clear(&tp->nb_dequeued);
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
+ num_to_process);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_to_process);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_dec_op(ops, num_to_process, 0, bufs->inputs,
+ bufs->hard_outputs, bufs->soft_outputs,
+ bufs->harq_inputs, bufs->harq_outputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_to_process; ++j)
+ ops[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (j = 0; j < TEST_REPETITIONS; ++j) {
+ for (i = 0; i < num_to_process; ++i) {
+ if (!loopback)
+ rte_pktmbuf_reset(
+ ops[i]->ldpc_dec.hard_output.data);
+ if (hc_out || loopback)
+ mbuf_reset(
+ ops[i]->ldpc_dec.harq_combined_output.data);
+ }
+
+ tp->start_time = rte_rdtsc_precise();
+ for (enqueued = 0; enqueued < num_to_process;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_to_process - enqueued < num_to_enq))
+ num_to_enq = num_to_process - enqueued;
+
+ enq = 0;
+ do {
+ enq += rte_bbdev_enqueue_ldpc_dec_ops(
+ tp->dev_id,
+ queue_id, &ops[enqueued],
+ num_to_enq);
+ } while (unlikely(num_to_enq != enq));
+ enqueued += enq;
+
+ /* Write to thread burst_sz current number of enqueued
+ * descriptors. It ensures that proper number of
+ * descriptors will be dequeued in callback
+ * function - needed for last batch in case where
+ * the number of operations is not a multiple of
+ * burst size.
+ */
+ rte_atomic16_set(&tp->burst_sz, num_to_enq);
+
+ /* Wait until processing of previous batch is
+ * completed
+ */
+ while (rte_atomic16_read(&tp->nb_dequeued) !=
+ (int16_t) enqueued)
+ rte_pause();
+ }
+ if (j != TEST_REPETITIONS - 1)
+ rte_atomic16_clear(&tp->nb_dequeued);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_intr_lcore_dec(void *arg)
+{
+ struct thread_params *tp = arg;
+ unsigned int enqueued;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_to_process = tp->op_params->num_to_process;
+ struct rte_bbdev_dec_op *ops[num_to_process];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ int ret, i, j;
+ uint16_t num_to_enq, enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
+ "Failed to enable interrupts for dev: %u, queue_id: %u",
+ tp->dev_id, queue_id);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ rte_atomic16_clear(&tp->processing_status);
+ rte_atomic16_clear(&tp->nb_dequeued);
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
+ num_to_process);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_to_process);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_dec_op(ops, num_to_process, 0, bufs->inputs,
+ bufs->hard_outputs, bufs->soft_outputs,
+ tp->op_params->ref_dec_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_to_process; ++j)
+ ops[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (j = 0; j < TEST_REPETITIONS; ++j) {
+ for (i = 0; i < num_to_process; ++i)
+ rte_pktmbuf_reset(ops[i]->turbo_dec.hard_output.data);
+
+ tp->start_time = rte_rdtsc_precise();
+ for (enqueued = 0; enqueued < num_to_process;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_to_process - enqueued < num_to_enq))
+ num_to_enq = num_to_process - enqueued;
+
+ enq = 0;
+ do {
+ enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
+ queue_id, &ops[enqueued],
+ num_to_enq);
+ } while (unlikely(num_to_enq != enq));
+ enqueued += enq;
+
+ /* Write to thread burst_sz current number of enqueued
+ * descriptors. It ensures that proper number of
+ * descriptors will be dequeued in callback
+ * function - needed for last batch in case where
+ * the number of operations is not a multiple of
+ * burst size.
+ */
+ rte_atomic16_set(&tp->burst_sz, num_to_enq);
+
+ /* Wait until processing of previous batch is
+ * completed
+ */
+ while (rte_atomic16_read(&tp->nb_dequeued) !=
+ (int16_t) enqueued)
+ rte_pause();
+ }
+ if (j != TEST_REPETITIONS - 1)
+ rte_atomic16_clear(&tp->nb_dequeued);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_intr_lcore_enc(void *arg)
+{
+ struct thread_params *tp = arg;
+ unsigned int enqueued;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_to_process = tp->op_params->num_to_process;
+ struct rte_bbdev_enc_op *ops[num_to_process];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ int ret, i, j;
+ uint16_t num_to_enq, enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
+ "Failed to enable interrupts for dev: %u, queue_id: %u",
+ tp->dev_id, queue_id);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ rte_atomic16_clear(&tp->processing_status);
+ rte_atomic16_clear(&tp->nb_dequeued);
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
+ num_to_process);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_to_process);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_enc_op(ops, num_to_process, 0, bufs->inputs,
+ bufs->hard_outputs, tp->op_params->ref_enc_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_to_process; ++j)
+ ops[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (j = 0; j < TEST_REPETITIONS; ++j) {
+ for (i = 0; i < num_to_process; ++i)
+ rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
+
+ tp->start_time = rte_rdtsc_precise();
+ for (enqueued = 0; enqueued < num_to_process;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_to_process - enqueued < num_to_enq))
+ num_to_enq = num_to_process - enqueued;
+
+ enq = 0;
+ do {
+ enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
+ queue_id, &ops[enqueued],
+ num_to_enq);
+ } while (unlikely(enq != num_to_enq));
+ enqueued += enq;
+
+ /* Write to thread burst_sz current number of enqueued
+ * descriptors. It ensures that proper number of
+ * descriptors will be dequeued in callback
+ * function - needed for last batch in case where
+ * the number of operations is not a multiple of
+ * burst size.
+ */
+ rte_atomic16_set(&tp->burst_sz, num_to_enq);
+
+ /* Wait until processing of previous batch is
+ * completed
+ */
+ while (rte_atomic16_read(&tp->nb_dequeued) !=
+ (int16_t) enqueued)
+ rte_pause();
+ }
+ if (j != TEST_REPETITIONS - 1)
+ rte_atomic16_clear(&tp->nb_dequeued);
+ }
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+throughput_intr_lcore_ldpc_enc(void *arg)
+{
+ struct thread_params *tp = arg;
+ unsigned int enqueued;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_to_process = tp->op_params->num_to_process;
+ struct rte_bbdev_enc_op *ops[num_to_process];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ int ret, i, j;
+ uint16_t num_to_enq, enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
+ "Failed to enable interrupts for dev: %u, queue_id: %u",
+ tp->dev_id, queue_id);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ rte_atomic16_clear(&tp->processing_status);
+ rte_atomic16_clear(&tp->nb_dequeued);
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
+ num_to_process);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_to_process);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_enc_op(ops, num_to_process, 0,
+ bufs->inputs, bufs->hard_outputs,
+ tp->op_params->ref_enc_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_to_process; ++j)
+ ops[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (j = 0; j < TEST_REPETITIONS; ++j) {
+ for (i = 0; i < num_to_process; ++i)
+ rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
+
+ tp->start_time = rte_rdtsc_precise();
+ for (enqueued = 0; enqueued < num_to_process;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_to_process - enqueued < num_to_enq))
+ num_to_enq = num_to_process - enqueued;
+
+ enq = 0;
+ do {
+ enq += rte_bbdev_enqueue_ldpc_enc_ops(
+ tp->dev_id,
+ queue_id, &ops[enqueued],
+ num_to_enq);
+ } while (unlikely(enq != num_to_enq));
+ enqueued += enq;
+
+ /* Write to thread burst_sz current number of enqueued
+ * descriptors. It ensures that proper number of
+ * descriptors will be dequeued in callback
+ * function - needed for last batch in case where
+ * the number of operations is not a multiple of
+ * burst size.
+ */
+ rte_atomic16_set(&tp->burst_sz, num_to_enq);
+
+ /* Wait until processing of previous batch is
+ * completed
+ */
+ while (rte_atomic16_read(&tp->nb_dequeued) !=
+ (int16_t) enqueued)
+ rte_pause();
+ }
+ if (j != TEST_REPETITIONS - 1)
+ rte_atomic16_clear(&tp->nb_dequeued);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_pmd_lcore_dec(void *arg)
+{
+ struct thread_params *tp = arg;
+ uint16_t enq, deq;
+ uint64_t total_time = 0, start_time;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_ops = tp->op_params->num_to_process;
+ struct rte_bbdev_dec_op *ops_enq[num_ops];
+ struct rte_bbdev_dec_op *ops_deq[num_ops];
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ struct test_buffers *bufs = NULL;
+ int i, j, ret;
+ struct rte_bbdev_info info;
+ uint16_t num_to_enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_dec_op(ops_enq, num_ops, 0, bufs->inputs,
+ bufs->hard_outputs, bufs->soft_outputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_ops; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (i = 0; i < TEST_REPETITIONS; ++i) {
+
+ for (j = 0; j < num_ops; ++j)
+ mbuf_reset(ops_enq[j]->turbo_dec.hard_output.data);
+
+ start_time = rte_rdtsc_precise();
+
+ for (enq = 0, deq = 0; enq < num_ops;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_ops - enq < num_to_enq))
+ num_to_enq = num_ops - enq;
+
+ enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
+ queue_id, &ops_enq[enq], num_to_enq);
+
+ deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ /* dequeue the remaining */
+ while (deq < enq) {
+ deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ total_time += rte_rdtsc_precise() - start_time;
+ }
+
+ tp->iter_count = 0;
+ /* get the max of iter_count for all dequeued ops */
+ for (i = 0; i < num_ops; ++i) {
+ tp->iter_count = RTE_MAX(ops_enq[i]->turbo_dec.iter_count,
+ tp->iter_count);
+ }
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_dec_op(ops_deq, num_ops, ref_op,
+ tp->op_params->vector_mask);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
+
+ double tb_len_bits = calc_dec_TB_size(ref_op);
+
+ tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
+ 1000000.0) / ((double)total_time /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+static int
+bler_pmd_lcore_ldpc_dec(void *arg)
+{
+ struct thread_params *tp = arg;
+ uint16_t enq, deq;
+ uint64_t total_time = 0, start_time;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_ops = tp->op_params->num_to_process;
+ struct rte_bbdev_dec_op *ops_enq[num_ops];
+ struct rte_bbdev_dec_op *ops_deq[num_ops];
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ struct test_buffers *bufs = NULL;
+ int i, j, ret;
+ float parity_bler = 0;
+ struct rte_bbdev_info info;
+ uint16_t num_to_enq;
+ bool extDdr = check_bit(ldpc_cap_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
+ bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
+ bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
+
+ /* For BLER tests we need to enable early termination */
+ if (!check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
+ ref_op->ldpc_dec.op_flags +=
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
+ ref_op->ldpc_dec.iter_max = get_iter_max();
+ ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
+ bufs->hard_outputs, bufs->soft_outputs,
+ bufs->harq_inputs, bufs->harq_outputs, ref_op);
+ generate_llr_input(num_ops, bufs->inputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_ops; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (i = 0; i < 1; ++i) { /* Could add more iterations */
+ for (j = 0; j < num_ops; ++j) {
+ if (!loopback)
+ mbuf_reset(
+ ops_enq[j]->ldpc_dec.hard_output.data);
+ if (hc_out || loopback)
+ mbuf_reset(
+ ops_enq[j]->ldpc_dec.harq_combined_output.data);
+ }
+ if (extDdr) {
+ bool preload = i == (TEST_REPETITIONS - 1);
+ preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
+ num_ops, preload);
+ }
+ start_time = rte_rdtsc_precise();
+
+ for (enq = 0, deq = 0; enq < num_ops;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_ops - enq < num_to_enq))
+ num_to_enq = num_ops - enq;
+
+ enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_enq[enq], num_to_enq);
+
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ /* dequeue the remaining */
+ while (deq < enq) {
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ total_time += rte_rdtsc_precise() - start_time;
+ }
+
+ tp->iter_count = 0;
+ tp->iter_average = 0;
+ /* get the max of iter_count for all dequeued ops */
+ for (i = 0; i < num_ops; ++i) {
+ tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
+ tp->iter_count);
+ tp->iter_average += (double) ops_enq[i]->ldpc_dec.iter_count;
+ if (ops_enq[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR))
+ parity_bler += 1.0;
+ }
+
+ parity_bler /= num_ops; /* This one is based on SYND */
+ tp->iter_average /= num_ops;
+ tp->bler = (double) validate_ldpc_bler(ops_deq, num_ops) / num_ops;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE
+ && tp->bler == 0
+ && parity_bler == 0
+ && !hc_out) {
+ ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
+ tp->op_params->vector_mask);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
+
+ double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
+ tp->ops_per_sec = ((double)num_ops * 1) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps = (((double)(num_ops * 1 * tb_len_bits)) /
+ 1000000.0) / ((double)total_time /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_pmd_lcore_ldpc_dec(void *arg)
+{
+ struct thread_params *tp = arg;
+ uint16_t enq, deq;
+ uint64_t total_time = 0, start_time;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_ops = tp->op_params->num_to_process;
+ struct rte_bbdev_dec_op *ops_enq[num_ops];
+ struct rte_bbdev_dec_op *ops_deq[num_ops];
+ struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
+ struct test_buffers *bufs = NULL;
+ int i, j, ret;
+ struct rte_bbdev_info info;
+ uint16_t num_to_enq;
+ bool extDdr = check_bit(ldpc_cap_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
+ bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
+ bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
+
+ /* For throughput tests we need to disable early termination */
+ if (check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
+ ref_op->ldpc_dec.op_flags -=
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
+ ref_op->ldpc_dec.iter_max = get_iter_max();
+ ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
+ bufs->hard_outputs, bufs->soft_outputs,
+ bufs->harq_inputs, bufs->harq_outputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_ops; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (i = 0; i < TEST_REPETITIONS; ++i) {
+ for (j = 0; j < num_ops; ++j) {
+ if (!loopback)
+ mbuf_reset(
+ ops_enq[j]->ldpc_dec.hard_output.data);
+ if (hc_out || loopback)
+ mbuf_reset(
+ ops_enq[j]->ldpc_dec.harq_combined_output.data);
+ }
+ if (extDdr) {
+ bool preload = i == (TEST_REPETITIONS - 1);
+ preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
+ num_ops, preload);
+ }
+ start_time = rte_rdtsc_precise();
+
+ for (enq = 0, deq = 0; enq < num_ops;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_ops - enq < num_to_enq))
+ num_to_enq = num_ops - enq;
+
+ enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_enq[enq], num_to_enq);
+
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ /* dequeue the remaining */
+ while (deq < enq) {
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ total_time += rte_rdtsc_precise() - start_time;
+ }
+
+ tp->iter_count = 0;
+ /* get the max of iter_count for all dequeued ops */
+ for (i = 0; i < num_ops; ++i) {
+ tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
+ tp->iter_count);
+ }
+ if (extDdr) {
+ /* Read loopback is not thread safe */
+ retrieve_harq_ddr(tp->dev_id, queue_id, ops_enq, num_ops);
+ }
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
+ tp->op_params->vector_mask);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
+
+ double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
+
+ tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
+ 1000000.0) / ((double)total_time /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_pmd_lcore_enc(void *arg)
+{
+ struct thread_params *tp = arg;
+ uint16_t enq, deq;
+ uint64_t total_time = 0, start_time;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_ops = tp->op_params->num_to_process;
+ struct rte_bbdev_enc_op *ops_enq[num_ops];
+ struct rte_bbdev_enc_op *ops_deq[num_ops];
+ struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
+ struct test_buffers *bufs = NULL;
+ int i, j, ret;
+ struct rte_bbdev_info info;
+ uint16_t num_to_enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
+ num_ops);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_ops);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_enc_op(ops_enq, num_ops, 0, bufs->inputs,
+ bufs->hard_outputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_ops; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (i = 0; i < TEST_REPETITIONS; ++i) {
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ for (j = 0; j < num_ops; ++j)
+ mbuf_reset(ops_enq[j]->turbo_enc.output.data);
+
+ start_time = rte_rdtsc_precise();
+
+ for (enq = 0, deq = 0; enq < num_ops;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_ops - enq < num_to_enq))
+ num_to_enq = num_ops - enq;
+
+ enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
+ queue_id, &ops_enq[enq], num_to_enq);
+
+ deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ /* dequeue the remaining */
+ while (deq < enq) {
+ deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ total_time += rte_rdtsc_precise() - start_time;
+ }
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_enc_op(ops_deq, num_ops, ref_op);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
+
+ double tb_len_bits = calc_enc_TB_size(ref_op);
+
+ tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
+ / 1000000.0) / ((double)total_time /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+static int
+throughput_pmd_lcore_ldpc_enc(void *arg)
+{
+ struct thread_params *tp = arg;
+ uint16_t enq, deq;
+ uint64_t total_time = 0, start_time;
+ const uint16_t queue_id = tp->queue_id;
+ const uint16_t burst_sz = tp->op_params->burst_sz;
+ const uint16_t num_ops = tp->op_params->num_to_process;
+ struct rte_bbdev_enc_op *ops_enq[num_ops];
+ struct rte_bbdev_enc_op *ops_deq[num_ops];
+ struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
+ struct test_buffers *bufs = NULL;
+ int i, j, ret;
+ struct rte_bbdev_info info;
+ uint16_t num_to_enq;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(tp->dev_id, &info);
+
+ TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
+ "NUM_OPS cannot exceed %u for this device",
+ info.drv.queue_size_lim);
+
+ bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
+ rte_pause();
+
+ ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
+ num_ops);
+ TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
+ num_ops);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_enc_op(ops_enq, num_ops, 0, bufs->inputs,
+ bufs->hard_outputs, ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < num_ops; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ for (i = 0; i < TEST_REPETITIONS; ++i) {
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ for (j = 0; j < num_ops; ++j)
+ mbuf_reset(ops_enq[j]->turbo_enc.output.data);
+
+ start_time = rte_rdtsc_precise();
+
+ for (enq = 0, deq = 0; enq < num_ops;) {
+ num_to_enq = burst_sz;
+
+ if (unlikely(num_ops - enq < num_to_enq))
+ num_to_enq = num_ops - enq;
+
+ enq += rte_bbdev_enqueue_ldpc_enc_ops(tp->dev_id,
+ queue_id, &ops_enq[enq], num_to_enq);
+
+ deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ /* dequeue the remaining */
+ while (deq < enq) {
+ deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
+ queue_id, &ops_deq[deq], enq - deq);
+ }
+
+ total_time += rte_rdtsc_precise() - start_time;
+ }
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_ldpc_enc_op(ops_deq, num_ops, ref_op);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
+
+ double tb_len_bits = calc_ldpc_enc_TB_size(ref_op);
+
+ tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
+ ((double)total_time / (double)rte_get_tsc_hz());
+ tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
+ / 1000000.0) / ((double)total_time /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+static void
+print_enc_throughput(struct thread_params *t_params, unsigned int used_cores)
+{
+ unsigned int iter = 0;
+ double total_mops = 0, total_mbps = 0;
+
+ for (iter = 0; iter < used_cores; iter++) {
+ printf(
+ "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps\n",
+ t_params[iter].lcore_id, t_params[iter].ops_per_sec,
+ t_params[iter].mbps);
+ total_mops += t_params[iter].ops_per_sec;
+ total_mbps += t_params[iter].mbps;
+ }
+ printf(
+ "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps\n",
+ used_cores, total_mops, total_mbps);
+}
+
+/* Aggregate the performance results over the number of cores used */
+static void
+print_dec_throughput(struct thread_params *t_params, unsigned int used_cores)
+{
+ unsigned int core_idx = 0;
+ double total_mops = 0, total_mbps = 0;
+ uint8_t iter_count = 0;
+
+ for (core_idx = 0; core_idx < used_cores; core_idx++) {
+ printf(
+ "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n",
+ t_params[core_idx].lcore_id,
+ t_params[core_idx].ops_per_sec,
+ t_params[core_idx].mbps,
+ t_params[core_idx].iter_count);
+ total_mops += t_params[core_idx].ops_per_sec;
+ total_mbps += t_params[core_idx].mbps;
+ iter_count = RTE_MAX(iter_count,
+ t_params[core_idx].iter_count);
+ }
+ printf(
+ "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n",
+ used_cores, total_mops, total_mbps, iter_count);
+}
+
+/* Aggregate the performance results over the number of cores used */
+static void
+print_dec_bler(struct thread_params *t_params, unsigned int used_cores)
+{
+ unsigned int core_idx = 0;
+ double total_mbps = 0, total_bler = 0, total_iter = 0;
+ double snr = get_snr();
+
+ for (core_idx = 0; core_idx < used_cores; core_idx++) {
+ printf("Core%u BLER %.1f %% - Iters %.1f - Tp %.1f Mbps %s\n",
+ t_params[core_idx].lcore_id,
+ t_params[core_idx].bler * 100,
+ t_params[core_idx].iter_average,
+ t_params[core_idx].mbps,
+ get_vector_filename());
+ total_mbps += t_params[core_idx].mbps;
+ total_bler += t_params[core_idx].bler;
+ total_iter += t_params[core_idx].iter_average;
+ }
+ total_bler /= used_cores;
+ total_iter /= used_cores;
+
+ printf("SNR %.2f BLER %.1f %% - Iterations %.1f %d - Tp %.1f Mbps %s\n",
+ snr, total_bler * 100, total_iter, get_iter_max(),
+ total_mbps, get_vector_filename());
+}
+
+/*
+ * Test function that determines BLER wireless performance
+ */
+static int
+bler_test(struct active_device *ad,
+ struct test_op_params *op_params)
+{
+ int ret;
+ unsigned int lcore_id, used_cores = 0;
+ struct thread_params *t_params;
+ struct rte_bbdev_info info;
+ lcore_function_t *bler_function;
+ uint16_t num_lcores;
+ const char *op_type_str;
+
+ rte_bbdev_info_get(ad->dev_id, &info);
+
+ op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
+ test_vector.op_type);
+
+ printf("+ ------------------------------------------------------- +\n");
+ printf("== test: bler\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
+ info.dev_name, ad->nb_queues, op_params->burst_sz,
+ op_params->num_to_process, op_params->num_lcores,
+ op_type_str,
+ intr_enabled ? "Interrupt mode" : "PMD mode",
+ (double)rte_get_tsc_hz() / 1000000000.0);
+
+ /* Set number of lcores */
+ num_lcores = (ad->nb_queues < (op_params->num_lcores))
+ ? ad->nb_queues
+ : op_params->num_lcores;
+
+ /* Allocate memory for thread parameters structure */
+ t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
+ RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
+ RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
+ RTE_CACHE_LINE_SIZE));
+
+ if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ bler_function = bler_pmd_lcore_ldpc_dec;
+ else
+ return TEST_SKIPPED;
+
+ rte_atomic16_set(&op_params->sync, SYNC_WAIT);
+
+ /* Master core is set at first entry */
+ t_params[0].dev_id = ad->dev_id;
+ t_params[0].lcore_id = rte_lcore_id();
+ t_params[0].op_params = op_params;
+ t_params[0].queue_id = ad->queue_ids[used_cores++];
+ t_params[0].iter_count = 0;
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (used_cores >= num_lcores)
+ break;
+
+ t_params[used_cores].dev_id = ad->dev_id;
+ t_params[used_cores].lcore_id = lcore_id;
+ t_params[used_cores].op_params = op_params;
+ t_params[used_cores].queue_id = ad->queue_ids[used_cores];
+ t_params[used_cores].iter_count = 0;
+
+ rte_eal_remote_launch(bler_function,
+ &t_params[used_cores++], lcore_id);
+ }
+
+ rte_atomic16_set(&op_params->sync, SYNC_START);
+ ret = bler_function(&t_params[0]);
+
+ /* Master core is always used */
+ for (used_cores = 1; used_cores < num_lcores; used_cores++)
+ ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
+
+ print_dec_bler(t_params, num_lcores);
+
+ /* Return if test failed */
+ if (ret) {
+ rte_free(t_params);
+ return ret;
+ }
+
+ /* Function to print something here*/
+ rte_free(t_params);
+ return ret;
+}
+
+/*
+ * Test function that determines how long an enqueue + dequeue of a burst
+ * takes on available lcores.
+ */
+static int
+throughput_test(struct active_device *ad,
+ struct test_op_params *op_params)
+{
+ int ret;
+ unsigned int lcore_id, used_cores = 0;
+ struct thread_params *t_params, *tp;
+ struct rte_bbdev_info info;
+ lcore_function_t *throughput_function;
+ uint16_t num_lcores;
+ const char *op_type_str;
+
+ rte_bbdev_info_get(ad->dev_id, &info);
+
+ op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
+ test_vector.op_type);
+
+ printf("+ ------------------------------------------------------- +\n");
+ printf("== test: throughput\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
+ info.dev_name, ad->nb_queues, op_params->burst_sz,
+ op_params->num_to_process, op_params->num_lcores,
+ op_type_str,
+ intr_enabled ? "Interrupt mode" : "PMD mode",
+ (double)rte_get_tsc_hz() / 1000000000.0);
+
+ /* Set number of lcores */
+ num_lcores = (ad->nb_queues < (op_params->num_lcores))
+ ? ad->nb_queues
+ : op_params->num_lcores;
+
+ /* Allocate memory for thread parameters structure */
+ t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
+ RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
+ RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
+ RTE_CACHE_LINE_SIZE));
+
+ if (intr_enabled) {
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
+ throughput_function = throughput_intr_lcore_dec;
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ throughput_function = throughput_intr_lcore_ldpc_dec;
+ else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
+ throughput_function = throughput_intr_lcore_enc;
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
+ throughput_function = throughput_intr_lcore_ldpc_enc;
+ else
+ throughput_function = throughput_intr_lcore_enc;
+
+ /* Dequeue interrupt callback registration */
+ ret = rte_bbdev_callback_register(ad->dev_id,
+ RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
+ t_params);
+ if (ret < 0) {
+ rte_free(t_params);
+ return ret;
+ }
+ } else {
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
+ throughput_function = throughput_pmd_lcore_dec;
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ throughput_function = throughput_pmd_lcore_ldpc_dec;
+ else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
+ throughput_function = throughput_pmd_lcore_enc;
+ else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
+ throughput_function = throughput_pmd_lcore_ldpc_enc;
+ else
+ throughput_function = throughput_pmd_lcore_enc;
+ }
+
+ rte_atomic16_set(&op_params->sync, SYNC_WAIT);
+
+ /* Master core is set at first entry */
+ t_params[0].dev_id = ad->dev_id;
+ t_params[0].lcore_id = rte_lcore_id();
+ t_params[0].op_params = op_params;
+ t_params[0].queue_id = ad->queue_ids[used_cores++];
+ t_params[0].iter_count = 0;
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (used_cores >= num_lcores)
+ break;
+
+ t_params[used_cores].dev_id = ad->dev_id;
+ t_params[used_cores].lcore_id = lcore_id;
+ t_params[used_cores].op_params = op_params;
+ t_params[used_cores].queue_id = ad->queue_ids[used_cores];
+ t_params[used_cores].iter_count = 0;
+
+ rte_eal_remote_launch(throughput_function,
+ &t_params[used_cores++], lcore_id);
+ }
+
+ rte_atomic16_set(&op_params->sync, SYNC_START);
+ ret = throughput_function(&t_params[0]);
+
+ /* Master core is always used */
+ for (used_cores = 1; used_cores < num_lcores; used_cores++)
+ ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
+
+ /* Return if test failed */
+ if (ret) {
+ rte_free(t_params);
+ return ret;
+ }
+
+ /* Print throughput if interrupts are disabled and test passed */
+ if (!intr_enabled) {
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
+ test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ print_dec_throughput(t_params, num_lcores);
+ else
+ print_enc_throughput(t_params, num_lcores);
+ rte_free(t_params);
+ return ret;
+ }
+
+ /* In interrupt TC we need to wait for the interrupt callback to deqeue
+ * all pending operations. Skip waiting for queues which reported an
+ * error using processing_status variable.
+ * Wait for master lcore operations.
+ */
+ tp = &t_params[0];
+ while ((rte_atomic16_read(&tp->nb_dequeued) <
+ op_params->num_to_process) &&
+ (rte_atomic16_read(&tp->processing_status) !=
+ TEST_FAILED))
+ rte_pause();
+
+ tp->ops_per_sec /= TEST_REPETITIONS;
+ tp->mbps /= TEST_REPETITIONS;
+ ret |= (int)rte_atomic16_read(&tp->processing_status);
+
+ /* Wait for slave lcores operations */
+ for (used_cores = 1; used_cores < num_lcores; used_cores++) {
+ tp = &t_params[used_cores];
+
+ while ((rte_atomic16_read(&tp->nb_dequeued) <
+ op_params->num_to_process) &&
+ (rte_atomic16_read(&tp->processing_status) !=
+ TEST_FAILED))
+ rte_pause();
+
+ tp->ops_per_sec /= TEST_REPETITIONS;
+ tp->mbps /= TEST_REPETITIONS;
+ ret |= (int)rte_atomic16_read(&tp->processing_status);
+ }
+
+ /* Print throughput if test passed */
+ if (!ret) {
+ if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
+ test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
+ print_dec_throughput(t_params, num_lcores);
+ else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC ||
+ test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
+ print_enc_throughput(t_params, num_lcores);
+ }
+
+ rte_free(t_params);
+ return ret;
+}
+
+static int
+latency_test_dec(struct rte_mempool *mempool,
+ struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
+ int vector_mask, uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
+{
+ int ret = TEST_SUCCESS;
+ uint16_t i, j, dequeued;
+ struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t start_time = 0, last_time = 0;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+ bool first_time = true;
+ last_time = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_dec_op_alloc_bulk() failed");
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_dec_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ bufs->soft_outputs,
+ ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < burst_sz; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ start_time = rte_rdtsc_precise();
+
+ enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
+ burst_sz);
+ TEST_ASSERT(enq == burst_sz,
+ "Error enqueueing burst, expected %u, got %u",
+ burst_sz, enq);
+
+ /* Dequeue */
+ do {
+ deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+ if (likely(first_time && (deq > 0))) {
+ last_time = rte_rdtsc_precise() - start_time;
+ first_time = false;
+ }
+ } while (unlikely(burst_sz != deq));
+
+ *max_time = RTE_MAX(*max_time, last_time);
+ *min_time = RTE_MIN(*min_time, last_time);
+ *total_time += last_time;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_dec_op(ops_deq, burst_sz, ref_op,
+ vector_mask);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+latency_test_ldpc_dec(struct rte_mempool *mempool,
+ struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
+ int vector_mask, uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
+{
+ int ret = TEST_SUCCESS;
+ uint16_t i, j, dequeued;
+ struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t start_time = 0, last_time = 0;
+ bool extDdr = ldpc_cap_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+ bool first_time = true;
+ last_time = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_dec_op_alloc_bulk() failed");
+
+ /* For latency tests we need to disable early termination */
+ if (check_bit(ref_op->ldpc_dec.op_flags,
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
+ ref_op->ldpc_dec.op_flags -=
+ RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
+ ref_op->ldpc_dec.iter_max = get_iter_max();
+ ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ bufs->soft_outputs,
+ bufs->harq_inputs,
+ bufs->harq_outputs,
+ ref_op);
+
+ if (extDdr)
+ preload_harq_ddr(dev_id, queue_id, ops_enq,
+ burst_sz, true);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < burst_sz; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ start_time = rte_rdtsc_precise();
+
+ enq = rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz);
+ TEST_ASSERT(enq == burst_sz,
+ "Error enqueueing burst, expected %u, got %u",
+ burst_sz, enq);
+
+ /* Dequeue */
+ do {
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+ if (likely(first_time && (deq > 0))) {
+ last_time = rte_rdtsc_precise() - start_time;
+ first_time = false;
+ }
+ } while (unlikely(burst_sz != deq));
+
+ *max_time = RTE_MAX(*max_time, last_time);
+ *min_time = RTE_MIN(*min_time, last_time);
+ *total_time += last_time;
+
+ if (extDdr)
+ retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_ldpc_dec_op(ops_deq, burst_sz, ref_op,
+ vector_mask);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+ return i;
+}
+
+static int
+latency_test_enc(struct rte_mempool *mempool,
+ struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
+ uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
+{
+ int ret = TEST_SUCCESS;
+ uint16_t i, j, dequeued;
+ struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t start_time = 0, last_time = 0;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+ bool first_time = true;
+ last_time = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_enc_op_alloc_bulk() failed");
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_enc_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < burst_sz; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ start_time = rte_rdtsc_precise();
+
+ enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
+ burst_sz);
+ TEST_ASSERT(enq == burst_sz,
+ "Error enqueueing burst, expected %u, got %u",
+ burst_sz, enq);
+
+ /* Dequeue */
+ do {
+ deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+ if (likely(first_time && (deq > 0))) {
+ last_time += rte_rdtsc_precise() - start_time;
+ first_time = false;
+ }
+ } while (unlikely(burst_sz != deq));
+
+ *max_time = RTE_MAX(*max_time, last_time);
+ *min_time = RTE_MIN(*min_time, last_time);
+ *total_time += last_time;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_enc_op(ops_deq, burst_sz, ref_op);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+latency_test_ldpc_enc(struct rte_mempool *mempool,
+ struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
+ uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
+{
+ int ret = TEST_SUCCESS;
+ uint16_t i, j, dequeued;
+ struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t start_time = 0, last_time = 0;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+ bool first_time = true;
+ last_time = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_enc_op_alloc_bulk() failed");
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ ref_op);
+
+ /* Set counter to validate the ordering */
+ for (j = 0; j < burst_sz; ++j)
+ ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
+
+ start_time = rte_rdtsc_precise();
+
+ enq = rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz);
+ TEST_ASSERT(enq == burst_sz,
+ "Error enqueueing burst, expected %u, got %u",
+ burst_sz, enq);
+
+ /* Dequeue */
+ do {
+ deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+ if (likely(first_time && (deq > 0))) {
+ last_time += rte_rdtsc_precise() - start_time;
+ first_time = false;
+ }
+ } while (unlikely(burst_sz != deq));
+
+ *max_time = RTE_MAX(*max_time, last_time);
+ *min_time = RTE_MIN(*min_time, last_time);
+ *total_time += last_time;
+
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
+ ret = validate_enc_op(ops_deq, burst_sz, ref_op);
+ TEST_ASSERT_SUCCESS(ret, "Validation failed!");
+ }
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+latency_test(struct active_device *ad,
+ struct test_op_params *op_params)
+{
+ int iter;
+ uint16_t burst_sz = op_params->burst_sz;
+ const uint16_t num_to_process = op_params->num_to_process;
+ const enum rte_bbdev_op_type op_type = test_vector.op_type;
+ const uint16_t queue_id = ad->queue_ids[0];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ uint64_t total_time, min_time, max_time;
+ const char *op_type_str;
+
+ total_time = max_time = 0;
+ min_time = UINT64_MAX;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(ad->dev_id, &info);
+ bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ op_type_str = rte_bbdev_op_type_str(op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
+
+ printf("+ ------------------------------------------------------- +\n");
+ printf("== test: validation/latency\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
+ info.dev_name, burst_sz, num_to_process, op_type_str);
+
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC)
+ iter = latency_test_dec(op_params->mp, bufs,
+ op_params->ref_dec_op, op_params->vector_mask,
+ ad->dev_id, queue_id, num_to_process,
+ burst_sz, &total_time, &min_time, &max_time);
+ else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
+ iter = latency_test_enc(op_params->mp, bufs,
+ op_params->ref_enc_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &total_time,
+ &min_time, &max_time);
+ else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
+ iter = latency_test_ldpc_enc(op_params->mp, bufs,
+ op_params->ref_enc_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &total_time,
+ &min_time, &max_time);
+ else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
+ iter = latency_test_ldpc_dec(op_params->mp, bufs,
+ op_params->ref_dec_op, op_params->vector_mask,
+ ad->dev_id, queue_id, num_to_process,
+ burst_sz, &total_time, &min_time, &max_time);
+ else
+ iter = latency_test_enc(op_params->mp, bufs,
+ op_params->ref_enc_op,
+ ad->dev_id, queue_id,
+ num_to_process, burst_sz, &total_time,
+ &min_time, &max_time);
+
+ if (iter <= 0)
+ return TEST_FAILED;
+
+ printf("Operation latency:\n"
+ "\tavg: %lg cycles, %lg us\n"
+ "\tmin: %lg cycles, %lg us\n"
+ "\tmax: %lg cycles, %lg us\n",
+ (double)total_time / (double)iter,
+ (double)(total_time * 1000000) / (double)iter /
+ (double)rte_get_tsc_hz(), (double)min_time,
+ (double)(min_time * 1000000) / (double)rte_get_tsc_hz(),
+ (double)max_time, (double)(max_time * 1000000) /
+ (double)rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+}
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+static int
+get_bbdev_queue_stats(uint16_t dev_id, uint16_t queue_id,
+ struct rte_bbdev_stats *stats)
+{
+ struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
+ struct rte_bbdev_stats *q_stats;
+
+ if (queue_id >= dev->data->num_queues)
+ return -1;
+
+ q_stats = &dev->data->queues[queue_id].queue_stats;
+
+ stats->enqueued_count = q_stats->enqueued_count;
+ stats->dequeued_count = q_stats->dequeued_count;
+ stats->enqueue_err_count = q_stats->enqueue_err_count;
+ stats->dequeue_err_count = q_stats->dequeue_err_count;
+ stats->acc_offload_cycles = q_stats->acc_offload_cycles;
+
+ return 0;
+}
+
+static int
+offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
+ struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
+ uint16_t queue_id, const uint16_t num_to_process,
+ uint16_t burst_sz, struct test_time_stats *time_st)
+{
+ int i, dequeued, ret;
+ struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t enq_start_time, deq_start_time;
+ uint64_t enq_sw_last_time, deq_last_time;
+ struct rte_bbdev_stats stats;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_dec_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ bufs->soft_outputs,
+ ref_op);
+
+ /* Start time meas for enqueue function offload latency */
+ enq_start_time = rte_rdtsc_precise();
+ do {
+ enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz - enq);
+ } while (unlikely(burst_sz != enq));
+
+ ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to get stats for queue (%u) of device (%u)",
+ queue_id, dev_id);
+
+ enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
+ stats.acc_offload_cycles;
+ time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
+ enq_sw_last_time);
+ time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
+ enq_sw_last_time);
+ time_st->enq_sw_total_time += enq_sw_last_time;
+
+ time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_total_time += stats.acc_offload_cycles;
+
+ /* give time for device to process ops */
+ rte_delay_us(200);
+
+ /* Start time meas for dequeue function offload latency */
+ deq_start_time = rte_rdtsc_precise();
+ /* Dequeue one operation */
+ do {
+ deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], 1);
+ } while (unlikely(deq != 1));
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
+ deq_last_time);
+ time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
+ deq_last_time);
+ time_st->deq_total_time += deq_last_time;
+
+ /* Dequeue remaining operations if needed*/
+ while (burst_sz != deq)
+ deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+offload_latency_test_ldpc_dec(struct rte_mempool *mempool,
+ struct test_buffers *bufs,
+ struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
+ uint16_t queue_id, const uint16_t num_to_process,
+ uint16_t burst_sz, struct test_time_stats *time_st)
+{
+ int i, dequeued, ret;
+ struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t enq_start_time, deq_start_time;
+ uint64_t enq_sw_last_time, deq_last_time;
+ struct rte_bbdev_stats stats;
+ bool extDdr = ldpc_cap_flags &
+ RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ bufs->soft_outputs,
+ bufs->harq_inputs,
+ bufs->harq_outputs,
+ ref_op);
+
+ if (extDdr)
+ preload_harq_ddr(dev_id, queue_id, ops_enq,
+ burst_sz, true);
+
+ /* Start time meas for enqueue function offload latency */
+ enq_start_time = rte_rdtsc_precise();
+ do {
+ enq += rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz - enq);
+ } while (unlikely(burst_sz != enq));
+
+ enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
+ ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to get stats for queue (%u) of device (%u)",
+ queue_id, dev_id);
+
+ enq_sw_last_time -= stats.acc_offload_cycles;
+ time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
+ enq_sw_last_time);
+ time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
+ enq_sw_last_time);
+ time_st->enq_sw_total_time += enq_sw_last_time;
+
+ time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_total_time += stats.acc_offload_cycles;
+
+ /* give time for device to process ops */
+ rte_delay_us(200);
+
+ /* Start time meas for dequeue function offload latency */
+ deq_start_time = rte_rdtsc_precise();
+ /* Dequeue one operation */
+ do {
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], 1);
+ } while (unlikely(deq != 1));
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
+ deq_last_time);
+ time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
+ deq_last_time);
+ time_st->deq_total_time += deq_last_time;
+
+ /* Dequeue remaining operations if needed*/
+ while (burst_sz != deq)
+ deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+
+ if (extDdr) {
+ /* Read loopback is not thread safe */
+ retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
+ }
+
+ rte_bbdev_dec_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
+ struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
+ uint16_t queue_id, const uint16_t num_to_process,
+ uint16_t burst_sz, struct test_time_stats *time_st)
+{
+ int i, dequeued, ret;
+ struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t enq_start_time, deq_start_time;
+ uint64_t enq_sw_last_time, deq_last_time;
+ struct rte_bbdev_stats stats;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_enc_op_alloc_bulk() failed");
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_enc_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ ref_op);
+
+ /* Start time meas for enqueue function offload latency */
+ enq_start_time = rte_rdtsc_precise();
+ do {
+ enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz - enq);
+ } while (unlikely(burst_sz != enq));
+
+ enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
+
+ ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to get stats for queue (%u) of device (%u)",
+ queue_id, dev_id);
+ enq_sw_last_time -= stats.acc_offload_cycles;
+ time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
+ enq_sw_last_time);
+ time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
+ enq_sw_last_time);
+ time_st->enq_sw_total_time += enq_sw_last_time;
+
+ time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_total_time += stats.acc_offload_cycles;
+
+ /* give time for device to process ops */
+ rte_delay_us(200);
+
+ /* Start time meas for dequeue function offload latency */
+ deq_start_time = rte_rdtsc_precise();
+ /* Dequeue one operation */
+ do {
+ deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], 1);
+ } while (unlikely(deq != 1));
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
+ deq_last_time);
+ time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
+ deq_last_time);
+ time_st->deq_total_time += deq_last_time;
+
+ while (burst_sz != deq)
+ deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+
+static int
+offload_latency_test_ldpc_enc(struct rte_mempool *mempool,
+ struct test_buffers *bufs,
+ struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
+ uint16_t queue_id, const uint16_t num_to_process,
+ uint16_t burst_sz, struct test_time_stats *time_st)
+{
+ int i, dequeued, ret;
+ struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
+ uint64_t enq_start_time, deq_start_time;
+ uint64_t enq_sw_last_time, deq_last_time;
+ struct rte_bbdev_stats stats;
+
+ for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
+ uint16_t enq = 0, deq = 0;
+
+ if (unlikely(num_to_process - dequeued < burst_sz))
+ burst_sz = num_to_process - dequeued;
+
+ ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
+ TEST_ASSERT_SUCCESS(ret,
+ "rte_bbdev_enc_op_alloc_bulk() failed");
+ if (test_vector.op_type != RTE_BBDEV_OP_NONE)
+ copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
+ bufs->inputs,
+ bufs->hard_outputs,
+ ref_op);
+
+ /* Start time meas for enqueue function offload latency */
+ enq_start_time = rte_rdtsc_precise();
+ do {
+ enq += rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
+ &ops_enq[enq], burst_sz - enq);
+ } while (unlikely(burst_sz != enq));
+
+ enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
+ ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to get stats for queue (%u) of device (%u)",
+ queue_id, dev_id);
+
+ enq_sw_last_time -= stats.acc_offload_cycles;
+ time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
+ enq_sw_last_time);
+ time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
+ enq_sw_last_time);
+ time_st->enq_sw_total_time += enq_sw_last_time;
+
+ time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
+ stats.acc_offload_cycles);
+ time_st->enq_acc_total_time += stats.acc_offload_cycles;
+
+ /* give time for device to process ops */
+ rte_delay_us(200);
+
+ /* Start time meas for dequeue function offload latency */
+ deq_start_time = rte_rdtsc_precise();
+ /* Dequeue one operation */
+ do {
+ deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], 1);
+ } while (unlikely(deq != 1));
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
+ deq_last_time);
+ time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
+ deq_last_time);
+ time_st->deq_total_time += deq_last_time;
+
+ while (burst_sz != deq)
+ deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
+ &ops_deq[deq], burst_sz - deq);
+
+ rte_bbdev_enc_op_free_bulk(ops_enq, deq);
+ dequeued += deq;
+ }
+
+ return i;
+}
+#endif
+
+static int
+offload_cost_test(struct active_device *ad,
+ struct test_op_params *op_params)
+{
+#ifndef RTE_BBDEV_OFFLOAD_COST
+ RTE_SET_USED(ad);
+ RTE_SET_USED(op_params);
+ printf("Offload latency test is disabled.\n");
+ printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
+ return TEST_SKIPPED;
+#else
+ int iter;
+ uint16_t burst_sz = op_params->burst_sz;
+ const uint16_t num_to_process = op_params->num_to_process;
+ const enum rte_bbdev_op_type op_type = test_vector.op_type;
+ const uint16_t queue_id = ad->queue_ids[0];
+ struct test_buffers *bufs = NULL;
+ struct rte_bbdev_info info;
+ const char *op_type_str;
+ struct test_time_stats time_st;
+
+ memset(&time_st, 0, sizeof(struct test_time_stats));
+ time_st.enq_sw_min_time = UINT64_MAX;
+ time_st.enq_acc_min_time = UINT64_MAX;
+ time_st.deq_min_time = UINT64_MAX;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(ad->dev_id, &info);
+ bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
+
+ op_type_str = rte_bbdev_op_type_str(op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
+
+ printf("+ ------------------------------------------------------- +\n");
+ printf("== test: offload latency test\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
+ info.dev_name, burst_sz, num_to_process, op_type_str);
+
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC)
+ iter = offload_latency_test_dec(op_params->mp, bufs,
+ op_params->ref_dec_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &time_st);
+ else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
+ iter = offload_latency_test_enc(op_params->mp, bufs,
+ op_params->ref_enc_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &time_st);
+ else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
+ iter = offload_latency_test_ldpc_enc(op_params->mp, bufs,
+ op_params->ref_enc_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &time_st);
+ else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
+ iter = offload_latency_test_ldpc_dec(op_params->mp, bufs,
+ op_params->ref_dec_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &time_st);
+ else
+ iter = offload_latency_test_enc(op_params->mp, bufs,
+ op_params->ref_enc_op, ad->dev_id, queue_id,
+ num_to_process, burst_sz, &time_st);
+
+ if (iter <= 0)
+ return TEST_FAILED;
+
+ printf("Enqueue driver offload cost latency:\n"
+ "\tavg: %lg cycles, %lg us\n"
+ "\tmin: %lg cycles, %lg us\n"
+ "\tmax: %lg cycles, %lg us\n"
+ "Enqueue accelerator offload cost latency:\n"
+ "\tavg: %lg cycles, %lg us\n"
+ "\tmin: %lg cycles, %lg us\n"
+ "\tmax: %lg cycles, %lg us\n",
+ (double)time_st.enq_sw_total_time / (double)iter,
+ (double)(time_st.enq_sw_total_time * 1000000) /
+ (double)iter / (double)rte_get_tsc_hz(),
+ (double)time_st.enq_sw_min_time,
+ (double)(time_st.enq_sw_min_time * 1000000) /
+ rte_get_tsc_hz(), (double)time_st.enq_sw_max_time,
+ (double)(time_st.enq_sw_max_time * 1000000) /
+ rte_get_tsc_hz(), (double)time_st.enq_acc_total_time /
+ (double)iter,
+ (double)(time_st.enq_acc_total_time * 1000000) /
+ (double)iter / (double)rte_get_tsc_hz(),
+ (double)time_st.enq_acc_min_time,
+ (double)(time_st.enq_acc_min_time * 1000000) /
+ rte_get_tsc_hz(), (double)time_st.enq_acc_max_time,
+ (double)(time_st.enq_acc_max_time * 1000000) /
+ rte_get_tsc_hz());
+
+ printf("Dequeue offload cost latency - one op:\n"
+ "\tavg: %lg cycles, %lg us\n"
+ "\tmin: %lg cycles, %lg us\n"
+ "\tmax: %lg cycles, %lg us\n",
+ (double)time_st.deq_total_time / (double)iter,
+ (double)(time_st.deq_total_time * 1000000) /
+ (double)iter / (double)rte_get_tsc_hz(),
+ (double)time_st.deq_min_time,
+ (double)(time_st.deq_min_time * 1000000) /
+ rte_get_tsc_hz(), (double)time_st.deq_max_time,
+ (double)(time_st.deq_max_time * 1000000) /
+ rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+#endif
+}
+
+#ifdef RTE_BBDEV_OFFLOAD_COST
+static int
+offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *deq_total_time, uint64_t *deq_min_time,
+ uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
+{
+ int i, deq_total;
+ struct rte_bbdev_dec_op *ops[MAX_BURST];
+ uint64_t deq_start_time, deq_last_time;
+
+ /* Test deq offload latency from an empty queue */
+
+ for (i = 0, deq_total = 0; deq_total < num_to_process;
+ ++i, deq_total += burst_sz) {
+ deq_start_time = rte_rdtsc_precise();
+
+ if (unlikely(num_to_process - deq_total < burst_sz))
+ burst_sz = num_to_process - deq_total;
+ if (op_type == RTE_BBDEV_OP_LDPC_DEC)
+ rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id, ops,
+ burst_sz);
+ else
+ rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops,
+ burst_sz);
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
+ *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
+ *deq_total_time += deq_last_time;
+ }
+
+ return i;
+}
+
+static int
+offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
+ const uint16_t num_to_process, uint16_t burst_sz,
+ uint64_t *deq_total_time, uint64_t *deq_min_time,
+ uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
+{
+ int i, deq_total;
+ struct rte_bbdev_enc_op *ops[MAX_BURST];
+ uint64_t deq_start_time, deq_last_time;
+
+ /* Test deq offload latency from an empty queue */
+ for (i = 0, deq_total = 0; deq_total < num_to_process;
+ ++i, deq_total += burst_sz) {
+ deq_start_time = rte_rdtsc_precise();
+
+ if (unlikely(num_to_process - deq_total < burst_sz))
+ burst_sz = num_to_process - deq_total;
+ if (op_type == RTE_BBDEV_OP_LDPC_ENC)
+ rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id, ops,
+ burst_sz);
+ else
+ rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops,
+ burst_sz);
+
+ deq_last_time = rte_rdtsc_precise() - deq_start_time;
+ *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
+ *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
+ *deq_total_time += deq_last_time;
+ }
+
+ return i;
+}
+
+#endif
+
+static int
+offload_latency_empty_q_test(struct active_device *ad,
+ struct test_op_params *op_params)
+{
+#ifndef RTE_BBDEV_OFFLOAD_COST
+ RTE_SET_USED(ad);
+ RTE_SET_USED(op_params);
+ printf("Offload latency empty dequeue test is disabled.\n");
+ printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
+ return TEST_SKIPPED;
+#else
+ int iter;
+ uint64_t deq_total_time, deq_min_time, deq_max_time;
+ uint16_t burst_sz = op_params->burst_sz;
+ const uint16_t num_to_process = op_params->num_to_process;
+ const enum rte_bbdev_op_type op_type = test_vector.op_type;
+ const uint16_t queue_id = ad->queue_ids[0];
+ struct rte_bbdev_info info;
+ const char *op_type_str;
+
+ deq_total_time = deq_max_time = 0;
+ deq_min_time = UINT64_MAX;
+
+ TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
+ "BURST_SIZE should be <= %u", MAX_BURST);
+
+ rte_bbdev_info_get(ad->dev_id, &info);
+
+ op_type_str = rte_bbdev_op_type_str(op_type);
+ TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
+
+ printf("+ ------------------------------------------------------- +\n");
+ printf("== test: offload latency empty dequeue\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
+ info.dev_name, burst_sz, num_to_process, op_type_str);
+
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
+ op_type == RTE_BBDEV_OP_LDPC_DEC)
+ iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
+ num_to_process, burst_sz, &deq_total_time,
+ &deq_min_time, &deq_max_time, op_type);
+ else
+ iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
+ num_to_process, burst_sz, &deq_total_time,
+ &deq_min_time, &deq_max_time, op_type);
+
+ if (iter <= 0)
+ return TEST_FAILED;
+
+ printf("Empty dequeue offload:\n"
+ "\tavg: %lg cycles, %lg us\n"
+ "\tmin: %lg cycles, %lg us\n"
+ "\tmax: %lg cycles, %lg us\n",
+ (double)deq_total_time / (double)iter,
+ (double)(deq_total_time * 1000000) / (double)iter /
+ (double)rte_get_tsc_hz(), (double)deq_min_time,
+ (double)(deq_min_time * 1000000) / rte_get_tsc_hz(),
+ (double)deq_max_time, (double)(deq_max_time * 1000000) /
+ rte_get_tsc_hz());
+
+ return TEST_SUCCESS;
+#endif
+}
+
+static int
+bler_tc(void)
+{
+ return run_test_case(bler_test);
+}
+
+static int
+throughput_tc(void)
+{
+ return run_test_case(throughput_test);
+}
+
+static int
+offload_cost_tc(void)
+{
+ return run_test_case(offload_cost_test);
+}
+
+static int
+offload_latency_empty_q_tc(void)
+{
+ return run_test_case(offload_latency_empty_q_test);
+}
+
+static int
+latency_tc(void)
+{
+ return run_test_case(latency_test);
+}
+
+static int
+interrupt_tc(void)
+{
+ return run_test_case(throughput_test);
+}
+
+static struct unit_test_suite bbdev_bler_testsuite = {
+ .suite_name = "BBdev BLER Tests",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, bler_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite bbdev_throughput_testsuite = {
+ .suite_name = "BBdev Throughput Tests",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite bbdev_validation_testsuite = {
+ .suite_name = "BBdev Validation Tests",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite bbdev_latency_testsuite = {
+ .suite_name = "BBdev Latency Tests",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite bbdev_offload_cost_testsuite = {
+ .suite_name = "BBdev Offload Cost Tests",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, offload_cost_tc),
+ TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite bbdev_interrupt_testsuite = {
+ .suite_name = "BBdev Interrupt Tests",
+ .setup = interrupt_testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+REGISTER_TEST_COMMAND(bler, bbdev_bler_testsuite);
+REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
+REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
+REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
+REGISTER_TEST_COMMAND(offload, bbdev_offload_cost_testsuite);
+REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);
diff --git a/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.c b/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.c
new file mode 100644
index 000000000..50d1da00f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.c
@@ -0,0 +1,1434 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ #define _WITH_GETLINE
+#endif
+#include <stdio.h>
+#include <stdbool.h>
+#include <rte_malloc.h>
+
+#include "test_bbdev_vector.h"
+
+#define VALUE_DELIMITER ","
+#define ENTRY_DELIMITER "="
+
+const char *op_data_prefixes[] = {
+ "input",
+ "soft_output",
+ "hard_output",
+ "harq_input",
+ "harq_output",
+};
+
+/* trim leading and trailing spaces */
+static void
+trim_space(char *str)
+{
+ char *start, *end;
+
+ for (start = str; *start; start++) {
+ if (!isspace((unsigned char) start[0]))
+ break;
+ }
+
+ for (end = start + strlen(start); end > start + 1; end--) {
+ if (!isspace((unsigned char) end[-1]))
+ break;
+ }
+
+ *end = 0;
+
+ /* Shift from "start" to the beginning of the string */
+ if (start > str)
+ memmove(str, start, (end - start) + 1);
+}
+
+static bool
+starts_with(const char *str, const char *pre)
+{
+ return strncmp(pre, str, strlen(pre)) == 0;
+}
+
+/* tokenization test values separated by a comma */
+static int
+parse_values(char *tokens, uint32_t **data, uint32_t *data_length)
+{
+ uint32_t n_tokens = 0;
+ uint32_t data_size = 32;
+
+ uint32_t *values, *values_resized;
+ char *tok, *error = NULL;
+
+ tok = strtok(tokens, VALUE_DELIMITER);
+ if (tok == NULL)
+ return -1;
+
+ values = (uint32_t *)
+ rte_zmalloc(NULL, sizeof(uint32_t) * data_size, 0);
+ if (values == NULL)
+ return -1;
+
+ while (tok != NULL) {
+ values_resized = NULL;
+
+ if (n_tokens >= data_size) {
+ data_size *= 2;
+
+ values_resized = (uint32_t *) rte_realloc(values,
+ sizeof(uint32_t) * data_size, 0);
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+ values = values_resized;
+ }
+
+ values[n_tokens] = (uint32_t) strtoul(tok, &error, 0);
+
+ if ((error == NULL) || (*error != '\0')) {
+ printf("Failed with convert '%s'\n", tok);
+ rte_free(values);
+ return -1;
+ }
+
+ *data_length = *data_length + (strlen(tok) - strlen("0x"))/2;
+
+ tok = strtok(NULL, VALUE_DELIMITER);
+ if (tok == NULL)
+ break;
+
+ n_tokens++;
+ }
+
+ values_resized = (uint32_t *) rte_realloc(values,
+ sizeof(uint32_t) * (n_tokens + 1), 0);
+
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+
+ *data = values_resized;
+
+ return 0;
+}
+
+/* convert turbo decoder flag from string to unsigned long int*/
+static int
+op_decoder_flag_strtoul(char *token, uint32_t *op_flag_value)
+{
+ if (!strcmp(token, "RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE"))
+ *op_flag_value = RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_CRC_TYPE_24B"))
+ *op_flag_value = RTE_BBDEV_TURBO_CRC_TYPE_24B;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_EQUALIZER"))
+ *op_flag_value = RTE_BBDEV_TURBO_EQUALIZER;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_SOFT_OUT_SATURATE"))
+ *op_flag_value = RTE_BBDEV_TURBO_SOFT_OUT_SATURATE;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_HALF_ITERATION_EVEN"))
+ *op_flag_value = RTE_BBDEV_TURBO_HALF_ITERATION_EVEN;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH"))
+ *op_flag_value = RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_SOFT_OUTPUT"))
+ *op_flag_value = RTE_BBDEV_TURBO_SOFT_OUTPUT;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_EARLY_TERMINATION"))
+ *op_flag_value = RTE_BBDEV_TURBO_EARLY_TERMINATION;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN"))
+ *op_flag_value = RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN"))
+ *op_flag_value = RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT"))
+ *op_flag_value = RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT"))
+ *op_flag_value = RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_MAP_DEC"))
+ *op_flag_value = RTE_BBDEV_TURBO_MAP_DEC;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_DEC_SCATTER_GATHER"))
+ *op_flag_value = RTE_BBDEV_TURBO_DEC_SCATTER_GATHER;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP"))
+ *op_flag_value = RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP;
+ else {
+ printf("The given value is not a turbo decoder flag\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* convert LDPC flag from string to unsigned long int*/
+static int
+op_ldpc_decoder_flag_strtoul(char *token, uint32_t *op_flag_value)
+{
+ if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS"))
+ *op_flag_value = RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_DECODE_BYPASS"))
+ *op_flag_value = RTE_BBDEV_LDPC_DECODE_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_SOFT_OUT_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_SOFT_OUT_ENABLE;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS"))
+ *op_flag_value = RTE_BBDEV_LDPC_SOFT_OUT_RM_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS"))
+ *op_flag_value = RTE_BBDEV_LDPC_SOFT_OUT_DEINTERLEAVER_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_DEC_INTERRUPTS"))
+ *op_flag_value = RTE_BBDEV_LDPC_DEC_INTERRUPTS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_DEC_SCATTER_GATHER"))
+ *op_flag_value = RTE_BBDEV_LDPC_DEC_SCATTER_GATHER;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION"))
+ *op_flag_value = RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_LLR_COMPRESSION"))
+ *op_flag_value = RTE_BBDEV_LDPC_LLR_COMPRESSION;
+ else if (!strcmp(token,
+ "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
+ else if (!strcmp(token,
+ "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE"))
+ *op_flag_value = RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
+ else if (!strcmp(token,
+ "RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK"))
+ *op_flag_value = RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
+ else {
+ printf("The given value is not a LDPC decoder flag\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* convert turbo encoder flag from string to unsigned long int*/
+static int
+op_encoder_flag_strtoul(char *token, uint32_t *op_flag_value)
+{
+ if (!strcmp(token, "RTE_BBDEV_TURBO_RV_INDEX_BYPASS"))
+ *op_flag_value = RTE_BBDEV_TURBO_RV_INDEX_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_RATE_MATCH"))
+ *op_flag_value = RTE_BBDEV_TURBO_RATE_MATCH;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_CRC_24B_ATTACH"))
+ *op_flag_value = RTE_BBDEV_TURBO_CRC_24B_ATTACH;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_CRC_24A_ATTACH"))
+ *op_flag_value = RTE_BBDEV_TURBO_CRC_24A_ATTACH;
+ else if (!strcmp(token, "RTE_BBDEV_TURBO_ENC_SCATTER_GATHER"))
+ *op_flag_value = RTE_BBDEV_TURBO_ENC_SCATTER_GATHER;
+ else {
+ printf("The given value is not a turbo encoder flag\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* convert LDPC encoder flag from string to unsigned long int*/
+static int
+op_ldpc_encoder_flag_strtoul(char *token, uint32_t *op_flag_value)
+{
+ if (!strcmp(token, "RTE_BBDEV_LDPC_INTERLEAVER_BYPASS"))
+ *op_flag_value = RTE_BBDEV_LDPC_INTERLEAVER_BYPASS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_RATE_MATCH"))
+ *op_flag_value = RTE_BBDEV_LDPC_RATE_MATCH;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_24A_ATTACH"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_24A_ATTACH;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_24B_ATTACH"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_24B_ATTACH;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_CRC_16_ATTACH"))
+ *op_flag_value = RTE_BBDEV_LDPC_CRC_16_ATTACH;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_ENC_INTERRUPTS"))
+ *op_flag_value = RTE_BBDEV_LDPC_ENC_INTERRUPTS;
+ else if (!strcmp(token, "RTE_BBDEV_LDPC_ENC_SCATTER_GATHER"))
+ *op_flag_value = RTE_BBDEV_LDPC_ENC_SCATTER_GATHER;
+ else {
+ printf("The given value is not a turbo encoder flag\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* tokenization turbo decoder/encoder flags values separated by a comma */
+static int
+parse_turbo_flags(char *tokens, uint32_t *op_flags,
+ enum rte_bbdev_op_type op_type)
+{
+ char *tok = NULL;
+ uint32_t op_flag_value = 0;
+
+ tok = strtok(tokens, VALUE_DELIMITER);
+ if (tok == NULL)
+ return -1;
+
+ while (tok != NULL) {
+ trim_space(tok);
+ if (op_type == RTE_BBDEV_OP_TURBO_DEC) {
+ if (op_decoder_flag_strtoul(tok, &op_flag_value) == -1)
+ return -1;
+ } else if (op_type == RTE_BBDEV_OP_TURBO_ENC) {
+ if (op_encoder_flag_strtoul(tok, &op_flag_value) == -1)
+ return -1;
+ } else if (op_type == RTE_BBDEV_OP_LDPC_ENC) {
+ if (op_ldpc_encoder_flag_strtoul(tok, &op_flag_value)
+ == -1)
+ return -1;
+ } else if (op_type == RTE_BBDEV_OP_LDPC_DEC) {
+ if (op_ldpc_decoder_flag_strtoul(tok, &op_flag_value)
+ == -1)
+ return -1;
+ } else {
+ return -1;
+ }
+
+ *op_flags = *op_flags | op_flag_value;
+
+ tok = strtok(NULL, VALUE_DELIMITER);
+ if (tok == NULL)
+ break;
+ }
+
+ return 0;
+}
+
+/* convert turbo encoder/decoder op_type from string to enum*/
+static int
+op_turbo_type_strtol(char *token, enum rte_bbdev_op_type *op_type)
+{
+ trim_space(token);
+ if (!strcmp(token, "RTE_BBDEV_OP_TURBO_DEC"))
+ *op_type = RTE_BBDEV_OP_TURBO_DEC;
+ else if (!strcmp(token, "RTE_BBDEV_OP_TURBO_ENC"))
+ *op_type = RTE_BBDEV_OP_TURBO_ENC;
+ else if (!strcmp(token, "RTE_BBDEV_OP_LDPC_ENC"))
+ *op_type = RTE_BBDEV_OP_LDPC_ENC;
+ else if (!strcmp(token, "RTE_BBDEV_OP_LDPC_DEC"))
+ *op_type = RTE_BBDEV_OP_LDPC_DEC;
+ else if (!strcmp(token, "RTE_BBDEV_OP_NONE"))
+ *op_type = RTE_BBDEV_OP_NONE;
+ else {
+ printf("Not valid turbo op_type: '%s'\n", token);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* tokenization expected status values separated by a comma */
+static int
+parse_expected_status(char *tokens, int *status, enum rte_bbdev_op_type op_type)
+{
+ char *tok = NULL;
+ bool status_ok = false;
+
+ tok = strtok(tokens, VALUE_DELIMITER);
+ if (tok == NULL)
+ return -1;
+
+ while (tok != NULL) {
+ trim_space(tok);
+ if (!strcmp(tok, "OK"))
+ status_ok = true;
+ else if (!strcmp(tok, "DMA"))
+ *status = *status | (1 << RTE_BBDEV_DRV_ERROR);
+ else if (!strcmp(tok, "FCW"))
+ *status = *status | (1 << RTE_BBDEV_DATA_ERROR);
+ else if (!strcmp(tok, "SYNCRC")) {
+ *status = *status | (1 << RTE_BBDEV_SYNDROME_ERROR);
+ *status = *status | (1 << RTE_BBDEV_CRC_ERROR);
+ } else if (!strcmp(tok, "SYN"))
+ *status = *status | (1 << RTE_BBDEV_SYNDROME_ERROR);
+ else if (!strcmp(tok, "CRC")) {
+ if ((op_type == RTE_BBDEV_OP_TURBO_DEC) ||
+ (op_type == RTE_BBDEV_OP_LDPC_DEC))
+ *status = *status | (1 << RTE_BBDEV_CRC_ERROR);
+ else {
+ printf(
+ "CRC is only a valid value for decoder\n");
+ return -1;
+ }
+ } else {
+ printf("Not valid status: '%s'\n", tok);
+ return -1;
+ }
+
+ tok = strtok(NULL, VALUE_DELIMITER);
+ if (tok == NULL)
+ break;
+ }
+
+ if (status_ok && *status != 0) {
+ printf(
+ "Not valid status values. Cannot be OK and ERROR at the same time.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* parse ops data entry (there can be more than 1 input entry, each will be
+ * contained in a separate op_data_buf struct)
+ */
+static int
+parse_data_entry(const char *key_token, char *token,
+ struct test_bbdev_vector *vector, enum op_data_type type,
+ const char *prefix)
+{
+ int ret;
+ uint32_t data_length = 0;
+ uint32_t *data = NULL;
+ unsigned int id;
+ struct op_data_buf *op_data;
+ unsigned int *nb_ops;
+
+ if (type >= DATA_NUM_TYPES) {
+ printf("Unknown op type: %d!\n", type);
+ return -1;
+ }
+
+ op_data = vector->entries[type].segments;
+ nb_ops = &vector->entries[type].nb_segments;
+
+ if (*nb_ops >= RTE_BBDEV_TURBO_MAX_CODE_BLOCKS) {
+ printf("Too many segments (code blocks defined): %u, max %d!\n",
+ *nb_ops, RTE_BBDEV_TURBO_MAX_CODE_BLOCKS);
+ return -1;
+ }
+
+ if (sscanf(key_token + strlen(prefix), "%u", &id) != 1) {
+ printf("Missing ID of %s\n", prefix);
+ return -1;
+ }
+ if (id != *nb_ops) {
+ printf(
+ "Please order data entries sequentially, i.e. %s0, %s1, ...\n",
+ prefix, prefix);
+ return -1;
+ }
+
+ /* Clear new op data struct */
+ memset(op_data + *nb_ops, 0, sizeof(struct op_data_buf));
+
+ ret = parse_values(token, &data, &data_length);
+ if (!ret) {
+ op_data[*nb_ops].addr = data;
+ op_data[*nb_ops].length = data_length;
+ ++(*nb_ops);
+ }
+
+ return ret;
+}
+
+/* parses turbo decoder parameters and assigns to global variable */
+static int
+parse_decoder_params(const char *key_token, char *token,
+ struct test_bbdev_vector *vector)
+{
+ int ret = 0, status = 0;
+ uint32_t op_flags = 0;
+ char *err = NULL;
+
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &vector->turbo_dec;
+
+ /* compare keys */
+ if (starts_with(key_token, op_data_prefixes[DATA_INPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_INPUT, op_data_prefixes[DATA_INPUT]);
+
+ else if (starts_with(key_token, op_data_prefixes[DATA_SOFT_OUTPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_SOFT_OUTPUT,
+ op_data_prefixes[DATA_SOFT_OUTPUT]);
+
+ else if (starts_with(key_token, op_data_prefixes[DATA_HARD_OUTPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARD_OUTPUT,
+ op_data_prefixes[DATA_HARD_OUTPUT]);
+ else if (!strcmp(key_token, "e")) {
+ vector->mask |= TEST_BBDEV_VF_E;
+ turbo_dec->cb_params.e = (uint32_t) strtoul(token, &err, 0);
+ } else if (!strcmp(key_token, "ea")) {
+ vector->mask |= TEST_BBDEV_VF_EA;
+ turbo_dec->tb_params.ea = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "eb")) {
+ vector->mask |= TEST_BBDEV_VF_EB;
+ turbo_dec->tb_params.eb = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k")) {
+ vector->mask |= TEST_BBDEV_VF_K;
+ turbo_dec->cb_params.k = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k_pos")) {
+ vector->mask |= TEST_BBDEV_VF_K_POS;
+ turbo_dec->tb_params.k_pos = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k_neg")) {
+ vector->mask |= TEST_BBDEV_VF_K_NEG;
+ turbo_dec->tb_params.k_neg = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c")) {
+ vector->mask |= TEST_BBDEV_VF_C;
+ turbo_dec->tb_params.c = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c_neg")) {
+ vector->mask |= TEST_BBDEV_VF_C_NEG;
+ turbo_dec->tb_params.c_neg = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "cab")) {
+ vector->mask |= TEST_BBDEV_VF_CAB;
+ turbo_dec->tb_params.cab = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "rv_index")) {
+ vector->mask |= TEST_BBDEV_VF_RV_INDEX;
+ turbo_dec->rv_index = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "iter_max")) {
+ vector->mask |= TEST_BBDEV_VF_ITER_MAX;
+ turbo_dec->iter_max = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "iter_min")) {
+ vector->mask |= TEST_BBDEV_VF_ITER_MIN;
+ turbo_dec->iter_min = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "expected_iter_count")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_ITER_COUNT;
+ turbo_dec->iter_count = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ext_scale")) {
+ vector->mask |= TEST_BBDEV_VF_EXT_SCALE;
+ turbo_dec->ext_scale = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "num_maps")) {
+ vector->mask |= TEST_BBDEV_VF_NUM_MAPS;
+ turbo_dec->num_maps = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "r")) {
+ vector->mask |= TEST_BBDEV_VF_R;
+ turbo_dec->tb_params.r = (uint8_t)strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "code_block_mode")) {
+ vector->mask |= TEST_BBDEV_VF_CODE_BLOCK_MODE;
+ turbo_dec->code_block_mode = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "op_flags")) {
+ vector->mask |= TEST_BBDEV_VF_OP_FLAGS;
+ ret = parse_turbo_flags(token, &op_flags,
+ vector->op_type);
+ if (!ret)
+ turbo_dec->op_flags = op_flags;
+ } else if (!strcmp(key_token, "expected_status")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_STATUS;
+ ret = parse_expected_status(token, &status, vector->op_type);
+ if (!ret)
+ vector->expected_status = status;
+ } else {
+ printf("Not valid dec key: '%s'\n", key_token);
+ return -1;
+ }
+
+ if (ret != 0) {
+ printf("Failed with convert '%s\t%s'\n", key_token, token);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* parses turbo encoder parameters and assigns to global variable */
+static int
+parse_encoder_params(const char *key_token, char *token,
+ struct test_bbdev_vector *vector)
+{
+ int ret = 0, status = 0;
+ uint32_t op_flags = 0;
+ char *err = NULL;
+
+
+ struct rte_bbdev_op_turbo_enc *turbo_enc = &vector->turbo_enc;
+
+ if (starts_with(key_token, op_data_prefixes[DATA_INPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_INPUT, op_data_prefixes[DATA_INPUT]);
+ else if (starts_with(key_token, "output"))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARD_OUTPUT, "output");
+ else if (!strcmp(key_token, "e")) {
+ vector->mask |= TEST_BBDEV_VF_E;
+ turbo_enc->cb_params.e = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ea")) {
+ vector->mask |= TEST_BBDEV_VF_EA;
+ turbo_enc->tb_params.ea = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "eb")) {
+ vector->mask |= TEST_BBDEV_VF_EB;
+ turbo_enc->tb_params.eb = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k")) {
+ vector->mask |= TEST_BBDEV_VF_K;
+ turbo_enc->cb_params.k = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k_neg")) {
+ vector->mask |= TEST_BBDEV_VF_K_NEG;
+ turbo_enc->tb_params.k_neg = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "k_pos")) {
+ vector->mask |= TEST_BBDEV_VF_K_POS;
+ turbo_enc->tb_params.k_pos = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c_neg")) {
+ vector->mask |= TEST_BBDEV_VF_C_NEG;
+ turbo_enc->tb_params.c_neg = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c")) {
+ vector->mask |= TEST_BBDEV_VF_C;
+ turbo_enc->tb_params.c = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "cab")) {
+ vector->mask |= TEST_BBDEV_VF_CAB;
+ turbo_enc->tb_params.cab = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "rv_index")) {
+ vector->mask |= TEST_BBDEV_VF_RV_INDEX;
+ turbo_enc->rv_index = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ncb")) {
+ vector->mask |= TEST_BBDEV_VF_NCB;
+ turbo_enc->cb_params.ncb = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ncb_neg")) {
+ vector->mask |= TEST_BBDEV_VF_NCB_NEG;
+ turbo_enc->tb_params.ncb_neg =
+ (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ncb_pos")) {
+ vector->mask |= TEST_BBDEV_VF_NCB_POS;
+ turbo_enc->tb_params.ncb_pos =
+ (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "r")) {
+ vector->mask |= TEST_BBDEV_VF_R;
+ turbo_enc->tb_params.r = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "code_block_mode")) {
+ vector->mask |= TEST_BBDEV_VF_CODE_BLOCK_MODE;
+ turbo_enc->code_block_mode = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "op_flags")) {
+ vector->mask |= TEST_BBDEV_VF_OP_FLAGS;
+ ret = parse_turbo_flags(token, &op_flags,
+ vector->op_type);
+ if (!ret)
+ turbo_enc->op_flags = op_flags;
+ } else if (!strcmp(key_token, "expected_status")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_STATUS;
+ ret = parse_expected_status(token, &status, vector->op_type);
+ if (!ret)
+ vector->expected_status = status;
+ } else {
+ printf("Not valid enc key: '%s'\n", key_token);
+ return -1;
+ }
+
+ if (ret != 0) {
+ printf("Failed with convert '%s\t%s'\n", key_token, token);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* parses LDPC encoder parameters and assigns to global variable */
+static int
+parse_ldpc_encoder_params(const char *key_token, char *token,
+ struct test_bbdev_vector *vector)
+{
+ int ret = 0, status = 0;
+ uint32_t op_flags = 0;
+ char *err = NULL;
+
+ struct rte_bbdev_op_ldpc_enc *ldpc_enc = &vector->ldpc_enc;
+
+ if (starts_with(key_token, op_data_prefixes[DATA_INPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_INPUT,
+ op_data_prefixes[DATA_INPUT]);
+ else if (starts_with(key_token, "output"))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARD_OUTPUT,
+ "output");
+ else if (!strcmp(key_token, "e")) {
+ vector->mask |= TEST_BBDEV_VF_E;
+ ldpc_enc->cb_params.e = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ea")) {
+ vector->mask |= TEST_BBDEV_VF_EA;
+ ldpc_enc->tb_params.ea = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "eb")) {
+ vector->mask |= TEST_BBDEV_VF_EB;
+ ldpc_enc->tb_params.eb = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c")) {
+ vector->mask |= TEST_BBDEV_VF_C;
+ ldpc_enc->tb_params.c = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "cab")) {
+ vector->mask |= TEST_BBDEV_VF_CAB;
+ ldpc_enc->tb_params.cab = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "rv_index")) {
+ vector->mask |= TEST_BBDEV_VF_RV_INDEX;
+ ldpc_enc->rv_index = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "n_cb")) {
+ vector->mask |= TEST_BBDEV_VF_NCB;
+ ldpc_enc->n_cb = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "r")) {
+ vector->mask |= TEST_BBDEV_VF_R;
+ ldpc_enc->tb_params.r = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "q_m")) {
+ vector->mask |= TEST_BBDEV_VF_QM;
+ ldpc_enc->q_m = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "basegraph")) {
+ vector->mask |= TEST_BBDEV_VF_BG;
+ ldpc_enc->basegraph = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "z_c")) {
+ vector->mask |= TEST_BBDEV_VF_ZC;
+ ldpc_enc->z_c = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "n_filler")) {
+ vector->mask |= TEST_BBDEV_VF_F;
+ ldpc_enc->n_filler = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "code_block_mode")) {
+ vector->mask |= TEST_BBDEV_VF_CODE_BLOCK_MODE;
+ ldpc_enc->code_block_mode = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "op_flags")) {
+ vector->mask |= TEST_BBDEV_VF_OP_FLAGS;
+ ret = parse_turbo_flags(token, &op_flags, vector->op_type);
+ if (!ret)
+ ldpc_enc->op_flags = op_flags;
+ } else if (!strcmp(key_token, "expected_status")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_STATUS;
+ ret = parse_expected_status(token, &status, vector->op_type);
+ if (!ret)
+ vector->expected_status = status;
+ } else {
+ printf("Not valid ldpc enc key: '%s'\n", key_token);
+ return -1;
+ }
+
+ if (ret != 0) {
+ printf("Failed with convert '%s\t%s'\n", key_token, token);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* parses LDPC decoder parameters and assigns to global variable */
+static int
+parse_ldpc_decoder_params(const char *key_token, char *token,
+ struct test_bbdev_vector *vector)
+{
+ int ret = 0, status = 0;
+ uint32_t op_flags = 0;
+ char *err = NULL;
+
+ struct rte_bbdev_op_ldpc_dec *ldpc_dec = &vector->ldpc_dec;
+
+ if (starts_with(key_token, op_data_prefixes[DATA_INPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_INPUT,
+ op_data_prefixes[DATA_INPUT]);
+ else if (starts_with(key_token, "output"))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARD_OUTPUT,
+ "output");
+ else if (starts_with(key_token, op_data_prefixes[DATA_HARQ_INPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARQ_INPUT,
+ op_data_prefixes[DATA_HARQ_INPUT]);
+ else if (starts_with(key_token, op_data_prefixes[DATA_HARQ_OUTPUT]))
+ ret = parse_data_entry(key_token, token, vector,
+ DATA_HARQ_OUTPUT,
+ op_data_prefixes[DATA_HARQ_OUTPUT]);
+ else if (!strcmp(key_token, "e")) {
+ vector->mask |= TEST_BBDEV_VF_E;
+ ldpc_dec->cb_params.e = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "ea")) {
+ vector->mask |= TEST_BBDEV_VF_EA;
+ ldpc_dec->tb_params.ea = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "eb")) {
+ vector->mask |= TEST_BBDEV_VF_EB;
+ ldpc_dec->tb_params.eb = (uint32_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "c")) {
+ vector->mask |= TEST_BBDEV_VF_C;
+ ldpc_dec->tb_params.c = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "cab")) {
+ vector->mask |= TEST_BBDEV_VF_CAB;
+ ldpc_dec->tb_params.cab = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "rv_index")) {
+ vector->mask |= TEST_BBDEV_VF_RV_INDEX;
+ ldpc_dec->rv_index = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "n_cb")) {
+ vector->mask |= TEST_BBDEV_VF_NCB;
+ ldpc_dec->n_cb = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "r")) {
+ vector->mask |= TEST_BBDEV_VF_R;
+ ldpc_dec->tb_params.r = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "q_m")) {
+ vector->mask |= TEST_BBDEV_VF_QM;
+ ldpc_dec->q_m = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "basegraph")) {
+ vector->mask |= TEST_BBDEV_VF_BG;
+ ldpc_dec->basegraph = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "z_c")) {
+ vector->mask |= TEST_BBDEV_VF_ZC;
+ ldpc_dec->z_c = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "n_filler")) {
+ vector->mask |= TEST_BBDEV_VF_F;
+ ldpc_dec->n_filler = (uint16_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "expected_iter_count")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_ITER_COUNT;
+ ldpc_dec->iter_count = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "iter_max")) {
+ vector->mask |= TEST_BBDEV_VF_ITER_MAX;
+ ldpc_dec->iter_max = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "code_block_mode")) {
+ vector->mask |= TEST_BBDEV_VF_CODE_BLOCK_MODE;
+ ldpc_dec->code_block_mode = (uint8_t) strtoul(token, &err, 0);
+ ret = ((err == NULL) || (*err != '\0')) ? -1 : 0;
+ } else if (!strcmp(key_token, "op_flags")) {
+ vector->mask |= TEST_BBDEV_VF_OP_FLAGS;
+ ret = parse_turbo_flags(token, &op_flags, vector->op_type);
+ if (!ret)
+ ldpc_dec->op_flags = op_flags;
+ } else if (!strcmp(key_token, "expected_status")) {
+ vector->mask |= TEST_BBDEV_VF_EXPECTED_STATUS;
+ ret = parse_expected_status(token, &status, vector->op_type);
+ if (!ret)
+ vector->expected_status = status;
+ } else {
+ printf("Not valid ldpc dec key: '%s'\n", key_token);
+ return -1;
+ }
+
+ if (ret != 0) {
+ printf("Failed with convert '%s\t%s'\n", key_token, token);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* checks the type of key and assigns data */
+static int
+parse_entry(char *entry, struct test_bbdev_vector *vector)
+{
+ int ret = 0;
+ char *token, *key_token;
+ enum rte_bbdev_op_type op_type = RTE_BBDEV_OP_NONE;
+
+ if (entry == NULL) {
+ printf("Expected entry value\n");
+ return -1;
+ }
+
+ /* get key */
+ token = strtok(entry, ENTRY_DELIMITER);
+ key_token = token;
+ /* get values for key */
+ token = strtok(NULL, ENTRY_DELIMITER);
+
+ if (key_token == NULL || token == NULL) {
+ printf("Expected 'key = values' but was '%.40s'..\n", entry);
+ return -1;
+ }
+ trim_space(key_token);
+
+ /* first key_token has to specify type of operation */
+ if (vector->op_type == RTE_BBDEV_OP_NONE) {
+ if (!strcmp(key_token, "op_type")) {
+ ret = op_turbo_type_strtol(token, &op_type);
+ if (!ret)
+ vector->op_type = op_type;
+ return (!ret) ? 0 : -1;
+ }
+ printf("First key_token (%s) does not specify op_type\n",
+ key_token);
+ return -1;
+ }
+
+ /* compare keys */
+ if (vector->op_type == RTE_BBDEV_OP_TURBO_DEC) {
+ if (parse_decoder_params(key_token, token, vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_TURBO_ENC) {
+ if (parse_encoder_params(key_token, token, vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_LDPC_ENC) {
+ if (parse_ldpc_encoder_params(key_token, token, vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_LDPC_DEC) {
+ if (parse_ldpc_decoder_params(key_token, token, vector) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+check_decoder_segments(struct test_bbdev_vector *vector)
+{
+ unsigned char i;
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &vector->turbo_dec;
+
+ if (vector->entries[DATA_INPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_INPUT].nb_segments; i++)
+ if (vector->entries[DATA_INPUT].segments[i].addr == NULL)
+ return -1;
+
+ if (vector->entries[DATA_HARD_OUTPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_HARD_OUTPUT].nb_segments;
+ i++)
+ if (vector->entries[DATA_HARD_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ if ((turbo_dec->op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
+ (vector->entries[DATA_SOFT_OUTPUT].nb_segments == 0))
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_SOFT_OUTPUT].nb_segments;
+ i++)
+ if (vector->entries[DATA_SOFT_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int
+check_ldpc_decoder_segments(struct test_bbdev_vector *vector)
+{
+ unsigned char i;
+ struct rte_bbdev_op_ldpc_dec *ldpc_dec = &vector->ldpc_dec;
+
+ for (i = 0; i < vector->entries[DATA_INPUT].nb_segments; i++)
+ if (vector->entries[DATA_INPUT].segments[i].addr == NULL)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_HARD_OUTPUT].nb_segments; i++)
+ if (vector->entries[DATA_HARD_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ if ((ldpc_dec->op_flags & RTE_BBDEV_LDPC_SOFT_OUT_ENABLE) &&
+ (vector->entries[DATA_SOFT_OUTPUT].nb_segments == 0))
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_SOFT_OUTPUT].nb_segments; i++)
+ if (vector->entries[DATA_SOFT_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ if ((ldpc_dec->op_flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE) &&
+ (vector->entries[DATA_HARQ_OUTPUT].nb_segments == 0))
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_HARQ_OUTPUT].nb_segments; i++)
+ if (vector->entries[DATA_HARQ_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int
+check_decoder_llr_spec(struct test_bbdev_vector *vector)
+{
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &vector->turbo_dec;
+
+ /* Check input LLR sign formalism specification */
+ if ((turbo_dec->op_flags & RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN) &&
+ (turbo_dec->op_flags &
+ RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN)) {
+ printf(
+ "Both positive and negative LLR input flags were set!\n");
+ return -1;
+ }
+ if (!(turbo_dec->op_flags & RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN) &&
+ !(turbo_dec->op_flags &
+ RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN)) {
+ printf(
+ "INFO: input LLR sign formalism was not specified and will be set to negative LLR for '1' bit\n");
+ turbo_dec->op_flags |= RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN;
+ }
+
+ if (!(turbo_dec->op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT))
+ return 0;
+
+ /* Check output LLR sign formalism specification */
+ if ((turbo_dec->op_flags & RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT) &&
+ (turbo_dec->op_flags &
+ RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT)) {
+ printf(
+ "Both positive and negative LLR output flags were set!\n");
+ return -1;
+ }
+ if (!(turbo_dec->op_flags & RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT) &&
+ !(turbo_dec->op_flags &
+ RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT)) {
+ printf(
+ "INFO: soft output LLR sign formalism was not specified and will be set to negative LLR for '1' bit\n");
+ turbo_dec->op_flags |=
+ RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
+ }
+
+ return 0;
+}
+
+static int
+check_decoder_op_flags(struct test_bbdev_vector *vector)
+{
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &vector->turbo_dec;
+
+ if ((turbo_dec->op_flags & RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP) &&
+ !(turbo_dec->op_flags & RTE_BBDEV_TURBO_CRC_TYPE_24B)) {
+ printf(
+ "WARNING: RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP flag is missing RTE_BBDEV_TURBO_CRC_TYPE_24B\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* checks decoder parameters */
+static int
+check_decoder(struct test_bbdev_vector *vector)
+{
+ struct rte_bbdev_op_turbo_dec *turbo_dec = &vector->turbo_dec;
+ const int mask = vector->mask;
+
+ if (check_decoder_segments(vector) < 0)
+ return -1;
+
+ if (check_decoder_llr_spec(vector) < 0)
+ return -1;
+
+ if (check_decoder_op_flags(vector) < 0)
+ return -1;
+
+ /* Check which params were set */
+ if (!(mask & TEST_BBDEV_VF_CODE_BLOCK_MODE)) {
+ printf(
+ "WARNING: code_block_mode was not specified in vector file and will be set to 1 (0 - TB Mode, 1 - CB mode)\n");
+ turbo_dec->code_block_mode = 1;
+ }
+ if (turbo_dec->code_block_mode == 0) {
+ if (!(mask & TEST_BBDEV_VF_EA))
+ printf(
+ "WARNING: ea was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_EB))
+ printf(
+ "WARNING: eb was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K_NEG))
+ printf(
+ "WARNING: k_neg was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K_POS))
+ printf(
+ "WARNING: k_pos was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_C_NEG))
+ printf(
+ "WARNING: c_neg was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_C)) {
+ printf(
+ "WARNING: c was not specified in vector file and will be set to 1\n");
+ turbo_dec->tb_params.c = 1;
+ }
+ if (!(mask & TEST_BBDEV_VF_CAB))
+ printf(
+ "WARNING: cab was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_R))
+ printf(
+ "WARNING: r was not specified in vector file and will be set to 0\n");
+ } else {
+ if (!(mask & TEST_BBDEV_VF_E))
+ printf(
+ "WARNING: e was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K))
+ printf(
+ "WARNING: k was not specified in vector file and will be set to 0\n");
+ }
+ if (!(mask & TEST_BBDEV_VF_RV_INDEX))
+ printf(
+ "INFO: rv_index was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_ITER_MIN))
+ printf(
+ "WARNING: iter_min was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_ITER_MAX))
+ printf(
+ "WARNING: iter_max was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT))
+ printf(
+ "WARNING: expected_iter_count was not specified in vector file and iter_count will not be validated\n");
+ if (!(mask & TEST_BBDEV_VF_EXT_SCALE))
+ printf(
+ "WARNING: ext_scale was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_OP_FLAGS)) {
+ printf(
+ "WARNING: op_flags was not specified in vector file and capabilities will not be validated\n");
+ turbo_dec->num_maps = 0;
+ } else if (!(turbo_dec->op_flags & RTE_BBDEV_TURBO_MAP_DEC) &&
+ mask & TEST_BBDEV_VF_NUM_MAPS) {
+ printf(
+ "INFO: RTE_BBDEV_TURBO_MAP_DEC was not set in vector file and num_maps will be set to 0\n");
+ turbo_dec->num_maps = 0;
+ }
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_STATUS))
+ printf(
+ "WARNING: expected_status was not specified in vector file and will be set to 0\n");
+ return 0;
+}
+
+/* checks LDPC decoder parameters */
+static int
+check_ldpc_decoder(struct test_bbdev_vector *vector)
+{
+ struct rte_bbdev_op_ldpc_dec *ldpc_dec = &vector->ldpc_dec;
+ const int mask = vector->mask;
+
+ if (check_ldpc_decoder_segments(vector) < 0)
+ return -1;
+
+ /*
+ * if (check_ldpc_decoder_llr_spec(vector) < 0)
+ * return -1;
+ *
+ * if (check_ldpc_decoder_op_flags(vector) < 0)
+ * return -1;
+ */
+
+ /* Check which params were set */
+ if (!(mask & TEST_BBDEV_VF_CODE_BLOCK_MODE)) {
+ printf(
+ "WARNING: code_block_mode was not specified in vector file and will be set to 1 (0 - TB Mode, 1 - CB mode)\n");
+ ldpc_dec->code_block_mode = 1;
+ }
+ if (ldpc_dec->code_block_mode == 0) {
+ if (!(mask & TEST_BBDEV_VF_EA))
+ printf(
+ "WARNING: ea was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_EB))
+ printf(
+ "WARNING: eb was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_C)) {
+ printf(
+ "WARNING: c was not specified in vector file and will be set to 1\n");
+ ldpc_dec->tb_params.c = 1;
+ }
+ if (!(mask & TEST_BBDEV_VF_CAB))
+ printf(
+ "WARNING: cab was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_R))
+ printf(
+ "WARNING: r was not specified in vector file and will be set to 0\n");
+ } else {
+ if (!(mask & TEST_BBDEV_VF_E))
+ printf(
+ "WARNING: e was not specified in vector file and will be set to 0\n");
+ }
+ if (!(mask & TEST_BBDEV_VF_RV_INDEX))
+ printf(
+ "INFO: rv_index was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_ITER_MAX))
+ printf(
+ "WARNING: iter_max was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT))
+ printf(
+ "WARNING: expected_iter_count was not specified in vector file and iter_count will not be validated\n");
+ if (!(mask & TEST_BBDEV_VF_OP_FLAGS)) {
+ printf(
+ "WARNING: op_flags was not specified in vector file and capabilities will not be validated\n");
+ }
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_STATUS))
+ printf(
+ "WARNING: expected_status was not specified in vector file and will be set to 0\n");
+ return 0;
+}
+
+/* checks encoder parameters */
+static int
+check_encoder(struct test_bbdev_vector *vector)
+{
+ unsigned char i;
+ const int mask = vector->mask;
+
+ if (vector->entries[DATA_INPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_INPUT].nb_segments; i++)
+ if (vector->entries[DATA_INPUT].segments[i].addr == NULL)
+ return -1;
+
+ if (vector->entries[DATA_HARD_OUTPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_HARD_OUTPUT].nb_segments; i++)
+ if (vector->entries[DATA_HARD_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ if (!(mask & TEST_BBDEV_VF_CODE_BLOCK_MODE)) {
+ printf(
+ "WARNING: code_block_mode was not specified in vector file and will be set to 1\n");
+ vector->turbo_enc.code_block_mode = 1;
+ }
+ if (vector->turbo_enc.code_block_mode == 0) {
+ if (!(mask & TEST_BBDEV_VF_EA) && (vector->turbo_enc.op_flags &
+ RTE_BBDEV_TURBO_RATE_MATCH))
+ printf(
+ "WARNING: ea was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_EB) && (vector->turbo_enc.op_flags &
+ RTE_BBDEV_TURBO_RATE_MATCH))
+ printf(
+ "WARNING: eb was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K_NEG))
+ printf(
+ "WARNING: k_neg was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K_POS))
+ printf(
+ "WARNING: k_pos was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_C_NEG))
+ printf(
+ "WARNING: c_neg was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_C)) {
+ printf(
+ "WARNING: c was not specified in vector file and will be set to 1\n");
+ vector->turbo_enc.tb_params.c = 1;
+ }
+ if (!(mask & TEST_BBDEV_VF_CAB) && (vector->turbo_enc.op_flags &
+ RTE_BBDEV_TURBO_RATE_MATCH))
+ printf(
+ "WARNING: cab was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_NCB_NEG))
+ printf(
+ "WARNING: ncb_neg was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_NCB_POS))
+ printf(
+ "WARNING: ncb_pos was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_R))
+ printf(
+ "WARNING: r was not specified in vector file and will be set to 0\n");
+ } else {
+ if (!(mask & TEST_BBDEV_VF_E) && (vector->turbo_enc.op_flags &
+ RTE_BBDEV_TURBO_RATE_MATCH))
+ printf(
+ "WARNING: e was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_K))
+ printf(
+ "WARNING: k was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_NCB))
+ printf(
+ "WARNING: ncb was not specified in vector file and will be set to 0\n");
+ }
+ if (!(mask & TEST_BBDEV_VF_RV_INDEX))
+ printf(
+ "INFO: rv_index was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_OP_FLAGS))
+ printf(
+ "INFO: op_flags was not specified in vector file and capabilities will not be validated\n");
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_STATUS))
+ printf(
+ "WARNING: expected_status was not specified in vector file and will be set to 0\n");
+
+ return 0;
+}
+
+
+/* checks encoder parameters */
+static int
+check_ldpc_encoder(struct test_bbdev_vector *vector)
+{
+ unsigned char i;
+ const int mask = vector->mask;
+
+ if (vector->entries[DATA_INPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_INPUT].nb_segments; i++)
+ if (vector->entries[DATA_INPUT].segments[i].addr == NULL)
+ return -1;
+
+ if (vector->entries[DATA_HARD_OUTPUT].nb_segments == 0)
+ return -1;
+
+ for (i = 0; i < vector->entries[DATA_HARD_OUTPUT].nb_segments; i++)
+ if (vector->entries[DATA_HARD_OUTPUT].segments[i].addr == NULL)
+ return -1;
+
+ if (!(mask & TEST_BBDEV_VF_CODE_BLOCK_MODE)) {
+ printf(
+ "WARNING: code_block_mode was not specified in vector file and will be set to 1\n");
+ vector->turbo_enc.code_block_mode = 1;
+ }
+ if (vector->turbo_enc.code_block_mode == 0) {
+ } else {
+ if (!(mask & TEST_BBDEV_VF_E) && (vector->turbo_enc.op_flags &
+ RTE_BBDEV_TURBO_RATE_MATCH))
+ printf(
+ "WARNING: e was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_NCB))
+ printf(
+ "WARNING: ncb was not specified in vector file and will be set to 0\n");
+ }
+ if (!(mask & TEST_BBDEV_VF_BG))
+ printf(
+ "WARNING: BG was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_ZC))
+ printf(
+ "WARNING: Zc was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_RV_INDEX))
+ printf(
+ "INFO: rv_index was not specified in vector file and will be set to 0\n");
+ if (!(mask & TEST_BBDEV_VF_OP_FLAGS))
+ printf(
+ "INFO: op_flags was not specified in vector file and capabilities will not be validated\n");
+ if (!(mask & TEST_BBDEV_VF_EXPECTED_STATUS))
+ printf(
+ "WARNING: expected_status was not specified in vector file and will be set to 0\n");
+
+ return 0;
+}
+
+static int
+bbdev_check_vector(struct test_bbdev_vector *vector)
+{
+ if (vector->op_type == RTE_BBDEV_OP_TURBO_DEC) {
+ if (check_decoder(vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_TURBO_ENC) {
+ if (check_encoder(vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_LDPC_ENC) {
+ if (check_ldpc_encoder(vector) == -1)
+ return -1;
+ } else if (vector->op_type == RTE_BBDEV_OP_LDPC_DEC) {
+ if (check_ldpc_decoder(vector) == -1)
+ return -1;
+ } else if (vector->op_type != RTE_BBDEV_OP_NONE) {
+ printf("Vector was not filled\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+test_bbdev_vector_read(const char *filename,
+ struct test_bbdev_vector *vector)
+{
+ int ret = 0;
+ size_t len = 0;
+
+ FILE *fp = NULL;
+ char *line = NULL;
+ char *entry = NULL;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ printf("File %s does not exist\n", filename);
+ return -1;
+ }
+
+ while (getline(&line, &len, fp) != -1) {
+
+ /* ignore comments and new lines */
+ if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
+ || line[0] == '\r')
+ continue;
+
+ trim_space(line);
+
+ /* buffer for multiline */
+ entry = realloc(entry, strlen(line) + 1);
+ if (entry == NULL) {
+ printf("Fail to realloc %zu bytes\n", strlen(line) + 1);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ strcpy(entry, line);
+
+ /* check if entry ends with , or = */
+ if (entry[strlen(entry) - 1] == ','
+ || entry[strlen(entry) - 1] == '=') {
+ while (getline(&line, &len, fp) != -1) {
+ trim_space(line);
+
+ /* extend entry about length of new line */
+ char *entry_extended = realloc(entry,
+ strlen(line) +
+ strlen(entry) + 1);
+
+ if (entry_extended == NULL) {
+ printf("Fail to allocate %zu bytes\n",
+ strlen(line) +
+ strlen(entry) + 1);
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ entry = entry_extended;
+ /* entry has been allocated accordingly */
+ strcpy(&entry[strlen(entry)], line);
+
+ if (entry[strlen(entry) - 1] != ',')
+ break;
+ }
+ }
+ ret = parse_entry(entry, vector);
+ if (ret != 0) {
+ printf("An error occurred while parsing!\n");
+ goto exit;
+ }
+ }
+ ret = bbdev_check_vector(vector);
+ if (ret != 0)
+ printf("An error occurred while checking!\n");
+
+exit:
+ fclose(fp);
+ free(line);
+ free(entry);
+
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.h b/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.h
new file mode 100644
index 000000000..4e5dbf5d5
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_bbdev_vector.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef TEST_BBDEV_VECTOR_H_
+#define TEST_BBDEV_VECTOR_H_
+
+#include <rte_bbdev_op.h>
+
+/* Flags which are set when specific parameter is define in vector file */
+enum {
+ TEST_BBDEV_VF_E = (1ULL << 0),
+ TEST_BBDEV_VF_EA = (1ULL << 1),
+ TEST_BBDEV_VF_EB = (1ULL << 2),
+ TEST_BBDEV_VF_K = (1ULL << 3),
+ TEST_BBDEV_VF_K_NEG = (1ULL << 4),
+ TEST_BBDEV_VF_K_POS = (1ULL << 5),
+ TEST_BBDEV_VF_C_NEG = (1ULL << 6),
+ TEST_BBDEV_VF_C = (1ULL << 7),
+ TEST_BBDEV_VF_CAB = (1ULL << 8),
+ TEST_BBDEV_VF_RV_INDEX = (1ULL << 9),
+ TEST_BBDEV_VF_ITER_MAX = (1ULL << 10),
+ TEST_BBDEV_VF_ITER_MIN = (1ULL << 11),
+ TEST_BBDEV_VF_EXPECTED_ITER_COUNT = (1ULL << 12),
+ TEST_BBDEV_VF_EXT_SCALE = (1ULL << 13),
+ TEST_BBDEV_VF_NUM_MAPS = (1ULL << 14),
+ TEST_BBDEV_VF_NCB = (1ULL << 15),
+ TEST_BBDEV_VF_NCB_NEG = (1ULL << 16),
+ TEST_BBDEV_VF_NCB_POS = (1ULL << 17),
+ TEST_BBDEV_VF_R = (1ULL << 18),
+ TEST_BBDEV_VF_BG = (1ULL << 19),
+ TEST_BBDEV_VF_ZC = (1ULL << 20),
+ TEST_BBDEV_VF_F = (1ULL << 21),
+ TEST_BBDEV_VF_QM = (1ULL << 22),
+ TEST_BBDEV_VF_CODE_BLOCK_MODE = (1ULL << 23),
+ TEST_BBDEV_VF_OP_FLAGS = (1ULL << 24),
+ TEST_BBDEV_VF_EXPECTED_STATUS = (1ULL << 25),
+};
+
+enum op_data_type {
+ DATA_INPUT = 0,
+ DATA_SOFT_OUTPUT,
+ DATA_HARD_OUTPUT,
+ DATA_HARQ_INPUT,
+ DATA_HARQ_OUTPUT,
+ DATA_NUM_TYPES,
+};
+
+struct op_data_buf {
+ uint32_t *addr;
+ uint32_t length;
+};
+
+struct op_data_entries {
+ struct op_data_buf segments[RTE_BBDEV_TURBO_MAX_CODE_BLOCKS];
+ unsigned int nb_segments;
+};
+
+struct test_bbdev_vector {
+ enum rte_bbdev_op_type op_type;
+ int expected_status;
+ int mask;
+ union {
+ struct rte_bbdev_op_turbo_dec turbo_dec;
+ struct rte_bbdev_op_turbo_enc turbo_enc;
+ struct rte_bbdev_op_ldpc_dec ldpc_dec;
+ struct rte_bbdev_op_ldpc_enc ldpc_enc;
+ };
+ /* Additional storage for op data entries */
+ struct op_data_entries entries[DATA_NUM_TYPES];
+};
+
+/* fills test vector parameters based on test file */
+int
+test_bbdev_vector_read(const char *filename,
+ struct test_bbdev_vector *vector);
+
+
+#endif /* TEST_BBDEV_VECTOR_H_ */
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/bbdev_null.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/bbdev_null.data
new file mode 100644
index 000000000..c9a9abe9e
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/bbdev_null.data
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_NONE \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_0.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_0.data
new file mode 100644
index 000000000..5d4d27d60
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_0.data
@@ -0,0 +1,353 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0xF301FC03, 0xF50F0EFA, 0xE70BF902, 0x1013060C, 0xF7F6FCE7, 0x04F3F709, 0x0C07FBF1, 0xFCF7070F,
+0xEA0FFAF8, 0x0FF71209, 0x070906F2, 0xF705F004, 0x15FA05F7, 0xF4F8010A, 0x0B0E09F5, 0xF70014F6,
+0xF106F80D, 0x0A06F9FC, 0x0DFBF803, 0x0308060D, 0x0CF9F8F9, 0xF2F409ED, 0x12FEF3EA, 0xF2FC07F9,
+0xEF12EEF8, 0xF90F030C, 0xEC171408, 0x11F902F3, 0xF102F6FF, 0x0AF6090C, 0x0103FA10, 0xF9FFF011,
+0x010FFB0F, 0xF80BFEF8, 0x10F2F1EE, 0x140204F6, 0x020AF206, 0x0BED04F2, 0x06FEF5F2, 0x0F070009,
+0xECF0F9F0, 0x081405F5, 0xF1000E18, 0xF4F7090C, 0xFD0F01EF, 0x0D12E702, 0x07EF1008, 0xEF06FD02,
+0x0302FD00, 0xF2F4040A, 0xF60BF9FC, 0x0BEEF20C, 0xF9ED0901, 0x00060406, 0xFF09F6F3, 0x0FF209F7,
+0x0D0EF210, 0xF3150611, 0x06060EF8, 0x0E06EFEC, 0x070C05F8, 0x0CFBF4F1, 0xFBFE0CF6, 0xFD03F714,
+0x03FCE40C, 0xF4F5F2F4, 0xF400F6FF, 0x0EF0090C, 0x04F9F9F6, 0xF5F6FEFD, 0xFE08FE01, 0x0607F3F3,
+0x11F4020C, 0xFD0FFB04, 0xEEF30D05, 0xFD040406, 0xFCF8F108, 0x0DFAFBF9, 0xE9F10B09, 0xEEF2140D,
+0xEE0A09F8, 0xFB010C0A, 0xF1FC0803, 0x0C07130A, 0x0312FD0A, 0xF6F10708, 0xFCF1FAEC, 0x0BF8F4F9,
+0xF009FBFF, 0x14EEF2EB, 0xEF0DF701, 0xFA14F90C, 0x08EF0110, 0xF50401E5, 0xEE13F30C, 0xF1F60916,
+0x05F414EC, 0xFF030A14, 0x0409FFF2, 0x0C0906FA, 0xF7F70414, 0xFBFA0EFA, 0xFD010BFD, 0xF5FA0EF1,
+0xF40FFAF4, 0xFF060503, 0x0BEF0BFA, 0x0717E7F3, 0xF4F1FD09, 0xEF09FEFE, 0x07F9F3FB, 0x0DFD08FE,
+0x0D0BF602, 0x05F21008, 0x1A0B0807, 0xEF0CFAF9, 0x090D0A06, 0x02EB0D0F, 0xF709FDFE, 0xFFF7F510,
+0xF10A0AF8, 0x15EF1311, 0xF20BEDF9, 0xF10A0BF7, 0x15150B08, 0x0B170F0A, 0x06FAFAF1, 0xF1F803FD,
+0x11F3EEEB, 0x0902FB04, 0x0703F215, 0x06EF10FE, 0xFB00140B, 0xF70CF806, 0x040AEE0E, 0xF9F1070C,
+0xEAF9F6FC, 0x0AECF80E, 0x09F2F9F3, 0xF708E8F0, 0x0902E9F7, 0x0209F6FD, 0x02F6EE10, 0x090BE811,
+0x0BF8E8F7, 0x03F8F5F1, 0x040AF109, 0x04F80CFB, 0x100A0913, 0x0CFBF403, 0xEE04FAF0, 0xFB040008,
+0x16081113, 0xFCE80708, 0xF2FF03F3, 0xF9F1F1F4, 0xF4ED09F7, 0x0BEBF0FC, 0xF80A01E8, 0x02F714F0,
+0xF516040E, 0x0A000AF1, 0xF5F3F101, 0x05F00807, 0xE9F20011, 0xE90E1613, 0xF6150AF4, 0x0707F4F8,
+0x10F7F20B, 0xF9F9F0EE, 0xF5FE0715, 0xF90E06F7, 0x0AE8F40C, 0x0B07FB06, 0xF0F6F10E, 0xF4060811,
+0x0A0C06F5, 0x0EFBFD0B, 0x0A0EF611, 0x03F4F8F5, 0xFDF10CEB, 0x13140CFD, 0xF712F80A, 0xF1F4E903,
+0xF5030203, 0xF80900F8, 0xFDF8F40B, 0xFEFBFD0A, 0x070813F5, 0xF9FA0B14, 0xFAF7FD17, 0xF5F50603,
+0xF916F210, 0x070F12FB, 0x0DF3F5FC, 0xEA11F207, 0x0DF70DF7, 0x10F1F4F4, 0x0BF409E8, 0x0606050E,
+0x09F50EFF, 0xF70406F8, 0xED0C11FA, 0x0F0400F3, 0x0208F4F8, 0xF9100EF0, 0xFCEEEDF3, 0xF1F5FE14,
+0xE0E80DFE, 0x0A0EF5ED, 0xF3E7F90B, 0x06E7F7FE, 0x12FE06F9, 0x0804F804, 0xF409F5F9, 0xF3F80EF5,
+0x02F6EFF2, 0x120AFF0E, 0x0D0EF4F8, 0xF7F80408, 0x0400F0F3, 0x150112F2, 0x0719ECF2, 0x0403EDFC,
+0xFBF205F8, 0xF00DF30F, 0xFC0CF413, 0x08F9F2FD, 0x1107FA03, 0xEC11EDFE, 0x0DF1F810, 0xFC0B11F9,
+0xF9FE0AFD, 0x0B0EF4F3, 0xF9F1050C, 0xFC0EF9F8, 0x000F14EA, 0xF00A0107, 0xF903F810, 0x0A040EFA,
+0x0C000203, 0xF40C02FE, 0xFA06130D, 0x100CFDF3, 0x0BF505FA, 0xF5FB00FC, 0xF8110808, 0x05ECEA0D,
+0x04F7F30A, 0xFE090FEC, 0xF9FBEE08, 0xFD0CEF0E, 0x09F80B0A, 0xF90BF9F4, 0x0EFB0C0C, 0x10EFF2F0,
+0x09F8F0FA, 0x060B0909, 0xF4FF0F13, 0x06FA0E16, 0x0515F512, 0x0E0B0708, 0xF6FBF9F7, 0xFBF405F2,
+0x050A1207, 0xFA001C0C, 0xFB0FEBEE, 0x0B13100C, 0x0D08F6FB, 0x16FEF2F9, 0x12F9F412, 0x09F600F5,
+0x02040B09, 0x0AF11310, 0x0C160A06, 0x0E09FF0E, 0xEF0B0CF3, 0x13F40DF5, 0x0BF704F9, 0x07EE0A00,
+0xF0F504F6, 0x0BFAFCFB, 0x0B0BF70A, 0x0207FF08, 0xF20B09E7, 0xF9F1F115, 0xF0090812, 0xFF0DF5F8,
+0x0C080709, 0x0512F3EF, 0xEE110708, 0x03EBFCFF, 0xEE0D08FE, 0x110BFCF6, 0x15F61408, 0xF413F30D,
+0x06F2F2F1, 0x04120BEF, 0xF90CF30B, 0xE40400FB, 0x0BFC1A09, 0x130109FD, 0xFF08E7F9, 0xF2FAF4F8,
+0x060BF901, 0xF112EE02, 0xFF060D0F, 0xFAFC0DED, 0x09FFF6FF, 0xF304ED0D, 0x050AF8F3, 0xF40403F8,
+0xF5F6070B, 0xF8F7FF00, 0x170E0708, 0xF808FFF4, 0x03F80C0F, 0x0A06FCF7, 0xF3EFF404, 0xF10D09FD,
+0xFDF9F016, 0x04FD06EF, 0xF5070EEF, 0xEFF20411, 0xF310FDF1, 0xF50AFB11, 0x040DF4F3, 0xF30307F7,
+0xFC031C00, 0xF008ECF5, 0xF011F5F9, 0xFCF1ECF7, 0x16FF0F0C, 0xF9F611FC, 0x0CF70D04, 0x020C0BFF,
+0x06FE0B09, 0xF9080C0C, 0x080DE706, 0x030FFAF8, 0xFF0C0D08, 0x03051108, 0xF402FA10, 0xF4FE0502,
+0xF7F6F2E9, 0x0DFBEB11, 0xFAF2F2F1, 0x0E06F60B, 0xEDEA0EF9, 0x09EDF30B, 0xEF0CF202, 0xFE0208F3,
+0x000D08FB, 0x0FF817F4, 0x0F0DFC01, 0x0D02FF0D, 0xED060EF1, 0x0B0CF0F4, 0x0EF80712, 0x0DF31402,
+0x110EF3F2, 0xF208F60C, 0x02000B06, 0x1106E901, 0xF309F708, 0xEEF003FA, 0x00F9EF05, 0xFC08FDF9,
+0x09050B08, 0xF5FB180A, 0x10F7EEF4, 0xF10F15F0, 0x0712FF10, 0xF5FFFB08, 0x11F6F0F1, 0xFEEEFC18,
+0xF0E806F2, 0x10F90DF9, 0xF30900FD, 0x0A06F40B, 0x12EE0004, 0xED0A0AFE, 0xED04F5F8, 0xFE09F7F3,
+0x01F601F8, 0xF7EA0405, 0x04080EF5, 0x0F1CF201, 0x0712F70F, 0xF0F21205, 0xFF0A1004, 0x0AF4F30D,
+0x0DF3000D, 0xF6000B01, 0xEF0DEDFA, 0x0700F8FF, 0x03F7FBF7, 0x06020D0B, 0xFCF7F6F0, 0xFA0208F2,
+0xFA0B04F1, 0xEE04F6F9, 0xFFEEF907, 0x080106EF, 0x0FF8F007, 0xFFEB0BE4, 0xF10FF8EF, 0x080AF3F9,
+0xEF0BF311, 0xF00FF504, 0x0D100100, 0xF10BEEF9, 0xF3F8F612, 0xFB00FE0C, 0x06F30BF0, 0xF2030D11,
+0x0002EB18, 0xEFF8FE07, 0x03F6EE14, 0x08ED08FF, 0x12150AF1, 0x06F0170C, 0x050F0C16, 0x1200100D,
+0xFAF70707, 0xF0FA100E, 0xEF090D01, 0x09EE0808, 0x0809F2F5, 0x03FF090C, 0x060410F1, 0x01EE16F7,
+0xF41015F9, 0x12F10B0C, 0x0FEBF1F7, 0xF906F40B, 0x0CFD02F6, 0x0FFAF00E, 0x0D030BF2, 0x0BF711F4,
+0xF1F30A06, 0x0CF5F9F0, 0x031A0D0F, 0x0CEC0608, 0x08EEF5F5, 0xF202020A, 0xFAF7F1FB, 0x0FFB07F9,
+0xF5010C0A, 0xF0F6FA0C, 0xF70FF0FF, 0x08ECF80E, 0x0EFBEC10, 0x01F0EF14, 0xE9030C08, 0x0A0EEFFD,
+0xF7001415, 0xEF04FCF3, 0xFF0C13EE, 0x05F4F2FC, 0xF9F3E7F7, 0xEC0CF6FE, 0xFDF70702, 0xFE12EFF0,
+0x0FFB0D07, 0xF6E8ED03, 0xF40607F5, 0x06040F0D, 0xF60700F1, 0x080503FA, 0xEE0B06F8, 0x0114050A,
+0x0DFF0B11, 0xF5EFF7ED, 0x11EE0F13, 0x0201EAEF, 0xF80BF80F, 0x070D0F0C, 0x090502F0, 0x0BE70401,
+0x0A0CF0F4, 0xF601F3F7, 0x1AEEF912, 0x11060C03, 0x09EDF7F9, 0xF6ED1708, 0xF0FA0E02, 0x0DF20FFC,
+0xEFFCF7F3, 0x090EF50C, 0xFAF8FDF9, 0x0F0E1304, 0xF117F3F9, 0x0CF3020D, 0xF8FBF705, 0xFBFEF0ED,
+0xF5F1EB14, 0x0D07F81B, 0xF9F704F4, 0xF1F3FE09, 0x03030DF6, 0xFA02F1F5, 0x11F4F600, 0x16081215,
+0xF5090B0A, 0xFA0C0AF0, 0xF60F0E02, 0xF3E8160D, 0x08FDEEF8, 0x10F907FC, 0x0AFE00F5, 0x0AF0F00F,
+0xF4F7EE0B, 0xFFF3F4F5, 0xFDF718EF, 0x0CFC0B10, 0xF70AFEFE, 0xFCF2EDFB, 0x08EC0F15, 0xFBEE11EC,
+0x0BF6080E, 0x0D02F702, 0xF3FE09F9, 0xF9F30A10, 0x0FF20809, 0xF910FDF8, 0xFA060EEE, 0x10FBFE06,
+0x150C0810, 0xEE0D160B, 0xFF08FB0C, 0x0411FC10, 0x09F8FEF6, 0x0BFC10F2, 0x0DEE0D07, 0x0C03F40D,
+0xF1F5FC11, 0xF80C0011, 0x06EF0208, 0x070C08F6, 0xF807F80C, 0x10090000, 0x050EFD0F, 0xF80CF216,
+0xF9FFF2F9, 0x08EE09F8, 0x09EEFFF5, 0xF8F70CF0, 0xF609F803, 0xF90AF509, 0x0E00FE0E, 0x05F7FE0A,
+0xF807F1F6, 0xFCF5F6FF, 0x0AFE0BFD, 0x09F500E5, 0x0DF8FC0C, 0x070808F1, 0xEDEEF00D, 0x0900FBF2,
+0xF407FAEA, 0xEFFA0CED, 0x10170A0B, 0xF807F6EA, 0xF1ECF9FF, 0xF5FEF4FF, 0x0E020B11, 0xFFEDFC0B,
+0xF3F4ECE6, 0xEE0AF6F4, 0x09F7FE05, 0xF4F2EAFA, 0xF7F70D06, 0xF708EF07, 0x10F8FCF7, 0xEFFB08F2,
+0xFA05FDF7, 0xF3F31111, 0x0109ECFB, 0x0DF1F208, 0x0EF3F307, 0xFFF1F4FE, 0xEDFF12FA, 0x13080405,
+0xF307040D, 0xF408FCFC, 0x10120500, 0x090AEC07, 0x0CF10907, 0x09EEF8ED, 0xFCED0CFB, 0x0CF91008,
+0xFB0FFCF2, 0xF709F7F6, 0x080608F8, 0xF70BF60C, 0x03F60808, 0x0507F9FC, 0x13F3F40C, 0xEC000A0F,
+0xF7F307FD, 0xF2FF0B0E, 0x03FCF5F4, 0x04E4FE0B, 0x0F0BFEF4, 0x100C02F5, 0x13E9ED0D, 0x0204F4ED,
+0xF5F3FAF1, 0x05FD0A05, 0x00F4E4FA, 0xF9FA0EEC, 0xF308F50F, 0xFAF8FB0C, 0x14F70B0A, 0x090A080B,
+0x011207F4, 0xF0070AF0, 0xEDFE0EF3, 0x1311EF09, 0xF8F9F5F1, 0x04F5F507, 0xFFF70FFD, 0xF1F50413,
+0xF6F8F50F, 0xF7FEF00A, 0xF70104F1, 0x0D04F717, 0xEBF31209, 0xFFF50CE7, 0x0CF7070C, 0xFA0AF50A,
+0xF5FEF6F1, 0x050EEF00, 0x0705F6EF, 0x1204FAE5, 0xF80BF9FD, 0x0AF4FDEF, 0x08F80307, 0xEE04050C,
+0xFBEFED07, 0x0A120401, 0x1208F2F1, 0xF6F31315, 0xF7F3E909, 0xF1F90F08, 0x03E40709, 0xFB0BFD0E,
+0xF5F9F7F8, 0x0AF7FEEB, 0x12F4F306, 0x12F1FBF7, 0xF20606F6, 0xFAFB1402, 0x0E11FBF2, 0xFAECF8FD,
+0xFAEEFCF6, 0xFA07FD02, 0x0DFCF604, 0xFAF4FC09, 0xF100EF10, 0xFDEE08F8, 0x0D0B14F0, 0x0BF30DEC,
+0xF9000FF1, 0xF8090E06, 0x09EB03F7, 0x0FF90DF5, 0xEC11F6F8, 0xF6EE09FE, 0xF5F0F9FA, 0xF907EF0B,
+0xFCEE06F8, 0x0FFEFB16, 0x0AFD0805, 0x05F10A08, 0x0CF303F7, 0x0115F3FA, 0xEE0D0A0D, 0xF9F6F80E,
+0x100A0AF8, 0x0BF702FC, 0xF6080705, 0xFD01F3F4, 0x0DFE0101, 0x0EF7FF0A, 0xF00BFFF9, 0xF8FBEF0F,
+0x1101F7F6, 0x1104F5E7, 0xF81709F6, 0x0809F7F5, 0xFEF509F8, 0xEBFB00E8, 0x0800FFF6, 0xF111FAFE,
+0x14F2F6F5, 0xFAEF0108, 0x0FFB100F, 0xF0FB090C, 0xF608EF0B, 0xF304FB19, 0xFEEE0E11, 0x12030908,
+0xF3090907, 0xF707FC11, 0xF8EDFD0F, 0x04F2F5F5, 0x03FEF2F6, 0xF00B02FA, 0xFBF805F9, 0xF5FA1012,
+0x08060E06, 0x12E8F709, 0x0AEAFCEC, 0x080EF10C, 0xF510FEF8, 0xEF06F6FD, 0x0F0508FD, 0xFFF8FA05,
+0xF6091212, 0x07F114F7, 0x070CF50B, 0xF3F501EF, 0x080BF00B, 0x06F9FDEF, 0x08F5EEF2, 0xFA0D0C05,
+0x02FFF90E, 0x050AFA08, 0x0803FF00, 0xF40901F5, 0xF113F514, 0xF9080DF9, 0x03F6000A, 0x170AFCFE,
+0x08050A04, 0x09E5F2FC, 0x0B00F00E, 0x10EF100A, 0x0BFF10F1, 0x120602FD, 0x0AF1F703, 0xF50DF811,
+0xEBF5F012, 0xF908020C, 0x030112F2, 0x16F9E0F5, 0x06070008, 0xFEFAEAF6, 0xFA0D1305, 0xFFFEFA14,
+0x0602F9EF, 0xF2F90202, 0xEF0E10ED, 0x06F00BFD, 0xF0E90503, 0x1506FAF2, 0x01F80A0D, 0xF6E90304,
+0xF1F810F8, 0xF5F60A00, 0x0309F9F5, 0xF1F4F9FA, 0xF4FA0A07, 0xE5080803, 0xF7F9040B, 0x0FFC0FF9,
+0x0AF4FCF5, 0xF0F20B02, 0xFAFB02FE, 0xF3000D0E, 0xF3FAF9FD, 0x02040209, 0xED0DF1F4, 0xF6F00DEA,
+0xFC0004FF, 0x050BFF0D, 0xFFFBF80D, 0xF40302F8, 0xF8FA07F2, 0xF103F907, 0x050B08FB, 0xEF010E0C,
+0xF8030DFD, 0xF814F60C, 0xFA09F506, 0xF4F4F2FE, 0x09F8EFED, 0x03F612F6, 0xF609F20D, 0xF90BFB11,
+0xF60EF5F8, 0x00F60AF9, 0x0D0112E8, 0xF60900F0, 0x0C0008F8, 0xF5ECFD06, 0xEFF9000E, 0x0411FA09,
+0x110B0BEF, 0x11EA0301, 0x0B0CF10A, 0xF1EFF50A, 0x111004FD, 0x0807FDF5, 0x0AF5F100, 0xF8080BF3,
+0x0D01F7F5, 0x000716ED, 0xF3F6F80A, 0xFDF30513, 0xF8FA0B0E, 0x0DF80103, 0x020DF308, 0x10F6050B,
+0x09F7F609, 0xFCF103F0, 0x0709F6F4, 0xF40D12F6, 0x0B02FD0B, 0xF2FC10ED, 0x04EDF7E9, 0x040E0E0E,
+0x090708F2, 0xE90808F9, 0x0E0CEA13, 0x06F103FC, 0xF80C0506, 0xF4FF0DFB, 0x060A08F7, 0x09EBEE07,
+0xF4F8FB0A, 0x0CF60306, 0xFB1EF1FF, 0x08F90C0E, 0x160BF5F5, 0x10F604EE, 0xF40302F7, 0x040507FF,
+0xFDF3FD09, 0xFD0FFB0D, 0xF8F406F8, 0x0BFAF40C, 0x16F6FFF3, 0xFC1F0B0C, 0xF3EEF50F, 0x08F5EB0D,
+0xF0FD0BF4, 0xECF5F9F7, 0xF30100EF, 0xF80BE9F5, 0x0200F50F, 0x08F7F8FA, 0x10F0F4F5, 0xF3ECEFFA,
+0x09FEF5F1, 0xFEEAF402, 0xFAFC13FC, 0x15F8F70F, 0xF7060700, 0x07100D0B, 0x1705F901, 0x0EFF0605,
+0xF407FA16, 0x02FA0615, 0xFDFF0BF4, 0xF211FA0F, 0x0F0406F8, 0x10EEEB0B, 0xEBF1FF12, 0x170E130F,
+0x0B0BF3F4, 0x03120AF8, 0x00160304, 0xF7F6E3F4, 0x0DE6EEEF, 0xEC07F5ED, 0x050F060B, 0x141705EE,
+0xFCFE0AF2, 0x16050AF5, 0x01FEF6F5, 0x0EEFFD0B, 0x0BFDEB15, 0x02FF0507, 0x1507F409, 0x03011609,
+0xFCEE090D, 0xF202F3EB, 0x07FB040D, 0xFAF614F9, 0x0F07070E, 0x0AEFF2F6, 0xFE0604F6, 0xF709F908,
+0xECFE06F1, 0xF1140E0F, 0x0BEEFCEB, 0x13F60DFC, 0xED140FF2, 0xF607F3EF, 0x10040D0B, 0xF2FB0D03,
+0xF4F40CFC, 0xF10AF605, 0xF1FBF20D, 0x0E0D0BF6, 0xF50213F8, 0x0C060F0B, 0x13FBFB0E, 0xEBFFEE0F,
+0xF40909F7, 0xF8090E07, 0xEC0F0A02, 0xF6F70818, 0x0DF0F105, 0xF90B09F8, 0xEFF6090D, 0xF6FE020C,
+0xF6ECEFF0, 0x1409F7F4, 0xF9F3F00A, 0xF4040110, 0x10F1FB05, 0x13EB0B05, 0x110C0111, 0x0F05F3F9,
+0x12F3ED0B, 0xECFC09F1, 0xF90BF8F3, 0x0D12030B, 0xF10403FC, 0xF403FA11, 0xF1FC0A0F, 0xFE03F40B,
+0xE9EF0AFC, 0xF6FB0B09, 0xF7FBF111, 0xFFF5F00C, 0xF205F004, 0xF80B01F8, 0x0BFC1AF7, 0x00F61509,
+0x13FB0F00, 0x09FEEE0C, 0xF7F7EAFB, 0x130F0D08, 0x00060809, 0x130BFBFD, 0xF00F0E15, 0xF10EF912,
+0xF507F0F8, 0x0502010B, 0x0BFAF8F0, 0x0307F614, 0xFEF30508, 0x09060B15, 0xFAF8F3F9, 0xEBF2F8FD,
+0xF9060AF8, 0xEAEE12F6, 0xF406F0E8, 0xF405FC09, 0x130612F7, 0x0D07F811, 0x0D03F8F8, 0x0100130C,
+0x0CF9F20A, 0xF30406F9, 0x0CF5F4F7, 0x0006F10B, 0x11F2F0F7, 0xE80DF60C, 0xFE02F6F7, 0xF70607FB,
+0x130AFCF5, 0xF8F71006, 0x0AFCFDF4, 0xF00E04F1, 0x16F5FCFE, 0xF6FA06FA, 0x09F9ED17, 0xFE051106,
+0x0D0CED0A, 0xEDFC14F4, 0xF81012E8, 0x030303FC, 0xF400F8FD, 0xFDF3F407, 0x0B091406, 0x0CFCF6F4,
+0x180D110B, 0x0DFBF10B, 0xFBE4FAF9, 0x0B10F417, 0x0608F9F2, 0xF2F2F904, 0xF80306F7, 0x0902F3FA,
+0x080EFA07, 0x03F00600, 0xE2ED0DF1, 0x0AFB140A, 0xF50FFAEB, 0x0AE608F5, 0x0DF8FB0B, 0xE7F206FC,
+0x050D0BFB, 0x0204FDF5, 0xFBF70706, 0xF4F0F60B, 0x0B07F7FC, 0x01F7F905, 0x0F16F309, 0x0C0AFAF0,
+0xFDF2010F, 0x0BFF040D, 0x060E04F2, 0x0FEA0915, 0x0F020AF3, 0x06080E02, 0xFFF906F5, 0xF600F1FA,
+0x060E1104, 0xFCEF0CF7, 0x0CF30D14, 0x010F03F6, 0xF9FAF6EE, 0xF6F112FE, 0xF0F302F2, 0x12080FF1,
+0xF911F002, 0xF0F6F010, 0x0D02FC06, 0x10F8FEF2, 0xF6FCE703, 0xEA12FC0D, 0xFFF6FC13, 0xF407F0F8,
+0x0DF5010D, 0xEA0C08F4, 0x02050AFB, 0x090DF6FF, 0xF2F4F709, 0xF104ED0E, 0x0906F8F6, 0xF8F806FB,
+0xF8F20F0D, 0xF8F3F7FA, 0xFE04FB02, 0xF80DF7F9, 0x030EF400, 0x0A05EE08, 0x04EB06EC, 0xF6F50FEF,
+0xEF0E03E7, 0x13FE090B, 0xF70FFC0E, 0x120B150E, 0x0712EDF4, 0x0E04EDF8, 0x0D0DF510, 0x080EF3EE,
+0x0DF702EF, 0x0902E91A, 0xFD10F4EC, 0xF1F7FA0F, 0xFEFDF4FA, 0xFDF60F04, 0xF10FF20B, 0x031017E9,
+0x12EF03FE, 0xF3F6110C, 0xFEF4FC07, 0xF20A08EB, 0x020613F0, 0xF5F6FB0A, 0x07160207, 0x15F5F20B,
+0x18FFED0B, 0x0F11F911, 0xFFEF0B08, 0xF3F8F8F8, 0x0AF40B10, 0x0FF70A04, 0x0AEB13FE, 0xEE0B0C0A,
+0xF5020605, 0x0A140A00, 0x010EF6F2, 0x1A0304FC, 0x08EB0FFF, 0xF0FDF617, 0x12FC01F4, 0xEC1709FA,
+0x0C0C02FA, 0xF90DF9F9, 0xF0F50311, 0xF1100C04, 0xF20200FC, 0xF2141703, 0xFA051100, 0x0D14F8FC,
+0x03F2F6FE, 0x04FCF6F6, 0x10FAFA03, 0x0309FB05, 0x09F00DF4, 0x0A08F4F3, 0xF3F5EFEF, 0xF106FBFE,
+0x050105F8, 0x0D09F0F8, 0x0E130EF1, 0xFAF00B09, 0x080D11ED, 0xFDF703F8, 0xF8F10AFC, 0xFE04ED0A,
+0xF4100B08, 0xF1FCF10F, 0x050E14F4, 0x05070D04, 0x0AEC100C, 0x0D0BFCF6, 0x01FAEB0C, 0xFF0C0DF8,
+0x010E0DFF, 0x07F7F70F, 0x00FBF6FC, 0xF9FB0D09, 0xF1ED080D, 0xFCF9EDF4, 0xF3F80C0B, 0xFD0210F4,
+0xFBF206F2, 0xF3F5F7FC, 0xF8FDFFF1, 0xF0020908, 0xF804F505, 0xF8F2080B, 0xF0FA09F3, 0xEFF8120A,
+0x14EDF8EA, 0x0CF40E15, 0x0EEB0600, 0x02FD01FB, 0xF5F30D0F, 0xFFF400F1, 0xF30F0909, 0xF9ECF107,
+0xEE0AF0FF, 0x05FA070D, 0xFD0CFB06, 0xF8F7EFEE, 0x13F0030B, 0x050404F4, 0xEE0FF6F5, 0xFC0813F5
+
+output0 =
+0xCE63DECD, 0xD5F54E4C, 0xB969BECF, 0x67199350, 0x73BD1B5F, 0xF3FA3DD7, 0xB72F3304, 0xCA6C9E7F,
+0xC75EBD3C, 0xE9183BC1, 0xD2EFF1F5, 0xDB98D960, 0x9183FF24, 0x84E53C2E, 0xBC0ACB99, 0x7544F27D,
+0x61B01F8C, 0x6F8E7BCA, 0x0F9A1912, 0xA4DE41C3, 0xFB1F18F3, 0x44764A35, 0x9525E193, 0xAD6AFC2C,
+0xEAC9CBE7, 0x82E626C3, 0x6764F162, 0xB7180FC5, 0x92F0BF10, 0x6BE2A423, 0x6652CA83, 0x76AB8A79,
+0xD2DC0142, 0x3684A5B0, 0x6AF81D1E, 0xCE7B11D8, 0x5C0A7AA6, 0x9B519157, 0xCF71DB9C, 0xE66B5219,
+0x0976A858, 0x97CCD7A4, 0xBD21A44D, 0x694DB77D, 0x2046F400, 0x66BF01FF, 0x4FE7F1B2, 0x7D287C99,
+0xA6DD65A8, 0xDDAC14DF, 0xB4EA7458, 0x9BF75449, 0xBCCF3BC5, 0x59B3E1D5, 0x04D5FEAA, 0xA91CED07,
+0x264A3E33, 0x314BE435, 0x47FB659B, 0xC8C6CBDD, 0xD4BAF083, 0x51A5AE91, 0x39A33C7A, 0xC54DBA59,
+0x81FD7FFA, 0xE2A3941C, 0x386750ED, 0x85C6A1CF, 0x52E46581, 0x2DD58578, 0x4F8C20DC, 0xCA6C89B8,
+0xD33AF49E, 0xB73D9A1C, 0x8F5992A5, 0x4613FE36, 0x8F724B6A, 0xD2C9A290, 0x5C4791D6, 0x8AA4DE2A,
+0xBCA9EEF4, 0x769D6618, 0x71DF1DFC, 0xE9DC6A93, 0x99E831C3, 0x88B8CBD4, 0x4C9E63C5, 0xBEBC2792,
+0x9E54A535, 0x55181DEF, 0x0F83F8D2, 0x79A8094D, 0x2DA8AAEB, 0xD64C6C17, 0x4F0AADB5, 0x20CB1D7F,
+0x2D6E9F16, 0xB97E8AA9, 0x36167C67, 0x8D84329F, 0x4002AA1C, 0x6326776B, 0xB9B50F8F, 0xF9C52D71,
+0x4D1A117F, 0x604A6DEE, 0xBB19DFB2, 0x96121F4E, 0x9E7C8D9E, 0x00F8F1F3, 0x204B8054, 0xA67E9C60,
+0xC534F776, 0x94B8C032, 0x38E7CFEC, 0xF1E48A55, 0x821E3625, 0xFAC9EBD0, 0xF3D38EF2, 0xB4DA79FB,
+0xF32472
+
+harq_output0 =
+0x0FFA0103, 0x130C0B02, 0xF309F6E7, 0xF70F07F1, 0xF7090FF8, 0x050409F2, 0xF80AFAF7, 0x00F60EF5,
+0x06FC060D, 0x080DFB03, 0xF4EDF9F9, 0xFCF9FEEA, 0x0F0C12F8, 0xF9F31708, 0xF60C02FF, 0xFF110310,
+0x0BF80F0F, 0x02F6F2EE, 0xEDF20A06, 0x0709FEF2, 0x14F5F0F0, 0xF70C0018, 0x12020FEF, 0x0602EF08,
+0xF40A0200, 0xEE0C0BFC, 0x0606ED01, 0xF2F709F3, 0x15110E10, 0x06EC06F8, 0xFBF10CF8, 0x0314FEF6,
+0xF5F4FC0C, 0xF00C00FF, 0xF6FDF9F6, 0x07F30801, 0x0F04F40C, 0x0406F305, 0xFAF9F808, 0xF20DF109,
+0x010A0AF8, 0x070AFC03, 0xF108120A, 0xF8F9F1EC, 0xEEEB09FF, 0x140C0D01, 0x04E5EF10, 0xF616130C,
+0x0314F4EC, 0x09FA09F2, 0xFAFAF714, 0xFAF101FD, 0x06030FF4, 0x17F3EFFA, 0x09FEF109, 0xFDFEF9FB,
+0xF2080B02, 0x0CF90B07, 0xEB0F0D06, 0xF71009FE, 0xEF110AF8, 0x0AF70BF9, 0x170A1508, 0xF8FDFAF1,
+0x0204F3EB, 0xEFFE0315, 0x0C06000B, 0xF10C0A0E, 0xEC0EF9FC, 0x08F0F2F3, 0x09FD02F7, 0x0B11F610,
+0xF8F1F8F7, 0xF8FB0A09, 0xFB030A13, 0x040804F0, 0xE8080813, 0xF1F4FFF3, 0xEBFCEDF7, 0xF7F00AE8,
+0x00F1160E, 0xF007F301, 0x0E13F211, 0x07F815F4, 0xF9EEF70B, 0x0EF7FE15, 0x0706E80C, 0x0611F60E,
+0xFB0B0CF5, 0xF4F50E11, 0x14FDF1EB, 0xF403120A, 0x09F80303, 0xFB0AF80B, 0xFA1408F5, 0xF503F717,
+0x0FFB1610, 0x1107F3FC, 0xF1F4F7F7, 0x060EF4E8, 0x04F8F5FF, 0x04F30CFA, 0x10F008F8, 0xF514EEF3,
+0x0EEDE8FE, 0xE7FEE70B, 0x0404FEF9, 0xF8F509F9, 0x0A0EF6F2, 0xF8080EF8, 0x01F200F3, 0x03FC19F2,
+0x0D0FF2F8, 0xF9FD0C13, 0x11FE0703, 0x0BF9F110, 0x0EF3FEFD, 0x0EF8F10C, 0x0A070FEA, 0x04FA0310,
+0x0CFE0003, 0x0CF3060D, 0xFBFCF5FA, 0xEC0D1108, 0x09ECF70A, 0x0C0EFB08, 0x0BF4F80A, 0xEFF0FB0C,
+0x0B09F8FA, 0xFA16FF13, 0x0B081512, 0xF4F2FBF7, 0x000C0A07, 0x130C0FEE, 0xFEF908FB, 0xF6F5F912,
+0xF1100409, 0x090E1606, 0xF4F50BF3, 0xEE00F7F9, 0xFAFBF5F6, 0x07080B0A, 0xF1150BE7, 0x0DF80912,
+0x12EF0809, 0xEBFF1108, 0x0BF60DFE, 0x130DF608, 0x12EFF2F1, 0x04FB0C0B, 0x01FDFC09, 0xFAF808F9,
+0x12020B01, 0xFCED060F, 0x040DFFFF, 0x04F80AF3, 0xF700F60B, 0x08F40E08, 0x06F7F80F, 0x0DFDEF04,
+0xFDEFF916, 0xF21107EF, 0x0A1110F1, 0x03F70DF3, 0x08F50300, 0xF1F711F9, 0xF6FCFF0C, 0x0CFFF704,
+0x080CFE09, 0x0FF80D06, 0x05080C08, 0xFE020210, 0xFB11F6E9, 0x060BF2F1, 0xED0BEAF9, 0x02F30C02,
+0xF8F40DFB, 0x020D0D01, 0x0CF406F1, 0xF302F812, 0x080C0EF2, 0x06010006, 0xF0FA0908, 0x08F9F905,
+0xFB0A0508, 0x0FF0F7F4, 0xFF081210, 0xEE18F6F1, 0xF9F9E8F2, 0x060B09FD, 0x0AFEEE04, 0x09F304F8,
+0xEA05F6F8, 0x1C0108F5, 0xF205120F, 0xF40D0A04, 0x0001F30D, 0x00FF0DFA, 0x020BF7F7, 0x02F2F7F0,
+0x04F90BF1, 0x01EFEE07, 0xEBE4F807, 0x0AF90FEF, 0x0F040B11, 0x0BF91000, 0x000CF812, 0x0311F3F0,
+0xF8070218, 0xEDFFF614, 0xF00C15F1, 0x000D0F16, 0xFA0EF707, 0xEE080901, 0xFF0C09F5, 0xEEF704F1,
+0xF10C10F9, 0x060BEBF7, 0xFA0EFDF6, 0xF7F403F2, 0xF5F0F306, 0xEC081A0F, 0x020AEEF5, 0xFBF9F7FB,
+0xF60C010A, 0xEC0E0FFF, 0xF014FB10, 0x0EFD0308, 0x04F30015, 0xF4FC0CEE, 0x0CFEF3F7, 0x12F0F702,
+0xE803FB07, 0x040D06F5, 0x05FA07F1, 0x140A0BF8, 0xEFEDFF11, 0x01EFEE13, 0x0D0C0B0F, 0xE70105F0,
+0x01F70CF4, 0x0603EE12, 0xED08EDF9, 0xF2FCFA02, 0x0E0CFCF3, 0x0E04F8F9, 0xF30D17F9, 0xFEEDFB05,
+0x071BF114, 0xF309F7F4, 0x02F503F6, 0x0815F400, 0x0CF0090A, 0xE80D0F02, 0xF9FCFDF8, 0xF00FFEF5,
+0xF3F5F70B, 0xFC10F7EF, 0xF2FB0AFE, 0xEEECEC15, 0x0202F60E, 0xF310FEF9, 0x10F8F209, 0xFB0606EE,
+0x0D0B0C10, 0x1110080C, 0xFCF2F8F6, 0x030DEE07, 0x0C11F511, 0x0CF6EF08, 0x0900070C, 0x0C160E0F,
+0xEEF8FFF9, 0xF7F0EEF5, 0x0A090903, 0xF70A000E, 0xF5FF07F6, 0xF5E5FEFD, 0x08F1F80C, 0x00F2EE0D,
+0xFAED07EA, 0x07EA170B, 0xFEFFECFF, 0xED0B0211, 0x0AF4F4E6, 0xF2FAF705, 0x0807F706, 0xFBF2F8F7,
+0xF31105F7, 0xF10809FB, 0xF1FEF307, 0x0805FFFA, 0x08FC070D, 0x0A071200, 0xEEEDF107, 0xF908EDFB,
+0x09F60FF2, 0x0B0C06F8, 0x07FCF608, 0x000FF30C, 0xFF0EF3FD, 0xE40BFCF4, 0x0CF50BF4, 0x04EDE90D,
+0xFD05F3F1, 0xFAECF4FA, 0xF80C080F, 0x0A0BF70A, 0x07F012F4, 0x1109FEF3, 0xF507F9F1, 0xF513F7FD,
+0xFE0AF80F, 0x041701F1, 0xF5E7F309, 0x0A0AF70C, 0x0E00FEF1, 0x04E505EF, 0xF4EF0BFD, 0x040CF807,
+0x1201EF07, 0xF31508F1, 0xF908F309, 0x0B0EE409, 0xF7EBF9F8, 0xF1F7F406, 0xFB0206F6, 0xECFD11F2,
+0x0702EEF6, 0xF409FC04, 0xEEF80010, 0xF3EC0BF0, 0x090600F1, 0xF9F5EBF7, 0xEEFE11F8, 0x070BF0FA,
+0xFE16EEF8, 0xF108FD05, 0x15FAF3F7, 0xF60E0D0D, 0xF7FC0AF8, 0x01F40805, 0xF70AFE01, 0xFB0F0BF9,
+0x04E701F6, 0x09F517F6, 0xFBE8F5F8, 0x11FE00F6, 0xEF08F2F5, 0xFB0CFB0F, 0x0419080B, 0x0308EE11,
+0x07110907, 0xF2F5ED0F, 0x0BFAFEF6, 0xFA12F8F9, 0xE8090606, 0x0E0CEAEC, 0x06FD10F8, 0xF80505FD,
+0xF1F70912, 0xF5EF0C0B, 0xF9EF0B0B, 0x0D05F5F2, 0x0A08FF0E, 0x09F50300, 0x08F91314, 0x0AFEF60A,
+0xE5FC0504, 0xEF0A000E, 0x06FDFFF1, 0x0D11F103, 0x080CF512, 0xF9F501F2, 0xFAF60708, 0xFE140D05,
+0xF90202EF, 0xF0FD0EED, 0x06F2E903, 0xE904F80D, 0xF600F8F8, 0xF4FA09F5, 0x0803FA07, 0xFCF9F90B,
+0xF202F4F5, 0x000EFBFE, 0x0409FAFD, 0xF0EA0DF4, 0x0B0D00FF, 0x03F8FB0D, 0x0307FAF2, 0x010C0BFB,
+0x140C03FD, 0xF4FE0906, 0xF6F6F8ED, 0x0B11090D, 0xF6F90EF8, 0x09F001E8, 0xEC0600F8, 0x1109F90E,
+0xEA010BEF, 0xEF0A0C0A, 0x07F510FD, 0x08F3F500, 0x07ED01F5, 0xF313F60A, 0xF803FA0E, 0xF60B0D08,
+0xF1F0F709, 0x0DF609F4, 0xFCED020B, 0x0E0EEDE9, 0x08F907F2, 0xF1FC0C13, 0xFFFB0C06, 0xEB070AF7,
+0xF606F80A, 0xF90E1EFF, 0xF6EE0BF5, 0x05FF03F7, 0x0F0DF309, 0xFA0CF4F8, 0x1F0CF6F3, 0xF50DEE0F,
+0xF5F7FDF4, 0x0BF501EF, 0xF7FA000F, 0xECFAF0F5, 0xEA02FEF1, 0xF80FFCFC, 0x100B0600, 0xFF050501,
+0xFA150716, 0x110FFFF4, 0xEE0B04F8, 0x0E0FF112, 0x12F80BF4, 0xF6F41604, 0x07EDE6EF, 0x17EE0F0B,
+0x05F5FEF2, 0xEF0BFEF5, 0xFF07FD15, 0x01090709, 0x02EBEE0D, 0xF6F9FB0D, 0xEFF6070E, 0x090806F6,
+0x140FFEF1, 0xF6FCEEEB, 0x07EF14F2, 0xFB03040B, 0x0A05F4FC, 0x0DF6FB0D, 0x060B02F8, 0xFF0FFB0E,
+0x090709F7, 0xF7180F02, 0x0BF8F005, 0xFE0CF60D, 0x09F4ECF0, 0x0410F30A, 0xEB05F105, 0x05F90C11,
+0xFCF1F30B, 0x120B0BF3, 0x031104FC, 0x030BFC0F, 0xFB09EFFC, 0xF50CFB11, 0x0BF80504, 0xF609FCF7,
+0xFE0CFB00, 0x0F08F7FB, 0x0BFD0609, 0x0E120F15, 0x020B07F8, 0x0714FAF0, 0x0615F308, 0xF2FDF8F9,
+0xEEF606F8, 0x050906E8, 0x071106F7, 0x000C03F8, 0x04F9F90A, 0x060BF5F7, 0x0D0CF2F7, 0x06FB02F7,
+0xF7060AF5, 0x0EF1FCF4, 0xFAFAF5FE, 0x0506F917, 0xFCF40C0A, 0x03FC10E8, 0xF30700FD, 0xFCF40906,
+0xFB0B0D0B, 0x1017E4F9, 0xF20408F2, 0x02FA03F7, 0xF0000E07, 0xFB0AEDF1, 0xE6F50FEB, 0xF2FCF80B,
+0x04F50DFB, 0xF00BF706, 0xF70507FC, 0x0AF01609, 0xFF0DF20F, 0xEA150EF2, 0x080202F3, 0x00FAF9F5,
+0xEFF70E04, 0x0FF6F314, 0xF1FEFAEE, 0x08F1F3F2, 0xF6101102, 0xF8F20206, 0x120DFC03, 0x07F8F613,
+0x0CF4F50D, 0x0DFF05FB, 0x040EF409, 0xF8FB06F6, 0xF3FAF20D, 0x0DF90402, 0x05080E00, 0xF5EFEBEC,
+0xFE0B0EE7, 0x0B0E0F0E, 0x04F812F4, 0x0EEE0D10, 0x021AF7EF, 0xF70F10EC, 0xF604FDFA, 0x10E90F0B,
+0xF60CEFFE, 0x0AEBF407, 0xF60A06F0, 0xF50B1607, 0x1111FF0B, 0xF8F8EF08, 0xF704F410, 0x0B0AEBFE,
+0x14000205, 0x03FC0EF2, 0xFD17EBFF, 0x17FAFCF4, 0x0DF90CFA, 0x1004F511, 0x140302FC, 0x14FC0500,
+0xFCF6F2FE, 0x0905FA03, 0x08F3F0F4, 0x06FEF5EF, 0x09F801F8, 0xF00913F1, 0xF7F80DED, 0x040AF1FC,
+0xFC0F1008, 0x07040EF4, 0x0BF6EC0C, 0x0CF8FA0C, 0xF70F0EFF, 0xFB09FBFC, 0xF9F4ED0D, 0x02F4F80B,
+0xF5FCF2F2, 0x0208FDF1, 0xF20B0405, 0xF80AFAF3, 0xF415EDEA, 0xFDFBEB00, 0xF4F1F30F, 0xEC070F09,
+0xFA0D0AFF, 0xF7EE0C06, 0x04F4F00B, 0x08F50FF5, 0xF50EF3FC, 0x1006E7F9, 0x04F7F7FC, 0xFC070CFB,
+0x0F12EAFA, 0xF7F00706, 0xF4011505, 0xF7140B09, 0x0AF9F1F8, 0x03060DF8, 0xF2090CF8, 0xF20712F3,
+0xF903EFEE, 0x1102EC14, 0x0A09F1F6, 0xF9F001FA, 0xF8FE01FB, 0x140410F1, 0x0B0402F2, 0x0F0006F5,
+0x0805ECF9, 0xF409F10E, 0x0DE7FD01, 0xEFFD0710, 0xF20403FD, 0x0BF2F6F9, 0x0004F909, 0x0F09FFF6,
+0xF3060DF2, 0x0EEF060E, 0x0CF40705, 0xFDF7FB0C, 0xF4F203E4, 0x0E09F4F6, 0xF5FE04F9, 0x06F3FEFE,
+0xFDFB1102, 0xFD04EE0D, 0x0DFBFCF1, 0xEE14E90B, 0xFB0CEE09, 0x0C13F108, 0xF60703FD, 0x0BF4FCFA,
+0x14F2F0FB, 0xFAF9EFF7, 0xF5010801, 0xF109EEF3, 0xFF0A0514, 0x0C0604FF, 0xFB0EF704, 0xF50EFD0B,
+0xFF05F4FA, 0x07E70B0B, 0xEFFEF4FD, 0x0D0807F3, 0x05100DF6, 0xEFFA1A08, 0x020D090A, 0xFFF5F7FD,
+0x1513F10A, 0xF10BF2ED, 0x0B0F150B, 0xF10306FA, 0x09FB11EE, 0x061007F2, 0xF7F8FB14, 0xF90704EE,
+0x0AF8EAF6, 0xF7E809F9, 0x02F609E9, 0x09E802EE, 0x03F50BE8, 0x040C04F1, 0x0CF41009, 0xFB00EEFA,
+0xFC071611, 0xF9F1F203, 0x0BF0F409, 0x0214F801, 0x0A0AF504, 0x0508F5F1, 0xE916E900, 0x07F4F60A,
+0xF9F010F2, 0xF906F507, 0x0BFB0AF4, 0xF408F0F1, 0x0EFD0A06, 0x03F80AF6, 0x130CFD0C, 0xF1E9F7F8,
+0xF800F502, 0xFEFDFDF4, 0xF90B0713, 0xF506FAFD, 0x0712F9F2, 0xEAF20DF5, 0x10F40D0D, 0x06050B09,
+0xF706090E, 0x0F00ED11, 0xF90E02F4, 0xF1FEFCED, 0x0AF5E00D, 0x06F7F3F9, 0x08F81206, 0xF30EF4F5,
+0x12FF02EF, 0xF7040DF4, 0x151204F0, 0x04ED07EC, 0xF0F3FB05, 0x08F2FCF4, 0xECED11FA, 0xFC110DF8,
+0x0BF4F90A, 0xFCF9F905, 0xF0010014, 0x0A0EF9F8, 0xF4020C02, 0x10FDFA13, 0xF5000B05, 0x05EAF808,
+0xFE0F04F3, 0xFDEFF9EE, 0xF9F9090B, 0x10F20E0C, 0x060909F0, 0x060EF40F, 0x0E0705F5, 0xFB05F6F9,
+0xFA1C0512, 0x0B10FBEB, 0x16F20DF6, 0x090012F4, 0x0A13020B, 0x0EFF0C0A, 0x130DEF0C, 0x070A0B04,
+0x0BFCF004, 0x02FF0BF7, 0xF9F1F209, 0xFFF5F008, 0x05F30C07, 0x03FCEE07, 0x11FCEE08, 0xF4F31514,
+0x040B06F2, 0xE400F9F3, 0x13090B1A, 0xF2F4FFE7, 0xF1EE06F9, 0xFA0DFF0D, 0xF3ED09F6, 0xF40305F8,
+0xF8FFF507, 0xF8FF1707, 0x0AFC030C, 0xF109F3F4, 0x0406FDF0, 0xEF04F50E, 0xF5FBF3FD, 0xF30704F4,
+0xF0ECFC1C, 0xFCECF0F5, 0xF911160F, 0x020B0C0D, 0xF90C060B, 0x03FA08E7, 0x0311FF0D, 0xF405F4FA,
+0x0DEBF7F2, 0x0EF6FAF2, 0x09F3ED0E, 0xFE08EFF2, 0x0F170008, 0x0DFF0FFC, 0x0BF0ED0E, 0x0D140E07,
+0xF2F611F3, 0x11E9020B, 0xEE03F3F7, 0xFCFD00EF, 0xF518090B, 0xF11510EE, 0xF5FB07FF, 0xFEFC11F0,
+0x100DF006, 0x0AF4F300, 0xED0A1200, 0xFEF7EDF5, 0xF7040101, 0x0FF2040E, 0xF01207F7, 0x0AF3FF10,
+0xF60B0D00, 0x07F8EFED, 0x060D03FB, 0xFA08FCF6, 0xEEF6FA04, 0x0806FFF9, 0xFF0B0FF0, 0x08F3F1F8,
+0xF0F5EFF3, 0xF1EE0D01, 0xFBFEF3F6, 0xF20D060B, 0xEFFE00EB, 0x080803EE, 0x0617120A, 0x1210050C,
+0xF010FA07, 0x0908EF0D, 0x030908F2, 0x01160610, 0x120BF415, 0xF9F40FF1, 0x0FF00C02, 0x0B110D0B,
+0x0CF9F10A, 0x0C06030D, 0xF20208F5, 0x0F07FAF1, 0xF0FAF50C, 0x08F8F7F0, 0x01EF0EEC, 0x0AEFE90C,
+0xEFFCF714, 0x05F2FF13, 0xECF6F9E7, 0xFEEFFD07, 0xF6ED0F0D, 0x060FF407, 0x0803F600, 0x0105EE06,
+0xF5F70D0B, 0x02EA110F, 0x070FF8F8, 0x0B040902, 0xF6F30AF0, 0x110C1AF9, 0xF61709F7, 0x0D0FF00E,
+0x09F5EFF7, 0x0F13FAFD, 0x0C02F1F3, 0xFBF0F8F7, 0x0DF8F5EB, 0xF1FEF904, 0xFAF1030D, 0x161211F6,
+0xFA0AF50B, 0xF316F60E, 0x100708EE, 0x0AF00A00, 0xFFF4F4EE, 0x0C0BFD18, 0xFCEDF7FE, 0xFB11080F,
+0x0DF70B08, 0xF90AF309, 0xF9FD0F08, 0x10FEFA0E, 0xEE161508, 0x04FCFFFB, 0x0B1009FE, 0x0CF40D0D,
+0xF800F1FC, 0x07080602, 0x1000F8F8, 0xF8F205FD, 0x0809F9F2, 0xF80C09FF, 0xF9F5F6F8, 0x05FE0EFE,
+0xFCF6F8F1, 0x09000A0B, 0x07080DFC, 0x09FBEDF0, 0xEF0CF4FA, 0xF8F6100A, 0xF5F4F1F9, 0xFFFC0E0B,
+0xEEF6F3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEF0810FC, 0xF311FAFD, 0x0DF201EC, 0xFFF40EF3, 0x1304ED12,
+0xF4FCF304, 0x09EC1005, 0x09F80C09, 0x0C10FC0C, 0xF7F7FBFC, 0xF7F60808, 0x05F90308, 0xEC0A13F4,
+0xF20BF707, 0x04FE03F5, 0x10020FFE, 0x02F413ED, 0x050AF5FA, 0xF90E00E4, 0xFAFBF3F5, 0x0908140B,
+0xF00A0107, 0x13EFED0E, 0x04F5F8F5, 0xF104FF0F, 0xF7F0F6F5, 0x0DF7F704, 0xFF0CEB12, 0xFAF50C07,
+0x05EFF5F6, 0x12FA07F6, 0x0AFDF8F9, 0xEE050803, 0x0A04FBED, 0xF61312F2, 0xF10FF7E9, 0xFBFD0307,
+0x0AFEF5F7, 0x12FB12F3, 0xFA14F206, 0xFAF80EFB, 0xFAFDFAFC, 0xFAFC0DF6, 0xFD08F1EF, 0x0B0D0D14,
+0xF80EF90F, 0x0F0D0903, 0xF609ECF6, 0xF9EFF5F9, 0x0FFBFC06, 0x050A0A08, 0x01F30C03, 0xF9F8EE0A,
+0x0B02100A, 0xFDF3F607, 0x0EFF0D01, 0xF8EFF0FF, 0x11F511F7, 0x08F7F809, 0xEB00FE09, 0xF1FA08FF,
+0xFA0114F6, 0xF0090F10, 0xF3FBF6EF, 0x1209FE0E, 0xF7FCF309, 0x04F5F8FD, 0xF00203F2, 0xF510FB05,
+0x12F7080E, 0x08F10AFC, 0xEFF6F5FE, 0xFFFA0F08, 0x0714F612, 0xF30107F5, 0x06FD08F0, 0xFA0C08EE,
+0x05FA02F9, 0xF40108FF, 0xF90DF1F5, 0x17FC0300, 0x09F2080A, 0x10100BF0, 0x12020B10, 0xF5F80AF7,
+0xF902EBF0, 0x16E00312, 0xFEEA0600, 0xFFFAFA13, 0xF20206F9, 0x060BEF10, 0x15FAF005, 0xF603010A,
+0xF50AF110, 0xF1F903F9, 0xE508F40A, 0x0F0FF704, 0xF00B0AFC, 0xF30DFA02, 0x0202F3F9, 0xF60DEDF1,
+0x05FFFC04, 0xF402FFF8, 0xF1F9F807, 0xEF0E0508, 0xF8F6F80D, 0xF4F2FAF5, 0x031209EF, 0xF9FBF6F2,
+0x000AF6F5, 0xF6000D12, 0xF5FD0C08, 0x04FAEF00, 0x1103110B, 0xF1F50BF1, 0x08FD1104, 0xF80B0AF1,
+0x00160DF7, 0xFD05F3F8, 0x0D01F80B, 0x100502F3, 0xFC0309F6, 0xF41207F6, 0xF2100BFD, 0x040E04F7,
+0xE9080908, 0x06030EEA, 0xF40DF805, 0x09EE0608, 0x0C03F4FB, 0x080CFBF1, 0x100416F5, 0x0407F402,
+0xFDFBFDFD, 0x0BF4F806, 0xFC0B16FF, 0x08EBF3F5, 0xECF9F00B, 0xF8E9F300, 0x08F802F5, 0xF3EF10F4,
+0xFEF409F5, 0x15F7FA13, 0x070DF707, 0x0E0617F9, 0x0206F4FA, 0xF2FAFD0B, 0x10EB0F06, 0x1713EBFF,
+0x030A0BF3, 0xF7E30003, 0xECF50DEE, 0x14050506, 0x160AFC0A, 0x0EFD01F6, 0x02050BEB, 0x031615F4,
+0xF2F3FC09, 0xFA140704, 0x0AF20F07, 0xF7F9FE04, 0xF10EEC06, 0x130D0BFC, 0xF6F3ED0F, 0xF20D100D,
+0xF1F6F40C, 0x0E0BF1F2, 0x0C0FF513, 0xEBEE13FB, 0xF80EF409, 0xF608EC0A, 0xF9090DF1, 0xF602EF09,
+0x14F7F6EF, 0xF401F9F0, 0x130B10FB, 0x0FF31101, 0xEC0912ED, 0x0D03F9F8, 0xF4FAF103, 0xFEF4F10A,
+0xF60BE90A, 0xFFF0F7F1, 0xF801F2F0, 0x00150B1A, 0x09EE130F, 0x130DF7EA, 0x13FB0008, 0xF1F9F00E,
+0x0501F5F0, 0x03F60BF8, 0x090BFE05, 0xEBF8FAF3, 0xEA12F90A, 0xF4FCF4F0, 0x0DF81312, 0x01130DF8,
+0xF3060CF2, 0x00F10CF4, 0xE8F611F0, 0xF707FEF6, 0xF81013FC, 0xF0040AFD, 0xF60616FC, 0xFE1109ED,
+0xED140DED, 0x0303F812, 0xFDF4F4F8, 0x0CF60B14, 0x0DF11811, 0x0BF4FBFA, 0xF2F906F9, 0x09F3F806,
+0x030608FA, 0x0A14E20D, 0x0A08F5FA, 0xE7060DFB, 0x02FD050B, 0xF4F6FB07, 0x01F90BF7, 0x0CFA0FF3,
+0x0B04FD01, 0x0F090604, 0x060E0F0A, 0xF6F1FF06, 0xFC0C0611, 0x01030C0D, 0xF612F9F6, 0x120FF002,
+0xF0F0F9F0, 0x10FE0DFC, 0xEAFCF6E7, 0xF4F0FFFC, 0xEA080D01, 0x09F6020A, 0xF1EDF2F7, 0xF80609F8,
+0xF8F7F80F, 0xF8F7FEFB, 0x0AEE03F4, 0xF60F0406, 0x1309EF03, 0x1215F7FC, 0x0EED07ED, 0x08F30DF5,
+0x09E90D02, 0xF1FAFDF4, 0xFD0FFEF4, 0x0317F1F2, 0xF3111203, 0xF208FEFC, 0xF5FB0213, 0x15F20702,
+0x0FF918ED, 0xF3F8FF0B, 0x0F0A0A0B, 0xEE0C0A13, 0x0A0AF506, 0x1A0401F6, 0xF0F6080F, 0xEC091201,
+0xF9F90C02, 0xF10CF003, 0xF217F200, 0x0DF8FA11, 0x04F603F6, 0x03FB10FA, 0x0AF4090D, 0xF1FBF3EF,
+0x0DF00505, 0xFA0B0E0E, 0xFD030811, 0xFEEDF80A, 0xF1F1F40B, 0x050D0514, 0x0DFC0A10, 0xFF0D01EB,
+0x07F7010D, 0xF90D00F6, 0xFCEDF108, 0xFD10F30C, 0xF3F7FB06, 0xF009F8FF, 0xF808F8F5, 0xEF12F009,
+0x0C0E14F8, 0x02010E06, 0xFF00F50D, 0xF9F1F309, 0x0507EEF0, 0xF8EFFDFB, 0x05041303, 0xFC13EEF6
+
+basegraph=
+1
+
+z_c=
+176
+
+n_cb=
+11616
+
+q_m=
+2
+
+n_filler=
+8
+
+e=
+4640
+
+rv_index=
+0
+
+code_block_mode=
+1
+
+iter_max=
+20
+
+expected_iter_count=
+20
+
+op_flags=
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE
+
+expected_status=
+SYN
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_1.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_1.data
new file mode 100644
index 000000000..63c2d3b61
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_1.data
@@ -0,0 +1,684 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0xF30110EF, 0x09FB0E0E, 0xFB0BF902, 0x10FF060C, 0xF70A10FB, 0xF007F709, 0x0CF30FF1, 0xFC0B07FB,
+0xEA0FFA0D, 0xFB0B1209, 0x0709F1F2, 0x0BF1F004, 0x000EF10B, 0x08F8010A, 0xF70E0909, 0xF7EC00F6,
+0x05F2F8F9, 0x0A060D10, 0x0DFB0CEF, 0xEFF4F2F9, 0xF80DF8F9, 0xF20809ED, 0xFDFEF3FE, 0xF2FC07F9,
+0xEF12EEF8, 0x0D0FEF0C, 0x011714F4, 0xFDF902F3, 0x05020A13, 0x0A0BF5F8, 0x1517FA10, 0x0DFF04FD,
+0xED0F0FFB, 0x0C0B12F8, 0x10F205EE, 0x14EEF0F6, 0xEEF50606, 0xF701F006, 0xF2120906, 0x0FF31409,
+0x0004F9F0, 0x080005F5, 0x05000E18, 0x080BF50C, 0xE9FA01EF, 0x0DFDE702, 0xF303FC08, 0x0306FDED,
+0x0302FD15, 0xF2F404F6, 0xF60B0DFC, 0xF702F2F8, 0x0D0109ED, 0xECF2F006, 0xFFF50AF3, 0xFB0609F7,
+0xF9FAF2FC, 0xF3010611, 0xF2F20EF8, 0x0EF203EC, 0xF30C050D, 0x0CFB0905, 0x10EAF80A, 0x1103F714,
+0x17FCE4F8, 0xF409F2F4, 0x09000A13, 0x0EF009F8, 0xF00DF90A, 0x0AF612E9, 0x12F4FE15, 0x06F3F307,
+0xFDF4EEF8, 0xFDFBFB04, 0x02F30DF1, 0xE9F0F006, 0x10F80508, 0x0DFAFBF9, 0xE9F10B09, 0x020600F9,
+0x020AF50C, 0x0FED0C0A, 0x05FCF403, 0xF8F3FFF6, 0x0312FD0A, 0x0A05F308, 0x10F10E00, 0x0B0CF40D,
+0x04090FFF, 0x1402F2FF, 0xEF0D0B01, 0x0E00F9F8, 0x08040110, 0x0A04EDE5, 0xEE13080C, 0x05F6F516,
+0x05F414EC, 0xFF030A00, 0xF0F5FF06, 0xF809F20E, 0xF70CF014, 0x0FFAFA0E, 0x1201F611, 0xE10E0EF1,
+0xF40FFA09, 0x13F2F103, 0x0B030B0E, 0xF303FCF3, 0xF405FD09, 0xEF09FEEA, 0x07F908FB, 0xF9FD08FE,
+0xF9F7F602, 0x0506FCF4, 0x060BF4F3, 0x040C0E0D, 0xF5F9F606, 0x02FF0DFB, 0x0BF51112, 0x13F7F5FB,
+0xF10AF6F8, 0x15031311, 0x07F7ED0D, 0x050AF7F7, 0x0101F708, 0xF717FBF6, 0x06FAFA05, 0xF1F8EF11,
+0x11070200, 0x09EEFB04, 0x07EF0601, 0x0603FCFE, 0x0FEC140B, 0xF7F7F806, 0xF00A02FA, 0x0E06F30C,
+0xFEF90A10, 0x0AECF80E, 0xF5F2F907, 0x0B08E804, 0x0902E9F7, 0xEE09F6E9, 0xEEF60210, 0x09F7E8FD,
+0x0B0CFC0B, 0x030C0905, 0xF0F6F109, 0xF0F8F8E7, 0x100A0913, 0xF8FB0817, 0x0204FA04, 0x0FF00008,
+0x02F4FD13, 0xFCE8F208, 0x06EBEF07, 0x0DF1F1F4, 0x0801F5F7, 0xF7EB04FC, 0x0C0A15E8, 0x020B1404,
+0xF502EF0E, 0xF600F6F1, 0x090705EC, 0xF1F008F2, 0xFDF2EC11, 0xE90E02FF, 0xF615F6F4, 0xF3F3F4F8,
+0xFC0BF20B, 0xF9F90402, 0xF512F301, 0xF90E06F7, 0x0AFC080C, 0xF707FB06, 0xF0F6F1FA, 0x0806F4FD,
+0xF6F8F10A, 0x0EFBFDF7, 0xF60EF6FD, 0x0308F809, 0x11050CFF, 0xFF140CFD, 0xF7FEF80A, 0xF1F4FD03,
+0xF5EF0203, 0xF8F514F8, 0x11F808F7, 0x12FBFD0A, 0xF3F41309, 0x0D0FF700, 0xFA0B1103, 0xF50A06EF,
+0xF902F210, 0x070FFEFB, 0x0D070910, 0xEA11F207, 0x0D0B0D0B, 0xFCF1F408, 0xF70809E8, 0x06F2F10E,
+0x1DF5FAEB, 0xF7F0F20C, 0xED0C110E, 0xFBF000F3, 0x0208080D, 0x0DFCFAF0, 0x11EE0107, 0xF109FE00,
+0xF4FCF9FE, 0x0AFAF501, 0xF3E7F90B, 0x06E70B12, 0xFDFE06F9, 0x08F00C04, 0xF409090D, 0xF30C0EF5,
+0x02F6EF06, 0x12F6EB0E, 0x0DFA09F8, 0x0BF8EFF4, 0xF015F007, 0x15ED1206, 0x07050006, 0x18EF0111,
+0x0FF2050C, 0x05F9070F, 0xFCF80813, 0xF3F90611, 0xFDF30EEF, 0x00FC0112, 0x0DF1F8FC, 0x10F7FDF9,
+0xF9EA0AE9, 0xF70E0807, 0x0DF105F8, 0x100E0DF8, 0x140F14EA, 0x04F60107, 0x0D030C10, 0x0AF0F9FA,
+0xF814EE17, 0xF4F802FE, 0xFA06FFF9, 0xFCF811F3, 0xF6F5050E, 0xF5FB00FC, 0xF811F4F3, 0xF0ECEA0D,
+0x04F7070A, 0x12090F00, 0xF9FBEEF3, 0x11F8030E, 0xF5F8F7F6, 0xF90BF908, 0x0E0FF80C, 0x10EF06F0,
+0xF5F804FA, 0x06F70909, 0x08EB0F13, 0xF20E0E16, 0xF11509FE, 0x0E0BF3F4, 0xF60F0E0B, 0xFBF405F2,
+0x050AFDF3, 0x0EEC1C0C, 0xFBFBEB02, 0xF71310F8, 0xF9080BFB, 0x1612F2F9, 0xFE0DF412, 0xF50A0009,
+0xEEF0F7F5, 0x0AF11310, 0x0C02F61B, 0x0EF4FF0E, 0x03F7F8F3, 0xFF08F909, 0x0B0BF00D, 0xF3EE0A00,
+0xF0F504F6, 0xF70EFC0F, 0xF70B0BF6, 0x16F313F4, 0x060BF5E7, 0xF9050515, 0xF00908FE, 0xEB0D09F8,
+0x0C08F309, 0x0512F303, 0xEEFCF308, 0x03FF1013, 0x02F9F412, 0xFD0B10F6, 0x010A14F4, 0x091307F9,
+0x06F206F1, 0x04FE0B03, 0xF90C07F7, 0xE40400FB, 0x0BE81AF5, 0x1301F4FD, 0xEBF4E70D, 0x060EF4F8,
+0x06F7F9ED, 0xF1FEEE02, 0x13F20DFB, 0xFAE7F9ED, 0x09FF0A13, 0xF304EDF9, 0x050AF807, 0x08F0EFF8,
+0xF5F607F7, 0xF8F71400, 0x170E07F4, 0xF8F41308, 0xEFF80C0F, 0x1EF2FCF7, 0x07EF08F0, 0xF10D09FD,
+0x11F9F002, 0x0411F2EF, 0x09070E03, 0xEFF2F0FC, 0xF310FDF1, 0x090AFBFD, 0x040DF407, 0xF317F2F7,
+0xFCEF1CEB, 0xF00800F5, 0xF01109F9, 0xFCF1000B, 0x16FF0FF8, 0xF9F6FD10, 0xF80B0D18, 0x160CF713,
+0x06FE0BF5, 0x0D08F80C, 0xF4F9FB06, 0x03FBFAF8, 0xFF0C0D08, 0x03F1FD08, 0xF4EE0E10, 0xF4EAF1EE,
+0xF7F6F2FD, 0xF90FEB11, 0xFA0606F1, 0x0E06F6F7, 0xEDEAFA0D, 0x09EDF30B, 0xEF0CF202, 0xFEEEF4F3,
+0x000DF40F, 0x0FF803F4, 0xFB0DFCEC, 0x0D02EB0D, 0x01060E05, 0x1F0CF0F4, 0x0E0C0712, 0xF9071402,
+0xFD0E07F2, 0xF2F4F60C, 0x02150BF2, 0x1106E901, 0x07F50B08, 0xEEF017E6, 0x00F903F0, 0x10F4FD0D,
+0xF505F7F4, 0x090F040A, 0xFC0BEE08, 0x050F15F0, 0x07FEFFFC, 0x09EB0F08, 0x110A04F1, 0x12EEFC03,
+0xF0E8F106, 0x100DF9F9, 0x07F500FD, 0x0AF208F7, 0x12EE00F0, 0x010A0A12, 0x01EFF5F8, 0x12090BF3,
+0xEDF601F8, 0xF7FEF005, 0x04F40EF5, 0xFB1C06ED, 0xF3120BFB, 0xF006FE05, 0x130AFCF0, 0x0A0807F9,
+0xF907ECF9, 0xF600F701, 0x03F9EDFA, 0x0714F8FF, 0xEF0B0F0B, 0xF216F9F7, 0x10F70A04, 0xFAEEF4F2,
+0xFA0B04F1, 0x02040AF9, 0x13020DF3, 0x08150603, 0x0FF804F3, 0xFFEB0BF8, 0x050FF8EF, 0x08F607F9,
+0x03F7F3FD, 0x04FBF5F0, 0xF910ED00, 0x05F7EE0D, 0xF30C0A12, 0xFBECFEF7, 0xF2F30BF0, 0xF203F9FD,
+0xEC16EB04, 0x03E4FEF3, 0x03F60200, 0x0802F4FF, 0xFE010A05, 0x06F0170C, 0x050F0C02, 0xFEEC100D,
+0xFAF7F307, 0x04FA10FA, 0xEFF5F901, 0xF5020808, 0x0809F2F5, 0x03FF09F8, 0x0604FC05, 0x01EE02F7,
+0xF4FC15F9, 0xFD05F70C, 0x0FEB05F7, 0xF9F2080B, 0x0C11EEF6, 0xFBFAF00E, 0x0D030BF2, 0x0BF7FDF4,
+0xF1F30A06, 0xF7F5F9F0, 0x031AF90F, 0xF8000608, 0xF4EEF509, 0xF20202F6, 0xFA0B050F, 0x0F0F070D,
+0x09EDF8F6, 0x040AFAF7, 0x0B0F04EB, 0x08ECF8FA, 0x0EFB00FC, 0xEDF00300, 0xFD03F8F4, 0x0AF90411,
+0x0B001401, 0xEFF0FCF3, 0xFFF8FEEE, 0x0508F2FC, 0x0EF3FB0B, 0xEC0CF6FE, 0xFD0B0702, 0xFEFE0404,
+0xFB0F0DF3, 0x0AFCED03, 0xF4F20709, 0xF2040FF9, 0x0A070005, 0xF4F1030E, 0xEE0BF20C, 0x1514F1F6,
+0x0D130B11, 0xF5030BED, 0x11EEFB13, 0x02EDFE03, 0xF8F7F80F, 0xF3F9FBF8, 0xF5051604, 0xF7FBF001,
+0x0A0C0408, 0xF6ED07F7, 0x1A020DFE, 0xFD060C18, 0xF5010BF9, 0xF6ED0308, 0x04FAFA16, 0x0D060FFC,
+0xEFFCF7F3, 0xF50EF5F8, 0x0F0CE90E, 0xFB0E13F0, 0x0517F30D, 0x0CF302F9, 0x0C0FF705, 0xFBFE0501,
+0x0905FF00, 0xF9F3F81B, 0x0D0BF0F4, 0xF10712F5, 0x0303F80A, 0x0EEE0509, 0xFDF4F600, 0x16F4FE01,
+0xF509F70A, 0xFA0C0A04, 0xF60FF902, 0xF3FC02F9, 0xF4FDEE0C, 0xFC0D0710, 0x0AEA0009, 0x0AF0040F,
+0x090BEEF7, 0xFFF3F4F5, 0xFDF718EF, 0xF8FCF7FC, 0xF70AEA12, 0xFC0601FB, 0xF4EC0F01, 0x0F021100,
+0xF70A080E, 0x0D02F702, 0x08FE090D, 0x0DF3F6FC, 0x0FF20809, 0x0DFCFD0C, 0xFAF20EEE, 0x10FB1206,
+0x150CF410, 0x02F9160B, 0xEBF4FB0C, 0x04FDFCFC, 0x09F8FE0B, 0xF7FCFC06, 0x0D02F9F3, 0x0CEF08F9,
+0x0509FC11, 0xF80CEB11, 0xF2EFEEF3, 0x07F8080A, 0xF8F30C0C, 0xFC091400, 0xF10E110F, 0x0CF80616,
+0xF913F20D, 0x08EE090D, 0x0902FF09, 0x0C0BF8F0, 0x0A09F8EF, 0x0D0AF5F5, 0x0E1412FA, 0x05F7EAF6,
+0xF807050A, 0xFCF5F613, 0x0A120BFD, 0xF509ECE5, 0x0D0D100C, 0xF2F30805, 0xED02040D, 0x0900FB06,
+0xF4070EFE, 0xEFFAF7ED, 0x1017F60B, 0xF807F6FE, 0xF100F9FF, 0x0912F413, 0x0E020BFD, 0xFF02FCF6,
+0xF308ECFA, 0x020A0AF4, 0x09F7FEF1, 0xF406EAFA, 0xF7F70D1A, 0xF708EF07, 0x100CFC0B, 0xEFFBF4F2,
+0x0E05FDF7, 0x07F3FDFD, 0x0109000F, 0x0D0606F4, 0xFAF3F307, 0x13F1F4FE, 0x01EBFEFA, 0xFF08F005,
+0x0707F00D, 0x0808FC10, 0xFC120514, 0x09F600F3, 0xF7060907, 0xF502F8ED, 0x10010C0F, 0x0C0DFC08,
+0xFB0FFCF2, 0xF709F7F6, 0x08F2F40C, 0xF70BF6F8, 0x03F608F4, 0x051BF9FC, 0xFF07080C, 0xECECF6FB,
+0x0BF307FD, 0xF213F7FA, 0x03FCF5F4, 0x04F8FEF7, 0xFBF7FEF4, 0xFC0C0209, 0x13E901F9, 0x02F0F401,
+0xF5F30E05, 0xF111F6F1, 0x0008E4FA, 0xF9FAFAEC, 0x07F4090F, 0x0EF8FBF8, 0x000BF70A, 0xF5F608F7,
+0xEC1207F4, 0x04070AF0, 0x01FEFAF3, 0x13FD03F5, 0xF80E09F1, 0x04090907, 0xEAF70FE9, 0xF10904FF,
+0x0A0C090F, 0xF7EAF0F6, 0xF7010406, 0xF8040B03, 0x0007FE09, 0x13F5F8E7, 0x0CF7F30C, 0xFA0AF5F6,
+0x09FE0AF1, 0xF1FA0314, 0xF3190A03, 0x12F0FAE5, 0xF80BF911, 0xF6F411EF, 0xF40C03F3, 0x02F0F1F8,
+0x0F03ED07, 0x0A1204ED, 0xFEF4F205, 0x0AF3FF01, 0xF7F3FDF5, 0x05F9FBF4, 0x03F8F309, 0x0F0BE90E,
+0x09F90BF8, 0xF6F7EAEB, 0xFEF40706, 0x12F10F0B, 0x06F2F2F6, 0xFAFB14EE, 0x0E11FBF2, 0x0EECF811,
+0xFAEEFCF6, 0x0E07FD16, 0x0D100AF0, 0x0E08FC09, 0x0500EF10, 0x12EE080D, 0xF9F700F0, 0xF7070DEC,
+0xE500FB05, 0x0C090E06, 0xF5EB030B, 0x0F0D0DF5, 0x00110A0C, 0xF6020912, 0xF504F9FA, 0x0DF303F7,
+0x1002060C, 0x0FEAFB02, 0x0A1108F1, 0x0505F608, 0xF807EFF7, 0xED0107FA, 0xEE0D0A0D, 0xF9F60C0E,
+0x10F60A0C, 0x0BF71611, 0xF6F407F1, 0xFD010708, 0x0DFE0101, 0x0EF7FFF6, 0x04F7EBF9, 0x0C0FEF0F,
+0xFD010B0A, 0x11EFF5E7, 0x0C02F5F6, 0x08090B09, 0xFE09F5F8, 0xFF0F14E8, 0xF40013F6, 0xF1FDFAFE,
+0x0006F6F5, 0xFAEF0108, 0x0F0FFC0F, 0xF01009F8, 0x0AF4EF0B, 0xF304FB19, 0xFEEE0EFD, 0xFEEF0908,
+0xF3F5F507, 0xF7071011, 0x0C0111FB, 0x04F20909, 0xEF13F20A, 0x040BEEFA, 0x0F0CF1F9, 0x09FAFC12,
+0xF4F2F9F2, 0xFEE80B09, 0x0AFEFC00, 0x08FAF1F8, 0xF5FCFEF8, 0x03F20AFD, 0x0FF1F4FD, 0x13F8FA05,
+0x0A09FE12, 0x07F100F7, 0x07F8F50B, 0x07091503, 0x08F7F00B, 0x06F9FDEF, 0x08F5EEF2, 0x0F0D0C05,
+0x02FF0D0E, 0x190A0E08, 0xF4EEEB00, 0x0809EDF5, 0xF1130914, 0x0D080DF9, 0xEFF6000A, 0x020A10FE,
+0x08050AF0, 0xF5E50610, 0xF7ECF0FA, 0x1004101E, 0xF7FFFB05, 0xFE0602FD, 0xF6F1F7EF, 0x090DF811,
+0xFF090412, 0xF9F402F8, 0x0301FE06, 0x160DE009, 0x1AF30008, 0x12FAEAF6, 0x0FF8FFF1, 0x13FE0E14,
+0xF2EEF903, 0x070D0202, 0xEFFAFCED, 0xF1F00BFD, 0x04E9F103, 0x01F20EF2, 0x150CF60D, 0xF6E9EF04,
+0x05F810F8, 0xF50A0A00, 0xEF090D09, 0x05F40DFA, 0xF4FAF61B, 0xF9F408EF, 0x0B0DF00B, 0x0FFC0F0D,
+0xF608FCF5, 0x04F2F7EE, 0xFA0FEE12, 0x0700F90E, 0x070FF911, 0x02F0EEF5, 0x01F905F4, 0xF604F9FE,
+0xFC1404EB, 0xF10BFFF9, 0xEBFB0CF9, 0x0817020C, 0x0C0EF306, 0xF1030EF3, 0x05F7080F, 0x03010EF8,
+0x0CEFF9FD, 0x0C14F6F8, 0x0EF5F5F2, 0x08F4F212, 0x090CEF01, 0xEF0AFEF6, 0x0A09060D, 0xF9F7FB11,
+0xF6F9F50C, 0x14F6F60D, 0x0DECFEE8, 0xF60914F0, 0xF814F40C, 0xF5EC1106, 0xEF0D00FA, 0xF0FDFA09,
+0xFCF70BEF, 0x11EA0301, 0x0BF805F6, 0xF103090A, 0x11FCF0FD, 0xF4F3FDF5, 0xF6F5F100, 0xF8F40BF3,
+0x0DEC0BF5, 0x14F316ED, 0x070A0CF6, 0x11F30513, 0xF8FA0B0E, 0x0DF8EDEF, 0xEE0D07F4, 0x100A050B,
+0xF5F7E2F5, 0xFCF1EFF0, 0xF309F6F4, 0x080D120A, 0x0BEEFDF7, 0xF21010ED, 0xF0ED0BFE, 0x040EFA0E,
+0xF5F30806, 0xFDF408F9, 0x0EF8EAFF, 0x060503FC, 0x0CF705F2, 0xF413F9FB, 0x06F608F7, 0xF5FFEE07,
+0xF4F80FF6, 0x0C0AEEF2, 0xFB1E06FF, 0xF40DF8FA, 0x160B0909, 0xFCF6F0EE, 0xF403020B, 0x04F10713,
+0xFDF3FDF5, 0xFDFAFBF9, 0xF808060C, 0x0BFAF40C, 0x01F6EB07, 0xFC0BF7F8, 0x070209FB, 0x0809EBF9,
+0x04FD0B08, 0xECF5F90B, 0xF31500EF, 0xF8F7E9F5, 0xEE00F5FB, 0x1C0B0CFA, 0xFCF00809, 0x070103FA,
+0x09FE0905, 0xFEEAF402, 0x0EFCFF10, 0x150C0BFB, 0x0BF20714, 0xF3FB0DF7, 0x03F1F9ED, 0xFA13F205,
+0x09F2FA16, 0x02FAF201, 0xFDFFF7F4, 0x06FD0EFB, 0x0F04F20C, 0xFCEEEB0B, 0xFF0513FD, 0x03FA13FB,
+0x0BF707F4, 0x03FE0AF8, 0x000203EF, 0x0BF6F708, 0x0DE60203, 0x00F30901, 0xF1FA06F7, 0x140305EE,
+0xFCEAF6F2, 0x02F10A09, 0x01FEF6F5, 0xFAEFFD0B, 0xF711EB15, 0xEEFF05F3, 0x01F3F409, 0x03ED0209,
+0x10EE090D, 0x060207FF, 0x070F04F9, 0x0EF6000D, 0x0F0707FA, 0x0A03060A, 0xFE06040A, 0x0CF50DF4,
+0x00FE1AF1, 0xF114FA0F, 0x0BEE10FF, 0xFFF6F9FC, 0xED000F06, 0xF6070703, 0x10040DF7, 0x06FBF9EF,
+0xF4090CFC, 0x050AF6F0, 0xF10F06F9, 0x0EF90B0A, 0x0902FFF8, 0xF8F2FBF7, 0x13FBFB0E, 0xEBFFEEFB,
+0xF409F50B, 0x0C090E07, 0xEC0F0A02, 0xF60B0818, 0xF9040505, 0xF90BF50C, 0x030AF5F9, 0x0A12EEF8,
+0x0A0003F0, 0x00090BF4, 0xF907040A, 0x08F01510, 0x10050FF1, 0x13EBF7F1, 0x110CED11, 0xFB0507F9,
+0xFDF3010B, 0xECE8F505, 0xF90B0CF3, 0x0D1203F7, 0x05EFEFFC, 0xF4EFFA11, 0x05FC0A0F, 0x12EF09F7,
+0xFDEF0A10, 0xF6E70B09, 0xF7FB06FD, 0xFFF5040C, 0x0605F0F0, 0xF8F7EDF8, 0xF7FC1AF7, 0x00F60109,
+0xFF0FFA00, 0x09EAEEF8, 0x0B0BEA10, 0xFFFB0DF4, 0x0006F4F5, 0x13F70F11, 0x04FBFA01, 0xF1FAF912,
+0xF5F3040C, 0x0502ED0B, 0xF7FAF804, 0x03070A14, 0x1207F108, 0x0906F701, 0x0E0D070D, 0xFFF20C11,
+0xF9F2F6F8, 0xFEEE12F6, 0x08F1F0E8, 0x08F0FC09, 0x1306FEF7, 0xF907F8FD, 0x0DEF0C0C, 0x0114FFF8,
+0x0CF906F6, 0xF3F0F10D, 0xF7F5F40B, 0xECF2050B, 0xFD0604F7, 0xFCF9F60C, 0xFE02F6F7, 0x0B0607FB,
+0x130AE809, 0xF8F7FCF2, 0xF6101108, 0xF0FA0405, 0x02091013, 0xF60E06FA, 0xF50DED03, 0x1205FD06,
+0xF90CEDF6, 0x01FC00F4, 0xF8FCFEFC, 0xEE0303E8, 0xF4140C11, 0x11F3F4F3, 0xF6091406, 0x0CFC0BF4,
+0x04F911F7, 0x0DFB050B, 0x0FF8FA0D, 0x0BFC0802, 0x0608F9F2, 0xF2F2F904, 0xF8EFF20B, 0xF5EEF30E,
+0x080E0EF3, 0xEFF00600, 0xF6ED0DF1, 0xF6FB14F6, 0x0A0F0EEB, 0x0AFA08F5, 0xF90CFB0B, 0xFB06F2FC,
+0xF1F8F70F, 0x16F01209, 0x0FF7F306, 0xF4F0F6F7, 0x0B070BFC, 0x01F70D05, 0xFB020709, 0x0C0A0EF0,
+0xFDF2ED0F, 0x0BFF040D, 0x06FA0406, 0xFAEAF515, 0xFBED0AF3, 0xF208FA16, 0xFFF9F2F5, 0x0A00F10E,
+0x06FA1104, 0x10EF0CF7, 0x0C08F914, 0x010FEFF6, 0xF9FA0A02, 0x0BF112FE, 0xF0F30206, 0x1208FB05,
+0x0DFD05EE, 0x04F60410, 0xF9161006, 0x10F8FE06, 0x0AFCE7EF, 0xEAFEFC0D, 0xFFF6FC13, 0xF40704F8,
+0xF909EDF9, 0xEA0C0808, 0x16F0F6FB, 0xF50DF6EB, 0x06F4F7F4, 0xF1F0010E, 0xF5F2F80A, 0xF8F806E7,
+0x0CF2FA0D, 0xF8F3F7FA, 0xFE04FBEE, 0x0CF9F70D, 0xEF0E0800, 0x0AF1EEF4, 0xF0FFF2EC, 0x0A09FBEF,
+0xEF0EEFE7, 0x13FEF50B, 0x0B0FFC0E, 0xFDF701FA, 0xF3FEEDF4, 0xFAF0010C, 0x0DF909FC, 0x08FAF3EE,
+0xF9F70203, 0x0916FE1A, 0xFD10F4EC, 0x05F70F0F, 0xFE1108FA, 0x11F6FAF0, 0xF1FBF20B, 0x171003FD,
+0xFE0303FE, 0xF3F6FC0C, 0xEA0810F3, 0x060AF4FF, 0xEE0613F0, 0x09F60FF6, 0x071602F3, 0x00F5F2F7,
+0x04EB01F7, 0xFBFDF9FD, 0xEBEFF7F4, 0x070C0CF8, 0xF5090B10, 0x0FE3F6EF, 0xF6FFFF12, 0xEEF7F8F6,
+0xF50206F1, 0x0A000A14, 0x010E0AF2, 0x0603F010, 0xF4EBFBFF, 0xF011F617, 0x12100108, 0x0017F5FA,
+0x0CF8020E, 0x0D0DF9F9, 0xF0F5EF11, 0xF1FCF8F0, 0x06EEECFC, 0x06141703, 0x0EF1FD00, 0x0D00F810,
+0x03060A12, 0xF011F60A, 0x10FA0EEF, 0x03F5FB05, 0xF5040DF4, 0xF6F408F3, 0x0809EFEF, 0xF1060F12,
+0xF115050C, 0xF909F00C, 0xFA130E06, 0x0E04F7F4, 0x080D11ED, 0xFD0B030C, 0x0CF1F610, 0x12F0EDF6,
+0x0810F708, 0x05FC050F, 0x050E1408, 0x05F3F9EF, 0x0AEC10F8, 0x0D0B100A, 0x01FAFF0C, 0xEA0CF9F8,
+0x010E0DFF, 0x07F70BFB, 0x140F0AFC, 0xF90F0DF5, 0xF1EDF4F8, 0xFC0D02F4, 0xF30CF80B, 0xE902FC08,
+0x0FF2F2F2, 0x07F5F710, 0xF8FDFFF1, 0x04020908, 0x0C04F5F1, 0x0C06080B, 0xF0E6F507, 0x03F8FEF6,
+0x00ED0CFF, 0xF8F40E15, 0xFAEBF2EC, 0x02E801FB, 0x09F30D0F, 0x13081405, 0x070FF509, 0xF90005F3,
+0x02F6F0EB, 0x05FAF30D, 0xFDF8FB06, 0x0C0BEFEE, 0x13F0EF0B, 0xF1041808, 0xEEFBF609, 0x10F4FFF5
+
+harq_input0 =
+0x0FFA0103, 0x130C0B02, 0xF309F6E7, 0xF70F07F1, 0xF7090FF8, 0x050409F2, 0xF80AFAF7, 0x00F60EF5,
+0x06FC060D, 0x080DFB03, 0xF4EDF9F9, 0xFCF9FEEA, 0x0F0C12F8, 0xF9F31708, 0xF60C02FF, 0xFF110310,
+0x0BF80F0F, 0x02F6F2EE, 0xEDF20A06, 0x0709FEF2, 0x14F5F0F0, 0xF70C0018, 0x12020FEF, 0x0602EF08,
+0xF40A0200, 0xEE0C0BFC, 0x0606ED01, 0xF2F709F3, 0x15110E10, 0x06EC06F8, 0xFBF10CF8, 0x0314FEF6,
+0xF5F4FC0C, 0xF00C00FF, 0xF6FDF9F6, 0x07F30801, 0x0F04F40C, 0x0406F305, 0xFAF9F808, 0xF20DF109,
+0x010A0AF8, 0x070AFC03, 0xF108120A, 0xF8F9F1EC, 0xEEEB09FF, 0x140C0D01, 0x04E5EF10, 0xF616130C,
+0x0314F4EC, 0x09FA09F2, 0xFAFAF714, 0xFAF101FD, 0x06030FF4, 0x17F3EFFA, 0x09FEF109, 0xFDFEF9FB,
+0xF2080B02, 0x0CF90B07, 0xEB0F0D06, 0xF71009FE, 0xEF110AF8, 0x0AF70BF9, 0x170A1508, 0xF8FDFAF1,
+0x0204F3EB, 0xEFFE0315, 0x0C06000B, 0xF10C0A0E, 0xEC0EF9FC, 0x08F0F2F3, 0x09FD02F7, 0x0B11F610,
+0xF8F1F8F7, 0xF8FB0A09, 0xFB030A13, 0x040804F0, 0xE8080813, 0xF1F4FFF3, 0xEBFCEDF7, 0xF7F00AE8,
+0x00F1160E, 0xF007F301, 0x0E13F211, 0x07F815F4, 0xF9EEF70B, 0x0EF7FE15, 0x0706E80C, 0x0611F60E,
+0xFB0B0CF5, 0xF4F50E11, 0x14FDF1EB, 0xF403120A, 0x09F80303, 0xFB0AF80B, 0xFA1408F5, 0xF503F717,
+0x0FFB1610, 0x1107F3FC, 0xF1F4F7F7, 0x060EF4E8, 0x04F8F5FF, 0x04F30CFA, 0x10F008F8, 0xF514EEF3,
+0x0EEDE8FE, 0xE7FEE70B, 0x0404FEF9, 0xF8F509F9, 0x0A0EF6F2, 0xF8080EF8, 0x01F200F3, 0x03FC19F2,
+0x0D0FF2F8, 0xF9FD0C13, 0x11FE0703, 0x0BF9F110, 0x0EF3FEFD, 0x0EF8F10C, 0x0A070FEA, 0x04FA0310,
+0x0CFE0003, 0x0CF3060D, 0xFBFCF5FA, 0xEC0D1108, 0x09ECF70A, 0x0C0EFB08, 0x0BF4F80A, 0xEFF0FB0C,
+0x0B09F8FA, 0xFA16FF13, 0x0B081512, 0xF4F2FBF7, 0x000C0A07, 0x130C0FEE, 0xFEF908FB, 0xF6F5F912,
+0xF1100409, 0x090E1606, 0xF4F50BF3, 0xEE00F7F9, 0xFAFBF5F6, 0x07080B0A, 0xF1150BE7, 0x0DF80912,
+0x12EF0809, 0xEBFF1108, 0x0BF60DFE, 0x130DF608, 0x12EFF2F1, 0x04FB0C0B, 0x01FDFC09, 0xFAF808F9,
+0x12020B01, 0xFCED060F, 0x040DFFFF, 0x04F80AF3, 0xF700F60B, 0x08F40E08, 0x06F7F80F, 0x0DFDEF04,
+0xFDEFF916, 0xF21107EF, 0x0A1110F1, 0x03F70DF3, 0x08F50300, 0xF1F711F9, 0xF6FCFF0C, 0x0CFFF704,
+0x080CFE09, 0x0FF80D06, 0x05080C08, 0xFE020210, 0xFB11F6E9, 0x060BF2F1, 0xED0BEAF9, 0x02F30C02,
+0xF8F40DFB, 0x020D0D01, 0x0CF406F1, 0xF302F812, 0x080C0EF2, 0x06010006, 0xF0FA0908, 0x08F9F905,
+0xFB0A0508, 0x0FF0F7F4, 0xFF081210, 0xEE18F6F1, 0xF9F9E8F2, 0x060B09FD, 0x0AFEEE04, 0x09F304F8,
+0xEA05F6F8, 0x1C0108F5, 0xF205120F, 0xF40D0A04, 0x0001F30D, 0x00FF0DFA, 0x020BF7F7, 0x02F2F7F0,
+0x04F90BF1, 0x01EFEE07, 0xEBE4F807, 0x0AF90FEF, 0x0F040B11, 0x0BF91000, 0x000CF812, 0x0311F3F0,
+0xF8070218, 0xEDFFF614, 0xF00C15F1, 0x000D0F16, 0xFA0EF707, 0xEE080901, 0xFF0C09F5, 0xEEF704F1,
+0xF10C10F9, 0x060BEBF7, 0xFA0EFDF6, 0xF7F403F2, 0xF5F0F306, 0xEC081A0F, 0x020AEEF5, 0xFBF9F7FB,
+0xF60C010A, 0xEC0E0FFF, 0xF014FB10, 0x0EFD0308, 0x04F30015, 0xF4FC0CEE, 0x0CFEF3F7, 0x12F0F702,
+0xE803FB07, 0x040D06F5, 0x05FA07F1, 0x140A0BF8, 0xEFEDFF11, 0x01EFEE13, 0x0D0C0B0F, 0xE70105F0,
+0x01F70CF4, 0x0603EE12, 0xED08EDF9, 0xF2FCFA02, 0x0E0CFCF3, 0x0E04F8F9, 0xF30D17F9, 0xFEEDFB05,
+0x071BF114, 0xF309F7F4, 0x02F503F6, 0x0815F400, 0x0CF0090A, 0xE80D0F02, 0xF9FCFDF8, 0xF00FFEF5,
+0xF3F5F70B, 0xFC10F7EF, 0xF2FB0AFE, 0xEEECEC15, 0x0202F60E, 0xF310FEF9, 0x10F8F209, 0xFB0606EE,
+0x0D0B0C10, 0x1110080C, 0xFCF2F8F6, 0x030DEE07, 0x0C11F511, 0x0CF6EF08, 0x0900070C, 0x0C160E0F,
+0xEEF8FFF9, 0xF7F0EEF5, 0x0A090903, 0xF70A000E, 0xF5FF07F6, 0xF5E5FEFD, 0x08F1F80C, 0x00F2EE0D,
+0xFAED07EA, 0x07EA170B, 0xFEFFECFF, 0xED0B0211, 0x0AF4F4E6, 0xF2FAF705, 0x0807F706, 0xFBF2F8F7,
+0xF31105F7, 0xF10809FB, 0xF1FEF307, 0x0805FFFA, 0x08FC070D, 0x0A071200, 0xEEEDF107, 0xF908EDFB,
+0x09F60FF2, 0x0B0C06F8, 0x07FCF608, 0x000FF30C, 0xFF0EF3FD, 0xE40BFCF4, 0x0CF50BF4, 0x04EDE90D,
+0xFD05F3F1, 0xFAECF4FA, 0xF80C080F, 0x0A0BF70A, 0x07F012F4, 0x1109FEF3, 0xF507F9F1, 0xF513F7FD,
+0xFE0AF80F, 0x041701F1, 0xF5E7F309, 0x0A0AF70C, 0x0E00FEF1, 0x04E505EF, 0xF4EF0BFD, 0x040CF807,
+0x1201EF07, 0xF31508F1, 0xF908F309, 0x0B0EE409, 0xF7EBF9F8, 0xF1F7F406, 0xFB0206F6, 0xECFD11F2,
+0x0702EEF6, 0xF409FC04, 0xEEF80010, 0xF3EC0BF0, 0x090600F1, 0xF9F5EBF7, 0xEEFE11F8, 0x070BF0FA,
+0xFE16EEF8, 0xF108FD05, 0x15FAF3F7, 0xF60E0D0D, 0xF7FC0AF8, 0x01F40805, 0xF70AFE01, 0xFB0F0BF9,
+0x04E701F6, 0x09F517F6, 0xFBE8F5F8, 0x11FE00F6, 0xEF08F2F5, 0xFB0CFB0F, 0x0419080B, 0x0308EE11,
+0x07110907, 0xF2F5ED0F, 0x0BFAFEF6, 0xFA12F8F9, 0xE8090606, 0x0E0CEAEC, 0x06FD10F8, 0xF80505FD,
+0xF1F70912, 0xF5EF0C0B, 0xF9EF0B0B, 0x0D05F5F2, 0x0A08FF0E, 0x09F50300, 0x08F91314, 0x0AFEF60A,
+0xE5FC0504, 0xEF0A000E, 0x06FDFFF1, 0x0D11F103, 0x080CF512, 0xF9F501F2, 0xFAF60708, 0xFE140D05,
+0xF90202EF, 0xF0FD0EED, 0x06F2E903, 0xE904F80D, 0xF600F8F8, 0xF4FA09F5, 0x0803FA07, 0xFCF9F90B,
+0xF202F4F5, 0x000EFBFE, 0x0409FAFD, 0xF0EA0DF4, 0x0B0D00FF, 0x03F8FB0D, 0x0307FAF2, 0x010C0BFB,
+0x140C03FD, 0xF4FE0906, 0xF6F6F8ED, 0x0B11090D, 0xF6F90EF8, 0x09F001E8, 0xEC0600F8, 0x1109F90E,
+0xEA010BEF, 0xEF0A0C0A, 0x07F510FD, 0x08F3F500, 0x07ED01F5, 0xF313F60A, 0xF803FA0E, 0xF60B0D08,
+0xF1F0F709, 0x0DF609F4, 0xFCED020B, 0x0E0EEDE9, 0x08F907F2, 0xF1FC0C13, 0xFFFB0C06, 0xEB070AF7,
+0xF606F80A, 0xF90E1EFF, 0xF6EE0BF5, 0x05FF03F7, 0x0F0DF309, 0xFA0CF4F8, 0x1F0CF6F3, 0xF50DEE0F,
+0xF5F7FDF4, 0x0BF501EF, 0xF7FA000F, 0xECFAF0F5, 0xEA02FEF1, 0xF80FFCFC, 0x100B0600, 0xFF050501,
+0xFA150716, 0x110FFFF4, 0xEE0B04F8, 0x0E0FF112, 0x12F80BF4, 0xF6F41604, 0x07EDE6EF, 0x17EE0F0B,
+0x05F5FEF2, 0xEF0BFEF5, 0xFF07FD15, 0x01090709, 0x02EBEE0D, 0xF6F9FB0D, 0xEFF6070E, 0x090806F6,
+0x140FFEF1, 0xF6FCEEEB, 0x07EF14F2, 0xFB03040B, 0x0A05F4FC, 0x0DF6FB0D, 0x060B02F8, 0xFF0FFB0E,
+0x090709F7, 0xF7180F02, 0x0BF8F005, 0xFE0CF60D, 0x09F4ECF0, 0x0410F30A, 0xEB05F105, 0x05F90C11,
+0xFCF1F30B, 0x120B0BF3, 0x031104FC, 0x030BFC0F, 0xFB09EFFC, 0xF50CFB11, 0x0BF80504, 0xF609FCF7,
+0xFE0CFB00, 0x0F08F7FB, 0x0BFD0609, 0x0E120F15, 0x020B07F8, 0x0714FAF0, 0x0615F308, 0xF2FDF8F9,
+0xEEF606F8, 0x050906E8, 0x071106F7, 0x000C03F8, 0x04F9F90A, 0x060BF5F7, 0x0D0CF2F7, 0x06FB02F7,
+0xF7060AF5, 0x0EF1FCF4, 0xFAFAF5FE, 0x0506F917, 0xFCF40C0A, 0x03FC10E8, 0xF30700FD, 0xFCF40906,
+0xFB0B0D0B, 0x1017E4F9, 0xF20408F2, 0x02FA03F7, 0xF0000E07, 0xFB0AEDF1, 0xE6F50FEB, 0xF2FCF80B,
+0x04F50DFB, 0xF00BF706, 0xF70507FC, 0x0AF01609, 0xFF0DF20F, 0xEA150EF2, 0x080202F3, 0x00FAF9F5,
+0xEFF70E04, 0x0FF6F314, 0xF1FEFAEE, 0x08F1F3F2, 0xF6101102, 0xF8F20206, 0x120DFC03, 0x07F8F613,
+0x0CF4F50D, 0x0DFF05FB, 0x040EF409, 0xF8FB06F6, 0xF3FAF20D, 0x0DF90402, 0x05080E00, 0xF5EFEBEC,
+0xFE0B0EE7, 0x0B0E0F0E, 0x04F812F4, 0x0EEE0D10, 0x021AF7EF, 0xF70F10EC, 0xF604FDFA, 0x10E90F0B,
+0xF60CEFFE, 0x0AEBF407, 0xF60A06F0, 0xF50B1607, 0x1111FF0B, 0xF8F8EF08, 0xF704F410, 0x0B0AEBFE,
+0x14000205, 0x03FC0EF2, 0xFD17EBFF, 0x17FAFCF4, 0x0DF90CFA, 0x1004F511, 0x140302FC, 0x14FC0500,
+0xFCF6F2FE, 0x0905FA03, 0x08F3F0F4, 0x06FEF5EF, 0x09F801F8, 0xF00913F1, 0xF7F80DED, 0x040AF1FC,
+0xFC0F1008, 0x07040EF4, 0x0BF6EC0C, 0x0CF8FA0C, 0xF70F0EFF, 0xFB09FBFC, 0xF9F4ED0D, 0x02F4F80B,
+0xF5FCF2F2, 0x0208FDF1, 0xF20B0405, 0xF80AFAF3, 0xF415EDEA, 0xFDFBEB00, 0xF4F1F30F, 0xEC070F09,
+0xFA0D0AFF, 0xF7EE0C06, 0x04F4F00B, 0x08F50FF5, 0xF50EF3FC, 0x1006E7F9, 0x04F7F7FC, 0xFC070CFB,
+0x0F12EAFA, 0xF7F00706, 0xF4011505, 0xF7140B09, 0x0AF9F1F8, 0x03060DF8, 0xF2090CF8, 0xF20712F3,
+0xF903EFEE, 0x1102EC14, 0x0A09F1F6, 0xF9F001FA, 0xF8FE01FB, 0x140410F1, 0x0B0402F2, 0x0F0006F5,
+0x0805ECF9, 0xF409F10E, 0x0DE7FD01, 0xEFFD0710, 0xF20403FD, 0x0BF2F6F9, 0x0004F909, 0x0F09FFF6,
+0xF3060DF2, 0x0EEF060E, 0x0CF40705, 0xFDF7FB0C, 0xF4F203E4, 0x0E09F4F6, 0xF5FE04F9, 0x06F3FEFE,
+0xFDFB1102, 0xFD04EE0D, 0x0DFBFCF1, 0xEE14E90B, 0xFB0CEE09, 0x0C13F108, 0xF60703FD, 0x0BF4FCFA,
+0x14F2F0FB, 0xFAF9EFF7, 0xF5010801, 0xF109EEF3, 0xFF0A0514, 0x0C0604FF, 0xFB0EF704, 0xF50EFD0B,
+0xFF05F4FA, 0x07E70B0B, 0xEFFEF4FD, 0x0D0807F3, 0x05100DF6, 0xEFFA1A08, 0x020D090A, 0xFFF5F7FD,
+0x1513F10A, 0xF10BF2ED, 0x0B0F150B, 0xF10306FA, 0x09FB11EE, 0x061007F2, 0xF7F8FB14, 0xF90704EE,
+0x0AF8EAF6, 0xF7E809F9, 0x02F609E9, 0x09E802EE, 0x03F50BE8, 0x040C04F1, 0x0CF41009, 0xFB00EEFA,
+0xFC071611, 0xF9F1F203, 0x0BF0F409, 0x0214F801, 0x0A0AF504, 0x0508F5F1, 0xE916E900, 0x07F4F60A,
+0xF9F010F2, 0xF906F507, 0x0BFB0AF4, 0xF408F0F1, 0x0EFD0A06, 0x03F80AF6, 0x130CFD0C, 0xF1E9F7F8,
+0xF800F502, 0xFEFDFDF4, 0xF90B0713, 0xF506FAFD, 0x0712F9F2, 0xEAF20DF5, 0x10F40D0D, 0x06050B09,
+0xF706090E, 0x0F00ED11, 0xF90E02F4, 0xF1FEFCED, 0x0AF5E00D, 0x06F7F3F9, 0x08F81206, 0xF30EF4F5,
+0x12FF02EF, 0xF7040DF4, 0x151204F0, 0x04ED07EC, 0xF0F3FB05, 0x08F2FCF4, 0xECED11FA, 0xFC110DF8,
+0x0BF4F90A, 0xFCF9F905, 0xF0010014, 0x0A0EF9F8, 0xF4020C02, 0x10FDFA13, 0xF5000B05, 0x05EAF808,
+0xFE0F04F3, 0xFDEFF9EE, 0xF9F9090B, 0x10F20E0C, 0x060909F0, 0x060EF40F, 0x0E0705F5, 0xFB05F6F9,
+0xFA1C0512, 0x0B10FBEB, 0x16F20DF6, 0x090012F4, 0x0A13020B, 0x0EFF0C0A, 0x130DEF0C, 0x070A0B04,
+0x0BFCF004, 0x02FF0BF7, 0xF9F1F209, 0xFFF5F008, 0x05F30C07, 0x03FCEE07, 0x11FCEE08, 0xF4F31514,
+0x040B06F2, 0xE400F9F3, 0x13090B1A, 0xF2F4FFE7, 0xF1EE06F9, 0xFA0DFF0D, 0xF3ED09F6, 0xF40305F8,
+0xF8FFF507, 0xF8FF1707, 0x0AFC030C, 0xF109F3F4, 0x0406FDF0, 0xEF04F50E, 0xF5FBF3FD, 0xF30704F4,
+0xF0ECFC1C, 0xFCECF0F5, 0xF911160F, 0x020B0C0D, 0xF90C060B, 0x03FA08E7, 0x0311FF0D, 0xF405F4FA,
+0x0DEBF7F2, 0x0EF6FAF2, 0x09F3ED0E, 0xFE08EFF2, 0x0F170008, 0x0DFF0FFC, 0x0BF0ED0E, 0x0D140E07,
+0xF2F611F3, 0x11E9020B, 0xEE03F3F7, 0xFCFD00EF, 0xF518090B, 0xF11510EE, 0xF5FB07FF, 0xFEFC11F0,
+0x100DF006, 0x0AF4F300, 0xED0A1200, 0xFEF7EDF5, 0xF7040101, 0x0FF2040E, 0xF01207F7, 0x0AF3FF10,
+0xF60B0D00, 0x07F8EFED, 0x060D03FB, 0xFA08FCF6, 0xEEF6FA04, 0x0806FFF9, 0xFF0B0FF0, 0x08F3F1F8,
+0xF0F5EFF3, 0xF1EE0D01, 0xFBFEF3F6, 0xF20D060B, 0xEFFE00EB, 0x080803EE, 0x0617120A, 0x1210050C,
+0xF010FA07, 0x0908EF0D, 0x030908F2, 0x01160610, 0x120BF415, 0xF9F40FF1, 0x0FF00C02, 0x0B110D0B,
+0x0CF9F10A, 0x0C06030D, 0xF20208F5, 0x0F07FAF1, 0xF0FAF50C, 0x08F8F7F0, 0x01EF0EEC, 0x0AEFE90C,
+0xEFFCF714, 0x05F2FF13, 0xECF6F9E7, 0xFEEFFD07, 0xF6ED0F0D, 0x060FF407, 0x0803F600, 0x0105EE06,
+0xF5F70D0B, 0x02EA110F, 0x070FF8F8, 0x0B040902, 0xF6F30AF0, 0x110C1AF9, 0xF61709F7, 0x0D0FF00E,
+0x09F5EFF7, 0x0F13FAFD, 0x0C02F1F3, 0xFBF0F8F7, 0x0DF8F5EB, 0xF1FEF904, 0xFAF1030D, 0x161211F6,
+0xFA0AF50B, 0xF316F60E, 0x100708EE, 0x0AF00A00, 0xFFF4F4EE, 0x0C0BFD18, 0xFCEDF7FE, 0xFB11080F,
+0x0DF70B08, 0xF90AF309, 0xF9FD0F08, 0x10FEFA0E, 0xEE161508, 0x04FCFFFB, 0x0B1009FE, 0x0CF40D0D,
+0xF800F1FC, 0x07080602, 0x1000F8F8, 0xF8F205FD, 0x0809F9F2, 0xF80C09FF, 0xF9F5F6F8, 0x05FE0EFE,
+0xFCF6F8F1, 0x09000A0B, 0x07080DFC, 0x09FBEDF0, 0xEF0CF4FA, 0xF8F6100A, 0xF5F4F1F9, 0xFFFC0E0B,
+0xEEF6F3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEF0810FC, 0xF311FAFD, 0x0DF201EC, 0xFFF40EF3, 0x1304ED12,
+0xF4FCF304, 0x09EC1005, 0x09F80C09, 0x0C10FC0C, 0xF7F7FBFC, 0xF7F60808, 0x05F90308, 0xEC0A13F4,
+0xF20BF707, 0x04FE03F5, 0x10020FFE, 0x02F413ED, 0x050AF5FA, 0xF90E00E4, 0xFAFBF3F5, 0x0908140B,
+0xF00A0107, 0x13EFED0E, 0x04F5F8F5, 0xF104FF0F, 0xF7F0F6F5, 0x0DF7F704, 0xFF0CEB12, 0xFAF50C07,
+0x05EFF5F6, 0x12FA07F6, 0x0AFDF8F9, 0xEE050803, 0x0A04FBED, 0xF61312F2, 0xF10FF7E9, 0xFBFD0307,
+0x0AFEF5F7, 0x12FB12F3, 0xFA14F206, 0xFAF80EFB, 0xFAFDFAFC, 0xFAFC0DF6, 0xFD08F1EF, 0x0B0D0D14,
+0xF80EF90F, 0x0F0D0903, 0xF609ECF6, 0xF9EFF5F9, 0x0FFBFC06, 0x050A0A08, 0x01F30C03, 0xF9F8EE0A,
+0x0B02100A, 0xFDF3F607, 0x0EFF0D01, 0xF8EFF0FF, 0x11F511F7, 0x08F7F809, 0xEB00FE09, 0xF1FA08FF,
+0xFA0114F6, 0xF0090F10, 0xF3FBF6EF, 0x1209FE0E, 0xF7FCF309, 0x04F5F8FD, 0xF00203F2, 0xF510FB05,
+0x12F7080E, 0x08F10AFC, 0xEFF6F5FE, 0xFFFA0F08, 0x0714F612, 0xF30107F5, 0x06FD08F0, 0xFA0C08EE,
+0x05FA02F9, 0xF40108FF, 0xF90DF1F5, 0x17FC0300, 0x09F2080A, 0x10100BF0, 0x12020B10, 0xF5F80AF7,
+0xF902EBF0, 0x16E00312, 0xFEEA0600, 0xFFFAFA13, 0xF20206F9, 0x060BEF10, 0x15FAF005, 0xF603010A,
+0xF50AF110, 0xF1F903F9, 0xE508F40A, 0x0F0FF704, 0xF00B0AFC, 0xF30DFA02, 0x0202F3F9, 0xF60DEDF1,
+0x05FFFC04, 0xF402FFF8, 0xF1F9F807, 0xEF0E0508, 0xF8F6F80D, 0xF4F2FAF5, 0x031209EF, 0xF9FBF6F2,
+0x000AF6F5, 0xF6000D12, 0xF5FD0C08, 0x04FAEF00, 0x1103110B, 0xF1F50BF1, 0x08FD1104, 0xF80B0AF1,
+0x00160DF7, 0xFD05F3F8, 0x0D01F80B, 0x100502F3, 0xFC0309F6, 0xF41207F6, 0xF2100BFD, 0x040E04F7,
+0xE9080908, 0x06030EEA, 0xF40DF805, 0x09EE0608, 0x0C03F4FB, 0x080CFBF1, 0x100416F5, 0x0407F402,
+0xFDFBFDFD, 0x0BF4F806, 0xFC0B16FF, 0x08EBF3F5, 0xECF9F00B, 0xF8E9F300, 0x08F802F5, 0xF3EF10F4,
+0xFEF409F5, 0x15F7FA13, 0x070DF707, 0x0E0617F9, 0x0206F4FA, 0xF2FAFD0B, 0x10EB0F06, 0x1713EBFF,
+0x030A0BF3, 0xF7E30003, 0xECF50DEE, 0x14050506, 0x160AFC0A, 0x0EFD01F6, 0x02050BEB, 0x031615F4,
+0xF2F3FC09, 0xFA140704, 0x0AF20F07, 0xF7F9FE04, 0xF10EEC06, 0x130D0BFC, 0xF6F3ED0F, 0xF20D100D,
+0xF1F6F40C, 0x0E0BF1F2, 0x0C0FF513, 0xEBEE13FB, 0xF80EF409, 0xF608EC0A, 0xF9090DF1, 0xF602EF09,
+0x14F7F6EF, 0xF401F9F0, 0x130B10FB, 0x0FF31101, 0xEC0912ED, 0x0D03F9F8, 0xF4FAF103, 0xFEF4F10A,
+0xF60BE90A, 0xFFF0F7F1, 0xF801F2F0, 0x00150B1A, 0x09EE130F, 0x130DF7EA, 0x13FB0008, 0xF1F9F00E,
+0x0501F5F0, 0x03F60BF8, 0x090BFE05, 0xEBF8FAF3, 0xEA12F90A, 0xF4FCF4F0, 0x0DF81312, 0x01130DF8,
+0xF3060CF2, 0x00F10CF4, 0xE8F611F0, 0xF707FEF6, 0xF81013FC, 0xF0040AFD, 0xF60616FC, 0xFE1109ED,
+0xED140DED, 0x0303F812, 0xFDF4F4F8, 0x0CF60B14, 0x0DF11811, 0x0BF4FBFA, 0xF2F906F9, 0x09F3F806,
+0x030608FA, 0x0A14E20D, 0x0A08F5FA, 0xE7060DFB, 0x02FD050B, 0xF4F6FB07, 0x01F90BF7, 0x0CFA0FF3,
+0x0B04FD01, 0x0F090604, 0x060E0F0A, 0xF6F1FF06, 0xFC0C0611, 0x01030C0D, 0xF612F9F6, 0x120FF002,
+0xF0F0F9F0, 0x10FE0DFC, 0xEAFCF6E7, 0xF4F0FFFC, 0xEA080D01, 0x09F6020A, 0xF1EDF2F7, 0xF80609F8,
+0xF8F7F80F, 0xF8F7FEFB, 0x0AEE03F4, 0xF60F0406, 0x1309EF03, 0x1215F7FC, 0x0EED07ED, 0x08F30DF5,
+0x09E90D02, 0xF1FAFDF4, 0xFD0FFEF4, 0x0317F1F2, 0xF3111203, 0xF208FEFC, 0xF5FB0213, 0x15F20702,
+0x0FF918ED, 0xF3F8FF0B, 0x0F0A0A0B, 0xEE0C0A13, 0x0A0AF506, 0x1A0401F6, 0xF0F6080F, 0xEC091201,
+0xF9F90C02, 0xF10CF003, 0xF217F200, 0x0DF8FA11, 0x04F603F6, 0x03FB10FA, 0x0AF4090D, 0xF1FBF3EF,
+0x0DF00505, 0xFA0B0E0E, 0xFD030811, 0xFEEDF80A, 0xF1F1F40B, 0x050D0514, 0x0DFC0A10, 0xFF0D01EB,
+0x07F7010D, 0xF90D00F6, 0xFCEDF108, 0xFD10F30C, 0xF3F7FB06, 0xF009F8FF, 0xF808F8F5, 0xEF12F009,
+0x0C0E14F8, 0x02010E06, 0xFF00F50D, 0xF9F1F309, 0x0507EEF0, 0xF8EFFDFB, 0x05041303, 0xFC13EEF6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+output0 =
+0x8EC35F65, 0xF1011E4E, 0x01283C76, 0x46C59B44, 0x66BD1E7E, 0x71CC3D13, 0xF54F7B59, 0xC2E51E78,
+0x878ACD1F, 0x0BB83AD9, 0xD6EB81F6, 0xDA98D960, 0x9583FF24, 0x84E13C2E, 0xB80A4BD9, 0x7546DA7D,
+0x61301F84, 0x4E8E7BCA, 0x0F9A1992, 0x84DE01C3, 0xFB1B38F1, 0x44764A25, 0x9525C193, 0xAD6AFC2C,
+0xEAC9CBE7, 0x822626C3, 0x6764F1E2, 0xB7080FC1, 0x92F0BF18, 0x2BE2A423, 0x6652CA22, 0x7E2B8B7D,
+0xDADC0042, 0x1684A5B0, 0x6AF80D1E, 0xDE4B11F8, 0x4C027AA7, 0x9B499047, 0xDF71DF9C, 0xE66B5211,
+0x0976A858, 0x97CCDFA6, 0xF921AC4D, 0x684DB77D, 0x2046F400, 0x66BF05FF, 0xCFE771B2, 0x7D285899,
+0xA6DD74A8, 0xD5AC14DF, 0xB4EE744D, 0x9BF75449, 0xBCCF7BE5, 0xD9B3E1C5, 0x04D5FEEA, 0xA91CED17,
+0x260A3E33, 0xB14FA433, 0xC7FB659B, 0xD847CBDD, 0xD4BAF083, 0x51A5AEB1, 0x39A13C7A, 0xC54DBA51,
+0x81DD7FFE, 0xE2A3941C, 0x386750AD, 0x85C6A1CF, 0x52E46581, 0x2DC58468, 0x4F8C204C, 0xCA6C89B8,
+0xD338F49E, 0xB71D9A1C, 0xAE5992A5, 0x461FFEB6, 0x0F724968, 0xD2D9A290, 0x4C0791D6, 0x8AA45E2A,
+0xBCE9EEF4, 0x769D6618, 0x71D659F8, 0xE9DC6A13, 0x99E831C3, 0x8AB8CFD6, 0x489E23C5, 0xBEFC2792,
+0x9E54E534, 0x54101DEF, 0x1F83D8D2, 0x69A8094D, 0x2DA8AAEB, 0x564C6C07, 0x4F2AADB5, 0x20CB1D7F,
+0x2D6E9D54, 0xB97A8BC9, 0x36365C67, 0x8D84329F, 0x4000A81C, 0x6326766B, 0xB9B50B8D, 0xF9D51D73,
+0x4D1A117F, 0x70486DEE, 0xBB19FFB6, 0x96929F46, 0x8E7C8D1C, 0x04B8D1F3, 0x204B8156, 0xA67E9C62,
+0x4534F672, 0x94B8C832, 0x38E7CFE4, 0x71F48255, 0x82181625, 0xF8C9EB50, 0xF3D38EF0, 0xB4DE79FB,
+0xF32452
+
+harq_output0 =
+0x0FFA0103, 0x130C0B02, 0xF309F6E7, 0xF70F07F1, 0xF7090FF8, 0x050409F2, 0xF80AFAF7, 0x00F60EF5,
+0x06FC060D, 0x080DFB03, 0xF4EDF9F9, 0xFCF9FEEA, 0x0F0C12F8, 0xF9F31708, 0xF60C02FF, 0xFF110310,
+0x0BF80F0F, 0x02F6F2EE, 0xEDF20A06, 0x0709FEF2, 0x14F5F0F0, 0xF70C0018, 0x12020FEF, 0x0602EF08,
+0xF40A0200, 0xEE0C0BFC, 0x0606ED01, 0xF2F709F3, 0x15110E10, 0x06EC06F8, 0xFBF10CF8, 0x0314FEF6,
+0xF5F4FC0C, 0xF00C00FF, 0xF6FDF9F6, 0x07F30801, 0x0F04F40C, 0x0406F305, 0xFAF9F808, 0xF20DF109,
+0x010A0AF8, 0x070AFC03, 0xF108120A, 0xF8F9F1EC, 0xEEEB09FF, 0x140C0D01, 0x04E5EF10, 0xF616130C,
+0x0314F4EC, 0x09FA09F2, 0xFAFAF714, 0xFAF101FD, 0x06030FF4, 0x17F3EFFA, 0x09FEF109, 0xFDFEF9FB,
+0xF2080B02, 0x0CF90B07, 0xEB0F0D06, 0xF71009FE, 0xEF110AF8, 0x0AF70BF9, 0x170A1508, 0xF8FDFAF1,
+0x0204F3EB, 0xEFFE0315, 0x0C06000B, 0xF10C0A0E, 0xEC0EF9FC, 0x08F0F2F3, 0x09FD02F7, 0x0B11F610,
+0xF8F1F8F7, 0xF8FB0A09, 0xFB030A13, 0x040804F0, 0xE8080813, 0xF1F4FFF3, 0xEBFCEDF7, 0xF7F00AE8,
+0x00F1160E, 0xF007F301, 0x0E13F211, 0x07F815F4, 0xF9EEF70B, 0x0EF7FE15, 0x0706E80C, 0x0611F60E,
+0xFB0B0CF5, 0xF4F50E11, 0x14FDF1EB, 0xF403120A, 0x09F80303, 0xFB0AF80B, 0xFA1408F5, 0xF503F717,
+0x0FFB1610, 0x1107F3FC, 0xF1F4F7F7, 0x060EF4E8, 0x04F8F5FF, 0x04F30CFA, 0x10F008F8, 0xF514EEF3,
+0x0EEDE8FE, 0xE7FEE70B, 0x0404FEF9, 0xF8F509F9, 0x0A0EF6F2, 0xF8080EF8, 0x01F200F3, 0x03FC19F2,
+0x0D0FF2F8, 0xF9FD0C13, 0x11FE0703, 0x0BF9F110, 0x0EF3FEFD, 0x0EF8F10C, 0x0A070FEA, 0x04FA0310,
+0x0CFE0003, 0x0CF3060D, 0xFBFCF5FA, 0xEC0D1108, 0x09ECF70A, 0x0C0EFB08, 0x0BF4F80A, 0xEFF0FB0C,
+0x0B09F8FA, 0xFA16FF13, 0x0B081512, 0xF4F2FBF7, 0x000C0A07, 0x130C0FEE, 0xFEF908FB, 0xF6F5F912,
+0xF1100409, 0x090E1606, 0xF4F50BF3, 0xEE00F7F9, 0xFAFBF5F6, 0x07080B0A, 0xF1150BE7, 0x0DF80912,
+0x12EF0809, 0xEBFF1108, 0x0BF60DFE, 0x130DF608, 0x12EFF2F1, 0x04FB0C0B, 0x01FDFC09, 0xFAF808F9,
+0x12020B01, 0xFCED060F, 0x040DFFFF, 0x04F80AF3, 0xF700F60B, 0x08F40E08, 0x06F7F80F, 0x0DFDEF04,
+0xFDEFF916, 0xF21107EF, 0x0A1110F1, 0x03F70DF3, 0x08F50300, 0xF1F711F9, 0xF6FCFF0C, 0x0CFFF704,
+0x080CFE09, 0x0FF80D06, 0x05080C08, 0xFE020210, 0xFB11F6E9, 0x060BF2F1, 0xED0BEAF9, 0x02F30C02,
+0xF8F40DFB, 0x020D0D01, 0x0CF406F1, 0xF302F812, 0x080C0EF2, 0x06010006, 0xF0FA0908, 0x08F9F905,
+0xFB0A0508, 0x0FF0F7F4, 0xFF081210, 0xEE18F6F1, 0xF9F9E8F2, 0x060B09FD, 0x0AFEEE04, 0x09F304F8,
+0xEA05F6F8, 0x1C0108F5, 0xF205120F, 0xF40D0A04, 0x0001F30D, 0x00FF0DFA, 0x020BF7F7, 0x02F2F7F0,
+0x04F90BF1, 0x01EFEE07, 0xEBE4F807, 0x0AF90FEF, 0x0F040B11, 0x0BF91000, 0x000CF812, 0x0311F3F0,
+0xF8070218, 0xEDFFF614, 0xF00C15F1, 0x000D0F16, 0xFA0EF707, 0xEE080901, 0xFF0C09F5, 0xEEF704F1,
+0xF10C10F9, 0x060BEBF7, 0xFA0EFDF6, 0xF7F403F2, 0xF5F0F306, 0xEC081A0F, 0x020AEEF5, 0xFBF9F7FB,
+0xF60C010A, 0xEC0E0FFF, 0xF014FB10, 0x0EFD0308, 0x04F30015, 0xF4FC0CEE, 0x0CFEF3F7, 0x12F0F702,
+0xE803FB07, 0x040D06F5, 0x05FA07F1, 0x140A0BF8, 0xEFEDFF11, 0x01EFEE13, 0x0D0C0B0F, 0xE70105F0,
+0x01F70CF4, 0x0603EE12, 0xED08EDF9, 0xF2FCFA02, 0x0E0CFCF3, 0x0E04F8F9, 0xF30D17F9, 0xFEEDFB05,
+0x071BF114, 0xF309F7F4, 0x02F503F6, 0x0815F400, 0x0CF0090A, 0xE80D0F02, 0xF9FCFDF8, 0xF00FFEF5,
+0xF3F5F70B, 0xFC10F7EF, 0xF2FB0AFE, 0xEEECEC15, 0x0202F60E, 0xF310FEF9, 0x10F8F209, 0xFB0606EE,
+0x0D0B0C10, 0x1110080C, 0xFCF2F8F6, 0x030DEE07, 0x0C11F511, 0x0CF6EF08, 0x0900070C, 0x0C160E0F,
+0xEEF8FFF9, 0xF7F0EEF5, 0x0A090903, 0xF70A000E, 0xF5FF07F6, 0xF5E5FEFD, 0x08F1F80C, 0x00F2EE0D,
+0xFAED07EA, 0x07EA170B, 0xFEFFECFF, 0xED0B0211, 0x0AF4F4E6, 0xF2FAF705, 0x0807F706, 0xFBF2F8F7,
+0xF31105F7, 0xF10809FB, 0xF1FEF307, 0x0805FFFA, 0x08FC070D, 0x0A071200, 0xEEEDF107, 0xF908EDFB,
+0x09F60FF2, 0x0B0C06F8, 0x07FCF608, 0x000FF30C, 0xFF0EF3FD, 0xE40BFCF4, 0x0CF50BF4, 0x04EDE90D,
+0xFD05F3F1, 0xFAECF4FA, 0xF80C080F, 0x0A0BF70A, 0x07F012F4, 0x1109FEF3, 0xF507F9F1, 0xF513F7FD,
+0xFE0AF80F, 0x041701F1, 0xF5E7F309, 0x0A0AF70C, 0x0E00FEF1, 0x04E505EF, 0xF4EF0BFD, 0x040CF807,
+0x1201EF07, 0xF31508F1, 0xF908F309, 0x0B0EE409, 0xF7EBF9F8, 0xF1F7F406, 0xFB0206F6, 0xECFD11F2,
+0x0702EEF6, 0xF409FC04, 0xEEF80010, 0xF3EC0BF0, 0x090600F1, 0xF9F5EBF7, 0xEEFE11F8, 0x070BF0FA,
+0xFE16EEF8, 0xF108FD05, 0x15FAF3F7, 0xF60E0D0D, 0xF7FC0AF8, 0x01F40805, 0xF70AFE01, 0xFB0F0BF9,
+0x04E701F6, 0x09F517F6, 0xFBE8F5F8, 0x11FE00F6, 0xEF08F2F5, 0xFB0CFB0F, 0x0419080B, 0x0308EE11,
+0x07110907, 0xF2F5ED0F, 0x0BFAFEF6, 0xFA12F8F9, 0xE8090606, 0x0E0CEAEC, 0x06FD10F8, 0xF80505FD,
+0xF1F70912, 0xF5EF0C0B, 0xF9EF0B0B, 0x0D05F5F2, 0x0A08FF0E, 0x09F50300, 0x08F91314, 0x0AFEF60A,
+0xE5FC0504, 0xEF0A000E, 0x06FDFFF1, 0x0D11F103, 0x080CF512, 0xF9F501F2, 0xFAF60708, 0xFE140D05,
+0xF90202EF, 0xF0FD0EED, 0x06F2E903, 0xE904F80D, 0xF600F8F8, 0xF4FA09F5, 0x0803FA07, 0xFCF9F90B,
+0xF202F4F5, 0x000EFBFE, 0x0409FAFD, 0xF0EA0DF4, 0x0B0D00FF, 0x03F8FB0D, 0x0307FAF2, 0x010C0BFB,
+0x140C03FD, 0xF4FE0906, 0xF6F6F8ED, 0x0B11090D, 0xF6F90EF8, 0x09F001E8, 0xEC0600F8, 0x1109F90E,
+0xEA010BEF, 0xEF0A0C0A, 0x07F510FD, 0x08F3F500, 0x07ED01F5, 0xF313F60A, 0xF803FA0E, 0xF60B0D08,
+0xF1F0F709, 0x0DF609F4, 0xFCED020B, 0x0E0EEDE9, 0x08F907F2, 0xF1FC0C13, 0xFFFB0C06, 0xEB070AF7,
+0xF606F80A, 0xF90E1EFF, 0xF6EE0BF5, 0x05FF03F7, 0x0F0DF309, 0xFA0CF4F8, 0x1F0CF6F3, 0xF50DEE0F,
+0xF5F7FDF4, 0x0BF501EF, 0xF7FA000F, 0xECFAF0F5, 0xEA02FEF1, 0xF80FFCFC, 0x100B0600, 0xFF050501,
+0xFA150716, 0x110FFFF4, 0xEE0B04F8, 0x0E0FF112, 0x12F80BF4, 0xF6F41604, 0x07EDE6EF, 0x17EE0F0B,
+0x05F5FEF2, 0xEF0BFEF5, 0xFF07FD15, 0x01090709, 0x02EBEE0D, 0xF6F9FB0D, 0xEFF6070E, 0x090806F6,
+0x140FFEF1, 0xF6FCEEEB, 0x07EF14F2, 0xFB03040B, 0x0A05F4FC, 0x0DF6FB0D, 0x060B02F8, 0xFF0FFB0E,
+0x090709F7, 0xF7180F02, 0x0BF8F005, 0xFE0CF60D, 0x09F4ECF0, 0x0410F30A, 0xEB05F105, 0x05F90C11,
+0xFCF1F30B, 0x120B0BF3, 0x031104FC, 0x030BFC0F, 0xFB09EFFC, 0xF50CFB11, 0x0BF80504, 0xF609FCF7,
+0xFE0CFB00, 0x0F08F7FB, 0x0BFD0609, 0x0E120F15, 0x020B07F8, 0x0714FAF0, 0x0615F308, 0xF2FDF8F9,
+0xEEF606F8, 0x050906E8, 0x071106F7, 0x000C03F8, 0x04F9F90A, 0x060BF5F7, 0x0D0CF2F7, 0x06FB02F7,
+0xF7060AF5, 0x0EF1FCF4, 0xFAFAF5FE, 0x0506F917, 0xFCF40C0A, 0x03FC10E8, 0xF30700FD, 0xFCF40906,
+0xFB0B0D0B, 0x1017E4F9, 0xF20408F2, 0x02FA03F7, 0xF0000E07, 0xFB0AEDF1, 0xE6F50FEB, 0xF2FCF80B,
+0x04F50DFB, 0xF00BF706, 0xF70507FC, 0x0AF01609, 0xFF0DF20F, 0xEA150EF2, 0x080202F3, 0x00FAF9F5,
+0xEFF70E04, 0x0FF6F314, 0xF1FEFAEE, 0x08F1F3F2, 0xF6101102, 0xF8F20206, 0x120DFC03, 0x07F8F613,
+0x0CF4F50D, 0x0DFF05FB, 0x040EF409, 0xF8FB06F6, 0xF3FAF20D, 0x0DF90402, 0x05080E00, 0xF5EFEBEC,
+0xFE0B0EE7, 0x0B0E0F0E, 0x04F812F4, 0x0EEE0D10, 0x021AF7EF, 0xF70F10EC, 0xF604FDFA, 0x10E90F0B,
+0xF60CEFFE, 0x0AEBF407, 0xF60A06F0, 0xF50B1607, 0x1111FF0B, 0xF8F8EF08, 0xF704F410, 0x0B0AEBFE,
+0x14000205, 0x03FC0EF2, 0xFD17EBFF, 0x17FAFCF4, 0x0DF90CFA, 0x1004F511, 0x140302FC, 0x14FC0500,
+0xFCF6F2FE, 0x0905FA03, 0x08F3F0F4, 0x06FEF5EF, 0x09F801F8, 0xF00913F1, 0xF7F80DED, 0x040AF1FC,
+0xFC0F1008, 0x07040EF4, 0x0BF6EC0C, 0x0CF8FA0C, 0xF70F0EFF, 0xFB09FBFC, 0xF9F4ED0D, 0x02F4F80B,
+0xF5FCF2F2, 0x0208FDF1, 0xF20B0405, 0xF80AFAF3, 0xF415EDEA, 0xFDFBEB00, 0xF4F1F30F, 0xEC070F09,
+0xFA0D0AFF, 0xF7EE0C06, 0x04F4F00B, 0x08F50FF5, 0xF50EF3FC, 0x1006E7F9, 0x04F7F7FC, 0xFC070CFB,
+0x0F12EAFA, 0xF7F00706, 0xF4011505, 0xF7140B09, 0x0AF9F1F8, 0x03060DF8, 0xF2090CF8, 0xF20712F3,
+0xF903EFEE, 0x1102EC14, 0x0A09F1F6, 0xF9F001FA, 0xF8FE01FB, 0x140410F1, 0x0B0402F2, 0x0F0006F5,
+0x0805ECF9, 0xF409F10E, 0x0DE7FD01, 0xEFFD0710, 0xF20403FD, 0x0BF2F6F9, 0x0004F909, 0x0F09FFF6,
+0xF3060DF2, 0x0EEF060E, 0x0CF40705, 0xFDF7FB0C, 0xF4F203E4, 0x0E09F4F6, 0xF5FE04F9, 0x06F3FEFE,
+0xFDFB1102, 0xFD04EE0D, 0x0DFBFCF1, 0xEE14E90B, 0xFB0CEE09, 0x0C13F108, 0xF60703FD, 0x0BF4FCFA,
+0x14F2F0FB, 0xFAF9EFF7, 0xF5010801, 0xF109EEF3, 0xFF0A0514, 0x0C0604FF, 0xFB0EF704, 0xF50EFD0B,
+0xFF05F4FA, 0x07E70B0B, 0xEFFEF4FD, 0x0D0807F3, 0x05100DF6, 0xEFFA1A08, 0x020D090A, 0xFFF5F7FD,
+0x1513F10A, 0xF10BF2ED, 0x0B0F150B, 0xF10306FA, 0x09FB11EE, 0x061007F2, 0xF7F8FB14, 0xF90704EE,
+0x0AF8EAF6, 0xF7E809F9, 0x02F609E9, 0x09E802EE, 0x03F50BE8, 0x040C04F1, 0x0CF41009, 0xFB00EEFA,
+0xFC071611, 0xF9F1F203, 0x0BF0F409, 0x0214F801, 0x0A0AF504, 0x0508F5F1, 0xE916E900, 0x07F4F60A,
+0xF9F010F2, 0xF906F507, 0x0BFB0AF4, 0xF408F0F1, 0x0EFD0A06, 0x03F80AF6, 0x130CFD0C, 0xF1E9F7F8,
+0xF800F502, 0xFEFDFDF4, 0xF90B0713, 0xF506FAFD, 0x0712F9F2, 0xEAF20DF5, 0x10F40D0D, 0x06050B09,
+0xF706090E, 0x0F00ED11, 0xF90E02F4, 0xF1FEFCED, 0x0AF5E00D, 0x06F7F3F9, 0x08F81206, 0xF30EF4F5,
+0x12FF02EF, 0xF7040DF4, 0x151204F0, 0x04ED07EC, 0xF0F3FB05, 0x08F2FCF4, 0xECED11FA, 0xFC110DF8,
+0x0BF4F90A, 0xFCF9F905, 0xF0010014, 0x0A0EF9F8, 0xF4020C02, 0x10FDFA13, 0xF5000B05, 0x05EAF808,
+0xFE0F04F3, 0xFDEFF9EE, 0xF9F9090B, 0x10F20E0C, 0x060909F0, 0x060EF40F, 0x0E0705F5, 0xFB05F6F9,
+0xFA1C0512, 0x0B10FBEB, 0x16F20DF6, 0x090012F4, 0x0A13020B, 0x0EFF0C0A, 0x130DEF0C, 0x070A0B04,
+0x0BFCF004, 0x02FF0BF7, 0xF9F1F209, 0xFFF5F008, 0x05F30C07, 0x03FCEE07, 0x11FCEE08, 0xF4F31514,
+0x040B06F2, 0xE400F9F3, 0x13090B1A, 0xF2F4FFE7, 0xF1EE06F9, 0xFA0DFF0D, 0xF3ED09F6, 0xF40305F8,
+0xF8FFF507, 0xF8FF1707, 0x0AFC030C, 0xF109F3F4, 0x0406FDF0, 0xEF04F50E, 0xF5FBF3FD, 0xF30704F4,
+0xF0ECFC1C, 0xFCECF0F5, 0xF911160F, 0x020B0C0D, 0xF90C060B, 0x03FA08E7, 0x0311FF0D, 0xF405F4FA,
+0x0DEBF7F2, 0x0EF6FAF2, 0x09F3ED0E, 0xFE08EFF2, 0x0F170008, 0x0DFF0FFC, 0x0BF0ED0E, 0x0D140E07,
+0xF2F611F3, 0x11E9020B, 0xEE03F3F7, 0xFCFD00EF, 0xF518090B, 0xF11510EE, 0xF5FB07FF, 0xFEFC11F0,
+0x100DF006, 0x0AF4F300, 0xED0A1200, 0xFEF7EDF5, 0xF7040101, 0x0FF2040E, 0xF01207F7, 0x0AF3FF10,
+0xF60B0D00, 0x07F8EFED, 0x060D03FB, 0xFA08FCF6, 0xEEF6FA04, 0x0806FFF9, 0xFF0B0FF0, 0x08F3F1F8,
+0xF0F5EFF3, 0xF1EE0D01, 0xFBFEF3F6, 0xF20D060B, 0xEFFE00EB, 0x080803EE, 0x0617120A, 0x1210050C,
+0xF010FA07, 0x0908EF0D, 0x030908F2, 0x01160610, 0x120BF415, 0xF9F40FF1, 0x0FF00C02, 0x0B110D0B,
+0x0CF9F10A, 0x0C06030D, 0xF20208F5, 0x0F07FAF1, 0xF0FAF50C, 0x08F8F7F0, 0x01EF0EEC, 0x0AEFE90C,
+0xEFFCF714, 0x05F2FF13, 0xECF6F9E7, 0xFEEFFD07, 0xF6ED0F0D, 0x060FF407, 0x0803F600, 0x0105EE06,
+0xF5F70D0B, 0x02EA110F, 0x070FF8F8, 0x0B040902, 0xF6F30AF0, 0x110C1AF9, 0xF61709F7, 0x0D0FF00E,
+0x09F5EFF7, 0x0F13FAFD, 0x0C02F1F3, 0xFBF0F8F7, 0x0DF8F5EB, 0xF1FEF904, 0xFAF1030D, 0x161211F6,
+0xFA0AF50B, 0xF316F60E, 0x100708EE, 0x0AF00A00, 0xFFF4F4EE, 0x0C0BFD18, 0xFCEDF7FE, 0xFB11080F,
+0x0DF70B08, 0xF90AF309, 0xF9FD0F08, 0x10FEFA0E, 0xEE161508, 0x04FCFFFB, 0x0B1009FE, 0x0CF40D0D,
+0xF800F1FC, 0x07080602, 0x1000F8F8, 0xF8F205FD, 0x0809F9F2, 0xF80C09FF, 0xF9F5F6F8, 0x05FE0EFE,
+0xFCF6F8F1, 0x09000A0B, 0x07080DFC, 0x09FBEDF0, 0xEF0CF4FA, 0xF8F6100A, 0xF5F4F1F9, 0xFFFC0E0B,
+0xEEF6F3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEF0810FC, 0xF311FAFD, 0x0DF201EC, 0xFFF40EF3, 0x1304ED12,
+0xF4FCF304, 0x09EC1005, 0x09F80C09, 0x0C10FC0C, 0xF7F7FBFC, 0xF7F60808, 0x05F90308, 0xEC0A13F4,
+0xF20BF707, 0x04FE03F5, 0x10020FFE, 0x02F413ED, 0x050AF5FA, 0xF90E00E4, 0xFAFBF3F5, 0x0908140B,
+0xF00A0107, 0x13EFED0E, 0x04F5F8F5, 0xF104FF0F, 0xF7F0F6F5, 0x0DF7F704, 0xFF0CEB12, 0xFAF50C07,
+0x05EFF5F6, 0x12FA07F6, 0x0AFDF8F9, 0xEE050803, 0x0A04FBED, 0xF61312F2, 0xF10FF7E9, 0xFBFD0307,
+0x0AFEF5F7, 0x12FB12F3, 0xFA14F206, 0xFAF80EFB, 0xFAFDFAFC, 0xFAFC0DF6, 0xFD08F1EF, 0x0B0D0D14,
+0xF80EF90F, 0x0F0D0903, 0xF609ECF6, 0xF9EFF5F9, 0x0FFBFC06, 0x050A0A08, 0x01F30C03, 0xF9F8EE0A,
+0x0B02100A, 0xFDF3F607, 0x0EFF0D01, 0xF8EFF0FF, 0x11F511F7, 0x08F7F809, 0xEB00FE09, 0xF1FA08FF,
+0xFA0114F6, 0xF0090F10, 0xF3FBF6EF, 0x1209FE0E, 0xF7FCF309, 0x04F5F8FD, 0xF00203F2, 0xF510FB05,
+0x12F7080E, 0x08F10AFC, 0xEFF6F5FE, 0xFFFA0F08, 0x0714F612, 0xF30107F5, 0x06FD08F0, 0xFA0C08EE,
+0x05FA02F9, 0xF40108FF, 0xF90DF1F5, 0x17FC0300, 0x09F2080A, 0x10100BF0, 0x12020B10, 0xF5F80AF7,
+0xF902EBF0, 0x16E00312, 0xFEEA0600, 0xFFFAFA13, 0xF20206F9, 0x060BEF10, 0x15FAF005, 0xF603010A,
+0xF50AF110, 0xF1F903F9, 0xE508F40A, 0x0F0FF704, 0xF00B0AFC, 0xF30DFA02, 0x0202F3F9, 0xF60DEDF1,
+0x05FFFC04, 0xF402FFF8, 0xF1F9F807, 0xEF0E0508, 0xF8F6F80D, 0xF4F2FAF5, 0x031209EF, 0xF9FBF6F2,
+0x000AF6F5, 0xF6000D12, 0xF5FD0C08, 0x04FAEF00, 0x1103110B, 0xF1F50BF1, 0x08FD1104, 0xF80B0AF1,
+0x00160DF7, 0xFD05F3F8, 0x0D01F80B, 0x100502F3, 0xFC0309F6, 0xF41207F6, 0xF2100BFD, 0x040E04F7,
+0xE9080908, 0x06030EEA, 0xF40DF805, 0x09EE0608, 0x0C03F4FB, 0x080CFBF1, 0x100416F5, 0x0407F402,
+0xFDFBFDFD, 0x0BF4F806, 0xFC0B16FF, 0x08EBF3F5, 0xECF9F00B, 0xF8E9F300, 0x08F802F5, 0xF3EF10F4,
+0xFEF409F5, 0x15F7FA13, 0x070DF707, 0x0E0617F9, 0x0206F4FA, 0xF2FAFD0B, 0x10EB0F06, 0x1713EBFF,
+0x030A0BF3, 0xF7E30003, 0xECF50DEE, 0x14050506, 0x160AFC0A, 0x0EFD01F6, 0x02050BEB, 0x031615F4,
+0xF2F3FC09, 0xFA140704, 0x0AF20F07, 0xF7F9FE04, 0xF10EEC06, 0x130D0BFC, 0xF6F3ED0F, 0xF20D100D,
+0xF1F6F40C, 0x0E0BF1F2, 0x0C0FF513, 0xEBEE13FB, 0xF80EF409, 0xF608EC0A, 0xF9090DF1, 0xF602EF09,
+0x14F7F6EF, 0xF401F9F0, 0x130B10FB, 0x0FF31101, 0xEC0912ED, 0x0D03F9F8, 0xF4FAF103, 0xFEF4F10A,
+0xF60BE90A, 0xFFF0F7F1, 0xF801F2F0, 0x00150B1A, 0x09EE130F, 0x130DF7EA, 0x13FB0008, 0xF1F9F00E,
+0x0501F5F0, 0x03F60BF8, 0x090BFE05, 0xEBF8FAF3, 0xEA12F90A, 0xF4FCF4F0, 0x0DF81312, 0x01130DF8,
+0xF3060CF2, 0x00F10CF4, 0xE8F611F0, 0xF707FEF6, 0xF81013FC, 0xF0040AFD, 0xF60616FC, 0xFE1109ED,
+0xED140DED, 0x0303F812, 0xFDF4F4F8, 0x0CF60B14, 0x0DF11811, 0x0BF4FBFA, 0xF2F906F9, 0x09F3F806,
+0x030608FA, 0x0A14E20D, 0x0A08F5FA, 0xE7060DFB, 0x02FD050B, 0xF4F6FB07, 0x01F90BF7, 0x0CFA0FF3,
+0x0B04FD01, 0x0F090604, 0x060E0F0A, 0xF6F1FF06, 0xFC0C0611, 0x01030C0D, 0xF612F9F6, 0x120FF002,
+0xF0F0F9F0, 0x10FE0DFC, 0xEAFCF6E7, 0xF4F0FFFC, 0xEA080D01, 0x09F6020A, 0xF1EDF2F7, 0xF80609F8,
+0xF8F7F80F, 0xF8F7FEFB, 0x0AEE03F4, 0xF60F0406, 0x1309EF03, 0x1215F7FC, 0x0EED07ED, 0x08F30DF5,
+0x09E90D02, 0xF1FAFDF4, 0xFD0FFEF4, 0x0317F1F2, 0xF3111203, 0xF208FEFC, 0xF5FB0213, 0x15F20702,
+0x0FF918ED, 0xF3F8FF0B, 0x0F0A0A0B, 0xEE0C0A13, 0x0A0AF506, 0x1A0401F6, 0xF0F6080F, 0xEC091201,
+0xF9F90C02, 0xF10CF003, 0xF217F200, 0x0DF8FA11, 0x04F603F6, 0x03FB10FA, 0x0AF4090D, 0xF1FBF3EF,
+0x0DF00505, 0xFA0B0E0E, 0xFD030811, 0xFEEDF80A, 0xF1F1F40B, 0x050D0514, 0x0DFC0A10, 0xFF0D01EB,
+0x07F7010D, 0xF90D00F6, 0xFCEDF108, 0xFD10F30C, 0xF3F7FB06, 0xF009F8FF, 0xF808F8F5, 0xEF12F009,
+0x0C0E14F8, 0x02010E06, 0xFF00F50D, 0xF9F1F309, 0x0507EEF0, 0xF8EFFDFB, 0x05041303, 0xFC13EEF6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0xFB0E01EF, 0xFF0C0B02, 0x07090AFB, 0x0BFBF3F1, 0x0B090F0D, 0xF10409F2,
+0xF80A0E0B, 0xECF60E09, 0x0610F2F9, 0xF4F9FBEF, 0x08ED0DF9, 0xFCF9FEFE, 0x0F0C12F8, 0xF9F317F4,
+0x0BF80213, 0xFFFD1710, 0x0BF80FFB, 0xEEF6F2EE, 0x0106F506, 0xF3091206, 0x00F504F0, 0x0B0C0018,
+0xFD02FAEF, 0x06ED0308, 0xF4F60215, 0x02F80BFC, 0xF20601ED, 0x06F7F5F3, 0x0111FAFC, 0xF2ECF2F8,
+0xFB050C0D, 0x0314EA0A, 0x09F4FCF8, 0xF0F80013, 0xF6E90D0A, 0xF307F415, 0xFB04F4F8, 0xF006F3F1,
+0xFAF9F808, 0x06F9F109, 0xED0A0A0C, 0xF3F6FC03, 0x0508120A, 0x0C0DF100, 0x02FF09FF, 0x00F80D01,
+0x04E50410, 0xF616130C, 0x0300F4EC, 0x090EF506, 0xFA0E0C14, 0x0EF10111, 0xF2030F09, 0x03F3030E,
+0x09EA0509, 0xFDFEF9FB, 0x06F4F702, 0x0C0D0BF3, 0xFFFBF906, 0xF7FBF512, 0x03110AF8, 0x0AF7F70D,
+0x17F60108, 0xF811FA05, 0xEE040700, 0x03FEEF01, 0xF706EC0B, 0x060C0AFA, 0xEC0EF910, 0x0804F207,
+0x09E902F7, 0xF7FDF610, 0x0C050C0B, 0xF8E7F609, 0xFB170A13, 0xF0080404, 0xE808F413, 0xF1F4EB07,
+0xEBFC01F7, 0x0B040AE8, 0x00F1020E, 0xF0F207EC, 0x0EFFF211, 0xF3F815F4, 0xF9020B0B, 0x0EF71201,
+0x0706FC0C, 0x06FDF6FA, 0xFBF7F80A, 0x08090EFD, 0x14FD05FF, 0xF403FE0A, 0xF5F8EF03, 0xFB0AF8F7,
+0x0F00F409, 0x0AEF0B03, 0x0FFB0210, 0x11070710, 0xF1080B0B, 0xF20E08E8, 0xF00CF5EB, 0xF0F30C0E,
+0xFCF0080D, 0x0900EE07, 0xFA01FCFE, 0xE712E70B, 0xF004FEF9, 0x0CF5090D, 0xF60EF606, 0xF8F4FAF8,
+0xED061507, 0xEF110506, 0xF90FF20C, 0xF911F813, 0xFC12F3EF, 0xF7F9F1FC, 0x0E07EAE9, 0x0EF8F1F8,
+0xF6070FEA, 0xF0FA0310, 0xF8FE1417, 0xF8F306F9, 0xFBFCF50E, 0xEC0D11F3, 0x0900F70A, 0xF80EFBF3,
+0x0B08F8F6, 0xEFF00F0C, 0xF709F8FA, 0x0E16EB13, 0x0BF415FE, 0xF4F20F0B, 0xEC0C0AF3, 0x13F8FB02,
+0x12F908FB, 0x0A090D12, 0xF110F0F5, 0xF40E021B, 0x0809F7F3, 0xEE000B0D, 0x0E0FF5F6, 0xF3F40BF6,
+0x05150BE7, 0x0DF809FE, 0x12030809, 0xFF13FC08, 0x0BF6F912, 0x13F90AF4, 0xFE03F2F1, 0x04FB0CF7,
+0x01FDE8F5, 0x0EF8F40D, 0xFE02F7ED, 0xE7EDF2FB, 0x04F9FF13, 0xF0F80A07, 0xF700F6F7, 0xF4080EF4,
+0xF2F7F80F, 0x0DFDEFF0, 0x11EFF902, 0xF2FC0703, 0x0AFD10F1, 0x17F70D07, 0x08F5EFEB, 0xF10B11F9,
+0xF610FFF8, 0x0C130B18, 0x080CFEF5, 0xFBF8F906, 0xF1080C08, 0xEAEEEE10, 0x0F11F6FD, 0x06F706F1,
+0xED0BEA0D, 0xEEF30C02, 0xF8F40D0F, 0x020D0DEC, 0x0CF40605, 0x07020C12, 0xF40C0EF2, 0x060115F2,
+0xF0E6F508, 0xF40DF9F0, 0x0F0A05F4, 0x0FF00B08, 0xEB08FEFC, 0xEE030AF1, 0x0DF9E806, 0xF2F7F5FD,
+0x0A12EEF0, 0x09F3EFF8, 0xFE05F6F8, 0x1CEDF4F5, 0x060512FB, 0x08F90AF0, 0x000107F9, 0x14FFF9FA,
+0x16F70B0B, 0xEEF2F704, 0x04F90BF1, 0x150302F3, 0xEBF8F8F3, 0xF6F90FEF, 0xFBF0F7FD, 0xF70D1000,
+0xECF70C12, 0x03FDF3F0, 0xE4F31604, 0x02FFF600, 0xF00C0105, 0xEC0D0F02, 0xFAFAF707, 0x0208F501,
+0xFFF809F5, 0xEEF70405, 0x050CFCF9, 0xF20BEBF7, 0xFA0E11F6, 0xF7F403F2, 0xF5F0F306, 0x00081A0F,
+0x02F6EE09, 0x0F0D0B0F, 0x0AF7EDF6, 0xECFA0FEB, 0xF000FBFC, 0xF91103F4, 0xF0F30001, 0x08FCF8EE,
+0x0CFEF30B, 0xFE040B02, 0xFC030FF3, 0x04F9F209, 0xF10E0705, 0x14F60B0C, 0x03ED1311, 0xED03EE13,
+0xF9F8F70F, 0xFB010504, 0xEDF70C08, 0x061802FE, 0xED0801F9, 0x06FCFA16, 0x0EF8FCF3, 0x0EF00C0E,
+0xF3F9170D, 0xFE010F05, 0xF31B0500, 0x07F50BF4, 0xEE09030A, 0xF401F400, 0x0C04090A, 0xFCF90F02,
+0x0D10FD0C, 0xF00FEA09, 0xF3F50BF7, 0xFCFCF7EF, 0x06FB0A12, 0x0200EC01, 0x02020A0E, 0xF3FCFE0D,
+0xFC0CF209, 0xFB06F2EE, 0xF90B0C10, 0xFDFCF40C, 0xFC06F80B, 0xEFF902F3, 0x0C110911, 0xF80AEFF3,
+0x0900F30C, 0xF8160E0F, 0xEE0D130D, 0x0BF00209, 0x0AF509EF, 0xF7F614FA, 0xF513070A, 0x09E512FD,
+0xF3050D0C, 0x0006020D, 0xFAED07FE, 0x07FE170B, 0x121300FF, 0x02F602FD, 0x0AF408FA, 0x06FAF7F1,
+0x0807F71A, 0xFBF20C0B, 0xF3FD05F7, 0x06F4090F, 0xF1FEF307, 0x0805EBFA, 0x0810070D, 0xF6F31214,
+0x02ED0607, 0x0D08010F, 0x09F60FF2, 0x0BF8F20C, 0x1BFCF6F4, 0xECFB070C, 0x13FAF3FD, 0xF8F7FCF4,
+0x0C09F7F4, 0xF001E9F9, 0x11F1F305, 0xFAEC08FA, 0xF8F8F40F, 0xF6F70B0A, 0x07F012F4, 0xFDF5FEF3,
+0x09070EF1, 0x09FFF7E9, 0xEAF60C0F, 0x04030106, 0xF5E70709, 0x0AF6F70C, 0xFA14FEF1, 0xF0E51903,
+0xF4EF0B11, 0xF0F80CF3, 0x12ED0307, 0xF301F405, 0xF9F4F3F5, 0x0B0EF809, 0xF7EBF9F8, 0xF10BF406,
+0xFBEEF2F6, 0xEC1111F2, 0x0716EEF6, 0x080910F0, 0xEE0D0010, 0x07ECF7F0, 0x09060005, 0x0DF5EB0B,
+0x0212110C, 0xF3F704FA, 0xEA02020C, 0x050811F1, 0x01FA07F7, 0xF60E0D0D, 0xF711F60C, 0x0108F4F1,
+0xF7F6FE01, 0x0F0FF7F9, 0xEFE7010A, 0x090902F6, 0x0FE809F8, 0xFDFE00F6, 0xEF0806F5, 0x10F80F0F,
+0x0419F40B, 0xEF08EEFD, 0x0711F507, 0xF20901FB, 0x0BFA130A, 0xFA120CF9, 0xE809F2F2, 0xFAF8FE00,
+0xF2FDFCF8, 0xF805F1FD, 0xF1F70912, 0x0903F80B, 0xF9EFF70B, 0x0D05F5F2, 0x0A08FF0E, 0x09F5EE00,
+0x08F91314, 0x0AFEF60A, 0xE51005F0, 0x041EECFA, 0x06FDFF05, 0x0D11F1EF, 0xF4F80912, 0x0D090106,
+0xFAF6F308, 0xFE14F8F1, 0x0D02EE03, 0xF0FDFAED, 0xF2F2E903, 0xE9040C0D, 0x0A00F8F8, 0xF4FA0909,
+0xF4EFFA1B, 0xFC0D0D0B, 0xF2EE08F5, 0x000E0F12, 0xF0F50F11, 0x04FEF9F4, 0x0BF914EB, 0x170CFBF9,
+0x03F30E06, 0x01F8F70F, 0x14F8EFFD, 0xF412F5F2, 0x0AF60C01, 0xF711090D, 0xF60DF90C, 0x09F0ECE8,
+0xEC06140C, 0xFD090DFA, 0xEA01F7EF, 0x030AF8F6, 0xF3F5FCFD, 0xF4F3F500, 0xF3EDECF5, 0xF3130AF6,
+0xF8EFFA0E, 0x0A0B0DF4, 0xF1F0F7F5, 0x0D0A09F4, 0x10EDEEF7, 0x0E0EEDFE, 0xF4F9F306, 0x05FCF8FF,
+0x13FBF7F2, 0xFF07F6F7, 0x0AF2F8F6, 0x0DFA1EFF, 0xF6EE0B09, 0xF113030B, 0xFAF9F3F5, 0xFA0C080C,
+0x0BF8F607, 0x09F902FB, 0xF50BFD08, 0xF7F515EF, 0x0BFA00FB, 0x01FAF009, 0xEA02FE05, 0x0CFBFC10,
+0xFBF7F214, 0x1305F1ED, 0xFA01F216, 0xFDFBFFF4, 0xEE0B040C, 0xFAFB05FD, 0xFEF8F7F4, 0xF60802EF,
+0xF301E603, 0x03EEFAF7, 0xF109EAF2, 0xEF0BFEF5, 0xFFF31115, 0xED09F309, 0x02FFEE0D, 0xF60D0FF9,
+0x030A07FA, 0xF5F4060A, 0x140FFEF1, 0xF6FCEEFF, 0x07030006, 0xFBEF04F7, 0x0AF009FC, 0xF90A0FF9,
+0xF2F702F8, 0xFFFBFB0E, 0x0907090B, 0x0B180F02, 0x0B0C0405, 0x12F80AF9, 0x09F400F0, 0xF010070A,
+0xEBF105F1, 0x05F90C11, 0xE805F30B, 0x12F70BF3, 0xEF11EFFC, 0xEFF7FC0F, 0xE709EF10, 0xF50CFBFD,
+0xF7F805F0, 0xF609FCF7, 0xEAF80F00, 0xFBF40B10, 0xF71106F5, 0xFA12FB01, 0x020BF30C, 0x0714FA04,
+0x06010708, 0xF2110D0D, 0xEEF6F2F8, 0xF009F1E8, 0x07FD06F7, 0x14F8EF0C, 0xF00DF9F6, 0xF20BF50B,
+0xF90C06F7, 0x06FB02F7, 0xF7F20A09, 0xFA051008, 0x0EFA0913, 0x05060D03, 0xFCF40CF6, 0x03E8FCFC,
+0xF3F31411, 0xFCF40906, 0xFB0BF9F7, 0xFC02F80D, 0xF20408F2, 0xEE0EEF0B, 0xF0000EF3, 0xFBF6EDF1,
+0xFAF50FEB, 0x06FC0C0B, 0xF009F80F, 0xF0F7F706, 0xF70507FC, 0x0AF00209, 0xFF0DF20F, 0xEA15FA06,
+0x0816EDF3, 0x000EF9F5, 0xEFF7FA04, 0x0FF60814, 0xF1FEFA02, 0x0805F306, 0xF610FDEE, 0xF8061606,
+0xFE0DFCEF, 0x07F8F613, 0x0C0809F9, 0x0DEBF0FB, 0xF00EF4F4, 0xF8E7F20A, 0xF3FAF20D, 0xF90D04EE,
+0xF1F40E00, 0x09EFFFEC, 0xFE0B0EE7, 0xF7FA0F0E, 0xF00CFEF4, 0xFAEEF9FC, 0x161AF703, 0xF70F10EC,
+0xF6F011FA, 0x10FDFB0B, 0xF60C03FE, 0x0AFF08F3, 0xF6F606F0, 0xF5F716F3, 0xFDFDEBF7, 0x0CF8EFF4,
+0xE3EF0910, 0xF7F6FF12, 0x001402F1, 0x03100EF2, 0x1117EBFF, 0x17FA1008, 0x0DF9F80E, 0xFCF0F511,
+0x1403EEFC, 0x0010F100, 0x110A0612, 0xF505FAEF, 0xF4F304F4, 0x061209EF, 0x090C150C, 0x04F41306,
+0x0B0C0DED, 0xF0F6F110, 0xFC0F1008, 0xF3EF0E08, 0x0B0AECF8, 0x0CF8FA0C, 0xF7FB0EFF, 0x0FF50FFC,
+0x0DF4EDF8, 0x02080C0B, 0xF510F2F2, 0x0208FDF1, 0x060B04F1, 0xF8F6E607, 0xF415EDFF, 0xE8FBEBEC,
+0x0805F30F, 0x00F30F09, 0xFA0DF6EB, 0x0BEEF806, 0x0408F00B, 0xF4F5FB09, 0x090EF310, 0x1006FBF9,
+0xF0F7F710, 0xFC070C0F, 0xFB12EAFA, 0x0BF007F1, 0x080100F1, 0xF700F709, 0x0A0D05F8, 0xEFF20D0C,
+0xF209F8F8, 0xF207FDF3, 0x0DEFEFEE, 0xFD020114, 0x0AF5050A, 0x0D0415FA, 0x0C12ED0F, 0x14F01005,
+0xF7F0EE06, 0x0F14F209, 0x080500F9, 0x08F5050E, 0x0DE7E901, 0x03FDF3FC, 0xF20403FD, 0xF7F2F60D,
+0xECF00D09, 0xFB09FF0A, 0xF306F9F2, 0x0E03F20E, 0x0C09F305, 0x11F710F8, 0xF4F217E4, 0x0E09090A,
+0x0A12F0F9, 0x06F312FE, 0xFDFBFDEE, 0xE9F0020D, 0x0DFB1005, 0x0200E90B, 0x0F0C02F5, 0xF8FF05F4,
+0x0AF303FD, 0x0BF4100E, 0x14F2040F, 0x0EF9EF0B, 0x0AED0801, 0x05F5EE08, 0xFF0A0514, 0xF8F2F0FF,
+0x0FFAF7F0, 0xE10E12F6, 0x13F1F4FA, 0xF3FC0B0B, 0xEFFEF4FD, 0xF9080708, 0x05FCF9F6, 0x040E06F4,
+0x020DF5F6, 0x13F50B11, 0x1513F1F6, 0x05F707ED, 0xF7FB01F7, 0xF1EF06FA, 0x09FB1102, 0x06FC0706,
+0xF7F80F14, 0x0EF3F002, 0x0AF8FE0A, 0x0BE8F5F9, 0xEEF609E9, 0x09E8EE02, 0x03090BFC, 0xF0F8F0F1,
+0xF8081009, 0x0F0002FA, 0xFCF202FD, 0x0DF106EF, 0xF70408F5, 0x02140C15, 0xF6F6F5EF, 0xF1080905,
+0xE902FDEC, 0xF3F4F6F6, 0xF904FCF2, 0xF906F5F3, 0xF7FB0A08, 0x08F4F0F1, 0x0EFDF6F1, 0x03F8F6F6,
+0xFF0C110C, 0xF1FDF7F8, 0xF814F502, 0x12FD1108, 0x0DF7F313, 0xF506FA11, 0x07FEF9F2, 0xEAF20D09,
+0xFCF40D0D, 0x06F1F709, 0xF7F21DFA, 0xFB00ED11, 0x0DFA0208, 0xF1FE1101, 0x0AF5F4F9, 0x060BF3F9,
+0x080CFD06, 0xF30EF409, 0x12EB02EF, 0x0BEF0D09, 0x1512F0F0, 0x18010700, 0x05070F05, 0xF306FC08,
+0x0001FD0E, 0x10FD0DF8, 0xF708F90A, 0x100D0D05, 0x04011414, 0x0AF90D0C, 0xF402F8EE, 0xFC11FAFF,
+0xF500F605, 0xF0EAF8F4, 0x120F0407, 0x1103F9EE, 0xF9F9F5F7, 0x10060EF8, 0x0609F504, 0xF20E080F,
+0x0EF3F109, 0xFB05F60E, 0x0E1C05FD, 0xF710FBEB, 0x16F2F90B, 0xF500FEF4, 0x0A13EEF7, 0x0EFF0CF6,
+0xFFF903F8, 0xF30A0BF0, 0xF7FCF004, 0x1613F70B, 0xF90506F5, 0xEB09F008, 0x05F30CF3, 0x0310EEF3,
+0xFD1002F4, 0x09070114, 0x040B0606, 0xE400F907, 0x13F40B1A, 0x06F4EBE7, 0xF1EE06F9, 0xFAF9130D,
+0xF3ED090A, 0x08EF05F8, 0xF814F507, 0xF8131707, 0x1EFCEF0C, 0xF1090708, 0x04F211F0, 0xEFF0090E,
+0x09FBF3FD, 0xF3F204F4, 0xF000FC1C, 0xFC00F009, 0xF9FD160F, 0x16F7F80D, 0x0DF8060B, 0x03FAF4FB,
+0x03FDFF0D, 0xF4F1F40E, 0xF9EBF7F2, 0x0EF6FA06, 0x09F3EDFA, 0xFEF4EFF2, 0x0F0300F4, 0x0DEBFBFC,
+0x1FF0010E, 0xF9140E07, 0xF2F6FD07, 0x11E9020B, 0xEE17070B, 0x10FD0003, 0x0904F5F7, 0x0515FCEE,
+0x090F07FF, 0x12FC1104, 0x10F9F0F1, 0x0A080700, 0x010A1200, 0x120B01F5, 0xF7F0ED01, 0xFB06040E,
+0xF0FEF30B, 0x0A0713FC, 0xF6F7F9EC, 0x07F803ED, 0xF2F9EF0F, 0xFAF4100A, 0x020AFA04, 0x0806130D,
+0xFF0B0F04, 0x080705F8, 0x04F503F3, 0x05EEF9ED, 0xFBFEF30A, 0xF2F9F20B, 0x03FEECEB, 0x08F40302,
+0x0617FE0A, 0xFE10050C, 0x0410FAF3, 0xF508EFF9, 0x030908F2, 0x010206FC, 0xFDF7F415, 0xF9080F05,
+0xFBF00CEE, 0x0BFD0D0B, 0xF7F9F10A, 0xF80603F9, 0xF202F4F5, 0x0F07FA05, 0x04FA09F8, 0x08F80B04,
+0xED030E00, 0x0A04FDF8, 0xEFFC0B14, 0x05F2FFFE, 0xECF60EFB, 0xFE04FD07, 0x0AEDFB0D, 0xF20FF407,
+0xF4030A00, 0x15F1EEF2, 0xF50B0D0B, 0x02FE11FB, 0xF3FBF8F8, 0xF7F0F516, 0xF6070A04, 0xFD0C1A0D,
+0xF603F50B, 0x0D0F04FA, 0xF5F5EFF7, 0xFB130FE9, 0x0C0205F3, 0xFB050CF7, 0xF9F809FF, 0xF1120DF0,
+0x0E0503F8, 0x16FEFDF6, 0xFA0AF5F7, 0xF302F6F9, 0xFC07F4EE, 0x0A040A00, 0xFFF409EE, 0xF8F7FD18,
+0xFC01F7EA, 0x0F11F40F, 0x0DF7F708, 0x0DF60809, 0x0DFD0F08, 0x1012FA0E, 0x021615F4, 0x04FCEBFB,
+0xF7FC09FE, 0x0C080DF9, 0xF8EB05FC, 0x0708F2EE, 0xFC14F80C, 0x0C06F111, 0x0809F9F2, 0x0CF809FF,
+0x0DF50AF8, 0x05EA0E12, 0xFCF6F805, 0xF5EC0A0B, 0xF2080D10, 0x09FBED04, 0xEFF7F40E, 0xF8F610F6,
+0x09F4F1F9, 0xFFFC0E0B, 0x020AF3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEFF410FC, 0x07FD0EFD, 0x0D060100,
+0x13F4FAF3, 0xFFF001FE, 0x08FC07F0, 0x0900FC05, 0xF5F8F709, 0x0CFC100C, 0xF7F7FBFC, 0xF7F608F4,
+0x05F90308, 0xECF6FF08, 0xF2F70B07, 0x04FE03F5, 0xFC02FBFE, 0x02F41301, 0xF1F6F50E, 0xF9FA00E4,
+0x0EFB0709, 0xF50800F7, 0x040AEC07, 0x130301FA, 0x0409F809, 0xF104EA0F, 0xF7F00A09, 0xF80BF704,
+0x13F800FE, 0xFAF50CF3, 0xF103090A, 0x12FAF30A, 0xF611F8F9, 0x02F1F403, 0x0A040FED, 0x0AFFFEF2,
+0x05FBF7FD, 0x0FE903F3, 0xF6EA090B, 0x120FFE07, 0xFA1406F2, 0x0EF80EFB, 0x0EFDFAFC, 0x0EFC0D0A,
+0x120805EF, 0xF70DF900, 0x0C0EE5FB, 0x0F0DF503, 0xF609000A, 0x0D03F5F9, 0x0FFB1006, 0x05F60A08,
+0xED07F8EF, 0xF90CEE0A, 0x0B16100A, 0xFD07F607, 0x0EFF0D01, 0x0CEF04EB, 0x11F5FD0B, 0x080B0CF5,
+0xFF14FEF5, 0xF1FAF413, 0xFA0100F6, 0xF0090FFC, 0xF3FB0AEF, 0xFE09FE0E, 0xF710F3F5, 0x04090C11,
+0x04EEEFF2, 0x09FC0FF1, 0xFE0BF4F9, 0x08F10AFC, 0x030AF5FE, 0x13FA0FF4, 0x07000AFE, 0x071507F5,
+0x06FD08F0, 0x0F0C08EE, 0x190E020D, 0x08EDF4EB, 0x0D0DF109, 0x0210EF00, 0xF506080A, 0x1010F7F0,
+0xFE02F7FB, 0x09F8F6F7, 0xF902FF04, 0x16E003FE, 0x12EA1A00, 0x130E0FFF, 0x0702F2F9, 0xF10BEFFC,
+0x010E04F1, 0xF6EF15F6, 0xF50A0510, 0x050DEF0D, 0xF908F4F6, 0x0F0F0BF0, 0x04F7F6FC, 0x07F9FAEE,
+0x02EE07F9, 0xF6F90105, 0xF1FFFC04, 0x0802EB0C, 0xF10E0CF3, 0x030E0508, 0x0CF60CF9, 0x08F20EF5,
+0xEFFE09EF, 0xF9FB0A06, 0x14F6F6F5, 0xF6140DFE, 0xF511F8F4, 0xF0FAEF00, 0x1103FC0B, 0xF1090B05,
+0xF4FD11F0, 0xF80BF6F1, 0x14160D0B, 0x1105070C, 0x0DEDF80B, 0x1005EE07, 0xFCEFF5E2, 0x0812F3F6,
+0xF2100BFD, 0x04FAF00B, 0xFD08F508, 0x06030EEA, 0xF4F90C05, 0xF5EE0608, 0x0CEEF40F, 0xF4F8FB06,
+0xFCF01609, 0x0407F402, 0xFDFBFDFD, 0x0BF4F806, 0xFCF701EB, 0x08EB0709, 0xECF9040B, 0xF8E9F300,
+0x1C0CEEF5, 0x0703FC08, 0xFEF40909, 0x150B0EFF, 0xF30D0B07, 0xFAF203F9, 0x02F209FA, 0x060EFDF7,
+0xFCEB0FF2, 0x0313FF13, 0x030A0B07, 0x0BF70003, 0x00090D02, 0x1405F106, 0x020AFCF6, 0xFAFD01F6,
+0xEE05F7EB, 0x030201F4, 0x06071009, 0x0E000704, 0x0A060F07, 0x0C0DFE04, 0xF1FA001A, 0xFFF90B10,
+0xF607ED0F, 0x06F9100D, 0x05F6F40C, 0x0E0BF106, 0xF8FB09FF, 0xEBEE13FB, 0x0C0EF4F5, 0xF608EC0A,
+0xF9F5F905, 0x0AEE03F5, 0x000B0A03, 0x0815F904, 0x13F7100F, 0xFB0711ED, 0xECF5FD01, 0x0D03F90C,
+0xF4FA05EF, 0x1209050A, 0xF60BFD0A, 0xFF04F706, 0xF8ED06F0, 0x0001F71A, 0x09EEFFFA, 0xFF0D0BEA,
+0x130F00F4, 0xF1F904FA, 0x05EDF504, 0x030AF7F8, 0x09F712F1, 0xFF0C0E07, 0xFE12F9F6, 0x08FC08F0,
+0xF9F813FE, 0x01FF0D0C, 0xF3F10C06, 0xEC05F7F4, 0xFCF6FD04, 0x0B07FEF6, 0xF8FC13E8, 0xF004F611,
+0xF6060210, 0x12FDF5ED, 0x0100F9ED, 0xEE03F8FE, 0x11F4F40C, 0x0C0BF614, 0x0D050411, 0x0B080FFA,
+0xF2F906F9, 0xF5F3F8F2, 0xEF06080E, 0xF614F60D, 0x0A080A0E, 0xFBF2F9FB, 0x1612F1F7, 0xF4F60FF3,
+0x010D0B0B, 0x0C0EFB07, 0x0B04FDED, 0xFAF50604, 0xF2FAFB0A, 0x0AF1FFF2, 0x100C0611, 0x01EF0CF9,
+0x0B12F90A, 0x12FBF002, 0x04040D05, 0x10FEF910, 0xEAFC0AE7, 0xF404FFFC, 0xEA08F9ED, 0xF5F616F6,
+0xF10106F7, 0xF806F5F8, 0xF8F70CFA, 0x0CF7FEFB, 0x0AEEEF08, 0x0AFBF0F2, 0x13F5EFEF, 0xFD010BFC,
+0xFA01F3ED, 0x08F30D09, 0x09FEF902, 0x050FFDF4, 0x11FAFE08, 0x1703F1F2, 0xF3FCFE03, 0x06F4EA10,
+0x090FEE13, 0x00F20702, 0xFBF90401, 0x070CEBF7, 0x0FF6F50B, 0xEEF8F6FF, 0x0A0AF506, 0x06F0010A,
+0xF0F6F4FB, 0x00F51201, 0x0DF90C02, 0xF1F8F0EF, 0x061706EC, 0x0DF80EFD, 0xF0F6030A, 0x03FB100E,
+0xF608F50D, 0xF10F08EF, 0xF9F0F105, 0x0EF7FA0E, 0xFD030811, 0x12ED0CF6, 0x050508F7, 0x05F90514,
+0x0D100A10, 0xEAF901FF, 0x070B010D, 0xF90D140A, 0xFC02F1F4, 0xE9FCF3F8, 0x07F70FF2, 0x0409F8FF,
+0x0C080CF5, 0x03FEF0F5, 0xF80E000C, 0x0201FAF2, 0x1314090D, 0xF90507F5, 0x05F302F0, 0x0CEFFDFB,
+0xF11813EF, 0x10FFEEF6
+
+
+basegraph=
+1
+
+z_c=
+176
+
+n_cb=
+11616
+
+q_m=
+2
+
+n_filler=
+8
+
+e=
+4640
+
+rv_index=
+2
+
+code_block_mode=
+1
+
+iter_max=
+20
+
+expected_iter_count=
+4
+
+op_flags=
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE
+
+expected_status=
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_2.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_2.data
new file mode 100644
index 000000000..2463df617
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_HARQ_1_2.data
@@ -0,0 +1,902 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0xF315FCEF, 0xF50FFAFA, 0xFBF70DEE, 0x1013060C, 0x0B0AFCE7, 0xF0F30BF4, 0x0C070F06, 0x10F7F30F,
+0xFE0F0E0D, 0x0FF7FE09, 0x07090606, 0xF705F004, 0x150EF10B, 0x080C010A, 0xF7FA0909, 0x0B00140A,
+0xF1F2F8F9, 0x0AF2F910, 0x0D0F0CEF, 0x03F4F20D, 0x0CF90CF9, 0x06F4F501, 0x12FEF3EA, 0xF210F3F9,
+0x0312020C, 0x0D0FEF0C, 0x011714F4, 0x110E02F3, 0xF102F613, 0x0A0B090C, 0x1503FA10, 0x0D13F011,
+0xED0F0F0F, 0xF8F712F8, 0x10060502, 0x14EEF0F6, 0xEEF50606, 0x0BEDF006, 0xF2120906, 0x0F0700F4,
+0xECF00D04, 0xF414F1F5, 0xF1ECF918, 0xF40B090C, 0xFD0FEDEF, 0x0DFDFBED, 0x0703FCF3, 0xEFF2FDED,
+0x03021100, 0x0608F00A, 0x0BF7F910, 0xF7EEF20C, 0xF9ED0901, 0xECF2F0F2, 0xEB09F6F3, 0x0F06F5F7,
+0xF90E0610, 0x07010611, 0x06F20E0D, 0x0E06EF00, 0x070C050D, 0x0C0F09F1, 0x10FE0CF6, 0x11EF0B14,
+0x03FCE40C, 0xF4F506F4, 0xF400F613, 0x0E0509F8, 0xF00DF9F6, 0xF5F612E9, 0x1208FE15, 0x0607F307,
+0x1108EE0C, 0xFDFBFB04, 0x02F30D05, 0xFDF0041A, 0x100CF1F4, 0x0DFAFBF9, 0xE9F10B09, 0xEEF214F9,
+0x02F6F5F8, 0x0F010CF6, 0xF11008EF, 0x0CF3130A, 0x03FE11F5, 0xF6050708, 0xFC050EEC, 0x0BF8F4F9,
+0x04F50FFF, 0x000206EB, 0xEFF9F7ED, 0x0E14F90C, 0x080401FC, 0x0A0401E5, 0xEE13F30C, 0xF10A0916,
+0xF0F400EC, 0xFF03F614, 0x0409EBF2, 0x0C0906FA, 0xF70C0400, 0x0FFAFAFA, 0x1201F611, 0xF5FAFAF1,
+0xF40FFA09, 0xFFF2F1EF, 0x0BEFF7FA, 0x0703FC07, 0x08F11109, 0xEF09FEEA, 0x07F908FB, 0xF9FD0812,
+0xF90B0A02, 0x05F210F4, 0x1AF7F407, 0xEFF8FA0D, 0xF5F9F606, 0x02EB0D0F, 0xF7F5FDFE, 0x130BF5FB,
+0x05F6F6F8, 0x1503FFFD, 0xF2F701F9, 0xF1F6F70B, 0x01010B08, 0xF717FBF6, 0x06FAFA05, 0x050CEF11,
+0x11F30200, 0x09020F04, 0x07030601, 0x0603FC12, 0xFB0014F7, 0xF7F70CF2, 0xF0F6EEFA, 0x0EF107F8,
+0xEA0D0A10, 0x0AEC0C0E, 0xF5060D07, 0xF7F4E804, 0x0902E90B, 0xEE090AFD, 0x02F60210, 0x090BFCFD,
+0xF7F8FCF7, 0x030C0905, 0x040AF1F5, 0xF0F80CE7, 0x100AF413, 0xF8FB0817, 0x02EFFA04, 0xFB04EC08,
+0x16F4FDFE, 0xE8FD07F4, 0xF2FFEF07, 0x0DF105F4, 0xF4EDF50B, 0xF7EB04FC, 0xF8F601E8, 0xEE0B00F0,
+0xF516040E, 0xF600F605, 0x090705EC, 0xF10408F2, 0xE9F2EC11, 0xE90E1613, 0xF601F6F4, 0xF307F4F8,
+0x100B060B, 0xF90D0402, 0x09FE0715, 0xF90E06F7, 0xF6FC08F7, 0xF7F30FF2, 0x040A05FA, 0x08F1F411,
+0xF6F806F5, 0x0EFBFD0B, 0x0A0EF6FD, 0xEFF4F8F5, 0xFD05F8EB, 0x1300F8FD, 0xF7FE0CF6, 0x05F4E903,
+0xF50302EF, 0xF8F514F8, 0x11F8F4F7, 0x120F11F6, 0x07F4FF09, 0x0D0FF700, 0x0EF7FD03, 0x090A06EF,
+0xF90206FC, 0xF20FFEFB, 0xF90709FC, 0xFEFDF2F3, 0x0DF70DF7, 0x10F10808, 0x0B08F5FC, 0xF20605F9,
+0x1DF5FAFF, 0x0B04F20C, 0xEDF811FA, 0x0F04EC07, 0xEEF4F40D, 0xF9100EF0, 0xFCEEEDF3, 0xF109EA00,
+0xE0E8F913, 0x0AFA0AED, 0xF3E7F90B, 0x06FB0BFE, 0x12FEF20D, 0xF4040C04, 0xF409090D, 0xF3F8FAF5,
+0x02F60306, 0x12F6FFFA, 0xF9FAF4F8, 0xF70D0408, 0x0400F007, 0x1501FDF2, 0xF305ECF2, 0x18EF01FC,
+0x0FF2050C, 0x050DF30F, 0xFCF80813, 0xF3F906FD, 0xFDF3FAEF, 0xECFCEDFE, 0x0D05F810, 0xFC0B11F9,
+0xF9FE0AE9, 0xF70EF4F3, 0xF9F1F1F8, 0xFCFA0DF8, 0x140F00EA, 0xF00AED07, 0xF9030CFC, 0xF604F9FA,
+0xF8140217, 0x08F816FE, 0xFA06FF0D, 0xFC0C11F3, 0xF6F5050E, 0x09FB0010, 0x0C11F4F3, 0x05ECFE0D,
+0x04F7070A, 0x12F50FEC, 0x0DFB0208, 0x110C03FA, 0xF50CF70A, 0xF90BF908, 0xFA0F0CF8, 0x100306F0,
+0xF50C04FA, 0x060B0909, 0xF4FF0F13, 0x06FAFA02, 0x05150912, 0x0E0BF308, 0x0BFB0E0B, 0x0FF405F2,
+0xF10AFD07, 0xFA00080C, 0xFB0FEB02, 0xF7FFFC0C, 0x0DF40BFB, 0x16FE060D, 0xFEF908FE, 0xF5F600F5,
+0x0204F7F5, 0xF605FFFC, 0xF802F606, 0xFA09EB0E, 0xEF0B0CF3, 0x1308F909, 0xF7F704F9, 0x0702F600,
+0x04F5F00A, 0xF7FAFC0F, 0x0BF70BF6, 0x16F3FF08, 0xF20B09FB, 0xF905F115, 0x040908FE, 0xEBF9090C,
+0xF808F3F5, 0x0512F3EF, 0xEEFC07F4, 0xEFFFFCFF, 0xEE0DF4FE, 0x11F7100A, 0x01F600F4, 0xF413F3F9,
+0x06F2F2F1, 0xF0120B03, 0x0D0CF3F7, 0xE4F000FB, 0xF7FC1A09, 0xFFED0912, 0xFF08E7F9, 0x06FA08F8,
+0x06F70D01, 0x05FEEE16, 0x13F2F90F, 0x0EFC0D01, 0xF5130AFF, 0xF3F0ED0D, 0xF10AF807, 0xF4F0030C,
+0x090AF3F7, 0x0C0BFFEC, 0x17FAF3F4, 0x0C0813F4, 0xEF0C0C0F, 0x0AF2E7F7, 0xF3EF0804, 0x05F90912,
+0xFDF9F002, 0x041106EF, 0xF51BFAEF, 0xEFF20411, 0x07FCFDF1, 0x09F6FB11, 0xF00D0907, 0x0717F20B,
+0xFCEF0800, 0xF0080009, 0xF011F50D, 0xFC06EC0B, 0x16FF0FF8, 0xF9F611FC, 0xF8F70D18, 0x160C0B13,
+0x0612F7F5, 0x0D08F80C, 0xF4F9E7F2, 0x03FB0EF8, 0xFF0CF908, 0xEFF111F4, 0xF4EE0EFB, 0xF4FE0502,
+0xF70A06FD, 0x0DFBFFFD, 0xFAF2F205, 0xFA060A0B, 0xEDFE0EF9, 0xF5EDF30B, 0xEF0C0616, 0x12020807,
+0x00F9F4FB, 0x0FF803F4, 0xFBF8FC01, 0x0D02EB0D, 0x01F2F9F1, 0x0B0CF0F4, 0xFA0C0712, 0x0DF314EE,
+0xFD0E0706, 0x06080AF8, 0x1600F7F2, 0xFCF2FEED, 0xF3090BF4, 0xEE0417FA, 0x00F90305, 0x1008110D,
+0xF5F1F7F4, 0xF5FB04F6, 0xFC0B02F4, 0xF1FB00F0, 0x0712FF10, 0xF5EB0FF4, 0x110AF005, 0xFE02FC18,
+0xF0E8F106, 0x100DF90D, 0xF30900FD, 0xF6F208F7, 0xFE021404, 0xED0AF612, 0x0104F5F8, 0xFE09F7F3,
+0xED0A01F8, 0x0BFE0405, 0xF008FA0A, 0xFB1CF201, 0x0712F70F, 0xF0F2FE05, 0xFFF6FC04, 0x0AF4070D,
+0xF9F3ECF9, 0x0AEC0BED, 0xEF0D010E, 0xF314F8FF, 0xEF0BFB0B, 0x0602F90B, 0x10F70A04, 0xFAEE0806,
+0x0EF7F005, 0xEEF0F60D, 0x13EE0D07, 0xF415F203, 0xFBF8F0F3, 0xEBEB0BE4, 0x05FBF803, 0xF40A07F9,
+0xEFF7F311, 0x040FF5F0, 0x0DFCED00, 0x050BEEF9, 0xF30CF612, 0xFB00EA0C, 0xF208F7F0, 0x0603F911,
+0xEC02EB04, 0xEFF812F3, 0xEFF60200, 0xF40208FF, 0x12010A05, 0x06F017F8, 0x050F0C16, 0x120010F9,
+0x0EF70707, 0xF0FA100E, 0xEFF50D01, 0xF5EE0808, 0xF409F2F5, 0x03FFF50C, 0xF2F0FCF1, 0x01EE16F7,
+0x081015F9, 0xFDF10BF7, 0xFBEBF10B, 0x0EF208F7, 0x0C11EE0A, 0x0FFAF00E, 0x0D03F706, 0xF7F711F4,
+0x05F30A06, 0xF709F904, 0x031A0DFB, 0xF8EC0608, 0x08EE0909, 0xF202EEF6, 0xFAF7F10F, 0x0F0FF3F9,
+0x09010CF6, 0x04F60EF7, 0x0B0FF0EB, 0x08ECF80E, 0x0EFB0010, 0x0104EF14, 0xE9EF0CF4, 0x0AF9EFFD,
+0x0B001415, 0xEF04FC07, 0xFF0C13EE, 0xF1F4F2FC, 0x0E08E7F7, 0x000CF612, 0xFD0B07EE, 0xFEFE04F0,
+0xFBFB0D07, 0x0AE80103, 0xF4F2F309, 0xF2EFFBF9, 0x0A07EC05, 0xF405EEFA, 0x03F706F8, 0x010005F6,
+0x0DFFF711, 0xF5030BED, 0x11EEFB13, 0xEE01EAEF, 0xF8F70DFB, 0x070DFBF8, 0xF5F116F0, 0xF7FB0401,
+0xF6F8F008, 0xF6EDF3F7, 0x1A02F912, 0xFD06F803, 0xF501F70D, 0x0A011708, 0xF0FA0E02, 0xF906FBFC,
+0xEFFCF707, 0xF50E09F8, 0xFA0CE9F9, 0xFB0E13F0, 0xF117F30D, 0x0C0702F9, 0x0CFBF705, 0xFB12F0ED,
+0xF5F1FF14, 0x0D070C07, 0xF90B0409, 0xF1F3FE09, 0xEF03F80A, 0xFAEE0509, 0x11F4F600, 0x16081215,
+0x0909F7F6, 0x0EF80A04, 0x0AFB0EEE, 0xF3FC020D, 0xF4FDEEF8, 0xFCF9F310, 0x0AEA00F5, 0x0AF0040F,
+0x09F7EEF7, 0xFFF3F409, 0x11F704EF, 0x0C10F710, 0xF70AEA12, 0xFCF201FB, 0xF4000F01, 0x0F021100,
+0x0B0AF4FA, 0xF802F702, 0x0812090D, 0xF9F30A10, 0x0FF2F309, 0x0DFCE9F8, 0xFA06FA02, 0x10E7FE06,
+0x15F8F410, 0x020D02F7, 0xEB0810F8, 0xF011FC10, 0xF5F812F6, 0xF71010F2, 0x0DEE0DF3, 0xF8EF08F9,
+0xF1F5FC11, 0xF8F8EBFD, 0x0604EEF3, 0x070CF40A, 0x0C070CF8, 0xFC090014, 0xF10EFDFB, 0x0CF80616,
+0x0DFFF2F9, 0x0802F5F8, 0x09EE1309, 0xF8F70C04, 0x0AF50C03, 0xF90AF5F5, 0x0E00FE0E, 0xF1F7FEF6,
+0xF8F3050A, 0xFCF50A13, 0x0AFE0B11, 0xF5F500E5, 0x0D0DFCF8, 0xF208F405, 0x01EEF0F9, 0x0900FB06,
+0xF4F30EEA, 0x03FA0C02, 0xFC03F60B, 0xF8070AEA, 0xF1ECF9FF, 0x09FE0813, 0xFA020B11, 0xFF0210F6,
+0xF3F4ECE6, 0xEEF6F6F4, 0xF50CFEF1, 0x08F2EA0E, 0xF7F70D06, 0xF708EF07, 0xFB0CFC0B, 0xEF0FF4F2,
+0xFAF0FD0C, 0xF3F311FD, 0x01F5EC0F, 0xF9F10608, 0x0E07F3F3, 0x130508FE, 0x01EB12FA, 0xFF0804F1,
+0x0707040D, 0xF408FCFC, 0xFCFEF014, 0x090A0007, 0x0C06F5F3, 0xF5020CED, 0xFCED0C0F, 0x0C0D1008,
+0x0F0FFC06, 0x0B09F7F6, 0x08F208F8, 0xF7F7F60C, 0x030AF408, 0x051BF9FC, 0x1307080C, 0x0000F60F,
+0x0B07F211, 0x0613F70E, 0x0310F5F4, 0xF0F812F7, 0xFB0B1308, 0xFC0C02F5, 0x13FD010D, 0x02F008ED,
+0xF5F30EF1, 0x0511F605, 0x0008F80E, 0xF90EFA00, 0x0708090F, 0xFAF8FB0C, 0x14F7F70A, 0x09F608F7,
+0xEC120708, 0x04070A04, 0xEDFEFA08, 0xFF11EFF5, 0x0CF9F5F1, 0x04F5F507, 0xFFF70FFD, 0xF10904FF,
+0xF6F8F50F, 0x0BFE040A, 0xF71504F1, 0x0D04F717, 0x00F3FEF5, 0x13F50CFB, 0xF8F707F8, 0xFA0A09F6,
+0x09FEF605, 0x050E0300, 0x07190AEF, 0xFE040EE5, 0xF8F70D11, 0x0A08FD03, 0xF40C03F3, 0xEEF0050C,
+0xFBEFED07, 0x0AFEEFED, 0xFE0806F1, 0x0A071315, 0xF707FDF5, 0xF10D0FF4, 0x03F80709, 0x0F0BE9FA,
+0xF50D0B0C, 0x0AF7EAEB, 0x12F4F306, 0x12F10FF7, 0x06F2F20A, 0x0E0F14EE, 0xFAFC0F06, 0x0E000CFD,
+0xFAEEFCF6, 0x0EF3FD02, 0xF9100A04, 0xFAF410F5, 0x051403FB, 0x12EEF40D, 0xF90B0004, 0xF7070DEC,
+0xE5140FF1, 0x0C090E06, 0xF5FFEFF7, 0x0FF90D09, 0x00FD0A0C, 0x0A02F5FE, 0x09040DFA, 0x0D07030B,
+0x10EEF2F8, 0x0FEA0F16, 0xF611F405, 0x05F10A08, 0xF80703F7, 0x010107FA, 0xEE0DF60D, 0xF9F6F80E,
+0x10F6F5F8, 0x0B0B02FC, 0x0A08F305, 0x110107F4, 0x0D120101, 0x0EF7130A, 0x04F7EBF9, 0xF8FB03FB,
+0xFD160BF6, 0x1104F5E7, 0xF802F5F6, 0x08090BF5, 0xEA09F50D, 0xFFFB14E8, 0x0800FF0A, 0x05FDE612,
+0x14F2F609, 0xFA0301F4, 0xFBFBFC0F, 0x0410F40C, 0xF6F4EF0B, 0xF304FB05, 0xFEEE0E11, 0x12030908,
+0x07090907, 0xF707FC11, 0x0C01FDFB, 0x04F20909, 0xEFFEF20A, 0xF00B02FA, 0x0FF8050D, 0xF50EFCFE,
+0x08F20EF2, 0xFEFC0BF5, 0xF6EAFCEC, 0x08FA05F8, 0x0AFCFE0C, 0xEFF20A11, 0x0FF1F411, 0x13F8FAF1,
+0x0A0912FE, 0x070514F7, 0xF3F8F50B, 0xF3091503, 0x080BF00B, 0xF2F9FD03, 0xF3F503F2, 0xFAF9F819,
+0x02FFF9FA, 0x19F6FA08, 0xF403FF00, 0xF40901F5, 0x0613F514, 0xF9F40DF9, 0x030A14F6, 0x170AFC12,
+0xF4F10AF0, 0xF5E506FC, 0x0BECF0FA, 0xFC04101E, 0x0BFFFBF1, 0x12F2EEFD, 0xF605F7EF, 0x090DF8FD,
+0xFF09F012, 0xF9F4020C, 0x03011206, 0x16F9E009, 0x0607EC1D, 0xFE0EEAF6, 0xFA0DFFF1, 0x13FEFA14,
+0x06020D03, 0xF2F902EE, 0xEF0EFCED, 0xF104F711, 0xF0E90503, 0x15060EF2, 0x01F80AF9, 0x0AFDEF04,
+0xF10C100D, 0x090AF600, 0x03F5F909, 0x05080DFA, 0xF40E0A1B, 0xF9F408EF, 0x0BF9F0F7, 0xFB100FF9,
+0xF6081009, 0xF006F7EE, 0xFA0F0212, 0x0714F90E, 0x070F0DFD, 0x160402F5, 0xED0DF108, 0xF6F0F9EA,
+0x1000F0FF, 0xF10B130D, 0xFF0F0C0D, 0x081702F8, 0x0C0EF306, 0x0517F907, 0x05F708FB, 0x0301FAF8,
+0xF803F912, 0xF8140AF8, 0x0EF5F506, 0xF4F406FE, 0xF5F8EFED, 0xEF0A120A, 0x0A0906F9, 0x0D0BFB11,
+0xF60EF5F8, 0x000B0A0D, 0xF9EC12E8, 0x0A0900F0, 0x0C14F40C, 0xF50011F2, 0x030D000E, 0xF0FD0E09,
+0x11F70B03, 0x11EA0316, 0xF7F8050A, 0xF103F5F6, 0xFD1004FD, 0x08F31109, 0xF6F5F114, 0x0CF40BF3,
+0x0DEC0BF5, 0x14F30202, 0x070AF80A, 0x11F3F1FF, 0xF8FA0BFA, 0xF90C01EF, 0xEE0DF308, 0x10F6F10B,
+0x09F7E2F5, 0x10F1EF04, 0xF3F50AF4, 0x08F9120A, 0x0B02FDF7, 0x06FC1001, 0x0401F7FE, 0x18FAFAFA,
+0xF5F3F4F2, 0xE9F4F40D, 0xFA0CFEFF, 0x060503FC, 0xF8F7F106, 0x0813F9FB, 0xF20AF4F7, 0x09EBEEF3,
+0xF40CFBF6, 0x0CF6EEF2, 0x0F1EF1EB, 0xF4F90C0E, 0x160BF5F5, 0xFCF6F0EE, 0xF403EEF7, 0x04F10713,
+0x11071109, 0xFDFA0F0D, 0x0C08060C, 0x0BFA08F8, 0x010AFF07, 0x101FF7F8, 0xF3EE090F, 0x08F5EBF9,
+0x04FDF708, 0xEC090DF7, 0xF3150003, 0xF80BFD0A, 0xEE000A0F, 0x08F7F8FA, 0xFCF008F5, 0x0701EFFA,
+0xF5FEF505, 0xEAEAF4EE, 0x0EFCFF10, 0x15F80BFB, 0xF7060700, 0xF3100D0B, 0x1705F901, 0xFA130605,
+0xF4F2FA16, 0xEEFA0615, 0xFD130BF4, 0x06FDFA0F, 0xFB0406F8, 0xFC03EB0B, 0xFFF113FD, 0x03FA130F,
+0x0B0B07F4, 0x03120AF8, 0x00020304, 0xF70AE308, 0xF9FA0203, 0x0007F501, 0x05FAF2F7, 0x1417F1EE,
+0xFCEAF606, 0x02050AF5, 0xED12F609, 0x0E03FD0B, 0xF7FDEB01, 0x02FFF107, 0x1507F4F5, 0xEFED1609,
+0xFC02F5F9, 0x06ED07FF, 0x070F18F9, 0xFA0A000D, 0x0FF307FA, 0xF6EFF20A, 0x120604F6, 0xF7090DF4,
+0xEC120605, 0x0514FAFB, 0x0BEEFCFF, 0x130A0D10, 0x0100FAF2, 0xF6F307EF, 0x10F0F9F7, 0xF2FB0DEF,
+0xF409F8FC, 0xF10A0A05, 0xF10F060D, 0x0EF9F7F6, 0xF502FFF8, 0x0CF20F0B, 0xFFFBFB0E, 0xEBFFEE0F,
+0x0809F50B, 0xF809FAF3, 0x00FBF6EE, 0x0A0B0804, 0x0D04F105, 0x0DF709F8, 0x03F6F5F9, 0x0A12EE0C,
+0xF6ECEFF0, 0x14090BF4, 0xF907040A, 0xF4F01510, 0x10050FF1, 0x13FFF705, 0x11F80111, 0xFB05F30D,
+0x12F3EDF7, 0xECE80905, 0xF90BF8F3, 0x0DFE030B, 0xF1EF0310, 0x08030E11, 0x0510F6FB, 0x12EF09F7,
+0xFD03F610, 0xF6FB0B09, 0x0B0F06FD, 0x1309F0F8, 0x060504F0, 0x0CF7EDF8, 0xF7101AF7, 0x000A0109,
+0xFFFBFA00, 0xF5EAEEF8, 0xF7F7EAFB, 0x13FB0D08, 0x14F2F4F5, 0xFFF7FB11, 0xF00FFA01, 0x050EF9FE,
+0x09F3040C, 0xF002ED0B, 0xF7FA0C04, 0x03070A00, 0xFEF3F108, 0x09F2F701, 0xFAF8070D, 0xEBF20C11,
+0xF9060AF8, 0xEA02120A, 0xF4F104FC, 0x08051009, 0x1306FE0C, 0xF9F30C11, 0xF9EFF8F8, 0x1500FFF8,
+0xF80DF20A, 0x07F0F1F9, 0xF709F40B, 0xEC06F10B, 0x11F2040B, 0xE80D0AF8, 0xFE02F60B, 0xF7F2070F,
+0x13F6FCF5, 0xF80B1006, 0x0A1011F4, 0x040E04F1, 0x02F51013, 0xF6FA06FA, 0xF50D0103, 0x12F111F2,
+0xF90CEDF6, 0xED111408, 0x0DFC12E8, 0x0303EFE8, 0xF400F811, 0xFD070807, 0x0BF500F2, 0x0C100BF4,
+0x180DFDF7, 0x0DFB050B, 0x0FF80E0D, 0xF710F402, 0x06080D06, 0xF2F20D04, 0xF803F2F7, 0xF5EEF30E,
+0xF40E0EF3, 0x03F00600, 0xE201F9F1, 0xF60F14F6, 0x0A0F0EFF, 0x0AFA0809, 0x0DF8E6F7, 0xE7F206FC,
+0x05F8F7FB, 0x1604FD09, 0x0F0BF306, 0x08F00AF7, 0xF7070B11, 0x150BF905, 0x0F16F309, 0xF8F60E04,
+0xFDF2EDFB, 0x0BFF040D, 0x06FAF0F2, 0xFAFEF501, 0x0F02F6F3, 0x0608FA16, 0x13F9F20A, 0x0A00F10E,
+0x06FAFD04, 0x10EFF8F7, 0x0C08F914, 0x01FB030A, 0x0D0E0A02, 0x0BF1FEFE, 0xF00702F2, 0xFE080F05,
+0x0D110502, 0x04F60410, 0xF9161006, 0xFCF8FEF2, 0xF6FCFCEF, 0xFEFEFCF8, 0xEB0AFCFF, 0x08F304F8,
+0xF909010D, 0xFE0C08F4, 0x02F0F60F, 0x09F90AFF, 0xF2F40B09, 0xF104010E, 0xF5060CF6, 0x0C0CF2E7,
+0x0CF2FA0D, 0xF8F3F7FA, 0xFEF00F02, 0xF80D0BF9, 0x03FAF400, 0x0A05EE08, 0xF0EBF200, 0xF6090F03,
+0x030E03E7, 0x13FEF50B, 0x0B0FFC0E, 0x12F701FA, 0xF3FE01F4, 0x0E04010C, 0xF90DF510, 0xF4FAF302,
+0xF90B0203, 0xF516E906, 0xFDFCF400, 0xF1F7FA0F, 0x121108FA, 0xFDF60F04, 0xF1FBF20B, 0x03FC17FD,
+0xFE03EE12, 0x070A11F8, 0xFEF4FCF3, 0xF20AF4FF, 0x02F213F0, 0x09F6FBF6, 0x070202F3, 0x1509060B,
+0x04EB010B, 0xFB110DFD, 0xEB030BF4, 0x070C0CF8, 0x0A09F7FC, 0xFAF70AEF, 0xF6EBFFFE, 0xEEF70C0A,
+0xF5EE06F1, 0x0A14F500, 0x01FAF606, 0x1AEFF0FC, 0x08EB0FEB, 0x0411F617, 0xFE10EDF4, 0xEC0309FA,
+0xF8F802FA, 0x0D0D0D0D, 0x0409EFFD, 0xF1FC0C04, 0x06EEECFC, 0x061417EF, 0x0E05FD00, 0xF914F8FC,
+0xEFF20AFE, 0xF011F60A, 0x100EFA03, 0x03F5FBF1, 0x0904F808, 0xF608F4F3, 0x08F5EF03, 0xF1060FFE,
+0xF115050C, 0x0D09F0F8, 0xFAFF0E06, 0xFA04F7F4, 0xF40D11ED, 0xE90B030C, 0xF805F610, 0x120401F6,
+0x08FC0BF4, 0xF110F1FB, 0xF10E1408, 0x1907F9EF, 0x0AEC10F8, 0xF9F7FCF6, 0x010EFF0C, 0xFFF8F90C,
+0x01FAF913, 0xF30B0BFB, 0x00FBF610, 0xF90FF809, 0x05ED080D, 0xFC0DEDF4, 0x07F80C0B, 0xFDEEFCF4,
+0x0FF2F2F2, 0x07090B10, 0xF8FD1305, 0x04EE0908, 0x0C18F505, 0x0C06080B, 0xF0E6F5F3, 0xEFF812F6,
+0x14010CFF, 0xF8080E15, 0xFAFFF2EC, 0x16FD010F, 0x0907F9FB, 0x13F400F1, 0x07FBF509, 0x0DEC05F3,
+0x020A04FF, 0x05FA070D, 0x110C0FF2, 0x0C0B0302, 0xFF0403F7, 0x05F018F4, 0x02FB0BF5, 0x10F413F5
+
+harq_input0 =
+0x0FFA0103, 0x130C0B02, 0xF309F6E7, 0xF70F07F1, 0xF7090FF8, 0x050409F2, 0xF80AFAF7, 0x00F60EF5,
+0x06FC060D, 0x080DFB03, 0xF4EDF9F9, 0xFCF9FEEA, 0x0F0C12F8, 0xF9F31708, 0xF60C02FF, 0xFF110310,
+0x0BF80F0F, 0x02F6F2EE, 0xEDF20A06, 0x0709FEF2, 0x14F5F0F0, 0xF70C0018, 0x12020FEF, 0x0602EF08,
+0xF40A0200, 0xEE0C0BFC, 0x0606ED01, 0xF2F709F3, 0x15110E10, 0x06EC06F8, 0xFBF10CF8, 0x0314FEF6,
+0xF5F4FC0C, 0xF00C00FF, 0xF6FDF9F6, 0x07F30801, 0x0F04F40C, 0x0406F305, 0xFAF9F808, 0xF20DF109,
+0x010A0AF8, 0x070AFC03, 0xF108120A, 0xF8F9F1EC, 0xEEEB09FF, 0x140C0D01, 0x04E5EF10, 0xF616130C,
+0x0314F4EC, 0x09FA09F2, 0xFAFAF714, 0xFAF101FD, 0x06030FF4, 0x17F3EFFA, 0x09FEF109, 0xFDFEF9FB,
+0xF2080B02, 0x0CF90B07, 0xEB0F0D06, 0xF71009FE, 0xEF110AF8, 0x0AF70BF9, 0x170A1508, 0xF8FDFAF1,
+0x0204F3EB, 0xEFFE0315, 0x0C06000B, 0xF10C0A0E, 0xEC0EF9FC, 0x08F0F2F3, 0x09FD02F7, 0x0B11F610,
+0xF8F1F8F7, 0xF8FB0A09, 0xFB030A13, 0x040804F0, 0xE8080813, 0xF1F4FFF3, 0xEBFCEDF7, 0xF7F00AE8,
+0x00F1160E, 0xF007F301, 0x0E13F211, 0x07F815F4, 0xF9EEF70B, 0x0EF7FE15, 0x0706E80C, 0x0611F60E,
+0xFB0B0CF5, 0xF4F50E11, 0x14FDF1EB, 0xF403120A, 0x09F80303, 0xFB0AF80B, 0xFA1408F5, 0xF503F717,
+0x0FFB1610, 0x1107F3FC, 0xF1F4F7F7, 0x060EF4E8, 0x04F8F5FF, 0x04F30CFA, 0x10F008F8, 0xF514EEF3,
+0x0EEDE8FE, 0xE7FEE70B, 0x0404FEF9, 0xF8F509F9, 0x0A0EF6F2, 0xF8080EF8, 0x01F200F3, 0x03FC19F2,
+0x0D0FF2F8, 0xF9FD0C13, 0x11FE0703, 0x0BF9F110, 0x0EF3FEFD, 0x0EF8F10C, 0x0A070FEA, 0x04FA0310,
+0x0CFE0003, 0x0CF3060D, 0xFBFCF5FA, 0xEC0D1108, 0x09ECF70A, 0x0C0EFB08, 0x0BF4F80A, 0xEFF0FB0C,
+0x0B09F8FA, 0xFA16FF13, 0x0B081512, 0xF4F2FBF7, 0x000C0A07, 0x130C0FEE, 0xFEF908FB, 0xF6F5F912,
+0xF1100409, 0x090E1606, 0xF4F50BF3, 0xEE00F7F9, 0xFAFBF5F6, 0x07080B0A, 0xF1150BE7, 0x0DF80912,
+0x12EF0809, 0xEBFF1108, 0x0BF60DFE, 0x130DF608, 0x12EFF2F1, 0x04FB0C0B, 0x01FDFC09, 0xFAF808F9,
+0x12020B01, 0xFCED060F, 0x040DFFFF, 0x04F80AF3, 0xF700F60B, 0x08F40E08, 0x06F7F80F, 0x0DFDEF04,
+0xFDEFF916, 0xF21107EF, 0x0A1110F1, 0x03F70DF3, 0x08F50300, 0xF1F711F9, 0xF6FCFF0C, 0x0CFFF704,
+0x080CFE09, 0x0FF80D06, 0x05080C08, 0xFE020210, 0xFB11F6E9, 0x060BF2F1, 0xED0BEAF9, 0x02F30C02,
+0xF8F40DFB, 0x020D0D01, 0x0CF406F1, 0xF302F812, 0x080C0EF2, 0x06010006, 0xF0FA0908, 0x08F9F905,
+0xFB0A0508, 0x0FF0F7F4, 0xFF081210, 0xEE18F6F1, 0xF9F9E8F2, 0x060B09FD, 0x0AFEEE04, 0x09F304F8,
+0xEA05F6F8, 0x1C0108F5, 0xF205120F, 0xF40D0A04, 0x0001F30D, 0x00FF0DFA, 0x020BF7F7, 0x02F2F7F0,
+0x04F90BF1, 0x01EFEE07, 0xEBE4F807, 0x0AF90FEF, 0x0F040B11, 0x0BF91000, 0x000CF812, 0x0311F3F0,
+0xF8070218, 0xEDFFF614, 0xF00C15F1, 0x000D0F16, 0xFA0EF707, 0xEE080901, 0xFF0C09F5, 0xEEF704F1,
+0xF10C10F9, 0x060BEBF7, 0xFA0EFDF6, 0xF7F403F2, 0xF5F0F306, 0xEC081A0F, 0x020AEEF5, 0xFBF9F7FB,
+0xF60C010A, 0xEC0E0FFF, 0xF014FB10, 0x0EFD0308, 0x04F30015, 0xF4FC0CEE, 0x0CFEF3F7, 0x12F0F702,
+0xE803FB07, 0x040D06F5, 0x05FA07F1, 0x140A0BF8, 0xEFEDFF11, 0x01EFEE13, 0x0D0C0B0F, 0xE70105F0,
+0x01F70CF4, 0x0603EE12, 0xED08EDF9, 0xF2FCFA02, 0x0E0CFCF3, 0x0E04F8F9, 0xF30D17F9, 0xFEEDFB05,
+0x071BF114, 0xF309F7F4, 0x02F503F6, 0x0815F400, 0x0CF0090A, 0xE80D0F02, 0xF9FCFDF8, 0xF00FFEF5,
+0xF3F5F70B, 0xFC10F7EF, 0xF2FB0AFE, 0xEEECEC15, 0x0202F60E, 0xF310FEF9, 0x10F8F209, 0xFB0606EE,
+0x0D0B0C10, 0x1110080C, 0xFCF2F8F6, 0x030DEE07, 0x0C11F511, 0x0CF6EF08, 0x0900070C, 0x0C160E0F,
+0xEEF8FFF9, 0xF7F0EEF5, 0x0A090903, 0xF70A000E, 0xF5FF07F6, 0xF5E5FEFD, 0x08F1F80C, 0x00F2EE0D,
+0xFAED07EA, 0x07EA170B, 0xFEFFECFF, 0xED0B0211, 0x0AF4F4E6, 0xF2FAF705, 0x0807F706, 0xFBF2F8F7,
+0xF31105F7, 0xF10809FB, 0xF1FEF307, 0x0805FFFA, 0x08FC070D, 0x0A071200, 0xEEEDF107, 0xF908EDFB,
+0x09F60FF2, 0x0B0C06F8, 0x07FCF608, 0x000FF30C, 0xFF0EF3FD, 0xE40BFCF4, 0x0CF50BF4, 0x04EDE90D,
+0xFD05F3F1, 0xFAECF4FA, 0xF80C080F, 0x0A0BF70A, 0x07F012F4, 0x1109FEF3, 0xF507F9F1, 0xF513F7FD,
+0xFE0AF80F, 0x041701F1, 0xF5E7F309, 0x0A0AF70C, 0x0E00FEF1, 0x04E505EF, 0xF4EF0BFD, 0x040CF807,
+0x1201EF07, 0xF31508F1, 0xF908F309, 0x0B0EE409, 0xF7EBF9F8, 0xF1F7F406, 0xFB0206F6, 0xECFD11F2,
+0x0702EEF6, 0xF409FC04, 0xEEF80010, 0xF3EC0BF0, 0x090600F1, 0xF9F5EBF7, 0xEEFE11F8, 0x070BF0FA,
+0xFE16EEF8, 0xF108FD05, 0x15FAF3F7, 0xF60E0D0D, 0xF7FC0AF8, 0x01F40805, 0xF70AFE01, 0xFB0F0BF9,
+0x04E701F6, 0x09F517F6, 0xFBE8F5F8, 0x11FE00F6, 0xEF08F2F5, 0xFB0CFB0F, 0x0419080B, 0x0308EE11,
+0x07110907, 0xF2F5ED0F, 0x0BFAFEF6, 0xFA12F8F9, 0xE8090606, 0x0E0CEAEC, 0x06FD10F8, 0xF80505FD,
+0xF1F70912, 0xF5EF0C0B, 0xF9EF0B0B, 0x0D05F5F2, 0x0A08FF0E, 0x09F50300, 0x08F91314, 0x0AFEF60A,
+0xE5FC0504, 0xEF0A000E, 0x06FDFFF1, 0x0D11F103, 0x080CF512, 0xF9F501F2, 0xFAF60708, 0xFE140D05,
+0xF90202EF, 0xF0FD0EED, 0x06F2E903, 0xE904F80D, 0xF600F8F8, 0xF4FA09F5, 0x0803FA07, 0xFCF9F90B,
+0xF202F4F5, 0x000EFBFE, 0x0409FAFD, 0xF0EA0DF4, 0x0B0D00FF, 0x03F8FB0D, 0x0307FAF2, 0x010C0BFB,
+0x140C03FD, 0xF4FE0906, 0xF6F6F8ED, 0x0B11090D, 0xF6F90EF8, 0x09F001E8, 0xEC0600F8, 0x1109F90E,
+0xEA010BEF, 0xEF0A0C0A, 0x07F510FD, 0x08F3F500, 0x07ED01F5, 0xF313F60A, 0xF803FA0E, 0xF60B0D08,
+0xF1F0F709, 0x0DF609F4, 0xFCED020B, 0x0E0EEDE9, 0x08F907F2, 0xF1FC0C13, 0xFFFB0C06, 0xEB070AF7,
+0xF606F80A, 0xF90E1EFF, 0xF6EE0BF5, 0x05FF03F7, 0x0F0DF309, 0xFA0CF4F8, 0x1F0CF6F3, 0xF50DEE0F,
+0xF5F7FDF4, 0x0BF501EF, 0xF7FA000F, 0xECFAF0F5, 0xEA02FEF1, 0xF80FFCFC, 0x100B0600, 0xFF050501,
+0xFA150716, 0x110FFFF4, 0xEE0B04F8, 0x0E0FF112, 0x12F80BF4, 0xF6F41604, 0x07EDE6EF, 0x17EE0F0B,
+0x05F5FEF2, 0xEF0BFEF5, 0xFF07FD15, 0x01090709, 0x02EBEE0D, 0xF6F9FB0D, 0xEFF6070E, 0x090806F6,
+0x140FFEF1, 0xF6FCEEEB, 0x07EF14F2, 0xFB03040B, 0x0A05F4FC, 0x0DF6FB0D, 0x060B02F8, 0xFF0FFB0E,
+0x090709F7, 0xF7180F02, 0x0BF8F005, 0xFE0CF60D, 0x09F4ECF0, 0x0410F30A, 0xEB05F105, 0x05F90C11,
+0xFCF1F30B, 0x120B0BF3, 0x031104FC, 0x030BFC0F, 0xFB09EFFC, 0xF50CFB11, 0x0BF80504, 0xF609FCF7,
+0xFE0CFB00, 0x0F08F7FB, 0x0BFD0609, 0x0E120F15, 0x020B07F8, 0x0714FAF0, 0x0615F308, 0xF2FDF8F9,
+0xEEF606F8, 0x050906E8, 0x071106F7, 0x000C03F8, 0x04F9F90A, 0x060BF5F7, 0x0D0CF2F7, 0x06FB02F7,
+0xF7060AF5, 0x0EF1FCF4, 0xFAFAF5FE, 0x0506F917, 0xFCF40C0A, 0x03FC10E8, 0xF30700FD, 0xFCF40906,
+0xFB0B0D0B, 0x1017E4F9, 0xF20408F2, 0x02FA03F7, 0xF0000E07, 0xFB0AEDF1, 0xE6F50FEB, 0xF2FCF80B,
+0x04F50DFB, 0xF00BF706, 0xF70507FC, 0x0AF01609, 0xFF0DF20F, 0xEA150EF2, 0x080202F3, 0x00FAF9F5,
+0xEFF70E04, 0x0FF6F314, 0xF1FEFAEE, 0x08F1F3F2, 0xF6101102, 0xF8F20206, 0x120DFC03, 0x07F8F613,
+0x0CF4F50D, 0x0DFF05FB, 0x040EF409, 0xF8FB06F6, 0xF3FAF20D, 0x0DF90402, 0x05080E00, 0xF5EFEBEC,
+0xFE0B0EE7, 0x0B0E0F0E, 0x04F812F4, 0x0EEE0D10, 0x021AF7EF, 0xF70F10EC, 0xF604FDFA, 0x10E90F0B,
+0xF60CEFFE, 0x0AEBF407, 0xF60A06F0, 0xF50B1607, 0x1111FF0B, 0xF8F8EF08, 0xF704F410, 0x0B0AEBFE,
+0x14000205, 0x03FC0EF2, 0xFD17EBFF, 0x17FAFCF4, 0x0DF90CFA, 0x1004F511, 0x140302FC, 0x14FC0500,
+0xFCF6F2FE, 0x0905FA03, 0x08F3F0F4, 0x06FEF5EF, 0x09F801F8, 0xF00913F1, 0xF7F80DED, 0x040AF1FC,
+0xFC0F1008, 0x07040EF4, 0x0BF6EC0C, 0x0CF8FA0C, 0xF70F0EFF, 0xFB09FBFC, 0xF9F4ED0D, 0x02F4F80B,
+0xF5FCF2F2, 0x0208FDF1, 0xF20B0405, 0xF80AFAF3, 0xF415EDEA, 0xFDFBEB00, 0xF4F1F30F, 0xEC070F09,
+0xFA0D0AFF, 0xF7EE0C06, 0x04F4F00B, 0x08F50FF5, 0xF50EF3FC, 0x1006E7F9, 0x04F7F7FC, 0xFC070CFB,
+0x0F12EAFA, 0xF7F00706, 0xF4011505, 0xF7140B09, 0x0AF9F1F8, 0x03060DF8, 0xF2090CF8, 0xF20712F3,
+0xF903EFEE, 0x1102EC14, 0x0A09F1F6, 0xF9F001FA, 0xF8FE01FB, 0x140410F1, 0x0B0402F2, 0x0F0006F5,
+0x0805ECF9, 0xF409F10E, 0x0DE7FD01, 0xEFFD0710, 0xF20403FD, 0x0BF2F6F9, 0x0004F909, 0x0F09FFF6,
+0xF3060DF2, 0x0EEF060E, 0x0CF40705, 0xFDF7FB0C, 0xF4F203E4, 0x0E09F4F6, 0xF5FE04F9, 0x06F3FEFE,
+0xFDFB1102, 0xFD04EE0D, 0x0DFBFCF1, 0xEE14E90B, 0xFB0CEE09, 0x0C13F108, 0xF60703FD, 0x0BF4FCFA,
+0x14F2F0FB, 0xFAF9EFF7, 0xF5010801, 0xF109EEF3, 0xFF0A0514, 0x0C0604FF, 0xFB0EF704, 0xF50EFD0B,
+0xFF05F4FA, 0x07E70B0B, 0xEFFEF4FD, 0x0D0807F3, 0x05100DF6, 0xEFFA1A08, 0x020D090A, 0xFFF5F7FD,
+0x1513F10A, 0xF10BF2ED, 0x0B0F150B, 0xF10306FA, 0x09FB11EE, 0x061007F2, 0xF7F8FB14, 0xF90704EE,
+0x0AF8EAF6, 0xF7E809F9, 0x02F609E9, 0x09E802EE, 0x03F50BE8, 0x040C04F1, 0x0CF41009, 0xFB00EEFA,
+0xFC071611, 0xF9F1F203, 0x0BF0F409, 0x0214F801, 0x0A0AF504, 0x0508F5F1, 0xE916E900, 0x07F4F60A,
+0xF9F010F2, 0xF906F507, 0x0BFB0AF4, 0xF408F0F1, 0x0EFD0A06, 0x03F80AF6, 0x130CFD0C, 0xF1E9F7F8,
+0xF800F502, 0xFEFDFDF4, 0xF90B0713, 0xF506FAFD, 0x0712F9F2, 0xEAF20DF5, 0x10F40D0D, 0x06050B09,
+0xF706090E, 0x0F00ED11, 0xF90E02F4, 0xF1FEFCED, 0x0AF5E00D, 0x06F7F3F9, 0x08F81206, 0xF30EF4F5,
+0x12FF02EF, 0xF7040DF4, 0x151204F0, 0x04ED07EC, 0xF0F3FB05, 0x08F2FCF4, 0xECED11FA, 0xFC110DF8,
+0x0BF4F90A, 0xFCF9F905, 0xF0010014, 0x0A0EF9F8, 0xF4020C02, 0x10FDFA13, 0xF5000B05, 0x05EAF808,
+0xFE0F04F3, 0xFDEFF9EE, 0xF9F9090B, 0x10F20E0C, 0x060909F0, 0x060EF40F, 0x0E0705F5, 0xFB05F6F9,
+0xFA1C0512, 0x0B10FBEB, 0x16F20DF6, 0x090012F4, 0x0A13020B, 0x0EFF0C0A, 0x130DEF0C, 0x070A0B04,
+0x0BFCF004, 0x02FF0BF7, 0xF9F1F209, 0xFFF5F008, 0x05F30C07, 0x03FCEE07, 0x11FCEE08, 0xF4F31514,
+0x040B06F2, 0xE400F9F3, 0x13090B1A, 0xF2F4FFE7, 0xF1EE06F9, 0xFA0DFF0D, 0xF3ED09F6, 0xF40305F8,
+0xF8FFF507, 0xF8FF1707, 0x0AFC030C, 0xF109F3F4, 0x0406FDF0, 0xEF04F50E, 0xF5FBF3FD, 0xF30704F4,
+0xF0ECFC1C, 0xFCECF0F5, 0xF911160F, 0x020B0C0D, 0xF90C060B, 0x03FA08E7, 0x0311FF0D, 0xF405F4FA,
+0x0DEBF7F2, 0x0EF6FAF2, 0x09F3ED0E, 0xFE08EFF2, 0x0F170008, 0x0DFF0FFC, 0x0BF0ED0E, 0x0D140E07,
+0xF2F611F3, 0x11E9020B, 0xEE03F3F7, 0xFCFD00EF, 0xF518090B, 0xF11510EE, 0xF5FB07FF, 0xFEFC11F0,
+0x100DF006, 0x0AF4F300, 0xED0A1200, 0xFEF7EDF5, 0xF7040101, 0x0FF2040E, 0xF01207F7, 0x0AF3FF10,
+0xF60B0D00, 0x07F8EFED, 0x060D03FB, 0xFA08FCF6, 0xEEF6FA04, 0x0806FFF9, 0xFF0B0FF0, 0x08F3F1F8,
+0xF0F5EFF3, 0xF1EE0D01, 0xFBFEF3F6, 0xF20D060B, 0xEFFE00EB, 0x080803EE, 0x0617120A, 0x1210050C,
+0xF010FA07, 0x0908EF0D, 0x030908F2, 0x01160610, 0x120BF415, 0xF9F40FF1, 0x0FF00C02, 0x0B110D0B,
+0x0CF9F10A, 0x0C06030D, 0xF20208F5, 0x0F07FAF1, 0xF0FAF50C, 0x08F8F7F0, 0x01EF0EEC, 0x0AEFE90C,
+0xEFFCF714, 0x05F2FF13, 0xECF6F9E7, 0xFEEFFD07, 0xF6ED0F0D, 0x060FF407, 0x0803F600, 0x0105EE06,
+0xF5F70D0B, 0x02EA110F, 0x070FF8F8, 0x0B040902, 0xF6F30AF0, 0x110C1AF9, 0xF61709F7, 0x0D0FF00E,
+0x09F5EFF7, 0x0F13FAFD, 0x0C02F1F3, 0xFBF0F8F7, 0x0DF8F5EB, 0xF1FEF904, 0xFAF1030D, 0x161211F6,
+0xFA0AF50B, 0xF316F60E, 0x100708EE, 0x0AF00A00, 0xFFF4F4EE, 0x0C0BFD18, 0xFCEDF7FE, 0xFB11080F,
+0x0DF70B08, 0xF90AF309, 0xF9FD0F08, 0x10FEFA0E, 0xEE161508, 0x04FCFFFB, 0x0B1009FE, 0x0CF40D0D,
+0xF800F1FC, 0x07080602, 0x1000F8F8, 0xF8F205FD, 0x0809F9F2, 0xF80C09FF, 0xF9F5F6F8, 0x05FE0EFE,
+0xFCF6F8F1, 0x09000A0B, 0x07080DFC, 0x09FBEDF0, 0xEF0CF4FA, 0xF8F6100A, 0xF5F4F1F9, 0xFFFC0E0B,
+0xEEF6F3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEF0810FC, 0xF311FAFD, 0x0DF201EC, 0xFFF40EF3, 0x1304ED12,
+0xF4FCF304, 0x09EC1005, 0x09F80C09, 0x0C10FC0C, 0xF7F7FBFC, 0xF7F60808, 0x05F90308, 0xEC0A13F4,
+0xF20BF707, 0x04FE03F5, 0x10020FFE, 0x02F413ED, 0x050AF5FA, 0xF90E00E4, 0xFAFBF3F5, 0x0908140B,
+0xF00A0107, 0x13EFED0E, 0x04F5F8F5, 0xF104FF0F, 0xF7F0F6F5, 0x0DF7F704, 0xFF0CEB12, 0xFAF50C07,
+0x05EFF5F6, 0x12FA07F6, 0x0AFDF8F9, 0xEE050803, 0x0A04FBED, 0xF61312F2, 0xF10FF7E9, 0xFBFD0307,
+0x0AFEF5F7, 0x12FB12F3, 0xFA14F206, 0xFAF80EFB, 0xFAFDFAFC, 0xFAFC0DF6, 0xFD08F1EF, 0x0B0D0D14,
+0xF80EF90F, 0x0F0D0903, 0xF609ECF6, 0xF9EFF5F9, 0x0FFBFC06, 0x050A0A08, 0x01F30C03, 0xF9F8EE0A,
+0x0B02100A, 0xFDF3F607, 0x0EFF0D01, 0xF8EFF0FF, 0x11F511F7, 0x08F7F809, 0xEB00FE09, 0xF1FA08FF,
+0xFA0114F6, 0xF0090F10, 0xF3FBF6EF, 0x1209FE0E, 0xF7FCF309, 0x04F5F8FD, 0xF00203F2, 0xF510FB05,
+0x12F7080E, 0x08F10AFC, 0xEFF6F5FE, 0xFFFA0F08, 0x0714F612, 0xF30107F5, 0x06FD08F0, 0xFA0C08EE,
+0x05FA02F9, 0xF40108FF, 0xF90DF1F5, 0x17FC0300, 0x09F2080A, 0x10100BF0, 0x12020B10, 0xF5F80AF7,
+0xF902EBF0, 0x16E00312, 0xFEEA0600, 0xFFFAFA13, 0xF20206F9, 0x060BEF10, 0x15FAF005, 0xF603010A,
+0xF50AF110, 0xF1F903F9, 0xE508F40A, 0x0F0FF704, 0xF00B0AFC, 0xF30DFA02, 0x0202F3F9, 0xF60DEDF1,
+0x05FFFC04, 0xF402FFF8, 0xF1F9F807, 0xEF0E0508, 0xF8F6F80D, 0xF4F2FAF5, 0x031209EF, 0xF9FBF6F2,
+0x000AF6F5, 0xF6000D12, 0xF5FD0C08, 0x04FAEF00, 0x1103110B, 0xF1F50BF1, 0x08FD1104, 0xF80B0AF1,
+0x00160DF7, 0xFD05F3F8, 0x0D01F80B, 0x100502F3, 0xFC0309F6, 0xF41207F6, 0xF2100BFD, 0x040E04F7,
+0xE9080908, 0x06030EEA, 0xF40DF805, 0x09EE0608, 0x0C03F4FB, 0x080CFBF1, 0x100416F5, 0x0407F402,
+0xFDFBFDFD, 0x0BF4F806, 0xFC0B16FF, 0x08EBF3F5, 0xECF9F00B, 0xF8E9F300, 0x08F802F5, 0xF3EF10F4,
+0xFEF409F5, 0x15F7FA13, 0x070DF707, 0x0E0617F9, 0x0206F4FA, 0xF2FAFD0B, 0x10EB0F06, 0x1713EBFF,
+0x030A0BF3, 0xF7E30003, 0xECF50DEE, 0x14050506, 0x160AFC0A, 0x0EFD01F6, 0x02050BEB, 0x031615F4,
+0xF2F3FC09, 0xFA140704, 0x0AF20F07, 0xF7F9FE04, 0xF10EEC06, 0x130D0BFC, 0xF6F3ED0F, 0xF20D100D,
+0xF1F6F40C, 0x0E0BF1F2, 0x0C0FF513, 0xEBEE13FB, 0xF80EF409, 0xF608EC0A, 0xF9090DF1, 0xF602EF09,
+0x14F7F6EF, 0xF401F9F0, 0x130B10FB, 0x0FF31101, 0xEC0912ED, 0x0D03F9F8, 0xF4FAF103, 0xFEF4F10A,
+0xF60BE90A, 0xFFF0F7F1, 0xF801F2F0, 0x00150B1A, 0x09EE130F, 0x130DF7EA, 0x13FB0008, 0xF1F9F00E,
+0x0501F5F0, 0x03F60BF8, 0x090BFE05, 0xEBF8FAF3, 0xEA12F90A, 0xF4FCF4F0, 0x0DF81312, 0x01130DF8,
+0xF3060CF2, 0x00F10CF4, 0xE8F611F0, 0xF707FEF6, 0xF81013FC, 0xF0040AFD, 0xF60616FC, 0xFE1109ED,
+0xED140DED, 0x0303F812, 0xFDF4F4F8, 0x0CF60B14, 0x0DF11811, 0x0BF4FBFA, 0xF2F906F9, 0x09F3F806,
+0x030608FA, 0x0A14E20D, 0x0A08F5FA, 0xE7060DFB, 0x02FD050B, 0xF4F6FB07, 0x01F90BF7, 0x0CFA0FF3,
+0x0B04FD01, 0x0F090604, 0x060E0F0A, 0xF6F1FF06, 0xFC0C0611, 0x01030C0D, 0xF612F9F6, 0x120FF002,
+0xF0F0F9F0, 0x10FE0DFC, 0xEAFCF6E7, 0xF4F0FFFC, 0xEA080D01, 0x09F6020A, 0xF1EDF2F7, 0xF80609F8,
+0xF8F7F80F, 0xF8F7FEFB, 0x0AEE03F4, 0xF60F0406, 0x1309EF03, 0x1215F7FC, 0x0EED07ED, 0x08F30DF5,
+0x09E90D02, 0xF1FAFDF4, 0xFD0FFEF4, 0x0317F1F2, 0xF3111203, 0xF208FEFC, 0xF5FB0213, 0x15F20702,
+0x0FF918ED, 0xF3F8FF0B, 0x0F0A0A0B, 0xEE0C0A13, 0x0A0AF506, 0x1A0401F6, 0xF0F6080F, 0xEC091201,
+0xF9F90C02, 0xF10CF003, 0xF217F200, 0x0DF8FA11, 0x04F603F6, 0x03FB10FA, 0x0AF4090D, 0xF1FBF3EF,
+0x0DF00505, 0xFA0B0E0E, 0xFD030811, 0xFEEDF80A, 0xF1F1F40B, 0x050D0514, 0x0DFC0A10, 0xFF0D01EB,
+0x07F7010D, 0xF90D00F6, 0xFCEDF108, 0xFD10F30C, 0xF3F7FB06, 0xF009F8FF, 0xF808F8F5, 0xEF12F009,
+0x0C0E14F8, 0x02010E06, 0xFF00F50D, 0xF9F1F309, 0x0507EEF0, 0xF8EFFDFB, 0x05041303, 0xFC13EEF6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0xFB0E01EF, 0xFF0C0B02, 0x07090AFB, 0x0BFBF3F1, 0x0B090F0D, 0xF10409F2,
+0xF80A0E0B, 0xECF60E09, 0x0610F2F9, 0xF4F9FBEF, 0x08ED0DF9, 0xFCF9FEFE, 0x0F0C12F8, 0xF9F317F4,
+0x0BF80213, 0xFFFD1710, 0x0BF80FFB, 0xEEF6F2EE, 0x0106F506, 0xF3091206, 0x00F504F0, 0x0B0C0018,
+0xFD02FAEF, 0x06ED0308, 0xF4F60215, 0x02F80BFC, 0xF20601ED, 0x06F7F5F3, 0x0111FAFC, 0xF2ECF2F8,
+0xFB050C0D, 0x0314EA0A, 0x09F4FCF8, 0xF0F80013, 0xF6E90D0A, 0xF307F415, 0xFB04F4F8, 0xF006F3F1,
+0xFAF9F808, 0x06F9F109, 0xED0A0A0C, 0xF3F6FC03, 0x0508120A, 0x0C0DF100, 0x02FF09FF, 0x00F80D01,
+0x04E50410, 0xF616130C, 0x0300F4EC, 0x090EF506, 0xFA0E0C14, 0x0EF10111, 0xF2030F09, 0x03F3030E,
+0x09EA0509, 0xFDFEF9FB, 0x06F4F702, 0x0C0D0BF3, 0xFFFBF906, 0xF7FBF512, 0x03110AF8, 0x0AF7F70D,
+0x17F60108, 0xF811FA05, 0xEE040700, 0x03FEEF01, 0xF706EC0B, 0x060C0AFA, 0xEC0EF910, 0x0804F207,
+0x09E902F7, 0xF7FDF610, 0x0C050C0B, 0xF8E7F609, 0xFB170A13, 0xF0080404, 0xE808F413, 0xF1F4EB07,
+0xEBFC01F7, 0x0B040AE8, 0x00F1020E, 0xF0F207EC, 0x0EFFF211, 0xF3F815F4, 0xF9020B0B, 0x0EF71201,
+0x0706FC0C, 0x06FDF6FA, 0xFBF7F80A, 0x08090EFD, 0x14FD05FF, 0xF403FE0A, 0xF5F8EF03, 0xFB0AF8F7,
+0x0F00F409, 0x0AEF0B03, 0x0FFB0210, 0x11070710, 0xF1080B0B, 0xF20E08E8, 0xF00CF5EB, 0xF0F30C0E,
+0xFCF0080D, 0x0900EE07, 0xFA01FCFE, 0xE712E70B, 0xF004FEF9, 0x0CF5090D, 0xF60EF606, 0xF8F4FAF8,
+0xED061507, 0xEF110506, 0xF90FF20C, 0xF911F813, 0xFC12F3EF, 0xF7F9F1FC, 0x0E07EAE9, 0x0EF8F1F8,
+0xF6070FEA, 0xF0FA0310, 0xF8FE1417, 0xF8F306F9, 0xFBFCF50E, 0xEC0D11F3, 0x0900F70A, 0xF80EFBF3,
+0x0B08F8F6, 0xEFF00F0C, 0xF709F8FA, 0x0E16EB13, 0x0BF415FE, 0xF4F20F0B, 0xEC0C0AF3, 0x13F8FB02,
+0x12F908FB, 0x0A090D12, 0xF110F0F5, 0xF40E021B, 0x0809F7F3, 0xEE000B0D, 0x0E0FF5F6, 0xF3F40BF6,
+0x05150BE7, 0x0DF809FE, 0x12030809, 0xFF13FC08, 0x0BF6F912, 0x13F90AF4, 0xFE03F2F1, 0x04FB0CF7,
+0x01FDE8F5, 0x0EF8F40D, 0xFE02F7ED, 0xE7EDF2FB, 0x04F9FF13, 0xF0F80A07, 0xF700F6F7, 0xF4080EF4,
+0xF2F7F80F, 0x0DFDEFF0, 0x11EFF902, 0xF2FC0703, 0x0AFD10F1, 0x17F70D07, 0x08F5EFEB, 0xF10B11F9,
+0xF610FFF8, 0x0C130B18, 0x080CFEF5, 0xFBF8F906, 0xF1080C08, 0xEAEEEE10, 0x0F11F6FD, 0x06F706F1,
+0xED0BEA0D, 0xEEF30C02, 0xF8F40D0F, 0x020D0DEC, 0x0CF40605, 0x07020C12, 0xF40C0EF2, 0x060115F2,
+0xF0E6F508, 0xF40DF9F0, 0x0F0A05F4, 0x0FF00B08, 0xEB08FEFC, 0xEE030AF1, 0x0DF9E806, 0xF2F7F5FD,
+0x0A12EEF0, 0x09F3EFF8, 0xFE05F6F8, 0x1CEDF4F5, 0x060512FB, 0x08F90AF0, 0x000107F9, 0x14FFF9FA,
+0x16F70B0B, 0xEEF2F704, 0x04F90BF1, 0x150302F3, 0xEBF8F8F3, 0xF6F90FEF, 0xFBF0F7FD, 0xF70D1000,
+0xECF70C12, 0x03FDF3F0, 0xE4F31604, 0x02FFF600, 0xF00C0105, 0xEC0D0F02, 0xFAFAF707, 0x0208F501,
+0xFFF809F5, 0xEEF70405, 0x050CFCF9, 0xF20BEBF7, 0xFA0E11F6, 0xF7F403F2, 0xF5F0F306, 0x00081A0F,
+0x02F6EE09, 0x0F0D0B0F, 0x0AF7EDF6, 0xECFA0FEB, 0xF000FBFC, 0xF91103F4, 0xF0F30001, 0x08FCF8EE,
+0x0CFEF30B, 0xFE040B02, 0xFC030FF3, 0x04F9F209, 0xF10E0705, 0x14F60B0C, 0x03ED1311, 0xED03EE13,
+0xF9F8F70F, 0xFB010504, 0xEDF70C08, 0x061802FE, 0xED0801F9, 0x06FCFA16, 0x0EF8FCF3, 0x0EF00C0E,
+0xF3F9170D, 0xFE010F05, 0xF31B0500, 0x07F50BF4, 0xEE09030A, 0xF401F400, 0x0C04090A, 0xFCF90F02,
+0x0D10FD0C, 0xF00FEA09, 0xF3F50BF7, 0xFCFCF7EF, 0x06FB0A12, 0x0200EC01, 0x02020A0E, 0xF3FCFE0D,
+0xFC0CF209, 0xFB06F2EE, 0xF90B0C10, 0xFDFCF40C, 0xFC06F80B, 0xEFF902F3, 0x0C110911, 0xF80AEFF3,
+0x0900F30C, 0xF8160E0F, 0xEE0D130D, 0x0BF00209, 0x0AF509EF, 0xF7F614FA, 0xF513070A, 0x09E512FD,
+0xF3050D0C, 0x0006020D, 0xFAED07FE, 0x07FE170B, 0x121300FF, 0x02F602FD, 0x0AF408FA, 0x06FAF7F1,
+0x0807F71A, 0xFBF20C0B, 0xF3FD05F7, 0x06F4090F, 0xF1FEF307, 0x0805EBFA, 0x0810070D, 0xF6F31214,
+0x02ED0607, 0x0D08010F, 0x09F60FF2, 0x0BF8F20C, 0x1BFCF6F4, 0xECFB070C, 0x13FAF3FD, 0xF8F7FCF4,
+0x0C09F7F4, 0xF001E9F9, 0x11F1F305, 0xFAEC08FA, 0xF8F8F40F, 0xF6F70B0A, 0x07F012F4, 0xFDF5FEF3,
+0x09070EF1, 0x09FFF7E9, 0xEAF60C0F, 0x04030106, 0xF5E70709, 0x0AF6F70C, 0xFA14FEF1, 0xF0E51903,
+0xF4EF0B11, 0xF0F80CF3, 0x12ED0307, 0xF301F405, 0xF9F4F3F5, 0x0B0EF809, 0xF7EBF9F8, 0xF10BF406,
+0xFBEEF2F6, 0xEC1111F2, 0x0716EEF6, 0x080910F0, 0xEE0D0010, 0x07ECF7F0, 0x09060005, 0x0DF5EB0B,
+0x0212110C, 0xF3F704FA, 0xEA02020C, 0x050811F1, 0x01FA07F7, 0xF60E0D0D, 0xF711F60C, 0x0108F4F1,
+0xF7F6FE01, 0x0F0FF7F9, 0xEFE7010A, 0x090902F6, 0x0FE809F8, 0xFDFE00F6, 0xEF0806F5, 0x10F80F0F,
+0x0419F40B, 0xEF08EEFD, 0x0711F507, 0xF20901FB, 0x0BFA130A, 0xFA120CF9, 0xE809F2F2, 0xFAF8FE00,
+0xF2FDFCF8, 0xF805F1FD, 0xF1F70912, 0x0903F80B, 0xF9EFF70B, 0x0D05F5F2, 0x0A08FF0E, 0x09F5EE00,
+0x08F91314, 0x0AFEF60A, 0xE51005F0, 0x041EECFA, 0x06FDFF05, 0x0D11F1EF, 0xF4F80912, 0x0D090106,
+0xFAF6F308, 0xFE14F8F1, 0x0D02EE03, 0xF0FDFAED, 0xF2F2E903, 0xE9040C0D, 0x0A00F8F8, 0xF4FA0909,
+0xF4EFFA1B, 0xFC0D0D0B, 0xF2EE08F5, 0x000E0F12, 0xF0F50F11, 0x04FEF9F4, 0x0BF914EB, 0x170CFBF9,
+0x03F30E06, 0x01F8F70F, 0x14F8EFFD, 0xF412F5F2, 0x0AF60C01, 0xF711090D, 0xF60DF90C, 0x09F0ECE8,
+0xEC06140C, 0xFD090DFA, 0xEA01F7EF, 0x030AF8F6, 0xF3F5FCFD, 0xF4F3F500, 0xF3EDECF5, 0xF3130AF6,
+0xF8EFFA0E, 0x0A0B0DF4, 0xF1F0F7F5, 0x0D0A09F4, 0x10EDEEF7, 0x0E0EEDFE, 0xF4F9F306, 0x05FCF8FF,
+0x13FBF7F2, 0xFF07F6F7, 0x0AF2F8F6, 0x0DFA1EFF, 0xF6EE0B09, 0xF113030B, 0xFAF9F3F5, 0xFA0C080C,
+0x0BF8F607, 0x09F902FB, 0xF50BFD08, 0xF7F515EF, 0x0BFA00FB, 0x01FAF009, 0xEA02FE05, 0x0CFBFC10,
+0xFBF7F214, 0x1305F1ED, 0xFA01F216, 0xFDFBFFF4, 0xEE0B040C, 0xFAFB05FD, 0xFEF8F7F4, 0xF60802EF,
+0xF301E603, 0x03EEFAF7, 0xF109EAF2, 0xEF0BFEF5, 0xFFF31115, 0xED09F309, 0x02FFEE0D, 0xF60D0FF9,
+0x030A07FA, 0xF5F4060A, 0x140FFEF1, 0xF6FCEEFF, 0x07030006, 0xFBEF04F7, 0x0AF009FC, 0xF90A0FF9,
+0xF2F702F8, 0xFFFBFB0E, 0x0907090B, 0x0B180F02, 0x0B0C0405, 0x12F80AF9, 0x09F400F0, 0xF010070A,
+0xEBF105F1, 0x05F90C11, 0xE805F30B, 0x12F70BF3, 0xEF11EFFC, 0xEFF7FC0F, 0xE709EF10, 0xF50CFBFD,
+0xF7F805F0, 0xF609FCF7, 0xEAF80F00, 0xFBF40B10, 0xF71106F5, 0xFA12FB01, 0x020BF30C, 0x0714FA04,
+0x06010708, 0xF2110D0D, 0xEEF6F2F8, 0xF009F1E8, 0x07FD06F7, 0x14F8EF0C, 0xF00DF9F6, 0xF20BF50B,
+0xF90C06F7, 0x06FB02F7, 0xF7F20A09, 0xFA051008, 0x0EFA0913, 0x05060D03, 0xFCF40CF6, 0x03E8FCFC,
+0xF3F31411, 0xFCF40906, 0xFB0BF9F7, 0xFC02F80D, 0xF20408F2, 0xEE0EEF0B, 0xF0000EF3, 0xFBF6EDF1,
+0xFAF50FEB, 0x06FC0C0B, 0xF009F80F, 0xF0F7F706, 0xF70507FC, 0x0AF00209, 0xFF0DF20F, 0xEA15FA06,
+0x0816EDF3, 0x000EF9F5, 0xEFF7FA04, 0x0FF60814, 0xF1FEFA02, 0x0805F306, 0xF610FDEE, 0xF8061606,
+0xFE0DFCEF, 0x07F8F613, 0x0C0809F9, 0x0DEBF0FB, 0xF00EF4F4, 0xF8E7F20A, 0xF3FAF20D, 0xF90D04EE,
+0xF1F40E00, 0x09EFFFEC, 0xFE0B0EE7, 0xF7FA0F0E, 0xF00CFEF4, 0xFAEEF9FC, 0x161AF703, 0xF70F10EC,
+0xF6F011FA, 0x10FDFB0B, 0xF60C03FE, 0x0AFF08F3, 0xF6F606F0, 0xF5F716F3, 0xFDFDEBF7, 0x0CF8EFF4,
+0xE3EF0910, 0xF7F6FF12, 0x001402F1, 0x03100EF2, 0x1117EBFF, 0x17FA1008, 0x0DF9F80E, 0xFCF0F511,
+0x1403EEFC, 0x0010F100, 0x110A0612, 0xF505FAEF, 0xF4F304F4, 0x061209EF, 0x090C150C, 0x04F41306,
+0x0B0C0DED, 0xF0F6F110, 0xFC0F1008, 0xF3EF0E08, 0x0B0AECF8, 0x0CF8FA0C, 0xF7FB0EFF, 0x0FF50FFC,
+0x0DF4EDF8, 0x02080C0B, 0xF510F2F2, 0x0208FDF1, 0x060B04F1, 0xF8F6E607, 0xF415EDFF, 0xE8FBEBEC,
+0x0805F30F, 0x00F30F09, 0xFA0DF6EB, 0x0BEEF806, 0x0408F00B, 0xF4F5FB09, 0x090EF310, 0x1006FBF9,
+0xF0F7F710, 0xFC070C0F, 0xFB12EAFA, 0x0BF007F1, 0x080100F1, 0xF700F709, 0x0A0D05F8, 0xEFF20D0C,
+0xF209F8F8, 0xF207FDF3, 0x0DEFEFEE, 0xFD020114, 0x0AF5050A, 0x0D0415FA, 0x0C12ED0F, 0x14F01005,
+0xF7F0EE06, 0x0F14F209, 0x080500F9, 0x08F5050E, 0x0DE7E901, 0x03FDF3FC, 0xF20403FD, 0xF7F2F60D,
+0xECF00D09, 0xFB09FF0A, 0xF306F9F2, 0x0E03F20E, 0x0C09F305, 0x11F710F8, 0xF4F217E4, 0x0E09090A,
+0x0A12F0F9, 0x06F312FE, 0xFDFBFDEE, 0xE9F0020D, 0x0DFB1005, 0x0200E90B, 0x0F0C02F5, 0xF8FF05F4,
+0x0AF303FD, 0x0BF4100E, 0x14F2040F, 0x0EF9EF0B, 0x0AED0801, 0x05F5EE08, 0xFF0A0514, 0xF8F2F0FF,
+0x0FFAF7F0, 0xE10E12F6, 0x13F1F4FA, 0xF3FC0B0B, 0xEFFEF4FD, 0xF9080708, 0x05FCF9F6, 0x040E06F4,
+0x020DF5F6, 0x13F50B11, 0x1513F1F6, 0x05F707ED, 0xF7FB01F7, 0xF1EF06FA, 0x09FB1102, 0x06FC0706,
+0xF7F80F14, 0x0EF3F002, 0x0AF8FE0A, 0x0BE8F5F9, 0xEEF609E9, 0x09E8EE02, 0x03090BFC, 0xF0F8F0F1,
+0xF8081009, 0x0F0002FA, 0xFCF202FD, 0x0DF106EF, 0xF70408F5, 0x02140C15, 0xF6F6F5EF, 0xF1080905,
+0xE902FDEC, 0xF3F4F6F6, 0xF904FCF2, 0xF906F5F3, 0xF7FB0A08, 0x08F4F0F1, 0x0EFDF6F1, 0x03F8F6F6,
+0xFF0C110C, 0xF1FDF7F8, 0xF814F502, 0x12FD1108, 0x0DF7F313, 0xF506FA11, 0x07FEF9F2, 0xEAF20D09,
+0xFCF40D0D, 0x06F1F709, 0xF7F21DFA, 0xFB00ED11, 0x0DFA0208, 0xF1FE1101, 0x0AF5F4F9, 0x060BF3F9,
+0x080CFD06, 0xF30EF409, 0x12EB02EF, 0x0BEF0D09, 0x1512F0F0, 0x18010700, 0x05070F05, 0xF306FC08,
+0x0001FD0E, 0x10FD0DF8, 0xF708F90A, 0x100D0D05, 0x04011414, 0x0AF90D0C, 0xF402F8EE, 0xFC11FAFF,
+0xF500F605, 0xF0EAF8F4, 0x120F0407, 0x1103F9EE, 0xF9F9F5F7, 0x10060EF8, 0x0609F504, 0xF20E080F,
+0x0EF3F109, 0xFB05F60E, 0x0E1C05FD, 0xF710FBEB, 0x16F2F90B, 0xF500FEF4, 0x0A13EEF7, 0x0EFF0CF6,
+0xFFF903F8, 0xF30A0BF0, 0xF7FCF004, 0x1613F70B, 0xF90506F5, 0xEB09F008, 0x05F30CF3, 0x0310EEF3,
+0xFD1002F4, 0x09070114, 0x040B0606, 0xE400F907, 0x13F40B1A, 0x06F4EBE7, 0xF1EE06F9, 0xFAF9130D,
+0xF3ED090A, 0x08EF05F8, 0xF814F507, 0xF8131707, 0x1EFCEF0C, 0xF1090708, 0x04F211F0, 0xEFF0090E,
+0x09FBF3FD, 0xF3F204F4, 0xF000FC1C, 0xFC00F009, 0xF9FD160F, 0x16F7F80D, 0x0DF8060B, 0x03FAF4FB,
+0x03FDFF0D, 0xF4F1F40E, 0xF9EBF7F2, 0x0EF6FA06, 0x09F3EDFA, 0xFEF4EFF2, 0x0F0300F4, 0x0DEBFBFC,
+0x1FF0010E, 0xF9140E07, 0xF2F6FD07, 0x11E9020B, 0xEE17070B, 0x10FD0003, 0x0904F5F7, 0x0515FCEE,
+0x090F07FF, 0x12FC1104, 0x10F9F0F1, 0x0A080700, 0x010A1200, 0x120B01F5, 0xF7F0ED01, 0xFB06040E,
+0xF0FEF30B, 0x0A0713FC, 0xF6F7F9EC, 0x07F803ED, 0xF2F9EF0F, 0xFAF4100A, 0x020AFA04, 0x0806130D,
+0xFF0B0F04, 0x080705F8, 0x04F503F3, 0x05EEF9ED, 0xFBFEF30A, 0xF2F9F20B, 0x03FEECEB, 0x08F40302,
+0x0617FE0A, 0xFE10050C, 0x0410FAF3, 0xF508EFF9, 0x030908F2, 0x010206FC, 0xFDF7F415, 0xF9080F05,
+0xFBF00CEE, 0x0BFD0D0B, 0xF7F9F10A, 0xF80603F9, 0xF202F4F5, 0x0F07FA05, 0x04FA09F8, 0x08F80B04,
+0xED030E00, 0x0A04FDF8, 0xEFFC0B14, 0x05F2FFFE, 0xECF60EFB, 0xFE04FD07, 0x0AEDFB0D, 0xF20FF407,
+0xF4030A00, 0x15F1EEF2, 0xF50B0D0B, 0x02FE11FB, 0xF3FBF8F8, 0xF7F0F516, 0xF6070A04, 0xFD0C1A0D,
+0xF603F50B, 0x0D0F04FA, 0xF5F5EFF7, 0xFB130FE9, 0x0C0205F3, 0xFB050CF7, 0xF9F809FF, 0xF1120DF0,
+0x0E0503F8, 0x16FEFDF6, 0xFA0AF5F7, 0xF302F6F9, 0xFC07F4EE, 0x0A040A00, 0xFFF409EE, 0xF8F7FD18,
+0xFC01F7EA, 0x0F11F40F, 0x0DF7F708, 0x0DF60809, 0x0DFD0F08, 0x1012FA0E, 0x021615F4, 0x04FCEBFB,
+0xF7FC09FE, 0x0C080DF9, 0xF8EB05FC, 0x0708F2EE, 0xFC14F80C, 0x0C06F111, 0x0809F9F2, 0x0CF809FF,
+0x0DF50AF8, 0x05EA0E12, 0xFCF6F805, 0xF5EC0A0B, 0xF2080D10, 0x09FBED04, 0xEFF7F40E, 0xF8F610F6,
+0x09F4F1F9, 0xFFFC0E0B, 0x020AF3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEFF410FC, 0x07FD0EFD, 0x0D060100,
+0x13F4FAF3, 0xFFF001FE, 0x08FC07F0, 0x0900FC05, 0xF5F8F709, 0x0CFC100C, 0xF7F7FBFC, 0xF7F608F4,
+0x05F90308, 0xECF6FF08, 0xF2F70B07, 0x04FE03F5, 0xFC02FBFE, 0x02F41301, 0xF1F6F50E, 0xF9FA00E4,
+0x0EFB0709, 0xF50800F7, 0x040AEC07, 0x130301FA, 0x0409F809, 0xF104EA0F, 0xF7F00A09, 0xF80BF704,
+0x13F800FE, 0xFAF50CF3, 0xF103090A, 0x12FAF30A, 0xF611F8F9, 0x02F1F403, 0x0A040FED, 0x0AFFFEF2,
+0x05FBF7FD, 0x0FE903F3, 0xF6EA090B, 0x120FFE07, 0xFA1406F2, 0x0EF80EFB, 0x0EFDFAFC, 0x0EFC0D0A,
+0x120805EF, 0xF70DF900, 0x0C0EE5FB, 0x0F0DF503, 0xF609000A, 0x0D03F5F9, 0x0FFB1006, 0x05F60A08,
+0xED07F8EF, 0xF90CEE0A, 0x0B16100A, 0xFD07F607, 0x0EFF0D01, 0x0CEF04EB, 0x11F5FD0B, 0x080B0CF5,
+0xFF14FEF5, 0xF1FAF413, 0xFA0100F6, 0xF0090FFC, 0xF3FB0AEF, 0xFE09FE0E, 0xF710F3F5, 0x04090C11,
+0x04EEEFF2, 0x09FC0FF1, 0xFE0BF4F9, 0x08F10AFC, 0x030AF5FE, 0x13FA0FF4, 0x07000AFE, 0x071507F5,
+0x06FD08F0, 0x0F0C08EE, 0x190E020D, 0x08EDF4EB, 0x0D0DF109, 0x0210EF00, 0xF506080A, 0x1010F7F0,
+0xFE02F7FB, 0x09F8F6F7, 0xF902FF04, 0x16E003FE, 0x12EA1A00, 0x130E0FFF, 0x0702F2F9, 0xF10BEFFC,
+0x010E04F1, 0xF6EF15F6, 0xF50A0510, 0x050DEF0D, 0xF908F4F6, 0x0F0F0BF0, 0x04F7F6FC, 0x07F9FAEE,
+0x02EE07F9, 0xF6F90105, 0xF1FFFC04, 0x0802EB0C, 0xF10E0CF3, 0x030E0508, 0x0CF60CF9, 0x08F20EF5,
+0xEFFE09EF, 0xF9FB0A06, 0x14F6F6F5, 0xF6140DFE, 0xF511F8F4, 0xF0FAEF00, 0x1103FC0B, 0xF1090B05,
+0xF4FD11F0, 0xF80BF6F1, 0x14160D0B, 0x1105070C, 0x0DEDF80B, 0x1005EE07, 0xFCEFF5E2, 0x0812F3F6,
+0xF2100BFD, 0x04FAF00B, 0xFD08F508, 0x06030EEA, 0xF4F90C05, 0xF5EE0608, 0x0CEEF40F, 0xF4F8FB06,
+0xFCF01609, 0x0407F402, 0xFDFBFDFD, 0x0BF4F806, 0xFCF701EB, 0x08EB0709, 0xECF9040B, 0xF8E9F300,
+0x1C0CEEF5, 0x0703FC08, 0xFEF40909, 0x150B0EFF, 0xF30D0B07, 0xFAF203F9, 0x02F209FA, 0x060EFDF7,
+0xFCEB0FF2, 0x0313FF13, 0x030A0B07, 0x0BF70003, 0x00090D02, 0x1405F106, 0x020AFCF6, 0xFAFD01F6,
+0xEE05F7EB, 0x030201F4, 0x06071009, 0x0E000704, 0x0A060F07, 0x0C0DFE04, 0xF1FA001A, 0xFFF90B10,
+0xF607ED0F, 0x06F9100D, 0x05F6F40C, 0x0E0BF106, 0xF8FB09FF, 0xEBEE13FB, 0x0C0EF4F5, 0xF608EC0A,
+0xF9F5F905, 0x0AEE03F5, 0x000B0A03, 0x0815F904, 0x13F7100F, 0xFB0711ED, 0xECF5FD01, 0x0D03F90C,
+0xF4FA05EF, 0x1209050A, 0xF60BFD0A, 0xFF04F706, 0xF8ED06F0, 0x0001F71A, 0x09EEFFFA, 0xFF0D0BEA,
+0x130F00F4, 0xF1F904FA, 0x05EDF504, 0x030AF7F8, 0x09F712F1, 0xFF0C0E07, 0xFE12F9F6, 0x08FC08F0,
+0xF9F813FE, 0x01FF0D0C, 0xF3F10C06, 0xEC05F7F4, 0xFCF6FD04, 0x0B07FEF6, 0xF8FC13E8, 0xF004F611,
+0xF6060210, 0x12FDF5ED, 0x0100F9ED, 0xEE03F8FE, 0x11F4F40C, 0x0C0BF614, 0x0D050411, 0x0B080FFA,
+0xF2F906F9, 0xF5F3F8F2, 0xEF06080E, 0xF614F60D, 0x0A080A0E, 0xFBF2F9FB, 0x1612F1F7, 0xF4F60FF3,
+0x010D0B0B, 0x0C0EFB07, 0x0B04FDED, 0xFAF50604, 0xF2FAFB0A, 0x0AF1FFF2, 0x100C0611, 0x01EF0CF9,
+0x0B12F90A, 0x12FBF002, 0x04040D05, 0x10FEF910, 0xEAFC0AE7, 0xF404FFFC, 0xEA08F9ED, 0xF5F616F6,
+0xF10106F7, 0xF806F5F8, 0xF8F70CFA, 0x0CF7FEFB, 0x0AEEEF08, 0x0AFBF0F2, 0x13F5EFEF, 0xFD010BFC,
+0xFA01F3ED, 0x08F30D09, 0x09FEF902, 0x050FFDF4, 0x11FAFE08, 0x1703F1F2, 0xF3FCFE03, 0x06F4EA10,
+0x090FEE13, 0x00F20702, 0xFBF90401, 0x070CEBF7, 0x0FF6F50B, 0xEEF8F6FF, 0x0A0AF506, 0x06F0010A,
+0xF0F6F4FB, 0x00F51201, 0x0DF90C02, 0xF1F8F0EF, 0x061706EC, 0x0DF80EFD, 0xF0F6030A, 0x03FB100E,
+0xF608F50D, 0xF10F08EF, 0xF9F0F105, 0x0EF7FA0E, 0xFD030811, 0x12ED0CF6, 0x050508F7, 0x05F90514,
+0x0D100A10, 0xEAF901FF, 0x070B010D, 0xF90D140A, 0xFC02F1F4, 0xE9FCF3F8, 0x07F70FF2, 0x0409F8FF,
+0x0C080CF5, 0x03FEF0F5, 0xF80E000C, 0x0201FAF2, 0x1314090D, 0xF90507F5, 0x05F302F0, 0x0CEFFDFB,
+0xF11813EF, 0x10FFEEF6, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+
+output0 =
+0x8EC35F65, 0xF1011E4E, 0x01283C76, 0x46C59B44, 0x66BD1E7E, 0x71CC3D13, 0xF54F7B59, 0xC2E51E78,
+0x878ACD1F, 0x0BB83AD9, 0xD6EB81F6, 0xDA98D960, 0x9583FF24, 0x84E13C2E, 0xB80A4BD9, 0x7546DA7D,
+0x61301F84, 0x4E8E7BCA, 0x0F9A1992, 0x84DE01C3, 0xFB1B38F1, 0x44764A25, 0x9525C193, 0xAD6AFC2C,
+0xEAC9CBE7, 0x822626C3, 0x6764F1E2, 0xB7080FC1, 0x92F0BF18, 0x2BE2A423, 0x6652CA22, 0x7E2B8B7D,
+0xDADC0042, 0x1684A5B0, 0x6AF80D1E, 0xDE4B11F8, 0x4C027AA7, 0x9B499047, 0xDF71DF9C, 0xE66B5211,
+0x0976A858, 0x97CCDFA6, 0xF921AC4D, 0x684DB77D, 0x2046F400, 0x66BF05FF, 0xCFE771B2, 0x7D285899,
+0xA6DD74A8, 0xD5AC14DF, 0xB4EE744D, 0x9BF75449, 0xBCCF7BE5, 0xD9B3E1C5, 0x04D5FEEA, 0xA91CED17,
+0x260A3E33, 0xB14FA433, 0xC7FB659B, 0xD847CBDD, 0xD4BAF083, 0x51A5AEB1, 0x39A13C7A, 0xC54DBA51,
+0x81DD7FFE, 0xE2A3941C, 0x386750AD, 0x85C6A1CF, 0x52E46581, 0x2DC58468, 0x4F8C204C, 0xCA6C89B8,
+0xD338F49E, 0xB71D9A1C, 0xAE5992A5, 0x461FFEB6, 0x0F724968, 0xD2D9A290, 0x4C0791D6, 0x8AA45E2A,
+0xBCE9EEF4, 0x769D6618, 0x71D659F8, 0xE9DC6A13, 0x99E831C3, 0x8AB8CFD6, 0x489E23C5, 0xBEFC2792,
+0x9E54E534, 0x54101DEF, 0x1F83D8D2, 0x69A8094D, 0x2DA8AAEB, 0x564C6C07, 0x4F2AADB5, 0x20CB1D7F,
+0x2D6E9D54, 0xB97A8BC9, 0x36365C67, 0x8D84329F, 0x4000A81C, 0x6326766B, 0xB9B50B8D, 0xF9D51D73,
+0x4D1A117F, 0x70486DEE, 0xBB19FFB6, 0x96929F46, 0x8E7C8D1C, 0x04B8D1F3, 0x204B8156, 0xA67E9C62,
+0x4534F672, 0x94B8C832, 0x38E7CFE4, 0x71F48255, 0x82181625, 0xF8C9EB50, 0xF3D38EF0, 0xB4DE79FB,
+0xF32452
+
+harq_output0 =
+0x14EFEB09, 0x16171D0B, 0xF210F3E8, 0xE4180EE6, 0xE40811F1, 0x0F1118EB, 0xE714EDF1, 0x09EA14EB,
+0x1AF71812, 0x121DE902, 0xE7DCF9EB, 0xF7E8EEE1, 0x19111BF4, 0xF2E92615, 0xE81704F7, 0xFE20FE1E,
+0x14EB181A, 0x0DFAEDDC, 0xE4EA0E0B, 0x1915F4EB, 0x1DE9DCE0, 0xE71C0722, 0x110714E0, 0x0B0FE719,
+0xDC0FF5F7, 0xEC1716EF, 0x0917DC11, 0xE1EE19EE, 0x101A1120, 0x0FE415F5, 0xF2E911E8, 0x0D1D0EED,
+0xDFECF70C, 0xEB14F7FA, 0xED0EEBEB, 0x15F11702, 0x110FE718, 0x0B06ED09, 0xECFAEB10, 0xE41EE916,
+0x031410F0, 0x0C13EDFF, 0xE4191816, 0xF8F1E0E4, 0xDEE41609, 0x1A17160C, 0x11DDE11B, 0xE8251517,
+0x0E1AEAE1, 0x17EB19E6, 0xF4F4EC27, 0xEBE30E00, 0x170B1BEA, 0x1ADBEBE2, 0x1005F11A, 0x0DF2EEED,
+0xED1318F9, 0x1CFB0314, 0xDD13150C, 0xE51E0CF5, 0xDF1118EB, 0x19ED0CEA, 0x11132407, 0xEAF9F2E8,
+0x060DEBE6, 0xDFF50E1B, 0x170B071C, 0xE7102017, 0xEB1BEBF7, 0x06F1ECE5, 0x111304EA, 0x0B1FEF1A,
+0xE7E8F2FB, 0xF305121D, 0xEC011815, 0x0C0D0BE2, 0xDE181915, 0xE9E615F9, 0xE9F4E9E6, 0xEAE814E7,
+0x0CE51F1B, 0xE906E310, 0x1221E61A, 0x13DF1BEA, 0xECE8E918, 0x1BF0EE17, 0x0C0EE20C, 0x0F14E10E,
+0xF9161ADC, 0xEBEF1D1F, 0x1809EFDF, 0xEE051F1A, 0x1FFE0E06, 0xF219F40B, 0xF01819EF, 0xF100F222,
+0x19F31922, 0x1B06E7EF, 0xE7EAE9E7, 0x0F19F6DB, 0x15F5E00A, 0x10EB0FEE, 0x07DF11F4, 0xEC1ED9F1,
+0x22EDD6EF, 0xD6FAE111, 0x151BE9E4, 0xFBEF19ED, 0x171BEEEC, 0xF40C17F5, 0x15E1EEEF, 0x17F81EF2,
+0x1E19E4F6, 0xEEEE1A16, 0x19F10B0B, 0x11F7E613, 0x17EB1309, 0x12ECF012, 0x15131CD7, 0x08F00820,
+0x1CF9FCF7, 0x13E21415, 0xF2F2E1F2, 0xE4191F14, 0x14E7F11D, 0x1B17F618, 0x18E8E517, 0xDDE4F317,
+0x1419EAEC, 0xE81EFC18, 0x11132D17, 0xECE8E1EA, 0x08210B06, 0x101B0EDA, 0xF2EA0FF6, 0xE2E8F41B,
+0xEB1D0E08, 0x141022F8, 0xE4E90FEA, 0xE2F5F2EE, 0xEFF5E8F2, 0x170E0617, 0xE12016E3, 0x1DEB1521,
+0x21ED0617, 0xE2EF180E, 0x13F722EF, 0x1E21ED11, 0x1CE8E3E9, 0x07ED1917, 0x07F20815, 0xECEB1AEC,
+0x1FF10E03, 0x0DEF0723, 0x0E16F0F5, 0x11E81FED, 0xEF12E31A, 0x1CE41E0D, 0x11E7E615, 0x1CFDE10D,
+0xF1E0E523, 0xE61AF8E8, 0x170C0DDE, 0xF2F414EF, 0x0EE50611, 0xE8E91CF2, 0xE2ECF815, 0x1BF4E2FA,
+0x0F12F70F, 0x1DE71314, 0x1111130D, 0x0F0D121C, 0xEF17F9CD, 0x1414E6E7, 0xE21DDAF2, 0x08E61E00,
+0xF5EF1EE9, 0xFF110F0E, 0x19EF16E2, 0xE116E11D, 0x171810E7, 0x1214F10E, 0xE6010C19, 0x13EDF513,
+0xFB100917, 0x1DE9E6EB, 0x09091A11, 0xDF21E4E4, 0xF8EFD8F2, 0x12110DE8, 0x19F8E508, 0xFEED16EE,
+0xE9F6EAF2, 0x23FD13EC, 0xE1031A20, 0xED15110C, 0x0511EC17, 0xEFF927EE, 0x0418ECED, 0x15E7EEED,
+0x19F810E7, 0xF2E6E008, 0xE2DFF912, 0x0FE815E9, 0x18131C13, 0x11F51706, 0xF718F326, 0x1118E3DE,
+0x0213EC22, 0xE4E7EB21, 0xDE161EDA, 0x09091118, 0xFD17EE03, 0xDE140DF2, 0xF71419E9, 0xE9E306EB,
+0xD91326F6, 0x1310DDE6, 0xF112F1EB, 0xE5F4FBF3, 0xEBE6E80A, 0xDD102314, 0xEB20D7E1, 0xEEEDEDF1,
+0xEF101110, 0xE5141806, 0xE723F118, 0x16F1070D, 0x12F0F61B, 0xE3F416E4, 0x1FF6F0EF, 0x17D9EE0E,
+0xE017F009, 0x161E17E9, 0x12F10EF0, 0x1D1019F5, 0xE1EBF817, 0xFFE1E71C, 0x1D14181C, 0xD90610E5,
+0x0CE929EE, 0x15EFDB23, 0xE616DBED, 0xE3E6F6EF, 0x1816DCEC, 0x140FEBF2, 0xE71929EB, 0xF1E7EF0E,
+0x191AF317, 0xEA0DF0E8, 0x17F207E6, 0x2016E7EC, 0x11E3180F, 0xDB130B0A, 0xE5E9FAF2, 0xEC200BED,
+0xEAE9F015, 0xF81DF0E0, 0xE2E81EFE, 0xE4E5E521, 0x0A18EE10, 0xEF21F8F8, 0x19F8E80E, 0x000412E2,
+0x1F1A1017, 0x2213150E, 0xF5EBEDED, 0x1313E813, 0x121AEA15, 0x12F0E317, 0x17F30C15, 0x1B1B191D,
+0xE800F0F6, 0xEEECE9E0, 0x200F160E, 0xEC0AFE16, 0xEBFE09ED, 0xEFD0F6F3, 0x1BEAE718, 0x07E8E511,
+0xF1E90BDA, 0x1DE92216, 0xF7F0DE08, 0xD8140619, 0x0FE7ECD9, 0xE1F6E50C, 0x1917E5FA, 0xEFE5F9F7,
+0xE31C0BE9, 0xD50816EE, 0xF007EA21, 0x0E0DFEE1, 0x0DEA0D1A, 0x181425F9, 0xE1DAE611, 0xED0BDEF3,
+0x15F518E5, 0x171F1DEB, 0x11E3E514, 0x0518E614, 0x0314F0ED, 0xD30FF1EE, 0x15F012F1, 0x0BDFD916,
+0xED05EFF9, 0xF6D8E4EF, 0xF11D1E1E, 0x2016EF17, 0x14E818EB, 0x1417F2DA, 0xE418F8EA, 0xE918EB0B,
+0x0B09EF15, 0xFE21FBE3, 0xEADAE017, 0x1C12E612, 0x1D03FEE5, 0x11D000EB, 0xFFDF0CF6, 0x1120F20E,
+0x180BEC0E, 0xEF131EE8, 0xE71FE614, 0x1B1FE40C, 0xECEFEEEF, 0xE2F7F008, 0xF0110DF5, 0xEAF922E2,
+0x17FBDEE7, 0xEA11EF04, 0xDBEEFE24, 0xF1E30CE5, 0x140AEDF2, 0xF4E7DBF1, 0xDEFC18EF, 0x1112EFF6,
+0x0821E7E4, 0xE400EC06, 0x1BF3E2F2, 0xF0161D17, 0xE5F218E8, 0xF5E61B12, 0xE215F9F1, 0xEF1610F1,
+0x08DCF0E9, 0x0EE324E3, 0xF6D2E8EE, 0x17F7F2ED, 0xDE1ADEE0, 0xEF14EA11, 0x0A301A15, 0x1518F31D,
+0xF721170E, 0xE7FDDC1C, 0x0EEFF2E8, 0xFB28EAF5, 0xE5140E1B, 0x1C14E5DD, 0x15ED1CE6, 0xEF1612F4,
+0xE8F00E1C, 0xEDF50F18, 0xEBDD1314, 0x1CF8EFE3, 0x0E16081A, 0x11ED0EF0, 0x09E82114, 0x14EDDF16,
+0xD4F81018, 0xE0FCFF21, 0x06F30DD8, 0x0B15EE0A, 0x120DF01F, 0xEBF0F5E5, 0xEEE411F4, 0xFF19100B,
+0xEE0D0FE6, 0xDEE71FE8, 0x0DEDE110, 0xE008ED23, 0xECF3EEE8, 0xF1F223EE, 0x121AEFFE, 0xF5F4E919,
+0xE70BE3EC, 0xFB21F5E7, 0x100BEBF0, 0xEBDA19EB, 0x1819F5FE, 0xF4F6F411, 0xFD0CE9EA, 0x171E1CF1,
+0x22160CF4, 0xE7001314, 0xF2E9ECDB, 0x1515130D, 0xF5ED17E6, 0x15E712EC, 0xE807F7E2, 0x201AED1D,
+0xE2F816E3, 0xE8141413, 0x14DE1FF0, 0x18F1EFFA, 0x09EF16E9, 0xE30FE11A, 0xEF13EF20, 0xEE131A15,
+0xE9DBE805, 0x14EA0FE2, 0xF8ED0E17, 0x1A14DEE6, 0x10EE14E4, 0xE9081526, 0xF8F01612, 0xDC0518F5,
+0xF210F00F, 0xEE0E280A, 0xE8E218F1, 0x0EFA04E7, 0x1219E717, 0xF216F0EE, 0x2814E7EC, 0xF41DE81A,
+0xE3EDF0E0, 0x13DFF6ED, 0xEEE9F71C, 0xDBEEEBF1, 0xDD13F8EE, 0xF115FDE8, 0x231314F3, 0xFE090613,
+0xEE110E1A, 0x1A0FFBE4, 0xE31710ED, 0x1A1FED1E, 0x1DEF1AF0, 0xEDEA1E0C, 0x0CE6E9E3, 0x17E42213,
+0x0BEC09E4, 0xDF1D01EA, 0xFB09F828, 0x03111A0A, 0x07E1E31B, 0xEFF3FB05, 0xE9F10E17, 0x12101AED,
+0x1819EAF8, 0xF5EBDBE5, 0x0BE420E7, 0xEC07031A, 0x1509EAF1, 0x1AEDF211, 0x191702F6, 0xF918F315,
+0x0E0A12ED, 0xF526160C, 0x15F5E812, 0xEC11EA10, 0x13E3E7DD, 0x0E23F110, 0xDC14E802, 0x14E20F18,
+0x06DBE816, 0x241A1DE6, 0x11250AEE, 0x1117F61E, 0x0906E9F8, 0xEF1CF41B, 0x1DEC0A07, 0xED16F5F7,
+0x0A1AE00F, 0x1E15ECEA, 0x15F20613, 0x1B151822, 0x111A17EA, 0x0C1EF0E4, 0x071CEB0B, 0xEBF5E6EF,
+0xF9F816ED, 0x161010DB, 0x152413F8, 0xF80F07E3, 0x15EEF615, 0x0E16EDEC, 0x0C20DCEC, 0x0BE10AF6,
+0xF1071EEB, 0x12E5F7F0, 0xEDF5EBED, 0x170FF725, 0xF3F01313, 0x07051CE5, 0xE309EFEF, 0xF1F0180B,
+0xF9161519, 0x181CDAF5, 0xE10E12F0, 0x15F412EB, 0xF7141819, 0xEE1FE0E6, 0xD8F217DB, 0xECF4EB0E,
+0x1DEF0FF4, 0xE40CEB05, 0xF0120DF1, 0x21EC191D, 0xF413E619, 0xE62519E2, 0x1AF00DEE, 0x09F2EFEC,
+0xE8F90DF4, 0x25D6F626, 0xEFE800DA, 0x1BEBEDF1, 0xE812170F, 0xE9E9F102, 0x271BEC08, 0x11E7F71D,
+0x15EAE61D, 0x120C08F4, 0xFD16E813, 0xF30A11E6, 0xE3F1E81D, 0x14F2FE04, 0x1B0A150D, 0xEBE8D8DD,
+0xEF1E1ED7, 0x13100E1A, 0x09F11EE7, 0x11E81218, 0xFA24EFE8, 0xEB151EE1, 0xE516F2E9, 0x1DE41911,
+0xF616E5F3, 0x14EBED19, 0xEB1B12E4, 0xE5191907, 0x22141016, 0xE9EDE60D, 0xFF15F114, 0x1715E1EF,
+0x28020F10, 0x14ED15EA, 0xF618E30A, 0x27EBEAE7, 0x1DE815DC, 0x1816E81B, 0x1A130DF9, 0x2CF609F7,
+0xE5EAE7F2, 0x0F08F401, 0x10ECE8E5, 0x0FECE7E3, 0x15E6F5F3, 0xE41522E2, 0xF3E823E2, 0x0811E5EA,
+0xF91E2119, 0x120C1AFA, 0x1BEDED0B, 0x14E3ED15, 0xE31C12F6, 0xF306EEFC, 0x01ECDB17, 0x09E3F413,
+0xDFF0E7E7, 0x17130BF0, 0xE518FB0C, 0xF21011EC, 0xE21BE1E4, 0x03F5E80B, 0xF0DCEE15, 0xEF1A0E1C,
+0xFD171506, 0xEED10C09, 0x04E9E90D, 0x1CE614E7, 0xF718EFF2, 0x1E03D4EF, 0x06E8EEE7, 0xEB1D21EF,
+0x1519E6EF, 0xF1F00E1E, 0xEAF3240C, 0xEE211D0D, 0x0FF3DDFE, 0x161318F4, 0xE8100DF2, 0xE41422EC,
+0xEA0DE3E6, 0x1FF9DD1A, 0x1618E6F5, 0xE4DE00F5, 0xF0F809F0, 0x1E0C10E7, 0x180D0FE3, 0x19EE09EA,
+0x1C10E2E8, 0xE81EEA12, 0x20DE0D10, 0xEAF01811, 0xDE0D15EA, 0x18F5EFF1, 0x0812EA0C, 0x211204EC,
+0xE9110AE8, 0x21DF1114, 0x18E10D09, 0xFDF8F226, 0xE9E002DE, 0x2116EBE0, 0xF4F918ED, 0x0BECEEF8,
+0xEDE81A06, 0x000EE519, 0x16F2FAE2, 0xD920E312, 0xE51EE713, 0x1423E50C, 0xEF1316FB, 0x20F3F5F2,
+0x1BE3E8ED, 0xE6EAE6EB, 0xDD0B1905, 0xE810ECE9, 0xF71A1810, 0x100A0E10, 0xF114F914, 0x071FF20C,
+0xEC19EDE7, 0x0AD6181D, 0xEC06E8F5, 0x191312F3, 0x121525F3, 0xE6EE2916, 0xF41A0F17, 0xF4E8EFEF,
+0x1819E518, 0xE71FD4E6, 0x15171F19, 0xD80913E0, 0x1FF816E5, 0x0E1A16E5, 0x0CF1F21F, 0xF11513E1,
+0x15FCE7E3, 0xF1DD0FE9, 0x08F018DF, 0x13D915E0, 0x13ED11E5, 0x050F10EA, 0x17F21D13, 0xF90FDEFC,
+0x000B2316, 0xF5EFEB13, 0x09ECEA05, 0x0A18E3FD, 0x0812EE05, 0x0E12F7E7, 0xDA17DB0B, 0x13E6EB16,
+0xF1E71CEC, 0xF111F316, 0x15E90DE8, 0xEA17E0E3, 0x21F20D09, 0x15F915F2, 0x210DF00D, 0xE5DCF0ED,
+0xEDE9EE04, 0xEFF7FAE8, 0xF61A191B, 0xF81DEBEF, 0x0E23F7E0, 0xDCE60BF1, 0x19EF0F20, 0x1B0B120B,
+0xF2130D0F, 0x160CD81C, 0xF3180CEB, 0xDF0AF2EC, 0x14EAD513, 0x20E7F4EF, 0x0CEE1A15, 0xDF17F2E2,
+0x1F0CFAF1, 0xE81011E3, 0x1B290ADC, 0xFDE515E9, 0xE0E9EA0F, 0x0BED0CEE, 0xE2E11AF2, 0xED2015E7,
+0x18E4EA0F, 0xF6F0F313, 0xD904F425, 0x1C0FF1EE, 0xE5F3140D, 0x29F6EB27, 0xEEFC1515, 0x04E3F907,
+0xF11A05EC, 0xF6E7F9E4, 0xF5E60E13, 0x0DEE1518, 0x0D1418E2, 0x0A17EC22, 0x1A0F11EA, 0xEA17E6EE,
+0xF22A191E, 0x2111F5DD, 0x29F216EF, 0x160519E9, 0x0F1A040F, 0x1A021D19, 0x1825EE0F, 0x171D0D0F,
+0x0BFCF004, 0x02FF0BF7, 0xF9F1F209, 0xFFF5F008, 0x05F30C07, 0x03FCEE07, 0x11FCEE08, 0xF4F31514,
+0x040B06F2, 0xE400F9F3, 0x13090B1A, 0xF2F4FFE7, 0xF1EE06F9, 0xFA0DFF0D, 0xF3ED09F6, 0xF40305F8,
+0xF8FFF507, 0xF8FF1707, 0x0AFC030C, 0xF109F3F4, 0x0406FDF0, 0xEF04F50E, 0xF5FBF3FD, 0xF30704F4,
+0xF0ECFC1C, 0xFCECF0F5, 0xF911160F, 0x020B0C0D, 0xF90C060B, 0x03FA08E7, 0x0311FF0D, 0xF405F4FA,
+0x0DEBF7F2, 0x0EF6FAF2, 0x09F3ED0E, 0xFE08EFF2, 0x0F170008, 0x0DFF0FFC, 0x0BF0ED0E, 0x0D140E07,
+0xF2F611F3, 0x11E9020B, 0xEE03F3F7, 0xFCFD00EF, 0xF518090B, 0xF11510EE, 0xF5FB07FF, 0xFEFC11F0,
+0x100DF006, 0x0AF4F300, 0xED0A1200, 0xFEF7EDF5, 0xF7040101, 0x0FF2040E, 0xF01207F7, 0x0AF3FF10,
+0xF60B0D00, 0x07F8EFED, 0x060D03FB, 0xFA08FCF6, 0xEEF6FA04, 0x0806FFF9, 0xFF0B0FF0, 0x08F3F1F8,
+0xF0F5EFF3, 0xF1EE0D01, 0xFBFEF3F6, 0xF20D060B, 0xEFFE00EB, 0x080803EE, 0x0617120A, 0x1210050C,
+0xF010FA07, 0x0908EF0D, 0x030908F2, 0x01160610, 0x120BF415, 0xF9F40FF1, 0x0FF00C02, 0x0B110D0B,
+0x0CF9F10A, 0x0C06030D, 0xF20208F5, 0x0F07FAF1, 0xF0FAF50C, 0x08F8F7F0, 0x01EF0EEC, 0x0AEFE90C,
+0xEFFCF714, 0x05F2FF13, 0xECF6F9E7, 0xFEEFFD07, 0xF6ED0F0D, 0x060FF407, 0x0803F600, 0x0105EE06,
+0xF5F70D0B, 0x02EA110F, 0x070FF8F8, 0x0B040902, 0xF6F30AF0, 0x110C1AF9, 0xF61709F7, 0x0D0FF00E,
+0x09F5EFF7, 0x0F13FAFD, 0x0C02F1F3, 0xFBF0F8F7, 0x0DF8F5EB, 0xF1FEF904, 0xFAF1030D, 0x161211F6,
+0xFA0AF50B, 0xF316F60E, 0x100708EE, 0x0AF00A00, 0xFFF4F4EE, 0x0C0BFD18, 0xFCEDF7FE, 0xFB11080F,
+0x0DF70B08, 0xF90AF309, 0xF9FD0F08, 0x10FEFA0E, 0xEE161508, 0x04FCFFFB, 0x0B1009FE, 0x0CF40D0D,
+0xF800F1FC, 0x07080602, 0x1000F8F8, 0xF8F205FD, 0x0809F9F2, 0xF80C09FF, 0xF9F5F6F8, 0x05FE0EFE,
+0xFCF6F8F1, 0x09000A0B, 0x07080DFC, 0x09FBEDF0, 0xEF0CF4FA, 0xF8F6100A, 0xF5F4F1F9, 0xFFFC0E0B,
+0xEEF6F3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEF0810FC, 0xF311FAFD, 0x0DF201EC, 0xFFF40EF3, 0x1304ED12,
+0xF4FCF304, 0x09EC1005, 0x09F80C09, 0x0C10FC0C, 0xF7F7FBFC, 0xF7F60808, 0x05F90308, 0xEC0A13F4,
+0xF20BF707, 0x04FE03F5, 0x10020FFE, 0x02F413ED, 0x050AF5FA, 0xF90E00E4, 0xFAFBF3F5, 0x0908140B,
+0xF00A0107, 0x13EFED0E, 0x04F5F8F5, 0xF104FF0F, 0xF7F0F6F5, 0x0DF7F704, 0xFF0CEB12, 0xFAF50C07,
+0x05EFF5F6, 0x12FA07F6, 0x0AFDF8F9, 0xEE050803, 0x0A04FBED, 0xF61312F2, 0xF10FF7E9, 0xFBFD0307,
+0x0AFEF5F7, 0x12FB12F3, 0xFA14F206, 0xFAF80EFB, 0xFAFDFAFC, 0xFAFC0DF6, 0xFD08F1EF, 0x0B0D0D14,
+0xF80EF90F, 0x0F0D0903, 0xF609ECF6, 0xF9EFF5F9, 0x0FFBFC06, 0x050A0A08, 0x01F30C03, 0xF9F8EE0A,
+0x0B02100A, 0xFDF3F607, 0x0EFF0D01, 0xF8EFF0FF, 0x11F511F7, 0x08F7F809, 0xEB00FE09, 0xF1FA08FF,
+0xFA0114F6, 0xF0090F10, 0xF3FBF6EF, 0x1209FE0E, 0xF7FCF309, 0x04F5F8FD, 0xF00203F2, 0xF510FB05,
+0x12F7080E, 0x08F10AFC, 0xEFF6F5FE, 0xFFFA0F08, 0x0714F612, 0xF30107F5, 0x06FD08F0, 0xFA0C08EE,
+0x05FA02F9, 0xF40108FF, 0xF90DF1F5, 0x17FC0300, 0x09F2080A, 0x10100BF0, 0x12020B10, 0xF5F80AF7,
+0xF902EBF0, 0x16E00312, 0xFEEA0600, 0xFFFAFA13, 0xF20206F9, 0x060BEF10, 0x15FAF005, 0xF603010A,
+0xF50AF110, 0xF1F903F9, 0xE508F40A, 0x0F0FF704, 0xF00B0AFC, 0xF30DFA02, 0x0202F3F9, 0xF60DEDF1,
+0x05FFFC04, 0xF402FFF8, 0xF1F9F807, 0xEF0E0508, 0xF8F6F80D, 0xF4F2FAF5, 0x031209EF, 0xF9FBF6F2,
+0x000AF6F5, 0xF6000D12, 0xF5FD0C08, 0x04FAEF00, 0x1103110B, 0xF1F50BF1, 0x08FD1104, 0xF80B0AF1,
+0x00160DF7, 0xFD05F3F8, 0x0D01F80B, 0x100502F3, 0xFC0309F6, 0xF41207F6, 0xF2100BFD, 0x040E04F7,
+0xE9080908, 0x06030EEA, 0xF40DF805, 0x09EE0608, 0x0C03F4FB, 0x080CFBF1, 0x100416F5, 0x0407F402,
+0xFDFBFDFD, 0x0BF4F806, 0xFC0B16FF, 0x08EBF3F5, 0xECF9F00B, 0xF8E9F300, 0x08F802F5, 0xF3EF10F4,
+0xFEF409F5, 0x15F7FA13, 0x070DF707, 0x0E0617F9, 0x0206F4FA, 0xF2FAFD0B, 0x10EB0F06, 0x1713EBFF,
+0x030A0BF3, 0xF7E30003, 0xECF50DEE, 0x14050506, 0x160AFC0A, 0x0EFD01F6, 0x02050BEB, 0x031615F4,
+0xF2F3FC09, 0xFA140704, 0x0AF20F07, 0xF7F9FE04, 0xF10EEC06, 0x130D0BFC, 0xF6F3ED0F, 0xF20D100D,
+0xF1F6F40C, 0x0E0BF1F2, 0x0C0FF513, 0xEBEE13FB, 0xF80EF409, 0xF608EC0A, 0xF9090DF1, 0xF602EF09,
+0x14F7F6EF, 0xF401F9F0, 0x130B10FB, 0x0FF31101, 0xEC0912ED, 0x0D03F9F8, 0xF4FAF103, 0xFEF4F10A,
+0xF60BE90A, 0xFFF0F7F1, 0xF801F2F0, 0x00150B1A, 0x09EE130F, 0x130DF7EA, 0x13FB0008, 0xF1F9F00E,
+0x0501F5F0, 0x03F60BF8, 0x090BFE05, 0xEBF8FAF3, 0xEA12F90A, 0xF4FCF4F0, 0x0DF81312, 0x01130DF8,
+0xF3060CF2, 0x00F10CF4, 0xE8F611F0, 0xF707FEF6, 0xF81013FC, 0xF0040AFD, 0xF60616FC, 0xFE1109ED,
+0xED140DED, 0x0303F812, 0xFDF4F4F8, 0x0CF60B14, 0x0DF11811, 0x0BF4FBFA, 0xF2F906F9, 0x09F3F806,
+0x030608FA, 0x0A14E20D, 0x0A08F5FA, 0xE7060DFB, 0x02FD050B, 0xF4F6FB07, 0x01F90BF7, 0x0CFA0FF3,
+0x0B04FD01, 0x0F090604, 0x060E0F0A, 0xF6F1FF06, 0xFC0C0611, 0x01030C0D, 0xF612F9F6, 0x120FF002,
+0xF0F0F9F0, 0x10FE0DFC, 0xEAFCF6E7, 0xF4F0FFFC, 0xEA080D01, 0x09F6020A, 0xF1EDF2F7, 0xF80609F8,
+0xF8F7F80F, 0xF8F7FEFB, 0x0AEE03F4, 0xF60F0406, 0x1309EF03, 0x1215F7FC, 0x0EED07ED, 0x08F30DF5,
+0x09E90D02, 0xF1FAFDF4, 0xFD0FFEF4, 0x0317F1F2, 0xF3111203, 0xF208FEFC, 0xF5FB0213, 0x15F20702,
+0x0FF918ED, 0xF3F8FF0B, 0x0F0A0A0B, 0xEE0C0A13, 0x0A0AF506, 0x1A0401F6, 0xF0F6080F, 0xEC091201,
+0xF9F90C02, 0xF10CF003, 0xF217F200, 0x0DF8FA11, 0x04F603F6, 0x03FB10FA, 0x0AF4090D, 0xF1FBF3EF,
+0x0DF00505, 0xFA0B0E0E, 0xFD030811, 0xFEEDF80A, 0xF1F1F40B, 0x050D0514, 0x0DFC0A10, 0xFF0D01EB,
+0x07F7010D, 0xF90D00F6, 0xFCEDF108, 0xFD10F30C, 0xF3F7FB06, 0xF009F8FF, 0xF808F8F5, 0xEF12F009,
+0x0C0E14F8, 0x02010E06, 0xFF00F50D, 0xF9F1F309, 0x0507EEF0, 0xF8EFFDFB, 0x05041303, 0xFC13EEF6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0xFB0E01EF, 0xFF0C0B02, 0x07090AFB, 0x0BFBF3F1, 0x0B090F0D, 0xF10409F2,
+0xF80A0E0B, 0xECF60E09, 0x0610F2F9, 0xF4F9FBEF, 0x08ED0DF9, 0xFCF9FEFE, 0x0F0C12F8, 0xF9F317F4,
+0x0BF80213, 0xFFFD1710, 0x0BF80FFB, 0xEEF6F2EE, 0x0106F506, 0xF3091206, 0x00F504F0, 0x0B0C0018,
+0xFD02FAEF, 0x06ED0308, 0xF4F60215, 0x02F80BFC, 0xF20601ED, 0x06F7F5F3, 0x0111FAFC, 0xF2ECF2F8,
+0xFB050C0D, 0x0314EA0A, 0x09F4FCF8, 0xF0F80013, 0xF6E90D0A, 0xF307F415, 0xFB04F4F8, 0xF006F3F1,
+0xFAF9F808, 0x06F9F109, 0xED0A0A0C, 0xF3F6FC03, 0x0508120A, 0x0C0DF100, 0x02FF09FF, 0x00F80D01,
+0x04E50410, 0xF616130C, 0x0300F4EC, 0x090EF506, 0xFA0E0C14, 0x0EF10111, 0xF2030F09, 0x03F3030E,
+0x09EA0509, 0xFDFEF9FB, 0x06F4F702, 0x0C0D0BF3, 0xFFFBF906, 0xF7FBF512, 0x03110AF8, 0x0AF7F70D,
+0x17F60108, 0xF811FA05, 0xEE040700, 0x03FEEF01, 0xF706EC0B, 0x060C0AFA, 0xEC0EF910, 0x0804F207,
+0x09E902F7, 0xF7FDF610, 0x0C050C0B, 0xF8E7F609, 0xFB170A13, 0xF0080404, 0xE808F413, 0xF1F4EB07,
+0xEBFC01F7, 0x0B040AE8, 0x00F1020E, 0xF0F207EC, 0x0EFFF211, 0xF3F815F4, 0xF9020B0B, 0x0EF71201,
+0x0706FC0C, 0x06FDF6FA, 0xFBF7F80A, 0x08090EFD, 0x14FD05FF, 0xF403FE0A, 0xF5F8EF03, 0xFB0AF8F7,
+0x0F00F409, 0x0AEF0B03, 0x0FFB0210, 0x11070710, 0xF1080B0B, 0xF20E08E8, 0xF00CF5EB, 0xF0F30C0E,
+0xFCF0080D, 0x0900EE07, 0xFA01FCFE, 0xE712E70B, 0xF004FEF9, 0x0CF5090D, 0xF60EF606, 0xF8F4FAF8,
+0xED061507, 0xEF110506, 0xF90FF20C, 0xF911F813, 0xFC12F3EF, 0xF7F9F1FC, 0x0E07EAE9, 0x0EF8F1F8,
+0xF6070FEA, 0xF0FA0310, 0xF8FE1417, 0xF8F306F9, 0xFBFCF50E, 0xEC0D11F3, 0x0900F70A, 0xF80EFBF3,
+0x0B08F8F6, 0xEFF00F0C, 0xF709F8FA, 0x0E16EB13, 0x0BF415FE, 0xF4F20F0B, 0xEC0C0AF3, 0x13F8FB02,
+0x12F908FB, 0x0A090D12, 0xF110F0F5, 0xF40E021B, 0x0809F7F3, 0xEE000B0D, 0x0E0FF5F6, 0xF3F40BF6,
+0x05150BE7, 0x0DF809FE, 0x12030809, 0xFF13FC08, 0x0BF6F912, 0x13F90AF4, 0xFE03F2F1, 0x04FB0CF7,
+0x01FDE8F5, 0x0EF8F40D, 0xFE02F7ED, 0xE7EDF2FB, 0x04F9FF13, 0xF0F80A07, 0xF700F6F7, 0xF4080EF4,
+0xF2F7F80F, 0x0DFDEFF0, 0x11EFF902, 0xF2FC0703, 0x0AFD10F1, 0x17F70D07, 0x08F5EFEB, 0xF10B11F9,
+0xF610FFF8, 0x0C130B18, 0x080CFEF5, 0xFBF8F906, 0xF1080C08, 0xEAEEEE10, 0x0F11F6FD, 0x06F706F1,
+0xED0BEA0D, 0xEEF30C02, 0xF8F40D0F, 0x020D0DEC, 0x0CF40605, 0x07020C12, 0xF40C0EF2, 0x060115F2,
+0xF0E6F508, 0xF40DF9F0, 0x0F0A05F4, 0x0FF00B08, 0xEB08FEFC, 0xEE030AF1, 0x0DF9E806, 0xF2F7F5FD,
+0x0A12EEF0, 0x09F3EFF8, 0xFE05F6F8, 0x1CEDF4F5, 0x060512FB, 0x08F90AF0, 0x000107F9, 0x14FFF9FA,
+0x16F70B0B, 0xEEF2F704, 0x04F90BF1, 0x150302F3, 0xEBF8F8F3, 0xF6F90FEF, 0xFBF0F7FD, 0xF70D1000,
+0xECF70C12, 0x03FDF3F0, 0xE4F31604, 0x02FFF600, 0xF00C0105, 0xEC0D0F02, 0xFAFAF707, 0x0208F501,
+0xFFF809F5, 0xEEF70405, 0x050CFCF9, 0xF20BEBF7, 0xFA0E11F6, 0xF7F403F2, 0xF5F0F306, 0x00081A0F,
+0x02F6EE09, 0x0F0D0B0F, 0x0AF7EDF6, 0xECFA0FEB, 0xF000FBFC, 0xF91103F4, 0xF0F30001, 0x08FCF8EE,
+0x0CFEF30B, 0xFE040B02, 0xFC030FF3, 0x04F9F209, 0xF10E0705, 0x14F60B0C, 0x03ED1311, 0xED03EE13,
+0xF9F8F70F, 0xFB010504, 0xEDF70C08, 0x061802FE, 0xED0801F9, 0x06FCFA16, 0x0EF8FCF3, 0x0EF00C0E,
+0xF3F9170D, 0xFE010F05, 0xF31B0500, 0x07F50BF4, 0xEE09030A, 0xF401F400, 0x0C04090A, 0xFCF90F02,
+0x0D10FD0C, 0xF00FEA09, 0xF3F50BF7, 0xFCFCF7EF, 0x06FB0A12, 0x0200EC01, 0x02020A0E, 0xF3FCFE0D,
+0xFC0CF209, 0xFB06F2EE, 0xF90B0C10, 0xFDFCF40C, 0xFC06F80B, 0xEFF902F3, 0x0C110911, 0xF80AEFF3,
+0x0900F30C, 0xF8160E0F, 0xEE0D130D, 0x0BF00209, 0x0AF509EF, 0xF7F614FA, 0xF513070A, 0x09E512FD,
+0xF3050D0C, 0x0006020D, 0xFAED07FE, 0x07FE170B, 0x121300FF, 0x02F602FD, 0x0AF408FA, 0x06FAF7F1,
+0x0807F71A, 0xFBF20C0B, 0xF3FD05F7, 0x06F4090F, 0xF1FEF307, 0x0805EBFA, 0x0810070D, 0xF6F31214,
+0x02ED0607, 0x0D08010F, 0x09F60FF2, 0x0BF8F20C, 0x1BFCF6F4, 0xECFB070C, 0x13FAF3FD, 0xF8F7FCF4,
+0x0C09F7F4, 0xF001E9F9, 0x11F1F305, 0xFAEC08FA, 0xF8F8F40F, 0xF6F70B0A, 0x07F012F4, 0xFDF5FEF3,
+0x09070EF1, 0x09FFF7E9, 0xEAF60C0F, 0x04030106, 0xF5E70709, 0x0AF6F70C, 0xFA14FEF1, 0xF0E51903,
+0xF4EF0B11, 0xF0F80CF3, 0x12ED0307, 0xF301F405, 0xF9F4F3F5, 0x0B0EF809, 0xF7EBF9F8, 0xF10BF406,
+0xFBEEF2F6, 0xEC1111F2, 0x0716EEF6, 0x080910F0, 0xEE0D0010, 0x07ECF7F0, 0x09060005, 0x0DF5EB0B,
+0x0212110C, 0xF3F704FA, 0xEA02020C, 0x050811F1, 0x01FA07F7, 0xF60E0D0D, 0xF711F60C, 0x0108F4F1,
+0xF7F6FE01, 0x0F0FF7F9, 0xEFE7010A, 0x090902F6, 0x0FE809F8, 0xFDFE00F6, 0xEF0806F5, 0x10F80F0F,
+0x0419F40B, 0xEF08EEFD, 0x0711F507, 0xF20901FB, 0x0BFA130A, 0xFA120CF9, 0xE809F2F2, 0xFAF8FE00,
+0xF2FDFCF8, 0xF805F1FD, 0xF1F70912, 0x0903F80B, 0xF9EFF70B, 0x0D05F5F2, 0x0A08FF0E, 0x09F5EE00,
+0x08F91314, 0x0AFEF60A, 0xE51005F0, 0x041EECFA, 0x06FDFF05, 0x0D11F1EF, 0xF4F80912, 0x0D090106,
+0xFAF6F308, 0xFE14F8F1, 0x0D02EE03, 0xF0FDFAED, 0xF2F2E903, 0xE9040C0D, 0x0A00F8F8, 0xF4FA0909,
+0xF4EFFA1B, 0xFC0D0D0B, 0xF2EE08F5, 0x000E0F12, 0xF0F50F11, 0x04FEF9F4, 0x0BF914EB, 0x170CFBF9,
+0x03F30E06, 0x01F8F70F, 0x14F8EFFD, 0xF412F5F2, 0x0AF60C01, 0xF711090D, 0xF60DF90C, 0x09F0ECE8,
+0xEC06140C, 0xFD090DFA, 0xEA01F7EF, 0x030AF8F6, 0xF3F5FCFD, 0xF4F3F500, 0xF3EDECF5, 0xF3130AF6,
+0xF8EFFA0E, 0x0A0B0DF4, 0xF1F0F7F5, 0x0D0A09F4, 0x10EDEEF7, 0x0E0EEDFE, 0xF4F9F306, 0x05FCF8FF,
+0x13FBF7F2, 0xFF07F6F7, 0x0AF2F8F6, 0x0DFA1EFF, 0xF6EE0B09, 0xF113030B, 0xFAF9F3F5, 0xFA0C080C,
+0x0BF8F607, 0x09F902FB, 0xF50BFD08, 0xF7F515EF, 0x0BFA00FB, 0x01FAF009, 0xEA02FE05, 0x0CFBFC10,
+0xFBF7F214, 0x1305F1ED, 0xFA01F216, 0xFDFBFFF4, 0xEE0B040C, 0xFAFB05FD, 0xFEF8F7F4, 0xF60802EF,
+0xF301E603, 0x03EEFAF7, 0xF109EAF2, 0xEF0BFEF5, 0xFFF31115, 0xED09F309, 0x02FFEE0D, 0xF60D0FF9,
+0x030A07FA, 0xF5F4060A, 0x140FFEF1, 0xF6FCEEFF, 0x07030006, 0xFBEF04F7, 0x0AF009FC, 0xF90A0FF9,
+0xF2F702F8, 0xFFFBFB0E, 0x0907090B, 0x0B180F02, 0x0B0C0405, 0x12F80AF9, 0x09F400F0, 0xF010070A,
+0xEBF105F1, 0x05F90C11, 0xE805F30B, 0x12F70BF3, 0xEF11EFFC, 0xEFF7FC0F, 0xE709EF10, 0xF50CFBFD,
+0xF7F805F0, 0xF609FCF7, 0xEAF80F00, 0xFBF40B10, 0xF71106F5, 0xFA12FB01, 0x020BF30C, 0x0714FA04,
+0x06010708, 0xF2110D0D, 0xEEF6F2F8, 0xF009F1E8, 0x07FD06F7, 0x14F8EF0C, 0xF00DF9F6, 0xF20BF50B,
+0xF90C06F7, 0x06FB02F7, 0xF7F20A09, 0xFA051008, 0x0EFA0913, 0x05060D03, 0xFCF40CF6, 0x03E8FCFC,
+0xF3F31411, 0xFCF40906, 0xFB0BF9F7, 0xFC02F80D, 0xF20408F2, 0xEE0EEF0B, 0xF0000EF3, 0xFBF6EDF1,
+0xFAF50FEB, 0x06FC0C0B, 0xF009F80F, 0xF0F7F706, 0xF70507FC, 0x0AF00209, 0xFF0DF20F, 0xEA15FA06,
+0x0816EDF3, 0x000EF9F5, 0xEFF7FA04, 0x0FF60814, 0xF1FEFA02, 0x0805F306, 0xF610FDEE, 0xF8061606,
+0xFE0DFCEF, 0x07F8F613, 0x0C0809F9, 0x0DEBF0FB, 0xF00EF4F4, 0xF8E7F20A, 0xF3FAF20D, 0xF90D04EE,
+0xF1F40E00, 0x09EFFFEC, 0xFE0B0EE7, 0xF7FA0F0E, 0xF00CFEF4, 0xFAEEF9FC, 0x161AF703, 0xF70F10EC,
+0xF6F011FA, 0x10FDFB0B, 0xF60C03FE, 0x0AFF08F3, 0xF6F606F0, 0xF5F716F3, 0xFDFDEBF7, 0x0CF8EFF4,
+0xE3EF0910, 0xF7F6FF12, 0x001402F1, 0x03100EF2, 0x1117EBFF, 0x17FA1008, 0x0DF9F80E, 0xFCF0F511,
+0x1403EEFC, 0x0010F100, 0x110A0612, 0xF505FAEF, 0xF4F304F4, 0x061209EF, 0x090C150C, 0x04F41306,
+0x0B0C0DED, 0xF0F6F110, 0xFC0F1008, 0xF3EF0E08, 0x0B0AECF8, 0x0CF8FA0C, 0xF7FB0EFF, 0x0FF50FFC,
+0x0DF4EDF8, 0x02080C0B, 0xF510F2F2, 0x0208FDF1, 0x060B04F1, 0xF8F6E607, 0xF415EDFF, 0xE8FBEBEC,
+0x0805F30F, 0x00F30F09, 0xFA0DF6EB, 0x0BEEF806, 0x0408F00B, 0xF4F5FB09, 0x090EF310, 0x1006FBF9,
+0xF0F7F710, 0xFC070C0F, 0xFB12EAFA, 0x0BF007F1, 0x080100F1, 0xF700F709, 0x0A0D05F8, 0xEFF20D0C,
+0xF209F8F8, 0xF207FDF3, 0x0DEFEFEE, 0xFD020114, 0x0AF5050A, 0x0D0415FA, 0x0C12ED0F, 0x14F01005,
+0xF7F0EE06, 0x0F14F209, 0x080500F9, 0x08F5050E, 0x0DE7E901, 0x03FDF3FC, 0xF20403FD, 0xF7F2F60D,
+0xECF00D09, 0xFB09FF0A, 0xF306F9F2, 0x0E03F20E, 0x0C09F305, 0x11F710F8, 0xF4F217E4, 0x0E09090A,
+0x0A12F0F9, 0x06F312FE, 0xFDFBFDEE, 0xE9F0020D, 0x0DFB1005, 0x0200E90B, 0x0F0C02F5, 0xF8FF05F4,
+0x0AF303FD, 0x0BF4100E, 0x14F2040F, 0x0EF9EF0B, 0x0AED0801, 0x05F5EE08, 0xFF0A0514, 0xF8F2F0FF,
+0x0FFAF7F0, 0xE10E12F6, 0x13F1F4FA, 0xF3FC0B0B, 0xEFFEF4FD, 0xF9080708, 0x05FCF9F6, 0x040E06F4,
+0x020DF5F6, 0x13F50B11, 0x1513F1F6, 0x05F707ED, 0xF7FB01F7, 0xF1EF06FA, 0x09FB1102, 0x06FC0706,
+0xF7F80F14, 0x0EF3F002, 0x0AF8FE0A, 0x0BE8F5F9, 0xEEF609E9, 0x09E8EE02, 0x03090BFC, 0xF0F8F0F1,
+0xF8081009, 0x0F0002FA, 0xFCF202FD, 0x0DF106EF, 0xF70408F5, 0x02140C15, 0xF6F6F5EF, 0xF1080905,
+0xE902FDEC, 0xF3F4F6F6, 0xF904FCF2, 0xF906F5F3, 0xF7FB0A08, 0x08F4F0F1, 0x0EFDF6F1, 0x03F8F6F6,
+0xFF0C110C, 0xF1FDF7F8, 0xF814F502, 0x12FD1108, 0x0DF7F313, 0xF506FA11, 0x07FEF9F2, 0xEAF20D09,
+0xFCF40D0D, 0x06F1F709, 0xF7F21DFA, 0xFB00ED11, 0x0DFA0208, 0xF1FE1101, 0x0AF5F4F9, 0x060BF3F9,
+0x080CFD06, 0xF30EF409, 0x12EB02EF, 0x0BEF0D09, 0x1512F0F0, 0x18010700, 0x05070F05, 0xF306FC08,
+0x0001FD0E, 0x10FD0DF8, 0xF708F90A, 0x100D0D05, 0x04011414, 0x0AF90D0C, 0xF402F8EE, 0xFC11FAFF,
+0xF500F605, 0xF0EAF8F4, 0x120F0407, 0x1103F9EE, 0xF9F9F5F7, 0x10060EF8, 0x0609F504, 0xF20E080F,
+0x0EF3F109, 0xFB05F60E, 0x0E1C05FD, 0xF710FBEB, 0x16F2F90B, 0xF500FEF4, 0x0A13EEF7, 0x0EFF0CF6,
+0xFFF903F8, 0xF30A0BF0, 0xF7FCF004, 0x1613F70B, 0xF90506F5, 0xEB09F008, 0x05F30CF3, 0x0310EEF3,
+0xFD1002F4, 0x09070114, 0x040B0606, 0xE400F907, 0x13F40B1A, 0x06F4EBE7, 0xF1EE06F9, 0xFAF9130D,
+0xF3ED090A, 0x08EF05F8, 0xF814F507, 0xF8131707, 0x1EFCEF0C, 0xF1090708, 0x04F211F0, 0xEFF0090E,
+0x09FBF3FD, 0xF3F204F4, 0xF000FC1C, 0xFC00F009, 0xF9FD160F, 0x16F7F80D, 0x0DF8060B, 0x03FAF4FB,
+0x03FDFF0D, 0xF4F1F40E, 0xF9EBF7F2, 0x0EF6FA06, 0x09F3EDFA, 0xFEF4EFF2, 0x0F0300F4, 0x0DEBFBFC,
+0x1FF0010E, 0xF9140E07, 0xF2F6FD07, 0x11E9020B, 0xEE17070B, 0x10FD0003, 0x0904F5F7, 0x0515FCEE,
+0x090F07FF, 0x12FC1104, 0x10F9F0F1, 0x0A080700, 0x010A1200, 0x120B01F5, 0xF7F0ED01, 0xFB06040E,
+0xF0FEF30B, 0x0A0713FC, 0xF6F7F9EC, 0x07F803ED, 0xF2F9EF0F, 0xFAF4100A, 0x020AFA04, 0x0806130D,
+0xFF0B0F04, 0x080705F8, 0x04F503F3, 0x05EEF9ED, 0xFBFEF30A, 0xF2F9F20B, 0x03FEECEB, 0x08F40302,
+0x0617FE0A, 0xFE10050C, 0x0410FAF3, 0xF508EFF9, 0x030908F2, 0x010206FC, 0xFDF7F415, 0xF9080F05,
+0xFBF00CEE, 0x0BFD0D0B, 0xF7F9F10A, 0xF80603F9, 0xF202F4F5, 0x0F07FA05, 0x04FA09F8, 0x08F80B04,
+0xED030E00, 0x0A04FDF8, 0xEFFC0B14, 0x05F2FFFE, 0xECF60EFB, 0xFE04FD07, 0x0AEDFB0D, 0xF20FF407,
+0xF4030A00, 0x15F1EEF2, 0xF50B0D0B, 0x02FE11FB, 0xF3FBF8F8, 0xF7F0F516, 0xF6070A04, 0xFD0C1A0D,
+0xF603F50B, 0x0D0F04FA, 0xF5F5EFF7, 0xFB130FE9, 0x0C0205F3, 0xFB050CF7, 0xF9F809FF, 0xF1120DF0,
+0x0E0503F8, 0x16FEFDF6, 0xFA0AF5F7, 0xF302F6F9, 0xFC07F4EE, 0x0A040A00, 0xFFF409EE, 0xF8F7FD18,
+0xFC01F7EA, 0x0F11F40F, 0x0DF7F708, 0x0DF60809, 0x0DFD0F08, 0x1012FA0E, 0x021615F4, 0x04FCEBFB,
+0xF7FC09FE, 0x0C080DF9, 0xF8EB05FC, 0x0708F2EE, 0xFC14F80C, 0x0C06F111, 0x0809F9F2, 0x0CF809FF,
+0x0DF50AF8, 0x05EA0E12, 0xFCF6F805, 0xF5EC0A0B, 0xF2080D10, 0x09FBED04, 0xEFF7F40E, 0xF8F610F6,
+0x09F4F1F9, 0xFFFC0E0B, 0x020AF3EC, 0xF4EA09FE, 0xF7EFF70D, 0xEFF410FC, 0x07FD0EFD, 0x0D060100,
+0x13F4FAF3, 0xFFF001FE, 0x08FC07F0, 0x0900FC05, 0xF5F8F709, 0x0CFC100C, 0xF7F7FBFC, 0xF7F608F4,
+0x05F90308, 0xECF6FF08, 0xF2F70B07, 0x04FE03F5, 0xFC02FBFE, 0x02F41301, 0xF1F6F50E, 0xF9FA00E4,
+0x0EFB0709, 0xF50800F7, 0x040AEC07, 0x130301FA, 0x0409F809, 0xF104EA0F, 0xF7F00A09, 0xF80BF704,
+0x13F800FE, 0xFAF50CF3, 0xF103090A, 0x12FAF30A, 0xF611F8F9, 0x02F1F403, 0x0A040FED, 0x0AFFFEF2,
+0x05FBF7FD, 0x0FE903F3, 0xF6EA090B, 0x120FFE07, 0xFA1406F2, 0x0EF80EFB, 0x0EFDFAFC, 0x0EFC0D0A,
+0x120805EF, 0xF70DF900, 0x0C0EE5FB, 0x0F0DF503, 0xF609000A, 0x0D03F5F9, 0x0FFB1006, 0x05F60A08,
+0xED07F8EF, 0xF90CEE0A, 0x0B16100A, 0xFD07F607, 0x0EFF0D01, 0x0CEF04EB, 0x11F5FD0B, 0x080B0CF5,
+0xFF14FEF5, 0xF1FAF413, 0xFA0100F6, 0xF0090FFC, 0xF3FB0AEF, 0xFE09FE0E, 0xF710F3F5, 0x04090C11,
+0x04EEEFF2, 0x09FC0FF1, 0xFE0BF4F9, 0x08F10AFC, 0x030AF5FE, 0x13FA0FF4, 0x07000AFE, 0x071507F5,
+0x06FD08F0, 0x0F0C08EE, 0x190E020D, 0x08EDF4EB, 0x0D0DF109, 0x0210EF00, 0xF506080A, 0x1010F7F0,
+0xFE02F7FB, 0x09F8F6F7, 0xF902FF04, 0x16E003FE, 0x12EA1A00, 0x130E0FFF, 0x0702F2F9, 0xF10BEFFC,
+0x010E04F1, 0xF6EF15F6, 0xF50A0510, 0x050DEF0D, 0xF908F4F6, 0x0F0F0BF0, 0x04F7F6FC, 0x07F9FAEE,
+0x02EE07F9, 0xF6F90105, 0xF1FFFC04, 0x0802EB0C, 0xF10E0CF3, 0x030E0508, 0x0CF60CF9, 0x08F20EF5,
+0xEFFE09EF, 0xF9FB0A06, 0x14F6F6F5, 0xF6140DFE, 0xF511F8F4, 0xF0FAEF00, 0x1103FC0B, 0xF1090B05,
+0xF4FD11F0, 0xF80BF6F1, 0x14160D0B, 0x1105070C, 0x0DEDF80B, 0x1005EE07, 0xFCEFF5E2, 0x0812F3F6,
+0xF2100BFD, 0x04FAF00B, 0xFD08F508, 0x06030EEA, 0xF4F90C05, 0xF5EE0608, 0x0CEEF40F, 0xF4F8FB06,
+0xFCF01609, 0x0407F402, 0xFDFBFDFD, 0x0BF4F806, 0xFCF701EB, 0x08EB0709, 0xECF9040B, 0xF8E9F300,
+0x1C0CEEF5, 0x0703FC08, 0xFEF40909, 0x150B0EFF, 0xF30D0B07, 0xFAF203F9, 0x11EC1EE9, 0x191AF4E5,
+0xEFDF19D9, 0xFA220619, 0xFA131A14, 0x10FB0909, 0x0C131B0D, 0x140FEB0F, 0xF41AEEEF, 0xEE0A10E5,
+0xE206F0E4, 0x13FBFFDE, 0x15132215, 0x1CF31EF8, 0x1512111A, 0x1F1E0114, 0xE8F20F29, 0xEDEF1112,
+0xE30DE215, 0x0DED2213, 0x19EBE410, 0x1917DD1E, 0xF5E818EE, 0xDDDB16EE, 0x1418F6F5, 0xE414E31A,
+0xEBE7E606, 0x10E50CE8, 0x011C1813, 0x0E15EB11, 0x22E81C1C, 0xEA1B0FE3, 0xE1E9F90D, 0x12FBF91F,
+0xEAE312E5, 0x19100D1F, 0xF10F0516, 0xEF1EEA0B, 0xF2E612E4, 0xF2FAE823, 0x0AE4F5F2, 0xF2171BD9,
+0x1817FEE9, 0xE9F209E6, 0x07D8EA03, 0x1716F0E5, 0x0DDC16ED, 0x09222113, 0x0126EDE2, 0x11F611E2,
+0xF3F21FFE, 0xFBF00E1D, 0xE5E01B0F, 0xEF0CE6EE, 0x05E0EE0D, 0x0819F7F1, 0xEAF01EEA, 0xE811ED18,
+0xE115FB16, 0x1DF8EAEB, 0x04FDEFE5, 0xE40EEFF7, 0x28EAF514, 0x181CF019, 0x0F09F711, 0x0E1A12FB,
+0xE9EB06F0, 0xE6EBEEEC, 0xDB14151E, 0xEA18FC14, 0x13050C19, 0x06EFEF0B, 0x2217E9EE, 0xECDD19E8,
+0xFC24151E, 0x1016EA0B, 0x08F8F1EB, 0xEBE9050B, 0xDDF6E815, 0x15E1F5DA, 0x10111C1F, 0x05E113E5,
+0x1925EB1B, 0x19F3F1F6, 0x11061810, 0x1EF5F725, 0xDDEE06DE, 0xE51509F6, 0xE513F1E2, 0xE9EB24F3,
+0xF1FE0BE2, 0xEC09F3EE, 0xEDEF0FE9, 0x1BEDF6F2, 0x19EEE311, 0x14EAE7F5, 0x22F0F1EB, 0xFAF412F8,
+0xEB09EAE4, 0x0EEC1505, 0x0D0AEE01, 0x0916F5EE, 0x21EAF215, 0x2003DFE5, 0xEDE9E616, 0x01F2D11B,
+0x0D13EC20, 0xF8E7100F, 0xF1F3FA07, 0x1414E5EF, 0x10E8F512, 0xDDF4FBF1, 0x1719E712, 0xFFEDF91D,
+0xECF4E7EA, 0x0BEE1711, 0x1BEC0AEB, 0xEBF0E1E7, 0x101E15D6, 0x11F211F9, 0xE8F41721, 0x0FEE161B,
+0xF118EA1B, 0xDD1C19E2, 0xEEDCE80F, 0x1AF1F516, 0x080B141B, 0x15DD1BEE, 0x100E14F1, 0xFFFB0427,
+0x18181F22, 0xDEEBFC0A, 0x07170B14, 0xF819230C, 0xFA0FE5EF, 0xDFF1ECF6, 0x0CF313E7, 0x0D17FA05,
+0x141117E8, 0x05FEE7EE, 0xF21DF516, 0xF509F1E8, 0x18291408, 0xF21110F3, 0x17E20AE5, 0x0BEEF9EF,
+0xE82220ED, 0x23F8E4EA, 0x1203F2F1, 0xF0FB0CF7, 0xED12FC09, 0xFAF808F9, 0xFE16F701, 0xFC01F20F,
+0xF00D13FF, 0xF00C0A07, 0x0BEC0AF7, 0x08F4FAF4, 0xF2F70C0F, 0xF912EF04, 0x11EFF902, 0xF2111BEF,
+0xF611FCF1, 0x170B0D07, 0x0809EF00, 0x060B110D, 0xF6FCFFF8, 0x0C13F718, 0x080C12F5, 0xFBF8F9F2,
+0xF1F40C08, 0xFE02EEFB, 0xFBFD0AFD, 0x060BF205, 0xED0BFEF9, 0x02070C16, 0xF8F4F9FB, 0x020DF801,
+0x0CF4F2F1, 0xF3EE0C12, 0x08F80E06, 0xF2ED00F2, 0x04FA09F4, 0x080DF905, 0xFBF6F1F4, 0xFBF00BF4,
+0xEBF41210, 0x02180A05, 0x0D0DE806, 0xF2F709FD, 0x0A120204, 0x09F304F8, 0xFE050AF8, 0x1C01080A,
+0xF205120F, 0xF40DF604, 0xECEDF3F9, 0x14FF0D0E, 0x020B0B0B, 0xEE06F704, 0xF00DF705, 0x1503EE07,
+0xEBE4F8F3, 0x0AF9FB03, 0x0FF0F711, 0x0BF9FC00, 0x000C0C12, 0x031108F0, 0xF8F30204, 0x02FFF600,
+0xF0F80105, 0x00F90F16, 0xFA0EF707, 0xEE08F501, 0xFF0C09F5, 0xEEF7F0F1, 0xF1F710F9, 0xF2F7EB0B,
+0xFA0E110A, 0xF7F40306, 0x0904F306, 0xEC081AFB, 0x02F6EE09, 0x0FF9F70F, 0xF6F701F6, 0xEC0E0FEB,
+0x0414FB10, 0xF9FDEFF4, 0x04070015, 0xF4FC0CEE, 0x0C1208F7, 0xFEF00BEE, 0xE803FB07, 0xEFF9F209,
+0x05FA0705, 0x00F6F7F8, 0x03EDFF11, 0x01EFEE13, 0x0DF8F7FB, 0xFB01F1F0, 0xEDF7F808, 0x06030212,
+0x0108010D, 0x06FCFA02, 0x0EF8FC07, 0x0EF00CF9, 0x07F9170D, 0x12EDFB05, 0x0707F114, 0xF3090B09,
+0xEE09030A, 0x0815F400, 0xF80409F6, 0xFC0DFBEE, 0xF910FDF8, 0xF00FEAF5, 0xF309F7F7, 0x1010F7EF,
+0xF2FB0A12, 0x02000001, 0x02020AFA, 0xF310120D, 0xFCF8F209, 0xE7060602, 0x0DF7F810, 0x111008F8,
+0x10F2F8F6, 0xEFF9EEF3, 0xF8FDF511, 0x0C0A04F3, 0x091407F8, 0xF8160EFB, 0x02F8FFF9, 0xF704EE09,
+0x0AF5F503, 0xF7F6000E, 0xF513F30A, 0xF5E5FE11, 0x08050DF8, 0x0006EEF9, 0xFA02F3EA, 0x07EA030B,
+0xFE13ECFF, 0x02F60211, 0xF6F4F4E6, 0xF20E0CF1, 0x0807F706, 0x0FF20C0B, 0xF3FDF00C, 0xF108F50F,
+0x05FE07F3, 0x08F1EBFA, 0x08FC070D, 0x0A07FE14, 0x02ED06F3, 0x0D08ED0F, 0x09F60F06, 0xF70CF2F8,
+0x1BFC0A08, 0x000F070C, 0x130E0711, 0xF8F710F4, 0x0CF50B08, 0xF0EDFD0D, 0x1105F3F1, 0x0E00080E,
+0xF80C080F, 0xF6F7F70A, 0x07041208, 0x11F5FE08, 0xF507F9F1, 0x09FFF7FD, 0xFE0AF80F, 0x041715F1,
+0xF5FBF3F5, 0x0AF6F7F8, 0x0E00FE05, 0x04E519EF, 0x0803F711, 0xF00C0CF3, 0xFEEDEF07, 0x071508F1,
+0x0DF407F5, 0x0BFAF809, 0xF7EB0D0C, 0xF1F7F406, 0x0FEEF20A, 0x00FDFC06, 0xF302EEF6, 0xF4F51004,
+0xEE0D14FB, 0x07EC0B04, 0x090614F1, 0xF909FFF7, 0x02FEFD0C, 0x070B04FA, 0xEA16EEF8, 0xF1081105,
+0x01FA07F7, 0xF60E0D0D, 0x0BFCF6F8, 0x01F40805, 0xF70A1201, 0xFBFBF7F9, 0x04E716F6, 0x09F502F6,
+0xFBE8090D, 0xFD12000A, 0x03F4F209, 0x100CFB0F, 0x0405F40B, 0x0308EE11, 0x07110907, 0xF20901FB,
+0x0BFAFE0A, 0x0EFEF80D, 0xFCF5F2F2, 0xFAF8EAEC, 0xF211FC0C, 0xF8F1F111, 0x05F709FE, 0x0903F80B,
+0xF9030B0B, 0xF919F5F2, 0xF608FFFA, 0x09F50300, 0xF4F91314, 0x0A120AF6, 0xE5FCF1F0, 0x041EECFA,
+0xF2FDFFF1, 0x0DFD05EF, 0xF40C0912, 0xF9090106, 0x0EF6071D, 0xFE140DF1, 0xF9EE0203, 0x04110EED,
+0x06F2E903, 0xFD04F8F9, 0x0A000C0D, 0x08FAF509, 0xF4EF0E1B, 0x10F9F9F7, 0x06EE0809, 0x140E0F12,
+0x04F50FFD, 0xF0EA0D08, 0x0B0D00FF, 0x17F80F0D, 0x17070E06, 0x01F8F7FB, 0x14F80312, 0xF4FEF506,
+0x0A0AF8ED, 0x0B1109F9, 0x0B0D0EF8, 0x09F0ECE8, 0x00F2140C, 0xFD090D0E, 0xEA16F703, 0x03F6F80A,
+0xF30910FD, 0xF4F3F514, 0xF302ECF5, 0xF3FF0A0A, 0x0CEFFAFA, 0xF60B0D08, 0xF104F7F5, 0xF90AF5F4,
+0xFC0102F7, 0xFAFA01FE, 0xF40DF3F2, 0x05FC0CFF, 0x13FBF706, 0xEBF30AF7, 0xF6F20CF6, 0xF90E1EEB,
+0xF6EE0BF5, 0xF11303F7, 0xFA0D0709, 0xFAF8080C, 0x1FF80A07, 0xF5F9EE0F, 0x09F7FD08, 0x0B0A1503,
+0xF7FA000F, 0x01FAF0F5, 0xEAEEFE05, 0xF8FBFC10, 0x100B0600, 0x13050501, 0xFA15F216, 0xFD0F13F4,
+0x030B04F8, 0xFA0FF1FD, 0x12F80BF4, 0x0A080204, 0x0701FA03, 0x17EEFAF7
+
+basegraph=
+1
+
+z_c=
+176
+
+n_cb=
+11616
+
+q_m=
+2
+
+n_filler=
+8
+
+e=
+4640
+
+rv_index=
+3
+
+code_block_mode=
+1
+
+iter_max=
+20
+
+expected_iter_count=
+3
+
+op_flags=
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE
+
+expected_status=
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v11835.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v11835.data
new file mode 100644
index 000000000..84a04e11c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v11835.data
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x817F7F81, 0x817F817F, 0x7F818181, 0x7F818181, 0x7F817F81, 0x7F7F8181, 0x817F7F7F, 0x81817F81,
+0x7F7F6B7F, 0x7F7F817F, 0x7F7F8181, 0x817F8181, 0x81817F7F, 0x7F818192, 0x7F81817F, 0x817F7F7F,
+0x8181
+
+output0 =
+0x44FB08C0, 0x661CCC
+
+basegraph=
+2
+
+z_c=
+10
+
+n_cb=
+500
+
+q_m=
+6
+
+n_filler=
+44
+
+e=
+66
+
+rv_index=
+0
+
+code_block_mode=
+1
+
+iter_max=
+20
+
+expected_iter_count=
+4
+
+op_flags=
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE
+
+expected_status=
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v2342_drop.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v2342_drop.data
new file mode 100644
index 000000000..f30726e46
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v2342_drop.data
@@ -0,0 +1,745 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x7F817F81, 0x817F7F81, 0x8181817F, 0x7F817F81, 0x7F818181, 0x7F81817F, 0x7F817F81, 0x817F8181,
+0x817F8181, 0x817F8181, 0x7F818181, 0x81817F81, 0x81817F81, 0x7F7F817F, 0x817F7F7F, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F817F, 0x7F81817F, 0x7F81817F, 0x7F818181, 0x8181817F, 0x8181817F, 0x7F7F817F,
+0x7F7F8181, 0x8181817F, 0x817F7F7F, 0x81818181, 0x817F7F81, 0x7F7F817F, 0x7F818181, 0x81817F7F,
+0x7F7F7F7F, 0x7F7F817F, 0x7F7F8181, 0x81817F7F, 0x817F8181, 0x7F817F81, 0x7F7F817F, 0x7F7F7F81,
+0x7F7F7F81, 0x817F8181, 0x817F7F7F, 0x817F7F81, 0x7F817F7F, 0x7F7F8181, 0x817F7F7F, 0x7F818181,
+0x7F7F7F7F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F81, 0x81818181, 0x7F818181,
+0x817F8181, 0x7F818181, 0x7F817F81, 0x81817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F818181, 0x7F7F8181,
+0x81817F81, 0x8181817F, 0x7F7F817F, 0x7F817F81, 0x81817F7F, 0x817F7F7F, 0x81817F81, 0x81818181,
+0x7F7F8181, 0x81817F81, 0x81817F7F, 0x817F8181, 0x7F7F817F, 0x7F818181, 0x7F81817F, 0x81817F7F,
+0x7F817F7F, 0x81817F7F, 0x7F7F817F, 0x7F818181, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x81817F81, 0x81817F81, 0x7F817F7F, 0x81817F81, 0x817F7F7F, 0x817F817F, 0x7F7F7F81,
+0x7F817F81, 0x7F7F7F7F, 0x81817F7F, 0x8181817F, 0x81817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F7F,
+0x81817F7F, 0x7F7F7F81, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F81, 0x81817F81,
+0x7F817F7F, 0x7F81817F, 0x81817F81, 0x817F817F, 0x7F7F7F81, 0x817F8181, 0x81818181, 0x81817F81,
+0x7F818181, 0x817F7F81, 0x7F7F7F81, 0x7F817F7F, 0x81818181, 0x81818181, 0x817F7F7F, 0x81817F81,
+0x817F8181, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F817F, 0x7F817F7F, 0x7F81817F, 0x7F7F817F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x817F817F, 0x7F817F81, 0x817F7F81, 0x81818181, 0x8181817F,
+0x81817F81, 0x7F817F7F, 0x817F8181, 0x7F7F7F7F, 0x7F817F81, 0x7F7F817F, 0x7F81817F, 0x817F8181,
+0x817F7F81, 0x817F817F, 0x817F817F, 0x81817F7F, 0x7F818181, 0x817F7F7F, 0x81817F7F, 0x7F7F7F81,
+0x8181817F, 0x817F7F81, 0x7F817F81, 0x81817F7F, 0x7F7F8181, 0x817F7F7F, 0x817F7F81, 0x7F7F817F,
+0x7F81817F, 0x7F81817F, 0x817F8181, 0x7F81817F, 0x81817F7F, 0x7F818181, 0x7F817F7F, 0x7F7F817F,
+0x81817F81, 0x81817F7F, 0x817F817F, 0x817F817F, 0x8181817F, 0x7F817F7F, 0x81817F7F, 0x7F818181,
+0x817F8181, 0x81817F81, 0x8181817F, 0x7F7F7F81, 0x81817F81, 0x81817F7F, 0x8181817F, 0x817F8181,
+0x8181817F, 0x8181817F, 0x817F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F818181, 0x7F817F81, 0x81817F7F,
+0x817F7F81, 0x817F7F7F, 0x8181817F, 0x7F817F7F, 0x817F7F7F, 0x81817F7F, 0x7F818181, 0x7F7F7F7F,
+0x7F817F81, 0x7F7F8181, 0x817F817F, 0x7F7F7F7F, 0x817F8181, 0x81817F81, 0x7F7F817F, 0x7F817F7F,
+0x817F7F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F817F7F, 0x817F8181, 0x7F818181, 0x81817F81,
+0x7F7F817F, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x817F817F, 0x7F7F8181, 0x7F817F81,
+0x7F818181, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x81817F7F, 0x817F8181, 0x7F817F7F, 0x7F817F7F,
+0x7F7F8181, 0x81818181, 0x817F8181, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F81,
+0x8181817F, 0x8181817F, 0x8181817F, 0x817F817F, 0x7F817F7F, 0x7F818181, 0x7F817F81, 0x7F817F81,
+0x7F7F8181, 0x817F817F, 0x81817F7F, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x817F817F, 0x7F7F7F7F,
+0x817F817F, 0x8181817F, 0x7F7F7F81, 0x817F817F, 0x81817F7F, 0x7F7F8181, 0x817F817F, 0x7F818181,
+0x7F7F7F81, 0x81818181, 0x7F818181, 0x7F7F8181, 0x817F8181, 0x817F8181, 0x7F81817F, 0x81817F7F,
+0x81818181, 0x7F7F7F81, 0x817F817F, 0x7F81817F, 0x7F817F81, 0x7F817F7F, 0x7F7F817F, 0x817F7F81,
+0x817F817F, 0x7F81817F, 0x81818181, 0x817F8181, 0x7F817F81, 0x81817F81, 0x7F7F817F, 0x817F7F7F,
+0x817F8181, 0x8181817F, 0x7F817F81, 0x7F7F817F, 0x8181817F, 0x7F81817F, 0x7F818181, 0x81817F81,
+0x8181817F, 0x7F7F8181, 0x817F7F81, 0x7F7F8181, 0x7F7F817F, 0x7F818181, 0x7F7F817F, 0x81818181,
+0x81817F7F, 0x817F7F81, 0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x81817F7F, 0x817F817F,
+0x7F817F81, 0x7F7F7F7F, 0x817F7F81, 0x817F8181, 0x7F7F7F7F, 0x81818181, 0x817F817F, 0x81817F7F,
+0x81817F7F, 0x7F817F7F, 0x7F7F7F7F, 0x7F818181, 0x817F8181, 0x7F817F7F, 0x81818181, 0x81818181,
+0x7F81817F, 0x81817F7F, 0x8181817F, 0x817F7F81, 0x817F817F, 0x81818181, 0x81817F7F, 0x817F7F81,
+0x81818181, 0x8181817F, 0x81817F81, 0x81817F7F, 0x7F7F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F8181,
+0x7F7F8181, 0x8181817F, 0x7F817F7F, 0x817F7F81, 0x81817F81, 0x7F7F8181, 0x817F8181, 0x81817F7F,
+0x7F7F7F7F, 0x81818181, 0x817F8181, 0x817F7F81, 0x7F81817F, 0x7F818181, 0x7F7F817F, 0x817F8181,
+0x817F817F, 0x7F7F7F81, 0x7F818181, 0x81818181, 0x7F7F8181, 0x817F7F81, 0x7F7F8181, 0x817F7F7F,
+0x817F7F7F, 0x81817F7F, 0x7F7F817F, 0x7F817F81, 0x817F7F81, 0x817F8181, 0x817F7F81, 0x81817F81,
+0x7F81817F, 0x7F818181, 0x81818181, 0x81817F7F, 0x8181817F, 0x81817F81, 0x7F7F817F, 0x817F7F7F,
+0x817F8181, 0x7F7F7F81, 0x81818181, 0x817F8181, 0x81817F81, 0x817F817F, 0x817F7F7F, 0x81817F81,
+0x7F817F7F, 0x7F7F7F81, 0x81817F7F, 0x81818181, 0x8181817F, 0x817F7F81, 0x8181817F, 0x7F817F7F,
+0x7F817F81, 0x817F817F, 0x8181817F, 0x81818181, 0x7F817F7F, 0x817F7F81, 0x7F817F7F, 0x81818181,
+0x7F7F7F81, 0x7F7F7F81, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x7F817F81, 0x7F817F7F, 0x7F7F7F7F,
+0x81817F7F, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F81,
+0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81, 0x7F818181, 0x7F7F7F81, 0x8181817F, 0x7F7F7F81, 0x8181817F,
+0x817F7F81, 0x817F8181, 0x7F7F817F, 0x81818181, 0x7F7F7F7F, 0x7F817F7F, 0x81817F7F, 0x81817F7F,
+0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x7F7F7F81, 0x817F817F, 0x817F7F7F, 0x7F818181, 0x7F81817F,
+0x7F81817F, 0x7F818181, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F817F81, 0x817F817F, 0x7F81817F,
+0x7F81817F, 0x7F7F817F, 0x7F7F7F7F, 0x81817F81, 0x81817F7F, 0x817F8181, 0x7F818181, 0x7F7F8181,
+0x7F817F81, 0x7F818181, 0x817F817F, 0x7F817F81, 0x817F817F, 0x817F7F7F, 0x7F7F8181, 0x81817F81,
+0x7F7F8181, 0x817F8181, 0x817F7F81, 0x7F818181, 0x7F817F7F, 0x81817F81, 0x7F818181, 0x7F7F817F,
+0x817F8181, 0x817F7F7F, 0x81817F81, 0x7F7F7F7F, 0x7F818181, 0x7F817F7F, 0x7F817F7F, 0x7F817F81,
+0x7F817F7F, 0x7F7F7F81, 0x817F7F81, 0x7F817F81, 0x7F81817F, 0x817F817F, 0x7F7F8181, 0x817F8181,
+0x817F8181, 0x7F7F7F81, 0x7F818181, 0x7F7F817F, 0x817F8181, 0x817F817F, 0x7F7F7F81, 0x81817F81,
+0x817F8181, 0x7F81817F, 0x7F7F7F81, 0x817F8181, 0x7F81817F, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x81817F81, 0x817F7F7F, 0x7F7F7F81, 0x817F8181, 0x7F7F8181, 0x81818181, 0x817F7F7F, 0x7F7F817F,
+0x81817F81, 0x7F81817F, 0x7F817F7F, 0x81817F81, 0x81818181, 0x7F7F7F81, 0x7F818181, 0x817F7F81,
+0x7F817F81, 0x7F7F817F, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x817F817F, 0x817F817F,
+0x7F7F7F81, 0x7F7F8181, 0x817F7F81, 0x81818181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81,
+0x7F817F7F, 0x81817F7F, 0x7F81817F, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F, 0x817F7F7F, 0x817F817F,
+0x7F817F7F, 0x8181817F, 0x817F8181, 0x81817F81, 0x81817F7F, 0x8181817F, 0x7F81817F, 0x7F7F7F7F,
+0x7F817F81, 0x7F817F81, 0x7F817F81, 0x81817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F817F7F, 0x7F81817F,
+0x7F7F8181, 0x7F81817F, 0x7F7F817F, 0x7F817F81, 0x817F8181, 0x7F7F8181, 0x81818181, 0x7F7F7F81,
+0x7F7F8181, 0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x81817F7F, 0x7F7F817F, 0x817F817F, 0x81817F7F,
+0x817F817F, 0x817F817F, 0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x7F81817F, 0x8181817F, 0x81817F81,
+0x7F7F7F7F, 0x817F817F, 0x7F81817F, 0x817F8181, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x81817F81,
+0x81817F81, 0x7F817F81, 0x7F817F81, 0x817F7F7F, 0x81818181, 0x8181817F, 0x7F7F7F81, 0x817F7F81,
+0x7F7F7F7F, 0x7F81817F, 0x817F7F81, 0x7F81817F, 0x7F7F7F7F, 0x7F81817F, 0x7F7F8181, 0x81817F81,
+0x817F7F7F, 0x7F817F81, 0x817F8181, 0x8181817F, 0x8181817F, 0x7F817F7F, 0x7F81817F, 0x817F817F,
+0x7F818181, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x817F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F7F7F,
+0x81817F7F, 0x81817F81, 0x817F7F81, 0x817F7F7F, 0x817F817F, 0x81817F7F, 0x817F8181, 0x81817F7F,
+0x81817F81, 0x817F8181, 0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x81818181, 0x817F7F7F, 0x7F817F7F,
+0x7F817F81, 0x81817F7F, 0x7F818181, 0x7F817F7F, 0x81817F81, 0x7F7F8181, 0x7F7F7F81, 0x81817F7F,
+0x7F81817F, 0x7F81817F, 0x817F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F818181, 0x7F7F7F7F,
+0x7F7F7F81, 0x81818181, 0x7F81817F, 0x7F7F7F7F, 0x8181817F, 0x7F818181, 0x817F7F81, 0x7F818181,
+0x8181817F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F, 0x817F817F,
+0x7F7F817F, 0x7F817F7F, 0x817F8181, 0x817F8181, 0x7F7F817F, 0x7F817F81, 0x817F7F7F, 0x7F7F7F81,
+0x817F7F81, 0x81817F81, 0x7F7F817F, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x817F8181, 0x7F7F817F,
+0x817F7F7F, 0x81818181, 0x7F7F7F81, 0x7F81817F, 0x7F7F7F81, 0x817F8181, 0x8181817F, 0x7F817F81,
+0x81817F81, 0x7F7F7F81, 0x8181817F, 0x7F817F81, 0x7F7F8181, 0x817F7F81, 0x817F817F, 0x7F7F817F,
+0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F81,
+0x81817F7F, 0x7F817F81, 0x7F818181, 0x7F7F7F7F, 0x81817F7F, 0x817F8181, 0x817F8181, 0x81818181,
+0x817F7F7F, 0x7F818181, 0x81817F7F, 0x817F7F7F, 0x8181817F, 0x7F818181, 0x81817F81, 0x817F7F81,
+0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x81818181, 0x7F817F7F, 0x7F817F81, 0x81817F81, 0x81817F81,
+0x817F817F, 0x81817F81, 0x7F7F7F81, 0x817F8181, 0x7F817F81, 0x7F7F8181, 0x817F817F, 0x81817F7F,
+0x817F8181, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x7F7F7F81,
+0x817F7F81, 0x817F817F, 0x817F8181, 0x817F8181, 0x7F7F817F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81,
+0x7F817F81, 0x7F81817F, 0x7F818181, 0x7F817F81, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F7F817F, 0x81818181, 0x817F817F, 0x817F7F7F, 0x7F7F8181, 0x81817F7F, 0x81817F81,
+0x7F81817F, 0x81818181, 0x81817F7F, 0x817F7F7F, 0x81817F81, 0x7F818181, 0x817F8181, 0x81817F7F,
+0x7F81817F, 0x7F7F817F, 0x81817F7F, 0x7F7F8181, 0x817F7F7F, 0x817F8181, 0x817F7F81, 0x81817F81,
+0x7F81817F, 0x7F7F7F81, 0x7F817F81, 0x7F817F7F, 0x81818181, 0x7F7F817F, 0x7F7F7F81, 0x7F818181,
+0x7F817F81, 0x817F8181, 0x7F7F8181, 0x817F7F81, 0x7F7F8181, 0x81817F81, 0x81818181, 0x7F817F81,
+0x81817F7F, 0x81818181, 0x7F7F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F81817F, 0x817F8181, 0x7F7F8181,
+0x817F8181, 0x817F7F7F, 0x7F818181, 0x81817F7F, 0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x7F7F7F81,
+0x7F817F81, 0x817F7F7F, 0x7F818181, 0x81817F7F, 0x81818181, 0x81817F7F, 0x817F7F81, 0x7F817F7F,
+0x7F817F81, 0x7F7F8181, 0x7F817F7F, 0x817F7F7F, 0x7F7F8181, 0x817F7F7F, 0x817F7F7F, 0x7F818181,
+0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x81818181, 0x8181817F, 0x7F7F817F, 0x7F817F81, 0x7F81817F,
+0x7F818181, 0x81818181, 0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x7F7F8181, 0x7F81817F, 0x7F817F81,
+0x7F7F8181, 0x7F7F7F7F, 0x817F7F7F, 0x817F8181, 0x7F81817F, 0x7F7F817F, 0x7F7F7F7F, 0x81818181,
+0x7F7F8181, 0x81817F7F, 0x81817F81, 0x817F7F81, 0x7F7F8181, 0x7F817F81, 0x7F7F817F, 0x7F817F7F,
+0x817F8181, 0x817F8181, 0x81817F7F, 0x7F81817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F818181, 0x7F7F7F7F,
+0x7F7F7F81, 0x817F7F7F, 0x817F7F81, 0x81817F7F, 0x8181817F, 0x81817F7F, 0x817F7F81, 0x8181817F,
+0x7F7F7F7F, 0x7F7F817F, 0x7F817F81, 0x81817F7F, 0x7F7F817F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81,
+0x81817F81, 0x8181817F, 0x817F7F81, 0x7F817F81, 0x817F7F81, 0x7F818181, 0x817F7F81, 0x7F817F7F,
+0x8181817F, 0x81818181, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x7F7F7F7F,
+0x817F7F7F, 0x81818181, 0x817F817F, 0x81818181, 0x7F817F7F, 0x817F8181, 0x7F7F7F81, 0x817F7F81,
+0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F, 0x8181817F, 0x817F7F7F, 0x7F7F7F7F, 0x81818181,
+0x817F817F, 0x7F7F7F81, 0x7F817F81, 0x7F817F81, 0x7F7F817F, 0x817F817F, 0x817F8181, 0x81817F7F,
+0x7F7F8181, 0x7F7F817F, 0x817F7F7F, 0x817F817F, 0x817F7F81, 0x7F817F7F, 0x81818181, 0x81817F7F,
+0x817F817F, 0x817F7F7F, 0x7F7F7F7F, 0x81817F81, 0x7F817F81, 0x81817F81, 0x81817F81, 0x7F7F8181,
+0x81817F81, 0x7F7F7F7F, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x7F818181, 0x817F7F7F, 0x7F818181,
+0x8181817F, 0x817F7F7F, 0x817F817F, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F81817F, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F7F81, 0x817F8181, 0x8181817F, 0x817F7F81, 0x7F817F81, 0x81817F81, 0x81817F7F,
+0x8181817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x81818181, 0x8181817F, 0x7F817F7F, 0x81818181,
+0x7F818181, 0x817F817F, 0x817F7F7F, 0x81818181, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F7F7F,
+0x7F7F8181, 0x7F7F7F7F, 0x817F7F81, 0x817F817F, 0x817F7F7F, 0x7F817F81, 0x81817F81, 0x7F7F817F,
+0x8181817F, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F7F, 0x817F8181, 0x81817F81, 0x7F7F7F7F, 0x817F7F7F,
+0x7F81817F, 0x7F7F817F, 0x81818181, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x7F817F81, 0x7F7F817F,
+0x817F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F, 0x817F7F7F,
+0x7F817F7F, 0x81817F81, 0x7F7F817F, 0x81818181, 0x7F818181, 0x7F817F7F, 0x7F818181, 0x81817F81,
+0x81818181, 0x7F7F7F7F, 0x81818181, 0x81818181, 0x7F81817F, 0x81817F81, 0x7F7F7F7F, 0x7F7F7F81,
+0x7F7F817F, 0x7F7F7F7F, 0x817F8181, 0x7F818181, 0x7F81817F, 0x7F81817F, 0x8181817F, 0x81817F81,
+0x817F8181, 0x7F81817F, 0x7F81817F, 0x817F817F, 0x81818181, 0x7F81817F, 0x81818181, 0x81818181,
+0x817F7F81, 0x7F817F7F, 0x7F7F817F, 0x8181817F, 0x81817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F81,
+0x7F7F7F7F, 0x7F81817F, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x817F8181,
+0x81818181, 0x7F7F7F7F, 0x817F7F81, 0x81817F81, 0x817F7F7F, 0x81817F81, 0x7F7F8181, 0x7F7F817F,
+0x81817F81, 0x7F817F81, 0x7F7F817F, 0x8181817F, 0x817F7F81, 0x81817F7F, 0x7F7F8181, 0x8181817F,
+0x817F7F81, 0x7F81817F, 0x7F817F81, 0x81817F7F, 0x7F7F817F, 0x817F7F81, 0x7F81817F, 0x817F7F81,
+0x7F7F817F, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x817F7F81, 0x7F818181, 0x7F817F7F, 0x8181817F,
+0x81817F7F, 0x81817F7F, 0x81817F81, 0x817F817F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F,
+0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x7F817F7F, 0x81817F81, 0x81817F7F, 0x7F818181, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F817F, 0x81817F7F, 0x7F818181, 0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81,
+0x8181817F, 0x7F7F817F, 0x817F817F, 0x7F7F8181, 0x817F7F81, 0x7F7F817F, 0x81817F7F, 0x817F8181,
+0x817F8181, 0x7F7F7F81, 0x8181817F, 0x817F817F, 0x81817F81, 0x817F8181, 0x7F7F817F, 0x817F7F81,
+0x7F817F81, 0x7F7F7F7F, 0x81817F7F, 0x817F7F7F, 0x817F8181, 0x8181817F, 0x81817F81, 0x7F817F81,
+0x7F817F81, 0x81817F81, 0x7F817F81, 0x81818181, 0x81817F81, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F81,
+0x7F7F7F7F, 0x81817F7F, 0x81817F81, 0x817F7F81, 0x7F7F7F81, 0x81817F7F, 0x7F7F817F, 0x81817F7F,
+0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F81817F, 0x7F81817F, 0x817F7F81, 0x7F7F7F81, 0x7F817F81,
+0x817F817F, 0x7F7F7F81, 0x817F7F81, 0x817F7F81, 0x7F7F7F7F, 0x81817F81, 0x817F7F7F, 0x8181817F,
+0x81817F81, 0x7F81817F, 0x8181817F, 0x7F817F81, 0x81817F7F, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F81,
+0x7F81817F, 0x81817F7F, 0x8181817F, 0x7F7F817F, 0x7F81817F, 0x7F817F7F, 0x81817F7F, 0x81817F81,
+0x7F818181, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F7F, 0x81817F81,
+0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x817F8181, 0x7F7F7F81,
+0x7F818181, 0x8181817F, 0x817F7F7F, 0x817F7F81, 0x81817F7F, 0x7F817F7F, 0x8181817F, 0x7F817F7F,
+0x8181817F, 0x7F7F7F7F, 0x817F817F, 0x7F7F817F, 0x7F81817F, 0x7F818181, 0x7F7F817F, 0x81818181,
+0x817F7F81, 0x7F817F7F, 0x7F7F8181, 0x81818181, 0x81818181, 0x81817F7F, 0x7F818181, 0x7F7F817F,
+0x7F7F7F81, 0x7F817F81, 0x7F7F8181, 0x7F7F8181, 0x7F817F81, 0x7F817F81, 0x81817F7F, 0x8181817F,
+0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x817F817F, 0x7F818181, 0x7F7F817F, 0x7F817F81, 0x7F7F817F,
+0x81817F7F, 0x817F7F81, 0x817F8181, 0x7F817F81, 0x7F7F817F, 0x817F8181, 0x7F818181, 0x7F7F817F,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x7F81817F, 0x817F7F81, 0x7F81817F, 0x7F7F7F81,
+0x7F7F817F, 0x8181817F, 0x81817F7F, 0x7F7F8181, 0x817F7F7F, 0x7F7F817F, 0x81817F7F, 0x81817F7F,
+0x81817F7F, 0x7F7F7F81, 0x7F818181, 0x7F7F817F, 0x7F81817F, 0x7F818181, 0x817F7F81, 0x7F817F81,
+0x7F817F7F, 0x81817F7F, 0x7F7F7F7F, 0x81818181, 0x7F817F81, 0x7F7F7F7F, 0x817F817F, 0x81818181,
+0x7F7F817F, 0x7F7F7F81, 0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x7F818181, 0x817F8181, 0x7F817F7F,
+0x817F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x817F8181, 0x7F7F7F7F, 0x817F7F81, 0x7F7F817F, 0x7F81817F,
+0x7F817F81, 0x7F818181, 0x817F7F81, 0x817F7F7F, 0x817F817F, 0x7F7F817F, 0x817F8181, 0x7F818181,
+0x81817F7F, 0x7F818181, 0x7F7F7F81, 0x817F817F, 0x8181817F, 0x817F8181, 0x7F7F817F, 0x817F7F7F,
+0x81817F7F, 0x817F7F7F, 0x81817F81, 0x8181817F, 0x7F7F7F7F, 0x8181817F, 0x7F7F8181, 0x7F81817F,
+0x7F7F8181, 0x81818181, 0x817F8181, 0x7F7F8181, 0x817F8181, 0x8181817F, 0x8181817F, 0x817F7F81,
+0x7F7F7F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F7F, 0x7F7F7F7F, 0x817F7F7F, 0x81817F7F,
+0x7F818181, 0x817F7F81, 0x81817F81, 0x817F817F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x8181817F,
+0x7F818181, 0x7F817F81, 0x7F817F7F, 0x817F817F, 0x817F7F81, 0x817F817F, 0x81817F81, 0x817F817F,
+0x7F817F81, 0x817F817F, 0x7F81817F, 0x7F81817F, 0x8181817F, 0x81817F81, 0x7F818181, 0x7F7F817F,
+0x7F817F81, 0x81817F81, 0x7F817F81, 0x7F817F81, 0x7F817F7F, 0x817F817F, 0x81817F81, 0x817F7F7F,
+0x7F7F7F7F, 0x8181817F, 0x81818181, 0x7F818181, 0x7F7F8181, 0x7F7F8181, 0x7F817F7F, 0x7F7F7F7F,
+0x7F818181, 0x7F7F7F81, 0x81818181, 0x7F7F817F, 0x81818181, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F,
+0x7F817F7F, 0x81817F81, 0x81817F81, 0x817F8181, 0x7F7F817F, 0x7F7F817F, 0x7F7F8181, 0x81818181,
+0x7F7F7F81, 0x817F8181, 0x817F8181, 0x817F817F, 0x7F81817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F817F,
+0x81817F7F, 0x81817F81, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F7F7F7F,
+0x817F7F7F, 0x7F817F7F, 0x7F817F81, 0x8181817F, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x7F817F7F, 0x7F817F7F, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x81818181, 0x7F818181,
+0x817F7F7F, 0x8181817F, 0x81817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F817F7F, 0x817F7F7F, 0x817F817F,
+0x817F7F81, 0x817F8181, 0x7F818181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F7F, 0x8181817F, 0x7F817F81,
+0x817F817F, 0x817F7F81, 0x7F7F817F, 0x7F81817F, 0x81817F81, 0x7F7F817F, 0x7F7F817F, 0x817F7F81,
+0x817F817F, 0x7F7F817F, 0x7F817F81, 0x7F818181, 0x81818181, 0x81817F7F, 0x81817F81, 0x817F7F81,
+0x81817F81, 0x7F7F8181, 0x8181817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F817F, 0x7F817F81, 0x81818181,
+0x7F81817F, 0x817F8181, 0x817F7F7F, 0x7F817F81, 0x7F817F81, 0x81818181, 0x8181817F, 0x817F7F81,
+0x817F817F, 0x817F7F81, 0x81817F81, 0x7F817F81, 0x81817F7F, 0x7F7F7F7F, 0x8181817F, 0x7F7F817F,
+0x817F7F7F, 0x7F7F8181, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x7F818181, 0x7F817F81,
+0x8181817F, 0x817F8181, 0x7F817F7F, 0x817F8181, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x81817F7F,
+0x817F8181, 0x7F7F8181, 0x7F818181, 0x817F7F7F, 0x81818181, 0x817F7F7F, 0x817F7F7F, 0x7F818181,
+0x7F7F8181, 0x7F7F7F81, 0x81818181, 0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x81818181, 0x817F817F,
+0x8181817F, 0x7F818181, 0x81817F81, 0x7F7F7F7F, 0x81818181, 0x8181817F, 0x7F7F7F81, 0x7F7F7F7F,
+0x81817F81, 0x81817F81, 0x7F81817F, 0x7F818181, 0x817F817F, 0x81817F7F, 0x7F7F8181, 0x817F7F7F,
+0x817F7F7F, 0x817F8181, 0x81817F81, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x817F817F, 0x7F7F7F81,
+0x81817F7F, 0x7F7F8181, 0x7F7F7F81, 0x7F817F7F, 0x7F817F81, 0x81818181, 0x817F7F7F, 0x7F7F7F7F,
+0x8181817F, 0x817F7F7F, 0x7F817F81, 0x817F817F, 0x7F7F7F7F, 0x7F818181, 0x81817F7F, 0x817F7F81,
+0x7F7F7F7F, 0x7F817F7F, 0x7F7F8181, 0x81817F7F, 0x817F817F, 0x7F7F817F, 0x8181817F, 0x817F8181,
+0x81817F81, 0x7F818181, 0x7F818181, 0x7F7F8181, 0x7F7F817F, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F,
+0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81, 0x7F7F8181, 0x81817F7F, 0x7F81817F,
+0x7F818181, 0x7F818181, 0x7F817F7F, 0x81817F81, 0x81817F81, 0x8181817F, 0x81817F7F, 0x7F7F7F81,
+0x817F7F81, 0x7F7F7F81, 0x817F817F, 0x81818181, 0x81817F7F, 0x7F7F8181, 0x7F7F7F81, 0x81817F7F,
+0x7F81817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F, 0x7F818181,
+0x817F8181, 0x7F817F7F, 0x81817F81, 0x7F7F7F7F, 0x7F7F817F, 0x7F817F7F, 0x817F817F, 0x8181817F,
+0x81817F81, 0x7F7F7F81, 0x81818181, 0x7F7F7F7F, 0x81818181, 0x817F817F, 0x7F817F81, 0x7F7F7F81,
+0x817F817F, 0x817F8181, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x7F7F817F, 0x817F7F81, 0x817F7F7F,
+0x7F7F7F7F, 0x7F7F7F81, 0x7F817F81, 0x817F7F81, 0x817F7F81, 0x7F817F7F, 0x8181817F, 0x81817F7F,
+0x7F7F8181, 0x7F7F7F7F, 0x817F8181, 0x81817F81, 0x8181817F, 0x817F817F, 0x81817F7F, 0x817F7F7F,
+0x8181817F, 0x7F7F8181, 0x7F817F7F, 0x81818181, 0x7F817F81, 0x7F817F81, 0x7F817F7F, 0x817F7F81,
+0x8181817F, 0x81817F7F, 0x7F818181, 0x817F8181, 0x81817F7F, 0x81818181, 0x81818181, 0x817F817F,
+0x7F81817F, 0x81817F81, 0x7F817F7F, 0x81817F7F, 0x7F7F817F, 0x817F7F7F, 0x81818181, 0x7F818181,
+0x7F818181, 0x7F7F8181, 0x7F7F817F, 0x8181817F, 0x817F7F7F, 0x7F818181, 0x7F7F7F7F, 0x817F7F81,
+0x7F7F817F, 0x8181817F, 0x817F817F, 0x7F81817F, 0x817F7F7F, 0x817F7F81, 0x817F8181, 0x7F817F7F,
+0x81817F81, 0x817F817F, 0x7F817F81, 0x7F7F7F81, 0x7F817F81, 0x7F818181, 0x7F7F8181, 0x7F817F81,
+0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x817F817F, 0x817F8181, 0x817F7F81, 0x7F7F7F7F, 0x7F818181,
+0x817F817F, 0x7F81817F, 0x8181817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F7F, 0x81818181, 0x817F817F,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F81, 0x8181817F, 0x7F7F7F81, 0x81817F7F, 0x81818181, 0x817F7F7F,
+0x7F818181, 0x7F818181, 0x7F818181, 0x7F7F7F81, 0x81818181, 0x81818181, 0x817F7F7F, 0x7F81817F,
+0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x7F7F7F81, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x7F817F7F,
+0x7F817F81, 0x81818181, 0x81818181, 0x7F7F8181, 0x7F818181, 0x7F7F817F, 0x7F7F8181, 0x817F817F,
+0x7F7F817F, 0x81817F81, 0x7F7F817F, 0x7F7F8181, 0x7F7F8181, 0x7F817F7F, 0x7F817F7F, 0x8181817F,
+0x7F7F7F81, 0x7F818181, 0x817F7F81, 0x7F818181, 0x7F818181, 0x7F7F7F81, 0x81817F7F, 0x817F8181,
+0x7F7F8181, 0x7F81817F, 0x7F817F81, 0x817F8181, 0x7F81817F, 0x7F7F817F, 0x817F817F, 0x7F7F817F,
+0x817F7F81, 0x81817F7F, 0x7F7F7F81, 0x7F7F817F, 0x817F817F, 0x7F7F8181, 0x7F7F7F81, 0x7F81817F,
+0x817F7F81, 0x8181817F, 0x7F817F7F, 0x7F81817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F817F, 0x817F7F7F,
+0x8181817F, 0x817F817F, 0x7F817F7F, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x817F8181, 0x817F817F,
+0x81818181, 0x8181817F, 0x8181817F, 0x7F817F81, 0x817F7F7F, 0x7F81817F, 0x7F7F817F, 0x817F7F81,
+0x817F817F, 0x7F7F8181, 0x7F817F81, 0x7F7F817F, 0x817F7F7F, 0x7F817F81, 0x7F818181, 0x817F8181,
+0x817F7F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F81, 0x7F817F7F, 0x7F817F81, 0x7F81817F,
+0x7F817F81, 0x817F7F81, 0x7F81817F, 0x81817F81, 0x8181817F, 0x8181817F, 0x81817F81, 0x817F7F7F,
+0x81817F81, 0x7F81817F, 0x7F817F7F, 0x817F7F81, 0x7F817F7F, 0x817F7F7F, 0x817F7F81, 0x81818181,
+0x8181817F, 0x817F8181, 0x7F7F817F, 0x817F7F7F, 0x817F7F7F, 0x7F7F8181, 0x7F81817F, 0x817F7F7F,
+0x81817F81, 0x7F81817F, 0x7F818181, 0x7F7F7F81, 0x8181817F, 0x7F817F7F, 0x81817F7F, 0x81817F81,
+0x7F817F7F, 0x7F817F7F, 0x817F8181, 0x81817F81, 0x7F817F81, 0x8181817F, 0x817F7F7F, 0x7F817F81,
+0x7F7F7F7F, 0x7F818181, 0x81818181, 0x7F7F817F, 0x7F817F81, 0x817F8181, 0x81818181, 0x7F7F817F,
+0x81818181, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x7F7F817F, 0x81817F81, 0x7F817F81, 0x7F817F7F,
+0x817F7F81, 0x817F8181, 0x817F817F, 0x81818181, 0x817F817F, 0x7F7F8181, 0x81818181, 0x7F817F7F,
+0x8181817F, 0x7F818181, 0x7F7F7F7F, 0x7F7F817F, 0x7F817F7F, 0x7F7F8181, 0x7F818181, 0x817F817F,
+0x7F817F7F, 0x7F81817F, 0x817F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F7F8181, 0x81817F7F, 0x81817F81,
+0x7F818181, 0x7F7F817F, 0x7F81817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x8181817F, 0x7F7F817F, 0x7F7F8181,
+0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x7F7F8181, 0x7F7F7F7F, 0x7F817F7F, 0x8181817F, 0x81817F7F,
+0x817F8181, 0x7F7F7F81, 0x8181817F, 0x8181817F, 0x817F817F, 0x817F7F81, 0x817F7F7F, 0x81818181,
+0x817F7F81, 0x817F8181, 0x817F7F81, 0x8181817F, 0x7F817F81, 0x81818181, 0x7F81817F, 0x7F7F8181,
+0x817F7F81, 0x81818181, 0x8181817F, 0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x7F818181, 0x81818181,
+0x7F81817F, 0x7F817F81, 0x817F7F81, 0x81818181, 0x817F7F7F, 0x7F817F7F, 0x8181817F, 0x7F7F7F7F,
+0x7F7F8181, 0x817F8181, 0x7F817F7F, 0x817F7F7F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181,
+0x8181817F, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x817F817F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81,
+0x7F818181, 0x817F817F, 0x7F817F7F, 0x7F7F817F, 0x7F818181, 0x81817F81, 0x7F7F8181, 0x81817F7F,
+0x7F817F7F, 0x7F7F7F81, 0x817F8181, 0x7F81817F, 0x7F818181, 0x7F818181, 0x7F818181, 0x7F7F817F,
+0x8181817F, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x817F7F81, 0x7F7F7F7F, 0x817F7F81, 0x81818181,
+0x817F7F81, 0x7F7F7F81, 0x7F7F7F7F, 0x81817F7F, 0x7F81817F, 0x7F7F7F81, 0x81818181, 0x817F8181,
+0x817F7F81, 0x7F817F7F, 0x817F8181, 0x81818181, 0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x7F7F8181,
+0x7F7F817F, 0x8181817F, 0x7F817F81, 0x817F7F7F, 0x7F817F7F, 0x817F8181, 0x81818181, 0x817F7F81,
+0x7F7F8181, 0x81817F7F, 0x7F7F8181, 0x8181817F, 0x81818181, 0x8181817F, 0x81817F81, 0x7F817F7F,
+0x81817F81, 0x7F81817F, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F, 0x817F817F, 0x817F817F, 0x817F7F81,
+0x8181817F, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x81818181, 0x7F7F7F81, 0x7F7F817F, 0x817F8181,
+0x817F817F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x817F8181, 0x7F817F7F, 0x8181817F,
+0x817F7F81, 0x7F81817F, 0x817F8181, 0x7F817F81, 0x81817F7F, 0x7F817F7F, 0x81817F81, 0x7F818181,
+0x8181817F, 0x81818181, 0x7F7F817F, 0x7F7F8181, 0x81817F7F, 0x7F7F8181, 0x8181817F, 0x7F817F81,
+0x7F817F7F, 0x81818181, 0x81817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F7F, 0x7F7F8181, 0x817F817F,
+0x7F81817F, 0x817F817F, 0x7F817F7F, 0x7F81817F, 0x817F7F7F, 0x81817F81, 0x7F81817F, 0x817F817F,
+0x817F7F81, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x817F817F, 0x81817F7F, 0x7F81817F,
+0x7F7F7F81, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x81817F81, 0x817F7F7F, 0x817F7F81, 0x7F7F7F81,
+0x7F818181, 0x7F7F7F7F, 0x817F817F, 0x7F817F81, 0x817F817F, 0x7F817F81, 0x817F7F7F, 0x8181817F,
+0x7F7F8181, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F7F8181, 0x7F817F7F, 0x81817F81, 0x7F818181,
+0x7F7F7F81, 0x8181817F, 0x81817F81, 0x7F81817F, 0x81818181, 0x7F81817F, 0x817F8181, 0x817F8181,
+0x7F818181, 0x7F81817F, 0x817F8181, 0x81817F81, 0x7F818181, 0x81817F7F, 0x7F7F817F, 0x817F7F81,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x8181817F, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F7F, 0x8181817F,
+0x7F81817F, 0x817F7F7F, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x7F81817F, 0x81817F7F,
+0x7F818181, 0x7F7F8181, 0x7F817F81, 0x7F817F81, 0x81818181, 0x817F8181, 0x7F7F7F7F, 0x817F817F,
+0x7F817F81, 0x7F7F817F, 0x81817F7F, 0x7F7F7F81, 0x8181817F, 0x7F7F8181, 0x81818181, 0x7F817F81,
+0x817F7F7F, 0x7F7F7F81, 0x81817F7F, 0x7F81817F, 0x7F818181, 0x817F7F81, 0x817F817F, 0x7F818181,
+0x7F817F7F, 0x81817F81, 0x7F7F7F81, 0x7F7F8181, 0x81817F81, 0x8181817F, 0x81818181, 0x7F7F7F81,
+0x81817F81, 0x8181817F, 0x81817F7F, 0x817F817F, 0x817F817F, 0x7F7F7F7F, 0x81817F81, 0x81817F81,
+0x7F7F8181, 0x7F7F7F81, 0x8181817F, 0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x8181817F, 0x7F818181,
+0x81817F7F, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x7F7F8181, 0x7F817F7F, 0x7F81817F, 0x7F7F8181,
+0x817F817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F8181, 0x817F8181, 0x7F7F817F, 0x81817F7F, 0x7F7F7F7F,
+0x817F817F, 0x81817F81, 0x7F7F7F7F, 0x7F81817F, 0x81817F81, 0x817F7F7F, 0x7F818181, 0x7F7F8181,
+0x7F81817F, 0x7F818181, 0x81817F81, 0x817F7F81, 0x7F7F7F7F, 0x7F817F81, 0x81817F81, 0x7F7F7F7F,
+0x8181817F, 0x7F818181, 0x7F7F8181, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x8181817F,
+0x7F7F7F7F, 0x81817F7F, 0x817F7F7F, 0x7F7F817F, 0x7F817F81, 0x7F81817F, 0x7F7F7F7F, 0x7F817F81,
+0x7F7F7F81, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x817F7F7F, 0x7F7F817F, 0x81818181, 0x817F817F,
+0x7F818181, 0x81817F81, 0x7F7F8181, 0x7F818181, 0x81818181, 0x81817F7F, 0x817F8181, 0x81817F81,
+0x7F7F8181, 0x817F7F7F, 0x7F817F81, 0x7F7F817F, 0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x7F817F7F,
+0x817F7F81, 0x817F7F7F, 0x817F7F7F, 0x7F81817F, 0x7F7F7F7F, 0x817F8181, 0x817F7F81, 0x7F817F81,
+0x817F817F, 0x7F7F7F7F, 0x817F8181, 0x81818181, 0x7F818181, 0x81817F7F, 0x7F7F7F7F, 0x8181817F,
+0x7F818181, 0x7F7F7F81, 0x8181817F, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F817F,
+0x81818181, 0x8181817F, 0x7F7F817F, 0x817F7F81, 0x81818181, 0x81817F7F, 0x817F7F81, 0x7F7F7F81,
+0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x817F7F7F, 0x817F817F, 0x817F817F, 0x7F7F8181, 0x817F7F7F,
+0x7F7F7F7F, 0x817F7F81, 0x8181817F, 0x817F7F7F, 0x8181817F, 0x817F8181, 0x7F81817F, 0x81818181,
+0x817F7F7F, 0x817F817F, 0x81817F81, 0x7F817F7F, 0x7F7F8181, 0x8181817F, 0x81818181, 0x7F81817F,
+0x7F7F817F, 0x7F818181, 0x7F7F7F81, 0x81817F81, 0x8181817F, 0x7F7F817F, 0x8181817F, 0x81817F7F,
+0x81818181, 0x81818181, 0x817F817F, 0x81817F81, 0x817F7F81, 0x81818181, 0x7F817F81, 0x81818181,
+0x7F818181, 0x7F81817F, 0x7F7F7F81, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x817F8181, 0x817F8181,
+0x7F817F81, 0x7F817F81, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F8181, 0x8181817F, 0x7F817F81, 0x817F7F81,
+0x817F8181, 0x7F817F81, 0x7F817F81, 0x7F7F817F, 0x7F81817F, 0x817F817F, 0x817F817F, 0x817F7F81,
+0x81817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x81818181, 0x7F817F7F, 0x7F817F81, 0x8181817F, 0x7F81817F,
+0x8181817F, 0x7F7F7F81, 0x8181817F, 0x817F817F, 0x7F817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F817F,
+0x7F81817F, 0x817F8181, 0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x817F7F81, 0x81817F81, 0x7F817F81,
+0x81817F81, 0x8181817F, 0x81817F81, 0x7F7F8181, 0x7F7F8181, 0x7F817F81, 0x7F817F7F, 0x7F7F8181,
+0x7F81817F, 0x817F817F, 0x8181817F, 0x7F7F7F7F, 0x7F817F7F, 0x7F818181, 0x817F7F81, 0x81817F7F,
+0x8181817F, 0x7F818181, 0x81818181, 0x81817F7F, 0x81818181, 0x81817F7F, 0x817F8181, 0x7F81817F,
+0x817F7F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F817F, 0x817F7F81, 0x81818181, 0x8181817F, 0x7F817F7F,
+0x7F7F7F7F, 0x8181817F, 0x7F818181, 0x81817F81, 0x7F818181, 0x7F817F81, 0x7F818181, 0x817F817F,
+0x817F7F81, 0x817F7F7F, 0x8181817F, 0x7F817F7F, 0x7F817F7F, 0x817F8181, 0x817F7F7F, 0x7F7F8181,
+0x7F7F8181, 0x817F7F81, 0x7F818181, 0x7F81817F, 0x7F818181, 0x817F817F, 0x7F7F7F7F, 0x8181817F,
+0x817F8181, 0x817F817F, 0x7F818181, 0x7F818181, 0x817F7F7F, 0x7F81817F, 0x7F7F8181, 0x7F817F81,
+0x7F7F7F81, 0x817F8181, 0x817F817F, 0x817F817F, 0x7F7F7F81, 0x7F7F7F81, 0x817F8181, 0x7F7F817F,
+0x7F818181, 0x81817F81, 0x817F7F7F, 0x817F7F7F, 0x817F817F, 0x7F7F8181, 0x7F817F7F, 0x81817F7F,
+0x7F7F8181, 0x7F817F81, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x81817F81, 0x817F817F, 0x8181817F,
+0x817F817F, 0x7F7F7F7F, 0x7F817F7F, 0x7F817F7F, 0x81817F7F, 0x817F817F, 0x7F817F81, 0x7F7F8181,
+0x817F817F, 0x81817F7F, 0x817F8181, 0x817F817F, 0x7F7F7F81, 0x81817F81, 0x7F7F7F81, 0x817F817F,
+0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F818181, 0x7F7F8181,
+0x81818181, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x81817F7F, 0x8181817F,
+0x7F817F7F, 0x81817F7F, 0x817F8181, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x7F81817F,
+0x7F7F7F81, 0x7F7F817F, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x7F7F817F, 0x817F7F7F, 0x7F7F817F,
+0x7F81817F, 0x817F817F, 0x81817F81, 0x7F818181, 0x7F81817F, 0x81818181, 0x7F817F7F, 0x7F7F7F81,
+0x7F818181, 0x817F7F81, 0x7F817F81, 0x817F7F7F, 0x81818181, 0x817F817F, 0x817F8181, 0x81818181,
+0x817F7F7F, 0x817F817F, 0x81817F81, 0x7F81817F, 0x7F817F81, 0x81817F81, 0x8181817F, 0x817F7F7F,
+0x817F7F7F, 0x8181817F, 0x817F7F7F, 0x7F817F7F, 0x81817F7F, 0x81817F7F, 0x7F817F81, 0x7F818181,
+0x7F817F81, 0x817F817F, 0x81817F7F, 0x81817F7F, 0x7F818181, 0x81817F7F, 0x7F818181, 0x7F7F7F81,
+0x8181817F, 0x817F8181, 0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x7F7F817F, 0x817F7F81, 0x817F7F81,
+0x81817F7F, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x7F81817F, 0x7F817F7F, 0x7F81817F,
+0x7F817F81, 0x817F7F7F, 0x81818181, 0x7F818181, 0x7F817F81, 0x8181817F, 0x81817F7F, 0x817F817F,
+0x8181817F, 0x817F7F81, 0x81817F7F, 0x81817F81, 0x817F7F81, 0x81817F7F, 0x81817F7F, 0x7F818181,
+0x7F817F81, 0x81817F7F, 0x817F8181, 0x7F7F7F81, 0x817F817F, 0x817F7F7F, 0x7F7F817F, 0x817F7F7F,
+0x817F8181, 0x7F81817F, 0x8181817F, 0x7F7F7F81, 0x7F817F7F, 0x817F8181, 0x7F81817F, 0x8181817F,
+0x817F7F81, 0x817F7F81, 0x7F7F8181, 0x817F7F81, 0x7F7F7F81, 0x7F81817F, 0x7F7F8181, 0x817F817F,
+0x7F81817F, 0x81818181, 0x81818181, 0x81818181, 0x81818181, 0x7F818181, 0x7F818181, 0x81818181,
+0x7F817F7F, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F818181, 0x7F7F8181, 0x817F8181, 0x817F7F7F,
+0x817F7F81, 0x8181817F, 0x7F7F7F81, 0x8181817F, 0x81817F81, 0x81817F7F, 0x7F7F7F7F, 0x7F818181,
+0x817F7F7F, 0x7F7F7F7F, 0x8181817F, 0x8181817F, 0x81818181, 0x8181817F, 0x7F7F7F81, 0x817F817F,
+0x8181817F, 0x7F81817F, 0x7F818181, 0x7F7F7F81, 0x7F818181, 0x7F817F81, 0x817F817F, 0x81818181,
+0x7F818181, 0x7F817F7F, 0x7F818181, 0x7F7F817F, 0x81818181, 0x81817F81, 0x8181817F, 0x7F7F7F81,
+0x81817F7F, 0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F7F7F81, 0x7F7F817F, 0x7F81817F, 0x7F817F7F,
+0x7F817F81, 0x81818181, 0x81817F81, 0x7F7F7F7F, 0x817F817F, 0x7F7F817F, 0x7F81817F, 0x7F818181,
+0x81818181, 0x8181817F, 0x8181817F, 0x7F817F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F817F, 0x7F7F8181,
+0x81818181, 0x8181817F, 0x817F817F, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F817F,
+0x7F818181, 0x7F7F8181, 0x7F818181, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F817F81, 0x817F7F81,
+0x81818181, 0x81818181, 0x81817F81, 0x7F81817F, 0x817F8181, 0x817F8181, 0x7F817F81, 0x81818181,
+0x817F817F, 0x81817F7F, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F, 0x817F7F7F, 0x8181817F, 0x817F7F81,
+0x7F817F7F, 0x81817F7F, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x817F7F7F,
+0x817F7F81, 0x817F817F, 0x8181817F, 0x81817F81, 0x8181817F, 0x81817F81, 0x817F7F81, 0x817F7F81,
+0x7F818181, 0x81817F7F, 0x7F81817F, 0x81817F7F, 0x81818181, 0x7F7F8181, 0x817F7F81, 0x81817F81,
+0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x7F7F817F, 0x7F818181, 0x7F818181, 0x7F818181, 0x7F817F81,
+0x7F818181, 0x7F81817F, 0x7F7F8181, 0x81818181, 0x7F817F81, 0x7F818181, 0x817F7F7F, 0x7F7F817F,
+0x81817F7F, 0x7F7F7F81, 0x81817F7F, 0x81818181, 0x817F7F81, 0x7F817F81, 0x7F7F8181, 0x7F817F7F,
+0x817F817F, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x7F7F7F81, 0x81817F7F, 0x7F817F7F, 0x817F7F7F,
+0x7F817F81, 0x7F7F8181, 0x817F8181, 0x7F817F81, 0x7F81817F, 0x817F817F, 0x7F81817F, 0x81817F81,
+0x81817F7F, 0x81818181, 0x817F8181, 0x7F817F81, 0x7F818181, 0x7F817F81, 0x817F7F81, 0x7F817F81,
+0x7F7F7F81, 0x7F817F7F, 0x7F817F7F, 0x817F8181, 0x817F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F81817F,
+0x7F818181, 0x7F7F8181, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x8181817F, 0x817F8181, 0x7F81817F,
+0x7F81817F, 0x817F817F, 0x7F817F81, 0x81817F7F, 0x7F81817F, 0x8181817F, 0x7F818181, 0x7F818181,
+0x817F817F, 0x7F7F7F7F, 0x81818181, 0x817F8181, 0x81817F7F, 0x81817F7F, 0x81817F7F, 0x81818181,
+0x817F8181, 0x7F7F8181, 0x7F7F7F7F, 0x81817F7F, 0x817F8181, 0x7F81817F, 0x7F817F81, 0x81817F81,
+0x8181817F, 0x7F817F7F, 0x7F7F7F81, 0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x81818181, 0x817F8181, 0x817F7F7F, 0x7F817F81, 0x7F818181, 0x7F7F7F7F, 0x7F81817F, 0x817F7F81,
+0x7F7F7F81, 0x7F818181, 0x81817F81, 0x817F817F, 0x7F81817F, 0x7F817F7F, 0x7F7F817F, 0x7F7F7F81,
+0x817F7F81, 0x7F7F7F81, 0x7F7F8181, 0x7F817F81, 0x817F8181, 0x81818181, 0x7F818181, 0x817F7F7F,
+0x8181817F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F7F, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x81818181,
+0x7F7F817F, 0x7F7F7F81, 0x7F817F7F, 0x7F818181, 0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F,
+0x817F7F81, 0x81817F81, 0x7F81817F, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F7F, 0x817F817F,
+0x7F7F8181, 0x7F7F8181, 0x81818181, 0x7F817F81, 0x81817F7F, 0x7F81817F, 0x7F818181, 0x7F7F7F81,
+0x817F8181, 0x7F81817F, 0x817F8181, 0x7F7F817F, 0x81818181, 0x81818181, 0x7F7F7F81, 0x8181817F,
+0x8181817F, 0x7F7F7F7F, 0x81818181, 0x7F7F7F7F, 0x817F817F, 0x817F8181, 0x817F7F81, 0x81818181,
+0x7F817F7F, 0x7F7F7F7F, 0x817F7F81, 0x817F817F, 0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x81817F81,
+0x7F7F7F81, 0x8181817F, 0x81818181, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x817F817F, 0x7F7F8181,
+0x7F7F8181, 0x817F7F81, 0x81817F7F, 0x817F8181, 0x817F817F, 0x7F817F7F, 0x7F81817F, 0x7F81817F,
+0x7F817F81, 0x81817F7F, 0x7F818181, 0x7F818181, 0x817F8181, 0x7F7F7F7F, 0x817F817F, 0x7F7F817F,
+0x7F7F8181, 0x7F817F7F, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x817F8181, 0x817F8181,
+0x7F7F7F81, 0x7F818181, 0x81818181, 0x7F817F81, 0x81817F7F, 0x81817F81, 0x7F81817F, 0x7F81817F,
+0x817F817F, 0x7F817F7F, 0x7F818181, 0x817F7F81, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x817F817F,
+0x81817F81, 0x7F7F7F81, 0x817F8181, 0x7F817F81, 0x7F817F7F, 0x7F818181, 0x7F817F81, 0x7F7F7F81,
+0x7F817F7F, 0x81817F81, 0x7F7F7F7F, 0x817F7F81, 0x7F7F8181, 0x817F7F7F, 0x81817F7F, 0x81818181,
+0x7F7F8181, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F81, 0x817F817F,
+0x7F818181, 0x81818181, 0x7F81817F, 0x8181817F, 0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x7F818181,
+0x817F7F81, 0x7F7F8181, 0x7F7F817F, 0x817F8181, 0x81817F7F, 0x81817F7F, 0x7F7F817F, 0x7F817F81,
+0x7F81817F, 0x81818181, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x81817F81, 0x7F7F7F81, 0x7F81817F,
+0x81817F7F, 0x81818181, 0x8181817F, 0x817F7F7F, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x7F81817F,
+0x81818181, 0x7F818181, 0x8181817F, 0x7F818181, 0x7F7F7F81, 0x817F8181, 0x7F818181, 0x817F8181,
+0x7F7F817F, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x817F7F81, 0x7F817F7F, 0x81818181, 0x7F817F7F,
+0x817F7F7F, 0x7F817F7F, 0x8181817F, 0x817F817F, 0x7F818181, 0x817F7F81, 0x817F8181, 0x7F817F7F,
+0x7F7F7F7F, 0x81817F7F, 0x817F7F7F, 0x817F7F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F818181, 0x7F7F7F81,
+0x817F817F, 0x8181817F, 0x7F7F7F7F, 0x817F7F81, 0x817F8181, 0x81817F7F, 0x81817F7F, 0x817F8181,
+0x81817F7F, 0x81818181, 0x817F7F7F, 0x81817F81, 0x81817F81, 0x8181817F, 0x7F818181, 0x81818181,
+0x817F8181, 0x817F817F, 0x7F7F7F7F, 0x817F7F7F, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F817F81,
+0x81817F7F, 0x7F7F7F7F, 0x81818181, 0x8181817F, 0x8181817F, 0x817F817F, 0x7F7F7F81, 0x81818181,
+0x7F7F8181, 0x817F7F81, 0x81818181, 0x81817F81, 0x81817F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F8181,
+0x7F81817F, 0x7F7F7F81, 0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x7F7F7F7F, 0x8181817F, 0x7F817F81,
+0x817F8181, 0x817F7F81, 0x7F7F7F81, 0x7F818181, 0x817F7F81, 0x7F7F7F7F, 0x8181817F, 0x8181817F,
+0x7F818181, 0x7F7F817F, 0x7F7F7F7F, 0x817F8181, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x7F81817F,
+0x817F7F81, 0x7F7F8181, 0x7F818181, 0x7F817F7F, 0x8181817F, 0x817F7F81, 0x817F817F, 0x7F817F7F,
+0x817F817F, 0x81817F7F, 0x81817F81, 0x817F7F7F, 0x817F817F, 0x817F7F81, 0x7F81817F, 0x8181817F,
+0x8181817F, 0x81817F81, 0x817F817F, 0x7F818181, 0x8181817F, 0x7F818181, 0x8181817F, 0x7F7F817F,
+0x7F818181, 0x817F817F, 0x7F7F7F7F, 0x81817F81, 0x817F817F, 0x817F7F7F, 0x7F7F817F, 0x7F7F8181,
+0x81817F7F, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x7F818181, 0x81817F7F, 0x7F817F7F,
+0x7F818181, 0x7F7F7F7F, 0x7F81817F, 0x817F7F7F, 0x81817F81, 0x81817F7F, 0x817F817F, 0x7F7F817F,
+0x817F7F7F, 0x7F81817F, 0x817F7F81, 0x7F81817F, 0x7F7F817F, 0x817F8181, 0x7F7F8181, 0x81817F81,
+0x7F817F81, 0x7F7F817F, 0x7F7F817F, 0x81817F81, 0x7F7F817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F8181,
+0x817F7F7F, 0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F, 0x7F7F817F, 0x81817F81,
+0x817F8181, 0x817F7F7F, 0x7F81817F, 0x7F817F81, 0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F,
+0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F7F8181, 0x81817F7F, 0x81818181, 0x7F817F81, 0x7F818181,
+0x81817F81, 0x7F7F817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F8181, 0x81817F81, 0x7F7F7F81, 0x7F817F7F,
+0x81818181, 0x81818181, 0x7F7F817F, 0x817F817F, 0x7F818181, 0x7F7F8181, 0x81818181, 0x7F7F7F7F,
+0x817F7F7F, 0x81817F81, 0x8181817F, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F81,
+0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81, 0x7F7F817F, 0x81817F81, 0x817F8181, 0x7F818181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x81817F7F, 0x81817F81, 0x81818181, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x7F817F81, 0x7F7F8181, 0x7F7F817F, 0x81817F7F, 0x7F7F8181,
+0x817F817F, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F81, 0x81818181, 0x7F818181, 0x8181817F, 0x7F7F8181,
+0x817F7F81, 0x817F8181, 0x81817F81, 0x7F7F8181, 0x7F817F81, 0x8181817F, 0x817F7F81, 0x7F7F8181,
+0x81817F7F, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F817F, 0x817F7F7F, 0x7F7F7F7F, 0x7F818181,
+0x81818181, 0x7F81817F, 0x81817F7F, 0x817F817F, 0x7F817F7F, 0x817F817F, 0x81818181, 0x817F7F81,
+0x817F7F81, 0x817F7F81, 0x7F7F8181, 0x7F81817F, 0x817F7F81, 0x7F7F8181, 0x81818181, 0x817F7F7F,
+0x81818181, 0x7F7F817F, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F7F81,
+0x7F7F7F81, 0x7F817F7F, 0x81817F7F, 0x81818181, 0x817F817F, 0x81818181, 0x81818181, 0x817F7F7F,
+0x7F7F817F, 0x7F7F8181, 0x7F7F8181, 0x817F7F7F, 0x7F81817F, 0x7F7F8181, 0x7F7F8181, 0x81818181,
+0x8181817F, 0x7F818181, 0x7F817F81, 0x817F817F, 0x8181817F, 0x817F8181, 0x81818181, 0x7F817F7F,
+0x7F7F7F81, 0x7F817F7F, 0x7F7F7F81, 0x817F7F81, 0x817F8181, 0x81817F81, 0x81817F81, 0x7F7F7F81,
+0x81817F7F, 0x817F8181, 0x7F817F7F, 0x7F81817F, 0x8181817F, 0x7F818181, 0x81818181, 0x7F7F8181,
+0x817F7F7F, 0x817F7F7F, 0x7F81817F, 0x817F7F7F, 0x7F7F8181, 0x81817F7F, 0x7F81817F, 0x81817F7F,
+0x81817F81, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F81817F, 0x817F7F7F,
+0x7F7F7F81, 0x817F8181, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x7F7F8181, 0x81817F81, 0x7F7F7F81,
+0x7F81817F, 0x7F7F817F, 0x7F81817F, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F8181,
+0x7F817F7F, 0x7F7F8181, 0x81818181, 0x81818181, 0x817F8181, 0x81818181, 0x817F8181, 0x7F7F7F81,
+0x8181817F, 0x8181817F, 0x7F7F7F7F, 0x7F818181, 0x817F817F, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81,
+0x7F7F7F81, 0x817F817F, 0x7F7F7F7F, 0x81817F81, 0x81817F7F, 0x7F7F817F, 0x817F7F7F, 0x7F817F81,
+0x8181817F, 0x81818181, 0x7F817F81, 0x817F7F81, 0x81818181, 0x81817F81, 0x81817F81, 0x7F81817F,
+0x7F7F7F81, 0x817F8181, 0x817F7F81, 0x817F817F, 0x7F817F81, 0x817F7F7F, 0x8181817F, 0x8181817F,
+0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x817F7F81, 0x7F81817F, 0x7F7F817F, 0x817F7F7F,
+0x7F817F7F, 0x817F7F81, 0x817F817F, 0x8181817F, 0x7F817F81, 0x7F81817F, 0x7F7F7F81, 0x7F7F7F7F,
+0x7F7F817F, 0x817F7F7F, 0x817F7F7F, 0x817F7F7F, 0x7F818181, 0x7F7F8181, 0x7F7F8181, 0x81817F7F,
+0x7F7F7F7F, 0x81818181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F7F, 0x817F7F81, 0x81817F7F, 0x817F7F81,
+0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x817F817F, 0x81818181, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F817F,
+0x7F7F7F81, 0x8181817F, 0x7F818181, 0x817F7F81, 0x7F818181, 0x817F8181, 0x7F817F7F, 0x81818181,
+0x7F7F8181, 0x7F7F7F81, 0x817F7F7F, 0x7F817F81, 0x7F7F7F81, 0x817F817F, 0x7F7F7F81, 0x81817F7F,
+0x7F7F817F, 0x817F7F7F, 0x81817F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F81, 0x7F818181,
+0x817F7F81, 0x7F817F7F, 0x7F7F817F, 0x7F81817F, 0x7F817F7F, 0x7F7F7F81, 0x7F818181, 0x7F7F7F81,
+0x7F7F817F, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x7F7F817F, 0x81817F7F, 0x81817F7F, 0x7F817F7F,
+0x7F7F7F81, 0x7F7F7F7F, 0x817F817F, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x817F7F81, 0x7F7F8181,
+0x7F817F7F, 0x7F818181, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x81818181, 0x7F7F817F, 0x7F817F81,
+0x817F817F, 0x7F817F81, 0x7F7F7F7F, 0x81817F7F, 0x81817F81, 0x817F7F7F, 0x81818181, 0x7F81817F,
+0x8181817F, 0x7F81817F, 0x7F7F8181, 0x817F817F, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x817F7F81,
+0x81817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F81817F, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F,
+0x7F81817F, 0x817F8181, 0x7F818181, 0x817F7F7F, 0x7F7F817F, 0x8181817F, 0x81818181, 0x7F7F7F7F,
+0x81817F81, 0x8181817F, 0x7F7F7F81, 0x7F7F817F, 0x817F7F81, 0x7F817F7F, 0x7F7F7F7F, 0x8181817F,
+0x817F817F, 0x817F817F, 0x7F7F8181, 0x817F7F81, 0x81817F81, 0x7F81817F, 0x7F7F7F7F, 0x7F7F7F7F,
+0x7F7F7F7F, 0x81817F7F, 0x817F7F81, 0x817F7F7F, 0x81817F81, 0x817F7F7F, 0x7F817F81, 0x8181817F,
+0x7F81817F, 0x817F7F81, 0x81817F81, 0x7F7F7F7F, 0x817F7F81, 0x7F818181, 0x8181817F, 0x81817F81,
+0x7F7F817F, 0x81817F7F, 0x7F817F7F, 0x7F7F817F, 0x81817F7F, 0x7F818181, 0x8181817F, 0x81817F7F,
+0x7F817F81, 0x7F818181, 0x7F81817F, 0x7F818181, 0x817F7F81, 0x7F817F81, 0x7F7F817F, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F8181, 0x8181817F, 0x81817F81, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x81817F81,
+0x7F7F817F, 0x7F7F7F81, 0x81818181, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x7F81817F, 0x7F817F81,
+0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x817F7F81, 0x7F817F81, 0x7F817F7F, 0x7F818181, 0x81818181,
+0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x7F818181, 0x7F81817F, 0x7F7F817F, 0x7F7F8181, 0x7F7F817F,
+0x7F7F8181, 0x817F817F, 0x8181817F, 0x81818181, 0x81818181, 0x7F817F7F, 0x81817F7F, 0x7F81817F,
+0x81817F81, 0x7F817F7F, 0x7F818181, 0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x8181817F,
+0x81817F7F, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x81818181,
+0x7F7F8181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x7F7F8181,
+0x7F817F81, 0x81817F7F, 0x7F817F81, 0x817F7F7F, 0x7F817F7F, 0x7F817F81, 0x7F81817F, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F8181, 0x7F7F7F7F, 0x81817F7F, 0x7F818181, 0x8181817F, 0x81817F7F, 0x7F81817F,
+0x7F817F81, 0x7F7F7F81, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x7F817F81, 0x817F817F, 0x8181817F,
+0x7F7F8181, 0x7F818181, 0x7F7F7F81, 0x7F7F7F81, 0x817F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F7F81,
+0x817F8181, 0x7F7F817F, 0x7F817F81, 0x817F8181, 0x7F81817F, 0x7F817F7F, 0x817F8181, 0x7F818181,
+0x7F7F7F7F, 0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F7F7F7F,
+0x81818181, 0x817F817F, 0x8181817F, 0x7F81817F, 0x817F817F, 0x817F817F, 0x7F7F817F, 0x7F817F81,
+0x7F818181, 0x81817F7F, 0x81817F7F, 0x817F8181, 0x81818181, 0x81817F7F, 0x7F7F8181, 0x7F7F7F7F,
+0x8181817F, 0x7F817F81, 0x7F7F8181, 0x7F817F81, 0x817F7F81, 0x7F818181, 0x817F7F81, 0x817F7F7F,
+0x7F7F7F81, 0x8181817F, 0x817F8181, 0x7F818181, 0x81818181, 0x81818181, 0x817F7F7F, 0x7F7F817F,
+0x7F817F81, 0x81818181, 0x817F7F81, 0x8181817F, 0x7F817F7F, 0x7F7F7F81, 0x81817F7F, 0x7F81817F,
+0x7F7F7F81, 0x81817F7F, 0x81818181, 0x7F81817F, 0x7F7F817F, 0x7F817F7F, 0x817F8181, 0x817F817F,
+0x81818181, 0x7F7F8181, 0x7F7F8181, 0x7F7F7F7F, 0x81818181, 0x81817F81, 0x7F7F7F81, 0x7F81817F,
+0x81817F7F, 0x7F818181, 0x817F8181, 0x817F8181, 0x817F8181, 0x7F81817F, 0x7F7F7F81, 0x7F7F8181,
+0x817F8181, 0x81818181, 0x7F817F7F, 0x7F818181, 0x7F7F7F81, 0x81817F7F, 0x7F817F7F, 0x817F817F,
+0x8181817F, 0x7F7F817F, 0x7F818181, 0x7F818181, 0x7F7F8181, 0x817F7F81, 0x7F7F8181, 0x7F817F7F,
+0x817F7F81, 0x81817F81, 0x7F817F81, 0x7F7F7F81, 0x7F7F817F, 0x7F7F817F, 0x81817F81, 0x7F817F7F,
+0x7F7F817F, 0x7F7F817F, 0x7F817F7F, 0x81818181, 0x7F817F81, 0x81818181, 0x81818181, 0x7F818181,
+0x817F7F7F, 0x8181817F, 0x817F7F7F, 0x7F817F7F, 0x7F81817F, 0x81817F7F, 0x817F7F7F, 0x817F8181,
+0x7F81817F, 0x8181817F, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F,
+0x7F7F817F, 0x817F8181, 0x81817F7F, 0x81818181, 0x8181817F, 0x817F8181, 0x7F7F7F7F, 0x817F7F81,
+0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x7F7F817F, 0x7F81817F, 0x7F817F7F, 0x7F7F817F, 0x7F7F7F7F,
+0x81818181, 0x81818181, 0x81817F81, 0x817F817F, 0x8181817F, 0x817F7F7F, 0x7F7F7F7F, 0x817F817F,
+0x8181817F, 0x7F7F7F7F, 0x7F7F7F81, 0x8181817F, 0x7F81817F, 0x817F817F, 0x817F817F, 0x817F817F,
+0x7F817F81, 0x81817F7F, 0x7F81817F, 0x7F817F81, 0x7F817F7F, 0x81818181, 0x7F818181, 0x817F7F7F,
+0x81817F7F, 0x817F7F7F, 0x817F7F81, 0x7F7F7F81, 0x7F81817F, 0x817F8181, 0x7F81817F, 0x7F81817F,
+0x7F7F7F7F, 0x7F81817F, 0x8181817F, 0x81817F7F, 0x7F818181, 0x817F7F7F, 0x81817F7F, 0x8181817F,
+0x7F817F81, 0x81817F81, 0x7F817F7F, 0x7F81817F, 0x817F8181, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F81,
+0x817F8181, 0x817F7F81, 0x7F7F8181, 0x7F81817F, 0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x81817F81,
+0x7F7F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x817F817F, 0x8181817F, 0x7F817F81, 0x7F7F7F81,
+0x7F7F7F81, 0x7F817F7F, 0x817F817F, 0x7F817F81, 0x7F7F817F, 0x7F818181, 0x81817F81, 0x7F817F7F,
+0x7F817F81, 0x7F818181, 0x817F8181, 0x7F817F7F, 0x817F817F, 0x817F7F81, 0x81818181, 0x7F817F7F,
+0x7F817F81, 0x7F818181, 0x7F7F7F7F, 0x81818181, 0x817F7F81, 0x817F8181, 0x817F8181, 0x7F7F7F7F,
+0x817F817F, 0x7F7F7F7F, 0x81817F7F, 0x7F817F81, 0x81817F7F, 0x7F81817F, 0x7F7F7F81, 0x8181817F,
+0x7F7F8181, 0x817F7F81, 0x817F7F7F, 0x7F7F8181, 0x81817F7F, 0x81818181, 0x817F817F, 0x7F7F7F81,
+0x81818181, 0x81817F7F, 0x8181817F, 0x81817F7F, 0x81817F7F, 0x81818181, 0x7F81817F, 0x817F817F,
+0x7F7F7F7F, 0x81817F81, 0x817F7F81, 0x8181817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x7F817F7F, 0x81818181, 0x7F817F7F, 0x817F8181, 0x817F7F7F, 0x7F81817F, 0x7F7F817F,
+0x7F7F7F7F, 0x81817F81, 0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x7F818181, 0x7F818181, 0x81818181,
+0x817F8181, 0x81817F81, 0x7F7F817F, 0x817F7F81, 0x817F817F, 0x817F8181, 0x8181817F, 0x81818181,
+0x817F8181, 0x817F7F81, 0x7F7F817F, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x7F817F81, 0x7F7F8181,
+0x7F7F8181, 0x81818181, 0x817F7F7F, 0x81818181, 0x8181817F, 0x817F8181, 0x8181817F, 0x7F7F7F7F,
+0x7F7F7F7F, 0x7F81817F, 0x817F7F7F, 0x7F7F8181, 0x817F7F7F, 0x817F817F, 0x81817F7F, 0x7F817F81,
+0x7F7F817F, 0x7F817F81, 0x7F818181, 0x7F7F8181, 0x817F817F, 0x817F8181, 0x81818181, 0x7F818181,
+0x81817F81, 0x7F817F81, 0x7F7F8181, 0x7F7F8181, 0x817F8181, 0x7F81817F, 0x7F818181, 0x81817F7F,
+0x817F7F81, 0x81817F81, 0x817F8181, 0x7F817F81, 0x7F817F81, 0x81817F7F, 0x7F7F7F7F, 0x7F817F81,
+0x7F7F8181, 0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x817F817F, 0x7F7F817F, 0x7F81817F,
+0x7F7F7F7F, 0x81818181, 0x7F7F8181, 0x817F8181, 0x8181817F, 0x81817F81, 0x817F8181, 0x81818181,
+0x81818181, 0x817F817F, 0x7F7F7F7F, 0x81818181, 0x817F8181, 0x817F8181, 0x7F81817F, 0x81817F7F,
+0x7F7F817F, 0x7F817F7F, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x7F817F7F, 0x7F7F8181, 0x817F7F81,
+0x7F81817F, 0x817F8181, 0x817F817F, 0x817F7F7F, 0x7F7F7F7F, 0x81817F81, 0x81817F81, 0x7F7F817F,
+0x7F81817F, 0x817F817F, 0x7F817F81, 0x817F7F7F, 0x817F817F, 0x817F7F81, 0x7F818181, 0x7F817F7F,
+0x7F818181, 0x817F7F7F, 0x817F817F, 0x7F7F817F, 0x7F818181, 0x7F7F817F, 0x7F818181, 0x7F817F7F,
+0x817F8181, 0x817F8181, 0x7F7F817F, 0x7F818181, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F81,
+0x7F7F7F81, 0x81818181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x8181817F, 0x817F7F7F, 0x7F817F7F,
+0x81818181, 0x817F8181, 0x7F7F7F81, 0x817F8181, 0x8181817F, 0x7F817F81, 0x7F817F7F, 0x7F817F81,
+0x81818181, 0x817F7F7F, 0x81818181, 0x7F7F8181, 0x817F817F, 0x7F7F817F, 0x81818181, 0x7F7F7F81,
+0x7F7F817F, 0x7F818181, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x8181817F, 0x817F7F81,
+0x7F817F7F, 0x7F817F7F, 0x7F7F8181, 0x817F817F, 0x817F7F7F, 0x7F817F81, 0x81817F7F, 0x817F817F,
+0x7F817F7F, 0x8181817F, 0x7F7F8181, 0x817F817F, 0x7F81817F, 0x817F817F, 0x7F818181, 0x7F818181,
+0x817F817F, 0x817F7F7F, 0x7F7F7F7F, 0x7F818181, 0x817F7F7F, 0x7F81817F, 0x8181817F, 0x81818181,
+0x817F817F, 0x7F7F8181, 0x7F817F81, 0x81818181, 0x7F81817F, 0x817F817F, 0x81818181, 0x7F7F817F,
+0x7F7F817F, 0x81817F81, 0x817F7F81, 0x8181817F, 0x8181817F, 0x817F7F7F, 0x7F818181, 0x7F81817F,
+0x7F7F7F81, 0x817F8181, 0x7F7F8181, 0x7F817F81, 0x8181817F, 0x817F817F, 0x7F817F81, 0x81818181,
+0x7F817F7F, 0x817F7F81, 0x7F818181, 0x7F7F8181, 0x7F817F81, 0x817F817F, 0x7F7F817F, 0x8181817F,
+0x7F817F81, 0x817F8181, 0x7F7F8181, 0x7F7F7F81, 0x817F7F81, 0x81817F7F, 0x817F817F, 0x81818181,
+0x7F818181, 0x817F7F81, 0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F7F817F,
+0x817F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x7F817F81, 0x817F817F,
+0x81818181, 0x7F7F817F, 0x7F7F7F7F, 0x81817F81, 0x817F817F, 0x81818181, 0x7F817F7F, 0x7F81817F,
+0x7F81817F, 0x7F7F8181, 0x7F7F7F7F, 0x81817F7F, 0x7F817F7F, 0x7F817F7F, 0x7F81817F, 0x7F81817F,
+0x7F7F8181, 0x81817F81, 0x7F7F8181, 0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x817F817F,
+0x7F7F817F, 0x81818181, 0x81818181, 0x7F817F81, 0x817F8181, 0x817F7F7F, 0x817F8181, 0x81818181,
+0x817F7F7F, 0x817F7F81, 0x81817F81, 0x7F818181, 0x7F81817F, 0x817F7F81, 0x817F817F, 0x7F7F7F81,
+0x7F817F81, 0x7F818181, 0x817F817F, 0x7F818181, 0x7F81817F, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F817F,
+0x7F817F81, 0x8181817F, 0x81818181, 0x7F818181, 0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F7F817F,
+0x81818181, 0x7F817F81, 0x81818181, 0x817F817F, 0x7F817F7F, 0x81817F7F, 0x817F7F81, 0x817F817F,
+0x7F817F7F, 0x81817F81, 0x7F7F8181, 0x81818181, 0x7F7F7F81, 0x81818181, 0x7F818181, 0x817F7F7F,
+0x81817F81, 0x817F7F7F, 0x81818181, 0x8181817F, 0x817F7F7F, 0x817F7F7F, 0x817F817F, 0x81818181,
+0x81817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x817F7F81, 0x8181817F, 0x7F817F81,
+0x7F7F7F7F, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181, 0x817F8181, 0x817F8181, 0x81817F81,
+0x7F7F7F81, 0x81817F81, 0x7F7F7F7F, 0x817F8181, 0x7F7F817F, 0x7F818181, 0x7F7F7F7F, 0x7F817F7F,
+0x7F7F7F81, 0x81817F81, 0x8181817F, 0x8181817F, 0x7F7F7F81, 0x8181817F, 0x7F7F8181, 0x81817F7F,
+0x8181817F, 0x7F7F817F, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F7F, 0x81818181, 0x81817F7F, 0x7F7F8181,
+0x7F817F7F, 0x7F7F8181, 0x817F817F, 0x817F7F7F, 0x7F817F7F, 0x7F817F7F, 0x7F817F81, 0x8181817F,
+0x81818181, 0x81817F7F, 0x7F7F8181, 0x7F817F7F, 0x81817F81, 0x81817F7F, 0x7F818181, 0x7F817F81,
+0x81817F7F, 0x7F817F81, 0x817F817F, 0x81818181, 0x81817F81, 0x817F817F, 0x817F7F7F, 0x817F7F7F,
+0x817F8181, 0x7F81817F, 0x81817F81, 0x81817F81, 0x7F817F7F, 0x817F8181, 0x817F7F81, 0x7F7F8181,
+0x817F8181, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x8181817F,
+0x817F8181, 0x7F817F7F, 0x817F817F, 0x817F8181, 0x81817F7F, 0x7F817F81, 0x817F8181, 0x7F81817F,
+0x81818181, 0x7F817F7F, 0x8181817F, 0x7F817F81, 0x7F7F7F7F, 0x81818181, 0x81817F7F, 0x7F817F7F,
+0x7F7F817F, 0x7F7F8181, 0x817F817F, 0x7F7F817F, 0x7F7F7F7F, 0x8181817F, 0x7F817F81, 0x8181817F,
+0x817F817F, 0x7F7F7F81, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F81,
+0x81817F81, 0x7F7F7F7F, 0x7F817F81, 0x81817F7F, 0x7F7F8181, 0x7F7F8181, 0x817F817F, 0x7F7F7F7F,
+0x7F7F817F, 0x7F7F7F81, 0x7F818181, 0x7F817F7F, 0x7F7F817F, 0x81818181, 0x817F8181, 0x817F817F,
+0x7F817F81, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x7F818181, 0x81818181, 0x7F817F7F, 0x7F817F7F,
+0x7F81817F, 0x7F7F817F, 0x81818181, 0x817F817F, 0x817F7F7F, 0x7F7F7F81, 0x81818181, 0x7F81817F,
+0x7F7F8181, 0x7F7F7F81, 0x7F81817F, 0x7F81817F, 0x817F7F81, 0x7F817F7F, 0x817F7F7F, 0x817F8181,
+0x7F7F817F, 0x7F81817F, 0x81818181, 0x81817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x7F818181,
+0x7F818181, 0x81817F81, 0x7F7F817F, 0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x7F81817F, 0x817F8181,
+0x817F7F81, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F7F, 0x81818181, 0x81818181, 0x817F817F, 0x7F7F8181,
+0x817F7F81, 0x8181817F, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x7F818181, 0x817F7F7F, 0x817F7F7F,
+0x817F817F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x81818181, 0x817F8181, 0x7F7F817F, 0x7F81817F,
+0x7F7F8181, 0x7F7F8181, 0x7F818181, 0x817F817F, 0x81818181, 0x81817F81, 0x81817F7F, 0x7F7F7F81,
+0x7F818181, 0x81818181, 0x7F818181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F818181, 0x7F7F7F7F,
+0x817F7F7F, 0x7F7F817F, 0x7F817F81, 0x81818181, 0x7F7F7F81, 0x81818181, 0x817F817F, 0x8181817F,
+0x817F8181, 0x817F7F81, 0x817F8181, 0x817F7F7F, 0x7F818181, 0x7F818181, 0x81817F7F, 0x81817F81,
+0x7F7F8181, 0x7F818181, 0x81817F81, 0x7F7F817F, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F81, 0x7F7F8181,
+0x817F8181, 0x8181817F, 0x81817F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x81818181, 0x7F7F8181,
+0x81818181, 0x7F7F7F81, 0x7F818181, 0x7F7F8181, 0x817F7F7F, 0x81817F7F, 0x7F7F7F7F, 0x817F7F81,
+0x817F8181, 0x817F7F7F, 0x7F7F817F, 0x8181817F, 0x7F7F7F81, 0x817F8181, 0x7F7F817F, 0x817F7F81,
+0x81817F81, 0x81817F7F, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x7F7F817F, 0x817F817F, 0x7F81817F,
+0x81817F7F, 0x817F817F, 0x7F81817F, 0x8181817F, 0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F818181,
+0x7F7F7F7F, 0x817F7F81, 0x81817F81, 0x7F817F81, 0x81818181, 0x81817F7F, 0x7F817F81, 0x7F7F7F7F,
+0x7F7F7F81, 0x81818181, 0x7F817F7F, 0x817F817F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x7F7F817F,
+0x81817F81, 0x7F818181, 0x7F818181, 0x81817F7F, 0x7F7F7F81, 0x817F8181, 0x81818181, 0x7F817F81,
+0x7F7F817F, 0x817F817F, 0x81817F7F, 0x817F7F7F, 0x81817F81, 0x7F7F7F7F, 0x7F817F7F, 0x81818181,
+0x81817F81, 0x81817F7F, 0x7F81817F, 0x817F7F7F, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F81, 0x817F8181,
+0x81817F7F, 0x817F8181, 0x81818181, 0x817F817F, 0x817F8181, 0x7F81817F, 0x7F7F817F, 0x7F817F7F,
+0x7F7F817F, 0x817F817F, 0x817F8181, 0x8181817F, 0x817F7F7F, 0x81818181, 0x7F7F7F7F, 0x81817F7F,
+0x81817F7F, 0x7F7F7F81, 0x7F7F8181, 0x817F7F81, 0x7F7F7F81, 0x7F81817F, 0x81818181, 0x81818181,
+0x8181817F, 0x817F7F7F, 0x81817F81, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x7F817F81, 0x81817F7F,
+0x7F81817F, 0x817F7F81, 0x7F7F7F81, 0x817F7F81, 0x7F817F7F, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F7F,
+0x7F7F8181, 0x817F7F81, 0x7F7F7F7F, 0x817F7F81, 0x7F81817F, 0x817F7F81, 0x817F7F81, 0x81818181,
+0x817F817F, 0x817F817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x7F7F8181, 0x7F81817F, 0x7F7F7F81,
+0x7F7F817F, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F, 0x817F7F7F, 0x81817F7F,
+0x81818181, 0x8181817F, 0x81817F81, 0x7F818181, 0x817F8181, 0x7F818181, 0x817F8181, 0x81818181,
+0x7F7F7F81, 0x81817F7F, 0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x7F7F7F7F, 0x81817F7F, 0x817F817F,
+0x7F7F817F, 0x8181817F, 0x7F81817F, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x7F817F81, 0x81818181,
+0x817F7F81, 0x81818181, 0x7F81817F, 0x81818181, 0x7F817F81, 0x7F7F7F81, 0x7F7F8181, 0x7F817F81,
+0x7F817F81, 0x8181817F, 0x7F81817F, 0x817F817F, 0x817F817F, 0x81817F81, 0x817F817F, 0x81817F81,
+0x7F7F8181, 0x81817F7F, 0x7F817F81, 0x7F7F7F7F, 0x817F7F81, 0x817F8181, 0x817F817F, 0x817F7F81,
+0x81817F7F, 0x817F7F7F, 0x7F7F8181, 0x817F7F81, 0x817F7F81, 0x7F818181, 0x8181817F, 0x7F7F7F81,
+0x817F8181, 0x7F7F817F, 0x817F8181, 0x7F81817F, 0x7F81817F, 0x81817F7F, 0x7F7F7F7F, 0x817F7F7F,
+0x8181817F, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x81817F81, 0x81817F81, 0x81818181, 0x8181817F,
+0x817F817F, 0x7F817F7F, 0x817F817F, 0x7F7F7F7F, 0x8181817F, 0x817F817F, 0x817F817F, 0x7F817F81,
+0x8181817F, 0x8181817F, 0x7F7F8181, 0x7F818181, 0x7F817F7F, 0x8181817F, 0x81818181, 0x7F817F81,
+0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x817F7F7F, 0x7F81817F, 0x7F818181, 0x817F8181, 0x7F81817F,
+0x7F817F7F, 0x8181817F, 0x817F8181, 0x817F817F, 0x817F817F, 0x81817F81, 0x8181817F, 0x7F817F81,
+0x7F7F817F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x7F817F7F, 0x7F81817F, 0x817F7F7F, 0x81817F81,
+0x817F817F, 0x81817F81, 0x8181817F, 0x7F817F7F, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F817F81,
+0x7F817F81, 0x817F8181, 0x7F7F8181, 0x7F7F817F, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x7F817F81,
+0x817F8181, 0x81818181, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F818181, 0x817F8181, 0x817F8181,
+0x817F8181, 0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x7F81817F, 0x81818181, 0x7F7F7F7F,
+0x7F818181, 0x817F817F, 0x817F7F81, 0x817F7F81, 0x8181817F, 0x817F7F81, 0x81818181, 0x817F7F81,
+0x81817F7F, 0x7F7F7F81, 0x7F817F7F, 0x7F7F8181, 0x7F7F8181, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F,
+0x7F7F7F7F, 0x7F81817F, 0x81817F81, 0x7F818181, 0x7F81817F, 0x817F817F, 0x7F7F7F81, 0x7F7F817F,
+0x7F7F8181, 0x817F7F81, 0x817F7F7F, 0x7F817F7F, 0x7F81817F, 0x817F7F81, 0x8181817F, 0x81817F81,
+0x8181817F, 0x7F7F7F7F, 0x81818181, 0x7F7F7F7F, 0x81818181, 0x817F7F7F, 0x7F7F817F, 0x7F817F81,
+0x81817F81, 0x7F7F7F7F, 0x7F818181, 0x7F818181, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x81818181,
+0x81818181, 0x7F7F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F7F817F, 0x817F7F7F, 0x817F7F81,
+0x7F7F817F, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F7F, 0x81818181,
+0x81818181, 0x7F817F7F, 0x7F7F817F, 0x7F817F7F, 0x817F8181, 0x7F81817F, 0x8181817F, 0x81818181,
+0x7F817F7F, 0x81818181, 0x81818181, 0x81817F7F, 0x7F818181, 0x7F7F7F81, 0x81817F7F, 0x7F817F81,
+0x817F8181, 0x7F817F81, 0x817F7F7F, 0x817F8181, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F817F,
+0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F7F, 0x81817F81, 0x81817F7F,
+0x7F817F81, 0x7F81817F, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x81817F81, 0x7F817F7F, 0x7F817F81,
+0x81818181, 0x7F7F7F7F, 0x81817F7F, 0x817F7F7F, 0x7F818181, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F7F81,
+0x817F7F7F, 0x81817F7F, 0x7F7F817F, 0x817F8181, 0x7F817F7F, 0x81818181, 0x817F8181, 0x817F817F,
+0x7F818181, 0x7F7F7F7F, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x7F817F7F, 0x7F7F7F81, 0x817F7F81,
+0x817F7F81, 0x7F7F7F7F, 0x817F8181, 0x817F8181, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x817F7F81,
+0x7F7F817F, 0x8181817F, 0x81818181, 0x817F817F, 0x7F7F7F81, 0x7F81817F, 0x7F817F81, 0x817F7F81,
+0x7F818181, 0x7F7F7F81, 0x81817F81, 0x7F817F7F, 0x81818181, 0x817F7F7F, 0x7F817F81, 0x817F8181,
+0x81817F81, 0x7F81817F, 0x7F7F8181, 0x81818181, 0x81817F7F, 0x8181817F, 0x7F81817F, 0x81817F7F,
+0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x81818181, 0x817F817F, 0x817F7F81,
+0x7F7F817F, 0x817F7F81, 0x7F7F817F, 0x8181817F, 0x8181817F, 0x8181817F, 0x7F817F7F, 0x817F8181,
+0x81818181, 0x817F7F7F, 0x817F817F, 0x81818181, 0x7F81817F, 0x7F7F8181, 0x817F7F7F, 0x817F8181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x7F7F7F7F, 0x81817F7F, 0x81818181, 0x7F7F817F,
+0x817F817F, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x817F7F81, 0x817F7F7F, 0x7F81817F,
+0x8181817F, 0x817F8181, 0x7F7F7F81, 0x7F817F81, 0x7F817F7F, 0x7F7F817F, 0x7F7F8181, 0x7F818181,
+0x8181817F, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x7F818181, 0x8181817F, 0x7F7F817F, 0x81817F7F,
+0x7F7F817F, 0x7F817F81, 0x817F8181, 0x817F7F7F, 0x817F817F, 0x7F818181, 0x7F817F81, 0x7F7F7F81,
+0x7F81817F, 0x817F7F81, 0x7F818181, 0x81817F81, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x81818181,
+0x81818181, 0x7F81817F, 0x817F7F81, 0x7F817F81, 0x817F817F, 0x817F817F, 0x817F8181, 0x81818181,
+0x817F8181, 0x817F7F7F, 0x81817F7F, 0x81817F7F, 0x81817F81, 0x81818181, 0x7F7F8181, 0x81817F7F,
+0x7F7F7F81, 0x7F81817F, 0x81817F81, 0x7F7F817F, 0x81817F7F, 0x81817F81, 0x81818181, 0x7F7F7F7F,
+0x81817F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x8181817F, 0x817F8181, 0x817F7F7F, 0x7F7F7F7F,
+0x81817F7F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x817F7F81, 0x7F818181, 0x817F7F81, 0x81817F81,
+0x7F7F8181, 0x7F7F817F, 0x81817F7F, 0x7F818181, 0x7F7F7F81, 0x8181817F, 0x7F818181, 0x7F7F817F,
+0x7F7F7F81, 0x817F7F81, 0x7F817F7F, 0x7F818181, 0x8181817F, 0x7F7F8181, 0x81818181, 0x817F8181,
+0x7F817F7F, 0x7F81817F, 0x81818181, 0x817F8181, 0x7F81817F, 0x817F7F81, 0x81818181, 0x7F817F81,
+0x7F817F7F, 0x817F817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F817F, 0x81818181, 0x817F8181, 0x7F7F7F7F,
+0x817F7F7F, 0x81818181, 0x81818181, 0x81818181, 0x7F7F8181, 0x7F7F817F, 0x81817F81, 0x817F7F81,
+0x7F81817F, 0x7F7F8181, 0x7F7F7F81, 0x7F817F7F, 0x81818181, 0x7F7F7F7F, 0x81817F7F, 0x7F7F7F7F,
+0x81817F7F, 0x7F7F817F, 0x7F7F7F81, 0x7F817F81, 0x817F817F, 0x7F817F81, 0x7F7F7F81, 0x7F817F7F,
+0x817F8181, 0x7F7F8181, 0x7F7F817F, 0x7F817F81, 0x81817F81, 0x81817F81, 0x817F817F, 0x7F818181,
+0x81818181, 0x817F817F, 0x817F7F81, 0x81818181, 0x817F7F7F, 0x7F7F8181, 0x7F817F81, 0x8181817F,
+0x7F7F7F81, 0x7F817F81, 0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x7F818181, 0x7F818181, 0x817F7F81,
+0x7F7F7F7F, 0x81818181, 0x7F817F7F, 0x8181817F, 0x81818181, 0x81817F7F, 0x81818181, 0x7F818181,
+0x81817F81, 0x7F81817F, 0x7F817F7F, 0x7F817F81, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x817F817F,
+0x817F7F7F, 0x81818181, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x7F81817F, 0x81818181, 0x7F7F7F81,
+0x7F7F8181, 0x7F818181, 0x817F7F81, 0x7F818181, 0x817F817F, 0x7F817F81, 0x7F81817F, 0x7F817F7F,
+0x7F817F7F, 0x81817F7F, 0x81817F81, 0x817F7F7F, 0x81817F81, 0x817F7F81, 0x817F7F7F, 0x7F817F7F,
+0x817F817F, 0x7F7F8181, 0x817F8181, 0x817F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F817F81, 0x7F817F7F,
+0x7F7F817F, 0x7F817F81, 0x81817F7F, 0x81817F81, 0x7F81817F, 0x81818181, 0x7F817F7F, 0x8181817F,
+0x817F8181, 0x7F7F7F81, 0x817F7F81, 0x817F817F, 0x817F8181, 0x7F818181, 0x7F81817F, 0x7F7F8181,
+0x7F81817F, 0x7F81817F, 0x81818181, 0x7F7F7F81, 0x7F818181, 0x817F7F81, 0x8181817F, 0x7F818181,
+0x7F7F817F, 0x81818181, 0x817F7F81, 0x7F817F81, 0x8181817F, 0x7F81817F, 0x817F8181, 0x7F7F8181,
+0x81818181, 0x7F7F817F, 0x7F818181, 0x817F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F,
+0x817F7F81, 0x7F81817F, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x7F7F817F, 0x7F818181, 0x7F817F81,
+0x817F7F81, 0x7F818181, 0x81818181, 0x817F8181, 0x81817F7F, 0x7F817F81, 0x7F7F7F7F, 0x817F7F7F,
+0x7F7F817F, 0x817F8181, 0x817F7F7F, 0x7F817F81, 0x7F7F7F81, 0x7F818181, 0x7F81817F, 0x81818181,
+0x7F818181, 0x817F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F8181, 0x81818181, 0x81817F81, 0x7F818181,
+0x81817F81, 0x817F8181, 0x7F81817F, 0x8181817F, 0x7F7F8181, 0x817F817F, 0x7F817F7F, 0x7F7F8181,
+0x817F7F81, 0x817F8181, 0x7F817F81, 0x7F818181, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x7F81817F,
+0x7F818181, 0x7F7F7F81, 0x817F7F7F, 0x7F81817F, 0x817F7F7F, 0x8181817F, 0x81818181, 0x7F7F7F81,
+0x7F817F81, 0x7F818181, 0x7F7F817F, 0x7F817F81, 0x7F7F7F81, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F81,
+0x7F817F81, 0x7F818181, 0x7F817F81, 0x7F7F7F7F, 0x7F81817F, 0x8181817F, 0x817F7F7F, 0x7F7F8181,
+0x81817F7F, 0x81817F7F, 0x7F818181, 0x81817F81, 0x81817F81, 0x7F7F817F, 0x817F8181, 0x817F8181,
+0x7F818181, 0x7F81817F, 0x8181817F, 0x7F7F817F, 0x81818181, 0x7F7F7F81, 0x81818181, 0x7F7F7F7F,
+0x817F817F, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x7F818181, 0x817F7F81, 0x7F7F817F, 0x817F8181,
+0x7F817F81, 0x817F8181, 0x8181817F, 0x81817F7F, 0x7F817F81, 0x7F7F8181, 0x7F7F8181, 0x7F818181,
+0x817F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x7F7F7F7F, 0x817F817F, 0x7F7F8181,
+0x817F7F7F, 0x7F817F81, 0x81817F81, 0x7F81817F, 0x81817F7F, 0x817F7F7F, 0x7F81817F, 0x7F817F81,
+0x7F7F7F7F, 0x817F7F7F, 0x7F817F81, 0x817F817F, 0x81817F81, 0x81817F7F, 0x7F817F81, 0x7F7F7F81,
+0x7F7F7F7F, 0x8181817F, 0x817F7F81, 0x7F81817F, 0x7F81817F, 0x81817F7F, 0x8181817F, 0x81817F7F,
+0x7F817F81, 0x7F818181, 0x817F817F, 0x81817F81, 0x7F7F8181, 0x817F7F81
+
+output0 =
+0x02524C20, 0xB9B1FEA2, 0xC1BAB7E5, 0xEF5714CB, 0x7DE6A64D, 0xA05F9DC9, 0x0747D1E3, 0x3B20BC86,
+0x6FCBDB0F, 0xF2FB7A23, 0x79D5E062, 0x5BF4E7C3, 0xD4A68A37, 0x07B4A6AD, 0x37E911F9, 0x7FE7B30A,
+0xBBC284A2, 0xD38D6136, 0x25FAB76B, 0xBEBBF534, 0x9A88F9DB, 0xE37FD52D, 0x691DD493, 0xED2F738C,
+0x89A96EA0, 0xD981246A, 0x17CC820E, 0x07E3B463, 0xC9FC2590, 0x7475A33C, 0xA5151BB4, 0x1F7E759E,
+0x9554F964, 0xD0FA01F4, 0xD31774D2, 0xEB73A9F6, 0x8C9FBCB1, 0xF83010FB, 0x1909E09F, 0xC46023EB,
+0x02AEDC62, 0xC6352CC7, 0x674BDC6D, 0xE17CD747, 0x4E25B0B3, 0x4BFF6B17, 0x12C9AAA3, 0xC2BC91CD,
+0x44BE23A2, 0x8A72A157, 0x6E0DAD1F, 0x6CA69A09, 0xB55B582E, 0x01818B31, 0x5CA5CAB6, 0x1917AB24,
+0x38F98BCD, 0x01917487, 0x05906FDD, 0x760AFCBA, 0x19671085, 0x64E3546E, 0xEC10F922, 0x3CF286CA,
+0x68E273EA, 0xF1001325, 0x5DCB3B49, 0xE9547370, 0x65D26AE6, 0xF621256C, 0x25D6D99C, 0x7862EBA0,
+0x43365DB0, 0x4DBF06C5, 0x92FCAA02, 0xB0FD58FA, 0x910E80A6, 0x93D24A67, 0x6E39B144, 0x3D46D6F6,
+0xEDC55081, 0x33CD70C7, 0xC74B6E8E, 0x91AA27B9, 0x55B3542D, 0xEBF8046A, 0xB9ABDB94, 0x97FC38A8,
+0xD5837B4D, 0x764B1809, 0xFBE2096A, 0xC23887AC, 0x2A45029B, 0xCBB7DF70, 0x674654E1, 0x0C6A06BD,
+0xB3E8853E, 0x03FCC4CE, 0x26806F2E, 0x2CEB35B0, 0x10538B03, 0x94B059B8, 0xA95E7FFA, 0x48AD3D0A,
+0xEB9091E1, 0x972E31EF, 0x5EBC6F8F, 0x947FF108, 0xCB3123FA, 0xFEE1D939, 0xF3DC5C49, 0xA92927AE,
+0xF49BB8D0, 0xAA59F730, 0x4A66D1CD, 0x030E1ADF, 0x238D5B19, 0x96F861F1, 0x915424E4, 0x9127880C,
+0x8E779839, 0x87375FCE, 0x61FB3D79, 0x96B1EE83, 0x47BF6667, 0x19E7D408, 0x7E91137F, 0x0E4AD8E8,
+0xDABD2E45, 0x9B60873F, 0xD0294A65, 0x2A38A862, 0x59DD046D, 0x9832BB79, 0xA5870DB6, 0xB3F1CC48,
+0x7E9A8132, 0xEEA2E4BC, 0xF23ED87B, 0x550E011F, 0x9620E0C0, 0xE7CF0834, 0xDEE69623, 0x6184D512,
+0xD3D55728, 0xFA7711D4, 0x9C77B0F9, 0x8A26462B, 0xB3F5C8D5, 0x1123246D, 0x78F36272, 0x940EE0F9,
+0x757BF240, 0x7EE2B6D0, 0xD40FD5A1, 0xAB4205CA, 0x96E6B758, 0xAC5F4294, 0xC9268C66, 0xB48DC535,
+0x3CF6ED4C, 0xF187EFED, 0x7A09B08D, 0x8709EFCE, 0x267B2468, 0x0015D770, 0xDF1B90BF, 0xA03DAD85,
+0x2633012E, 0xE5437125, 0x58B79AFF, 0xB929C532, 0x6D890DC9, 0x89A59AD2, 0x2BB99316, 0x41B5B0EB,
+0x7304B295, 0xB37F6708, 0x2F84A68E, 0x3637D79A, 0xDD36687B, 0x904BF7B6, 0x6A2CF453, 0x733DED54,
+0x5DF48BAA, 0xC3FCC99F, 0x8E3BE1DB, 0x61D9CF2D, 0xB7DC202B, 0xA959FF95, 0x860D0F14, 0x4008C478,
+0xD9325A51, 0x27A29D4C, 0x308FE6D4, 0x7A1AA889, 0x5BD38393, 0xCBFA5D
+
+basegraph=
+1
+
+z_c=
+320
+
+n_cb=
+21120
+
+q_m=
+4
+
+n_filler=
+688
+
+e =
+21592
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+iter_max =
+20
+
+expected_iter_count =
+3
+
+op_flags =
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v7813.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v7813.data
new file mode 100644
index 000000000..c656fd3e4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v7813.data
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x7F817F81, 0x7F81817F, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x817F8181, 0x817F7F7F, 0x7F817F81,
+0x817F7F7F, 0x8181817F, 0x8181817F
+
+output0 =
+0x8C4DEB9F, 0x52
+
+basegraph=
+2
+
+z_c=
+7
+
+n_cb=
+350
+
+q_m=
+2
+
+n_filler=
+30
+
+e =
+44
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+iter_max =
+8
+
+expected_iter_count =
+6
+
+op_flags =
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8480.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8480.data
new file mode 100644
index 000000000..ddebf7bee
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8480.data
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x81817F81, 0x817F7F7F, 0x7F817F7F, 0x7F817F7F, 0x8181817F, 0x817F817F, 0x817F817F, 0x7F818181,
+0x7F817F7F, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x81817F7F, 0x8181817F, 0x81818181,
+0x817F8181, 0x7F7F7F81, 0x7F818181, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F817F81, 0x817F7F81,
+0x7F7F7F81, 0x817F8181, 0x7F818181, 0x817F817F, 0x7F7F817F, 0x7F817F7F, 0x7F817F7F, 0x7F81817F,
+0x7F818181, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x7F81817F, 0x817F7F81, 0x81817F81, 0x817F817F,
+0x7F7F8181, 0x817F7F81, 0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F, 0x7F81817F, 0x7F7F817F,
+0x8181817F, 0x817F8181, 0x7F817F81, 0x817F8181, 0x8181817F, 0x817F8181, 0x7F817F81, 0x8181817F,
+0x7F7F8181, 0x7F7F817F, 0x7F81817F, 0x81817F7F, 0x7F7F8181, 0x8181817F, 0x7F818181, 0x81817F81,
+0x7F7F817F, 0x7F7F8181, 0x7F817F81, 0x7F81817F, 0x817F7F81, 0x81818181, 0x7F817F81, 0x7F7F7F7F,
+0x7F817F7F, 0x81817F7F, 0x817F7F7F, 0x7F818181, 0x7F7F817F, 0x81817F81, 0x8181817F, 0x7F81817F,
+0x8181817F, 0x817F8181, 0x7F817F7F, 0x817F817F, 0x81818181, 0x7F81817F, 0x817F817F, 0x81817F81,
+0x7F7F8181, 0x817F7F7F, 0x7F818181, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x7F817F81, 0x81818181,
+0x81817F81, 0x817F7F7F, 0x817F7F81, 0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x817F817F, 0x7F7F817F,
+0x81817F7F, 0x7F7F817F, 0x817F8181, 0x817F8181, 0x7F81817F, 0x817F817F, 0x817F7F7F, 0x81817F81,
+0x81817F7F, 0x8181817F, 0x817F7F81, 0x81817F81, 0x7F7F817F, 0x7F7F8181, 0x7F7F817F, 0x81817F81,
+0x81817F7F, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x8181817F, 0x81818181, 0x7F817F7F, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F7F81, 0x817F8181, 0x7F817F81, 0x81818181, 0x8181817F, 0x7F81817F, 0x7F818181,
+0x7F7F817F, 0x7F7F7F81, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x817F7F7F, 0x7F81817F, 0x7F7F7F7F,
+0x7F818181, 0x7F817F7F, 0x817F7F81, 0x7F81817F, 0x7F7F8181, 0x7F7F8181, 0x8181817F, 0x7F7F817F,
+0x7F81817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x817F7F81, 0x7F7F8181, 0x817F8181, 0x817F7F7F,
+0x7F7F817F, 0x817F8181, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x81817F81,
+0x7F7F817F, 0x8181817F, 0x817F817F, 0x7F7F7F7F, 0x7F818181, 0x7F7F817F, 0x7F818181, 0x817F7F81,
+0x7F7F7F7F, 0x7F81817F, 0x817F7F7F, 0x81817F81, 0x7F817F81, 0x81818181, 0x7F7F8181, 0x817F817F,
+0x7F817F81, 0x81817F81, 0x7F817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x81817F81, 0x817F7F81, 0x7F7F817F,
+0x81818181, 0x7F7F7F7F, 0x817F817F, 0x817F7F81, 0x7F818181, 0x817F8181, 0x817F817F, 0x7F7F817F,
+0x7F817F81
+
+output0 =
+0x76332859, 0x417B1254, 0xEC8A8CFE, 0xE7EFCD06, 0x43C5BDA2, 0x2EACD776, 0x6CD515AC, 0x6D6E04AC,
+0xBC2D9F85, 0xD3643553, 0xD0C8DF8E, 0x235B434A, 0xD7AB7643, 0xA4D9C420, 0x372FA858, 0xF813CE10,
+0xE0C238F6, 0x07853FD4, 0xE04E40F2, 0x0EE765A9, 0x6EEAFCBC, 0xA7059C68, 0xFBBC
+
+basegraph=
+2
+
+z_c=
+72
+
+n_cb=
+3600
+
+q_m=
+2
+
+n_filler=
+0
+
+e =
+804
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+iter_max =
+8
+
+expected_iter_count =
+3
+
+op_flags =
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8568.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8568.data
new file mode 100644
index 000000000..0b95e4e0f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v8568.data
@@ -0,0 +1,255 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x7F7F7F7F, 0x7F7F7F7F, 0x8181817F, 0x7F7F8181, 0x817F7F7F, 0x7F817F81, 0x7F7F7F81, 0x81818181,
+0x7F818181, 0x817F817F, 0x81818181, 0x7F7F7F7F, 0x7F81817F, 0x7F7F8181, 0x7F7F7F81, 0x81817F7F,
+0x7F817F7F, 0x817F8181, 0x7F818181, 0x817F817F, 0x8181817F, 0x7F7F8181, 0x8181817F, 0x817F7F7F,
+0x7F7F817F, 0x7F7F817F, 0x81818181, 0x81817F81, 0x7F7F7F81, 0x7F81817F, 0x7F818181, 0x7F818181,
+0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x7F818181, 0x7F81817F, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F,
+0x81817F81, 0x817F817F, 0x817F817F, 0x7F817F81, 0x7F7F817F, 0x7F817F7F, 0x817F817F, 0x7F7F7F81,
+0x7F7F817F, 0x817F817F, 0x81818181, 0x7F81817F, 0x7F817F81, 0x7F7F7F7F, 0x7F818181, 0x7F7F8181,
+0x7F818181, 0x7F81817F, 0x7F81817F, 0x81817F7F, 0x817F7F81, 0x7F818181, 0x7F817F81, 0x7F818181,
+0x81817F81, 0x7F7F8181, 0x7F7F7F81, 0x7F7F817F, 0x8181817F, 0x817F8181, 0x7F817F7F, 0x7F7F7F81,
+0x7F7F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F817F, 0x817F7F7F, 0x817F7F81, 0x817F7F81, 0x81818181,
+0x7F817F81, 0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F8181, 0x817F8181, 0x7F81817F,
+0x817F817F, 0x7F817F81, 0x7F7F8181, 0x7F817F81, 0x7F7F817F, 0x7F817F81, 0x81817F7F, 0x817F817F,
+0x81818181, 0x7F7F7F81, 0x8181817F, 0x81818181, 0x7F7F7F81, 0x817F8181, 0x817F8181, 0x7F81817F,
+0x7F7F817F, 0x817F817F, 0x7F7F817F, 0x7F81817F, 0x7F817F81, 0x7F7F7F81, 0x81818181, 0x7F817F81,
+0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x7F7F8181, 0x7F7F7F7F, 0x817F8181, 0x7F7F8181, 0x81818181,
+0x81818181, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F81817F, 0x817F7F81,
+0x81817F7F, 0x7F7F8181, 0x817F8181, 0x7F817F7F, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x7F817F81,
+0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x817F817F, 0x7F818181, 0x817F7F81, 0x817F817F, 0x8181817F,
+0x817F7F81, 0x7F7F7F7F, 0x7F817F81, 0x81818181, 0x817F7F81, 0x81817F81, 0x817F7F81, 0x7F817F7F,
+0x817F8181, 0x7F7F7F81, 0x7F817F81, 0x8181817F, 0x7F817F7F, 0x81817F81, 0x7F7F7F81, 0x7F818181,
+0x7F7F7F81, 0x7F817F81, 0x81818181, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x817F817F, 0x7F818181,
+0x817F817F, 0x81817F7F, 0x81817F81, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x81818181, 0x81818181,
+0x8181817F, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F7F, 0x817F7F7F, 0x7F81817F, 0x817F7F81, 0x7F818181,
+0x7F817F81, 0x7F817F7F, 0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F7F817F, 0x817F8181,
+0x817F817F, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x81817F81,
+0x7F7F7F81, 0x8181817F, 0x7F7F817F, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x81817F81, 0x7F7F7F81,
+0x81818181, 0x7F7F8181, 0x817F7F7F, 0x817F8181, 0x7F81817F, 0x7F7F817F, 0x7F81817F, 0x817F7F81,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x817F7F81, 0x817F8181, 0x7F7F8181, 0x81818181, 0x817F817F,
+0x817F7F7F, 0x7F7F8181, 0x8181817F, 0x7F7F817F, 0x7F7F7F81, 0x7F818181, 0x7F7F817F, 0x81818181,
+0x817F8181, 0x7F817F81, 0x7F7F7F81, 0x7F817F7F, 0x81817F81, 0x7F81817F, 0x817F7F7F, 0x7F7F8181,
+0x817F7F7F, 0x7F7F817F, 0x7F818181, 0x817F7F81, 0x81817F7F, 0x7F81817F, 0x7F818181, 0x81818181,
+0x81817F7F, 0x7F7F7F7F, 0x81817F81, 0x7F817F81, 0x817F8181, 0x7F818181, 0x7F7F7F81, 0x81817F81,
+0x7F818181, 0x7F817F7F, 0x8181817F, 0x8181817F, 0x7F81817F, 0x8181817F, 0x7F7F817F, 0x81817F81,
+0x7F7F817F, 0x7F7F8181, 0x817F8181, 0x817F7F7F, 0x81817F81, 0x81818181, 0x7F818181, 0x81818181,
+0x7F81817F, 0x8181817F, 0x817F8181, 0x81818181, 0x81818181, 0x7F7F7F7F, 0x7F7F7F81, 0x817F817F,
+0x7F7F7F7F, 0x817F7F7F, 0x817F8181, 0x7F817F7F, 0x817F8181, 0x81817F81, 0x817F817F, 0x817F817F,
+0x817F7F7F, 0x7F817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F81, 0x7F7F8181, 0x81818181,
+0x8181817F, 0x81817F7F, 0x817F8181, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x7F7F7F81, 0x7F81817F,
+0x7F817F81, 0x81818181, 0x7F7F8181, 0x81818181, 0x7F7F817F, 0x81817F7F, 0x817F7F7F, 0x81818181,
+0x7F818181, 0x817F7F81, 0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x817F7F7F, 0x817F817F, 0x7F7F8181,
+0x817F817F, 0x7F7F817F, 0x7F817F7F, 0x7F81817F, 0x81817F7F, 0x7F817F7F, 0x817F7F81, 0x7F7F8181,
+0x8181817F, 0x7F817F81, 0x7F818181, 0x7F7F817F, 0x7F818181, 0x7F7F817F, 0x81818181, 0x7F7F7F81,
+0x7F7F7F7F, 0x7F81817F, 0x817F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F, 0x81818181,
+0x7F7F8181, 0x8181817F, 0x7F81817F, 0x81817F81, 0x8181817F, 0x81817F81, 0x7F7F7F7F, 0x7F7F8181,
+0x7F7F7F81, 0x7F817F81, 0x8181817F, 0x7F7F817F, 0x81817F81, 0x817F7F81, 0x81818181, 0x8181817F,
+0x817F7F81, 0x7F817F7F, 0x817F8181, 0x817F817F, 0x7F818181, 0x817F817F, 0x7F81817F, 0x817F8181,
+0x8181817F, 0x81817F7F, 0x817F7F81, 0x81817F7F, 0x817F7F7F, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x7F7F7F81, 0x7F7F8181, 0x7F7F8181, 0x7F817F7F, 0x8181817F, 0x817F8181, 0x817F817F, 0x81818181,
+0x81817F7F, 0x817F7F81, 0x7F81817F, 0x81818181, 0x81818181, 0x7F817F7F, 0x7F81817F, 0x7F7F7F81,
+0x7F7F7F81, 0x7F817F81, 0x7F818181, 0x817F7F7F, 0x7F7F817F, 0x8181817F, 0x7F817F81, 0x7F817F81,
+0x7F817F81, 0x81818181, 0x817F8181, 0x7F817F81, 0x817F7F81, 0x7F7F8181, 0x7F7F817F, 0x8181817F,
+0x81817F81, 0x81817F7F, 0x7F7F8181, 0x81817F81, 0x817F7F81, 0x817F8181, 0x7F818181, 0x817F7F7F,
+0x817F817F, 0x817F8181, 0x7F7F817F, 0x8181817F, 0x7F817F7F, 0x81817F81, 0x7F817F81, 0x8181817F,
+0x817F8181, 0x7F7F817F, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x7F7F7F81, 0x7F817F7F, 0x7F818181,
+0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x817F7F7F, 0x81817F81, 0x81817F81, 0x7F7F817F, 0x7F7F8181,
+0x817F7F7F, 0x817F8181, 0x817F817F, 0x7F817F81, 0x817F817F, 0x7F817F81, 0x817F817F, 0x7F818181,
+0x7F817F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F81817F, 0x7F81817F, 0x7F81817F, 0x7F817F7F, 0x81818181,
+0x7F818181, 0x817F7F7F, 0x817F7F81, 0x81818181, 0x81817F81, 0x817F8181, 0x7F7F7F81, 0x7F81817F,
+0x7F818181, 0x817F817F, 0x817F7F7F, 0x7F817F7F, 0x817F8181, 0x7F7F8181, 0x81818181, 0x817F7F7F,
+0x7F7F8181, 0x817F7F7F, 0x7F818181, 0x7F817F7F, 0x817F817F, 0x7F817F7F, 0x81817F81, 0x7F81817F,
+0x817F7F81, 0x817F7F81, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F817F7F, 0x7F818181,
+0x7F7F8181, 0x7F7F817F, 0x7F7F817F, 0x81817F7F, 0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x817F817F,
+0x817F7F7F, 0x7F818181, 0x81817F81, 0x817F817F, 0x81818181, 0x817F7F81, 0x817F7F7F, 0x7F7F817F,
+0x7F7F8181, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x81817F7F, 0x8181817F, 0x817F8181,
+0x817F817F, 0x81818181, 0x7F7F817F, 0x817F8181, 0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x817F7F7F,
+0x817F817F, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x7F818181, 0x7F7F8181, 0x8181817F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F81817F, 0x7F817F81, 0x817F7F7F, 0x817F7F81, 0x8181817F, 0x81818181, 0x817F7F81,
+0x7F81817F, 0x7F817F7F, 0x7F817F7F, 0x81818181, 0x81817F7F, 0x7F81817F, 0x81817F7F, 0x81818181,
+0x7F7F7F81, 0x817F817F, 0x7F7F8181, 0x7F817F81, 0x817F817F, 0x817F8181, 0x7F7F7F7F, 0x7F7F817F,
+0x7F7F7F81, 0x7F818181, 0x7F817F81, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x7F817F81, 0x817F8181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F817F, 0x81817F7F, 0x81817F7F, 0x81817F81, 0x81817F81, 0x8181817F,
+0x817F8181, 0x7F817F7F, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x7F81817F, 0x7F818181, 0x81817F81,
+0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x81817F81, 0x7F7F8181, 0x7F818181, 0x817F817F, 0x7F7F7F81,
+0x7F818181, 0x7F817F81, 0x817F8181, 0x817F7F7F, 0x7F817F81, 0x817F7F7F, 0x8181817F, 0x81817F7F,
+0x7F818181, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x817F817F, 0x817F7F81, 0x8181817F,
+0x7F818181, 0x7F7F7F81, 0x7F7F7F7F, 0x81817F7F, 0x7F7F817F, 0x8181817F, 0x7F817F7F, 0x7F817F7F,
+0x7F7F7F81, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x817F8181, 0x7F818181, 0x7F817F81, 0x7F7F7F7F,
+0x7F818181, 0x7F7F7F7F, 0x81817F81, 0x7F818181, 0x817F8181, 0x81817F81, 0x817F7F81, 0x7F7F8181,
+0x7F7F7F81, 0x817F817F, 0x7F817F81, 0x7F818181, 0x7F817F81, 0x81818181, 0x81817F81, 0x7F817F81,
+0x7F7F7F81, 0x7F817F81, 0x81818181, 0x81817F81, 0x817F817F, 0x7F7F8181, 0x817F7F7F, 0x81817F81,
+0x7F7F7F7F, 0x817F7F81, 0x817F817F, 0x7F817F7F, 0x7F81817F, 0x81817F81, 0x81818181, 0x7F81817F,
+0x81817F81, 0x81817F81, 0x81817F7F, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x817F7F81, 0x8181817F,
+0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x8181817F, 0x7F817F81, 0x7F81817F, 0x7F817F7F, 0x7F817F81,
+0x7F818181, 0x8181817F, 0x817F817F, 0x7F7F7F81, 0x81817F7F, 0x817F7F81, 0x8181817F, 0x7F818181,
+0x7F7F8181, 0x7F7F7F7F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x81818181, 0x817F8181, 0x81817F7F,
+0x7F7F817F, 0x81817F7F, 0x7F818181, 0x7F817F81, 0x81817F7F, 0x81817F81, 0x817F8181, 0x8181817F,
+0x81817F7F, 0x7F818181, 0x7F7F817F, 0x817F8181, 0x7F7F8181, 0x8181817F, 0x7F817F7F, 0x7F7F817F,
+0x817F8181, 0x8181817F, 0x7F7F8181, 0x7F817F7F, 0x8181817F, 0x7F817F7F, 0x817F7F81, 0x81817F7F,
+0x8181817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F81817F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F817F, 0x817F7F81,
+0x81818181, 0x7F7F8181, 0x7F7F7F81, 0x81817F7F, 0x7F817F81, 0x817F7F81, 0x81817F81, 0x81817F7F,
+0x7F81817F, 0x7F817F7F, 0x81817F81, 0x7F81817F, 0x7F81817F, 0x817F8181, 0x81818181, 0x7F817F81,
+0x817F817F, 0x7F7F7F7F, 0x8181817F, 0x817F817F, 0x7F81817F, 0x817F817F, 0x7F7F817F, 0x7F818181,
+0x7F7F8181, 0x7F817F7F, 0x817F817F, 0x8181817F, 0x81818181, 0x8181817F, 0x817F8181, 0x817F8181,
+0x7F818181, 0x8181817F, 0x817F817F, 0x817F8181, 0x7F817F7F, 0x7F81817F, 0x7F817F81, 0x8181817F,
+0x7F817F81, 0x7F81817F, 0x7F817F81, 0x817F7F7F, 0x81817F81, 0x81818181, 0x817F817F, 0x817F7F7F,
+0x817F817F, 0x817F8181, 0x81817F7F, 0x7F817F7F, 0x7F818181, 0x817F7F7F, 0x7F81817F, 0x81817F7F,
+0x817F817F, 0x81817F7F, 0x7F818181, 0x817F7F81, 0x817F8181, 0x81817F81, 0x817F7F7F, 0x81818181,
+0x817F8181, 0x81817F81, 0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x7F7F817F, 0x817F7F7F, 0x8181817F,
+0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x7F81817F, 0x817F8181, 0x7F81817F, 0x81817F81,
+0x7F817F7F, 0x81817F81, 0x8181817F, 0x8181817F, 0x81817F7F, 0x817F817F, 0x7F818181, 0x81817F7F,
+0x817F7F7F, 0x8181817F, 0x7F817F7F, 0x7F81817F, 0x7F81817F, 0x817F7F7F, 0x81817F7F, 0x7F817F7F,
+0x7F818181, 0x81817F81, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x81817F81, 0x7F7F8181, 0x817F7F7F,
+0x817F7F7F, 0x7F817F81, 0x7F7F7F81, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F8181,
+0x817F817F, 0x7F7F817F, 0x7F81817F, 0x817F7F7F, 0x817F817F, 0x7F81817F, 0x81818181, 0x81817F7F,
+0x81817F7F, 0x81817F7F, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x81818181, 0x817F817F,
+0x7F7F7F7F, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F81, 0x817F7F81, 0x7F817F81, 0x7F817F81, 0x817F8181,
+0x7F7F817F, 0x817F7F7F, 0x7F817F7F, 0x81817F81, 0x81818181, 0x817F7F81, 0x7F7F817F, 0x7F7F8181,
+0x8181817F, 0x81817F7F, 0x7F817F7F, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x81818181, 0x81817F7F,
+0x8181817F, 0x817F7F81, 0x8181817F, 0x7F7F7F81, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x7F7F7F7F,
+0x7F7F7F7F, 0x7F818181, 0x81817F81, 0x81817F81, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x817F7F81,
+0x7F7F7F81, 0x81817F7F, 0x8181817F, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x7F817F81, 0x817F8181,
+0x7F7F8181, 0x8181817F, 0x7F818181, 0x817F8181, 0x81817F81, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F,
+0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x7F7F7F81, 0x817F7F81, 0x7F81817F, 0x81817F7F, 0x81818181,
+0x81817F81, 0x8181817F, 0x817F7F7F, 0x817F7F7F, 0x817F7F81, 0x7F817F7F, 0x8181817F, 0x81817F81,
+0x7F7F7F7F, 0x817F7F7F, 0x817F7F81, 0x817F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x817F7F7F,
+0x81818181, 0x817F817F, 0x817F7F81, 0x81817F81, 0x817F7F81, 0x817F8181, 0x7F81817F, 0x7F817F81,
+0x7F7F7F7F, 0x8181817F, 0x7F818181, 0x7F7F817F, 0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F817F,
+0x7F817F7F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x817F817F, 0x81817F81,
+0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181, 0x7F817F7F,
+0x7F7F7F81, 0x7F817F81, 0x817F817F, 0x7F7F817F, 0x7F81817F, 0x81818181, 0x817F8181, 0x7F7F8181,
+0x7F817F7F, 0x7F817F81, 0x81817F81, 0x8181817F, 0x81818181, 0x7F81817F, 0x7F817F81, 0x7F7F817F,
+0x817F7F81, 0x817F7F7F, 0x817F7F81, 0x817F7F81, 0x81818181, 0x817F7F7F, 0x8181817F, 0x817F7F81,
+0x81817F7F, 0x7F7F8181, 0x81817F81, 0x7F818181, 0x7F817F7F, 0x817F7F7F, 0x7F81817F, 0x7F817F81,
+0x7F817F81, 0x817F817F, 0x81818181, 0x8181817F, 0x817F817F, 0x7F7F8181, 0x7F817F7F, 0x7F818181,
+0x7F7F817F, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x81817F81, 0x81817F81, 0x817F8181, 0x7F7F8181,
+0x7F7F817F, 0x817F7F81, 0x817F817F, 0x7F81817F, 0x817F817F, 0x81817F81, 0x81817F81, 0x7F7F7F7F,
+0x81818181, 0x817F7F7F, 0x7F7F8181, 0x7F7F8181, 0x7F81817F, 0x817F7F7F, 0x817F7F7F, 0x817F8181,
+0x81818181, 0x81817F7F, 0x7F817F7F, 0x7F817F7F, 0x7F7F8181, 0x817F7F7F, 0x817F7F81, 0x817F8181,
+0x7F7F7F81, 0x7F817F7F, 0x7F81817F, 0x7F817F81, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F7F,
+0x81818181, 0x7F7F7F7F, 0x7F7F8181, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x81817F81, 0x8181817F,
+0x7F817F81, 0x81817F7F, 0x817F817F, 0x7F817F7F, 0x817F817F, 0x7F817F7F, 0x7F81817F, 0x7F7F7F7F,
+0x817F7F81, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F,
+0x817F7F7F, 0x7F7F7F81, 0x817F7F7F, 0x7F81817F, 0x7F817F81, 0x7F817F81, 0x7F81817F, 0x817F7F7F,
+0x7F818181, 0x81818181, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81, 0x8181817F, 0x7F81817F, 0x7F81817F,
+0x817F7F81, 0x81818181, 0x817F817F, 0x817F7F81, 0x817F8181, 0x81817F81, 0x81818181, 0x7F7F7F7F,
+0x7F7F817F, 0x7F817F81, 0x7F7F817F, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F, 0x81817F7F, 0x7F818181,
+0x817F7F7F, 0x7F818181, 0x8181817F, 0x81818181, 0x81817F7F, 0x7F7F7F81, 0x817F7F7F, 0x8181817F,
+0x817F817F, 0x7F817F7F, 0x8181817F, 0x81817F81, 0x7F817F81, 0x7F7F8181, 0x81817F81, 0x817F8181,
+0x7F7F7F7F, 0x817F8181, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x817F8181, 0x7F818181, 0x7F818181,
+0x7F817F7F, 0x7F7F8181, 0x7F817F7F, 0x817F7F7F, 0x7F817F81, 0x81818181, 0x817F817F, 0x7F7F7F81,
+0x81818181, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F8181,
+0x817F8181, 0x81817F81, 0x81817F7F, 0x817F7F81, 0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x7F7F817F,
+0x7F7F817F, 0x817F7F81, 0x817F7F81, 0x817F817F, 0x7F7F8181, 0x81818181, 0x7F7F7F81, 0x7F7F7F81,
+0x817F817F, 0x7F817F7F, 0x7F7F8181, 0x7F81817F, 0x7F7F8181, 0x8181817F, 0x817F8181, 0x81817F7F,
+0x817F8181, 0x81817F81, 0x7F7F7F7F, 0x817F7F81, 0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x7F7F7F81,
+0x7F7F817F, 0x7F7F817F, 0x817F817F, 0x7F817F7F, 0x7F817F7F, 0x7F817F7F, 0x7F817F7F, 0x7F817F7F,
+0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x81817F7F, 0x817F817F, 0x81818181, 0x81817F7F, 0x7F7F7F7F,
+0x817F8181, 0x817F817F, 0x7F81817F, 0x7F81817F, 0x7F7F817F, 0x817F7F7F, 0x817F7F81, 0x81817F81,
+0x7F7F817F, 0x817F817F, 0x7F817F81, 0x7F7F817F, 0x7F7F817F, 0x81818181, 0x8181817F, 0x7F7F7F7F,
+0x7F817F81, 0x817F817F, 0x7F7F7F7F, 0x7F7F8181, 0x7F81817F, 0x7F817F81, 0x817F7F81, 0x817F817F,
+0x7F7F7F7F, 0x8181817F, 0x81817F7F, 0x817F8181, 0x817F7F81, 0x7F81817F, 0x7F7F7F81, 0x817F7F81,
+0x7F817F81, 0x81817F81, 0x817F7F7F, 0x81818181, 0x81818181, 0x7F81817F, 0x817F817F, 0x7F818181,
+0x7F7F7F7F, 0x7F81817F, 0x7F817F81, 0x817F8181, 0x817F7F7F, 0x7F818181, 0x81818181, 0x8181817F,
+0x817F7F7F, 0x7F7F817F, 0x81817F81, 0x7F7F7F81, 0x8181817F, 0x81818181, 0x7F817F81, 0x7F7F817F,
+0x817F817F, 0x7F7F8181, 0x817F7F7F, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F81817F,
+0x7F7F817F, 0x817F817F, 0x817F7F81, 0x7F7F817F, 0x817F7F7F, 0x81817F81, 0x81817F81, 0x7F7F7F81,
+0x7F7F7F81, 0x7F818181, 0x7F81817F, 0x7F7F7F7F, 0x7F7F8181, 0x817F8181, 0x7F7F817F, 0x7F818181,
+0x7F817F81, 0x81817F7F, 0x7F818181, 0x817F7F81, 0x7F81817F, 0x817F7F81, 0x7F818181, 0x81817F7F,
+0x7F818181, 0x817F817F, 0x7F7F7F7F, 0x7F818181, 0x81817F81, 0x7F7F7F81, 0x81818181, 0x7F818181,
+0x7F7F7F7F, 0x7F817F7F, 0x7F817F81, 0x81817F81, 0x817F7F81, 0x817F7F81, 0x817F7F7F, 0x81817F7F,
+0x7F818181, 0x7F817F81, 0x7F7F817F, 0x81817F81, 0x7F817F81, 0x8181817F, 0x81817F7F, 0x7F7F7F7F,
+0x7F7F817F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x81818181,
+0x7F817F7F, 0x7F7F7F81, 0x8181817F, 0x7F7F7F7F, 0x7F7F7F81, 0x817F817F, 0x81817F81, 0x7F7F7F7F,
+0x817F8181, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F8181, 0x817F7F7F, 0x81818181, 0x7F7F8181, 0x7F7F7F81,
+0x7F817F7F, 0x81817F7F, 0x81817F7F, 0x7F81817F, 0x7F818181, 0x817F7F7F, 0x7F81817F, 0x7F7F817F,
+0x81818181, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x81818181, 0x817F7F81, 0x7F817F81, 0x81818181,
+0x7F817F7F, 0x817F7F81, 0x8181817F, 0x7F81817F, 0x7F817F7F, 0x817F8181, 0x817F817F, 0x817F7F81,
+0x7F7F7F7F, 0x7F817F7F, 0x817F8181, 0x7F818181, 0x817F7F81, 0x817F817F, 0x8181817F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F7F817F, 0x7F817F7F, 0x81818181, 0x7F7F7F81, 0x7F818181, 0x7F818181, 0x817F7F81,
+0x7F817F7F, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x8181817F, 0x8181817F, 0x7F7F817F,
+0x7F7F817F, 0x8181817F, 0x817F7F81, 0x7F817F81, 0x7F818181, 0x7F818181, 0x7F7F7F81, 0x817F817F,
+0x8181817F, 0x817F7F7F, 0x81818181, 0x7F81817F, 0x81817F81, 0x7F81817F, 0x81818181, 0x817F7F81,
+0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181, 0x81818181, 0x7F7F817F, 0x8181817F, 0x8181817F,
+0x7F817F81, 0x817F7F7F, 0x8181817F, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x7F7F7F81, 0x817F7F7F,
+0x817F817F, 0x81818181, 0x7F817F7F, 0x817F8181, 0x8181817F, 0x81817F7F, 0x81817F81, 0x7F7F7F81,
+0x7F817F7F, 0x7F818181, 0x8181817F, 0x7F7F817F, 0x7F817F81, 0x7F7F8181, 0x7F7F8181, 0x8181817F,
+0x81817F7F, 0x7F81817F, 0x81817F7F, 0x7F7F7F81, 0x7F81817F, 0x7F817F7F, 0x81818181, 0x7F7F7F81,
+0x7F81817F, 0x7F81817F, 0x7F7F817F, 0x7F818181, 0x7F7F7F81, 0x81818181, 0x7F818181, 0x7F81817F,
+0x81817F81, 0x817F7F81, 0x817F7F81, 0x81817F81, 0x81818181, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F81,
+0x817F817F, 0x7F7F7F7F, 0x81817F7F, 0x81817F7F, 0x8181817F, 0x7F818181, 0x81818181, 0x817F817F,
+0x817F7F81, 0x7F7F8181, 0x81817F7F, 0x817F7F81, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F818181,
+0x7F817F81, 0x817F7F7F, 0x7F7F8181, 0x81818181, 0x7F7F817F, 0x7F817F81, 0x817F7F7F, 0x817F7F7F,
+0x7F817F81, 0x7F817F81, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x81818181, 0x81818181, 0x7F818181,
+0x817F7F81, 0x7F7F817F, 0x7F7F817F, 0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x81817F81, 0x7F7F7F7F,
+0x7F817F7F, 0x81817F7F, 0x7F81817F, 0x817F8181, 0x817F8181, 0x81818181, 0x7F7F8181, 0x7F7F7F81,
+0x817F7F7F, 0x7F7F7F81, 0x81818181, 0x81817F81, 0x8181817F, 0x817F7F7F, 0x8181817F, 0x7F7F8181,
+0x81818181, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x817F7F81, 0x817F7F7F,
+0x817F817F, 0x7F817F7F, 0x81817F81, 0x7F7F8181, 0x7F7F817F, 0x817F817F, 0x7F81817F, 0x7F817F81,
+0x7F817F7F, 0x817F8181, 0x817F7F81, 0x7F81817F, 0x817F7F81, 0x817F7F81, 0x81818181, 0x7F818181,
+0x81817F7F, 0x817F8181, 0x81817F81, 0x7F817F81, 0x81818181, 0x7F818181, 0x7F7F817F, 0x817F7F7F,
+0x817F7F81, 0x817F7F81, 0x81817F81, 0x7F7F817F, 0x817F7F7F, 0x81817F81, 0x817F817F, 0x7F7F8181,
+0x817F7F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F817F, 0x7F818181, 0x817F817F, 0x817F817F, 0x817F7F7F,
+0x817F8181, 0x7F818181, 0x7F7F8181, 0x817F8181, 0x817F8181, 0x817F7F81, 0x7F7F7F7F, 0x7F7F817F,
+0x7F7F7F81, 0x7F7F7F7F, 0x81817F81, 0x81817F81, 0x81817F7F, 0x81818181, 0x817F817F, 0x7F7F7F7F,
+0x7F818181, 0x7F818181, 0x81817F81, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F, 0x8181817F,
+0x817F8181, 0x7F7F7F81, 0x7F7F817F, 0x817F817F, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F817F7F,
+0x817F817F, 0x817F8181, 0x817F8181, 0x7F7F817F, 0x7F81817F, 0x817F8181, 0x817F817F, 0x81818181,
+0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x7F818181, 0x7F7F817F, 0x8181817F, 0x7F817F81,
+0x817F7F7F, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x7F81817F, 0x817F817F, 0x7F7F817F, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F8181, 0x817F8181, 0x817F817F, 0x81817F7F, 0x7F817F7F, 0x81817F7F, 0x7F7F8181,
+0x8181817F, 0x817F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x8181817F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81,
+0x7F817F81, 0x81817F7F, 0x817F817F, 0x7F7F817F, 0x7F817F81, 0x7F7F7F7F, 0x817F7F81, 0x8181817F,
+0x81817F81, 0x7F7F817F, 0x7F7F817F, 0x81817F7F, 0x7F7F8181, 0x7F7F817F, 0x8181817F, 0x81818181,
+0x817F7F81, 0x7F818181, 0x81818181, 0x81818181, 0x817F817F, 0x817F8181, 0x7F7F7F81, 0x7F7F7F7F,
+0x7F7F8181, 0x7F81817F, 0x817F8181, 0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x7F817F81, 0x7F81817F,
+0x7F7F8181, 0x7F817F7F, 0x7F7F7F81, 0x7F817F7F, 0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F817F7F,
+0x7F7F8181, 0x817F817F, 0x7F81817F, 0x7F7F817F, 0x7F7F817F, 0x7F81817F, 0x7F7F7F81, 0x7F7F7F81
+
+output0 =
+0xB6D49CE2, 0x3E96B93F, 0xF02009F6, 0x2DF3D30D, 0x3B06C160, 0x646C69CC, 0x54439F0F, 0xCE0D12C3,
+0x66E8BFD5, 0xA9D22B0C, 0xA9E7343B, 0x2B6EEF01, 0x6B6966C0, 0xB98FE144, 0xC3BF7BAD, 0x1B40DF1C,
+0x973B12DC, 0x46E25E90, 0xB324ACCA, 0x5F0ED2B9, 0xBB4F
+
+basegraph=
+2
+
+z_c=
+72
+
+n_cb=
+3600
+
+q_m=
+2
+
+n_filler=
+64
+
+e =
+6624
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+iter_max =
+20
+
+expected_iter_count =
+6
+
+op_flags =
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v9503.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v9503.data
new file mode 100644
index 000000000..7699ae315
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_dec_v9503.data
@@ -0,0 +1,1215 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_DEC
+
+input0 =
+0x81818181, 0x7F818181, 0x7F81817F, 0x7F817F7F, 0x817F8181, 0x7F7F817F, 0x7F81817F, 0x7F818181,
+0x8181817F, 0x7F7F7F7F, 0x7F81817F, 0x7F7F817F, 0x8181817F, 0x7F817F7F, 0x7F817F7F, 0x817F7F81,
+0x7F7F8181, 0x817F7F7F, 0x7F7F7F81, 0x8181817F, 0x817F7F81, 0x7F7F8181, 0x7F818181, 0x7F7F817F,
+0x817F817F, 0x7F818181, 0x8181817F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F81817F, 0x817F817F,
+0x7F818181, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F8181, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F,
+0x7F7F8181, 0x7F817F7F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F81, 0x81817F7F,
+0x7F817F81, 0x81817F81, 0x7F81817F, 0x817F7F7F, 0x7F7F817F, 0x7F817F7F, 0x817F817F, 0x81817F81,
+0x7F817F81, 0x7F7F817F, 0x7F818181, 0x81817F7F, 0x7F7F817F, 0x7F7F817F, 0x8181817F, 0x7F817F81,
+0x7F7F8181, 0x7F7F7F81, 0x81817F7F, 0x817F8181, 0x81817F81, 0x817F8181, 0x7F817F81, 0x7F7F8181,
+0x81817F7F, 0x7F7F7F7F, 0x81818181, 0x817F817F, 0x817F7F81, 0x7F817F81, 0x81817F7F, 0x817F7F7F,
+0x7F7F8181, 0x817F7F7F, 0x817F7F7F, 0x7F818181, 0x81817F81, 0x7F817F7F, 0x81818181, 0x81817F7F,
+0x817F7F7F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F817F81, 0x7F7F8181,
+0x81818181, 0x817F7F81, 0x817F7F81, 0x81818181, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x7F81817F,
+0x81818181, 0x817F8181, 0x81818181, 0x81817F81, 0x7F7F817F, 0x7F81817F, 0x817F817F, 0x817F7F81,
+0x817F7F81, 0x7F817F81, 0x817F7F81, 0x817F817F, 0x81817F7F, 0x817F7F7F, 0x7F81817F, 0x81818181,
+0x817F8181, 0x817F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x817F7F7F, 0x817F817F, 0x817F817F, 0x8181817F,
+0x81817F81, 0x8181817F, 0x7F81817F, 0x7F817F7F, 0x817F7F7F, 0x81818181, 0x81818181, 0x81817F81,
+0x81817F7F, 0x7F81817F, 0x7F81817F, 0x7F7F8181, 0x817F7F81, 0x81818181, 0x81818181, 0x817F7F7F,
+0x7F7F817F, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x7F7F817F, 0x81817F7F, 0x7F7F817F, 0x81817F7F,
+0x81817F7F, 0x7F81817F, 0x81818181, 0x7F7F817F, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F7F8181,
+0x81817F81, 0x7F7F817F, 0x817F7F81, 0x817F7F7F, 0x7F817F81, 0x81818181, 0x817F7F7F, 0x7F7F7F81,
+0x817F7F81, 0x81818181, 0x817F8181, 0x8181817F, 0x7F81817F, 0x7F818181, 0x817F8181, 0x7F7F7F81,
+0x817F7F81, 0x7F7F8181, 0x817F8181, 0x7F817F7F, 0x81817F7F, 0x7F817F7F, 0x7F7F7F81, 0x8181817F,
+0x817F817F, 0x817F7F81, 0x81817F81, 0x817F817F, 0x7F818181, 0x81817F7F, 0x7F81817F, 0x7F7F8181,
+0x7F817F7F, 0x81818181, 0x8181817F, 0x817F7F7F, 0x7F818181, 0x7F817F81, 0x7F817F7F, 0x817F8181,
+0x817F7F7F, 0x7F817F81, 0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x7F817F7F, 0x817F817F, 0x7F817F7F,
+0x7F7F817F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F817F, 0x7F818181, 0x817F817F, 0x7F7F8181,
+0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F, 0x81818181, 0x817F817F, 0x817F8181, 0x7F817F7F,
+0x7F7F817F, 0x7F7F7F81, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F7F,
+0x7F81817F, 0x7F81817F, 0x8181817F, 0x7F7F7F7F, 0x7F818181, 0x7F7F817F, 0x7F817F81, 0x81817F81,
+0x7F7F817F, 0x7F81817F, 0x81818181, 0x7F7F8181, 0x7F818181, 0x81817F7F, 0x7F7F7F81, 0x7F817F81,
+0x817F7F81, 0x817F7F81, 0x7F7F7F81, 0x817F7F81, 0x7F817F7F, 0x817F7F81, 0x81818181, 0x7F7F7F7F,
+0x7F7F7F81, 0x7F7F817F, 0x7F818181, 0x817F7F7F, 0x817F7F81, 0x81818181, 0x7F7F7F81, 0x7F817F7F,
+0x7F81817F, 0x81817F81, 0x81817F7F, 0x81817F81, 0x817F8181, 0x817F817F, 0x817F817F, 0x817F7F7F,
+0x81817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x817F817F,
+0x817F8181, 0x7F817F81, 0x7F817F7F, 0x7F817F7F, 0x7F7F8181, 0x81817F81, 0x81818181, 0x817F7F7F,
+0x7F81817F, 0x7F81817F, 0x81818181, 0x817F7F81, 0x817F8181, 0x7F81817F, 0x81817F81, 0x817F7F81,
+0x817F7F7F, 0x81818181, 0x7F7F7F7F, 0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F7F7F81, 0x817F817F,
+0x7F81817F, 0x7F81817F, 0x7F81817F, 0x817F817F, 0x7F817F7F, 0x817F7F81, 0x7F7F8181, 0x817F7F7F,
+0x817F7F7F, 0x7F81817F, 0x7F817F7F, 0x7F818181, 0x817F7F7F, 0x7F817F7F, 0x81817F81, 0x7F817F7F,
+0x7F817F7F, 0x817F817F, 0x7F7F7F81, 0x7F7F8181, 0x7F817F81, 0x81817F7F, 0x7F817F7F, 0x7F817F81,
+0x81818181, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F81, 0x7F817F81, 0x81818181, 0x817F8181, 0x8181817F,
+0x7F7F8181, 0x817F817F, 0x817F8181, 0x817F8181, 0x817F7F81, 0x81817F81, 0x7F7F817F, 0x7F7F7F81,
+0x817F7F81, 0x8181817F, 0x81817F7F, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F7F81, 0x81817F7F,
+0x81817F7F, 0x7F7F8181, 0x7F7F817F, 0x7F817F81, 0x7F81817F, 0x817F7F81, 0x7F7F817F, 0x7F7F8181,
+0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x817F817F, 0x81817F81, 0x81817F7F, 0x7F7F817F, 0x7F7F7F7F,
+0x81817F81, 0x7F817F7F, 0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x817F817F, 0x7F818181, 0x7F818181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x7F817F81, 0x7F81817F,
+0x817F817F, 0x81817F7F, 0x8181817F, 0x8181817F, 0x817F7F81, 0x7F817F81, 0x7F7F7F81, 0x81817F7F,
+0x7F7F7F7F, 0x8181817F, 0x817F8181, 0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x7F7F7F7F, 0x7F817F7F,
+0x81817F81, 0x817F817F, 0x7F7F8181, 0x7F81817F, 0x817F7F7F, 0x7F818181, 0x817F817F, 0x7F818181,
+0x8181817F, 0x7F81817F, 0x81817F7F, 0x7F7F7F7F, 0x817F817F, 0x7F817F7F, 0x7F818181, 0x817F8181,
+0x81817F7F, 0x7F817F81, 0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x817F817F, 0x817F8181, 0x817F7F81,
+0x817F817F, 0x817F7F81, 0x7F7F7F81, 0x7F817F7F, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F8181,
+0x817F8181, 0x7F7F817F, 0x81818181, 0x7F81817F, 0x7F818181, 0x81818181, 0x81817F81, 0x7F7F7F7F,
+0x817F7F81, 0x81817F81, 0x8181817F, 0x7F7F817F, 0x817F8181, 0x8181817F, 0x7F817F81, 0x817F7F81,
+0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x81818181, 0x7F7F8181, 0x7F817F81, 0x81817F7F, 0x7F817F7F,
+0x817F7F81, 0x8181817F, 0x7F7F817F, 0x7F818181, 0x7F817F81, 0x7F7F7F81, 0x7F817F81, 0x7F817F81,
+0x7F7F7F81, 0x81817F7F, 0x8181817F, 0x81817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F7F7F, 0x81818181,
+0x8181817F, 0x817F817F, 0x81817F7F, 0x817F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F818181, 0x8181817F,
+0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x81818181, 0x817F7F81, 0x7F7F817F, 0x7F817F81, 0x81817F7F,
+0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x7F7F7F81, 0x817F8181, 0x7F7F7F81,
+0x7F818181, 0x7F7F8181, 0x817F8181, 0x7F817F7F, 0x7F7F8181, 0x7F7F7F81, 0x81818181, 0x81818181,
+0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x817F817F, 0x7F7F8181, 0x81817F81, 0x817F7F81, 0x817F817F,
+0x7F7F817F, 0x7F81817F, 0x7F818181, 0x7F7F817F, 0x7F7F8181, 0x81817F81, 0x81817F81, 0x817F7F7F,
+0x7F7F817F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F817F, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x81817F7F,
+0x817F7F7F, 0x7F81817F, 0x817F7F81, 0x81818181, 0x817F7F81, 0x7F817F7F, 0x8181817F, 0x817F8181,
+0x81817F7F, 0x7F7F8181, 0x7F7F7F81, 0x8181817F, 0x817F8181, 0x817F7F7F, 0x7F81817F, 0x817F7F81,
+0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F81817F, 0x7F7F817F, 0x7F7F7F81, 0x817F817F,
+0x7F817F7F, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F7F, 0x7F817F7F, 0x81818181, 0x7F817F7F,
+0x7F81817F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x817F817F, 0x7F818181, 0x7F7F7F7F, 0x7F817F81,
+0x81817F7F, 0x7F817F81, 0x817F7F81, 0x81817F7F, 0x81817F81, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F81,
+0x8181817F, 0x817F817F, 0x7F817F7F, 0x81817F7F, 0x8181817F, 0x7F818181, 0x817F8181, 0x81817F7F,
+0x7F818181, 0x81818181, 0x7F818181, 0x7F7F8181, 0x7F7F8181, 0x7F818181, 0x81817F7F, 0x7F81817F,
+0x81818181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x8181817F, 0x7F817F81, 0x7F818181, 0x817F817F,
+0x7F7F8181, 0x817F7F81, 0x81817F81, 0x817F817F, 0x81817F7F, 0x817F817F, 0x7F7F817F, 0x7F817F81,
+0x7F817F81, 0x7F7F7F7F, 0x817F7F7F, 0x7F81817F, 0x7F81817F, 0x7F817F81, 0x7F7F7F7F, 0x817F7F7F,
+0x81817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x81818181, 0x817F7F81, 0x81817F81, 0x7F81817F, 0x81818181,
+0x817F8181, 0x7F7F7F7F, 0x81817F7F, 0x81817F81, 0x8181817F, 0x7F7F8181, 0x7F818181, 0x81817F81,
+0x81818181, 0x7F818181, 0x7F817F7F, 0x8181817F, 0x7F817F81, 0x81818181, 0x81817F81, 0x817F7F7F,
+0x7F81817F, 0x7F7F7F7F, 0x817F7F81, 0x81817F7F, 0x81817F7F, 0x7F7F7F81, 0x817F7F81, 0x7F7F8181,
+0x7F7F817F, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F, 0x817F7F7F, 0x81818181, 0x7F817F81, 0x817F7F81,
+0x817F8181, 0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x7F81817F, 0x817F817F, 0x817F7F7F,
+0x817F7F81, 0x8181817F, 0x817F817F, 0x7F81817F, 0x7F7F7F7F, 0x7F7F817F, 0x817F817F, 0x81818181,
+0x7F7F817F, 0x817F7F81, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x7F7F8181, 0x7F81817F, 0x817F817F,
+0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x81817F7F, 0x81817F7F, 0x7F7F7F81, 0x7F817F7F, 0x7F818181,
+0x7F81817F, 0x81817F7F, 0x817F7F7F, 0x7F818181, 0x7F7F7F81, 0x81818181, 0x817F7F81, 0x7F818181,
+0x7F7F7F81, 0x7F81817F, 0x817F817F, 0x7F81817F, 0x81817F81, 0x7F817F7F, 0x81818181, 0x817F7F7F,
+0x7F7F7F7F, 0x7F817F7F, 0x81818181, 0x81817F81, 0x7F7F8181, 0x817F8181, 0x7F817F81, 0x7F7F7F7F,
+0x817F817F, 0x817F8181, 0x7F81817F, 0x7F7F7F7F, 0x7F818181, 0x7F7F8181, 0x817F8181, 0x7F817F81,
+0x8181817F, 0x817F7F81, 0x7F7F7F7F, 0x81817F81, 0x817F7F81, 0x817F7F7F, 0x7F818181, 0x817F8181,
+0x7F7F817F, 0x817F7F7F, 0x7F817F81, 0x81817F7F, 0x7F818181, 0x817F7F7F, 0x7F817F81, 0x7F7F7F81,
+0x7F817F81, 0x81817F7F, 0x817F8181, 0x7F7F7F7F, 0x7F81817F, 0x81817F81, 0x7F817F81, 0x817F8181,
+0x7F7F7F7F, 0x817F8181, 0x81817F81, 0x81817F81, 0x81817F81, 0x7F817F81, 0x7F7F7F7F, 0x81817F7F,
+0x817F817F, 0x7F7F8181, 0x81817F7F, 0x817F817F, 0x817F817F, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F,
+0x7F7F817F, 0x7F81817F, 0x7F7F7F81, 0x7F81817F, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x7F818181,
+0x7F7F8181, 0x7F81817F, 0x7F818181, 0x7F7F7F7F, 0x817F8181, 0x817F7F81, 0x81818181, 0x817F8181,
+0x817F8181, 0x7F817F7F, 0x7F81817F, 0x81818181, 0x817F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x817F7F81,
+0x8181817F, 0x7F818181, 0x7F7F7F81, 0x817F817F, 0x81817F81, 0x81818181, 0x7F7F817F, 0x8181817F,
+0x817F7F7F, 0x81817F7F, 0x7F81817F, 0x81817F7F, 0x7F7F7F7F, 0x81818181, 0x8181817F, 0x7F7F817F,
+0x81818181, 0x81818181, 0x7F818181, 0x817F7F7F, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x81817F81,
+0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x7F817F7F, 0x81817F81, 0x7F817F7F, 0x817F7F81, 0x7F7F817F,
+0x81818181, 0x81817F7F, 0x7F818181, 0x817F8181, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x7F7F7F7F,
+0x8181817F, 0x817F7F7F, 0x81817F7F, 0x7F817F81, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x7F818181,
+0x7F818181, 0x7F818181, 0x817F817F, 0x7F81817F, 0x7F81817F, 0x817F7F81, 0x7F7F8181, 0x7F818181,
+0x8181817F, 0x817F8181, 0x81818181, 0x7F7F8181, 0x81817F7F, 0x7F7F7F81, 0x7F818181, 0x817F817F,
+0x7F818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F81, 0x817F817F, 0x7F817F7F, 0x7F7F817F, 0x8181817F,
+0x81818181, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F81, 0x7F817F7F, 0x7F817F81, 0x817F7F7F,
+0x817F7F81, 0x817F7F7F, 0x7F817F7F, 0x81817F81, 0x7F7F817F, 0x817F817F, 0x7F7F8181, 0x81817F81,
+0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x7F818181, 0x7F7F8181, 0x81817F81, 0x7F818181, 0x7F817F81,
+0x81817F7F, 0x7F7F817F, 0x7F817F7F, 0x7F817F81, 0x7F817F7F, 0x7F7F817F, 0x81817F81, 0x7F817F81,
+0x7F81817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F,
+0x8181817F, 0x817F7F7F, 0x81817F81, 0x7F817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F817F81, 0x817F817F,
+0x7F7F7F7F, 0x817F8181, 0x81817F7F, 0x817F817F, 0x7F7F817F, 0x81817F81, 0x8181817F, 0x7F817F7F,
+0x7F7F7F81, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x817F817F,
+0x7F81817F, 0x817F7F7F, 0x817F8181, 0x817F8181, 0x8181817F, 0x7F7F817F, 0x7F7F8181, 0x81818181,
+0x817F7F7F, 0x81817F81, 0x81818181, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F7F, 0x817F8181,
+0x817F8181, 0x7F817F7F, 0x7F7F817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x81817F7F, 0x7F7F7F81,
+0x7F7F7F81, 0x817F8181, 0x8181817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F81, 0x81817F81, 0x8181817F,
+0x7F817F81, 0x7F7F7F81, 0x817F7F81, 0x7F817F81, 0x7F7F817F, 0x8181817F, 0x7F7F817F, 0x817F8181,
+0x817F7F7F, 0x8181817F, 0x7F81817F, 0x7F7F7F81, 0x81817F81, 0x81818181, 0x81817F7F, 0x7F7F8181,
+0x8181817F, 0x8181817F, 0x817F817F, 0x8181817F, 0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x81818181,
+0x817F817F, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F81, 0x7F81817F, 0x817F7F81, 0x81817F81, 0x7F818181,
+0x7F7F817F, 0x7F7F8181, 0x7F817F7F, 0x81817F81, 0x817F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x8181817F,
+0x817F817F, 0x7F81817F, 0x7F81817F, 0x81817F81, 0x7F817F7F, 0x7F7F817F, 0x81818181, 0x81817F7F,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x7F7F7F81, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F81,
+0x7F7F7F81, 0x8181817F, 0x7F7F7F81, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x7F818181,
+0x81817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x817F817F, 0x81817F7F, 0x81817F7F, 0x7F81817F,
+0x817F7F81, 0x8181817F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F81, 0x8181817F, 0x7F818181, 0x81818181,
+0x7F7F8181, 0x8181817F, 0x7F7F8181, 0x817F7F7F, 0x7F817F81, 0x817F7F81, 0x817F8181, 0x81817F81,
+0x817F817F, 0x7F817F81, 0x7F817F7F, 0x81817F7F, 0x81818181, 0x8181817F, 0x7F7F817F, 0x7F818181,
+0x8181817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x817F817F, 0x7F81817F,
+0x7F7F8181, 0x8181817F, 0x81817F81, 0x7F818181, 0x7F817F7F, 0x817F8181, 0x7F7F8181, 0x7F817F7F,
+0x817F817F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x8181817F, 0x817F7F7F, 0x8181817F, 0x7F7F7F7F,
+0x817F8181, 0x7F7F817F, 0x817F8181, 0x81817F81, 0x7F81817F, 0x7F817F81, 0x81817F7F, 0x8181817F,
+0x81818181, 0x7F7F8181, 0x7F7F7F81, 0x7F81817F, 0x817F8181, 0x817F817F, 0x817F817F, 0x817F8181,
+0x7F817F7F, 0x817F7F7F, 0x7F817F81, 0x7F81817F, 0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F81817F,
+0x7F817F7F, 0x7F817F81, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x817F7F81, 0x7F81817F, 0x817F8181,
+0x7F817F7F, 0x817F817F, 0x7F7F8181, 0x817F7F81, 0x81818181, 0x7F7F7F7F, 0x7F81817F, 0x7F81817F,
+0x817F8181, 0x7F818181, 0x7F7F8181, 0x817F7F81, 0x81817F7F, 0x81818181, 0x7F7F7F7F, 0x7F817F7F,
+0x81817F7F, 0x7F81817F, 0x817F7F7F, 0x817F8181, 0x7F7F8181, 0x7F817F81, 0x81818181, 0x8181817F,
+0x7F7F7F81, 0x81817F81, 0x7F817F81, 0x817F7F7F, 0x817F7F7F, 0x817F7F81, 0x7F817F81, 0x81818181,
+0x817F7F81, 0x7F817F7F, 0x8181817F, 0x8181817F, 0x8181817F, 0x7F7F7F81, 0x7F817F7F, 0x7F817F81,
+0x817F8181, 0x8181817F, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81, 0x817F817F, 0x817F7F7F,
+0x7F7F817F, 0x7F817F81, 0x8181817F, 0x81817F81, 0x817F8181, 0x7F818181, 0x7F817F7F, 0x817F817F,
+0x817F7F7F, 0x7F7F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x81817F81, 0x817F8181, 0x817F8181, 0x7F818181,
+0x7F7F7F81, 0x817F8181, 0x817F817F, 0x817F817F, 0x7F7F7F81, 0x81817F7F, 0x817F7F81, 0x7F81817F,
+0x7F7F8181, 0x8181817F, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x7F81817F, 0x817F7F81, 0x7F7F8181,
+0x817F8181, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F81, 0x7F817F7F, 0x817F817F, 0x7F7F7F81, 0x81817F81,
+0x7F817F7F, 0x817F7F7F, 0x817F8181, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F8181, 0x8181817F, 0x817F7F81,
+0x817F8181, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F7F, 0x81817F7F, 0x817F817F, 0x7F7F7F7F, 0x7F817F81,
+0x7F818181, 0x817F8181, 0x81817F81, 0x7F7F8181, 0x7F7F817F, 0x81818181, 0x7F7F8181, 0x817F8181,
+0x8181817F, 0x817F817F, 0x81817F7F, 0x7F817F7F, 0x817F7F81, 0x81818181, 0x81817F81, 0x7F7F7F81,
+0x817F817F, 0x817F817F, 0x817F7F81, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x7F81817F, 0x7F7F817F,
+0x7F817F81, 0x817F7F7F, 0x817F7F81, 0x7F817F7F, 0x8181817F, 0x817F7F81, 0x7F818181, 0x817F8181,
+0x817F8181, 0x7F7F7F7F, 0x7F817F81, 0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x7F817F81, 0x81818181,
+0x817F7F7F, 0x81817F81, 0x7F818181, 0x81817F81, 0x7F817F81, 0x817F7F81, 0x7F817F7F, 0x817F7F81,
+0x7F7F8181, 0x7F7F7F7F, 0x81817F81, 0x7F817F7F, 0x7F7F817F, 0x7F7F817F, 0x817F7F81, 0x7F817F7F,
+0x7F7F817F, 0x817F817F, 0x7F7F7F81, 0x81818181, 0x817F8181, 0x7F7F7F81, 0x7F817F7F, 0x7F7F8181,
+0x7F7F7F81, 0x7F818181, 0x7F818181, 0x817F7F81, 0x7F817F81, 0x817F7F7F, 0x7F7F817F, 0x7F817F81,
+0x81817F7F, 0x7F7F8181, 0x7F7F8181, 0x7F7F8181, 0x81817F7F, 0x7F817F7F, 0x7F7F7F81, 0x7F818181,
+0x8181817F, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x817F817F, 0x7F7F7F81, 0x81817F81,
+0x7F817F7F, 0x7F7F817F, 0x7F7F7F81, 0x81817F81, 0x817F7F81, 0x7F7F8181, 0x8181817F, 0x817F817F,
+0x81817F81, 0x7F818181, 0x817F7F7F, 0x817F7F81, 0x7F817F81, 0x817F7F7F, 0x7F7F7F81, 0x7F817F81,
+0x7F81817F, 0x817F817F, 0x7F817F81, 0x7F7F7F7F, 0x81818181, 0x7F818181, 0x817F7F81, 0x7F7F8181,
+0x81818181, 0x817F8181, 0x7F7F7F81, 0x7F81817F, 0x817F7F7F, 0x81818181, 0x7F7F7F7F, 0x8181817F,
+0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x81818181, 0x81817F81, 0x7F7F7F81,
+0x81818181, 0x81817F81, 0x81818181, 0x7F817F7F, 0x7F7F817F, 0x81818181, 0x7F81817F, 0x7F7F7F7F,
+0x817F7F81, 0x7F7F817F, 0x7F7F8181, 0x81817F7F, 0x7F7F8181, 0x817F8181, 0x7F817F81, 0x7F817F81,
+0x81818181, 0x817F817F, 0x8181817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F8181, 0x7F7F7F7F, 0x81817F81,
+0x817F7F7F, 0x817F7F81, 0x7F7F8181, 0x81817F81, 0x7F7F8181, 0x7F7F7F7F, 0x7F818181, 0x817F7F81,
+0x817F817F, 0x81818181, 0x7F818181, 0x817F7F7F, 0x7F818181, 0x7F817F81, 0x817F817F, 0x7F81817F,
+0x7F818181, 0x81818181, 0x7F7F7F81, 0x817F8181, 0x81817F7F, 0x81817F81, 0x817F8181, 0x81817F7F,
+0x7F7F7F7F, 0x8181817F, 0x81817F81, 0x7F7F7F7F, 0x7F817F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F7F7F,
+0x7F817F81, 0x81817F7F, 0x7F7F8181, 0x817F7F7F, 0x817F8181, 0x8181817F, 0x81817F81, 0x7F818181,
+0x7F7F817F, 0x817F7F81, 0x7F7F7F81, 0x7F818181, 0x8181817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81,
+0x81817F7F, 0x7F7F7F7F, 0x7F818181, 0x7F817F81, 0x7F81817F, 0x817F817F, 0x81817F81, 0x817F817F,
+0x817F7F7F, 0x817F7F81, 0x81818181, 0x7F81817F, 0x7F81817F, 0x817F7F81, 0x7F7F8181, 0x7F817F7F,
+0x7F817F7F, 0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x81818181, 0x817F7F7F, 0x817F7F7F, 0x7F7F8181,
+0x817F817F, 0x817F7F81, 0x817F7F81, 0x81818181, 0x8181817F, 0x7F818181, 0x7F7F7F7F, 0x7F81817F,
+0x81817F81, 0x7F7F817F, 0x817F7F7F, 0x7F817F81, 0x7F818181, 0x7F81817F, 0x8181817F, 0x7F7F7F81,
+0x81817F81, 0x81817F81, 0x7F7F8181, 0x81818181, 0x7F7F817F, 0x7F81817F, 0x81817F7F, 0x817F8181,
+0x7F7F7F7F, 0x81817F81, 0x817F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x7F818181, 0x817F817F,
+0x817F817F, 0x81817F7F, 0x7F7F8181, 0x81818181, 0x8181817F, 0x7F817F81, 0x7F7F7F81, 0x7F818181,
+0x817F817F, 0x817F8181, 0x7F7F8181, 0x817F7F7F, 0x81817F81, 0x817F7F81, 0x817F7F7F, 0x7F818181,
+0x81817F81, 0x81818181, 0x7F7F817F, 0x81817F7F, 0x81817F7F, 0x7F7F8181, 0x7F7F817F, 0x7F818181,
+0x7F817F7F, 0x7F7F7F7F, 0x7F7F7F81, 0x81818181, 0x81817F7F, 0x817F8181, 0x7F818181, 0x81818181,
+0x81817F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F7F7F, 0x817F817F, 0x7F7F8181,
+0x7F818181, 0x8181817F, 0x7F818181, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x817F7F7F,
+0x7F7F817F, 0x817F7F7F, 0x7F7F817F, 0x817F7F81, 0x7F818181, 0x7F817F7F, 0x7F817F81, 0x81817F81,
+0x7F7F817F, 0x7F81817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F81, 0x7F817F81,
+0x7F7F8181, 0x81818181, 0x817F7F81, 0x7F7F7F7F, 0x7F818181, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F817F,
+0x817F7F7F, 0x7F7F817F, 0x7F7F8181, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F81, 0x81817F7F, 0x7F817F7F,
+0x7F7F7F7F, 0x81818181, 0x817F817F, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x7F817F81, 0x81818181,
+0x7F81817F, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x81817F81, 0x7F7F8181, 0x817F8181,
+0x817F8181, 0x7F7F817F, 0x7F7F7F81, 0x7F817F81, 0x7F7F817F, 0x81817F7F, 0x8181817F, 0x7F7F7F7F,
+0x81817F81, 0x7F7F7F7F, 0x817F8181, 0x7F7F7F81, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x7F7F817F,
+0x81818181, 0x7F818181, 0x7F81817F, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F81, 0x817F8181, 0x7F7F7F81,
+0x817F817F, 0x8181817F, 0x7F7F7F7F, 0x817F8181, 0x817F8181, 0x81818181, 0x81818181, 0x7F7F8181,
+0x817F7F81, 0x7F818181, 0x7F7F8181, 0x7F7F7F7F, 0x817F8181, 0x81817F81, 0x7F817F81, 0x7F817F7F,
+0x7F7F8181, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F81, 0x7F7F8181, 0x8181817F, 0x7F7F817F, 0x7F7F817F,
+0x81817F7F, 0x7F818181, 0x7F818181, 0x8181817F, 0x81818181, 0x7F818181, 0x817F8181, 0x7F7F7F81,
+0x7F817F81, 0x817F817F, 0x81817F81, 0x7F7F817F, 0x7F818181, 0x7F81817F, 0x81817F81, 0x817F7F7F,
+0x7F7F8181, 0x817F8181, 0x817F7F81, 0x817F817F, 0x7F7F8181, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F,
+0x7F81817F, 0x81818181, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x81818181, 0x7F7F8181, 0x7F7F8181,
+0x817F7F81, 0x7F7F7F81, 0x817F817F, 0x817F8181, 0x7F817F81, 0x7F7F8181, 0x8181817F, 0x7F7F7F7F,
+0x7F81817F, 0x8181817F, 0x817F7F7F, 0x7F817F7F, 0x817F8181, 0x7F817F7F, 0x817F817F, 0x8181817F,
+0x7F7F817F, 0x7F81817F, 0x81818181, 0x7F7F817F, 0x7F7F817F, 0x81817F7F, 0x7F7F7F81, 0x817F817F,
+0x7F817F81, 0x817F7F81, 0x7F818181, 0x7F817F81, 0x7F7F8181, 0x7F7F7F81, 0x817F7F7F, 0x817F817F,
+0x817F8181, 0x7F7F817F, 0x817F817F, 0x8181817F, 0x817F8181, 0x81817F7F, 0x7F7F7F7F, 0x817F8181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x7F7F817F, 0x7F7F8181,
+0x817F8181, 0x81818181, 0x81818181, 0x7F817F81, 0x817F7F81, 0x817F7F7F, 0x7F7F817F, 0x7F818181,
+0x7F817F7F, 0x8181817F, 0x7F7F7F81, 0x7F818181, 0x7F81817F, 0x817F817F, 0x7F818181, 0x7F7F7F7F,
+0x817F8181, 0x7F81817F, 0x7F817F81, 0x817F817F, 0x8181817F, 0x7F817F81, 0x81818181, 0x81818181,
+0x7F817F7F, 0x81817F7F, 0x817F8181, 0x8181817F, 0x7F81817F, 0x7F818181, 0x817F7F7F, 0x8181817F,
+0x7F7F8181, 0x81817F81, 0x7F7F7F7F, 0x817F7F81, 0x817F8181, 0x7F7F7F7F, 0x8181817F, 0x7F7F7F7F,
+0x7F817F81, 0x7F817F81, 0x817F8181, 0x81817F81, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x817F7F7F,
+0x817F817F, 0x817F8181, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F, 0x817F817F, 0x817F7F7F, 0x7F7F8181,
+0x7F7F7F7F, 0x7F818181, 0x81817F7F, 0x7F817F81, 0x817F817F, 0x81818181, 0x817F7F7F, 0x7F7F7F7F,
+0x817F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x8181817F, 0x81817F7F, 0x817F7F7F, 0x7F7F817F,
+0x7F7F8181, 0x817F7F81, 0x817F7F7F, 0x7F817F81, 0x81818181, 0x7F817F81, 0x817F8181, 0x7F7F7F7F,
+0x7F7F7F81, 0x7F7F8181, 0x7F817F7F, 0x7F81817F, 0x7F81817F, 0x81818181, 0x81817F81, 0x8181817F,
+0x7F7F7F81, 0x817F7F81, 0x817F817F, 0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x8181817F, 0x81817F81,
+0x817F7F81, 0x7F81817F, 0x817F817F, 0x8181817F, 0x7F7F817F, 0x817F817F, 0x7F817F81, 0x817F7F81,
+0x81817F7F, 0x7F818181, 0x7F817F7F, 0x81818181, 0x7F818181, 0x7F7F7F7F, 0x7F81817F, 0x817F817F,
+0x81818181, 0x7F817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F817F, 0x817F817F, 0x81817F81, 0x8181817F,
+0x7F7F8181, 0x8181817F, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x81818181, 0x7F81817F,
+0x7F817F81, 0x817F8181, 0x81818181, 0x817F8181, 0x7F817F81, 0x81817F81, 0x817F7F81, 0x7F7F817F,
+0x7F7F7F81, 0x8181817F, 0x817F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x817F8181, 0x817F7F7F, 0x7F818181,
+0x817F817F, 0x8181817F, 0x817F7F81, 0x7F817F7F, 0x817F817F, 0x7F817F81, 0x7F7F8181, 0x7F817F7F,
+0x7F817F81, 0x7F7F817F, 0x81818181, 0x817F7F81, 0x81818181, 0x7F817F81, 0x7F7F7F81, 0x8181817F,
+0x81818181, 0x7F817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x817F817F, 0x817F7F7F,
+0x817F8181, 0x8181817F, 0x7F817F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F817F,
+0x7F7F817F, 0x817F817F, 0x7F818181, 0x817F8181, 0x7F818181, 0x7F7F7F7F, 0x8181817F, 0x7F817F81,
+0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F,
+0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x81818181, 0x7F7F7F7F, 0x817F7F7F, 0x81817F81, 0x81817F81,
+0x817F8181, 0x817F817F, 0x81817F7F, 0x7F81817F, 0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x81818181,
+0x7F818181, 0x7F7F8181, 0x7F81817F, 0x7F817F81, 0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x817F7F81,
+0x81817F81, 0x7F817F7F, 0x81818181, 0x7F817F7F, 0x7F7F8181, 0x7F7F817F, 0x817F7F81, 0x81817F81,
+0x81817F81, 0x7F817F81, 0x817F8181, 0x817F817F, 0x817F7F81, 0x7F817F7F, 0x7F817F81, 0x7F818181,
+0x7F81817F, 0x7F818181, 0x7F7F7F7F, 0x81817F7F, 0x7F817F7F, 0x7F7F817F, 0x7F818181, 0x8181817F,
+0x817F8181, 0x7F818181, 0x7F81817F, 0x817F8181, 0x7F81817F, 0x7F7F7F7F, 0x7F818181, 0x817F817F,
+0x81818181, 0x817F7F81, 0x7F7F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F817F, 0x7F81817F, 0x81817F7F,
+0x7F7F7F81, 0x7F817F7F, 0x81817F81, 0x8181817F, 0x817F817F, 0x817F7F81, 0x81818181, 0x817F8181,
+0x7F818181, 0x7F7F817F, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x7F7F7F7F, 0x81818181, 0x817F7F7F,
+0x817F817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F8181, 0x7F818181, 0x7F817F81, 0x7F81817F, 0x7F81817F,
+0x7F81817F, 0x7F7F7F81, 0x817F7F7F, 0x8181817F, 0x7F817F7F, 0x7F7F8181, 0x81818181, 0x8181817F,
+0x7F818181, 0x7F7F8181, 0x7F818181, 0x7F7F8181, 0x7F817F7F, 0x7F7F817F, 0x817F817F, 0x7F7F8181,
+0x817F7F7F, 0x7F7F7F81, 0x81817F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x7F81817F, 0x81817F81,
+0x7F817F81, 0x81817F81, 0x7F817F81, 0x81817F7F, 0x81818181, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81,
+0x7F81817F, 0x7F817F7F, 0x81818181, 0x7F7F817F, 0x817F817F, 0x81818181, 0x7F7F817F, 0x7F81817F,
+0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F817F81, 0x7F7F7F81, 0x817F7F81, 0x7F7F8181, 0x81817F7F,
+0x7F7F7F7F, 0x7F7F817F, 0x7F81817F, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F7F7F, 0x81818181, 0x7F818181,
+0x7F7F7F7F, 0x7F7F8181, 0x7F7F8181, 0x8181817F, 0x817F8181, 0x81818181, 0x7F818181, 0x7F817F7F,
+0x7F7F7F81, 0x81818181, 0x81817F7F, 0x81817F7F, 0x7F7F8181, 0x81818181, 0x81817F7F, 0x7F817F81,
+0x817F8181, 0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x817F817F, 0x7F817F7F, 0x817F7F7F, 0x817F817F,
+0x8181817F, 0x8181817F, 0x817F7F81, 0x81817F81, 0x7F81817F, 0x817F7F81, 0x817F7F81, 0x81818181,
+0x7F817F7F, 0x817F7F81, 0x7F81817F, 0x817F8181, 0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x7F7F7F7F,
+0x81817F7F, 0x7F7F7F81, 0x81818181, 0x817F8181, 0x7F7F817F, 0x8181817F, 0x81817F81, 0x81818181,
+0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F81817F, 0x81817F81, 0x7F7F7F81, 0x7F817F7F,
+0x7F817F81, 0x7F7F8181, 0x7F817F81, 0x8181817F, 0x817F7F7F, 0x817F817F, 0x7F7F7F7F, 0x817F817F,
+0x7F817F7F, 0x7F817F7F, 0x7F817F81, 0x7F817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x81817F7F,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x7F7F7F7F, 0x817F817F, 0x8181817F, 0x817F8181,
+0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x817F7F7F, 0x81817F81, 0x81817F7F, 0x817F8181,
+0x81818181, 0x81817F7F, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x81817F81, 0x7F817F7F, 0x817F7F7F,
+0x817F7F7F, 0x817F817F, 0x7F818181, 0x817F7F81, 0x7F7F7F81, 0x817F7F81, 0x7F817F81, 0x7F7F7F81,
+0x817F817F, 0x7F81817F, 0x817F7F81, 0x8181817F, 0x817F7F81, 0x817F8181, 0x81818181, 0x7F7F7F7F,
+0x817F7F81, 0x7F817F81, 0x817F817F, 0x817F7F7F, 0x81817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81,
+0x817F8181, 0x81817F7F, 0x7F81817F, 0x81817F81, 0x81818181, 0x81817F81, 0x7F7F8181, 0x81818181,
+0x81818181, 0x817F7F81, 0x81818181, 0x7F7F817F, 0x817F817F, 0x7F818181, 0x8181817F, 0x817F8181,
+0x7F7F817F, 0x7F817F7F, 0x7F818181, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F, 0x81817F7F, 0x7F7F817F,
+0x7F817F7F, 0x8181817F, 0x7F817F81, 0x81817F7F, 0x7F81817F, 0x817F7F81, 0x7F7F7F81, 0x817F817F,
+0x7F81817F, 0x817F7F81, 0x817F817F, 0x7F817F7F, 0x817F8181, 0x7F7F8181, 0x81818181, 0x817F8181,
+0x7F7F817F, 0x81817F7F, 0x817F8181, 0x817F817F, 0x817F8181, 0x7F7F7F81, 0x7F81817F, 0x7F7F7F7F,
+0x7F7F7F81, 0x7F7F7F81, 0x7F7F817F, 0x81817F81, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F81,
+0x817F7F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F817F81, 0x817F8181, 0x7F818181, 0x817F817F, 0x7F7F7F7F,
+0x817F7F7F, 0x81818181, 0x81817F7F, 0x7F818181, 0x817F817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F,
+0x7F817F7F, 0x81817F81, 0x817F7F7F, 0x7F817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F7F81, 0x7F7F7F7F,
+0x8181817F, 0x81818181, 0x7F81817F, 0x7F7F7F7F, 0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x7F7F8181,
+0x7F7F7F7F, 0x817F817F, 0x8181817F, 0x7F818181, 0x817F7F81, 0x817F8181, 0x7F7F8181, 0x817F8181,
+0x7F7F7F7F, 0x7F818181, 0x817F817F, 0x817F7F7F, 0x81818181, 0x81817F7F, 0x7F7F8181, 0x7F7F7F7F,
+0x7F7F817F, 0x817F817F, 0x8181817F, 0x817F817F, 0x7F7F817F, 0x7F817F81, 0x7F7F817F, 0x817F7F7F,
+0x817F817F, 0x8181817F, 0x817F7F7F, 0x817F817F, 0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x7F7F7F81,
+0x817F817F, 0x81817F7F, 0x7F81817F, 0x81818181, 0x81817F7F, 0x7F818181, 0x817F7F7F, 0x7F7F7F7F,
+0x8181817F, 0x7F817F7F, 0x8181817F, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F81,
+0x817F7F81, 0x817F7F7F, 0x7F7F8181, 0x81817F7F, 0x817F8181, 0x817F7F81, 0x7F7F7F7F, 0x7F7F817F,
+0x817F817F, 0x7F7F8181, 0x81818181, 0x7F817F7F, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x7F817F7F,
+0x817F8181, 0x7F817F7F, 0x7F817F81, 0x7F817F81, 0x7F817F7F, 0x7F81817F, 0x8181817F, 0x817F817F,
+0x81817F7F, 0x81817F81, 0x81817F81, 0x7F7F817F, 0x7F7F7F81, 0x817F7F81, 0x81817F7F, 0x7F7F8181,
+0x817F817F, 0x817F7F81, 0x8181817F, 0x7F818181, 0x8181817F, 0x7F81817F, 0x81817F81, 0x7F817F81,
+0x7F817F81, 0x7F7F8181, 0x7F7F7F81, 0x7F818181, 0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x7F817F7F,
+0x81817F7F, 0x817F8181, 0x817F8181, 0x81818181, 0x81818181, 0x817F7F81, 0x817F817F, 0x7F818181,
+0x7F818181, 0x7F81817F, 0x81817F81, 0x81817F81, 0x8181817F, 0x7F817F7F, 0x7F7F7F81, 0x81818181,
+0x7F817F7F, 0x81817F81, 0x7F817F7F, 0x7F817F81, 0x81817F81, 0x817F817F, 0x7F7F8181, 0x7F7F817F,
+0x7F818181, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F818181, 0x7F7F7F81,
+0x817F8181, 0x817F817F, 0x7F817F7F, 0x7F7F817F, 0x7F81817F, 0x81817F81, 0x7F7F8181, 0x817F8181,
+0x817F817F, 0x817F7F7F, 0x7F7F817F, 0x8181817F, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x81818181,
+0x81817F81, 0x817F817F, 0x7F7F8181, 0x7F817F7F, 0x81818181, 0x7F7F8181, 0x7F817F81, 0x81817F7F,
+0x7F817F7F, 0x7F817F81, 0x81817F81, 0x817F7F7F, 0x7F7F817F, 0x81818181, 0x817F7F7F, 0x7F7F8181,
+0x7F7F817F, 0x817F817F, 0x81817F7F, 0x7F818181, 0x81817F7F, 0x7F81817F, 0x8181817F, 0x7F7F8181,
+0x81817F7F, 0x7F817F81, 0x81817F81, 0x7F81817F, 0x8181817F, 0x7F7F8181, 0x7F817F7F, 0x81817F7F,
+0x81818181, 0x817F8181, 0x817F8181, 0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x817F7F7F, 0x81818181,
+0x7F81817F, 0x817F7F7F, 0x81818181, 0x7F818181, 0x81818181, 0x81817F7F, 0x7F817F81, 0x7F817F81,
+0x7F817F81, 0x7F7F7F81, 0x81817F81, 0x81817F7F, 0x817F8181, 0x81817F7F, 0x7F7F817F, 0x7F7F7F81,
+0x7F7F7F81, 0x817F7F7F, 0x8181817F, 0x7F817F81, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x7F817F7F,
+0x81817F81, 0x7F7F817F, 0x7F7F817F, 0x7F817F81, 0x7F7F8181, 0x81818181, 0x7F817F81, 0x817F8181,
+0x81817F81, 0x7F7F817F, 0x81818181, 0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x817F8181, 0x81818181,
+0x81817F7F, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F81, 0x817F817F, 0x7F818181, 0x7F7F817F, 0x7F81817F,
+0x817F817F, 0x7F7F8181, 0x7F817F81, 0x817F7F7F, 0x7F7F817F, 0x81817F81, 0x7F7F8181, 0x7F818181,
+0x817F817F, 0x7F817F81, 0x7F81817F, 0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x8181817F, 0x817F817F,
+0x7F817F7F, 0x7F7F8181, 0x7F818181, 0x81817F7F, 0x81817F7F, 0x8181817F, 0x817F8181, 0x817F817F,
+0x7F7F8181, 0x817F8181, 0x81818181, 0x7F818181, 0x81818181, 0x7F7F7F81, 0x7F7F7F81, 0x817F817F,
+0x817F7F7F, 0x7F7F8181, 0x7F817F81, 0x81817F81, 0x8181817F, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F,
+0x817F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x81817F7F, 0x81818181, 0x817F7F81, 0x81817F7F, 0x7F7F817F,
+0x7F7F8181, 0x7F817F81, 0x81817F7F, 0x7F81817F, 0x7F7F7F7F, 0x81817F81, 0x7F7F8181, 0x7F7F817F,
+0x8181817F, 0x7F818181, 0x7F817F7F, 0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F8181,
+0x817F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F81817F, 0x7F817F7F, 0x8181817F, 0x81818181, 0x81817F81,
+0x7F818181, 0x7F7F8181, 0x7F7F7F81, 0x7F817F7F, 0x817F8181, 0x81818181, 0x7F81817F, 0x8181817F,
+0x7F817F81, 0x7F817F81, 0x7F7F7F81, 0x81818181, 0x81817F81, 0x817F817F, 0x7F7F7F81, 0x81817F81,
+0x7F7F8181, 0x7F817F7F, 0x81817F81, 0x817F8181, 0x7F817F81, 0x81817F7F, 0x7F7F8181, 0x7F818181,
+0x7F81817F, 0x7F7F7F81, 0x817F7F7F, 0x817F8181, 0x81817F81, 0x7F817F7F, 0x7F7F7F7F, 0x7F817F7F,
+0x7F81817F, 0x7F7F8181, 0x7F7F7F81, 0x7F817F81, 0x817F7F7F, 0x81818181, 0x7F7F8181, 0x7F7F8181,
+0x7F7F817F, 0x7F818181, 0x7F817F81, 0x81818181, 0x7F7F7F7F, 0x7F817F7F, 0x81818181, 0x817F7F81,
+0x7F818181, 0x7F817F81, 0x7F817F7F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F, 0x8181817F,
+0x7F7F7F81, 0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x7F817F7F, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F7F,
+0x817F817F, 0x7F81817F, 0x7F7F7F7F, 0x817F7F7F, 0x81817F81, 0x81818181, 0x81817F81, 0x817F817F,
+0x7F7F7F81, 0x7F7F7F81, 0x81817F7F, 0x817F7F7F, 0x81817F7F, 0x81817F81, 0x817F817F, 0x7F817F81,
+0x7F7F7F7F, 0x7F81817F, 0x7F81817F, 0x7F7F7F81, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x7F7F8181,
+0x7F817F81, 0x7F817F7F, 0x7F817F81, 0x7F7F817F, 0x81818181, 0x81817F7F, 0x7F818181, 0x7F817F7F,
+0x81817F81, 0x817F7F81, 0x7F81817F, 0x81817F81, 0x8181817F, 0x8181817F, 0x81817F7F, 0x81817F81,
+0x817F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x8181817F, 0x817F8181, 0x7F7F7F7F, 0x7F81817F, 0x7F81817F,
+0x817F7F7F, 0x7F7F817F, 0x7F817F7F, 0x7F7F817F, 0x81817F7F, 0x81818181, 0x817F7F7F, 0x81817F7F,
+0x8181817F, 0x817F8181, 0x81818181, 0x7F818181, 0x7F7F817F, 0x817F817F, 0x817F7F7F, 0x7F7F817F,
+0x817F817F, 0x81817F81, 0x817F7F81, 0x7F818181, 0x7F7F8181, 0x8181817F, 0x817F817F, 0x7F7F8181,
+0x7F7F7F7F, 0x81818181, 0x817F8181, 0x81817F7F, 0x817F817F, 0x81818181, 0x81817F81, 0x817F7F81,
+0x7F7F8181, 0x817F817F, 0x817F7F7F, 0x81818181, 0x817F7F81, 0x8181817F, 0x817F817F, 0x7F7F7F7F,
+0x7F7F8181, 0x7F817F81, 0x81818181, 0x7F818181, 0x7F81817F, 0x7F817F81, 0x7F7F7F81, 0x817F8181,
+0x8181817F, 0x7F7F8181, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x7F817F7F, 0x81817F7F, 0x81818181,
+0x7F818181, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x7F7F8181, 0x817F7F7F,
+0x7F817F81, 0x81818181, 0x81818181, 0x7F817F7F, 0x7F7F8181, 0x817F7F81, 0x817F817F, 0x7F7F817F,
+0x81818181, 0x81817F7F, 0x817F7F81, 0x817F8181, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x81818181,
+0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x817F817F, 0x817F7F7F, 0x81817F81,
+0x817F7F81, 0x7F81817F, 0x817F7F7F, 0x817F817F, 0x817F817F, 0x81817F81, 0x817F7F7F, 0x7F818181,
+0x81817F81, 0x817F7F81, 0x8181817F, 0x7F7F817F, 0x7F818181, 0x817F7F81, 0x817F7F81, 0x81817F7F,
+0x7F7F7F7F, 0x81818181, 0x817F7F7F, 0x7F817F81, 0x817F8181, 0x817F817F, 0x8181817F, 0x817F7F7F,
+0x817F8181, 0x817F8181, 0x81818181, 0x7F7F817F, 0x8181817F, 0x81817F7F, 0x7F7F8181, 0x817F7F81,
+0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F817F7F, 0x81817F81, 0x81818181, 0x8181817F, 0x817F7F81,
+0x81818181, 0x817F7F81, 0x817F817F, 0x7F7F7F81, 0x7F817F7F, 0x81818181, 0x7F7F8181, 0x8181817F,
+0x817F8181, 0x7F81817F, 0x8181817F, 0x7F7F7F81, 0x817F8181, 0x7F7F817F, 0x7F7F8181, 0x7F817F81,
+0x7F7F8181, 0x8181817F, 0x81817F7F, 0x7F81817F, 0x8181817F, 0x7F7F8181, 0x7F7F7F7F, 0x81818181,
+0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F,
+0x7F81817F, 0x8181817F, 0x7F7F7F81, 0x817F8181, 0x817F7F81, 0x817F817F, 0x7F7F817F, 0x81817F7F,
+0x817F7F7F, 0x7F817F81, 0x817F7F7F, 0x7F818181, 0x81818181, 0x817F7F7F, 0x817F7F81, 0x81817F7F,
+0x7F81817F, 0x7F817F7F, 0x7F7F8181, 0x7F818181, 0x817F8181, 0x817F8181, 0x817F8181, 0x7F7F8181,
+0x7F81817F, 0x7F817F7F, 0x7F817F81, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x81817F81, 0x7F7F817F,
+0x7F81817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F, 0x7F817F81, 0x817F7F81, 0x817F8181, 0x7F7F817F,
+0x817F7F7F, 0x7F817F81, 0x7F7F817F, 0x8181817F, 0x817F7F81, 0x81817F7F, 0x7F817F81, 0x8181817F,
+0x7F818181, 0x7F7F7F7F, 0x81817F7F, 0x8181817F, 0x81817F81, 0x7F81817F, 0x8181817F, 0x7F817F81,
+0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F81, 0x817F7F81, 0x81817F81, 0x817F7F7F, 0x81817F81,
+0x81818181, 0x8181817F, 0x817F817F, 0x7F818181, 0x7F81817F, 0x81817F81, 0x7F7F817F, 0x817F817F,
+0x817F7F7F, 0x817F7F7F, 0x817F817F, 0x8181817F, 0x7F818181, 0x8181817F, 0x817F8181, 0x7F817F7F,
+0x7F7F8181, 0x817F8181, 0x7F81817F, 0x81817F81, 0x817F817F, 0x7F818181, 0x81818181, 0x817F7F81,
+0x7F81817F, 0x8181817F, 0x81817F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F817F, 0x817F8181, 0x81817F7F,
+0x7F817F7F, 0x817F7F7F, 0x817F7F7F, 0x7F81817F, 0x7F81817F, 0x81818181, 0x7F7F7F7F, 0x817F817F,
+0x7F7F817F, 0x7F818181, 0x7F7F7F81, 0x817F8181, 0x817F8181, 0x817F817F, 0x7F817F7F, 0x817F7F7F,
+0x8181817F, 0x7F818181, 0x81818181, 0x817F817F, 0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x7F7F8181,
+0x81817F81, 0x817F7F7F, 0x7F7F817F, 0x817F817F, 0x81817F81, 0x7F81817F, 0x817F7F81, 0x7F81817F,
+0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F7F, 0x7F817F81, 0x7F7F7F81, 0x81818181, 0x817F817F,
+0x8181817F, 0x7F817F81, 0x7F7F817F, 0x7F7F8181, 0x817F7F81, 0x7F817F81, 0x81817F81, 0x817F8181,
+0x7F7F7F7F, 0x817F817F, 0x7F817F81, 0x81817F7F, 0x817F7F81, 0x7F7F817F, 0x7F7F817F, 0x817F8181,
+0x81817F81, 0x7F7F817F, 0x81818181, 0x817F7F81, 0x817F8181, 0x7F7F7F7F, 0x817F817F, 0x817F7F81,
+0x81818181, 0x817F7F81, 0x817F817F, 0x7F81817F, 0x81817F7F, 0x81818181, 0x817F7F7F, 0x817F7F7F,
+0x81817F81, 0x817F817F, 0x7F7F817F, 0x7F7F7F81, 0x7F817F81, 0x817F7F81, 0x7F818181, 0x7F7F7F7F,
+0x817F7F81, 0x817F7F81, 0x7F817F7F, 0x7F817F7F, 0x817F7F81, 0x7F7F7F81, 0x81817F81, 0x81818181,
+0x7F817F81, 0x817F7F7F, 0x817F7F7F, 0x7F818181, 0x817F817F, 0x817F8181, 0x7F817F81, 0x7F7F7F7F,
+0x7F7F7F81, 0x7F817F81, 0x7F7F7F7F, 0x81818181, 0x7F7F8181, 0x817F817F, 0x7F818181, 0x817F7F81,
+0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F81, 0x81818181, 0x7F81817F, 0x81817F81, 0x7F817F81, 0x81818181,
+0x817F817F, 0x7F818181, 0x7F7F817F, 0x7F7F7F81, 0x7F7F7F7F, 0x817F817F, 0x7F81817F, 0x81817F81,
+0x7F7F7F81, 0x7F817F81, 0x7F7F817F, 0x817F817F, 0x817F8181, 0x817F8181, 0x817F7F7F, 0x8181817F,
+0x7F81817F, 0x7F7F817F, 0x817F7F81, 0x7F7F817F, 0x7F7F7F81, 0x817F7F7F, 0x81818181, 0x81817F81,
+0x817F7F7F, 0x81818181, 0x81818181, 0x7F81817F, 0x7F818181, 0x7F817F7F, 0x817F817F, 0x7F7F8181,
+0x7F7F817F, 0x7F7F7F81, 0x817F817F, 0x81818181, 0x81818181, 0x817F7F81, 0x7F818181, 0x7F7F8181,
+0x7F817F81, 0x7F817F7F, 0x81818181, 0x81817F81, 0x7F81817F, 0x7F7F8181, 0x7F817F81, 0x7F817F7F,
+0x7F7F7F7F, 0x81818181, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x7F817F81,
+0x7F7F7F7F, 0x81818181, 0x7F7F8181, 0x81817F81, 0x7F817F81, 0x7F817F7F, 0x7F817F81, 0x8181817F,
+0x7F7F7F81, 0x817F8181, 0x8181817F, 0x7F81817F, 0x817F7F7F, 0x7F7F7F7F, 0x81818181, 0x7F818181,
+0x7F7F817F, 0x81817F7F, 0x7F7F7F81, 0x8181817F, 0x7F817F7F, 0x817F817F, 0x7F7F817F, 0x7F817F81,
+0x817F7F7F, 0x7F817F81, 0x7F7F8181, 0x7F7F817F, 0x81818181, 0x7F817F7F, 0x81817F81, 0x81817F81,
+0x7F818181, 0x7F818181, 0x817F8181, 0x81817F81, 0x817F7F7F, 0x817F7F81, 0x81818181, 0x817F817F,
+0x81817F81, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x7F817F81, 0x7F81817F, 0x817F7F81, 0x817F8181,
+0x7F7F8181, 0x817F7F81, 0x7F7F817F, 0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x7F818181, 0x7F7F7F81,
+0x7F818181, 0x817F817F, 0x7F818181, 0x81817F81, 0x817F7F7F, 0x81817F7F, 0x81817F7F, 0x7F818181,
+0x7F817F81, 0x817F817F, 0x7F7F817F, 0x7F817F7F, 0x7F7F817F, 0x7F817F81, 0x7F7F817F, 0x7F817F81,
+0x7F7F7F81, 0x7F817F7F, 0x81817F7F, 0x817F7F7F, 0x7F81817F, 0x7F81817F, 0x7F7F817F, 0x7F817F7F,
+0x7F817F81, 0x81817F81, 0x7F7F7F81, 0x817F817F, 0x7F817F81, 0x81818181, 0x817F8181, 0x7F817F81,
+0x7F7F8181, 0x81817F81, 0x817F7F7F, 0x81817F81, 0x7F81817F, 0x8181817F, 0x7F7F8181, 0x7F7F8181,
+0x7F818181, 0x7F818181, 0x817F7F81, 0x817F7F7F, 0x8181817F, 0x7F7F817F, 0x7F817F7F, 0x817F7F7F,
+0x81818181, 0x7F817F7F, 0x81817F81, 0x7F81817F, 0x7F7F8181, 0x817F7F81, 0x817F8181, 0x7F7F8181,
+0x7F818181, 0x7F817F81, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x81817F7F, 0x7F818181, 0x817F7F7F,
+0x81818181, 0x817F7F81, 0x81818181, 0x7F817F7F, 0x817F7F7F, 0x81817F7F, 0x8181817F, 0x81817F81,
+0x817F7F81, 0x81818181, 0x81817F81, 0x7F7F8181, 0x81818181, 0x7F7F8181, 0x7F7F8181, 0x81818181,
+0x7F7F7F81, 0x8181817F, 0x81818181, 0x81817F7F, 0x7F7F7F81, 0x81818181, 0x81817F7F, 0x817F8181,
+0x7F7F7F81, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F817F81, 0x81817F81, 0x8181817F, 0x817F7F7F,
+0x7F7F8181, 0x817F7F7F, 0x7F818181, 0x7F7F817F, 0x81817F7F, 0x81818181, 0x7F817F7F, 0x817F8181,
+0x817F8181, 0x7F7F8181, 0x81817F81, 0x81817F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81,
+0x7F7F817F, 0x81817F81, 0x81817F81, 0x7F817F81, 0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x81818181,
+0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F7F, 0x81818181, 0x7F7F8181, 0x7F818181, 0x7F7F817F, 0x7F817F81,
+0x817F7F81, 0x7F817F7F, 0x81817F81, 0x817F817F, 0x817F817F, 0x7F817F81, 0x7F81817F, 0x81818181,
+0x7F7F7F81, 0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F7F81, 0x817F8181, 0x81817F7F,
+0x7F818181, 0x817F7F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F, 0x81817F7F, 0x817F817F, 0x7F7F817F,
+0x8181817F, 0x7F817F81, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x7F7F817F, 0x7F818181, 0x8181817F,
+0x817F817F, 0x7F81817F, 0x7F817F7F, 0x7F7F7F81, 0x817F817F, 0x81817F7F, 0x7F818181, 0x7F7F7F81,
+0x7F7F7F81, 0x7F818181, 0x817F817F, 0x7F817F7F, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x7F7F7F81,
+0x7F817F81, 0x7F818181, 0x817F817F, 0x7F81817F, 0x7F817F7F, 0x81817F7F, 0x81817F7F, 0x81818181,
+0x7F7F7F81, 0x7F817F7F, 0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F81817F, 0x8181817F, 0x7F81817F,
+0x817F8181, 0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x817F7F7F, 0x817F7F7F, 0x7F818181, 0x7F7F8181,
+0x817F817F, 0x8181817F, 0x817F8181, 0x7F817F7F, 0x7F817F7F, 0x817F8181, 0x7F7F7F7F, 0x7F7F8181,
+0x817F817F, 0x7F7F7F81, 0x7F7F8181, 0x817F817F, 0x7F817F81, 0x8181817F, 0x7F7F817F, 0x7F7F7F7F,
+0x817F817F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F817F, 0x81818181, 0x81817F7F, 0x817F817F,
+0x817F817F, 0x8181817F, 0x7F7F7F7F, 0x8181817F, 0x7F817F7F, 0x7F818181, 0x7F817F7F, 0x7F817F81,
+0x817F7F81, 0x817F817F, 0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x7F817F81, 0x7F81817F, 0x7F7F8181,
+0x7F7F7F7F, 0x817F7F81, 0x81817F7F, 0x7F817F81, 0x7F7F8181, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F,
+0x81818181, 0x8181817F, 0x7F817F7F, 0x81818181, 0x81818181, 0x81817F7F, 0x817F8181, 0x817F7F7F,
+0x7F817F7F, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x8181817F, 0x8181817F, 0x7F818181,
+0x8181817F, 0x7F818181, 0x817F8181, 0x817F7F81, 0x817F8181, 0x81818181, 0x81817F7F, 0x7F7F8181,
+0x81818181, 0x81817F81, 0x7F7F7F7F, 0x8181817F, 0x7F81817F, 0x7F7F7F81, 0x7F817F7F, 0x81818181,
+0x81817F81, 0x817F8181, 0x7F7F7F7F, 0x8181817F, 0x7F818181, 0x817F8181, 0x817F8181, 0x81817F81,
+0x817F817F, 0x81817F81, 0x7F81817F, 0x7F7F817F, 0x81817F7F, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F,
+0x817F817F, 0x817F817F, 0x7F7F7F7F, 0x817F7F81, 0x7F7F817F, 0x81817F81, 0x81817F7F, 0x7F817F7F,
+0x7F817F7F, 0x8181817F, 0x7F7F7F7F, 0x817F8181, 0x7F81817F, 0x7F817F7F, 0x8181817F, 0x81817F7F,
+0x817F817F, 0x81818181, 0x817F8181, 0x8181817F, 0x7F7F817F, 0x8181817F, 0x7F7F7F7F, 0x7F7F8181,
+0x8181817F, 0x7F817F81, 0x817F8181, 0x81817F7F, 0x817F7F7F, 0x81817F81, 0x817F817F, 0x817F7F7F,
+0x7F7F817F, 0x7F7F817F, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x7F7F7F81,
+0x81818181, 0x7F818181, 0x8181817F, 0x7F817F81, 0x817F8181, 0x8181817F, 0x7F817F81, 0x81817F7F,
+0x81817F7F, 0x817F8181, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x81817F81, 0x7F7F7F7F, 0x817F817F,
+0x7F7F7F81, 0x8181817F, 0x7F7F8181, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x81817F7F, 0x817F7F81,
+0x7F7F7F7F, 0x81817F81, 0x817F817F, 0x81818181, 0x7F7F817F, 0x7F817F7F, 0x817F8181, 0x8181817F,
+0x7F81817F, 0x817F817F, 0x7F81817F, 0x8181817F, 0x7F7F7F81, 0x8181817F, 0x817F7F81, 0x81817F7F,
+0x7F7F817F, 0x7F7F8181, 0x817F8181, 0x81818181, 0x7F7F8181, 0x7F817F81, 0x817F7F7F, 0x7F7F7F7F,
+0x817F7F81, 0x7F817F81, 0x817F817F, 0x81817F7F, 0x81818181, 0x81817F7F, 0x7F7F8181, 0x7F7F817F,
+0x7F81817F, 0x7F7F8181, 0x8181817F, 0x8181817F, 0x8181817F, 0x81817F81, 0x81818181, 0x817F7F7F,
+0x81818181, 0x7F817F81, 0x817F8181, 0x7F818181, 0x8181817F, 0x81817F81, 0x7F7F7F7F, 0x817F7F7F,
+0x817F7F7F, 0x81818181, 0x7F81817F, 0x817F817F, 0x81818181, 0x7F7F817F, 0x8181817F, 0x7F7F817F,
+0x7F818181, 0x817F817F, 0x7F7F8181, 0x817F7F7F, 0x81818181, 0x81817F81, 0x7F81817F, 0x817F817F,
+0x81817F81, 0x7F81817F, 0x7F7F8181, 0x7F81817F, 0x817F817F, 0x7F7F8181, 0x81818181, 0x817F817F,
+0x817F7F7F, 0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x817F817F, 0x7F817F7F, 0x817F7F7F, 0x8181817F,
+0x81817F7F, 0x7F7F817F, 0x7F81817F, 0x7F7F817F, 0x81818181, 0x81817F81, 0x7F7F7F81, 0x817F817F,
+0x7F7F7F7F, 0x7F81817F, 0x7F7F7F7F, 0x81818181, 0x81818181, 0x817F8181, 0x81817F81, 0x7F7F7F81,
+0x81818181, 0x81818181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181, 0x7F7F817F, 0x817F8181,
+0x7F7F7F81, 0x817F8181, 0x7F7F817F, 0x81817F7F, 0x817F8181, 0x7F7F7F81, 0x7F7F7F7F, 0x817F8181,
+0x81817F81, 0x8181817F, 0x7F7F817F, 0x7F7F817F, 0x817F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F8181,
+0x7F81817F, 0x81817F81, 0x81818181, 0x7F81817F, 0x7F818181, 0x7F7F8181, 0x81817F7F, 0x817F7F7F,
+0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x817F817F, 0x7F817F81, 0x7F7F7F81, 0x81818181, 0x7F7F7F81,
+0x8181817F, 0x81817F7F, 0x7F7F7F7F, 0x81817F7F, 0x81817F81, 0x7F818181, 0x7F817F81, 0x817F7F81,
+0x81818181, 0x7F7F8181, 0x7F7F8181, 0x8181817F, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F8181, 0x7F7F817F,
+0x81818181, 0x7F7F817F, 0x81818181, 0x81818181, 0x7F817F81, 0x817F7F7F, 0x81817F7F, 0x81817F81,
+0x81817F81, 0x817F8181, 0x7F81817F, 0x81817F81, 0x817F7F81, 0x7F7F817F, 0x7F81817F, 0x81817F7F,
+0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x7F7F7F81, 0x817F817F, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F,
+0x817F8181, 0x7F81817F, 0x7F7F7F7F, 0x81817F7F, 0x7F818181, 0x81817F7F, 0x817F7F81, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x7F7F817F, 0x7F818181, 0x7F817F81, 0x817F817F, 0x817F7F7F,
+0x7F817F81, 0x7F817F7F, 0x7F817F81, 0x7F7F8181, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F7F, 0x817F817F,
+0x81817F7F, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x7F7F7F81, 0x817F7F7F, 0x81817F7F, 0x81818181,
+0x81817F7F, 0x81818181, 0x7F81817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F7F7F7F, 0x81818181,
+0x81817F81, 0x7F81817F, 0x7F7F7F81, 0x7F81817F, 0x81817F7F, 0x817F8181, 0x7F7F817F, 0x81817F81,
+0x817F817F, 0x7F7F7F7F, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x81818181, 0x817F8181, 0x81817F7F,
+0x7F7F8181, 0x7F7F7F7F, 0x81817F81, 0x81818181, 0x7F7F817F, 0x7F7F7F7F, 0x81817F7F, 0x81817F7F,
+0x817F7F81, 0x817F8181, 0x81817F81, 0x8181817F, 0x7F7F8181, 0x7F818181, 0x7F7F817F, 0x8181817F,
+0x81817F7F, 0x7F7F8181, 0x817F817F, 0x817F8181, 0x7F817F81, 0x81817F81, 0x817F7F7F, 0x7F7F8181,
+0x81817F81, 0x817F817F, 0x8181817F, 0x7F818181, 0x7F7F7F81, 0x817F7F81, 0x8181817F, 0x7F7F817F,
+0x7F81817F, 0x817F8181, 0x7F7F7F7F, 0x817F8181, 0x81817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F8181,
+0x817F8181, 0x7F817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F81, 0x81818181,
+0x817F7F7F, 0x81817F81, 0x81817F7F, 0x81817F7F, 0x7F7F7F81, 0x7F7F817F, 0x817F7F7F, 0x81817F7F,
+0x81817F81, 0x81817F7F, 0x7F817F81, 0x8181817F, 0x7F81817F, 0x81817F7F, 0x7F7F7F81, 0x81817F7F,
+0x7F7F7F7F, 0x7F7F817F, 0x817F7F81, 0x817F817F, 0x7F7F817F, 0x81817F7F, 0x7F817F81, 0x817F817F,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F81817F, 0x7F7F7F7F, 0x7F818181,
+0x817F817F, 0x7F7F8181, 0x81818181, 0x817F817F, 0x81817F81, 0x81818181, 0x7F7F817F, 0x81817F81,
+0x81818181, 0x81817F7F, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x8181817F,
+0x7F817F81, 0x7F817F81, 0x7F818181, 0x817F7F81, 0x7F818181, 0x7F7F7F81, 0x7F7F7F81, 0x817F8181,
+0x817F7F81, 0x7F81817F, 0x7F817F7F, 0x8181817F, 0x7F817F81, 0x8181817F, 0x7F817F81, 0x81817F81,
+0x7F81817F, 0x81817F7F, 0x81817F81, 0x7F817F7F, 0x81817F7F, 0x81817F7F, 0x7F7F817F, 0x81817F7F,
+0x7F818181, 0x81817F81, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x81818181, 0x7F81817F, 0x81818181,
+0x7F817F7F, 0x7F817F7F, 0x7F7F8181, 0x8181817F, 0x7F817F7F, 0x817F7F7F, 0x81818181, 0x817F7F81,
+0x7F7F8181, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x817F7F81, 0x817F7F81, 0x817F7F81, 0x817F817F,
+0x817F817F, 0x7F817F81, 0x81818181, 0x817F817F, 0x7F818181, 0x81818181, 0x81817F81, 0x81818181,
+0x7F7F7F7F, 0x7F817F7F, 0x7F817F81, 0x817F817F, 0x817F7F81, 0x7F817F81, 0x81818181, 0x7F7F7F81,
+0x817F7F7F, 0x7F7F7F81, 0x817F817F, 0x7F817F7F, 0x7F818181, 0x7F7F7F81, 0x817F8181, 0x81818181,
+0x81817F7F, 0x7F7F7F7F, 0x817F817F, 0x817F7F81, 0x7F818181, 0x817F7F7F, 0x7F7F7F7F, 0x7F818181,
+0x81818181, 0x7F7F7F81, 0x7F817F81, 0x8181817F, 0x7F817F7F, 0x7F817F81, 0x7F7F7F81, 0x81817F81,
+0x7F817F7F, 0x81817F7F, 0x81817F7F, 0x7F7F7F81, 0x81817F81, 0x7F7F7F7F, 0x817F8181, 0x817F8181,
+0x7F7F8181, 0x7F817F7F, 0x7F817F81, 0x81817F7F, 0x7F817F7F, 0x8181817F, 0x8181817F, 0x7F7F817F,
+0x817F817F, 0x7F81817F, 0x81818181, 0x817F817F, 0x7F7F817F, 0x7F817F81, 0x7F7F7F81, 0x7F818181,
+0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x7F7F817F, 0x7F817F81, 0x817F7F81, 0x7F81817F, 0x7F81817F,
+0x7F817F81, 0x7F818181, 0x8181817F, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x7F817F7F, 0x7F818181,
+0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x817F817F, 0x81817F81, 0x81818181, 0x7F7F8181,
+0x81817F7F, 0x7F817F7F, 0x81817F81, 0x7F7F817F, 0x817F817F, 0x7F7F7F7F, 0x817F8181, 0x7F7F8181,
+0x817F8181, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x81817F81, 0x81818181, 0x8181817F,
+0x817F8181, 0x7F818181, 0x817F817F, 0x7F81817F, 0x7F81817F, 0x817F7F7F, 0x7F817F81, 0x7F7F7F7F,
+0x7F7F817F, 0x7F7F7F7F, 0x8181817F, 0x7F817F81, 0x8181817F, 0x817F8181, 0x817F817F, 0x7F817F81,
+0x81817F81, 0x81818181, 0x8181817F, 0x7F7F817F, 0x81817F81, 0x817F8181, 0x7F7F817F, 0x7F7F7F7F,
+0x817F7F81, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x7F817F7F, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81,
+0x7F7F817F, 0x81817F7F, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x81817F81, 0x817F8181, 0x81817F81,
+0x7F81817F, 0x7F7F8181, 0x7F81817F, 0x7F7F7F81, 0x81817F7F, 0x7F817F7F, 0x817F817F, 0x817F817F,
+0x7F817F7F, 0x7F7F7F7F, 0x817F817F, 0x81817F7F, 0x817F8181, 0x7F81817F, 0x7F817F81, 0x7F81817F,
+0x7F817F7F, 0x7F817F81, 0x81817F81, 0x81817F7F, 0x81817F81, 0x817F817F, 0x7F81817F, 0x7F817F81,
+0x81817F7F, 0x817F817F, 0x817F7F81, 0x817F817F, 0x817F7F7F, 0x7F817F7F, 0x81817F7F, 0x7F7F817F,
+0x7F817F7F, 0x81818181, 0x817F8181, 0x817F7F81, 0x7F7F817F, 0x817F7F7F, 0x817F7F81, 0x7F818181,
+0x7F7F7F81, 0x817F817F, 0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F81817F, 0x81817F7F, 0x817F8181,
+0x7F7F8181, 0x817F7F7F, 0x7F818181, 0x7F7F7F7F, 0x8181817F, 0x817F8181, 0x7F817F81, 0x7F817F7F,
+0x817F7F7F, 0x817F7F7F, 0x7F818181, 0x7F7F8181, 0x81818181, 0x81817F81, 0x7F81817F, 0x81818181,
+0x7F7F7F81, 0x817F7F7F, 0x81817F81, 0x7F818181, 0x7F817F81, 0x7F7F817F, 0x8181817F, 0x8181817F,
+0x7F7F7F81, 0x7F81817F, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x817F8181, 0x7F7F8181, 0x7F818181,
+0x81817F81, 0x7F817F81, 0x817F7F81, 0x7F81817F, 0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x817F7F7F,
+0x7F7F7F81, 0x7F7F817F, 0x7F7F817F, 0x81817F81, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F,
+0x7F7F817F, 0x81818181, 0x7F7F7F81, 0x8181817F, 0x81817F81, 0x817F7F81, 0x7F7F817F, 0x7F7F7F7F,
+0x7F817F81, 0x817F7F81, 0x81818181, 0x817F7F81, 0x81818181, 0x817F7F81, 0x81817F7F, 0x817F7F81,
+0x7F7F8181, 0x81817F81, 0x7F817F81, 0x7F817F81, 0x7F818181, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F7F,
+0x817F817F, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F81, 0x8181817F, 0x81818181, 0x7F817F7F, 0x81817F7F,
+0x7F817F7F, 0x817F8181, 0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x7F7F7F7F, 0x81818181, 0x81818181,
+0x7F7F7F81, 0x817F8181, 0x817F817F, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F81, 0x7F7F7F81,
+0x7F7F7F81, 0x81817F7F, 0x817F8181, 0x817F817F, 0x817F817F, 0x7F818181, 0x817F817F, 0x7F818181,
+0x7F7F817F, 0x7F818181, 0x7F7F8181, 0x81817F81, 0x817F7F7F, 0x817F7F7F, 0x8181817F, 0x81817F81,
+0x8181817F, 0x81818181, 0x81817F7F, 0x81817F81, 0x8181817F, 0x81817F7F, 0x817F7F81, 0x817F7F81,
+0x7F817F81, 0x817F7F81, 0x81818181, 0x8181817F, 0x7F817F81, 0x7F817F81, 0x81818181, 0x81818181,
+0x81817F81, 0x8181817F, 0x817F7F7F, 0x81817F7F, 0x7F7F8181, 0x81817F81, 0x81817F81, 0x7F7F7F81,
+0x817F817F, 0x7F7F8181, 0x7F818181, 0x7F7F817F, 0x8181817F, 0x7F817F81, 0x7F818181, 0x7F81817F,
+0x7F7F8181, 0x7F817F7F, 0x7F817F7F, 0x81818181, 0x817F8181, 0x7F817F81, 0x81818181, 0x81818181,
+0x817F8181, 0x8181817F, 0x7F7F7F81, 0x81817F81, 0x817F8181, 0x7F7F7F7F, 0x7F7F817F, 0x8181817F,
+0x81818181, 0x7F81817F, 0x7F817F81, 0x7F7F8181, 0x7F7F7F81, 0x81817F81, 0x817F8181, 0x7F81817F,
+0x7F818181, 0x817F8181, 0x81817F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x817F8181, 0x7F817F81,
+0x7F817F81, 0x81818181, 0x817F817F, 0x7F7F8181, 0x8181817F, 0x81817F7F, 0x817F7F81, 0x817F817F,
+0x7F81817F, 0x817F817F, 0x81817F81, 0x817F7F7F, 0x817F7F81, 0x7F81817F, 0x81818181, 0x7F7F7F81,
+0x7F7F817F, 0x7F818181, 0x7F7F8181, 0x817F7F81, 0x817F817F, 0x81817F81, 0x81817F7F, 0x817F7F81,
+0x81817F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F7F, 0x81818181, 0x7F7F7F81, 0x7F817F81, 0x817F8181,
+0x7F7F817F, 0x817F8181, 0x7F817F7F, 0x81818181, 0x81817F81, 0x7F7F7F81, 0x8181817F, 0x7F81817F,
+0x81817F7F, 0x81817F7F, 0x817F8181, 0x817F8181, 0x817F7F7F, 0x7F817F7F, 0x81818181, 0x81817F7F,
+0x817F7F81, 0x817F8181, 0x7F817F81, 0x7F7F817F, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x817F817F, 0x7F818181, 0x81817F81, 0x81817F7F, 0x817F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F7F81,
+0x7F81817F, 0x7F81817F, 0x7F7F817F, 0x81817F7F, 0x81818181, 0x817F7F7F, 0x7F7F817F, 0x817F8181,
+0x8181817F, 0x817F7F81, 0x7F7F8181, 0x8181817F, 0x7F7F7F7F, 0x817F7F7F, 0x81817F81, 0x7F817F81,
+0x81818181, 0x7F817F81, 0x7F817F81, 0x7F7F7F81, 0x817F7F7F, 0x817F817F, 0x817F7F7F, 0x7F7F817F,
+0x7F817F7F, 0x817F817F, 0x81818181, 0x817F817F, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F81817F, 0x817F8181, 0x7F818181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F8181,
+0x7F818181, 0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x81817F7F, 0x7F7F7F7F, 0x817F7F81, 0x817F817F,
+0x7F818181, 0x817F817F, 0x81817F7F, 0x7F818181, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x81817F7F,
+0x7F817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F7F, 0x7F7F7F81, 0x81817F81, 0x7F7F8181, 0x817F7F7F,
+0x8181817F, 0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x817F8181, 0x817F7F7F, 0x81818181, 0x7F817F81,
+0x81817F81, 0x81818181, 0x817F7F81, 0x7F817F7F, 0x7F818181, 0x7F817F81, 0x7F817F81, 0x817F7F7F,
+0x817F7F81, 0x7F7F7F81, 0x817F7F7F, 0x8181817F, 0x7F818181, 0x7F81817F, 0x7F817F7F, 0x7F817F81,
+0x7F7F8181, 0x81818181, 0x7F7F8181, 0x7F7F7F7F, 0x817F8181, 0x7F7F7F7F, 0x7F81817F, 0x81817F7F,
+0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x7F817F81, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x7F7F8181,
+0x81818181, 0x81817F81, 0x7F7F7F81, 0x7F817F81, 0x8181817F, 0x7F7F817F, 0x817F8181, 0x81818181,
+0x817F7F81, 0x8181817F, 0x7F818181, 0x7F7F7F81, 0x81818181, 0x817F8181, 0x81818181, 0x7F7F7F7F,
+0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x81817F7F, 0x81818181, 0x7F7F8181, 0x7F817F7F, 0x7F81817F,
+0x7F7F8181, 0x817F817F, 0x81818181, 0x81818181, 0x7F81817F, 0x81817F7F, 0x7F818181, 0x817F817F,
+0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x7F817F7F, 0x7F817F81, 0x81818181, 0x7F818181, 0x7F81817F,
+0x7F7F817F, 0x81817F81, 0x7F817F7F, 0x817F817F, 0x7F818181, 0x81817F7F, 0x817F817F, 0x7F818181,
+0x7F7F7F7F, 0x7F7F7F81, 0x817F817F, 0x7F818181, 0x817F817F, 0x7F81817F, 0x8181817F, 0x7F81817F,
+0x81817F81, 0x7F818181, 0x7F818181, 0x81818181, 0x81818181, 0x817F817F, 0x8181817F, 0x7F7F7F7F,
+0x817F7F81, 0x7F817F81, 0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x7F81817F, 0x81817F81, 0x817F8181,
+0x81817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F8181, 0x7F7F7F81, 0x817F817F, 0x817F7F81, 0x7F7F7F7F,
+0x817F817F, 0x817F817F, 0x7F7F8181, 0x7F818181, 0x7F7F7F7F, 0x7F817F7F, 0x7F817F81, 0x7F7F7F7F,
+0x81818181, 0x7F7F817F, 0x7F81817F, 0x81817F7F, 0x7F818181, 0x7F817F7F, 0x7F817F81, 0x81818181,
+0x7F817F81, 0x817F817F, 0x7F817F81, 0x817F817F, 0x7F7F817F, 0x817F8181, 0x7F7F7F81, 0x7F7F7F7F,
+0x817F7F81, 0x817F817F, 0x817F7F7F, 0x81818181, 0x817F7F81, 0x8181817F, 0x81817F81, 0x81817F81,
+0x7F7F817F, 0x7F81817F, 0x817F8181, 0x7F818181, 0x817F817F, 0x81817F81, 0x8181817F, 0x8181817F,
+0x817F817F, 0x81818181, 0x817F817F, 0x81817F81, 0x7F817F81, 0x817F7F7F, 0x7F818181, 0x817F8181,
+0x81818181, 0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x817F817F, 0x7F817F81, 0x81817F7F, 0x817F8181,
+0x817F817F, 0x81817F7F, 0x7F818181, 0x817F7F81, 0x817F7F81, 0x81818181, 0x7F81817F, 0x817F8181,
+0x81818181, 0x817F817F, 0x7F7F817F, 0x817F7F7F, 0x7F7F817F, 0x817F817F, 0x7F818181, 0x7F7F7F81,
+0x7F817F7F, 0x817F7F81, 0x81818181, 0x81817F81, 0x8181817F, 0x7F7F817F, 0x7F81817F, 0x817F817F,
+0x7F81817F, 0x817F7F81, 0x817F8181, 0x7F7F8181, 0x81817F7F, 0x7F817F81, 0x81818181, 0x817F8181,
+0x7F818181, 0x817F8181, 0x817F8181, 0x817F8181, 0x7F817F81, 0x7F818181, 0x817F7F7F, 0x81817F81,
+0x7F7F8181, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F7F, 0x81818181, 0x7F7F7F81, 0x7F818181, 0x81817F7F,
+0x8181817F, 0x7F7F8181, 0x7F7F7F81, 0x817F8181, 0x7F7F8181, 0x7F7F8181, 0x7F7F7F81, 0x8181817F,
+0x817F7F81, 0x7F7F817F, 0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x81817F7F, 0x817F8181, 0x7F7F8181,
+0x817F8181, 0x7F7F8181, 0x7F817F81, 0x7F81817F, 0x81817F7F, 0x817F817F, 0x8181817F, 0x7F81817F,
+0x817F7F7F, 0x81817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x817F7F81,
+0x8181817F, 0x817F7F7F, 0x7F7F817F, 0x7F7F817F, 0x81818181, 0x7F817F81, 0x7F81817F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F818181, 0x7F7F7F81, 0x8181817F, 0x817F8181, 0x81817F7F, 0x7F7F7F81, 0x81817F7F,
+0x7F817F7F, 0x7F7F817F, 0x817F7F81, 0x81817F7F, 0x7F817F7F, 0x81817F81, 0x81818181, 0x7F7F7F81,
+0x7F7F7F7F, 0x7F7F817F, 0x81817F7F, 0x7F818181, 0x7F7F817F, 0x817F7F81, 0x7F7F7F81, 0x7F817F81,
+0x8181817F, 0x817F817F, 0x817F8181, 0x81818181, 0x81818181, 0x7F7F8181, 0x7F817F81, 0x7F7F7F81,
+0x7F7F7F81, 0x7F7F7F7F, 0x81817F7F, 0x7F817F81, 0x817F817F, 0x7F7F7F81, 0x7F817F7F, 0x7F7F7F7F,
+0x7F7F817F, 0x7F818181, 0x7F7F817F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x7F817F81,
+0x7F7F7F7F, 0x7F81817F, 0x817F8181, 0x817F7F81, 0x7F7F8181, 0x7F818181, 0x817F7F7F, 0x7F7F7F81,
+0x7F7F817F, 0x7F817F81, 0x81818181, 0x7F817F7F, 0x817F7F7F, 0x8181817F, 0x81817F81, 0x7F7F817F,
+0x7F7F817F, 0x817F7F7F, 0x817F7F81, 0x81817F7F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x8181817F,
+0x7F7F8181, 0x7F7F7F7F, 0x81817F7F, 0x7F817F7F, 0x7F817F81, 0x7F7F817F, 0x7F81817F, 0x7F817F7F,
+0x81818181, 0x817F8181, 0x8181817F, 0x817F8181, 0x7F7F8181, 0x817F7F7F, 0x81818181, 0x817F8181,
+0x817F8181, 0x7F817F7F, 0x7F7F8181, 0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x817F817F, 0x81817F81,
+0x81817F7F, 0x8181817F, 0x7F818181, 0x817F8181, 0x7F7F8181, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F81,
+0x81817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F7F81, 0x7F7F817F, 0x817F8181, 0x817F8181, 0x7F7F817F,
+0x7F817F7F, 0x7F7F8181, 0x81818181, 0x81818181, 0x7F81817F, 0x817F8181, 0x817F7F81, 0x7F817F81,
+0x7F81817F, 0x817F817F, 0x7F7F8181, 0x81817F81, 0x817F817F, 0x7F818181, 0x8181817F, 0x7F7F8181,
+0x817F817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81, 0x817F7F7F, 0x8181817F, 0x7F81817F,
+0x81817F7F, 0x81817F7F, 0x7F81817F, 0x7F817F81, 0x817F8181, 0x817F817F, 0x81817F81, 0x81817F7F,
+0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x7F7F817F, 0x81818181, 0x817F7F7F, 0x817F817F, 0x817F8181,
+0x817F8181, 0x817F7F81, 0x7F817F81, 0x817F817F, 0x817F7F81, 0x7F817F7F, 0x817F8181, 0x81817F81,
+0x7F7F7F7F, 0x817F8181, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F, 0x81818181, 0x7F817F7F, 0x817F7F7F,
+0x817F7F7F, 0x81817F81, 0x81818181, 0x81818181, 0x81818181, 0x81818181, 0x817F817F, 0x7F7F7F7F,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x817F8181, 0x8181817F, 0x7F818181, 0x817F7F7F, 0x81817F81,
+0x81818181, 0x7F818181, 0x817F8181, 0x7F817F7F, 0x817F7F7F, 0x7F818181, 0x7F7F817F, 0x7F7F7F81,
+0x7F818181, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F7F817F, 0x817F8181, 0x7F7F7F7F, 0x817F7F81,
+0x81818181, 0x7F817F81, 0x81818181, 0x7F7F7F81, 0x817F7F7F, 0x817F7F7F, 0x81818181, 0x817F7F7F,
+0x817F8181, 0x81818181, 0x8181817F, 0x7F817F7F, 0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x7F7F8181,
+0x7F7F817F, 0x7F7F7F7F, 0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x81818181, 0x7F7F817F, 0x81817F81,
+0x81818181, 0x817F8181, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F8181, 0x81818181, 0x7F817F81, 0x8181817F,
+0x817F7F7F, 0x81817F81, 0x7F817F81, 0x81818181, 0x7F817F81, 0x81818181, 0x8181817F, 0x7F817F7F,
+0x8181817F, 0x7F818181, 0x8181817F, 0x81818181, 0x81817F81, 0x7F818181, 0x7F817F7F, 0x8181817F,
+0x81817F7F, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x81818181, 0x7F7F817F, 0x7F818181, 0x817F817F,
+0x817F7F81, 0x7F81817F, 0x8181817F, 0x7F817F7F, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F817F7F,
+0x81818181, 0x7F81817F, 0x817F7F81, 0x7F7F8181, 0x817F817F, 0x81818181, 0x81817F7F, 0x7F817F7F,
+0x817F7F81, 0x7F817F7F, 0x817F7F7F, 0x7F7F8181, 0x7F818181, 0x7F818181, 0x817F7F81, 0x8181817F,
+0x817F817F, 0x7F7F8181, 0x81818181, 0x7F81817F, 0x7F818181, 0x7F81817F, 0x817F8181, 0x817F817F,
+0x7F7F7F7F, 0x81818181, 0x7F7F817F, 0x817F7F81, 0x7F817F81, 0x7F817F7F, 0x8181817F, 0x7F818181,
+0x817F817F, 0x817F7F7F, 0x81817F7F, 0x7F7F817F, 0x7F81817F, 0x7F818181, 0x7F81817F, 0x7F81817F,
+0x7F7F817F, 0x81817F7F, 0x7F81817F, 0x7F817F81, 0x8181817F, 0x7F818181, 0x81817F81, 0x817F7F7F,
+0x7F81817F, 0x7F818181, 0x7F818181, 0x7F7F817F, 0x81818181, 0x81817F81, 0x817F7F7F, 0x7F817F81,
+0x817F7F7F, 0x81817F81, 0x7F7F7F81, 0x8181817F, 0x7F817F7F, 0x81817F81, 0x7F7F7F81, 0x817F8181,
+0x817F7F81, 0x7F818181, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x7F817F81, 0x817F8181, 0x817F817F,
+0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x8181817F, 0x7F818181, 0x81817F81, 0x7F7F817F, 0x817F7F7F,
+0x7F81817F, 0x81817F81, 0x817F7F81, 0x7F7F7F7F, 0x7F7F817F, 0x81817F81, 0x817F7F81, 0x817F8181,
+0x81818181, 0x7F81817F, 0x7F817F81, 0x7F817F7F, 0x81817F81, 0x817F817F, 0x7F817F81, 0x7F818181,
+0x7F818181, 0x8181817F, 0x81817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x7F818181,
+0x8181817F, 0x7F818181, 0x7F7F8181, 0x7F7F7F81, 0x81817F7F, 0x81818181, 0x7F7F7F7F, 0x7F81817F,
+0x81817F7F, 0x7F817F7F, 0x7F7F7F7F, 0x8181817F, 0x7F7F7F81, 0x81817F7F, 0x7F7F817F, 0x7F7F7F81,
+0x7F817F7F, 0x817F817F, 0x7F817F7F, 0x81817F81, 0x7F818181, 0x7F7F8181, 0x7F818181, 0x817F817F,
+0x7F817F7F, 0x7F81817F, 0x7F7F7F7F, 0x81818181, 0x8181817F, 0x81817F81, 0x7F817F81, 0x817F7F7F,
+0x8181817F, 0x7F7F7F81, 0x7F817F81, 0x7F7F7F81, 0x7F81817F, 0x81817F7F, 0x7F817F7F, 0x7F7F8181,
+0x7F817F81, 0x817F7F7F, 0x7F81817F, 0x7F817F7F, 0x817F7F7F, 0x81817F7F, 0x8181817F, 0x7F817F81,
+0x81817F7F, 0x817F7F7F, 0x817F8181, 0x7F818181, 0x81817F81, 0x7F7F817F, 0x7F81817F, 0x7F7F7F81,
+0x8181817F, 0x7F818181, 0x7F7F817F, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x7F81817F, 0x7F818181,
+0x7F7F7F7F, 0x817F817F, 0x81817F7F, 0x81817F81, 0x817F817F, 0x7F7F8181, 0x7F818181, 0x7F81817F,
+0x7F818181, 0x7F7F8181, 0x817F817F, 0x7F817F7F, 0x81817F81, 0x7F7F817F, 0x7F7F7F81, 0x7F818181,
+0x7F7F8181, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x817F8181, 0x817F8181, 0x81817F81, 0x7F81817F,
+0x7F7F8181, 0x817F817F, 0x817F7F81, 0x7F817F7F, 0x7F7F8181, 0x817F817F, 0x7F7F7F81, 0x817F8181,
+0x81817F81, 0x7F818181, 0x7F817F81, 0x7F7F7F81, 0x7F817F7F, 0x7F818181, 0x7F7F817F, 0x7F7F7F7F,
+0x817F7F7F, 0x81817F81, 0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x81818181, 0x7F81817F, 0x7F7F7F81,
+0x817F8181, 0x817F7F7F, 0x817F817F, 0x7F7F817F, 0x81817F7F, 0x7F817F81, 0x817F8181, 0x7F817F81,
+0x7F817F81, 0x7F7F8181, 0x7F81817F, 0x7F7F817F, 0x817F8181, 0x7F817F7F, 0x7F7F817F, 0x817F7F7F,
+0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x7F818181, 0x817F7F7F, 0x817F817F, 0x7F817F81, 0x817F8181,
+0x817F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x8181817F, 0x8181817F, 0x817F817F, 0x817F8181, 0x8181817F,
+0x7F817F81, 0x7F7F7F7F, 0x7F818181, 0x7F817F7F, 0x7F7F817F, 0x7F81817F, 0x81817F81, 0x817F8181,
+0x7F7F7F81, 0x8181817F, 0x8181817F, 0x81818181, 0x7F7F8181, 0x817F7F81, 0x7F817F7F, 0x817F8181,
+0x7F817F81, 0x7F818181, 0x81818181, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x7F817F7F, 0x7F7F817F,
+0x7F7F7F81, 0x7F818181, 0x8181817F, 0x8181817F, 0x81818181, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F81,
+0x817F817F, 0x7F817F81, 0x7F818181, 0x8181817F, 0x81817F81, 0x817F7F81, 0x81817F81, 0x7F7F817F,
+0x817F8181, 0x7F81817F, 0x7F817F7F, 0x7F817F81, 0x817F817F, 0x81817F7F, 0x7F818181, 0x817F817F,
+0x7F7F7F81, 0x817F817F, 0x8181817F, 0x7F7F817F, 0x7F7F7F81, 0x7F817F81, 0x7F818181, 0x817F817F,
+0x817F817F, 0x81817F7F, 0x7F817F7F, 0x817F817F, 0x817F8181, 0x817F8181, 0x817F8181, 0x81818181,
+0x817F7F81, 0x817F7F7F, 0x81817F7F, 0x81818181, 0x817F7F81, 0x817F8181, 0x8181817F, 0x8181817F,
+0x81817F7F, 0x81817F7F, 0x81817F7F, 0x7F7F7F7F, 0x817F7F81, 0x81818181, 0x817F8181, 0x7F7F7F81,
+0x817F817F, 0x7F817F7F, 0x7F7F817F, 0x817F7F7F, 0x81817F81, 0x81817F81, 0x7F7F817F, 0x7F817F7F,
+0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x81817F81, 0x7F81817F, 0x7F818181, 0x7F817F7F, 0x81818181,
+0x81817F81, 0x81817F81, 0x7F7F817F, 0x81817F7F, 0x7F817F7F, 0x7F7F8181, 0x81818181, 0x8181817F,
+0x7F81817F, 0x81817F7F, 0x7F7F7F81, 0x7F81817F, 0x817F8181, 0x81817F81, 0x81818181, 0x817F7F7F,
+0x7F818181, 0x7F817F7F, 0x7F817F7F, 0x817F817F, 0x7F817F81, 0x7F81817F, 0x817F817F, 0x81817F81,
+0x817F7F7F, 0x8181817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F7F7F, 0x8181817F,
+0x81817F81, 0x81817F7F, 0x7F7F7F7F, 0x81817F7F, 0x817F7F7F, 0x81818181, 0x817F7F7F, 0x817F817F,
+0x8181817F, 0x7F817F7F, 0x817F7F81, 0x8181817F, 0x817F8181, 0x7F817F81, 0x8181817F, 0x81818181,
+0x7F7F7F81, 0x817F8181, 0x7F817F7F, 0x81818181, 0x7F818181, 0x81817F81, 0x817F7F7F, 0x817F8181,
+0x7F818181, 0x7F818181, 0x7F818181, 0x817F817F, 0x7F7F7F81, 0x817F8181, 0x817F7F7F, 0x8181817F,
+0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F817F81, 0x81818181, 0x817F7F7F, 0x817F8181, 0x81818181,
+0x7F817F7F, 0x7F817F81, 0x817F7F81, 0x81818181, 0x7F7F8181, 0x7F817F7F, 0x7F817F7F, 0x817F8181,
+0x7F7F817F, 0x7F81817F, 0x8181817F, 0x81817F7F, 0x8181817F, 0x817F7F81, 0x81818181, 0x7F817F7F,
+0x817F817F, 0x817F8181, 0x817F817F, 0x81817F7F, 0x817F7F81, 0x7F7F7F81, 0x7F7F8181, 0x7F817F7F,
+0x81817F7F, 0x817F817F, 0x817F7F7F, 0x817F8181, 0x7F81817F, 0x7F7F8181, 0x81817F81, 0x817F817F,
+0x7F7F7F81, 0x81817F81, 0x817F7F7F, 0x81817F7F, 0x7F7F7F81, 0x817F7F81, 0x7F81817F, 0x81817F7F,
+0x7F817F81, 0x7F818181, 0x81817F7F, 0x7F817F7F, 0x81817F81, 0x8181817F, 0x817F817F, 0x7F7F817F,
+0x817F817F, 0x7F7F7F81, 0x817F7F81, 0x817F7F81, 0x7F817F81, 0x81818181, 0x81817F7F, 0x81818181,
+0x817F817F, 0x7F817F7F, 0x81817F7F, 0x7F818181, 0x81818181, 0x7F818181, 0x81817F7F, 0x81817F81,
+0x81817F7F, 0x7F818181, 0x817F8181, 0x7F7F7F81, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x81817F7F,
+0x81817F81, 0x817F8181, 0x81817F81, 0x7F7F7F7F, 0x7F818181, 0x8181817F, 0x817F817F, 0x7F7F7F7F,
+0x81817F81, 0x7F7F817F, 0x817F7F81, 0x8181817F, 0x7F7F7F81, 0x81818181, 0x7F7F8181, 0x7F817F7F,
+0x81817F81, 0x8181817F, 0x7F817F81, 0x7F817F81, 0x817F7F7F, 0x81818181, 0x7F7F7F81, 0x7F7F8181,
+0x817F817F, 0x81817F7F, 0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x817F8181, 0x7F817F7F,
+0x7F81817F, 0x817F817F, 0x7F7F817F, 0x817F8181, 0x7F81817F, 0x7F817F81, 0x7F7F817F, 0x7F818181,
+0x817F817F, 0x817F7F7F, 0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x81817F81, 0x7F81817F, 0x7F817F7F,
+0x7F81817F, 0x7F7F8181, 0x8181817F, 0x81818181, 0x817F817F, 0x7F7F817F, 0x817F7F7F, 0x81818181,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F818181, 0x81818181,
+0x81817F81, 0x7F81817F, 0x7F81817F, 0x7F817F7F, 0x7F817F81, 0x7F7F7F7F, 0x81817F81, 0x8181817F,
+0x7F7F8181, 0x8181817F, 0x817F817F, 0x7F7F8181, 0x81817F7F, 0x7F817F7F, 0x7F818181, 0x817F7F7F,
+0x7F817F81, 0x7F817F7F, 0x7F818181, 0x8181817F, 0x7F7F7F7F, 0x8181817F, 0x7F7F7F81, 0x7F817F7F,
+0x817F8181, 0x7F81817F, 0x7F818181, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x81817F81, 0x7F7F7F7F,
+0x7F7F8181, 0x817F7F7F, 0x8181817F, 0x7F7F7F81, 0x8181817F, 0x81817F81, 0x7F7F7F7F, 0x817F7F81,
+0x8181817F, 0x7F81817F, 0x7F7F817F, 0x817F7F7F, 0x817F7F7F, 0x817F8181, 0x7F7F8181, 0x7F7F817F,
+0x81817F7F, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x817F8181, 0x81817F81, 0x817F7F7F, 0x81817F7F,
+0x817F7F81, 0x7F7F7F81, 0x7F818181, 0x817F817F, 0x817F7F81, 0x817F7F7F, 0x817F817F, 0x7F817F7F,
+0x81817F81, 0x7F7F817F, 0x7F817F81, 0x81818181, 0x817F8181, 0x817F7F7F, 0x81818181, 0x7F7F817F,
+0x8181817F, 0x7F7F7F7F, 0x7F818181, 0x817F7F81, 0x81817F7F, 0x81818181, 0x7F817F81, 0x817F7F81,
+0x817F8181, 0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F81817F, 0x8181817F,
+0x817F817F, 0x7F817F81, 0x7F817F81, 0x81817F7F, 0x817F7F81, 0x7F7F7F81, 0x7F7F8181, 0x7F7F8181,
+0x7F818181, 0x817F817F, 0x7F7F817F, 0x7F817F81, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x7F818181,
+0x81817F7F, 0x817F7F81, 0x81817F81, 0x81817F81, 0x81817F81, 0x7F7F7F81, 0x7F7F817F, 0x8181817F,
+0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x817F7F81, 0x7F7F7F81, 0x7F817F81, 0x817F817F, 0x81818181,
+0x7F7F7F81, 0x817F7F7F, 0x7F817F81, 0x7F7F7F81, 0x81818181, 0x817F8181, 0x81817F7F, 0x8181817F,
+0x81817F81, 0x817F8181, 0x817F8181, 0x817F817F, 0x7F7F7F81, 0x817F7F7F, 0x817F7F81, 0x7F818181,
+0x817F8181, 0x817F7F7F, 0x817F7F7F, 0x81817F81, 0x7F81817F, 0x817F7F81, 0x7F7F817F, 0x8181817F,
+0x81818181, 0x7F7F7F81, 0x81818181, 0x81817F81, 0x817F7F81, 0x7F817F7F, 0x81818181, 0x81817F81,
+0x7F7F7F81, 0x817F8181, 0x7F7F7F81, 0x817F7F81, 0x7F817F81, 0x7F817F81, 0x7F817F7F, 0x7F7F817F,
+0x7F817F7F, 0x817F7F81, 0x817F817F, 0x81817F81, 0x7F7F7F7F, 0x81817F81, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x7F7F7F81, 0x817F7F7F, 0x817F7F81, 0x7F818181, 0x817F7F7F, 0x7F818181, 0x817F817F,
+0x81817F7F, 0x8181817F, 0x7F81817F, 0x7F81817F, 0x81817F7F, 0x817F817F, 0x8181817F, 0x817F8181,
+0x7F7F7F7F, 0x7F818181, 0x817F817F, 0x817F8181, 0x817F817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F817F,
+0x7F7F7F81, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x7F817F81, 0x81818181, 0x8181817F, 0x7F817F7F,
+0x7F7F8181, 0x817F8181, 0x81817F7F, 0x81818181, 0x7F818181, 0x817F817F, 0x7F818181, 0x81817F81,
+0x817F7F81, 0x7F7F8181, 0x7F817F7F, 0x817F7F81, 0x81817F81, 0x81817F81, 0x81817F81, 0x7F7F8181,
+0x817F8181, 0x81817F7F, 0x7F817F7F, 0x7F81817F, 0x7F7F7F7F, 0x81817F81, 0x7F7F8181, 0x7F7F817F,
+0x7F81817F, 0x81817F7F, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F, 0x7F7F817F, 0x817F7F7F, 0x7F7F8181,
+0x81818181, 0x7F7F7F81, 0x7F7F8181, 0x8181817F, 0x7F817F7F, 0x817F7F7F, 0x7F7F817F, 0x7F81817F,
+0x81817F7F, 0x817F7F7F, 0x8181817F, 0x817F817F, 0x81817F7F, 0x81817F7F, 0x817F8181, 0x81817F7F,
+0x7F7F7F81, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x7F7F8181, 0x7F7F8181, 0x81818181, 0x817F817F,
+0x81817F81, 0x8181817F, 0x7F7F7F7F, 0x81817F81, 0x81817F7F, 0x817F8181, 0x817F817F, 0x817F8181,
+0x817F7F7F, 0x8181817F, 0x81817F81, 0x817F8181, 0x7F7F817F, 0x7F81817F, 0x7F817F7F, 0x7F817F7F,
+0x81818181, 0x817F7F81, 0x817F8181, 0x7F7F817F, 0x817F817F, 0x7F7F7F81, 0x81818181, 0x817F7F7F,
+0x7F817F81, 0x7F817F7F, 0x817F817F, 0x7F7F7F81, 0x7F7F8181, 0x81817F81, 0x7F818181, 0x817F817F,
+0x7F818181, 0x817F7F7F, 0x81818181, 0x817F7F7F, 0x81818181, 0x817F817F, 0x7F7F7F7F, 0x8181817F,
+0x7F7F817F, 0x7F81817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F817F, 0x7F817F7F, 0x817F7F81, 0x817F8181,
+0x7F81817F, 0x81817F81, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F, 0x7F7F8181, 0x817F7F81, 0x817F817F,
+0x7F817F7F, 0x8181817F, 0x7F817F7F, 0x7F817F7F, 0x81817F81, 0x81817F81, 0x817F7F81, 0x817F8181,
+0x81817F7F, 0x817F7F81, 0x817F7F7F, 0x7F81817F, 0x81817F7F, 0x817F8181, 0x7F817F7F, 0x7F7F7F7F,
+0x7F817F81, 0x817F8181, 0x817F8181, 0x7F7F7F81, 0x7F817F7F, 0x7F817F7F, 0x7F7F8181, 0x7F7F7F7F,
+0x817F8181, 0x817F8181, 0x81818181, 0x81817F7F, 0x817F7F81, 0x817F7F7F, 0x8181817F, 0x7F817F81,
+0x8181817F, 0x81817F81, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x7F81817F, 0x817F7F81, 0x81817F7F,
+0x81818181, 0x7F817F81, 0x81818181, 0x81817F7F, 0x8181817F, 0x817F7F7F, 0x7F817F7F, 0x817F7F81,
+0x7F7F817F, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x81818181, 0x7F7F7F81, 0x8181817F, 0x7F818181,
+0x817F8181, 0x7F817F81, 0x7F81817F, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x81817F81, 0x8181817F,
+0x7F7F7F7F, 0x7F7F817F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F7F, 0x7F817F81, 0x7F7F7F81, 0x7F7F817F,
+0x7F7F817F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F8181, 0x7F7F7F81, 0x817F7F7F, 0x7F81817F, 0x81818181,
+0x7F7F7F7F, 0x81817F81, 0x7F7F8181, 0x7F7F817F, 0x817F8181, 0x7F817F81, 0x7F7F8181, 0x7F7F7F7F,
+0x7F7F7F81, 0x817F7F7F, 0x817F817F, 0x7F817F7F, 0x817F8181, 0x8181817F, 0x7F81817F, 0x7F7F7F81,
+0x817F8181, 0x7F7F7F81, 0x81817F81, 0x7F817F7F, 0x817F8181, 0x7F7F8181, 0x81817F81, 0x8181817F,
+0x817F817F, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x7F817F7F, 0x817F7F7F, 0x817F7F81, 0x7F817F81,
+0x81817F81, 0x817F7F81, 0x7F7F7F7F, 0x817F8181, 0x8181817F, 0x817F7F7F, 0x7F818181, 0x7F818181,
+0x7F7F8181, 0x7F81817F, 0x817F8181, 0x7F817F81, 0x7F817F81, 0x817F8181, 0x817F817F, 0x7F7F817F,
+0x7F7F8181, 0x81818181, 0x817F7F7F, 0x7F818181, 0x81818181, 0x8181817F, 0x81818181, 0x7F81817F,
+0x7F7F7F81, 0x81817F7F, 0x7F7F7F7F, 0x817F8181, 0x817F7F7F, 0x7F818181, 0x7F81817F, 0x81818181,
+0x7F7F7F7F, 0x817F8181, 0x7F7F8181, 0x7F817F81, 0x817F817F, 0x7F818181, 0x817F8181, 0x7F818181,
+0x817F7F81, 0x81817F7F, 0x817F8181, 0x7F818181, 0x7F7F817F, 0x7F7F7F7F, 0x7F818181, 0x7F817F81,
+0x7F818181, 0x8181817F, 0x7F81817F, 0x7F7F7F7F, 0x7F817F7F, 0x817F8181, 0x817F7F81, 0x7F81817F,
+0x7F817F7F, 0x817F7F81, 0x817F817F, 0x7F818181, 0x817F817F, 0x8181817F, 0x7F81817F, 0x81817F81,
+0x8181817F, 0x8181817F, 0x7F81817F, 0x7F81817F, 0x7F7F8181, 0x7F7F8181, 0x81818181, 0x81818181,
+0x817F7F81, 0x7F817F7F, 0x817F7F81, 0x7F81817F, 0x7F7F7F81, 0x8181817F, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x7F7F817F, 0x81817F81, 0x7F818181, 0x7F7F7F81, 0x7F7F8181, 0x8181817F, 0x7F817F7F,
+0x81818181, 0x7F7F7F81, 0x81817F81, 0x81817F7F, 0x817F7F7F, 0x817F7F7F, 0x817F7F81, 0x7F7F7F7F,
+0x817F7F81, 0x7F818181, 0x7F7F7F7F, 0x81818181, 0x7F817F7F, 0x7F81817F, 0x7F817F81, 0x81817F81,
+0x7F7F8181, 0x7F817F81, 0x7F818181, 0x7F817F7F, 0x8181817F, 0x817F7F7F, 0x817F817F, 0x817F8181,
+0x817F7F7F, 0x81817F7F, 0x7F81817F, 0x7F81817F, 0x817F7F7F, 0x81818181, 0x817F817F, 0x7F7F7F7F,
+0x8181817F, 0x817F817F, 0x7F818181, 0x7F818181, 0x817F7F7F, 0x7F81817F, 0x817F817F, 0x81818181,
+0x8181817F, 0x7F7F817F, 0x7F818181, 0x817F7F81, 0x81817F7F, 0x81817F7F, 0x7F7F7F7F, 0x817F8181,
+0x7F818181, 0x7F7F7F81, 0x81817F81, 0x81817F81, 0x7F81817F, 0x817F817F, 0x7F7F7F81, 0x7F7F7F81,
+0x7F817F81, 0x7F81817F, 0x817F817F, 0x7F818181, 0x7F7F817F, 0x817F7F81, 0x817F7F7F, 0x7F7F7F7F,
+0x7F817F81, 0x81817F81, 0x81817F7F, 0x7F817F7F, 0x81817F7F, 0x7F7F7F7F, 0x81817F7F, 0x817F7F81,
+0x7F81817F, 0x817F7F7F, 0x7F7F817F, 0x7F817F81, 0x8181817F, 0x81818181, 0x7F81817F, 0x7F7F8181,
+0x817F817F, 0x7F817F7F, 0x817F8181, 0x817F7F7F, 0x7F7F7F81, 0x817F817F, 0x81817F81, 0x7F81817F,
+0x7F817F81, 0x7F7F817F, 0x7F817F7F, 0x817F7F81, 0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x817F7F81,
+0x81817F7F, 0x81817F7F, 0x8181817F, 0x7F818181, 0x7F7F8181, 0x7F817F81, 0x7F817F7F, 0x7F7F817F,
+0x81818181, 0x7F817F7F, 0x81818181, 0x81817F7F, 0x7F817F7F, 0x7F81817F, 0x7F7F8181, 0x817F8181,
+0x8181817F, 0x7F7F7F81, 0x817F817F, 0x7F7F7F7F, 0x817F8181, 0x7F7F7F81, 0x8181817F, 0x7F7F7F81,
+0x7F817F81, 0x81817F7F, 0x7F7F7F7F, 0x81817F81, 0x7F817F81, 0x817F7F81, 0x7F7F7F7F, 0x81817F81,
+0x7F7F817F, 0x7F7F817F, 0x81817F81, 0x8181817F, 0x7F7F7F7F, 0x7F7F8181, 0x81817F7F, 0x7F81817F,
+0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x817F7F7F, 0x817F7F81, 0x817F7F81, 0x817F8181, 0x81818181,
+0x7F7F817F, 0x7F7F817F, 0x81817F7F, 0x7F81817F, 0x7F7F7F7F, 0x81817F81, 0x81817F81, 0x7F81817F,
+0x817F7F81, 0x7F817F81, 0x817F8181, 0x7F7F817F, 0x7F818181, 0x7F818181, 0x81817F7F, 0x817F7F81,
+0x7F7F817F, 0x7F817F81, 0x7F7F817F, 0x7F818181, 0x8181817F, 0x817F7F81, 0x7F7F817F, 0x7F817F81,
+0x81817F81, 0x81818181, 0x817F7F7F, 0x817F817F, 0x7F81817F, 0x8181817F, 0x81817F7F, 0x81817F81,
+0x7F7F8181, 0x817F7F81, 0x817F817F, 0x817F8181, 0x817F8181, 0x81817F7F, 0x817F7F81, 0x7F817F7F,
+0x81817F81, 0x7F81817F, 0x7F817F81, 0x817F8181, 0x7F7F817F, 0x7F7F7F7F, 0x81818181, 0x7F81817F,
+0x81817F7F, 0x817F8181, 0x7F818181, 0x81818181, 0x817F7F81, 0x7F81817F, 0x81818181, 0x7F817F81,
+0x817F8181, 0x817F7F7F, 0x7F817F7F, 0x7F817F81, 0x7F7F8181, 0x7F817F7F, 0x7F7F7F7F, 0x817F8181,
+0x7F81817F, 0x7F7F7F81, 0x7F817F7F, 0x7F818181, 0x7F817F7F, 0x7F81817F, 0x7F7F817F, 0x7F7F7F81,
+0x81817F7F, 0x8181817F, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x81818181,
+0x7F7F817F, 0x7F817F7F, 0x7F818181, 0x7F817F7F, 0x7F817F7F, 0x817F7F81, 0x7F81817F, 0x81817F81,
+0x81817F81, 0x7F81817F, 0x7F818181, 0x7F818181, 0x81818181, 0x81817F81, 0x7F7F8181, 0x7F81817F,
+0x817F8181, 0x817F7F81, 0x7F817F81, 0x7F7F7F7F, 0x81817F7F, 0x7F7F817F, 0x81817F7F, 0x7F7F7F7F,
+0x7F7F817F, 0x81818181, 0x81818181, 0x7F7F817F, 0x7F817F7F, 0x7F818181, 0x817F7F7F, 0x7F817F7F,
+0x817F8181, 0x81818181, 0x7F81817F, 0x817F7F7F, 0x7F818181, 0x81818181, 0x8181817F, 0x7F818181,
+0x7F817F7F, 0x7F7F7F7F, 0x7F7F817F, 0x817F8181, 0x7F7F7F81, 0x817F817F, 0x81818181, 0x81817F7F,
+0x817F8181, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x81818181,
+0x81817F81, 0x81818181, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x817F817F, 0x7F7F7F7F, 0x817F8181,
+0x7F818181, 0x817F8181, 0x7F81817F, 0x81817F7F, 0x7F818181, 0x8181817F, 0x7F7F7F81, 0x7F817F81,
+0x817F817F, 0x81818181, 0x817F8181, 0x81817F7F, 0x817F7F81, 0x7F817F81, 0x81817F7F, 0x7F81817F,
+0x7F7F817F, 0x81817F7F, 0x81817F81, 0x7F81817F, 0x7F817F81, 0x8181817F, 0x7F7F7F81, 0x81817F81,
+0x81817F81, 0x817F817F, 0x81817F7F, 0x81817F81, 0x817F7F81, 0x81817F7F, 0x7F7F817F, 0x7F7F817F,
+0x817F817F, 0x8181817F, 0x7F81817F, 0x81817F7F, 0x7F818181, 0x817F7F81, 0x7F7F817F, 0x817F7F81,
+0x7F7F7F81, 0x7F7F817F, 0x817F7F81, 0x7F7F7F81, 0x8181817F, 0x81818181, 0x7F7F817F, 0x7F7F8181,
+0x817F7F81, 0x817F7F7F, 0x81818181, 0x7F7F817F, 0x817F817F, 0x81817F81, 0x7F817F7F, 0x7F817F81,
+0x7F7F8181, 0x7F817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F7F81, 0x817F8181, 0x81817F81, 0x81817F81,
+0x81818181, 0x817F817F, 0x7F7F8181, 0x817F817F, 0x8181817F, 0x81817F7F, 0x81817F7F, 0x7F7F7F81,
+0x7F817F7F, 0x7F81817F, 0x7F817F81, 0x81817F81, 0x81817F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x7F7F7F81, 0x7F817F81, 0x817F7F7F, 0x7F7F7F81, 0x81818181, 0x81818181, 0x7F7F7F7F, 0x817F7F81,
+0x7F7F7F7F, 0x817F8181, 0x817F7F7F, 0x7F7F7F81, 0x817F8181, 0x7F818181, 0x817F7F81, 0x81817F7F,
+0x7F817F81, 0x7F7F8181, 0x8181817F, 0x7F7F8181, 0x8181817F, 0x817F817F, 0x81817F81, 0x7F817F81,
+0x7F818181, 0x7F81817F, 0x81818181, 0x81817F81, 0x7F817F81, 0x81818181, 0x7F7F7F7F, 0x7F81817F,
+0x7F7F7F81, 0x7F817F7F, 0x8181817F, 0x81818181, 0x81817F81, 0x81817F7F, 0x817F7F7F, 0x7F817F7F,
+0x81817F7F, 0x7F7F817F, 0x81817F7F, 0x7F817F7F, 0x7F7F7F7F, 0x817F8181, 0x817F7F7F, 0x817F817F,
+0x817F7F7F, 0x7F818181, 0x7F817F81, 0x81817F81, 0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F7F,
+0x81818181, 0x81817F7F, 0x817F8181, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81,
+0x817F7F81, 0x7F81817F, 0x81817F81, 0x81817F81, 0x81817F81, 0x8181817F, 0x7F81817F, 0x817F817F,
+0x81817F81, 0x7F7F7F81, 0x817F817F, 0x817F7F7F, 0x81818181, 0x817F7F81, 0x81817F81, 0x81817F81,
+0x7F7F817F, 0x7F7F817F, 0x81817F7F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F817F,
+0x81817F81, 0x7F81817F, 0x81818181, 0x817F7F81, 0x7F817F7F, 0x81818181, 0x8181817F, 0x7F818181,
+0x7F817F7F, 0x8181817F, 0x7F817F7F, 0x7F7F7F81, 0x817F817F, 0x817F7F81, 0x7F7F7F81, 0x7F81817F,
+0x817F7F7F, 0x81817F81, 0x81817F81, 0x7F818181, 0x7F818181, 0x7F7F7F7F, 0x7F818181, 0x7F7F8181,
+0x7F81817F, 0x817F817F, 0x7F817F7F, 0x7F7F7F81, 0x81817F81, 0x81817F7F, 0x7F7F7F7F, 0x817F8181,
+0x8181817F, 0x81817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F8181, 0x7F817F7F, 0x817F817F, 0x81818181,
+0x817F7F7F, 0x7F81817F, 0x7F817F7F, 0x817F8181, 0x7F817F81, 0x817F8181, 0x81817F7F, 0x7F7F817F,
+0x7F817F81, 0x8181817F, 0x817F817F, 0x8181817F, 0x7F817F7F, 0x7F7F7F7F, 0x81817F7F, 0x81817F81,
+0x81817F7F, 0x81818181, 0x7F81817F, 0x7F81817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F8181, 0x81817F7F,
+0x7F818181, 0x81817F81, 0x817F8181, 0x817F7F7F, 0x817F817F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F81,
+0x81818181, 0x81817F7F, 0x81817F81, 0x7F7F8181, 0x817F8181, 0x817F817F, 0x7F818181, 0x81817F81,
+0x81818181, 0x81818181, 0x7F7F8181, 0x7F817F7F, 0x817F7F81, 0x817F8181, 0x7F7F817F, 0x81817F7F,
+0x7F817F81, 0x7F818181, 0x817F7F81, 0x7F7F8181, 0x81817F7F, 0x8181817F, 0x817F7F81, 0x81817F7F,
+0x7F7F7F81, 0x7F7F817F, 0x81817F7F, 0x817F7F81, 0x7F817F7F, 0x8181817F, 0x817F7F81, 0x817F7F81,
+0x817F7F7F, 0x81818181, 0x7F817F81, 0x817F7F7F, 0x817F817F, 0x817F7F81, 0x81817F7F, 0x7F81817F,
+0x81817F81, 0x817F8181, 0x817F817F, 0x81817F7F, 0x81818181, 0x81818181, 0x817F8181, 0x817F817F,
+0x7F7F817F, 0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x8181817F, 0x7F7F7F7F, 0x81817F7F, 0x7F7F7F81,
+0x81817F7F, 0x7F817F7F, 0x7F817F7F, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x81817F7F, 0x817F8181,
+0x7F817F7F, 0x817F7F81, 0x7F81817F, 0x8181817F, 0x81817F7F, 0x7F7F7F7F, 0x817F8181, 0x8181817F,
+0x817F7F81, 0x81818181, 0x817F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F818181, 0x7F7F817F, 0x7F817F7F,
+0x81818181, 0x81817F7F, 0x7F7F8181, 0x817F817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F81,
+0x7F7F7F81, 0x817F8181, 0x817F8181, 0x81818181, 0x7F7F7F81, 0x7F7F7F7F, 0x817F8181, 0x7F817F81,
+0x7F7F7F7F, 0x7F7F817F, 0x817F817F, 0x7F818181, 0x81817F7F, 0x817F7F81, 0x817F817F, 0x81817F7F,
+0x7F7F8181, 0x81818181, 0x7F7F7F7F, 0x817F8181, 0x7F81817F, 0x817F7F81, 0x7F818181, 0x81818181,
+0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F7F81, 0x8181817F, 0x81817F7F, 0x81818181, 0x817F7F81,
+0x7F81817F, 0x817F817F, 0x8181817F, 0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x7F818181, 0x817F7F81,
+0x7F817F81, 0x7F7F7F81, 0x7F7F7F7F, 0x817F7F7F, 0x81817F81, 0x817F7F81, 0x817F817F, 0x7F818181,
+0x7F817F7F, 0x7F7F8181, 0x7F81817F, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x817F7F7F, 0x8181817F,
+0x7F817F81, 0x7F818181, 0x7F81817F, 0x7F817F7F, 0x817F8181, 0x7F7F7F7F, 0x7F817F7F, 0x817F817F,
+0x817F7F81, 0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F7F8181, 0x7F7F8181, 0x7F818181, 0x7F7F817F,
+0x8181817F, 0x8181817F, 0x8181817F, 0x7F817F7F, 0x7F7F8181, 0x7F7F7F81, 0x817F7F81, 0x81817F7F,
+0x817F7F7F, 0x7F7F8181, 0x817F7F81, 0x817F7F7F, 0x81818181, 0x81818181, 0x81818181, 0x7F7F7F81,
+0x7F7F7F7F, 0x7F81817F, 0x7F81817F, 0x8181817F, 0x7F817F81, 0x7F818181, 0x817F8181, 0x8181817F,
+0x7F7F7F7F, 0x7F818181, 0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x8181817F,
+0x7F7F817F, 0x81817F81, 0x81818181, 0x7F81817F, 0x81817F81, 0x7F7F8181, 0x81817F7F, 0x7F7F7F81,
+0x81818181, 0x817F8181, 0x81818181, 0x817F7F81, 0x81818181, 0x81818181, 0x817F8181, 0x817F8181,
+0x7F7F7F81, 0x817F7F7F, 0x7F818181, 0x81817F7F, 0x81817F81, 0x817F8181, 0x817F8181, 0x817F7F7F,
+0x7F7F7F7F, 0x81817F81, 0x81817F7F, 0x7F817F81, 0x81817F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F817F,
+0x7F817F7F, 0x7F7F7F7F, 0x7F817F81, 0x817F817F, 0x817F8181, 0x817F8181, 0x7F7F817F, 0x7F7F7F81,
+0x7F818181, 0x81817F7F, 0x817F8181, 0x817F7F7F, 0x7F81817F, 0x7F7F817F, 0x817F8181, 0x7F7F7F7F,
+0x7F818181, 0x7F7F8181, 0x7F81817F, 0x817F7F7F, 0x81818181, 0x817F8181, 0x817F8181, 0x81817F81,
+0x817F7F81, 0x7F817F81, 0x8181817F, 0x7F818181, 0x7F817F81, 0x7F7F7F81, 0x8181817F, 0x7F818181,
+0x81818181, 0x817F8181, 0x7F817F81, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x81818181, 0x7F7F7F81,
+0x7F81817F, 0x7F7F7F81, 0x817F817F, 0x81817F7F, 0x817F817F, 0x7F81817F, 0x81817F81, 0x817F817F,
+0x81817F7F, 0x817F8181, 0x817F7F81, 0x81817F7F, 0x81817F7F, 0x7F7F817F, 0x7F817F7F, 0x7F7F8181,
+0x7F818181, 0x817F7F81, 0x7F7F7F7F, 0x817F8181, 0x81818181, 0x817F817F, 0x81818181, 0x7F7F7F7F,
+0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x817F7F7F, 0x7F818181, 0x81818181, 0x817F7F81,
+0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x81817F81, 0x7F818181, 0x7F7F8181, 0x7F818181, 0x81817F7F,
+0x7F817F81, 0x8181817F, 0x7F7F7F7F, 0x817F7F81, 0x817F7F81, 0x7F7F817F, 0x817F817F, 0x7F818181,
+0x817F7F81, 0x7F817F81, 0x817F8181, 0x81817F7F, 0x7F817F81, 0x817F7F81, 0x81817F81, 0x7F817F7F,
+0x81817F7F, 0x81818181, 0x817F7F81, 0x81818181, 0x81817F81, 0x817F7F7F, 0x81817F81, 0x7F81817F,
+0x7F7F8181, 0x817F7F81, 0x817F817F, 0x817F8181, 0x7F81817F, 0x7F7F7F81, 0x7F817F81, 0x7F81817F,
+0x8181817F, 0x7F7F817F, 0x817F817F, 0x81817F81, 0x81818181, 0x7F7F8181, 0x7F7F8181, 0x7F817F81,
+0x8181817F, 0x81818181, 0x817F817F, 0x81818181, 0x7F7F8181, 0x817F7F7F, 0x7F7F817F, 0x7F7F8181,
+0x7F7F7F7F, 0x817F7F81, 0x817F817F, 0x8181817F, 0x7F7F817F, 0x7F818181, 0x817F7F7F, 0x817F7F7F,
+0x7F818181, 0x81817F81, 0x7F818181, 0x7F7F7F7F, 0x81817F81, 0x7F81817F, 0x81817F7F, 0x817F7F7F,
+0x7F7F8181, 0x7F7F817F, 0x7F817F81, 0x817F817F, 0x817F8181, 0x7F817F81, 0x7F7F7F81, 0x7F7F8181,
+0x81817F7F, 0x817F7F7F, 0x817F8181, 0x7F81817F, 0x7F817F81, 0x81817F81, 0x81818181, 0x817F817F,
+0x7F7F8181, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x7F817F81, 0x7F7F817F, 0x817F7F7F, 0x7F817F7F,
+0x81817F81, 0x7F818181, 0x817F7F7F, 0x817F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x817F7F81, 0x7F81817F,
+0x817F7F81, 0x7F81817F, 0x817F7F81, 0x7F818181, 0x81817F81, 0x81817F7F, 0x817F7F81, 0x7F817F81,
+0x7F81817F, 0x817F7F81, 0x7F81817F, 0x817F817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x7F7F7F7F, 0x81817F7F, 0x817F817F, 0x817F7F7F, 0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x7F817F81,
+0x7F817F7F, 0x7F81817F, 0x7F7F817F, 0x7F7F8181, 0x7F7F817F, 0x8181817F, 0x7F81817F, 0x7F7F7F81,
+0x7F81817F, 0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F7F81, 0x817F8181, 0x817F7F81, 0x7F818181,
+0x7F7F7F7F, 0x81817F81, 0x7F7F817F, 0x81818181, 0x7F7F7F81, 0x7F818181, 0x817F7F81, 0x7F7F8181,
+0x81818181, 0x817F8181, 0x81817F7F, 0x7F7F7F7F, 0x7F7F817F, 0x7F81817F, 0x81817F7F, 0x817F7F7F,
+0x817F817F, 0x7F7F817F, 0x81817F81, 0x7F817F7F, 0x81817F7F, 0x7F7F7F7F, 0x7F817F7F, 0x81818181,
+0x81818181, 0x7F7F817F, 0x81818181, 0x7F7F8181, 0x7F7F7F81, 0x7F7F7F81, 0x81818181, 0x7F818181,
+0x7F817F7F, 0x817F8181, 0x81817F81, 0x7F818181, 0x817F7F7F, 0x81818181, 0x817F7F81, 0x7F7F817F,
+0x7F817F81, 0x81817F7F, 0x817F817F, 0x817F817F, 0x81817F7F, 0x81817F81, 0x7F7F8181, 0x7F7F7F7F,
+0x817F7F81, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x7F7F817F, 0x8181817F, 0x7F818181, 0x7F818181,
+0x817F8181, 0x7F817F7F, 0x81817F7F, 0x81817F81, 0x817F7F81, 0x81817F81, 0x7F818181, 0x7F7F8181,
+0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181, 0x7F7F7F7F, 0x817F8181, 0x817F8181,
+0x817F817F, 0x7F7F817F, 0x7F817F7F, 0x81817F81, 0x817F7F7F, 0x817F7F81, 0x8181817F, 0x81818181,
+0x7F7F8181, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181, 0x817F817F, 0x7F817F81, 0x7F817F81, 0x7F817F7F,
+0x817F817F, 0x817F7F81, 0x7F7F7F81, 0x81818181, 0x81818181, 0x817F7F7F, 0x817F8181, 0x7F7F8181,
+0x81817F81, 0x7F7F817F, 0x8181817F, 0x7F7F817F, 0x81818181, 0x7F81817F, 0x817F817F, 0x817F817F,
+0x7F7F817F, 0x7F81817F, 0x7F7F817F, 0x7F817F81, 0x8181817F, 0x81817F7F, 0x81818181, 0x7F81817F,
+0x7F818181, 0x7F817F7F, 0x7F817F81, 0x8181817F, 0x81817F81, 0x8181817F, 0x817F7F81, 0x7F817F7F,
+0x817F8181, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x817F8181, 0x7F817F81, 0x7F7F8181, 0x7F818181,
+0x7F7F7F81, 0x7F818181, 0x8181817F, 0x81817F7F, 0x7F818181, 0x7F817F81, 0x817F7F81, 0x7F7F7F7F,
+0x7F818181, 0x7F7F7F81, 0x81818181, 0x7F818181, 0x817F7F81, 0x7F7F7F81, 0x8181817F, 0x7F7F8181,
+0x7F818181, 0x817F8181, 0x7F818181, 0x8181817F, 0x81817F7F, 0x817F8181, 0x81818181, 0x7F7F8181,
+0x817F7F81, 0x81818181, 0x817F817F, 0x7F81817F, 0x8181817F, 0x817F817F, 0x7F7F817F, 0x7F7F7F7F,
+0x8181817F, 0x7F81817F, 0x81817F81, 0x7F81817F, 0x7F7F7F81, 0x817F7F81, 0x7F7F7F81, 0x817F7F81,
+0x817F8181, 0x7F817F81, 0x81817F7F, 0x7F7F817F, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x7F817F7F,
+0x817F7F81, 0x7F7F8181, 0x8181817F, 0x7F7F817F, 0x7F817F81, 0x7F7F8181, 0x817F817F, 0x7F817F7F,
+0x81818181, 0x7F7F7F81, 0x7F817F81, 0x7F7F8181, 0x8181817F, 0x817F7F7F, 0x7F817F81, 0x81818181,
+0x81818181, 0x7F7F817F, 0x7F81817F, 0x817F817F, 0x817F7F7F, 0x81818181, 0x817F8181, 0x7F7F8181,
+0x81818181, 0x817F7F81, 0x817F817F, 0x817F7F81, 0x7F7F7F81, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F7F,
+0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x817F817F, 0x7F81817F, 0x81817F81, 0x817F8181, 0x7F7F817F,
+0x8181817F, 0x817F7F81, 0x81817F81, 0x8181817F, 0x7F818181, 0x817F8181, 0x81818181, 0x7F817F81,
+0x817F8181, 0x81817F81, 0x7F81817F, 0x7F818181, 0x7F7F7F7F, 0x7F7F8181, 0x81817F81, 0x7F7F8181,
+0x8181817F, 0x817F7F81, 0x81817F81, 0x7F7F7F81, 0x7F7F7F81, 0x817F8181, 0x81818181, 0x7F81817F,
+0x7F7F8181, 0x817F8181, 0x817F7F7F, 0x81818181, 0x7F7F7F7F, 0x8181817F, 0x7F7F817F, 0x7F7F7F7F,
+0x7F7F7F81, 0x7F81817F, 0x7F817F81, 0x7F7F8181, 0x7F7F7F7F, 0x817F7F7F, 0x7F817F7F, 0x817F8181,
+0x7F7F7F81, 0x7F817F81, 0x817F8181, 0x817F817F, 0x817F817F, 0x7F817F7F, 0x8181817F, 0x817F7F81,
+0x81817F81, 0x7F817F81, 0x7F7F817F, 0x7F817F7F, 0x8181817F, 0x7F817F81, 0x7F7F817F, 0x81818181,
+0x7F81817F, 0x7F7F8181, 0x81817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F81, 0x817F8181, 0x817F817F,
+0x817F817F, 0x7F817F7F, 0x7F7F8181, 0x7F817F7F, 0x8181817F, 0x7F7F8181, 0x81818181, 0x7F817F81,
+0x7F7F7F81, 0x81817F7F, 0x817F817F, 0x81818181, 0x7F817F7F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81,
+0x7F7F8181, 0x81817F7F, 0x7F81817F, 0x81817F81, 0x7F7F8181, 0x817F8181, 0x817F817F, 0x817F7F7F,
+0x7F7F817F, 0x817F8181, 0x81817F81, 0x7F7F8181, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F81, 0x7F817F7F,
+0x7F7F7F7F, 0x7F81817F, 0x7F7F7F81, 0x81817F81, 0x7F7F7F81, 0x7F817F7F, 0x817F817F, 0x81817F7F,
+0x7F81817F, 0x81818181, 0x81817F81, 0x81817F7F, 0x7F7F7F81, 0x7F81817F, 0x7F7F7F81, 0x817F7F81,
+0x817F7F7F, 0x7F7F8181, 0x817F7F81, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F81817F, 0x7F818181,
+0x7F7F817F, 0x81818181, 0x7F7F7F7F, 0x8181817F, 0x7F7F7F7F, 0x817F817F, 0x7F81817F, 0x817F817F,
+0x7F7F8181, 0x7F7F8181, 0x81818181, 0x7F7F817F, 0x81817F7F, 0x7F817F81, 0x7F817F81, 0x81817F81,
+0x817F7F7F, 0x7F7F7F7F, 0x7F817F7F, 0x7F7F7F81, 0x817F8181, 0x817F7F81, 0x817F7F7F, 0x7F817F7F,
+0x81817F81, 0x817F817F, 0x817F8181, 0x7F7F7F7F, 0x81818181, 0x7F7F817F, 0x7F7F817F, 0x7F7F817F,
+0x817F8181, 0x817F8181, 0x81817F81, 0x7F7F8181, 0x8181817F, 0x817F8181, 0x7F7F7F7F, 0x817F8181,
+0x7F81817F, 0x7F7F7F81, 0x817F817F, 0x817F7F81, 0x7F817F7F, 0x7F817F81, 0x817F7F7F, 0x817F817F,
+0x7F7F8181, 0x7F817F81, 0x7F7F817F, 0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x7F817F81, 0x817F7F81,
+0x8181817F, 0x81818181, 0x7F818181, 0x817F7F7F, 0x817F7F81, 0x817F817F, 0x7F81817F, 0x8181817F,
+0x817F817F, 0x7F818181, 0x7F7F7F81, 0x8181817F, 0x7F817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F7F7F,
+0x7F7F817F, 0x7F7F8181, 0x7F817F81, 0x7F7F7F7F, 0x81817F81, 0x817F817F, 0x7F817F81, 0x7F7F817F,
+0x817F7F81, 0x817F817F, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F8181, 0x7F817F7F, 0x81818181,
+0x817F817F, 0x817F7F7F, 0x7F7F7F81, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x8181817F, 0x7F817F7F,
+0x7F7F817F, 0x7F7F8181, 0x8181817F, 0x7F817F81, 0x81817F81, 0x7F7F7F81, 0x817F817F, 0x817F7F81,
+0x7F7F7F81, 0x7F7F7F81, 0x7F817F7F, 0x817F7F81, 0x7F817F81, 0x817F8181, 0x81817F81, 0x81817F7F,
+0x8181817F, 0x81817F7F, 0x8181817F, 0x817F7F7F, 0x8181817F, 0x817F7F7F, 0x8181817F, 0x81817F81,
+0x7F818181, 0x81817F81, 0x7F7F8181, 0x7F81817F, 0x7F7F7F7F, 0x7F818181, 0x7F81817F, 0x817F8181,
+0x7F7F8181, 0x8181817F, 0x7F7F817F, 0x81818181, 0x81817F7F, 0x81817F81, 0x81818181, 0x8181817F,
+0x7F818181, 0x7F7F7F7F, 0x817F817F, 0x7F81817F, 0x817F817F, 0x817F8181, 0x7F81817F, 0x7F7F817F,
+0x817F7F81, 0x7F818181, 0x8181817F, 0x7F81817F, 0x8181817F, 0x81817F7F, 0x81817F81, 0x7F7F8181,
+0x817F817F, 0x7F7F8181, 0x7F818181, 0x817F8181, 0x7F7F7F81, 0x81817F7F, 0x817F7F81, 0x7F817F81,
+0x7F817F7F, 0x7F817F81, 0x81817F7F, 0x81817F7F, 0x817F817F, 0x81817F81, 0x7F7F8181, 0x7F818181,
+0x7F81817F, 0x7F7F8181, 0x7F7F817F, 0x817F8181, 0x817F7F7F, 0x7F817F81, 0x817F7F7F, 0x817F817F,
+0x81817F7F, 0x81817F7F, 0x7F81817F, 0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x817F8181, 0x7F818181,
+0x7F817F81, 0x817F7F81, 0x81818181, 0x7F818181, 0x8181817F, 0x7F7F8181, 0x81817F81, 0x7F817F81,
+0x8181817F, 0x817F817F, 0x817F8181, 0x7F7F7F81, 0x81817F81, 0x7F817F7F, 0x7F7F7F7F, 0x81818181,
+0x7F81817F, 0x7F81817F, 0x817F817F, 0x7F818181, 0x7F7F7F7F, 0x7F7F817F, 0x7F818181, 0x7F7F7F7F,
+0x7F817F7F, 0x7F817F81, 0x7F7F7F7F, 0x8181817F, 0x81817F81, 0x7F7F7F7F, 0x817F7F81, 0x817F8181,
+0x7F7F817F, 0x7F817F7F, 0x81817F7F, 0x7F7F8181, 0x81818181, 0x81817F81, 0x817F817F, 0x7F7F8181,
+0x817F8181, 0x817F817F, 0x7F818181, 0x81818181, 0x81817F7F, 0x81818181, 0x7F7F7F81, 0x7F7F8181,
+0x817F817F, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x8181817F, 0x7F7F8181, 0x7F7F817F, 0x7F818181,
+0x8181817F, 0x817F7F81, 0x7F818181, 0x7F7F8181, 0x7F7F7F7F, 0x817F817F, 0x7F817F7F, 0x817F7F81,
+0x7F7F7F7F, 0x7F7F7F81, 0x7F7F8181, 0x81817F7F, 0x81818181, 0x7F81817F, 0x7F817F81, 0x7F817F7F,
+0x817F7F81, 0x7F7F817F, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x7F817F81, 0x7F817F7F, 0x817F7F81,
+0x817F7F7F, 0x7F818181, 0x817F817F, 0x8181817F, 0x7F7F7F81, 0x817F7F81, 0x81817F81, 0x817F817F,
+0x7F7F7F81, 0x81818181, 0x81817F81, 0x7F7F8181, 0x81817F7F, 0x7F7F7F81, 0x7F7F817F, 0x7F81817F,
+0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x81817F81, 0x7F7F817F, 0x81817F81, 0x817F7F81, 0x7F81817F,
+0x817F817F, 0x81818181, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x8181817F, 0x81817F81, 0x7F818181,
+0x7F7F7F7F, 0x7F7F8181, 0x7F7F8181, 0x81817F7F, 0x817F7F81, 0x817F817F, 0x7F7F817F, 0x7F818181,
+0x7F817F81, 0x7F7F7F81, 0x7F817F81, 0x7F81817F, 0x817F817F, 0x7F81817F, 0x7F817F7F, 0x81817F81,
+0x7F7F8181, 0x81817F7F, 0x7F7F7F7F, 0x81817F81, 0x7F7F8181, 0x817F817F, 0x7F7F817F, 0x81817F81,
+0x7F7F7F81, 0x81817F81, 0x81817F81, 0x8181817F, 0x8181817F, 0x81817F81, 0x7F7F817F, 0x817F7F81,
+0x7F7F8181, 0x7F7F8181, 0x7F817F81, 0x7F81817F, 0x7F81817F, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F7F81,
+0x81817F81, 0x8181817F, 0x7F7F7F7F, 0x817F8181, 0x7F7F7F81, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F7F,
+0x81817F7F, 0x7F817F81, 0x7F81817F, 0x7F818181, 0x8181817F, 0x7F817F7F, 0x817F7F81, 0x817F8181,
+0x81818181, 0x817F8181, 0x7F7F7F7F, 0x7F7F7F7F, 0x81817F7F, 0x7F81817F, 0x7F818181, 0x7F81817F,
+0x7F7F7F7F, 0x81817F81, 0x81818181, 0x7F7F7F81, 0x7F81817F, 0x7F7F7F81, 0x8181817F, 0x7F817F81,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F8181, 0x817F817F, 0x7F7F8181, 0x817F7F7F, 0x7F7F8181,
+0x7F817F81, 0x7F7F817F, 0x81817F81, 0x7F81817F, 0x7F7F7F81, 0x7F7F817F, 0x817F7F7F, 0x8181817F,
+0x7F7F7F7F, 0x7F7F7F81, 0x7F818181, 0x81818181, 0x7F817F81, 0x8181817F, 0x81817F81, 0x7F7F8181,
+0x8181817F, 0x7F7F817F, 0x81817F81, 0x81818181, 0x817F817F, 0x7F817F81, 0x7F7F817F, 0x7F817F7F,
+0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x817F8181, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x7F81817F,
+0x7F7F8181, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x81818181, 0x7F817F7F, 0x8181817F, 0x7F817F7F,
+0x81818181, 0x7F7F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x7F817F81, 0x817F7F81, 0x7F817F81, 0x7F7F817F,
+0x817F7F7F, 0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F7F, 0x81817F81, 0x81817F81,
+0x817F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F81817F, 0x817F7F7F, 0x817F817F, 0x817F817F, 0x7F7F8181,
+0x7F7F7F7F, 0x7F818181, 0x7F7F8181, 0x7F7F8181, 0x817F7F7F, 0x7F818181, 0x8181817F, 0x7F7F8181,
+0x817F817F, 0x81817F81, 0x81817F81, 0x81817F81, 0x817F7F7F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81,
+0x817F7F81, 0x81818181, 0x8181817F, 0x817F8181, 0x7F818181, 0x817F7F7F, 0x7F7F7F7F, 0x817F8181,
+0x81817F81, 0x7F81817F, 0x7F7F817F, 0x81817F81, 0x7F7F7F7F, 0x817F8181, 0x81817F7F, 0x817F817F,
+0x81818181, 0x81817F81, 0x81818181, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F8181,
+0x81817F81, 0x7F7F7F7F, 0x7F7F8181, 0x8181817F, 0x817F7F7F, 0x81817F7F, 0x81817F81, 0x817F7F81,
+0x81818181, 0x7F81817F, 0x7F817F7F, 0x7F81817F, 0x817F8181, 0x7F7F8181, 0x7F818181, 0x817F7F81,
+0x7F7F8181, 0x817F817F, 0x817F7F81, 0x817F817F, 0x81817F81, 0x817F7F81, 0x7F817F7F, 0x817F817F,
+0x7F81817F, 0x81818181, 0x817F7F81, 0x7F818181, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F, 0x817F8181,
+0x7F817F81, 0x7F7F7F81, 0x817F7F81, 0x81817F7F, 0x817F7F81, 0x7F7F8181, 0x817F8181, 0x81817F7F,
+0x7F818181, 0x817F8181, 0x817F817F, 0x7F7F8181, 0x8181817F, 0x8181817F, 0x817F7F7F, 0x7F7F8181,
+0x8181817F, 0x817F8181, 0x817F7F81, 0x7F817F81, 0x7F818181, 0x7F81817F, 0x81818181, 0x817F7F7F,
+0x7F7F7F7F, 0x81818181, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x817F817F, 0x7F7F7F7F, 0x7F7F7F7F,
+0x81818181, 0x7F7F7F81, 0x81817F81, 0x817F8181, 0x7F817F7F, 0x81817F81, 0x8181817F, 0x7F7F7F81,
+0x7F818181, 0x7F7F817F, 0x7F7F7F81, 0x81817F7F, 0x81817F7F, 0x7F818181, 0x81818181, 0x817F8181,
+0x7F817F7F, 0x7F818181, 0x7F81817F, 0x7F7F7F7F, 0x817F8181, 0x817F8181, 0x81817F81, 0x817F817F,
+0x7F7F817F, 0x7F7F8181, 0x7F7F7F7F, 0x7F7F817F, 0x817F8181, 0x817F7F81, 0x817F7F7F, 0x7F7F8181,
+0x7F7F7F7F, 0x817F817F, 0x81817F7F, 0x7F7F817F, 0x81818181, 0x7F7F8181, 0x7F817F7F, 0x7F817F81,
+0x817F7F7F, 0x7F818181, 0x7F817F7F, 0x7F818181, 0x7F818181, 0x81817F7F, 0x8181817F, 0x817F7F81,
+0x8181817F, 0x817F7F81, 0x7F7F817F, 0x7F817F81, 0x817F7F81, 0x81817F81, 0x81817F81, 0x817F817F,
+0x817F7F7F, 0x7F818181, 0x7F817F7F, 0x8181817F, 0x7F7F7F7F, 0x817F7F81, 0x7F7F817F, 0x7F81817F,
+0x8181817F, 0x7F817F81, 0x7F7F817F, 0x817F8181, 0x817F817F, 0x7F818181, 0x817F7F7F, 0x7F7F8181,
+0x7F7F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F7F817F, 0x817F8181, 0x7F817F81, 0x8181817F,
+0x7F818181, 0x817F7F81, 0x7F7F7F7F, 0x8181817F, 0x817F7F81, 0x7F817F81, 0x81817F7F, 0x817F7F7F,
+0x81818181, 0x81818181, 0x7F817F81, 0x7F81817F, 0x7F7F8181, 0x81817F7F, 0x7F7F8181, 0x7F817F81,
+0x7F7F7F7F, 0x8181817F, 0x817F817F, 0x7F7F8181, 0x817F817F, 0x817F7F7F, 0x7F7F7F81, 0x81817F81,
+0x817F7F7F, 0x817F8181, 0x7F818181, 0x817F7F7F, 0x7F7F7F7F, 0x81818181, 0x7F818181, 0x7F7F7F81,
+0x7F7F7F7F, 0x817F817F, 0x7F7F8181, 0x81818181, 0x817F817F, 0x817F7F81, 0x817F7F7F, 0x817F8181,
+0x7F817F81, 0x7F818181, 0x7F7F817F, 0x7F81817F, 0x81818181, 0x817F7F81, 0x81817F7F, 0x7F7F7F81,
+0x7F7F817F, 0x7F818181, 0x817F8181, 0x817F7F81, 0x7F817F7F, 0x7F7F817F, 0x7F81817F, 0x81817F7F,
+0x7F818181, 0x7F7F7F81, 0x81817F7F, 0x81818181, 0x81817F7F, 0x817F8181, 0x81817F7F, 0x817F7F7F,
+0x7F7F817F, 0x7F7F8181, 0x81818181, 0x7F81817F, 0x7F7F7F7F, 0x7F817F81, 0x81817F7F, 0x817F7F7F,
+0x8181817F, 0x817F7F7F, 0x7F817F7F, 0x817F817F, 0x817F8181, 0x7F818181, 0x81817F7F, 0x7F7F8181,
+0x817F7F81, 0x8181817F, 0x817F8181, 0x7F817F81, 0x7F7F817F, 0x7F7F817F, 0x7F7F7F7F, 0x7F81817F,
+0x7F7F7F81, 0x7F81817F, 0x81818181, 0x7F817F7F, 0x817F8181, 0x81817F81, 0x7F818181, 0x7F817F81,
+0x7F817F81, 0x817F7F7F, 0x7F817F81, 0x7F7F8181, 0x817F817F, 0x817F8181, 0x8181817F, 0x81817F81,
+0x817F817F, 0x7F7F817F, 0x81817F7F, 0x7F817F81, 0x817F817F, 0x817F8181, 0x7F7F7F81, 0x817F8181,
+0x7F7F7F7F, 0x81817F7F, 0x7F817F81, 0x7F7F7F7F, 0x8181817F, 0x7F81817F, 0x817F7F7F, 0x81817F7F,
+0x817F7F81, 0x817F7F7F, 0x7F7F817F, 0x7F7F7F7F, 0x8181817F, 0x8181817F, 0x817F817F, 0x817F7F7F,
+0x817F7F81, 0x817F7F7F, 0x8181817F, 0x7F7F7F81, 0x7F817F7F, 0x7F817F81, 0x817F817F, 0x7F81817F,
+0x81818181, 0x7F817F81, 0x7F817F81, 0x817F7F81, 0x7F7F817F, 0x7F81817F, 0x7F7F8181, 0x7F817F7F,
+0x817F817F, 0x81818181, 0x7F7F8181, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F7F, 0x7F7F7F81, 0x7F817F7F,
+0x7F817F7F, 0x7F7F817F, 0x7F817F7F, 0x817F8181, 0x7F81817F, 0x7F81817F, 0x7F7F7F7F, 0x817F8181,
+0x81817F7F, 0x7F7F817F, 0x7F817F81, 0x817F817F, 0x817F8181, 0x817F8181, 0x7F817F81, 0x7F818181,
+0x7F7F7F7F, 0x7F81817F, 0x7F818181, 0x817F8181, 0x817F7F81, 0x7F81817F, 0x817F817F, 0x7F817F81,
+0x7F817F7F, 0x7F81817F, 0x817F817F, 0x81817F7F, 0x7F7F7F7F, 0x817F817F, 0x7F817F7F, 0x7F7F8181,
+0x81817F81, 0x7F7F7F7F, 0x81818181, 0x817F817F, 0x81818181, 0x7F817F7F, 0x81817F81, 0x7F7F7F7F,
+0x81818181, 0x7F81817F, 0x81818181, 0x7F7F7F7F, 0x7F7F8181, 0x817F7F7F, 0x7F817F7F, 0x817F7F7F,
+0x817F8181, 0x7F818181, 0x81818181, 0x817F7F7F, 0x81817F7F, 0x817F7F81, 0x7F81817F, 0x7F7F8181,
+0x81818181, 0x7F818181, 0x7F818181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x817F8181, 0x7F818181,
+0x81817F7F, 0x7F7F7F81, 0x817F7F7F, 0x817F817F, 0x7F7F8181, 0x817F8181, 0x81817F81, 0x817F817F,
+0x7F817F81, 0x7F7F8181, 0x817F817F, 0x7F81817F, 0x7F818181, 0x81817F7F, 0x7F7F8181, 0x7F7F817F,
+0x7F81817F, 0x81817F7F, 0x81818181, 0x7F818181, 0x7F817F7F, 0x7F7F817F, 0x817F7F7F, 0x81817F81,
+0x7F817F7F, 0x7F81817F, 0x817F7F7F, 0x7F7F817F, 0x7F81817F, 0x817F8181, 0x81818181, 0x81817F7F,
+0x817F8181, 0x7F817F7F, 0x7F817F7F, 0x8181817F, 0x81817F81, 0x7F7F7F81, 0x81817F81, 0x7F7F7F81,
+0x7F817F7F, 0x7F7F7F7F, 0x81818181, 0x7F81817F, 0x8181817F, 0x7F81817F, 0x817F7F7F, 0x817F817F,
+0x817F7F81, 0x7F818181, 0x817F817F, 0x7F7F7F81, 0x7F7F817F, 0x817F7F81, 0x81817F7F, 0x81818181,
+0x817F817F, 0x7F7F8181, 0x817F7F81, 0x8181817F, 0x81817F7F, 0x7F7F7F81, 0x7F7F8181, 0x7F7F817F,
+0x817F8181, 0x7F817F81, 0x7F7F7F7F, 0x7F818181, 0x7F7F7F81, 0x7F7F7F81, 0x7F81817F, 0x7F7F817F,
+0x7F7F7F81, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F81, 0x81817F7F, 0x7F817F7F, 0x8181817F, 0x7F7F8181,
+0x81817F81, 0x817F8181, 0x7F7F7F81, 0x81818181, 0x817F7F81, 0x8181817F, 0x817F8181, 0x81817F7F,
+0x817F7F7F, 0x7F818181, 0x81817F81, 0x7F81817F, 0x7F7F7F81, 0x8181817F, 0x7F7F817F, 0x8181817F,
+0x8181817F, 0x7F817F7F, 0x7F817F7F, 0x8181817F, 0x817F7F7F, 0x817F7F81, 0x7F817F7F, 0x7F818181,
+0x7F7F7F81, 0x817F7F81, 0x81817F81, 0x817F817F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F7F, 0x817F817F,
+0x7F7F7F81, 0x7F7F817F, 0x7F817F81, 0x7F81817F, 0x7F817F81, 0x7F817F81, 0x7F7F7F7F, 0x7F818181,
+0x817F817F, 0x817F7F7F, 0x817F8181, 0x7F818181, 0x7F7F7F81, 0x817F7F7F, 0x7F81817F, 0x817F8181,
+0x817F7F81, 0x7F7F7F81, 0x8181817F, 0x817F817F, 0x8181817F, 0x817F7F7F, 0x7F81817F, 0x81817F7F,
+0x7F7F817F, 0x817F8181, 0x7F7F7F81, 0x81817F81, 0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F81,
+0x7F7F8181, 0x817F817F, 0x7F7F7F81, 0x7F818181, 0x81818181, 0x7F7F7F81, 0x7F817F7F, 0x817F8181,
+0x817F817F, 0x7F7F8181, 0x7F817F7F, 0x7F7F7F81, 0x7F7F817F, 0x8181817F, 0x7F817F81, 0x7F81817F,
+0x7F817F81, 0x7F818181, 0x81818181, 0x8181817F, 0x7F7F7F81, 0x817F7F7F, 0x81818181, 0x7F7F8181,
+0x81817F7F, 0x7F7F817F, 0x7F7F7F81, 0x817F8181, 0x7F818181, 0x7F7F817F, 0x817F7F7F, 0x7F7F7F7F,
+0x817F7F81, 0x817F7F7F, 0x817F817F, 0x7F7F8181, 0x81817F7F, 0x81818181, 0x817F7F81, 0x7F81817F,
+0x817F7F81, 0x7F817F7F, 0x7F817F7F, 0x7F7F817F, 0x817F817F, 0x817F7F81, 0x7F7F7F81, 0x81818181,
+0x81817F81, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x8181817F,
+0x81817F7F, 0x7F81817F, 0x7F7F817F, 0x817F7F81, 0x7F81817F, 0x817F8181, 0x7F7F7F81, 0x7F817F81,
+0x7F7F7F81, 0x81817F81, 0x7F818181, 0x81817F7F, 0x817F817F, 0x817F7F81, 0x7F7F817F, 0x8181817F,
+0x817F817F, 0x817F817F, 0x817F817F, 0x7F817F7F, 0x81818181, 0x7F7F8181, 0x7F817F81, 0x7F7F8181,
+0x81817F81, 0x8181817F, 0x7F7F7F7F, 0x7F817F7F, 0x817F7F81, 0x817F8181, 0x7F7F7F7F, 0x7F7F8181,
+0x7F7F817F, 0x7F818181, 0x7F817F81, 0x81817F7F, 0x817F817F, 0x7F817F7F, 0x817F7F7F, 0x81817F81,
+0x7F817F81, 0x817F7F7F, 0x7F81817F, 0x7F7F7F7F, 0x7F7F7F7F, 0x7F817F81, 0x81817F7F, 0x81817F81,
+0x7F817F7F, 0x7F7F7F7F, 0x7F818181, 0x7F817F7F, 0x81817F81, 0x7F7F817F, 0x817F7F7F, 0x817F8181,
+0x7F817F7F, 0x81817F7F, 0x817F8181, 0x817F817F, 0x817F8181, 0x7F7F8181, 0x7F817F7F, 0x81817F7F,
+0x7F7F817F, 0x817F7F7F, 0x7F817F81, 0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x7F818181, 0x7F817F81,
+0x7F81817F, 0x81817F81, 0x81817F81, 0x7F7F7F81, 0x81817F7F, 0x7F7F8181, 0x817F7F81, 0x81817F81,
+0x7F817F7F, 0x7F7F817F, 0x81817F7F, 0x7F7F7F81, 0x817F817F, 0x7F7F7F7F, 0x7F81817F, 0x7F7F8181,
+0x817F817F, 0x817F8181, 0x7F7F7F81, 0x81817F7F, 0x817F8181, 0x7F7F8181, 0x7F7F817F, 0x817F7F7F,
+0x7F817F81, 0x817F817F, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x81817F7F, 0x7F817F7F, 0x7F817F7F,
+0x81817F7F, 0x7F818181, 0x817F8181, 0x7F7F7F7F, 0x8181817F, 0x7F817F81, 0x8181817F, 0x81817F81,
+0x8181817F, 0x7F817F7F, 0x817F817F, 0x817F7F81, 0x81818181, 0x7F817F81, 0x7F81817F, 0x7F817F81,
+0x817F7F81, 0x7F817F7F, 0x7F81817F, 0x817F8181, 0x817F817F, 0x7F7F7F7F, 0x81817F7F, 0x7F818181,
+0x817F7F81, 0x7F7F8181, 0x817F8181, 0x8181817F, 0x81818181, 0x7F818181, 0x7F7F7F7F, 0x7F7F817F,
+0x7F818181, 0x81818181, 0x817F7F7F, 0x7F818181, 0x7F7F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F818181,
+0x817F817F, 0x7F817F7F, 0x8181817F, 0x7F7F8181, 0x7F817F81, 0x817F7F7F, 0x8181817F, 0x81817F81,
+0x7F81817F, 0x7F817F81, 0x81817F81, 0x81817F81, 0x81818181, 0x81818181, 0x81817F7F, 0x7F817F81,
+0x7F7F7F81, 0x817F817F, 0x81817F7F, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x7F81817F,
+0x8181817F, 0x81817F81, 0x7F81817F, 0x81817F81, 0x81817F7F, 0x817F7F7F, 0x8181817F, 0x7F7F817F,
+0x81818181, 0x7F81817F, 0x81817F7F, 0x7F7F7F7F, 0x817F8181, 0x81817F7F, 0x817F7F7F, 0x817F7F7F,
+0x7F817F7F, 0x7F7F7F81, 0x7F818181, 0x817F817F, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81, 0x7F7F817F,
+0x817F7F7F, 0x817F8181, 0x7F817F7F, 0x7F81817F, 0x7F7F817F, 0x81817F7F, 0x81817F81, 0x7F81817F,
+0x7F7F817F, 0x7F7F7F7F, 0x7F81817F, 0x817F817F, 0x7F7F7F7F, 0x8181817F, 0x7F7F8181, 0x7F7F8181,
+0x817F7F81, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F, 0x817F7F7F, 0x7F81817F, 0x817F7F81, 0x817F7F7F,
+0x81817F7F, 0x7F7F817F, 0x817F817F, 0x7F81817F, 0x7F81817F, 0x817F8181, 0x7F7F817F, 0x81817F81,
+0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x817F8181, 0x817F817F, 0x81817F7F, 0x7F7F8181, 0x817F7F81,
+0x7F7F7F81, 0x817F7F7F, 0x81817F81, 0x817F7F81, 0x81817F81, 0x81817F81, 0x7F7F7F7F, 0x7F7F8181,
+0x817F7F7F, 0x81818181, 0x7F818181, 0x7F7F817F, 0x817F8181, 0x7F7F7F81, 0x7F818181, 0x7F7F7F81,
+0x7F7F7F81, 0x7F817F81, 0x7F7F817F, 0x7F7F7F7F, 0x8181817F, 0x81817F7F, 0x8181817F, 0x817F817F,
+0x7F817F7F, 0x817F8181, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F817F, 0x81818181, 0x7F81817F, 0x7F7F7F81,
+0x817F7F81, 0x7F818181, 0x7F81817F, 0x7F7F817F, 0x817F7F81, 0x7F817F7F, 0x817F7F81, 0x7F817F81,
+0x81817F7F, 0x817F7F81, 0x7F7F7F7F, 0x7F7F8181, 0x7F7F8181, 0x81818181, 0x81818181, 0x7F817F7F,
+0x7F817F81, 0x7F818181, 0x7F7F817F, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F, 0x81818181, 0x7F81817F,
+0x81817F7F, 0x7F81817F, 0x7F7F7F81, 0x7F81817F, 0x81817F7F, 0x7F81817F, 0x7F817F7F, 0x817F7F81,
+0x81818181, 0x81817F81, 0x817F8181, 0x8181817F, 0x817F817F, 0x81817F81, 0x7F81817F, 0x7F817F81,
+0x817F817F, 0x7F81817F, 0x81817F81, 0x7F817F7F, 0x7F7F817F, 0x7F7F817F, 0x817F817F, 0x7F7F7F7F,
+0x7F817F7F, 0x7F7F7F81, 0x7F7F8181, 0x7F7F7F7F, 0x7F817F81, 0x7F818181, 0x81817F7F, 0x817F817F,
+0x7F81817F, 0x81817F7F, 0x7F818181, 0x81817F7F, 0x817F7F7F, 0x7F817F7F, 0x7F7F7F81, 0x7F7F8181,
+0x7F81817F, 0x817F8181, 0x81818181, 0x7F818181, 0x7F817F81, 0x7F817F7F, 0x7F818181, 0x7F7F7F7F,
+0x7F7F817F, 0x817F7F81, 0x81817F81, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x817F7F81, 0x7F818181,
+0x7F7F817F, 0x817F817F, 0x7F7F8181, 0x81818181, 0x817F8181, 0x817F7F7F, 0x7F817F7F, 0x7F818181,
+0x7F7F7F7F, 0x81817F81, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F81, 0x817F7F81, 0x817F817F, 0x7F7F817F,
+0x817F817F, 0x7F7F817F, 0x817F817F, 0x81817F7F, 0x7F817F7F, 0x817F7F81, 0x7F7F817F, 0x7F818181,
+0x7F817F7F, 0x7F818181, 0x7F7F7F7F, 0x81818181, 0x8181817F, 0x81817F7F, 0x7F7F7F81, 0x81817F7F,
+0x7F817F7F, 0x8181817F, 0x817F8181, 0x7F7F7F7F, 0x817F7F81, 0x7F817F81, 0x7F817F7F, 0x8181817F,
+0x817F7F7F, 0x81818181, 0x817F7F81, 0x7F817F7F, 0x817F817F, 0x817F7F7F, 0x8181817F, 0x7F7F7F7F,
+0x7F817F81, 0x7F7F8181, 0x817F7F7F, 0x817F7F81, 0x7F818181, 0x7F817F7F, 0x7F7F8181, 0x7F7F817F,
+0x817F7F81, 0x81817F81, 0x7F7F7F7F, 0x7F817F81, 0x817F817F, 0x7F7F817F, 0x7F7F7F81, 0x81817F81,
+0x81818181, 0x817F817F, 0x817F7F81, 0x817F8181, 0x8181817F, 0x7F818181, 0x817F7F81, 0x7F7F817F,
+0x7F7F817F, 0x8181817F, 0x817F7F7F, 0x7F7F7F81, 0x81817F81, 0x7F81817F, 0x7F817F7F, 0x7F7F7F81,
+0x81817F7F, 0x7F7F817F, 0x7F817F7F, 0x7F7F817F, 0x7F818181, 0x81817F7F, 0x7F7F8181, 0x7F7F817F,
+0x7F817F7F, 0x7F7F7F81, 0x8181817F, 0x7F7F7F7F, 0x7F817F7F, 0x7F817F7F, 0x81818181, 0x817F7F81,
+0x817F7F7F, 0x817F7F7F, 0x817F7F81, 0x817F817F, 0x7F7F817F, 0x7F7F7F81, 0x81817F7F, 0x817F8181,
+0x817F7F81, 0x817F817F, 0x817F7F7F, 0x817F7F7F, 0x7F817F81, 0x7F7F817F, 0x817F8181, 0x817F817F,
+0x81817F81, 0x817F8181, 0x7F818181, 0x817F7F7F, 0x81817F7F, 0x7F818181, 0x7F817F81, 0x7F7F7F7F,
+0x817F7F7F, 0x81818181, 0x7F7F817F, 0x7F7F817F, 0x7F81817F, 0x817F7F7F, 0x817F8181, 0x8181817F,
+0x7F7F7F7F, 0x7F817F7F, 0x8181817F, 0x817F817F, 0x7F817F7F, 0x81818181, 0x7F7F817F, 0x7F7F7F7F,
+0x7F818181, 0x81818181, 0x7F7F7F81, 0x81817F81, 0x81817F81, 0x7F81817F, 0x817F817F, 0x7F817F81,
+0x81817F7F, 0x817F817F, 0x81817F81, 0x8181817F, 0x817F817F, 0x817F817F, 0x817F817F, 0x817F817F,
+0x81817F7F, 0x81818181, 0x7F81817F, 0x7F817F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F817F, 0x817F7F81,
+0x7F818181, 0x817F7F81, 0x81817F7F, 0x817F817F, 0x81817F7F, 0x8181817F, 0x817F7F81, 0x7F7F7F81,
+0x81817F81, 0x7F7F7F81, 0x81818181, 0x817F7F7F, 0x81817F7F, 0x7F817F7F, 0x7F818181, 0x81817F7F,
+0x7F817F7F, 0x7F7F7F81, 0x81817F7F, 0x7F7F8181, 0x817F8181, 0x7F7F7F81, 0x7F7F817F, 0x7F7F7F81,
+0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x7F818181, 0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x817F7F7F,
+0x817F817F, 0x81817F7F, 0x7F817F81, 0x7F817F81, 0x81817F81, 0x7F7F7F81, 0x7F817F81, 0x81817F81,
+0x7F7F8181, 0x7F818181, 0x7F7F8181, 0x81817F7F, 0x81818181, 0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F7F,
+0x7F81817F, 0x7F817F7F, 0x817F7F7F, 0x7F817F81, 0x7F817F7F, 0x817F7F81, 0x81817F81, 0x7F7F817F,
+0x7F817F7F, 0x8181817F, 0x7F7F817F, 0x81818181, 0x81817F7F, 0x7F7F817F, 0x7F7F7F81, 0x817F7F81,
+0x7F81817F, 0x7F7F8181, 0x7F818181, 0x7F817F81, 0x817F8181, 0x7F818181, 0x817F817F, 0x81818181,
+0x7F7F7F81, 0x7F81817F, 0x7F817F7F, 0x81818181, 0x817F8181, 0x7F817F7F, 0x7F818181, 0x7F81817F,
+0x817F8181, 0x7F7F8181, 0x7F7F8181, 0x8181817F, 0x7F7F7F81, 0x7F7F7F81, 0x817F7F81, 0x817F7F81,
+0x81817F7F, 0x7F817F7F, 0x817F7F7F, 0x7F7F817F, 0x817F7F7F, 0x7F817F81, 0x7F7F7F7F, 0x817F817F,
+0x81817F81, 0x7F7F8181, 0x7F81817F, 0x8181817F, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x817F7F7F,
+0x7F818181, 0x81818181, 0x817F7F81, 0x7F818181, 0x7F817F81, 0x7F7F817F, 0x7F818181, 0x81818181,
+0x8181817F, 0x817F7F81, 0x817F8181, 0x817F8181, 0x7F817F81, 0x7F817F81, 0x7F7F817F, 0x7F7F7F81,
+0x81818181, 0x81817F7F, 0x81817F7F, 0x81817F81, 0x7F81817F, 0x81817F7F, 0x81817F7F, 0x81817F7F,
+0x81817F81, 0x7F7F817F, 0x817F817F, 0x8181817F, 0x7F81817F, 0x81817F81, 0x7F817F81, 0x817F817F,
+0x817F7F81, 0x81818181, 0x7F817F81, 0x81817F81, 0x817F817F, 0x81817F7F, 0x7F817F81, 0x7F817F7F,
+0x7F7F7F7F, 0x7F817F81, 0x81817F7F, 0x7F7F817F, 0x7F7F8181, 0x7F7F7F81, 0x8181817F, 0x81818181,
+0x81817F7F, 0x7F817F7F, 0x81817F81, 0x817F7F7F, 0x8181817F, 0x81817F7F, 0x7F817F81, 0x81817F81,
+0x7F7F8181, 0x7F7F8181, 0x81817F81, 0x7F81817F, 0x817F8181, 0x81818181, 0x81818181, 0x817F7F7F,
+0x817F8181, 0x7F817F81, 0x7F817F7F, 0x7F818181, 0x81818181, 0x7F7F7F7F, 0x7F7F8181, 0x817F817F,
+0x7F7F8181, 0x817F8181, 0x7F7F7F81, 0x7F817F7F, 0x7F81817F, 0x8181817F, 0x7F7F817F, 0x7F817F7F,
+0x81817F7F, 0x817F817F, 0x7F7F7F81, 0x817F8181, 0x7F81817F, 0x7F7F817F, 0x81818181, 0x7F81817F,
+0x7F817F81, 0x7F7F7F7F, 0x7F7F7F81, 0x7F7F7F81, 0x7F817F81, 0x81817F81, 0x81817F81, 0x7F7F817F,
+0x7F7F7F81, 0x817F817F, 0x81817F81, 0x8181817F, 0x7F817F81, 0x8181817F, 0x817F7F81, 0x81817F81,
+0x7F7F817F, 0x817F7F7F, 0x81817F7F, 0x81817F7F, 0x7F7F8181, 0x7F7F7F7F, 0x7F81817F, 0x8181817F,
+0x81817F7F, 0x81817F7F, 0x7F817F7F, 0x817F8181, 0x7F81817F, 0x817F7F7F, 0x7F817F7F, 0x7F817F7F,
+0x817F7F81, 0x7F7F7F7F, 0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x7F818181, 0x817F8181, 0x81817F7F,
+0x7F81817F, 0x7F817F81, 0x7F81817F, 0x81818181, 0x7F817F81, 0x817F817F, 0x7F817F81, 0x7F817F81,
+0x7F7F8181, 0x817F8181, 0x817F8181, 0x7F7F7F81, 0x7F818181, 0x7F7F8181, 0x81817F7F, 0x8181817F,
+0x7F7F817F, 0x7F7F7F7F, 0x7F7F7F81, 0x817F7F7F, 0x7F7F7F81, 0x7F818181, 0x817F817F, 0x817F7F7F,
+0x817F7F7F, 0x7F7F8181, 0x81817F7F, 0x7F7F7F7F, 0x817F7F81, 0x7F7F7F7F, 0x8181817F, 0x81817F7F,
+0x7F81817F, 0x7F817F7F, 0x817F7F81, 0x7F818181, 0x81817F7F, 0x7F817F81, 0x81817F81, 0x81817F7F,
+0x817F8181, 0x7F7F817F, 0x7F817F7F, 0x7F7F7F7F, 0x7F7F817F, 0x7F817F7F, 0x7F817F7F, 0x7F7F817F,
+0x817F7F7F, 0x7F81817F, 0x7F818181, 0x7F817F7F, 0x7F7F7F81, 0x7F817F81, 0x817F8181, 0x7F7F7F81,
+0x7F818181, 0x7F817F81, 0x817F8181, 0x7F818181, 0x817F817F, 0x7F817F7F, 0x817F7F81, 0x8181817F,
+0x817F817F, 0x7F7F7F7F, 0x7F817F7F, 0x81818181, 0x7F817F81, 0x7F817F7F, 0x81817F81, 0x7F7F7F81,
+0x7F7F8181, 0x81817F81, 0x7F817F7F, 0x817F7F7F, 0x81817F81, 0x7F817F7F, 0x81817F81, 0x81818181,
+0x7F817F81, 0x7F7F7F7F, 0x817F817F, 0x8181817F, 0x7F7F817F, 0x817F8181, 0x817F8181, 0x81817F81,
+0x7F7F7F7F, 0x817F8181, 0x817F7F81, 0x7F817F81, 0x817F8181, 0x81817F7F, 0x7F7F7F7F, 0x7F817F7F,
+0x7F7F7F7F, 0x7F7F7F7F, 0x817F7F7F, 0x81818181, 0x81817F7F, 0x817F7F7F, 0x7F7F7F81, 0x7F7F8181,
+0x7F7F7F81, 0x7F7F8181, 0x8181817F, 0x7F7F817F, 0x817F7F81, 0x7F817F7F, 0x817F7F7F, 0x817F7F7F,
+0x7F7F817F, 0x7F81817F, 0x817F817F, 0x7F7F817F, 0x817F817F, 0x7F7F7F7F, 0x81817F81, 0x817F7F81,
+0x8181817F, 0x81817F81, 0x817F7F7F, 0x7F818181, 0x817F7F81, 0x7F7F8181, 0x7F7F817F, 0x7F81817F,
+0x7F817F81, 0x7F81817F, 0x81818181, 0x817F7F81, 0x7F818181, 0x81818181, 0x81817F7F, 0x7F817F81,
+0x7F818181, 0x7F7F7F81, 0x7F817F81, 0x81817F81, 0x817F8181, 0x817F817F, 0x8181817F, 0x7F7F8181,
+0x81818181, 0x817F817F, 0x7F818181, 0x817F817F, 0x7F7F817F, 0x817F7F81, 0x817F8181, 0x7F7F7F81,
+0x7F7F7F7F, 0x7F817F81, 0x81817F81, 0x81817F7F, 0x7F817F7F, 0x81818181, 0x817F7F7F, 0x7F818181,
+0x817F8181, 0x7F7F7F81, 0x817F7F81, 0x81817F81, 0x7F7F7F81, 0x8181817F, 0x817F7F7F, 0x7F7F7F81,
+0x7F81817F, 0x7F818181, 0x817F7F81, 0x7F81817F, 0x817F8181, 0x817F8181, 0x7F81817F, 0x817F8181,
+0x7F7F7F81, 0x81818181, 0x7F7F817F, 0x81817F81, 0x81817F81, 0x817F8181, 0x7F7F8181, 0x817F7F81,
+0x817F8181, 0x817F7F81, 0x7F7F8181, 0x7F7F8181, 0x7F818181, 0x81817F81, 0x7F7F8181, 0x7F818181,
+0x7F7F817F, 0x7F81817F, 0x817F7F7F, 0x81817F7F, 0x7F7F7F81, 0x7F7F7F81, 0x7F7F7F7F, 0x817F8181,
+0x7F817F7F, 0x7F7F7F7F
+
+output0 =
+0x88CCED56, 0x1C072C76, 0xD4D23B69, 0x78C979BF, 0x60764BE3, 0x4470E86B, 0x20A46F84, 0xA0211B5C,
+0xE1952001, 0xB77912DE, 0x52E8BA16, 0xE5BE8445, 0x95093ACF, 0xA8BE03D2, 0x49DBB5AB, 0xC3946403,
+0x4DD44236, 0xC2833E65, 0x7288C53B, 0xD64FB75E, 0x7438C1EC, 0x71070BEC, 0xA40F8094, 0xABF43E46,
+0x564487F5, 0x8435AC89, 0x2D98A4C3, 0x07CD13F4, 0xB44CEEA6, 0x2E00DD83, 0x12EF45EB, 0x01A047B8,
+0xBC563FD5, 0xCA5C1136, 0x7AB9F2C8, 0xD62C59A9, 0x913DF674, 0xC900322A, 0xCF54042E, 0x6CAADB1E,
+0x8077B98C, 0xBCB51468, 0x58339E5E, 0x1D176854, 0xF9E2D74A, 0x2994B28A, 0xD0E46263, 0xCD8A0FDB,
+0x0119B915, 0x1E5433C9, 0xEA298A7D, 0x9EB4FC8D, 0xEF93B537, 0x6D441397, 0x6A4C8DB3, 0xB8E4AFE9,
+0x1520BC1C, 0x8669961B, 0x5D484802, 0xC2793340, 0xB5FE7945, 0x43AC7CE2, 0xB74B70C1, 0xFCF56F87,
+0x3E146A49, 0x0391D092, 0x672D2427, 0xDC91BB53, 0xEB24AC1F, 0xCE0D8E63, 0xF12F7ED8, 0xB3192024,
+0x0697AE9C, 0x3415F178, 0xD8410FFC, 0xE34734DE, 0x6C6E6BF1, 0xDCD211C3, 0xBF6B0B87, 0xA1624F47,
+0x3524BC4D, 0x4B4A1891, 0x8691223C, 0x12EB2DA4, 0x0B51F616, 0x31276F0E, 0x86CB4D17, 0x15CA0F9B,
+0xEB989F98, 0x1141D335, 0x442C699F, 0x82E9758B, 0x267E6D4D, 0x71BAC54A, 0x2FBCBD52, 0xA0966795,
+0xEB08B437, 0x1A9899A0, 0x26484B82, 0x3AEE43A8, 0xC409BE45, 0xCF8C6EC9, 0x098DE63F, 0xC3BEA60B,
+0xCB7A5B6A, 0xCBF2A44B, 0x31E9FA4C, 0x34FD7E88, 0xA3C5AF89, 0xF13C8E2B, 0xC01C79FA, 0x622B9FD8,
+0x692D4C4F, 0x712BC24C, 0x16FBD6C3, 0x7B1BBC38, 0x63F1E328, 0x6F4B
+
+basegraph=
+2
+
+z_c=
+384
+
+n_cb=
+19200
+
+q_m=
+2
+
+n_filler=
+56
+
+e =
+36936
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+iter_max =
+20
+
+expected_iter_count =
+3
+
+op_flags =
+RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE, RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v11835.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v11835.data
new file mode 100644
index 000000000..e27ff6ecc
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v11835.data
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_LDPC_ENC
+
+input0 =
+0x44FB08C0, 0x661CCC
+
+output0 =
+0x1BACEE95, 0x613ECD04, 0xC0
+
+basegraph=
+2
+
+z_c=
+10
+
+n_cb=
+500
+
+q_m=
+6
+
+n_filler=
+44
+
+e=
+66
+
+rv_index=
+0
+
+code_block_mode=
+1
+
+op_flags=
+RTE_BBDEV_LDPC_RATE_MATCH
+
+expected_status=
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v2342.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v2342.data
new file mode 100644
index 000000000..619b29be5
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v2342.data
@@ -0,0 +1,151 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+# Origin : FEC5g_DL_1/2342
+
+op_type =
+RTE_BBDEV_OP_LDPC_ENC
+
+input0 =
+0x02524C20, 0xB9B1FEA2, 0xC1BAB7E5, 0xEF5714CB, 0x7DE6A64D, 0xA05F9DC9, 0x0747D1E3, 0x3B20BC86,
+0x6FCBDB0F, 0xF2FB7A23, 0x79D5E062, 0x5BF4E7C3, 0xD4A68A37, 0x07B4A6AD, 0x37E911F9, 0x7FE7B30A,
+0xBBC284A2, 0xD38D6136, 0x25FAB76B, 0xBEBBF534, 0x9A88F9DB, 0xE37FD52D, 0x691DD493, 0xED2F738C,
+0x89A96EA0, 0xD981246A, 0x17CC820E, 0x07E3B463, 0xC9FC2590, 0x7475A33C, 0xA5151BB4, 0x1F7E759E,
+0x9554F964, 0xD0FA01F4, 0xD31774D2, 0xEB73A9F6, 0x8C9FBCB1, 0xF83010FB, 0x1909E09F, 0xC46023EB,
+0x02AEDC62, 0xC6352CC7, 0x674BDC6D, 0xE17CD747, 0x4E25B0B3, 0x4BFF6B17, 0x12C9AAA3, 0xC2BC91CD,
+0x44BE23A2, 0x8A72A157, 0x6E0DAD1F, 0x6CA69A09, 0xB55B582E, 0x01818B31, 0x5CA5CAB6, 0x1917AB24,
+0x38F98BCD, 0x01917487, 0x05906FDD, 0x760AFCBA, 0x19671085, 0x64E3546E, 0xEC10F922, 0x3CF286CA,
+0x68E273EA, 0xF1001325, 0x5DCB3B49, 0xE9547370, 0x65D26AE6, 0xF621256C, 0x25D6D99C, 0x7862EBA0,
+0x43365DB0, 0x4DBF06C5, 0x92FCAA02, 0xB0FD58FA, 0x910E80A6, 0x93D24A67, 0x6E39B144, 0x3D46D6F6,
+0xEDC55081, 0x33CD70C7, 0xC74B6E8E, 0x91AA27B9, 0x55B3542D, 0xEBF8046A, 0xB9ABDB94, 0x97FC38A8,
+0xD5837B4D, 0x764B1809, 0xFBE2096A, 0xC23887AC, 0x2A45029B, 0xCBB7DF70, 0x674654E1, 0x0C6A06BD,
+0xB3E8853E, 0x03FCC4CE, 0x26806F2E, 0x2CEB35B0, 0x10538B03, 0x94B059B8, 0xA95E7FFA, 0x48AD3D0A,
+0xEB9091E1, 0x972E31EF, 0x5EBC6F8F, 0x947FF108, 0xCB3123FA, 0xFEE1D939, 0xF3DC5C49, 0xA92927AE,
+0xF49BB8D0, 0xAA59F730, 0x4A66D1CD, 0x030E1ADF, 0x238D5B19, 0x96F861F1, 0x915424E4, 0x9127880C,
+0x8E779839, 0x87375FCE, 0x61FB3D79, 0x96B1EE83, 0x47BF6667, 0x19E7D408, 0x7E91137F, 0x0E4AD8E8,
+0xDABD2E45, 0x9B60873F, 0xD0294A65, 0x2A38A862, 0x59DD046D, 0x9832BB79, 0xA5870DB6, 0xB3F1CC48,
+0x7E9A8132, 0xEEA2E4BC, 0xF23ED87B, 0x550E011F, 0x9620E0C0, 0xE7CF0834, 0xDEE69623, 0x6184D512,
+0xD3D55728, 0xFA7711D4, 0x9C77B0F9, 0x8A26462B, 0xB3F5C8D5, 0x1123246D, 0x78F36272, 0x940EE0F9,
+0x757BF240, 0x7EE2B6D0, 0xD40FD5A1, 0xAB4205CA, 0x96E6B758, 0xAC5F4294, 0xC9268C66, 0xB48DC535,
+0x3CF6ED4C, 0xF187EFED, 0x7A09B08D, 0x8709EFCE, 0x267B2468, 0x0015D770, 0xDF1B90BF, 0xA03DAD85,
+0x2633012E, 0xE5437125, 0x58B79AFF, 0xB929C532, 0x6D890DC9, 0x89A59AD2, 0x2BB99316, 0x41B5B0EB,
+0x7304B295, 0xB37F6708, 0x2F84A68E, 0x3637D79A, 0xDD36687B, 0x904BF7B6, 0x6A2CF453, 0x733DED54,
+0x5DF48BAA, 0xC3FCC99F, 0x8E3BE1DB, 0x61D9CF2D, 0xB7DC202B, 0xA959FF95, 0x860D0F14, 0x4008C478,
+0xD9325A51, 0x27A29D4C, 0x308FE6D4, 0x7A1AA889, 0x5BD38393, 0xCBFA5D
+
+output0 =
+0xADE67AA9, 0x1CB4EBDD, 0x74E76684, 0xE3941FC7, 0x48DAC304, 0x1E2C198D, 0xFE88B908, 0xEC21A3DE,
+0xBF314AB7, 0x634E3DCB, 0x0DA84E23, 0x58B1B22B, 0x02B837A0, 0x8B04BF38, 0xFB8DB526, 0x1BFF82E9,
+0x4226C4D0, 0xF7A9950E, 0x6DA4D0B2, 0x38E15395, 0x94C1A379, 0x243ED666, 0x3E7255B3, 0x7DB378DB,
+0xA3CE1377, 0xE0137291, 0x42DB50AC, 0xEB2D0A13, 0xCA55944A, 0x223DF8E0, 0xB800D1CF, 0xAA2E7577,
+0x50153EC5, 0x5E3C8557, 0x63DDEC8F, 0x49A256F8, 0x41ABFD56, 0xEB76A4D7, 0x4F4E9C7C, 0x3508DA39,
+0x530F9DA0, 0xFFD20E32, 0x395F7963, 0x1C48B3F7, 0xD3BC29C7, 0x4D6ED90F, 0xC1C9EF58, 0x9B9D4A13,
+0x417BF36E, 0x1BB5FDD8, 0x72793F28, 0x2F297FA5, 0x204AA988, 0x28317636, 0x87878EC8, 0x33024F9D,
+0xE651388E, 0x560ACA6E, 0xEC3D0B64, 0xCB515AAE, 0xE42B9ECD, 0x2AE2B0D1, 0xCD659A28, 0x8BD5E4D8,
+0x0D618DD6, 0x14CF8DB1, 0xE9F82BB6, 0x558C50A4, 0xA9809F8C, 0x15646823, 0x6037DB27, 0x26A0ABAA,
+0xF8DC4AC6, 0x533494C9, 0x7BF60155, 0x7BB16D05, 0x89F7A1BA, 0xCB069606, 0x6572D71A, 0x001917EB,
+0xD353913B, 0x128F78BD, 0x83BCE2A3, 0xE0065266, 0x9E7E608F, 0x25889472, 0x184ADD42, 0xD42B429B,
+0x7A8D861F, 0x54C97AB8, 0xB8B04229, 0xDF3DE03A, 0xB97E311E, 0xBB2A1FF8, 0x53AC8D5B, 0x1825B5DC,
+0x9843DD95, 0x0214EAA6, 0x3B1CF504, 0xD3BE316F, 0x9B1D3C64, 0x8EF4A268, 0xFACBC9AD, 0xDCC6033F,
+0xF801E3D1, 0x92F3E3A1, 0x1EC121AC, 0xA6747F20, 0x6ACC34EF, 0x0F641DC0, 0x42CAB9C3, 0xE04036DD,
+0x97739381, 0x9843A304, 0x929E9AB7, 0x600E057F, 0x892D5F1F, 0x0F718281, 0xD345AA58, 0xF39215C4,
+0xBCAB0B51, 0x1EBEA1B0, 0x68885471, 0xB39AD728, 0x2FF70470, 0x80D01FE5, 0xB41A95C0, 0x01DB8079,
+0xA4C9F364, 0x41860F1A, 0xEBE24F2B, 0x086BFFF0, 0x7B66DE40, 0xFFF665D6, 0x18324792, 0x1D253106,
+0xC41B9BF0, 0xC79347BA, 0x6949A396, 0x279E7A4A, 0x4029B533, 0xE8B382E2, 0x89783E24, 0x3D945C74,
+0x49BD75D8, 0xBAD731A0, 0x48B4AFAB, 0x4383B903, 0x8A6966A6, 0x170B9958, 0x58307AB6, 0x3B627463,
+0x0B981BEA, 0xD8E9A038, 0x723219E7, 0x4F6E5470, 0xE4F3CF92, 0x37AACC8A, 0xA4E46500, 0xE44DDA39,
+0x68690180, 0x33143C47, 0x9A6EE438, 0x5FA00F23, 0xD2CEE248, 0x46090D1A, 0xDE5491AE, 0x417D853E,
+0xC607B731, 0x79D7DCCF, 0x13200C03, 0x07CAB5E9, 0xB59525EA, 0xE47B66A5, 0xB125AAAB, 0x20CCFE07,
+0x82F1F4E8, 0xCF44BD2B, 0xC462D58D, 0x60A6A73B, 0x0D0CA712, 0xFE342922, 0x15123217, 0x7A02E89D,
+0x49B44659, 0xB9F3AE54, 0xAFC472BC, 0x79AF1A6D, 0x7430BA59, 0xEA13F81C, 0x33592D7D, 0x1EF1E1DC,
+0xF51FF0C8, 0x80F7B07E, 0xC1536EBB, 0x586CB41D, 0x10AF823C, 0x390EA571, 0x7D54C302, 0xA049ECBE,
+0x368C3981, 0x38B72BEE, 0x833C5F98, 0x2E18D066, 0x5742B0D2, 0xA8F5F0B8, 0x9144935D, 0x7392A908,
+0x3175DBC0, 0x29AA2F7C, 0xF53FED73, 0xFE41236B, 0x091E47EC, 0xD2195647, 0xCAAEA8B5, 0x0ED9750E,
+0xF5027456, 0xF1838780, 0x16FFE8EE, 0xA21568C6, 0xC5E4FCAF, 0x27C24C4B, 0x3DE89E8E, 0x5464ADC6,
+0x865C8493, 0x41032697, 0xD5F82075, 0x49167AF7, 0xED1AA45C, 0xA6B20018, 0xB1776BA9, 0x9F2129B6,
+0x611C417D, 0x3B72E8B6, 0x1AA7DB22, 0xF4ADF40E, 0xA24B8EFB, 0xF25C5F9D, 0xE52C047E, 0x3B8C9A26,
+0x4C0760E4, 0x73027C0E, 0x1F5977D8, 0x6CAF979D, 0xEF39719F, 0x70129F6A, 0x0CC821CD, 0x9853AE70,
+0xC3EB24E5, 0xE4EED628, 0x9F904579, 0xFD680398, 0x2C84DF92, 0xF92DA147, 0xB2F7C7C3, 0x59052EB6,
+0x4DF89375, 0x275D0C58, 0xBE32DA96, 0x7A3C4C7F, 0xC5C2B02F, 0x651B2665, 0x36E5DC9B, 0x98B1F08B,
+0x175A5AE0, 0xBEC258CA, 0xDDF6B687, 0x49E3DBE6, 0x07C1C780, 0x63E3B861, 0x05FDAAEC, 0xFA7C38A4,
+0x5EE93618, 0xF8B78C2B, 0xBB5035B7, 0x7E297AC8, 0x6CC27636, 0x30D44C50, 0xECB1065B, 0xB00AB96E,
+0x87B3C67E, 0x0AA61403, 0xF514C18B, 0xDBF3CEEB, 0x62ACA4C1, 0x9A0D1691, 0x07E3DF50, 0xC42070E8,
+0x98F349F7, 0xC1556162, 0x6F7D7109, 0xF6C7B215, 0x73748B4E, 0xAF9F5BFF, 0xDD1B8AE6, 0xA9C710AA,
+0x5965A4DA, 0x762A0F38, 0xD42C7578, 0xBA69C66D, 0x2CCABCB7, 0x932E7065, 0xD6F3F37E, 0x729F1412,
+0xE5EAEB07, 0x1C2D7291, 0x07E5E6C9, 0xCA16EED5, 0xD488558D, 0x235C11EB, 0x579B8BCA, 0xAC352250,
+0x858BD553, 0xECCBE50A, 0x370421F0, 0xA66CD423, 0x1424CB84, 0x286FBE65, 0xDFF5A1E9, 0x71ABB615,
+0xAE331217, 0xE8E333A5, 0x99044B7D, 0x26264E30, 0x35A7FEA1, 0x3E933B79, 0x4151D8A3, 0x672D78D6,
+0xC586C999, 0xEFFEFF6F, 0xD1EC082A, 0x0EB38797, 0x85F77710, 0x5FEAE876, 0x78FBE4E2, 0x6284663A,
+0x6E54B0AF, 0x5C107AF7, 0x24005DF7, 0xA994E2EC, 0xAFDDB6FF, 0x79019A53, 0xE1B8A123, 0x997B7B95,
+0x9BFC63E3, 0xEAEEB40C, 0x14AECFE6, 0xC29A3F38, 0x21833356, 0x6B65DAAC, 0x9AEADA3F, 0x16582D82,
+0xD6E7B8EC, 0xEE67A365, 0x3F33FD50, 0xABD603DC, 0x0DA08D72, 0x69E01AFD, 0x4862B58E, 0xE1DFCA98,
+0x5FE11079, 0x40992E48, 0x0589689B, 0xE836FACC, 0x87FFD4D6, 0x9F5DF070, 0x6BC69520, 0x5CF6F087,
+0x66523DC9, 0x54D0EEA3, 0xDD820FC2, 0x663BFA8E, 0x2561E952, 0xA82EDAB8, 0x3FC1092B, 0x8591A2C1,
+0x0E9E67EF, 0x4A334D9C, 0x867BB16F, 0xB6A1713F, 0xED8D7EFE, 0xF2926C44, 0xD2E97512, 0xE8301103,
+0x3DD30957, 0xEFB71B3F, 0x4AE801D5, 0x8F75F730, 0x0C34FBC9, 0x7A60C668, 0x77908ED9, 0x963C0DE4,
+0x5279E29C, 0x6759B153, 0x747E5E7B, 0x4C510BE5, 0x32BE2132, 0x54B361E0, 0xCB4D9616, 0x3C404BA4,
+0x4BA0E910, 0x05F06AD1, 0xAE3FBC5C, 0x82CB03B4, 0xF0EC45FF, 0x9888791B, 0xDE4B9813, 0xF83B4090,
+0x3CC4BA28, 0x7CFE8854, 0x9CA7BC9D, 0x0E41843E, 0xF92535F6, 0xF19CC699, 0x0821CBF4, 0xF15F3F82,
+0xCF6CC14C, 0xF27DA57E, 0xB8DB8982, 0xFC7E263D, 0x63C36111, 0x61587ABA, 0xB87CB18D, 0x2C806A64,
+0xD8DFFF2C, 0xC8540E77, 0x1A340B85, 0xB6FBA97F, 0x77A1958D, 0x419648E8, 0x80A65729, 0xC3EC1141,
+0x3909010F, 0x84F8C534, 0x2FEDE987, 0x83851AC8, 0xAE88B841, 0xE8284692, 0x3243F04B, 0x9C845E80,
+0x4A7FC52E, 0xF6B1035A, 0x59E1C576, 0x21620CB8, 0xF047E16D, 0x079284B7, 0x00B6C955, 0xA7B19103,
+0x7B9EB069, 0x733E2443, 0x489A6EAE, 0x7BB17B2C, 0x6AB4F848, 0xEFA299A2, 0xC464BE42, 0x36F27FC5,
+0xE70CEAB2, 0x6FCB4031, 0x9C0A14C0, 0x682AA1A3, 0x36E7032C, 0x57BA22A8, 0x085288CE, 0xDE62ADD4,
+0xC0138A07, 0x4A5576F5, 0xC0F33DE3, 0x919ECA7A, 0x14FFDE87, 0x362897AF, 0xD542F683, 0x86FBC0FC,
+0x8CD6DD3E, 0x25832EDF, 0xC2C9EE74, 0xB244A89B, 0xFEAF2F44, 0x1D631217, 0x80BA2267, 0x097D3F4D,
+0x406264AC, 0x0571B5FF, 0x55658770, 0xE12F6AA3, 0x666D9831, 0x37E17306, 0x88D926AB, 0xBB0CC6D9,
+0xA857A201, 0xB24E5A82, 0xF259D2AE, 0xD09D0FAE, 0x87363A50, 0x583F1CC9, 0x653F73F3, 0x0D04970B,
+0x64D1F222, 0xEF7E0E0B, 0x7F5D49DB, 0xAC4549D9, 0x707D1FCF, 0x3A151C06, 0xFE5DEC4A, 0xE3D6CCBA,
+0x0AA3DA9B, 0x4665CBC5, 0xDF7BCD0F, 0x63DD0FF5, 0xC9C2A642, 0xB40B516D, 0xE259A165, 0xE2E454E1,
+0x0A384EDD, 0x1287018F, 0x2A7A8DFD, 0xF854FCF1, 0x79CAA64E, 0x351AC522, 0xEE65C527, 0x7F160E51,
+0xF465AF5C, 0xE671974B, 0xAF75CA8D, 0x47A5EC29, 0x5F93C8AD, 0x6420D4E9, 0xA5CA4610, 0x265F0BF4,
+0x6622036C, 0xB542C8CB, 0xDFD1FA4F, 0x5869BE19, 0x14605EAE, 0xA438FEA7, 0x9523F5FA, 0xE18FCF2B,
+0x5F11F7B1, 0x7A790EBA, 0xDBDD0005, 0x024E0D8B, 0xC387778B, 0x3C0F1274, 0xA722512C, 0xEAB3C2F3,
+0x11B55F3A, 0x9C2DBBD6, 0xA76C80DC, 0xD63A5DD2, 0x320F7AF2, 0xA707544C, 0x889A3C58, 0x50CCA3B0,
+0xD54FE248, 0x22EF12A3, 0xF618F564, 0x1D9266C8, 0x4E08FB46, 0x6D1D41EB, 0x5CFF2094, 0x116ECB97,
+0x46FD4058, 0x38FBE5CC, 0xE008E8EF, 0x578FAF14, 0x3BEED1D9, 0x8C89B4CE, 0xFC0C33D7, 0x0913ECF8,
+0x498D47D1, 0x5644A9B3, 0x6EA66735, 0xA0F3BA09, 0x948B258F, 0xFA8DE3BE, 0x2FB03145, 0x8D0B61B3,
+0x42D6F53D, 0x031FD745, 0xFF86C938, 0xA32BB471, 0x50208969, 0x9F6909C9, 0x680C6D55, 0x13054044,
+0xDFDEBEF7, 0x35600E83, 0xAFB26C47, 0xCAA86F9F, 0x5B5B65A7, 0x599DA0C3, 0x789EC931, 0x0163D6D4,
+0xF7BBA271, 0x5A755052, 0xFA27CE77, 0xD66ED111, 0x7A5BD527, 0x1B26B948, 0xAA11725B, 0x4A6AC4AD,
+0xDD8EA8DF, 0xF0C618D3, 0xF97999E5, 0x00C42C38, 0x8465BE06, 0x7B6912C9, 0x4AF1F070, 0x4F93EEB0,
+0x19A400FC, 0x0F8A6744, 0x7FD642F2, 0x3AE8F32F, 0x84501DDA, 0xB39068C6, 0x2A5BE1A6, 0x08E231F0,
+0xD52F4D13, 0x89326BE0, 0x3981DD90, 0xA986F547, 0xADF1B2E8, 0x6337CFB6, 0x595FCBC0, 0x2D774749,
+0x1D6C5FF1, 0xF403CE90, 0x16792051, 0xCE248A7D, 0x43E76774, 0xA85ED14A, 0xCFBDEB69, 0xDF559AF6,
+0xC3BF33D1, 0xF03BB486, 0x107D04B0, 0x9B9E9432, 0xE4873EC4, 0xFD7C2E89, 0xFA69FD26, 0xD04F8825,
+0xB9C4FF1F, 0x30F0826C, 0x825A8A34, 0x5EBB4ADC, 0xA71C9FF5, 0xE90ECF8A, 0xFEF3270F, 0x25612AB6,
+0xF8560C1F, 0x625A9ECE, 0x12B9B123, 0xA281D55C, 0x276F3B4A, 0x6CDE95D8, 0x7EE9F866, 0xDC769A4F,
+0xC590E1F4, 0xEA845796, 0x013AFD9E, 0x6F8E1A4D, 0xBEDF18E1, 0x2CC567BD, 0x56CBAE9D, 0xF81716E8,
+0x88834AAE, 0x1C67A0AE, 0xDDB4EB33, 0xF0F874E6, 0x4DE9C550, 0xCEAC73AD, 0x5C800FD8, 0x6A31B61A,
+0xA8B3A501, 0x73639607, 0xC95BAE
+
+basegraph=
+1
+
+z_c=
+320
+
+n_cb=
+21120
+
+q_m=
+4
+
+n_filler=
+688
+
+e =
+21592
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_LDPC_RATE_MATCH, RTE_BBDEV_LDPC_CRC_24B_ATTACH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v7813.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v7813.data
new file mode 100644
index 000000000..6e1acf5a4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v7813.data
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+# Origin : FEC5g_DL_1/7813
+
+op_type =
+RTE_BBDEV_OP_LDPC_ENC
+
+input0 =
+0x8C4DEB9F, 0x52
+
+output0 =
+0x1A6D0FA6, 0x7017
+
+basegraph=
+2
+
+z_c=
+7
+
+n_cb=
+350
+
+q_m=
+2
+
+n_filler=
+30
+
+e =
+44
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_LDPC_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v8568.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v8568.data
new file mode 100644
index 000000000..e9bacd1b8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v8568.data
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+# Origin : FEC5g_DL_1/8568
+
+op_type =
+RTE_BBDEV_OP_LDPC_ENC
+
+input0 =
+0xB6D49CE2, 0x3E96B93F, 0xF02009F6, 0x2DF3D30D, 0x3B06C160, 0x646C69CC, 0x54439F0F, 0xCE0D12C3,
+0x66E8BFD5, 0xA9D22B0C, 0xA9E7343B, 0x2B6EEF01, 0x6B6966C0, 0xB98FE144, 0xC3BF7BAD, 0x1B40DF1C,
+0x973B12DC, 0x46E25E90, 0xB324ACCA, 0x5F0ED2B9, 0xBB4F
+
+output0 =
+0x8F1A7C00, 0x836CF0E5, 0x717CE52D, 0xEE86FB44, 0x21621E25, 0x58425AB5, 0xECA0F645, 0xAE9E63E6,
+0x287D84BC, 0x9F19A401, 0xD68C4CA3, 0x354ACA5A, 0xD68D7FF8, 0xFAA84645, 0xCF0DBC28, 0x693C50F0,
+0x9A3CD23C, 0x57E97520, 0x929BAF90, 0x8E2BA7D8, 0x5EF0FB8A, 0xFFE7B153, 0x9E164074, 0x4D06F0A2,
+0x6BC68E5B, 0xB8274587, 0x69641DFC, 0xF5DC89A0, 0x4F8E741C, 0x1CB682DA, 0xEF36E914, 0x8BDEBA30,
+0x4B6777E2, 0xEFBFD14C, 0x85F0DF67, 0x55DBD201, 0xCF29A01A, 0x862BD273, 0x1F43CFAF, 0x5CB128E9,
+0x9C322654, 0xF8E4E47A, 0x0FCD1806, 0x0C7B6BC7, 0xF7B9748A, 0x6DE5D592, 0x0D119373, 0x5F7DC28C,
+0x68F26F39, 0xAA47E18A, 0x479CDAAF, 0xE19DCBB3, 0xA72B475D, 0x2E781ED4, 0x4CBB910A, 0x5E5A5A1D,
+0x2F668621, 0x86BD9FE1, 0xF1DC12E5, 0xB652E2C1, 0x2E0AC199, 0x059E43C4, 0x14F9B51E, 0x7DA378C5,
+0x214E4D5F, 0x72ECE751, 0xF997A106, 0x3F362F62, 0x045DCA85, 0xAD27A58E, 0xB73B4390, 0xEB76C5D2,
+0x58CE8B78, 0x73A1D1EA, 0x9705C8E4, 0x224703E8, 0xA0DE7885, 0x9CDBBEE0, 0xBAAFAE85, 0x1B5CFB8A,
+0xF66B5209, 0x979335BB, 0x2AA6C7E2, 0x7E3958E7, 0xD39F8BC0, 0xD73BEA43, 0x24C74D3E, 0x9372C2D7,
+0x49804670, 0xB3A983FC, 0xFA6DB662, 0x4E657550, 0xDDF757C2, 0xA7265DE7, 0x51BFA1A6, 0x63E1325D,
+0x1FDBE953, 0x17348EDB, 0x6B6DC5C0, 0xE335772B, 0x32612617, 0xC13B63EB, 0x8C40891A, 0xF3566154,
+0xF5345933, 0xAD9AB800, 0x4CF92B41, 0xF3B32673, 0x80577879, 0x19F8BB0E, 0xAD677483, 0x21B2EDC7,
+0x3F96C8E2, 0x7B9211B7, 0x11909101, 0x6A9D9BF5, 0xC4A0E407, 0x5B013820, 0xD2102C31, 0xDC6F548A,
+0xA4F6B72A, 0x79F19991, 0x6A21BE3C, 0x2E5CF7A5, 0xDCBB384B, 0xB05B5649, 0x1D61CCF1, 0x9DC122F3,
+0x00CA6A82, 0xB7CECDF0, 0x605252A3, 0x0500B498, 0x61AA1618, 0x669788EF, 0xF0DB599F, 0x3ED04C4A,
+0x17387F1E, 0xBDAC7B52, 0xEE7D1E0D, 0x58AF212C, 0x0CB064F8, 0x646239DB, 0x88CF9549, 0xD3C7C652,
+0xB82109DB, 0x22225244, 0x305F8384, 0x9B4166D5, 0x704FA445, 0x956A0CA5, 0x89963D07, 0x5EF61FAB,
+0xF71EAD06, 0xA47FB814, 0x86581A5C, 0xB81B9445, 0x4ECD608E, 0xE369E9A3, 0xFEB80EE5, 0x1399AB02,
+0x30A74BEA, 0xCF08B948, 0xB0857028, 0xC81F8CD8, 0x64E13623, 0xAFF927F5, 0x592D7629, 0x7295DE02,
+0xE98E2F04, 0x7407C828, 0x85EE9A47, 0xF9B6F671, 0x77F40DF0, 0x81CE7DA1, 0xB8732D5F, 0xC7AC742E,
+0xF8623836, 0xE68F4E66, 0x18F29BB9, 0xF57E3350, 0x0E14399C, 0x114ACFA1, 0xFECFBDAA, 0xB0894694,
+0xC8DF6D23, 0x7C71FB18, 0x91F00CF2, 0x6A45BC52, 0xFE99962D, 0x41FEBA3D, 0x5C1BB499, 0x51E50591,
+0x04D9CDDE, 0x503FBB80, 0x2788B4EE, 0x82A545D8, 0x5F6DD45D, 0x7AE48BE2, 0x4C653419, 0x3C32D58C,
+0x48788C71, 0x97A054A3, 0x7FC443B4, 0x805DFF9E, 0xA607D2C6, 0x02DA82C2, 0x884664C5
+
+basegraph=
+2
+
+z_c=
+72
+
+n_cb=
+3600
+
+q_m=
+2
+
+n_filler=
+64
+
+e =
+6624
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_LDPC_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v9503.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v9503.data
new file mode 100644
index 000000000..7fc8c9543
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/ldpc_enc_v9503.data
@@ -0,0 +1,197 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+# Origin : FEC5g_DL_1/9503
+
+op_type =
+RTE_BBDEV_OP_LDPC_ENC
+
+input0 =
+0x88CCED56, 0x1C072C76, 0xD4D23B69, 0x78C979BF, 0x60764BE3, 0x4470E86B, 0x20A46F84, 0xA0211B5C, 0xE1952001, 0xB77912DE, 0x52E8BA16,
+0xE5BE8445, 0x95093ACF, 0xA8BE03D2, 0x49DBB5AB, 0xC3946403, 0x4DD44236, 0xC2833E65, 0x7288C53B, 0xD64FB75E, 0x7438C1EC, 0x71070BEC,
+0xA40F8094, 0xABF43E46, 0x564487F5, 0x8435AC89, 0x2D98A4C3, 0x07CD13F4, 0xB44CEEA6, 0x2E00DD83, 0x12EF45EB, 0x01A047B8, 0xBC563FD5,
+0xCA5C1136, 0x7AB9F2C8, 0xD62C59A9, 0x913DF674, 0xC900322A, 0xCF54042E, 0x6CAADB1E, 0x8077B98C, 0xBCB51468, 0x58339E5E, 0x1D176854,
+0xF9E2D74A, 0x2994B28A, 0xD0E46263, 0xCD8A0FDB, 0x0119B915, 0x1E5433C9, 0xEA298A7D, 0x9EB4FC8D, 0xEF93B537, 0x6D441397, 0x6A4C8DB3,
+0xB8E4AFE9, 0x1520BC1C, 0x8669961B, 0x5D484802, 0xC2793340, 0xB5FE7945, 0x43AC7CE2, 0xB74B70C1, 0xFCF56F87, 0x3E146A49, 0x0391D092,
+0x672D2427, 0xDC91BB53, 0xEB24AC1F, 0xCE0D8E63, 0xF12F7ED8, 0xB3192024, 0x0697AE9C, 0x3415F178, 0xD8410FFC, 0xE34734DE, 0x6C6E6BF1,
+0xDCD211C3, 0xBF6B0B87, 0xA1624F47, 0x3524BC4D, 0x4B4A1891, 0x8691223C, 0x12EB2DA4, 0x0B51F616, 0x31276F0E, 0x86CB4D17, 0x15CA0F9B,
+0xEB989F98, 0x1141D335, 0x442C699F, 0x82E9758B, 0x267E6D4D, 0x71BAC54A, 0x2FBCBD52, 0xA0966795, 0xEB08B437, 0x1A9899A0, 0x26484B82,
+0x3AEE43A8, 0xC409BE45, 0xCF8C6EC9, 0x098DE63F, 0xC3BEA60B, 0xCB7A5B6A, 0xCBF2A44B, 0x31E9FA4C, 0x34FD7E88, 0xA3C5AF89, 0xF13C8E2B,
+0xC01C79FA, 0x622B9FD8, 0x692D4C4F, 0x712BC24C, 0x16FBD6C3, 0x7B1BBC38, 0x63F1E328, 0x6F4B
+
+output0 =
+0x6ED462FE, 0x29726470, 0xE49C87C1, 0x6594725E, 0x64C81AE1, 0xA30C91C2, 0x5B4261AB, 0x7A44E3A4,
+ 0xACBD3DC8, 0x319AF530, 0xF3B21EC1, 0xAC180011, 0x26319FF9, 0x5946FBFD, 0x6F31959A, 0x571501D9,
+ 0xFB1F62B7, 0xF19F6C36, 0x43436C4A, 0x8CA5F436, 0x18AF91B4, 0xD86ED79F, 0x8732D29C, 0x6CE3B559,
+ 0x2DEA712F, 0x52C2E21A, 0x5C4E884C, 0xD2F50500, 0x2140E848, 0xABE47066, 0x8AE3FC46, 0xF0298999,
+ 0x829FE184, 0x51D53B6B, 0x7546D03C, 0xF1CB22DA, 0xB9D6F966, 0x85660A1F, 0xC1296566, 0xB2122E16,
+ 0x2AA38C25, 0xD7AF18FC, 0x489BDDC5, 0x93183097, 0x4C694A3C, 0x40B325F8, 0xEE05DAB2, 0xA6E0C990,
+ 0x839A7753, 0x0251D207, 0x5E1EC6B5, 0xED523076, 0xD985E23A, 0x8CA88259, 0xB0EFF6D4, 0xA9D7749B,
+ 0x32CA6F0E, 0xAAA84E97, 0x0F137B83, 0xE73C3175, 0xA3940FDA, 0xD878B121, 0xFFC8D2EC, 0x95CB65AC,
+ 0xB1CBE446, 0x73520449, 0x7D929F16, 0x69D1873C, 0x85640C01, 0xF2228024, 0x0A5E0461, 0x58B0933A,
+ 0xD37E2375, 0x36CEECEF, 0xE57A48F8, 0x4A35B5C9, 0x016A16A0, 0x6F9BCF30, 0xEB7C3BD0, 0xB1AF27FE,
+ 0x9C389360, 0xA91F2142, 0x51E618D3, 0x5F045697, 0x654C6A49, 0x2E38E30C, 0x9E8F1E63, 0xF1B25686,
+ 0xA0CDFB02, 0xDAEC605D, 0xED910B79, 0xA8E1A341, 0xAD6BD0A3, 0x03BABB0D, 0x4059355C, 0x5ECB8646,
+ 0xFDD9E0C6, 0x69106FD2, 0x47BF857E, 0x740F6313, 0xAB15E1FF, 0x94B21225, 0x600FEDF3, 0x1EF83A71,
+ 0xCE6956EE, 0xE538FC7D, 0x47520BE0, 0xA1A20CF2, 0xCB452B91, 0xEACB9E3C, 0xBA242A34, 0x13C81868,
+ 0xA58AB271, 0x724B350D, 0x95131286, 0xCF74DD61, 0x1D0CF41B, 0x38D046D2, 0xB709708D, 0x4D479AA8,
+ 0x3CBF6817, 0xDF115777, 0xBE69B850, 0x071A2B4C, 0xF3246B56, 0x2881CBA0, 0xAE158E87, 0x36538CB0,
+ 0xEF879197, 0xDBA9C1C7, 0x4EF7235A, 0x56120670, 0xC22DBEC7, 0x7071A05C, 0x376ADBD4, 0x5DD586FC,
+ 0xA638A621, 0x6D49A92A, 0x66F0C925, 0x023FC9DE, 0xF7CA1D36, 0xAF19A18B, 0x2A787792, 0x518938D7,
+ 0x25DE7B4A, 0xDEBD9010, 0x9683558D, 0x9C5694C7, 0x8B2558D0, 0x790CD121, 0x0A35C0D8, 0xCD4FBCED,
+ 0xB89F3275, 0x64A49655, 0xED7992A1, 0xAFB0A4D0, 0x29A9EB1B, 0x9244B2C0, 0x2CD88F45, 0x4AA1E98E,
+ 0x8E32CC3C, 0x8BE5DC7B, 0x759C8B24, 0x8AA119BE, 0x9CFEA065, 0x071F86FD, 0xB83F8181, 0x604FF2FB,
+ 0xAACDC394, 0x0BCC72F5, 0xE9C0CB19, 0x56EAE15F, 0xD33B8DEF, 0x01A1B007, 0xBED7C1A3, 0x18788E49,
+ 0xB565EA30, 0xC269F619, 0x1CF1B024, 0x067E9F59, 0x78E61AB4, 0x3D46CFBB, 0xE58E910B, 0x8E7ACF53,
+ 0x1EB9C15D, 0x4E3C43BF, 0xEF3D8F20, 0x5CC0A030, 0xE10AE4E7, 0xABE24941, 0x9A0C4046, 0x24E090CF,
+ 0x3248C414, 0xAF76560F, 0xCD1B106C, 0x70438AD4, 0x3463D8B0, 0xD85860FE, 0xFCDF0D57, 0xA2DBC09E,
+ 0x44C728C1, 0xD8FEE73E, 0xB1E6B4A5, 0xD0CC95CD, 0xCCEF186F, 0x70AC5D98, 0x57D21267, 0x8543F446,
+ 0x15C8EAA9, 0x0DD357D4, 0x4CE9C090, 0x4E91FADF, 0xE0658E27, 0xFF7AA5D6, 0x176ED723, 0x70D009CB,
+ 0x416ADBAA, 0x1C45865D, 0x105F3A0E, 0x14730450, 0xD0FA1AC9, 0xB76F268C, 0x7B075289, 0xA9455796,
+ 0x65E02F3E, 0xB74521F2, 0xF6CAA6C7, 0x94ABFDAD, 0x1E6D1087, 0xC25A9257, 0x87FAF9A4, 0x5184A0FA,
+ 0x240023D7, 0x7AE0ED45, 0x06E0A838, 0xBB018F31, 0x0FA836D5, 0x09CF6AEC, 0x9BC4F2B2, 0xAE92D5BA,
+ 0xE724036E, 0xE5606DDE, 0x631448F9, 0xFD59B782, 0xF17052E4, 0x66EA4C50, 0xF72C1768, 0x5C24ECEC,
+ 0x6B01B118, 0x89F8A3AB, 0x465FF462, 0xC3896A00, 0xFEC06004, 0xE2DFC70C, 0x3ACF338F, 0x1552E9D0,
+ 0x9F699B77, 0x60AC6D29, 0xBF47FD38, 0x826B0CA8, 0x0515A7AC, 0x1380A222, 0x7D054EA0, 0x3D1BCEC0,
+ 0x21AB6CF3, 0xA889E915, 0xF09D9756, 0x08BA519A, 0xCFFB6BD3, 0x7D5EF4F9, 0x34A0E942, 0x8569A327,
+ 0xFDDC5269, 0x60D8D543, 0x88B34B88, 0x50DEAA10, 0xD0563E1F, 0x80CD122B, 0xDC11607F, 0xCD9D7E05,
+ 0xC0F3510E, 0x414A7545, 0xB8211557, 0x103E6F53, 0x08A47672, 0x04D9C391, 0x3281F25C, 0x7526AAD2,
+ 0x3C89B43B, 0xBA767E59, 0xA2788EAC, 0x5EF9DF3D, 0x8F72BBE6, 0xC4B52A2B, 0xE81A80E9, 0xCD6B24D5,
+ 0x4F934751, 0xA3FCC2B5, 0x1C4FB12A, 0x7C363E45, 0x237CB63A, 0x1F26D6FD, 0xAAF3FE61, 0x48D3B3A8,
+ 0xA2A77A81, 0xADCF4AB4, 0xDF94F9B4, 0x465EA838, 0xCE4BA15C, 0x75826F5A, 0xD537E32C, 0x85F8FECD,
+ 0xD07CAB1C, 0x34F91310, 0xC40B36CA, 0xCCE0297E, 0xFB276610, 0x67DF82EC, 0x8BB58FAA, 0xCEA3BDC2,
+ 0x02B21D68, 0xCC1F8A6C, 0xF902AF4E, 0x271828EA, 0x9028298A, 0xB5BF0156, 0x5A3B3188, 0x6CCB6806,
+ 0xE2F3A4A2, 0x3B776BB9, 0x66D01790, 0x133F2414, 0x1445FE7D, 0x5CC79E5B, 0xB95FD30F, 0x50971FC5,
+ 0x8D6AFECA, 0x3FB2427C, 0xC1A980EC, 0x54C9F2AF, 0x0F509DF3, 0x1B950AA4, 0x1E5B1596, 0x93E974B9,
+ 0x71D51A0F, 0xC973F4DD, 0x79BF62A6, 0xC72F58F9, 0xCAD478D6, 0x0F7C36C7, 0x05D08481, 0x43958D67,
+ 0x93F11E1A, 0xDCDDCE62, 0xB457AC62, 0xD4A98268, 0xA793471A, 0x7AB637E0, 0x1B9BA86C, 0x456B5EF7,
+ 0xD2E75711, 0xF95E6BCD, 0xD3043467, 0x056F1621, 0x21D58D4E, 0x0C9EF57E, 0x96B645B1, 0xF5A80340,
+ 0xBD9A4C7A, 0x4D94A305, 0x59D0F9B4, 0x113F56F9, 0xE0A948B5, 0xBF982299, 0xA05D1EA1, 0xE9C50F8A,
+ 0xAF6B8F04, 0x6B05485E, 0x17DD458A, 0xFB819464, 0x5CE2F61F, 0xECF95F48, 0xA26CFBA2, 0x6A0FD00F,
+ 0xA7A2CB0F, 0xFE10768D, 0x4A258743, 0xBBF2C41A, 0xF519DBEE, 0x9DA676B6, 0xE89449C9, 0x3E13EBE5,
+ 0x4A4A42A5, 0x42663182, 0xDAAF85AB, 0xCC671BCB, 0x217491EE, 0xDCC9B6F2, 0xE1A3A7EA, 0x7B13F2F9,
+ 0xCFFCBC9F, 0x3D8FF387, 0x71ABA888, 0x2D3FE4C1, 0x081AB3DC, 0xBF21BA4B, 0x4ACE0F00, 0x6F5AB592,
+ 0xD328F08C, 0x542388E9, 0xE7A4157A, 0xE8532856, 0xE8DC528E, 0x3F2356AE, 0x76867882, 0xEC11E6D0,
+ 0x0C2DD257, 0x40A7C558, 0x354F885C, 0x2A2E0757, 0x6C0A6D95, 0xE0C23A09, 0xD1F32FF7, 0x7E27842E,
+ 0x3CDFD97E, 0x2F6807FB, 0xDBED07BD, 0xA039645B, 0x324B0955, 0x73620D27, 0x0C47D75F, 0x511BD37A,
+ 0xE80C4C44, 0xA3D77AFE, 0x058B503D, 0x391AC187, 0xD7425F0B, 0x93876765, 0x10CADF4C, 0xC4F3539A,
+ 0xF17B776C, 0x017BDEFA, 0x74F4651F, 0x65FBC1E5, 0xF55CC6B6, 0x1752401A, 0x85FB6434, 0xB8FD0F06,
+ 0x4D0D80FF, 0x0DD8438D, 0x1C5844B7, 0x31ECF66B, 0xF8A8B528, 0xA9BE0373, 0xC401C7FC, 0x3BA1FFF4,
+ 0x63946BBD, 0x82514893, 0x9CE303D6, 0x51EA2484, 0x054CACA2, 0x3F812B32, 0x0F3C603F, 0x4B3D86B6,
+ 0xD33F5950, 0x3340BFC0, 0x47CEB79D, 0x1CAB5D3C, 0x74897EB5, 0x1C320D6D, 0x8F0480D2, 0x1384331B,
+ 0x8363A7B3, 0xA5439504, 0x0E06AA80, 0x4BBFF55C, 0x470094F3, 0x8DE8E9AA, 0xABA72796, 0x4333B263,
+ 0x6FEF04EB, 0xF921C722, 0x9599B4C8, 0xBFEFF55A, 0xF89AA502, 0xDFE85218, 0x0EE15930, 0x8B2AA7F8,
+ 0xDDB03823, 0x7427A3C2, 0x8E4AF556, 0x66A9640E, 0x2EA271AE, 0xFC5BB50C, 0xDC50B432, 0xF78BB3D6,
+ 0xA06156DE, 0x5A7D7A40, 0x40BD74BF, 0x882CC19B, 0xDB2B6143, 0x5532686C, 0xA6D65320, 0x6AB5B32A,
+ 0x34129535, 0x9E41D92F, 0x3D86A085, 0xA27DE0C1, 0x6FFBEC11, 0x77A4BE81, 0xCE1DF886, 0x318E96BA,
+ 0x82C84B84, 0x40B9874F, 0x39F9F9A9, 0x21E0AACB, 0x237FC858, 0xFF700E2D, 0xA840518D, 0x5E5ED583,
+ 0x7B11CB4E, 0x99733B7F, 0xFFAAF7A9, 0xB8CB13B7, 0xE67AE45C, 0xFFDA2FC2, 0x47D08BD7, 0xD68BACF6,
+ 0xDAAE30ED, 0x95735CAF, 0xF896B165, 0x395BC94E, 0xADF803B0, 0x76B82F4D, 0xF312DD33, 0x0DD0A49D,
+ 0x0852B35E, 0x4DF14366, 0xBA01C779, 0x1415A8FA, 0xDC10F525, 0x1CE06D80, 0x953089E6, 0x933C3EE5,
+ 0xC18B1022, 0xFAD11D71, 0xA1EA92BF, 0x2AE61798, 0x63D0C0CF, 0x1CF8CA34, 0xDF748AFB, 0xF0FDE897,
+ 0x26FC4399, 0xE563FFC5, 0xE6AFE218, 0x5EE3254B, 0x76565E08, 0x70F5EFBE, 0xBD66AC9A, 0x90853CB1,
+ 0xA002CE55, 0xAFE263F4, 0x804DA5A5, 0xBB971F95, 0x775BDE46, 0xEDA15B5F, 0x3D5A2CFE, 0x6D9FE953,
+ 0xE84541F5, 0x6574FB29, 0xFD3ADC69, 0x1BAEDDED, 0xE3F810C2, 0x87CC8D7C, 0xDC23F894, 0x7635A6DC,
+ 0x294E131B, 0x62FA4471, 0x83D3870E, 0xF82B9324, 0x8A493E04, 0xA8FCDF75, 0x20583A80, 0x5A94424E,
+ 0x18CED906, 0xB417F24A, 0x47089341, 0x62A432C0, 0xFDC17DFD, 0x5B89C6D2, 0xC8C8ED37, 0xD44D38B1,
+ 0x9A6DFF2C, 0x7C5ECB65, 0x76814C50, 0xB3D56A33, 0x5DF124F8, 0xDB92A5D9, 0x210F2E0D, 0x50FFFF1B,
+ 0x1B7ECD90, 0x481ED2FE, 0x094DA8E8, 0xF111F8FA, 0xAC7872DF, 0x4B8FE240, 0xA7CF01FD, 0x72AFAF1B,
+ 0x27BE7F7E, 0xE5F42B34, 0x02807296, 0x325F9CF6, 0x97EE1C92, 0xD5E6F65C, 0x7EA2490F, 0x666E3451,
+ 0xB17E6A43, 0x1AFBE46E, 0x8D2B871B, 0xD52A1A9E, 0x41EBA711, 0x9D4B906B, 0xAEB5A2F6, 0x7EC530E7,
+ 0x063FC87E, 0x48830732, 0xE5EC2B25, 0xA17B0F26, 0x2C63A878, 0x7A1362A1, 0x68B4DE31, 0x6EC14B7E,
+ 0xE65C3B05, 0x8EB452EC, 0xB6DD94CA, 0x8DC592C5, 0x402EA8BE, 0x689F131B, 0xDA3A54D1, 0x41D264AC,
+ 0xAD150ECF, 0xD7750790, 0xBD46E2A0, 0x2DC97F87, 0x2476F6AE, 0x28F4778E, 0xB4B9E75A, 0xE5532AD6,
+ 0xE58A7485, 0xDFDD2553, 0x779D3F91, 0xD89F3033, 0x42BB4152, 0x2F6EFB01, 0xF72C43BB, 0xF1DB8663,
+ 0x5BA625E2, 0x17180017, 0x151F03B3, 0x7FDA9772, 0x1DEB2F8D, 0x178DE5EE, 0xDFF10ACA, 0x2DC29F2A,
+ 0xF2797346, 0xC298535D, 0xB56C1D35, 0x6389138B, 0x54B732AE, 0x3FAF9958, 0x3BFE3E52, 0xA311D83E,
+ 0x50E7B0BD, 0xC28F97B4, 0x8C1FAAB7, 0xD22BD453, 0x4E6A4D65, 0x626B6251, 0x1F547F6C, 0xEF8105A0,
+ 0xB7A062B6, 0xE1325CC7, 0x8207E7A2, 0xB0A9E0D6, 0x097B78C1, 0xC41D4176, 0x13DB573C, 0x5291E598,
+ 0xF4D1AFB4, 0xA93FE970, 0x673042D8, 0xCC98A35A, 0xCEBD4AE5, 0x47B8BB39, 0x5F8A294E, 0x37FDA881,
+ 0x9E81D5BD, 0x47691BD1, 0xFB92FBF8, 0x24AA898D, 0x0D0B5B29, 0xE5E11928, 0x7D356637, 0xC4525D0E,
+ 0x72AFE781, 0xEBE53FCD, 0xBCBB299C, 0xC40B26D3, 0x1C049A63, 0x4621C7F8, 0xD3337531, 0xF5CCAE80,
+ 0x5D3D0BB7, 0x2246BD17, 0xF158D4F9, 0xE5CB58A2, 0x07F5F1E1, 0x9D420346, 0x952C186B, 0x9DBB2227,
+ 0x203D1639, 0xC022D8AD, 0x7A91F3DD, 0x9326CB7B, 0x2971F3FA, 0x7EF8C14B, 0xB7B468DA, 0x840A9104,
+ 0x6F811C48, 0xC0DAC40B, 0x68D75281, 0xB7DCB2D8, 0x9A216C54, 0xEE710DB9, 0x54ADDAC6, 0xF6F71ECF,
+ 0x6F1E0D83, 0xDE5ECA0D, 0xEA40DE93, 0x962D60E7, 0x6B575E29, 0xFFCC6677, 0x0D879692, 0x728CBE24,
+ 0x9011B3F8, 0xAB260F9E, 0x5D71E2CA, 0x501F6613, 0x5F16EE75, 0x0D33E974, 0x8865BBE8, 0x10495EA6,
+ 0x393032AB, 0x6C7F4A61, 0xB685D152, 0x29D429A4, 0x24CA7E33, 0xCD26F3F2, 0x78D85078, 0x0BA90BA3,
+ 0x360CB744, 0xDF999168, 0xB60B3644, 0x39EED49A, 0x4A794E4A, 0x3B6715BF, 0x92D35DC9, 0xF640ADB6,
+ 0xFA96EF3D, 0x0DC22AD1, 0x48262E68, 0x6F620F37, 0x6B29E242, 0xC6FBEEB6, 0x3034A0D9, 0x122EF44F,
+ 0x7EEF61DF, 0xF3854D20, 0x0F84C1DB, 0x0DE504BF, 0x8AE763ED, 0x369AD35F, 0x8BA7B643, 0x44933BB5,
+ 0x49E96357, 0x4C7F9884, 0x2A5BF491, 0xBB8DCDC2, 0x3873C5F5, 0x0DB1AB26, 0x09FF188A, 0x93DE180D,
+ 0xBA757CAC, 0x06AFFBE6, 0x12B37F82, 0x150D3234, 0xC2C0AB1E, 0xC8B4D8F3, 0x65B7BB96, 0xBBF951B8,
+ 0xC4A03C44, 0x7E2FF9B6, 0x86592827, 0xECE0BE1B, 0x0DB32865, 0x5FC2CD73, 0x34AD2D16, 0x3B2057A7,
+ 0xC32C663F, 0xA85CD1EB, 0xEBD5BCF3, 0x439DC2FF, 0x93379CAE, 0x99273984, 0x3659A11F, 0xD5FF53BD,
+ 0x38704C43, 0x3D782532, 0xD7306729, 0x420E909F, 0x4840C5F3, 0xDA80DF8D, 0x53395E04, 0xEF690DCF,
+ 0xF9738931, 0xE91F7065, 0x5EB901A8, 0x176C6A2C, 0x25D062AE, 0xE4CCCB95, 0x93C87277, 0xF8FF911C,
+ 0xD7AE6706, 0xE704A40E, 0x38BCF64B, 0xDDFFF9FD, 0xD1BDE381, 0xA4313A0B, 0x48DDA520, 0xD064D1E3,
+ 0xDBFD61EC, 0x7EA87E9A, 0xF894AAFD, 0xB5565368, 0x2C34933D, 0xF0F50DE9, 0xF91EB25C, 0xE3EC3B8E,
+ 0x5E9409A7, 0xB2A9D39A, 0xB6B19F3F, 0xA6685DC9, 0xCAFC5B74, 0x4CC15F7F, 0x114E5709, 0x31B6E0EB,
+ 0x8CDAA5C4, 0xF5ABD631, 0x12A4A9C0, 0x969011BE, 0x9AB39E96, 0x0D406569, 0x8AE25103, 0x68474C26,
+ 0x9E8D006F, 0x9C8E4F0B, 0x314630FD, 0x2F30B254, 0xFE88FCF4, 0x941FBE2D, 0xC03B55A3, 0xEE474898,
+ 0xEC9B3BD2, 0xDDE00C4B, 0x7F192B54, 0xA25A0DC1, 0xDCF18F59, 0x55F674B4, 0xF6734A46, 0x92B7A7E2,
+ 0xCEDA18D8, 0x90EA738E, 0x7C98FEE8, 0xFC3DE7ED, 0x4075569F, 0x8989B676, 0x326B34DA, 0x52AC749C,
+ 0xAF71ACF8, 0xDC1F65F4, 0x408459F9, 0xD46B650F, 0xFAEDB779, 0xBC0C6EDB, 0xF68DB879, 0x40071FCD,
+ 0x2D01AC86, 0x7952D58A, 0x4F7A42BA, 0xD5C9306C, 0xFA7CC252, 0x48285F83, 0x51CD6BC3, 0x8212BC4D,
+ 0x53828B06, 0x8986B36F, 0x6E00951C, 0x6505074F, 0xAB3AF4CC, 0x12D92810, 0x44F4D0B5, 0x0D7DBCDD,
+ 0x152A5968, 0xA92C4ECA, 0x6795E17F, 0xD02C875E, 0xA4B5A04C, 0x2F0C4295, 0x72678451, 0x59B87A4C,
+ 0xB3AD2988, 0x7B717173, 0x6D0EC6EB, 0xF73B4FC7, 0x645D56E0, 0xBC73769E, 0x9A83ED5C, 0xCE5B332A,
+ 0x151A4D6C, 0xDEB26C33, 0xBA7CFEA9, 0x0FB2D875, 0xE0045E66, 0x9DB0072A, 0x5CFB3C42, 0x8C3FEFD5,
+ 0x4E7CB65C, 0x2905EC79, 0xA2F6C308, 0x296A6794, 0xB589571E, 0x4638BC8F, 0x964B8B40, 0xBE27615F,
+ 0x4E95C30C, 0x2B56A6A8, 0x4BC50BC3, 0x497BB78B, 0x8860A6CC, 0x80830DB7, 0x9D726E3A, 0xE63600FD,
+ 0x7A68F80B, 0x1C5CCCA0, 0x1784B6A4, 0xBCA7EF08, 0x425ABF74, 0x3663AD11, 0x72F2AEC0, 0xA4A940F0,
+ 0xBBC08817, 0x5C158691, 0x7C1ECC0E, 0x1818BB5B, 0x0DE17D9F, 0x350D4BB6, 0xAC21F0FB, 0xB913C7B0,
+ 0xE9DC26F6, 0x25B995C5, 0x0D2E9E6F, 0xD39C93A8, 0x1C775CED, 0xF1E69A7D, 0x0025310F, 0x782BBDF8,
+ 0xFD3E83E4, 0xB5DD602E, 0x1CD9044C, 0x2AFC3405, 0x79E32E1E, 0xB59B4A79, 0x4609271E, 0x1C5E4D7A,
+ 0xA74D0009, 0x319A07E9, 0xCAC3A6FF, 0x8B515C07, 0xE80FE11D, 0x1D59CF05, 0x38F946AE, 0x6324D94E,
+ 0x313D3FE8, 0x310AF64C, 0x3CDE2571, 0x0644DA97, 0xEADBF286, 0x7B5DACA1, 0x8D5D3A54, 0x1376A003,
+ 0x51774091, 0x562A7891, 0xC246A9FA, 0x82C1C05F, 0x0D662D24, 0xAEDDA534, 0x5A96ED06, 0x2C055326,
+ 0xB0F2F5B0, 0x21C1F0F6, 0x6C39F1DE, 0xDE48E8FE, 0xB5CD1538, 0xC4E356AC, 0x1B24FE63, 0xF36D1426,
+ 0xB8B827D2, 0x1576F620, 0x3F49589E, 0xC438975C, 0x64880EDA, 0x7C322884, 0xD3978FBD, 0x4787B61E,
+ 0x2E192772, 0x0584B589, 0x0EAAA684, 0x6D81DE51, 0x63717598, 0x08A48B4D, 0x2DF88EC5, 0xA647285C,
+ 0xFC81F7AE, 0x10E48D34, 0x963F5C91, 0x8F592492, 0xC79010B8, 0x8A6D4936, 0x4759E38B, 0xACFC5255,
+ 0x0C9D02B7, 0x1B52A34E, 0x3B0A60A1, 0x1DB4E220, 0x23DCD523, 0xEA42AD41, 0x9B3CB86B, 0x6C503824,
+ 0x41DC835D, 0x22A311A5, 0x7B7AD03E, 0x6AFA5972, 0x3E506D92, 0x04FED79C, 0xCE801EEF, 0x7BA17C52,
+ 0x3AFFBB6A, 0x96A23185, 0x74316B7B, 0x11D330F6, 0x8484E528, 0xB643261D, 0xCC076540, 0x9116E092,
+ 0x4B6D5634, 0xC9532DCB, 0x0CBBB981, 0xE8D8E41F, 0x7573408A, 0x684F202D, 0x9A92649E, 0xF2CF0C39,
+ 0xF6C540AE, 0x29368636, 0x6A5BD7FB, 0x5044B256, 0x35AEC028, 0x8C12E363, 0xE0A2FE6D, 0x9E8EB149,
+ 0x2ED1CF45, 0x54A9880B, 0x4E295354, 0x83730F2E, 0x279AD027, 0x7051921F, 0xC4E219AC, 0x8B540A9B,
+ 0x947E9DF5, 0x28B61847, 0xC4E32434, 0xF9227028, 0x3D489511, 0xD5A41195, 0xA03EE1BD, 0xD761441F,
+ 0x402F7502, 0x5AB68BEF, 0x5555B735, 0x5918623F, 0x983735E9, 0xE332F1B8, 0x48D83C28, 0x81318EE2,
+ 0xABB8AA53, 0x01F0C3CE, 0xB4291A62, 0x89344F27, 0x5FDEEA6C, 0xE6D22F86, 0x9988C7DC, 0x051A1432,
+ 0xE11867BC, 0xEFA49EEF, 0x48AADD79, 0x33633BF3, 0xA56B57B4, 0xA253AB9F, 0x7FC8340A, 0xAB73B132,
+ 0xF1DFB6CC, 0xC5F02EDA, 0x426782CD, 0xF6648D35, 0xB4AB88A0, 0x9BA7B785, 0x67C03341, 0x22612D33,
+ 0xD32ED490, 0xAAA56F6A, 0x37ECD8CD, 0x518E8140, 0x7390301C, 0xB33A9E62, 0x244220D4, 0xD88AE216,
+ 0x9752DEEA, 0xB8A22F50, 0xBFB221CB, 0xDB4D57A0, 0x02D39A0D, 0x8C311F00, 0x1192748C, 0xB9505446,
+ 0x469C1E7B, 0x3AEFF9A6, 0x7CD5ABE8, 0xD849E5F5, 0x1E2FB30A, 0x18879BD8, 0x6DDD966E, 0xC9BD4B8F,
+ 0xCEEBCCD9, 0x0D881346, 0x20
+
+basegraph=
+2
+
+z_c=
+384
+
+n_cb=
+19200
+
+q_m=
+2
+
+n_filler=
+56
+
+e =
+36936
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_LDPC_RATE_MATCH, RTE_BBDEV_LDPC_CRC_24B_ATTACH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k40_r0_e17280_sbd_negllr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k40_r0_e17280_sbd_negllr.data
new file mode 100644
index 000000000..d98210ff6
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k40_r0_e17280_sbd_negllr.data
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x7f007f00, 0x7f817f00, 0x767f8100, 0x817f8100, 0x81008100, 0x7f818100, 0x81817f00, 0x7f818100,
+0x86007f00, 0x7f818100, 0x887f8100, 0x81815200, 0x81008100, 0x817f7f00, 0x7f7f8100, 0x9e817f00,
+0x7f7f0000, 0xb97f0000, 0xa7810000, 0x7f7f4a7f, 0x7f810000, 0x7f7f7f7f, 0x81720000, 0x40658181,
+0x84810000, 0x817f0000, 0x81810000, 0x7f818181, 0x7f810000, 0x81815a81, 0x817f0000, 0x7a867f7b,
+0x817f0000, 0x6b7f0000, 0x7f810000, 0x81818181, 0x817f0000, 0x7f7f817f, 0x7f7f0000, 0xab7f4f7f,
+0x817f0000, 0x817f6c00, 0x81810000, 0x817f8181, 0x7f810000, 0x81816981, 0x7f7f0000, 0x007f8181
+
+hard_output0 =
+0xa7d6732e, 0x61
+
+soft_output0 =
+0x7f7f7f7f, 0x81817f7f, 0x7f817f81, 0x817f7f81, 0x81817f81, 0x81817f81, 0x8181817f, 0x7f81817f,
+0x7f81817f, 0x7f817f7f, 0x81817f7f, 0x817f8181, 0x81818181, 0x817f7f7f, 0x7f818181, 0x817f817f,
+0x81818181, 0x81817f7f, 0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x817f7f7f, 0x7f81817f, 0x817f817f,
+0x81817f7f, 0x81817f7f, 0x81817f7f, 0x7f817f7f, 0x817f7f81, 0x7f7f8181, 0x81817f81, 0x817f7f7f,
+0x7f7f8181
+
+e =
+17280
+
+k =
+40
+
+rv_index =
+1
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_SOFT_OUTPUT, RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE,
+RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN, RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data
new file mode 100644
index 000000000..3472c992f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data
@@ -0,0 +1,643 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xCE000000, 0x2F00F6D9, 0xCC1AF942, 0x22F8F4E1, 0xBED8FAFF, 0x43DC19B5, 0x35E91CC0, 0x5B070D30,
+0xF9DACDFD, 0x170121DA, 0x012AEF53, 0x39E7D90E, 0xD5FBEFDD, 0xCCF0FDC8, 0xD62B0D54, 0xEAE601BE,
+0xE5001328, 0x0CF00DC7, 0x3EE0E4B8, 0xC2D8EB00, 0xBE1EEBF7, 0xCDF5E7E4, 0x4FDFF4FA, 0xF402DA2A,
+0xFEFEE32B, 0xD62CDA55, 0x17DE0106, 0xF92411B5, 0x301B2142, 0xE50C09E3, 0x51030EDB, 0x48DB2A4C,
+0x03E420BC, 0x1AE1DCF8, 0xB6EE0D3A, 0xC2FADF22, 0xBF211508, 0x3228E8AF, 0xE0170BEE, 0x26F8091F,
+0xDBFA02D2, 0xC810FE19, 0xE4DE1005, 0x18FF0D29, 0xE723F04B, 0xFDF2F1E7, 0xCF05DBD3, 0x0412F616,
+0x00DC234C, 0x1501EDD7, 0xD9EB4FED, 0x1C03BC2B, 0xE2FDF6D4, 0xE9EC10C4, 0x2426034D, 0xEDE33B45,
+0x05DC2304, 0xEDE81411, 0x11E416BD, 0x03D1DAA8, 0x04F72431, 0x30F15718, 0xF3F33534, 0xED043AD3,
+0x1CE8BC11, 0xEDE1EBF7, 0x242C0454, 0x0118D740, 0x07F3D01B, 0x0205D623, 0x15233E05, 0xF2EBE5ED,
+0xED2D3BAC, 0xEBF83CD1, 0xFCF9D421, 0x0B0934E0, 0x0A09E1E0, 0x1AEB0EC4, 0xF8FEDF26, 0xFCE8D53F,
+0x20E10846, 0xE327F5B1, 0x18E340F5, 0xF71ED0BB, 0x0EF5CBE3, 0xF4F11C36, 0x141BC343, 0xF4E7E5F1,
+0x30205809, 0x10EAC713, 0x22DBB603, 0x250AFC1E, 0xE4F3BB1A, 0x2316FA12, 0xDEE105F7, 0x12FDC7D4,
+0xFC212507, 0xDB290300, 0x1500ED00, 0x1EABBA27, 0xF14ECA2D, 0xF2D93625, 0x23F20502, 0xF0B9C8E6,
+0xEAD83EE1, 0x0C331CFF, 0x23D205F5, 0x0EC61906, 0xF128C9EF, 0xEF3CC800, 0x0B9DCDED, 0xF3C2CC3C,
+0x23EB04E9, 0x0B51CD13, 0xEADEC3D7, 0x222D06FB, 0xF0331904, 0x16C93F0C, 0xDAE5FE0F, 0x1F14B80C,
+0x001B28ED, 0x3F3B67F3, 0xEEEDE9EC, 0x1CE94514, 0x1D4145EF, 0xD8BA5019, 0xFC06D41E, 0x17BDC0DF,
+0x16D712E4, 0xE8041001, 0xEC2AEDDB, 0x11BE3803, 0xEBD2ECE5, 0xEF5A17F9, 0x2BFF52CD, 0xE958C126,
+0xEE1A1531, 0x0EBF1BF2, 0x18BC401A, 0x2AC2521C, 0xEE4817EA, 0x07482E20, 0x141314E0, 0xF41DCD15,
+0xDB10B40C, 0xC23700E9, 0x4221EB10, 0x4BE7E607, 0xEEF9DC0E, 0x62AC16DF, 0xE2E1C5D3, 0x27E4F70A,
+0x3213020D, 0x4ABE0A14, 0xACC1DE1B, 0xD636D416, 0xDFAF020E, 0xCE230828, 0x2615F6FB, 0xEA1002EE,
+0xD1351117, 0xB71C07F3, 0x03C9DF0C, 0x2B52DB0F, 0xD9AB02D7, 0xD20702D3, 0x48EEFB21, 0x3AE5E116,
+0xE728EE0E, 0x33C50F00, 0x363EF5EC, 0xD4FBF217, 0xB00FFDDE, 0x2333281A, 0x3624040C, 0x02DB0E04,
+0x3FDE27FD, 0x173716FB, 0xF20BEFF1, 0x3EF0191E, 0xB6B01719, 0x1BC7DD27, 0xE80AF3EE, 0x20BE101E,
+0xF42EF8E6, 0x40531BF9, 0x4646172B, 0x44DA1E1D, 0xC7F5E503, 0xF3E8F0E4, 0xA4E2E5EF, 0x42B935F6,
+0xEB1D1A1E, 0xE500ED0B, 0x2909F2CF, 0xCE0E0037, 0xD1320AA6, 0xEB01F9D9, 0x45E7ECC0, 0x4CFEE3D7,
+0x0EE024B8, 0xD3F31B1A, 0xE846056E, 0xF522EFFB, 0x5F1AE443, 0xCAF93620, 0x2CE9F23E, 0xDDE604F2,
+0x3BDDFC04, 0xC8EBEE13, 0xC11FF0F6, 0x18EBE9EC, 0xFAEEF1C7, 0xB6EFDDEA, 0xF8E123F7, 0x4EF4E1CC,
+0x430C271C, 0x3BE01CB8, 0xABE813EF, 0xCAEED439, 0xC1FAF3D1, 0x4E2F1656, 0x11E4DB0C, 0xDAF816DF,
+0x44E3FE0C, 0x2B1D1C0B, 0x3300FD28, 0xC320F4F9, 0x2A1DEB0A, 0xEA2502B4, 0x41061322, 0xC81518C2,
+0x1F2510FD, 0xD1E1F7F7, 0xBD1906F1, 0xF3C9E55F, 0xB3D91A4F, 0x0D0D26CC, 0xBD071B20, 0x41141BC4,
+0x2A1B19F2, 0x4902FDD5, 0xD6F9DE2E, 0x19190341, 0x09E80F11, 0x31FC1E2C, 0xEC1DF8F4, 0xCC0B14E2,
+0x51DFF3B7, 0x1AF028C8, 0x0F0E0E37, 0x2B041A25, 0x1A03FD25, 0xC5030FD5, 0xBCFAED22, 0x9A1F1CB9,
+0xCCE8C2F0, 0xEF1BF4BD, 0x21EC163C, 0xBAED07C6, 0x03F7E3D0, 0xC503DB2A, 0xC20C13E4, 0xD4F8EA30,
+0x391B0544, 0x59F3EECB, 0xAD0A311D, 0xFE0C2C33, 0x250CDBE4, 0xC5E80341, 0x3B0914CE, 0xC0F2ED36,
+0xC204182B, 0x3B0C16E5, 0xFFFF1429, 0xC316D8C3, 0xE408EB1F, 0x3713F4C4, 0xE4F2F01A, 0x0A280C01,
+0xEC0FE318, 0xCB16153E, 0x5C04F2D4, 0x281F35F8, 0xE4D80051, 0x4E0A0CE3, 0xB107DB21, 0xD1DED9FB,
+0x380AFACE, 0x50CC105C, 0xD9D80100, 0xF40ECCE6, 0xDADC03B4, 0x0AE5E243, 0x0C22E4FA, 0x08CD1F5A,
+0xE2D1F7A9, 0x12CE39A5, 0xFFDDD7FB, 0x032C2BAC, 0xF1D9E700, 0x14003B28, 0xFC08D420, 0x08093131,
+0xFEFFD7D7, 0xBB219348, 0x07DC2E4C, 0xDF0DB8CB, 0x22EB06EC, 0x0BE034F8, 0xF10FC819, 0x1623EEFA,
+0x0D1DE6BA, 0xDA1AB142, 0x1C16F4EE, 0x27F500E2, 0x1137C85E, 0x1C0BF434, 0xF004C924, 0x02EBD9ED,
+0x1BF943D2, 0xE7F80F30, 0xEFFE39D9, 0x2CFA5323, 0x04242DFB, 0xF420E347, 0x15F43C33, 0xE9F41134,
+0x20EBB8C2, 0x0205D523, 0xECE03DB8, 0x10F3E935, 0x180BC11E, 0x12E2C7BA, 0xE70B4233, 0xEED8EAB0,
+0x110E3936, 0xFEE327F5, 0x12E60017, 0xFE4026F3, 0xED26C518, 0xE5E9F2FF, 0x200C08EE, 0xEF1439E4,
+0xE92010ED, 0xE1B80908, 0x18584021, 0x24FBFC31, 0x00AE2823, 0x040CDC2A, 0xDE34FBE5, 0x1439C30D,
+0x0DB7E6EF, 0xE6090F21, 0xECAF3C20, 0x10DFE8D8, 0x0CC0CCF9, 0x15061318, 0x043723DD, 0xEA3A3DF0,
+0xEC18C413, 0xFE2BD611, 0xE3BC45FE, 0x16FCC11D, 0x120E39DC, 0xEC00141B, 0x13F03B27, 0x24D2FC18,
+0x0917E1FB, 0x113BEAEE, 0xE9FE11EE, 0x2C505427, 0x0D0B3529, 0x15E73E1E, 0x0FD91AF1, 0xDFF8B6FF,
+0xF413CCE1, 0x1EEFB9EA, 0xDCD04C17, 0xCEC25AF8, 0x1AB2BE17, 0xD8BEAFDA, 0xE6CEBD19, 0xFCC42CF6,
+0xDE19FA15, 0x250203F2, 0xA90042DB, 0x242A2F1A, 0x004D0401, 0x0B4C2825, 0xACB61DDD, 0x07422CDE,
+0xCDFEDFE7, 0xAFF8F527, 0x35052820, 0x0B34F2DD, 0xD648E2F3, 0x3DDF02E0, 0xFE42EBF8, 0xC1F6251A,
+0xBA0DE9E2, 0x442FE2E5, 0xD014E308, 0x2DB409EC, 0x50F8FADC, 0x264BD8E0, 0x2E0FFEDC, 0x1E2D051A,
+0x0FD20AFB, 0xCE1CE7FA, 0x35CDF6F4, 0xFC49F3F4, 0x642FDCDF, 0x3625C507, 0xDF140FFC, 0xDB21F913,
+0xC7D5FDF9, 0xCEE112FE, 0xD1D4F7F8, 0x5D410704, 0xD914CC19, 0xCCF800EC, 0xE3E00C1F, 0xCD05F408,
+0xC952F4DD, 0x444EF02A, 0x1E15E526, 0xD73909ED, 0xFA1900EF, 0xFFB6210F, 0x06EB27DE, 0x0B5BDF13,
+0x1B4F1D33, 0xCDF5F4D9, 0x00F40C1D, 0xC6031CDC, 0xF91C13F4, 0x061321C6, 0xBFDD2206, 0xEE13193C,
+0xFF1C17BB, 0xA91E27F5, 0x25ECD13C, 0x0CF90321, 0xBA1FE5B8, 0x50151F3D, 0xE935285D, 0x330A10CE,
+0x3EE6F542, 0xE80AEA1E, 0x45251103, 0xC014E3EC, 0x2D2C1854, 0x9F0E0536, 0x2E14C7C3, 0xECE50642,
+0xE6E214F7, 0x1021F208, 0xBCDC19FB, 0x4B281BFF, 0x0CDFDEB7, 0x21E91CEE, 0xC22FF856, 0xA2F3EAE4,
+0x5810CB18, 0xE416D03E, 0x25E3F40C, 0xF4180340, 0xFE0EE4C9, 0x433C2763, 0x38F11BE7, 0xE5FC11D4,
+0x1E11F4C6, 0x491D0ABB, 0xC0E72140, 0xB226E84F, 0x122E26AB, 0xEAF116E7, 0xD5E4EE0B, 0xF4FB0323,
+0xDCE61D42, 0x05F1FCE7, 0x0DDCDDB4, 0xF9E42000, 0x181610EE, 0xE1F246CA, 0xEDEDC53B, 0x14DEC5B6,
+0x1E02F629, 0xDEE749F0, 0x1C02BDD7, 0x1EF3F5CB, 0x11E8C640, 0xFA272301, 0xF3FC352C, 0xFDD52553,
+0x09191FF1, 0xDB11FEE9, 0xF7EB1FEE, 0xFFF9292E, 0x0A2032B8, 0x0C1BCDBC, 0xDDFFFBD9, 0x1BEABDEF,
+0x19F84130, 0xECE5ECF3, 0x271302EB, 0xE7EB423D, 0x1E2146B7, 0x14E13CF7, 0x16FE112B, 0xEB211308,
+0xDAD802B0, 0x0017D811, 0xFE26D901, 0x0D0ACBE2, 0xF2ED1A3B, 0xFBDED206, 0x18F0F1C8, 0xD1EFA9C6,
+0xE5E1BDF7, 0x1514C314, 0xF9FCD1D3, 0x02EB2BED, 0x0EEB1BC2, 0x2427B5FF, 0x0B2233FA, 0xFE0FDBE8,
+0xF7DDCE04, 0x03F42BE3, 0x0525D202, 0xF9B20021, 0xEF0FE926, 0xF505E318, 0xF7DF1F23, 0xEADF12F8,
+0xF12C3807, 0xDF01FA04, 0x1D23F426, 0xF1231A05, 0x20F549FB, 0xE0F0F9E3, 0xDB67B418, 0xC6E5623F,
+0x212AF90D, 0xE6C7BD02, 0x24CA4C11, 0xE249F6F1, 0xE8383F21, 0xFC212310, 0xF7561F07, 0x25C4032E,
+0x070EDE14, 0x1437151A, 0xE93C4010, 0xF10CE615, 0xDB0D4D1C, 0xFAF6221B, 0xF5F3E21E, 0xE2470B1B,
+0xE71BC01F, 0x07B0220C, 0xF311CAD8, 0xFF052816, 0x1DC20BDC, 0xE7BB40EB, 0xF5DEE21E, 0x013527FB,
+0x0FF519F2, 0x1AE9BDE4, 0x2B0F53F0, 0x13C6C5E8, 0xF12636ED, 0x10BD38FE, 0xDD0606E4, 0xDA5C4FDE,
+0x1329C5CC, 0x0DC8CA00, 0xD33956F0, 0x0700D711, 0x31B1DE02, 0x210C09D9, 0x0C2EF81B, 0xF5FFE406,
+0x27C1E2DA, 0xCB1801E8, 0x38C70EF0, 0x0D1EF0EF, 0x142E1C0B, 0x0B00EB06, 0x5D441DD8, 0x1E4035E5,
+0xFD3C0AE8, 0x3732DCEC, 0xC8B5F00A, 0xB9BF1023, 0x0AF22018, 0xC6DDE21A, 0x18EF1306, 0x1AC8F1E9,
+0x1F020EF0, 0xEA0209DB, 0x41CFEEDA, 0x21E31AF8, 0x4BBD070A, 0xEECFDD1A, 0xD4DB15F8, 0x430FFC02,
+0x15361A18, 0xCF17ECF1, 0xE42009EF, 0xC21CF4F8, 0x3DDFEAF3, 0x3E0916F9, 0xF028151F, 0x03CA1700,
+0x983B26F1, 0xDE2AC112, 0x209FF9FD, 0x1935F7C6, 0xED18F1F3, 0xBFD0EA0F, 0xC5071908, 0x1F4E13DE,
+0x17F00926, 0xF80DEE19, 0x4DF01FE6, 0xB7D2DB18, 0x0AF5E0F9, 0x4043E21D, 0x4AD517E5, 0xB0CFDE03,
+0xFB22D90A, 0xDF5023F9, 0xDABDF828, 0x1911011A, 0xBDF30FE8, 0xCEAA1A1A, 0xB0D2F62D, 0x3AAC28F9,
+0x42D6ED2D, 0xA83D1B02, 0x1831D1EA, 0xF11D10F7, 0x1D201AF5, 0x394F0C07, 0xB327F0D9, 0x3254DA01,
+0xEBF40AD5, 0x26A413E4, 0x5113FECC, 0xD4F32915, 0xDDB3FD1A, 0xC0D2FB25, 0x02DEE7FB, 0xC33DDB05,
+0x01021615, 0x0B1D27DA, 0xCBC2E2F6, 0x193CF3E9, 0x27E2F1EC, 0x5A1BFF0A, 0xE8CF320D, 0xBD4DF0F8,
+0x0F291A26, 0x1817E7FF, 0xEFCB10F0, 0xD40CE9F3, 0x0606041B, 0xFABC2322, 0xE0E9DEE5, 0x1BD80710,
+0xC015F301, 0x4718E8EE, 0x69D81E11, 0x19F6BF00, 0xF60F1E00, 0x3002E225, 0x29EA08C1, 0xF4EA00EF,
+0x3910E5E7, 0xDB0B12E4, 0x2A3E0265, 0x3BE8FE11, 0xBBEFEEE9, 0x151BE2BE, 0x1E2314FB, 0x4C2DF754,
+0xD5F823E0, 0x10200247, 0x01DB194D, 0x1B17D93F, 0x5806F42E, 0xFA19D040, 0x040BDF1D, 0xFCCB25A4,
+0x39D9DC00, 0x2C0EEFE7, 0x20F3FDCB, 0xC2E70841, 0x3EEFEAE9, 0x32EDEAC5, 0xAC1BF70D, 0x0C15D4C3,
+0x4CE7E5BF, 0x26F024E9, 0x061AFE0D, 0xDE13DEC5, 0x09DE0706, 0xFC0C1FE5, 0xD41CDC0B, 0xCC1DFBBB,
+0xC6020CDB, 0xCD16133E, 0x3FF30CCC, 0x0B2D16AB, 0x3800E3D9, 0x3AFCF0DC, 0xE4FFED27, 0xFCF9F3E0,
+0x05FF24D9, 0xE1F9DE2F, 0x391908F2, 0xC8F211CB, 0xEAEF003D, 0xDC1C040D, 0x25F74ECF, 0xE41F0CBA,
+0xDF1708EE, 0xE016F83F, 0x1D124515, 0xF325344D, 0xE114F63C, 0x261FFEB9, 0x02F02739, 0xF12018F8,
+0xD9124F3A, 0x1E1A45F3, 0x1504142C, 0xDDF506E3, 0xEAEAC113, 0xDE1AFB42, 0xF113C93B, 0x1721C207,
+0xE3D4BB54, 0x070A2FCE, 0x0C0AE41D, 0xF90D3035, 0xE6DCF2B4, 0xFB15D4C3, 0xFE2425FC, 0x03002B28,
+0xE50AF433, 0x07EC2FC4, 0x07E921EF, 0xFE09DAE1, 0xE21EF6B9, 0xF3E6360D, 0x17EE3F39, 0xE7FA0E22,
+0xF5151DED, 0x1EF945DE, 0x0D1236EB, 0x0AFD32D6, 0x0928CFFF, 0xDCDAFD02, 0xFB272D00, 0xCE025B25,
+0xEA0D3ECB, 0xE3E2BBF5, 0x06D32354, 0xF4DDCCB6, 0xE4002245, 0x213AB706, 0xECCCC3ED, 0x3CED9C0B,
+0x15D23C14, 0x0BE7E3F9, 0x1FE70A0E, 0xF30D350F, 0x1928F01B, 0xD50AAE01, 0x120AC6E1, 0x0ED4C91E,
+0xFFF7D804, 0x0D0CCA1F, 0x0433DBE4, 0xEA0DEFF5, 0x36FB5E1C, 0xEB11ECDC, 0x23C0FB17, 0xEBC63C17,
+0x272800EF, 0xFC34D4FF, 0x0AB8E2F5, 0x01FB2AE0, 0x090630DD, 0xFE0AD522, 0x1B10BD1D, 0xDF520719,
+0xF12436D5, 0x1D20BAFC, 0xE442BCF8, 0x05E0DDE6, 0x183FF1F8, 0xF816E118, 0xE3C9F4EE, 0xF2F51AF0,
+0xFE5126E4, 0x1E31F7D7, 0xF9362F09, 0x15E43CF2, 0x0D3EE50C, 0xF74931EA, 0x23EEB621, 0x02B9DAE9,
+0xDFE5B71F, 0xFD46D50D, 0x103E181F, 0xDF580717, 0x00C3EC31, 0x0CF714EC, 0x4ACCE41E, 0xF2E0DEF4,
+0xB0431A08, 0xBD38D8E6, 0xEED6E510, 0x41B8EA02, 0xEC36E61F, 0xBEE9EBF3, 0xBE28E712, 0xF6051BFF,
+0x2FE5E222, 0x2ADCFAF2, 0x3834FF04, 0x2AD1100D, 0xF4C502F8, 0x4DE7E414, 0x07A5DA10, 0xD1A92133,
+0xB6ACFAD2, 0xCF51222C, 0xCD1BF8D7, 0x3F16F50E, 0xEEF4EA12, 0xA52F161D, 0xC4B3CE07, 0xB622EDDC,
+0xDE2ADE06, 0x4FC8FB02, 0x6EDED9F1, 0xFC19B9F9, 0xD5B4DDF1, 0xDFC30423, 0xDFFBF9EA, 0x012C07DD,
+0x12AF2805, 0x1A2EEAD6, 0xF8A1F207, 0xC0BA21CA, 0xFFDCE9E3, 0x36BFDA03, 0x05DD0E19, 0xF905DDFB,
+0x32AEDF23, 0xFDFB09D5, 0x45D5DA23, 0x4B3E1CFD, 0x0905DDEA, 0xDFE2DE00, 0xB1FB07DD, 0x33EA2813,
+0x02ECF5C3, 0xED0CD91B, 0x0D1BEABD, 0x4A17E5C0, 0xF707DFDF, 0xEE191F41, 0x19EC15C5, 0x4112F1EB,
+0xD4F01AE9, 0xBF21FC06, 0x19DCE605, 0x2F0C10E4, 0x181FF947, 0xC00AEF1E, 0xF72EE8AB, 0x42F8E2E1,
+0xA3EFE7C7, 0x31133514, 0x1EF608E2, 0x0DECF6EC, 0x0CECE5C5, 0x3DD31D54, 0xECE21545, 0xAE0CECE5,
+0x49202B08, 0x0EFE2026, 0x13F41B35, 0x1B0BEB32, 0x1719F30F, 0xECDAF0FF, 0xECE9ECC0, 0xF212EC3B,
+0x3DE8E6EF, 0x13F2EB1B, 0xB008EBE0, 0xBAE22845, 0x1A111DEA, 0xDBFC0EDD, 0x3F29FE50, 0xCDF817E0,
+0x4B030CD5, 0xEADCDE05, 0xC31312C6, 0x272EEAA9, 0x340201DA, 0x17F400EF, 0xED1F1608, 0x24D24B55,
+0xF4091DCE, 0xF51633C2, 0x03D32B56, 0x2325FA4D, 0xDEDA05FD, 0x01F72831, 0x04F12C19, 0x2716B1C3,
+0x1B19F3C0, 0x10E2C909, 0x050C2233, 0x03F22519, 0x1C06F422, 0xE7D70EAF, 0x03D725AF, 0x13EC14EB,
+0xF6F631E3, 0xF900DE28, 0x1FE2F7F6, 0xFBE9D2C1, 0xFBEFDDE9, 0xE110F7C8, 0x1C290C50, 0x27D9FFFF,
+0x07E421BB, 0x3BE89CF0, 0xF50733D0, 0x2514B2EC, 0xF5EB1DED, 0x0619D241, 0x1FE8B840, 0xEEEA3B3E,
+0xED1F1648, 0xFF15D73E, 0x0123D805, 0x0310D5E8, 0x010ED819, 0xECE53B43, 0x03E1D547, 0x01D9D6FF,
+0xDFE3B745, 0x1C14443C, 0xDF0908E1, 0x03FE2ADA, 0x1306C5D2, 0xDD001004, 0x1F3AF818, 0x1A3BF3ED,
+0x1EBC47EE, 0xF83E1F1B, 0xE21445EA, 0x2101B713, 0xE81AF126, 0x1930BFF3, 0x1533C408, 0xEDBFC60C,
+0x060F2EE8, 0x06BDD11A, 0x04F524E4, 0xD94C001E, 0x0334DCDD, 0x06F1D30C, 0xFBDBD219, 0x0EBE1A03,
+0x08D230E5, 0x250B4DFA, 0x0903311C, 0x14233C25, 0x1ABAF205, 0x30C5581D, 0x02FAD712, 0xDF2108DE,
+0x02DDDB07, 0x1D47F606, 0x0EEF191F, 0x1B3AF2E9, 0xF9E52E12, 0xF0B1C8F4, 0x290CAF28, 0x0013D8E5,
+0xE1B50AEC, 0x1A224322, 0xFDE8DB06, 0xF8A531EF, 0x0DD1CCCD, 0xE81AC007, 0x201048F3, 0x1800F1E8,
+0x000BD8D9, 0xEC2A13E2, 0xF3EE3502, 0x282F0117, 0x08F8E006, 0xFE542620, 0x19E9C0D3, 0xDD140412,
+0x1119C6EB, 0xF6C2E10E, 0x1EC50BEB, 0x15BD13ED, 0x143DC51B, 0xE5F2BE14, 0xF552E41A, 0xE10FF62A,
+0x2A0B5218, 0xE33A0CE2, 0x02D7D612, 0xE1A7B800, 0xD8C10031, 0x0810E0E9, 0xD93AB0E8, 0xF8113011,
+0x15B73C17, 0xFE46D520, 0xF6C51EE3, 0xD51A52ED, 0x1A0ABD0E, 0xFBF8DEE2, 0xE245BA20, 0x2225FB1E,
+0xEC3A3CFD, 0x19340EEE, 0x08FE20F4, 0x1F154727, 0x05F8D213, 0x16F2EEE1, 0x22B6FA1A, 0xF404CCDF,
+0xE22E4624, 0xFB3FDDFB, 0xE6F7BF17, 0xF0B6E71F, 0xF013E723, 0x17081114, 0x24EBFCE0, 0xFBE52DEC,
+0xE9C310F3, 0x26F04E15, 0xF145E8E8, 0x122B17E2, 0x0D40CCFD, 0x43CA96E8, 0x421D0F00, 0x27DCE70B,
+0x233B00FC, 0xCC44FAEE, 0xE0BC0BE3, 0x1BE7071C, 0x01C7F20F, 0xB29B28F0, 0xFB02DBC4, 0x32092326,
+0xE648F5E2, 0x4707F2DF, 0xDF36E2E0, 0x1CC308F2, 0xBBA50DEB, 0x1DE71D34, 0xCE36F5F1, 0xCDF90AF2,
+0x0FDE0CE0, 0xCF0C1906, 0xE0E509E4, 0xBC37F9F3, 0xDA06E510, 0x1FD3FDDF, 0xDB09F705, 0xF445031E,
+0x24311CE2, 0x55EEFDF8, 0x3CEDD216, 0xAFF01516, 0xCA3D29E8, 0xCCAEF1EA, 0xE0F60CD5, 0x4CECF7E2,
+0xDCD5DBEB, 0xAEC2FC02, 0x4825D7EA, 0x252D2004, 0x24F604FB, 0xD9D7051F, 0x1AF201FF, 0x3DE70EE6,
+0x43BCEC0F, 0x43D8E5E4, 0x20EB1BFF, 0x2AAFF814, 0x021A02D8, 0xD80C26F2, 0xDB00001C, 0x2BF2FCE6,
+0x181F0347, 0xAFE8F0F1, 0xE31D2A0B, 0xD015F4C2, 0xEF02072B, 0x361717EF, 0xFA25F2B3, 0xEEFADE22,
+0xEE21EBF8, 0xD6F5EA1D, 0xBF160212, 0x03E6190F, 0x452126B7, 0x32D91DFF, 0x2D000A28, 0x25F205CA,
+0xDEED043B, 0x36DCFA04, 0x13EAF112, 0x141915F1, 0xF2F0EC38, 0xBC20E6F8, 0x0BF2E519, 0xD0F11D19,
+0xC7F6F932, 0xBFE2EFB9, 0xA4F919DF, 0xFFEACCEE, 0x3BDBDAFC, 0x2B1E1245, 0x5CEBFC14, 0xDB10CD18,
+0xB718FE40, 0x0BE92012, 0x2414E2C5, 0x3B09FCE0, 0x17DF1306, 0x212F12A9, 0xC71407C4, 0x0901EFD7,
+0x22EAE23F, 0xE7E805C1, 0xC6F21037, 0x4A111218, 0x1AEC22EC, 0x27E30EF6, 0x0C000134, 0x1BF10D37,
+0xFD1F2A09, 0x1AEFF3E9, 0x160F3EC8, 0xEC173B3F, 0xE8F711E1, 0x050A22CD, 0x15263DB1, 0x07012127,
+0x1D22BBB7, 0x34E3A5BB, 0x19210FB8, 0x17D41254, 0xD822B1FA, 0xE6DE0E06, 0x1519ED40, 0xDDE54CBE,
+0x1EFC0BD4, 0xFE0D2A35, 0xE8EF40C7, 0x09E5E1F3, 0xF60631DE, 0xD6EDADC5, 0xE61A0FBE, 0x091C30BC,
+0x0514DE3C, 0x1D1A45BF, 0x03E0DC08, 0xF4FE1C25, 0x1D260BFF, 0xF6FD3126, 0x1013C8EA, 0xFE18DB3F,
+0xDF114916, 0x1806BF2D, 0x0E0535DC, 0xE5ED0DEB, 0x1EE445F5, 0x16DC12B4, 0x23FA4B2F, 0xFFD6DAAF,
+0xECF714E2, 0x273D0066, 0x1B15F313, 0x1D0CF533, 0x17003E28, 0x1FD3F654, 0x00EFB117, 0x1C13BBD9,
+0xF5C21D15, 0xF1CF3715, 0x244A0309, 0x09321FDD, 0xEFF81609, 0xE1ED091F, 0xFDFA2A16, 0xF742D022,
+0xDCECB51B, 0x16FAEE14, 0x140C3C21, 0xEA0AED1B, 0x24E94CE2, 0x17E03F12, 0x1E01BAF9, 0xE82E4128,
+0xEE311506, 0xF7FEE1F6, 0x0661DFD9, 0xDFB1FAC8, 0xFF282928, 0xEA3412FF, 0x104FC80C, 0x00ABD927,
+0xEE32EA2D, 0x153B3D09, 0xFCB82DEC, 0xE9E8C021, 0x09BECEF0, 0xFCCA2D19, 0xDF09F90F, 0x013F2AE1,
+0xFC44D4E9, 0xFD24D6E5, 0x1C0CF3FB, 0x2601021C, 0x1AB6BED9, 0x04B7DCDD, 0x102BC8E0, 0x09331EFC,
+0xE8ACC1F5, 0x222E4BD4, 0xF715E1FA, 0x23484BED, 0xEB3913E0, 0xDFE4B711, 0x0C411B0D, 0x18FEE800,
+0x42231127, 0x493B19FC, 0x39BCDE12, 0xFB46121B, 0x452DDDE2, 0xEA0DE3FB, 0x2109EF1A, 0x1B3CF81E,
+0xE228F2EC, 0x48ADF6FF, 0xC2C0202C, 0x9F3FEB19, 0x192BC8E9, 0x2B0F0F04, 0x4F2DFD19, 0x1045D9FB,
+0x0B3FE8E2, 0xF2FBE316, 0xBC0EE623, 0xB301E419, 0x1F2226D9, 0xBE0009FA, 0x27121A27, 0xF95002EA,
+0x4714DED8, 0xBAE6E1ED, 0xC5191EF2, 0x3B2E14F1, 0xFB0FEC06, 0xDAB123E7, 0x3DDBFFD9, 0xC318ECFD,
+0xDFD014EF, 0xB23D0608, 0x11E326EB, 0xC4CAE90B, 0xD847EC0D, 0xDFC3FFE2, 0x55BD0815, 0x17F9D3E5,
+0x3EE91121, 0xF9C41712, 0x22AFE0ED, 0xCDE7FBD7, 0x1BC9F5F0, 0x0422F4F0, 0x200EDC06, 0xC3F700E6,
+0x3B20EBF7, 0xD115EDEE, 0xC3ED08EA, 0x5AFEEC29, 0xC21F3247, 0x3315163E, 0xE330F659, 0xEAF5F5CC,
+0x1716113E, 0x4CE611BF, 0xD517DBC2, 0xB2EF043A, 0x45DD25B5, 0xC0151E13, 0x131CE843, 0xFFE4EB44,
+0x5FFB27DC, 0x381336EB, 0xB8EFF017, 0xECF720CF, 0x200B131D, 0x0622F805, 0xBA07DD30, 0xD9061FDE,
+0x30EA013D, 0x40300858, 0x9AD917B2, 0x270FC1C9, 0x1209FFCF, 0x201716EE, 0x2A050723, 0x1BEF0239,
+0xBF18F310, 0xA83719A0, 0xA9DDD105, 0xE70F3037, 0xDE0D0E1B, 0xE1D4F955, 0x0CF00AC8, 0xE80FE4C9,
+0x1BE2100A, 0x40FB0EDC, 0xDD1A17BD, 0x4E1604C2, 0x5CE7270F, 0x2BF635E3, 0x00D80350, 0xFD0027DB,
+0xDD22B54A, 0xEAE11247, 0xF705CE22, 0x01F2D736, 0x1D17443E, 0x1D0145D8, 0x18181111, 0x04FEDCDA,
+0x01EAD7C3, 0x05DC23B5, 0x1FCFB959, 0x1A0A431E, 0xFCDC2CFC, 0xD61452EC, 0xECF23DCB, 0x31D6A652,
+0x261BFE0D, 0x0CD73552, 0xEAFB11D3, 0x10291952, 0xF7F41F34, 0xEC1E3CF6, 0x180A41E2, 0x03FBDB23,
+0x2026F9B3, 0x0C02E42A, 0x08F030C9, 0x0E19E70E, 0x0F1519C4, 0xDCE703F2, 0x100CC833, 0x0105272C,
+0x01252903, 0x0DCCCB5C, 0xD21AAA0E, 0x2917AFC0, 0x1BEA0E3F, 0x2A1B52BE, 0xF2E8CAC0, 0x1DDDBB4C,
+0x0215D73D, 0x0DF7E5E1, 0x08E230F5, 0x0EDFCA4A, 0x19FE0ED9, 0xE6EC42C4, 0xFB1D23F4, 0x22090632,
+0xEA073F21, 0x06ED2115, 0x180BBFCC, 0xE6E20EF6, 0xE512F23A, 0xE21BF7F4, 0xF9F22E37, 0xF82B2F53,
+0x1CF94421, 0x16D8C2B1, 0xD9F4FF1C, 0x23EC4B14, 0xF5F03339, 0xFE172B40, 0x1C2F0D57, 0x230A0632,
+0xECDA3CFD, 0x1306C52D, 0x01D3D856, 0x1D2846FF, 0xF9D82150, 0x1B0CF31D, 0xEE03C626, 0x1AFFBED8,
+0xD605AEDD, 0x2403FD25, 0x01EC28C3, 0xF1E1C8F7, 0x06E7D140, 0x09CF325A, 0xF2151AC3, 0xE7F8F120,
+0x0A2BE353, 0x23E5FBBD, 0x1C1645C1, 0xF716D011, 0xF6ED1D15, 0xFB2123B7, 0xE2070A2E, 0x16F7C2E0,
+0xE6100D18, 0xFB19D440, 0x2FF15619, 0x1F0FB938, 0x0101272A, 0xF8F42F35, 0xF3DFE649, 0x21E549F4,
+0x0D430000, 0x400EE51B, 0x452E181A, 0xF1411DFB, 0xF4DC1919, 0xF247E3FC, 0x33141AE1, 0xF81CF515,
+0x3115200D, 0x3FCFF713, 0xE9DA17F6, 0x0BF31102, 0x17D1E3E5, 0x0E9712FA, 0x2EAFE6C0, 0x5900F928,
+0x50D8CE27, 0xCDACD9FF, 0x41BB0B2B, 0x2AC9181E, 0x13E1020F, 0x0708EC08, 0x09D220E1, 0x1EC0E206,
+0x1F2BF6E9, 0xD23809FD, 0x46D3FBF0, 0xF617E2FB, 0xF4F61EEF, 0x31D71BE2, 0x1AD4F7FE, 0xB534F103,
+0xDE15DD0C, 0xC7FBFA12, 0x1931F0DC, 0x4AD8F1F7, 0x4937DEFF, 0xF908210F, 0x35D121E0, 0xECCC0EFA,
+0x34CBEDF5, 0x062A0CF3, 0xE4B12103, 0xD73DF427, 0xDCE8FE15, 0xB4FC04F0, 0x0B06DC23, 0x16391D22,
+0x23051310, 0xE6FCFADC, 0x1C95F2DB, 0xE3DE0DBD, 0xDB270A05, 0xB4EEFC00, 0x1845DD16, 0x0149F11D,
+0xC6D52621, 0x1E34EE03, 0x17D20AF4, 0xA10611FA, 0x20F937DE, 0x5D17F8DF, 0xA00435EF, 0x3ECEC7DC,
+0xF9D8EB0A, 0xFC332200, 0x1DE9DBF5, 0x2E580CEE, 0x3E1AF9D1, 0xC64715F2, 0xD7CB121F, 0xEFF400F2,
+0x084CEAE4, 0x064DE0DD, 0x2B10DE25, 0xC1FB0218, 0xD4F8EADE, 0x32D6FBE1, 0x0F65F602, 0xEC32E83C,
+0xD2F613F5, 0xC526F9E1, 0xF0F51302, 0xF5B017E3, 0xFA0FE4D7, 0xFACBDFE8, 0xC0F222F2, 0xD630E81A,
+0xD6DEFEF8, 0x33A602F9, 0xC826F633, 0x10E51002, 0x0308E9F3, 0xE011251F, 0xBAEAF8EA, 0x26F21E12,
+0x0000021A, 0xE00E08CB, 0xE0ED0715, 0xE71CC0F4, 0x0A1ECE0A, 0xDB260303, 0xE7E2BEF5, 0xDDE705F0,
+0xDA0BFEE3, 0xF6D83250, 0xF4FA1CD3, 0x2805FFDC, 0x1DDBBAB4, 0x1611C218, 0x18E13F09, 0x1C1D0DF5,
+0xDC25B403, 0x2BF6AE32, 0x180F4136, 0x39FC61D3, 0xF3DE1BFA, 0x1AD94100, 0xE8F8BFDF, 0x0826E0FE,
+0x1AE142B8, 0xF80F20C8, 0x0116D9EE, 0x22E84BF1, 0xEB22C3B6, 0xEE01EBD7, 0x0EE8CA10, 0xD8FA00D1,
+0xEB073DD1, 0x1EE3BBBB, 0x12EFC639, 0x3708A121, 0xDFDB49B3, 0x28D85000, 0x0C003429, 0x000D28CA,
+0x12D1C6A9, 0x0D061B2D, 0xEBDCC304, 0xEF05C8D4, 0xDACD02A5, 0xF3F7CAE2, 0xE5144313, 0xFC222B4A,
+0x23F4B51C, 0x18270FFE, 0xEDDC3CB4, 0xE9213F49, 0x1EF309CB, 0xE3E5BB44, 0x0AF6E333, 0xE1EF473A,
+0x080DD036, 0x0FEB38EE, 0xFE0629DE, 0xDAFCB224, 0x0DF9CB21, 0x07D3DFAC, 0x06F822D0, 0x1E1ABAF1,
+0x00F32835, 0xE00AF71E, 0x08E2D009, 0xE003F9D5, 0xD5F2AECA, 0xF4EFCCEA, 0x0B0E33E5, 0x0D271A00,
+0x1232EB59, 0x07DBDFB4, 0xD2ECAAED, 0x17FC40D4, 0xDAEB0313, 0x07E8E010, 0x07F5201E, 0x13173CC1,
+0xDBDCFDFD, 0x24ECFBC3, 0xF2D9E6FE, 0x420695DE, 0xFC172C11, 0xDF0F06C9, 0xF413CC3C, 0x1B11F217,
+0xE01148C7, 0x1EEEBA3B, 0xDDDCFCB3, 0x24E1B4F6, 0xF4DA3303, 0xF1FC192C, 0xEAFC11D4, 0xEAD41354,
+0x22ED06EC, 0x23090000, 0x0BE7FBE1, 0xE0BFE4F0, 0xF2C4F818, 0xE5BEE6EC, 0xDD3E0DE7, 0xEB360516,
+0xFBC6ECF2, 0xFCEC23EE, 0x0A20DD13, 0x12211FF8, 0xF23A1706, 0xCC36E6EF, 0x1C26F5F2, 0x2F05F303,
+0xF540FA23, 0xFE4FE3E9, 0x23CED927, 0x18C2FA0A, 0xD1A411EA, 0x1A4306CB, 0x474E0EE6, 0x21331FDB,
+0x2C33070B, 0xC60804F6, 0x515A12DF, 0xE8FDD7CE, 0xD7171126, 0x1043FF11, 0x48F8E81C, 0xCF48E021,
+0xF9CA09E0, 0x2B26210F, 0x1F10FD02, 0xC9ECF8E7, 0xF9D30FED, 0x33222205, 0xC44E0A05, 0x41381425,
+0xCEC21811, 0xCFFFF5EA, 0xC0E7F727, 0xF5481810, 0xE247E3E1, 0x11150AE0, 0x40C116EE, 0xFDEC18E9,
+0xCF0F2415, 0x46E5F6E6, 0x430D1DF3, 0x11EEE61A, 0xA45017EA, 0xF1BBCB28, 0x35DC19E3, 0xECBC0CFB,
+0x3631ED1D, 0x202C0EF8, 0xE7D2F8FC, 0x441910FA, 0xBED4E4F2, 0xCE3DE6FD, 0xD8CB0B15, 0xDE3C01F2,
+0xD7F1F914, 0xFDCE00E7, 0xBDEF240A, 0x2CC5E616, 0x1C16FCED, 0xE805F412, 0xE4F11023, 0x14110DE8,
+0xE2ED1418, 0xD7F7F6EC, 0xF8E9001E, 0x18C3E111, 0xAA4BF1EA, 0x2BB02DDE, 0xEB18FDD9, 0xEECFED11,
+0xAEF8E9F7, 0xB0D129E0, 0x1952D9FA, 0x07D40ED6, 0xB13EDF03, 0xC74C28E9, 0xD7DB12DC, 0x0B11FFFD,
+0xCEFC1D17, 0xC34CF623, 0x4A011523, 0x0410DDDA, 0xF2072317, 0x33101B21, 0x35F7F4E7, 0xF2CBF3E0,
+0xAACDE6F4, 0x00002F0B, 0xE51344C5, 0x1211E938, 0x091EE1F6, 0x26CD02A4, 0xE028F84F, 0x2522B206,
+0x1BFDF3D5, 0x0C23CC06, 0xE809C031, 0x19D30F54, 0x1B0DBD1C, 0x2EE256F5, 0xE11A080E, 0x17DF11B8,
+0x16E4C20C, 0xEECA3B5F, 0x05EA2D11, 0x140AC432, 0xE0F6481D, 0xE024094B, 0x16F6121D, 0x14083C20,
+0x200A481F, 0xE1F308E5, 0xFB0623D1, 0xDE1EF946, 0xEE211606, 0x15EC3D13, 0xF402E4DA, 0xF1D8E700,
+0xE6D0F358, 0xEEF9C621, 0xE3F3BB36, 0x0A171E3F, 0x0D0ACBE1, 0x09071F21, 0x04DDDDB5, 0x051422C4,
+0x07F2211B, 0xFD1BD5F3, 0xEFFE3926, 0x261602C1, 0xF40F3438, 0xEE07EB21, 0xF4DA1CB2, 0x241EFCBA,
+0x2600B2D8, 0x11DC174C, 0x1A0542D4, 0xDF1349C6, 0x19E10F47, 0x09131F16, 0x010A27E2, 0x0A12E2C5,
+0x01E229F5, 0xE3090AE1, 0xDEFEB629, 0x150E1319, 0x221D050B, 0xE3F4F6CD, 0x21F6071D, 0x23FC4C24,
+0x1312C6EA, 0x12F01738, 0xEFFF3AD7, 0x1FFD48D5, 0x1C0B0CE4, 0xF5F71C30, 0x03F725E0, 0x0D38349F,
+0xEB0614DE, 0xFB03DCD5, 0xEAC9EDA2, 0xDEF8B6E1, 0xDD0B0532, 0x17ECC2C3, 0x27E1FEB9, 0xEF14EA14,
+0xF9FC2F2C, 0x160AC232, 0x1C0445DD, 0xE92311FB, 0x06162F3D, 0x03F12538, 0x0AFE1E26, 0x06E72141,
+0xE1E6F841, 0x3221A5B7, 0x00E6D70D, 0xF8F8E030, 0x24FF4CD8, 0xFB02DCDB, 0x162313FB, 0xEAF1C2CA,
+0x190CBFCC, 0xEFF4E834, 0x60370000, 0x25C139F2, 0xF731FCEA, 0xF734E009, 0xF10AE00B, 0xD2C81AE2,
+0x26590710, 0x1ACE0231, 0xF41D0EF5, 0xD62BE4F6, 0xEF340303, 0x0AB9EA0C, 0xBA251EE1, 0xCE6BE204,
+0xC1530A42, 0xC411E82A, 0xD4CD15E9, 0x35D4040C, 0xBEBE0C04, 0x01D4E7E5, 0xE9CAD9FD, 0x58F1EFF2,
+0xAC46D1E6, 0x21DED4E2, 0x2C240706, 0xE0330304, 0x4931F80B, 0xF44C2109, 0xB74A1DDB, 0x2AC320DE,
+0xBC2D02EC, 0x07EEE4FB, 0x2DCB20E9, 0xC910FBF4, 0xAF52F217, 0xD720D72B, 0xDBCC02F8, 0x1342FDF3,
+0x26B315E7, 0x3D450325, 0xC7C0151E, 0xE9471219, 0x42E4111F, 0x4AA3E60B, 0x5537DF36, 0xB4E92E0F,
+0xDCFEDC10, 0x18F1FCDA, 0xBFFA10E7, 0xD706E721, 0x2BD20022, 0x16500305, 0x4CC2EF29, 0xD71F2417,
+0x20120009, 0xE7EC08EA, 0xE520F1EC, 0x42C8F3F8, 0xF23A19F0, 0x34111BEE, 0xCBF00DE8, 0x02F50DE8,
+0xC3F0DA1C, 0x67CC1518, 0x09463FF4, 0xFCF7E11D, 0x01F6DC20, 0x2F1D27E1, 0x2816F9F4, 0xAA1800EE,
+0x2E592DF0, 0xF4DC07CE, 0xCF49E504, 0xD33BF6E0, 0x17040514, 0xC445EE25, 0x4C33EB1D, 0xBB39250C,
+0x4BAFE310, 0x58F8222A, 0xDD34CF1F, 0x4CCBFBF4, 0x32FDDC0D, 0xCF230ADC, 0x2D13F7FC, 0x49D6FA15,
+0x09E2E002, 0x4425E20A, 0x170D1C02, 0x47DDF0E4, 0x2A441F05, 0xC0B502E4, 0x40B71823, 0xCFEE19DF,
+0xD34A0917, 0xE7370521, 0x0000F1F1, 0x1CFDBD25, 0x1B080D30, 0xC61F61F7, 0x05122C3A, 0xDEF606CF,
+0xF805D023, 0xD91D50F6, 0x1E0D0AE6, 0xE111F7E9, 0x1B1F42F7, 0xE9221106, 0xF7101EC8, 0x061C2FBD,
+0xE8E711F2, 0xFB0E2335, 0x0DFDE6D5, 0x10E7E742, 0xF1FFE62A, 0x04F424CC, 0xF82B1F54, 0x10F8E821,
+0xF40B1C33, 0xE2F3BA1B, 0xFBFBD32C, 0xF6E531BD, 0x12F7171E, 0x13073BDF, 0xDDEFFAC8, 0xDC1DFB0B,
+0x0D00E4D9, 0x120AC7E2, 0xFEE1D546, 0xD9EFFEEA, 0x1EF0F737, 0x021225E9, 0xD4DE54FA, 0xF3FC1B2D,
+0xF80DD1CC, 0x1EE1470A, 0x01E6D7F2, 0xE1E6F70D, 0xF9F0DEE9, 0xFB14D2C5, 0xE603F2D5, 0xD82750FF,
+0x011AD941, 0xE2040A23, 0xE425BD4C, 0xFC28DC01, 0x22D94BFF, 0x0AE6E242, 0x16EDC2C5, 0xD90B011C,
+0x050AD232, 0xDB114E18, 0xF2EB3512, 0x1AE642F3, 0xCFF1A7E7, 0xF220C9F8, 0x171FC148, 0x0735225D,
+0xF2FF1926, 0x14D914FF, 0x0DFC36DC, 0x191BF00E, 0xE50CF3CB, 0x07F5221C, 0x2305FAD4, 0x1FD9094F,
+0x25FFB4D6, 0x170FC1CA, 0x0FF3C91A, 0x02E82BF0, 0xDFEA07ED, 0xECE9143F, 0xE2E44645, 0xF2F6E71E,
+0x26FAFE21, 0xFD17DB3F, 0xF0F6181E, 0xF818D0F0, 0xDD24B5B5, 0x00E8D8BF, 0xFE08DA20, 0x1104C6DC,
+0x22FCB5D4, 0xE5FFF3D7, 0xE4CEF5A6, 0xF1EBE6EC, 0xEC06EBD3, 0xF5E91DC1, 0xE70540D4, 0xFC1A2D0E,
+0x08E7E10F, 0xFAFE22D9, 0x06F82130, 0x09E80000, 0xF4F51F10, 0x49EE1CE2, 0xEEFADF17, 0x44ECE9DE,
+0x0ECEE415, 0x354C1AF6, 0xCC020DDC, 0x50100C25, 0x1F362818, 0xCCB6090D, 0xE5C30C21, 0xFDDA0DEC,
+0x350DDA01, 0x131A0C1A, 0x1AAB15F2, 0x2B590DD2, 0xC4A80331, 0xC517EC30, 0xCED3EEEF, 0xCC44F505,
+0xF40DF5E3, 0xE2341BE5, 0x20C50AF3, 0xF9D308ED, 0xE345DF06, 0x3DF10CE4, 0x203D15E6, 0x1F4BF8EB,
+0x1D37F8DD, 0xFEDC0BF1, 0xC14726FC, 0x0EDD1820, 0xCC221A05, 0xC1CB0D06, 0xC1CAE90C, 0x45EC180F,
+0x9A3AE3EB, 0x15D23EED, 0xABCDEE06, 0x5EB52DF4, 0x19D33523, 0x0C41F1FB, 0xE8F8E4E8, 0xCD24F01F,
+0x1239F604, 0xE6EA1611, 0xF23E0E11, 0x14F01A16, 0x450F14E8, 0x44BD1DE8, 0x3DE3E41C, 0x13E316F5,
+0xEABEECF6, 0xEE00121B, 0x3AEEEB28, 0xE33AED15, 0x229AF5ED, 0xBF26FAC1, 0xE7351A02, 0xA6D80FF3,
+0x5303CEFF, 0xCF082ADB, 0xB7BFF6E1, 0x3521E0E6, 0x07120DFA, 0x25E9E0EA, 0xB423FDEE, 0x0E012305,
+0x1DF21B28, 0xCE1AF6E6, 0x2AF50AF2, 0xF80602E4, 0x0AB71FDF, 0x1F2A1E21, 0x0316F8FE, 0x0F4F2512,
+0xEBCE1A27, 0xC0B3EC0A, 0x23E818DA, 0xEB0AFBEF, 0x164F13E3, 0xCDE61326, 0xC4DF0BF3, 0xBE3C14FA,
+0x51E8E714, 0x10F2D710, 0xD3DB191B, 0xEA1F06FD, 0x344311F7, 0x21D60C1A, 0x301207FE, 0x2FF3F9EA,
+0xEED1F9E4, 0xD335EAF9, 0xFA0505F3, 0x4B62DDDD, 0xD130DC3A, 0xD1D60708, 0x21D508FD, 0x4112FAFE,
+0xEE431816, 0xAE0BEAE4, 0x03E0D51D, 0xD0AEDC07, 0x092BF72A, 0x07C92003, 0x20BDDEF1, 0xDC45F9E5,
+0xCC1905E4, 0x0AE50CF2, 0x53D41E0D, 0xC928D505, 0x48B90F00, 0xF9CCDF1F, 0x3D4D21F4, 0xCB0B15DB,
+0xF0050D1D, 0xE1F2E8DE, 0x36E5091A, 0x3EF20E0C, 0xD8E6161A, 0x241D00F3, 0xC1E7FD0C, 0xCFB8EA0F,
+0xE33CF6DF, 0xF1AA0CEB, 0x45F11A2E, 0x3BFDE3E7, 0x28971425, 0x2DDC00BF, 0xE9DFFC03, 0x05B6EE07,
+0xF1DE23DD, 0xB6E01807, 0x1F31DDF7, 0xEB390A0A, 0xD44B13F0, 0x11E2FC22, 0x5021E80A, 0x072E28FA,
+0xEEBBDF07, 0xEC30E9E3, 0xD2F2EDF8, 0x3AE8061B, 0x4CB6EF10, 0xCBD2DC23, 0x302F0D07, 0xB73308FA,
+0xAFE821F6, 0xD63FD6F0, 0x4CF20216, 0xBFEC23E6, 0x17DB19ED, 0xC9E8EF03, 0x3A34F10F, 0x404711F3,
+0x1814181E, 0xEF17F1EB, 0x551F17EE, 0xD7D62E09, 0xF519FFFD, 0xFC16E4F1, 0x28E62412, 0xDD2600F2,
+0xFD220501, 0x5DE52407, 0xB9B6CC0E, 0x180220DE, 0x27351026, 0xFA13010D, 0x050222EC, 0x2BE0DDDA,
+0xCEB2FC08, 0x0CD00A27, 0xC3FBE509, 0xF6F51422, 0xEEAC1EE3, 0x10CFEAD5, 0x1FDBE9F7, 0x47C20AFE,
+0x3AC8E2E9, 0xC80DEEEF, 0xECD9F1E5, 0x0FCEEC00, 0x1F2CE70B, 0xE5BCF8FC, 0x37B10DE4, 0x4200F1DA,
+0xFB081A27, 0x385C231F, 0xC7210FCB, 0xFEF610F9, 0x26E30000, 0xEBF8132F, 0x051ADEBF, 0xEDE13CBA,
+0x1819C0BF, 0xFE0F2AE7, 0xFC1D24F5, 0xDBE90311, 0x02F02918, 0x190FF037, 0x1CE10B46, 0x0AD0CF58,
+0x170410DD, 0xF72231FA, 0x1D15BBED, 0x16053EDD, 0x0A1D1D45, 0xF412E316, 0x191510EE, 0xE3DE0BF9,
+0x10113838, 0x02D92AB2, 0xFF07D7E0, 0x21ECF83C, 0xEDEBC4C2, 0xE8EDC13B, 0xF9042025, 0xDB35B4A4,
+0x1AE3BF45, 0xFEEB2514, 0xEDFAC522, 0x0B08E3E0, 0x13F2151A, 0xF3D7E551, 0x1D110BE8, 0x25170312,
+0x19C9F1A2, 0xEA0C1234, 0xE3FBF52D, 0xF3DC1BFD, 0x11F518CC, 0xFDF92521, 0xF61E31F6, 0xE0EA47EF,
+0x09E6E142, 0x09F8E031, 0xDDF9B52F, 0xDAE34EBA, 0x160111D8, 0x1524C34C, 0xF01C170C, 0xDDE14BB9,
+0xE7EEC0EB, 0x34005CD8, 0x17E1C2F7, 0x0F1B1943, 0xFD11DCEA, 0xD5EF5417, 0x08D73052, 0x1CDAF4B2,
+0x162AED52, 0xFBE9D3EF, 0xF31C1CBC, 0xF225CA03, 0xEB231405, 0x13FFEC2A, 0xDAF4B135, 0xDC21FDB8,
+0xDBF90420, 0x0F23184B, 0xE40945E1, 0xFE03DBD4, 0xDF1B48BE, 0x0CE01C49, 0x1200C728, 0xEFF016C7,
+0xFC12D43A, 0x0AE9CDC1, 0x15101318, 0xDFE949C1, 0x2314B6C4, 0xFADF2349, 0xFCE4D5F4, 0x1EFA462E,
+0x03DEDBFA, 0x19230F05, 0x210D061B, 0xFF2327FB, 0xDA21B207, 0x1302ECD6, 0xEF14E93D, 0xE4010D27,
+0xEEE7E942, 0x1B1DF30B, 0x1A180D3F, 0xFF17DAC1, 0x0000F2FA, 0xB1351ADD, 0x4FE626F3, 0x2A12D80E,
+0x1434FEEA, 0x36F2EC0D, 0x42C6F2E7, 0xB8C1E512, 0xE23821E9, 0x0E3B0AF0, 0xFC3E1BEE, 0xB631DB15,
+0x0623DDF8, 0xD81B2306, 0x28B5FFF3, 0xEF270023, 0x1718E9FF, 0x33EB110F, 0x30F0F5ED, 0x1426F8E7,
+0xC727ECFD, 0xB34010FF, 0x3CFFDBE9, 0x44141326, 0x5EA2E4EC, 0x3325CBC9, 0xD8130BFC, 0x0C1E0016,
+0xF92EE4F7, 0x1109DEFA, 0x2632E9E0, 0x520EFEF6, 0x342ED619, 0x3229F4F9, 0x0D0DF700, 0x1D111BE5,
+0x15BC0C18, 0xA728ED1B, 0x54283000, 0x47C32B00, 0xCAEE1FEB, 0x11EEF2E9, 0xC00C1717, 0xB215181C,
+0x030CDA13, 0x480325E4, 0xEDCAE126, 0xD8D915F2, 0x23DAFF01, 0x16240503, 0x374AED04, 0x2904F1DE,
+0x3D3DFF25, 0xB3CF1516, 0xDE0A25F8, 0x3306F9E2, 0xCDB9F622, 0xBCD0F5E0, 0xEC291DF8, 0xA8DE14FE,
+0x07FC2F06, 0xCB3CE0DC, 0xFBC4F213, 0x2ED0DE15, 0x35DEFB08, 0x38C8F305, 0xCF36F010, 0x3ACE0A0E,
+0xEC3A1209, 0x2152EDEF, 0x40440729, 0xCC04E91C, 0x0C56F424, 0xB04A1C2E, 0x28CAD721, 0xCDD8FF0F,
+0xCC1CF400, 0xE6BDF3F3, 0x0F020E1C, 0xFBFD19D9, 0x3DC12326, 0x00D8EA17, 0xCB2ED900, 0x5008F3FA,
+0xEF2B28DF, 0xA726E9FE, 0xEAF5CFFD, 0x3FE4EEE3, 0x3F27180B, 0x3C47EA01, 0xC8B5EBE0, 0xBEC1F023,
+0xD7231A16, 0xE15501FA, 0x40AAF82E, 0x4511E72D, 0xF8DAE317, 0x20030000, 0x0BF7E232, 0x0BF1CDE6,
+0xCFF25835, 0xFAE12DF7, 0xCFEAA613, 0x22FFF928, 0xE8E93FC1, 0xE327BAFE, 0x1E030A24, 0xDFDFFAF8,
+0x06F2D3E6, 0x00FED8D6, 0xE7DFF2F8, 0x10FB39DD, 0xDBD74CB0, 0x072BDEAE, 0x1EE90A11, 0x26DB4DFD,
+0x16E8EEC0, 0x17FEC126, 0xEB03C4DB, 0xFCF924D0, 0xDBD8FC00, 0xE510F3E9, 0xEBF6C4E2, 0xFF2127F8,
+0x0DE335F6, 0xE1E7B840, 0x1724C203, 0x0D23E5FB, 0xFD1ADB0F, 0x2C0C5434, 0x22EEFBC6, 0xDB130316,
+0x1EE60A0F, 0x27E94F3F, 0xF7E21F46, 0xF1D837FF, 0xECFB3B22, 0x330FA638, 0x0CE21CF7, 0x22FFB728,
+0x281AB042, 0xF714CE13, 0x11E0C707, 0x11D9E9FE, 0xD9EBFF3E, 0xF8043023, 0x1C15BCC3, 0xCAC95DA0,
+0x13ECEB15, 0xDFEDB73B, 0x201CF8BD, 0xF033185B, 0x160B12CD, 0x01092631, 0x0E06192D, 0x0E001BD8,
+0xEC0FEC37, 0xE4E143B9, 0xDD2405B4, 0x1EDAF501, 0xEFFF16D6, 0xD8F70130, 0xF1EF3738, 0xFBEB2E3D,
+0x1F0147D6, 0xFAF52EE4, 0x00D92800, 0xE31B440D, 0x02112617, 0xF1DCE6B4, 0x17E3C144, 0xE117B9C1,
+0x10F1E719, 0x0C15E3EE, 0xE315F53C, 0xE5260D4E, 0x02F8DB31, 0xEA14EF3C, 0x4B178DC1, 0xDC070320,
+0x0F1CC8F4, 0xEAFB122D, 0xE71042C8, 0xEBE8EC40, 0x0EEDE6C5, 0xEDEF1618, 0xFFDE2AFA, 0x260B4DCE,
+0xF3D9E600, 0xF816DFC2, 0xEA26EE4E, 0x14F23CCA, 0xD51AAD43, 0x0000133C, 0xFF5116EB, 0xCEF7D9D7,
+0x3EFCF7E2, 0xE13E16DC, 0x39D5F7EA, 0x583312FD, 0x3FEB2FF6, 0x35B3E9EE, 0xDD01F424, 0x26230528,
+0x5EB4FFFB, 0xB91E3623, 0x0AE11E09, 0xF6201F09, 0x4CC6E208, 0x1CBA2413, 0xC4370D1E, 0xD1001310,
+0x35150627, 0x122AF4ED, 0x0BF71502, 0xC618E3E1, 0xF202ED10, 0xF2C31A25, 0xB3F71BEB, 0x2312DB1F,
+0xC20804EA, 0x11FAEBDF, 0xA8DE18DE, 0x28113006, 0xE9CC0016, 0x4021120C, 0xEFC41908, 0xEB51E9EB,
+0x331113D7, 0x5ACBF5E8, 0x10C431F4, 0x0927E914, 0xB403E0FE, 0xFBE925DA, 0x1B24DD10, 0xB43B0CFB,
+0xE7C52413, 0xB94A0F13, 0x1DD7E1DE, 0xE5D10A01, 0xAE560C07, 0x290E292E, 0xF3F3001B, 0x5A131B1B,
+0xB4E0CE15, 0xBAE6DDF7, 0xC801E20D, 0xEEC61028, 0x16F1EB11, 0x2FC5EEE6, 0x4D2FF814, 0x2DB526FA,
+0x15B105DD, 0x2932EDD9, 0x0FD1FEF6, 0x2DD719F9, 0x29F30601, 0x3AFFFFE5, 0x44BFEFDA, 0xA437E5E8,
+0x0E38350F, 0xDF07E510, 0x06AA0821, 0x0052222E, 0xEFEB27D5, 0x1ED11814, 0x0B0E0908, 0x2DA11D1A,
+0xEB3405C9, 0x161C140C, 0xC2FBEF0D, 0x02E8E923, 0xD5BADAF1, 0x24C303E3, 0x374F04EA, 0xE8F10FD8,
+0x21B01118, 0xB536F8D9, 0x3BF1DDF2, 0xFD0012E6, 0x2F4FDB28, 0x0D2CF826, 0xBEBC1C04, 0xC64C1A1B,
+0xC62911DB, 0xF3AAEEFF, 0x40D5E52E, 0xA21C18FC, 0x18ED36F3, 0x00000F15, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+hard_output0 =
+0x7FE75E62, 0xB98D686A, 0x16FBEDEE, 0xB22861F2, 0x0A1180B7, 0x666C4407, 0x1D4C462A, 0xB81A3416,
+0xC6948E41, 0x3CCAE97E, 0x55352D5A, 0x85474DAC, 0xB8DBF013, 0xB9AF7B16, 0xEABEE865, 0x1EB02EF7,
+0xBDE86A3E, 0x24EDAAC9, 0x88A3D4B9, 0x8CA15C44, 0x42487190, 0xF4BF8BFF, 0x05EA0214, 0x4708DC42,
+0x222993B3, 0x24AAA18B, 0x4D49B2EA, 0xBBA8E2B3, 0x40426630, 0x5676818F, 0x1B79CC4B, 0x1595A8CD,
+0x9088385F, 0x351D2A23, 0x0EDC4446, 0x8F17D03E, 0xEA8B3464, 0x8799E718, 0x79E11F5A, 0xE771403F,
+0x38C65263, 0xA969930A, 0x59942FBB, 0x74138F31, 0x80518035, 0xB42D7BE0, 0x0C4A7E00, 0x4ACA8CB5,
+0x76C89CCB, 0xB56F2806, 0x1C8CF4E5, 0xA192BBF1, 0x1139DA94, 0x46B1C7C9, 0x8B630748, 0xA882704B,
+0x69DA8BE2, 0xF2508EA5, 0x05E4AEAF, 0x5AA0A9C8, 0x6177DDCE, 0x8D06A0E1, 0xECD023CA, 0x34FC0800,
+0x5AE69AAD, 0xFE8E2F72, 0x5ED3DC49, 0x8B46EB93, 0xC0C3D55F, 0xAC8C8B89, 0x54A20A93, 0x81F6659B,
+0x412B7086, 0x09D572AB, 0x85891AB0, 0x96DC6C57, 0xD7117C38, 0xFBA06F16, 0x9EAAFCE5, 0x44AD2185,
+0x618D398E, 0xD9AC89E7, 0x031F1D0B, 0xE7D05975, 0x9E500DF3, 0x06BFEF20, 0x42888C91, 0xD6AF7FA6,
+0xC839E4C7, 0x0E7B7724, 0x48693BD9, 0xD17B6519, 0x48004F1A, 0xF5A147D5, 0x521C8AD6, 0x26E19AE7,
+0xAA17116F, 0x7196631D, 0x89643E51, 0x8CE6B02E, 0x128B9CF6, 0x2F45C206, 0x4EB6C731, 0xCFB17835,
+0xCFE85026, 0xA4B9B9B0, 0xD2C152AC, 0xA4F89035, 0x79ED0C5F, 0xBC030479, 0x51D91130, 0x570C019C,
+0x4E0306B7, 0x27978CCD, 0x5F8DA612, 0x33C121FE, 0x4407BB22, 0x6FF06E2F, 0x5D7F378B, 0x491B9A93,
+0xA0BDE688, 0x0EA89618, 0xE91C3661, 0x27C69F6D, 0xC46463FD, 0x67649FE9, 0x8F6E077F, 0x4D456A5F,
+0x396B7218, 0x0C26C824, 0xA4E8FD71, 0xDCA1C865, 0x6F1CC581, 0x97C974D3, 0x38D0F6FC, 0x04190419,
+0xED8C7FC5, 0x794BA619, 0x0090798D, 0x3044F72D, 0xBB77EEEF, 0xF9BCFDE1, 0x2C1580F7, 0xC0292305,
+0x86827E71, 0x356C7D12, 0xA84DBECC, 0xCA53E3D9, 0x236E73F0, 0x9FD2AFBA, 0x652E7A66, 0x744A1147,
+0xBFE9AF5B, 0x59F2552F, 0xBD77D3C0, 0xCD726524, 0x1D56A0FB, 0x85207831, 0xB6F1861B, 0x369CF946,
+0x71CA18BD, 0x5EE3F7CF, 0x2C3FC902, 0x4301214D, 0x53A64F16, 0x2956B34F, 0x3DF40618, 0x41A36C68,
+0xF7BB2B5F, 0x0C5CD46D, 0x3E4354AC, 0xC29AFEF7, 0xC1A310AF, 0xFFEF128F, 0xBE1C8D14, 0x8B123664,
+0x854B7E00, 0xAE175861, 0xE4067FE2, 0xA264F00A, 0x988634EF, 0xEC9E38E7, 0xFE2968A6, 0x2B30719D,
+0xFE3DC88D, 0x09E222C8, 0x6B4F1B50, 0x436C7137, 0x161DFE10, 0xA68C403E, 0x12A2856F, 0xAAB8DFF0
+
+k =
+6144
+
+e =
+10376
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE, RTE_BBDEV_TURBO_CRC_TYPE_24B,
+RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_low_snr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_low_snr.data
new file mode 100644
index 000000000..8ff71aac4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_low_snr.data
@@ -0,0 +1,643 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x16000000, 0x081112e9, 0xcd2d1fac, 0xf9fdf4db, 0x110edf1a, 0x0dd9e84f, 0xdbe9e611, 0x0fde0206,
+0x43df19f9, 0x071ee4f7, 0x1f1322c5, 0xd4e5f6f3, 0xe3fafcde, 0xd002f52a, 0x4427f801, 0xbadce403,
+0xce101dc9, 0x09fff729, 0xd5f91f2e, 0xf3f0fee8, 0x4f061cde, 0x4a2b2753, 0x1d24dffb, 0xd3040bdb,
+0xcaf2fbe6, 0x1cd9f350, 0x00fff42a, 0x49d02759, 0x4005de2d, 0xd3fb1923, 0x36cbfc5c, 0x020a0de1,
+0x39072621, 0x3b0defe5, 0xb4ebec13, 0xddee2416, 0x24f206e5, 0xd1e1fcb9, 0x0e150713, 0x21f6191f,
+0x0d0bf9e3, 0xf0061bd2, 0xae2717ff, 0x0de9d740, 0x13031a2b, 0x4c0215d6, 0x4534dc5c, 0xa1f41c1c,
+0x001b3842, 0xeaf83ecf, 0x2519b4be, 0x1d220afb, 0x05162312, 0xee00ea29, 0x25ef4d39, 0x0cc03398,
+0x08f5e0ce, 0xb7e68f43, 0x14f7ec31, 0xe7f5f11e, 0xfd29d6ae, 0x0af133c9, 0x03fdd5db, 0x0bca1d5f,
+0x00172840, 0x061add0e, 0x0516ddee, 0xe10cf735, 0x1709101f, 0xdf0908d0, 0x06fe2dd6, 0x18ed11c6,
+0xd315ac14, 0x06f0d3c8, 0x1ed9474f, 0xef223806, 0x28f3ffe5, 0x0eeb1aee, 0x080de0cb, 0x29f452e4,
+0xdbd702b0, 0x041b2cbd, 0x1df30b34, 0x1927f102, 0x2010b719, 0xf0fde8d5, 0xe9eaef3e, 0xf10b36ce,
+0xdff4fa1b, 0xfd0cd5e4, 0x04f923d0, 0x110f3936, 0x06fe2e26, 0x00e42844, 0x11e839c0, 0x13ecea13,
+0xf621e349, 0xff332600, 0xe604f1f5, 0x0533d425, 0xf240c9f5, 0x0b5933e8, 0xdf1bf931, 0x02c929f2,
+0xeee6eb0f, 0x12a2160f, 0xfdde26ca, 0xf016c8f9, 0xdd03b5ee, 0xe2ee09da, 0xfdf4db17, 0xdb0603e4,
+0xffda2821, 0xf6f9cefd, 0xd5ca5421, 0x12f03af2, 0x182f0fe9, 0x10423808, 0x0c19e41a, 0x27af02f0,
+0xfc14d42a, 0x08c9d114, 0x274700f2, 0xe8c110e1, 0x0e0f19e9, 0xeb58c3e7, 0xe20fbbd1, 0xe52e0e1a,
+0xf145e607, 0xe316bc1d, 0xe3e04511, 0xd93c0009, 0x27db01ed, 0x0a30cd03, 0x23434af8, 0xe13f09e6,
+0xe4d00de9, 0x07202208, 0xdb3ffd07, 0x0955cfea, 0xeae8112c, 0x041324f1, 0x1011e815, 0xf6d01f17,
+0xe5eb0cf9, 0x17be00ee, 0xa2dbeee6, 0xb2e73603, 0x08ebda0f, 0x250fe0ed, 0xe61a0218, 0xf1dbf2f3,
+0x420b18fd, 0xa1e9e5e4, 0xd9e1caf0, 0xe7cffe08, 0xeba8f009, 0xc45213d0, 0x20a1ed29, 0x28fa0737,
+0x1ad900dd, 0x1bc10dfe, 0xab360c18, 0x023bd3f1, 0xacfd2514, 0x4d382c25, 0xf25adbf1, 0x1eda1a32,
+0xf11e0902, 0x23a5e70a, 0x1f32fcce, 0x0ef0f8f5, 0x2029e6e9, 0xdfda0701, 0x1860fafe, 0xd8e5f139,
+0x5612010d, 0xf2572d15, 0xba23192f, 0x2ac1e2fb, 0xe91e02e8, 0x44d2100b, 0x08f9e307, 0x5edddfe0,
+0x240fc906, 0xc1c3fbe7, 0x0f231614, 0xaa111806, 0x1e2d2eea, 0xc6ba0a06, 0xedc9121e, 0x1ffc150e,
+0xd11b0a23, 0xe800f80d, 0x2f27f101, 0x06110638, 0xd01fdef8, 0x15ee0717, 0xba0e131a, 0xcde51f43,
+0xd21df6bc, 0x051006c8, 0x2616ddc3, 0x3ef8fee0, 0xf3cde9a4, 0x3bd81b4f, 0x25001229, 0xf6eb023e,
+0xd81ee3b9, 0x1cecff14, 0x29fef4d9, 0x9f2d0255, 0x121e38f5, 0x18eb16c2, 0x271a1041, 0xf7f700cf,
+0x28f3e1e4, 0x49e90011, 0x4b0fde1a, 0xd9e723f1, 0x0de402bd, 0x261f1b0a, 0xbe0afe1e, 0x0823e606,
+0x3d041f2c, 0xf1f21436, 0xec1ae7f1, 0x02ebebc3, 0x52f1da1a, 0xc9e5d60d, 0xa9dc0e04, 0xc504d22d,
+0x09fd1325, 0x3706e02e, 0x26dc0f4b, 0x2012fe3b, 0xeef109e7, 0xb509161f, 0xf01dde45, 0x13d51853,
+0xc823ebfb, 0x2d23f0fc, 0xcbf6fbcd, 0xd505f22d, 0xee0afd1e, 0xa6e615bd, 0xa020ce07, 0x411937c0,
+0xbcd318ab, 0x2a1d1cf5, 0xc400ff28, 0xe32014f7, 0x2bf30b1b, 0x0e03fc25, 0xe1e41bf3, 0x2f1b0943,
+0x06060721, 0xc601de26, 0xd3faee2e, 0xe51c05bc, 0x0411f4c8, 0xcfe7dcbf, 0x2d12083a, 0x0bedfb3a,
+0x0efc1d2c, 0xca1f1909, 0x13f80e30, 0x3a21eab7, 0x3c2b1252, 0xf2e4140b, 0x2527e5b1, 0x2ffe03d6,
+0x44e4f90b, 0xcf21e449, 0xd8e9f6c2, 0xeef8001f, 0xfb151513, 0x48f9de22, 0x2ad6e0ad, 0xe63602a3,
+0xdae50e0d, 0xe3e5ff0c, 0xc721f449, 0xa0d5efac, 0xe70039d8, 0xc7f71031, 0x2b22eefa, 0xe5fb04d3,
+0x0021f2f9, 0x2bce28a5, 0xdffefa00, 0x1af642e2, 0x1d190bf1, 0xecf515cd, 0x0af4cf34, 0xf406cbd1,
+0x08ebd013, 0x14173b40, 0xe40e0bca, 0x29ff51d9, 0xd303abda, 0xe303f5d5, 0xf6facddf, 0xecef3cc8,
+0x1324ecb4, 0xd213563c, 0xe00ff91a, 0xef121639, 0xf5d2cdaa, 0x1914f013, 0xe80f3fe8, 0xe31c0bbc,
+0xe3d5bcad, 0xe610be38, 0xe72df155, 0x1cef44c7, 0x13ccc5a3, 0xe1e20909, 0xecf2c337, 0xf2fd35da,
+0xe5cd435b, 0xdc1304c5, 0x050722d2, 0x121fea46, 0x36f8a1e1, 0x1223c6fb, 0x18040fd4, 0xef1517ee,
+0xf8e32ff5, 0xf22cc953, 0xfe04d7dc, 0x10e7390e, 0x1ef4091b, 0xdbf2fde6, 0x1afa432e, 0x2211b5e8,
+0x211eb8ba, 0xff1529c4, 0xdaea004e, 0x11e539ed, 0x13b4eaf2, 0xe10af7db, 0x11e9c81e, 0x1eeef6f0,
+0x17b73fea, 0x09c61fde, 0xeefdebef, 0xd92fffdc, 0xd7e05007, 0xfe42d9f8, 0xd2feaae6, 0xf3001cd9,
+0xee12c727, 0xe5d90cea, 0x2c21ac01, 0xe3de0b08, 0x265703fa, 0x1a410d30, 0x2f1f5719, 0xe742bff6,
+0xfc2e23e5, 0x2746b105, 0x262efe1d, 0xe43ff4fb, 0xf01018e9, 0xd9014e18, 0xef043927, 0x23fb0524,
+0x27094e23, 0x19ce41e1, 0xf70a200b, 0x1daff5e3, 0x274eb22a, 0xf612cd26, 0xf903df17, 0xe3f1ba25,
+0xe45bbc18, 0x062a2132, 0x11bfea01, 0xf4fe34e7, 0x0637ddda, 0xede0c510, 0x02022509, 0xfbbf2c26,
+0xeda8c619, 0xecb0edd0, 0xeb00d0d8, 0xf054edf7, 0x0356182c, 0x5fd3252e, 0xd74e3805, 0xc2100026,
+0xe4161517, 0xf106f412, 0x26f219df, 0x440bfde5, 0x1b031d1d, 0xe6c4f325, 0xd349f213, 0x2b0605df,
+0x4bdbfcdf, 0xe32e23fd, 0x49460a07, 0xcff022e3, 0xf9c2f617, 0xdfbc2116, 0xed2f071b, 0xd6a91406,
+0xc33bfe2f, 0xc623eb12, 0xc2d0ee06, 0x243aeb07, 0x1fe8fb13, 0xffc409f0, 0x1ed6d814, 0xde4bf602,
+0x31dcfb22, 0xf5da0afd, 0x0afd1e03, 0x1cc01fdc, 0xf82bf4e8, 0xcccce003, 0xfb0f0df4, 0xd2ff23e8,
+0x0845fbd9, 0x16e821e2, 0xe5c5eef0, 0x14bbf4ec, 0x1cefeb1d, 0xffcd0de9, 0x5bbad90b, 0x0630331d,
+0xf826dd09, 0xc62c2001, 0x00ed12fc, 0x16e8eb40, 0xf3e4120c, 0xc105e52d, 0xca181610, 0xb9e0f149,
+0xfc011f28, 0xfc17233f, 0xc5f12318, 0xea1dedbb, 0x37e91240, 0x47d9f0b2, 0x19271e01, 0x09240ffb,
+0x1edd1f4b, 0x02240ab3, 0xf3e6d90e, 0xfd03e425, 0xb12325b5, 0xb92cd9ac, 0xcee71e41, 0x47fa0bdf,
+0x0fcb1fa3, 0xd406e7de, 0x31defcfa, 0x300af71e, 0xfa0608dd, 0x10e922c1, 0xb2f3e936, 0xf336265e,
+0x0610e517, 0x16e72242, 0xab23134b, 0xbaddd34b, 0x1afee225, 0xfc100d38, 0x44e6dcbe, 0x02ede4c4,
+0xbe19da41, 0x2ff1e6c9, 0xea14f8c3, 0xc21bed0d, 0xac1017e8, 0x35202df8, 0xd9f10dca, 0x03fc02dc,
+0xf2e425bb, 0x29efe5e9, 0x3ce10046, 0x09153000, 0x0b061d2e, 0x1f1a0abe, 0xfb18d2c0, 0x0008d730,
+0xf3071b30, 0x17dfeff9, 0xc5d09da8, 0x23d7fbaf, 0x07e921ee, 0x16e4ee45, 0x1624c304, 0x01f828d0,
+0x20ddb8fb, 0x030325d5, 0x0424d5fc, 0x0216dac3, 0xe5040c23, 0xd71552ec, 0x28ef00e9, 0x16de13fb,
+0x1520edb8, 0x0416db12, 0xdeee07c7, 0x07fc20d4, 0x08fadf2e, 0xf0f639ce, 0x30f0a7e8, 0xef0d39e6,
+0x210d071c, 0xf2f235cb, 0x05192242, 0xd6095130, 0x2605ff2d, 0x19f8bf30, 0x1320eb48, 0xfbd72e51,
+0x01d92701, 0xe127f601, 0xdc0a051f, 0xfdf1dc37, 0x0b0bce1e, 0x09ff1f29, 0x1507c3df, 0xf7e3e1bb,
+0xdb204df8, 0x11e517bd, 0x3004a7dc, 0x0d1300cc, 0xf42134ea, 0xe9b9c1f8, 0x1fbef720, 0x07bcdfe5,
+0xeccf3ce5, 0x17301109, 0xf2b4e6f7, 0x1258c723, 0xdaf84dd0, 0xd507ae1f, 0x011d2a22, 0xfd3f25f5,
+0xfd4edb17, 0xf9cadf26, 0x144dc3f1, 0x09003124, 0xec503b27, 0xfed1d628, 0x0ffbc9f8, 0xf2e619de,
+0xf832dff1, 0xf3d034f5, 0x1dea0b09, 0xe80e0fef, 0xf1dd38e6, 0xf8fce104, 0xde1f07db, 0x06ccdef7,
+0x24554b0c, 0xcde0a6d2, 0xe2e0baf8, 0xeae6ef09, 0xe31b440f, 0xe5c6f3f2, 0xf447ccee, 0x1944f2e1,
+0xe33fbb1b, 0xebad3eea, 0x0b1de32b, 0x0d24e50c, 0x18e711fc, 0x2830b110, 0x14413cf8, 0xe7e7f219,
+0x1c49bc0e, 0x0734e0df, 0xe255f50c, 0x540045d2, 0xe3c0d3e3, 0xef0ff518, 0x34c017e6, 0x052af517,
+0xff4e2402, 0xc4eadada, 0x00d3ed12, 0x4bc727fa, 0xaaf62211, 0x28e1d21e, 0x530a00f7, 0xfd40d5e1,
+0x0dafdbe8, 0x2b0de5d6, 0xc722fce5, 0xca241007, 0xe1eb0efc, 0xfa63f8ee, 0x28dfdec5, 0x07420107,
+0xccf6dfe7, 0xcb1df4e1, 0xd9def40b, 0x47ef0105, 0x1041e0e9, 0xe849e919, 0x27f10fdf, 0xef2c02e7,
+0xe74fe805, 0x4cb7f2d9, 0xe7ee2521, 0xee430f17, 0x5b09161b, 0xdce2cd1f, 0x2343050a, 0xc22c05e5,
+0x5ae7eafc, 0x9749cef1, 0x4dea4221, 0x0e2726ee, 0x24a8e6ff, 0xcc5afcd0, 0xbcd2f432, 0xf514e306,
+0xbd0ee414, 0xc4dbe41b, 0x310a1302, 0x090cf8e2, 0xd5dce11d, 0x1c13fdfb, 0xeacbf515, 0xc5eeeef3,
+0x3027eee9, 0x29420701, 0xc01700e6, 0xc4b7e910, 0xaaebec21, 0x129fd2ee, 0x2ec5eac7, 0x0eecf9ec,
+0xe10b1aec, 0x57b3f7e3, 0x3939d1db, 0xcf42f012, 0x163ef719, 0xd5111217, 0xe92203e9, 0xf13eef05,
+0xece5e6ea, 0x3301ecf4, 0xfff6f527, 0x39ded9e2, 0x110deffa, 0x262fe91a, 0xb7bd0207, 0x39d8dfe4,
+0x0a2e1101, 0x2adf1ef9, 0xe52ffef9, 0xb70ff307, 0x1cdd22e7, 0x2b3bf4fb, 0xe4eb02ec, 0xd80bf4ed,
+0xfebaff1d, 0xcd12271e, 0xfeee0aea, 0xc70726e9, 0x0f4fefdf, 0xd9b6e6da, 0xf5d300df, 0xccbc1dfa,
+0x34270de4, 0xf0d3f400, 0xc649e7fb, 0x18deeede, 0x4d0f0600, 0x2bdf2549, 0x1f07fe21, 0xf0e6f60f,
+0x0c1b1743, 0x0f0a1b1d, 0x46efe7e9, 0x0ae6e242, 0x0ff61f33, 0xae21e84a, 0x500ad6e2, 0xfcddd74b,
+0x4a17ddc2, 0xe9d9dd4f, 0xc7241205, 0xb9e8110f, 0xda111ec7, 0x37e1fe46, 0x39f3f1e5, 0x000512d2,
+0x0e05d92d, 0xfeec193c, 0xf519daf0, 0x1e291d52, 0x362bf652, 0xbce9f311, 0x30fae5d2, 0xe6fcf7db,
+0x36ec0fc4, 0xddfa0f23, 0xf1f605e3, 0x1ed1e857, 0xb9def6b6, 0xc0091ee0, 0xcff1e8ca, 0x3fe5090d,
+0xf3edea15, 0x23111b16, 0x0207fbd2, 0x1d2cdbac, 0xbdf6f6cd, 0x1a311ba8, 0x420af2cd, 0x1bde1ab7,
+0xc512f217, 0x0fe3edbc, 0x1afe19d6, 0x200bf1e3, 0x100900c8, 0xfe1a29f2, 0x12c51663, 0xdfe606f2,
+0xf7ea1f12, 0xf841df96, 0xe2f50a33, 0xe9f5efcd, 0x13fdeb25, 0x2524044d, 0x0d1a35be, 0xfaee23c7,
+0xf0043824, 0xda200108, 0x04f225c9, 0xe101f7d6, 0xf30dcb36, 0x07fb22dd, 0xd1fba92c, 0xdf03f824,
+0xd0efa8e9, 0xf5dd1d05, 0xfe332a5c, 0xf4221bb6, 0xe5ddbdb5, 0x1401c3d9, 0xfc12d33a, 0x1b14bd3b,
+0xddf2fb36, 0xf0e13709, 0x12d9c601, 0x0cf7cce1, 0x1b06bc22, 0x22d6b7ae, 0xf7291eae, 0x15f81321,
+0x1a04f2db, 0xe425f404, 0x05f32435, 0x060f2218, 0x0bd93250, 0x26f9fd20, 0xfe2fd5aa, 0x121deb45,
+0xf6e731bf, 0xf90c2e1d, 0xe9dbc2b3, 0xfb0edd36, 0x1500b93e, 0x281db01e, 0x061ddff5, 0x2712fe0a,
+0x0f461ae9, 0xe32f0b1f, 0xed691507, 0xf61d32bf, 0x0d24e5f5, 0xfae422fd, 0x03d126f4, 0xee0ac6f9,
+0xd8a4b11e, 0xebf51335, 0x15f7c31e, 0x07fd22e1, 0xe40a0cdb, 0xdd04b5e3, 0xd1f25825, 0xec033de6,
+0x12fee925, 0x292051da, 0xdff54af7, 0x34d0a4e3, 0xf53de209, 0xedeceb14, 0x0f4cca13, 0xe3340b25,
+0xf023e90c, 0xf6be32fa, 0x2254fae7, 0x07c1212b, 0x31015816, 0x1bd24227, 0x1438edf9, 0x151f3df0,
+0x02d1270a, 0x0fffc9f9, 0x0d4235da, 0xf638e2e6, 0x241ffc0f, 0x1d380b08, 0x1a93bdf0, 0x1b4f44bb,
+0xfe57da26, 0x24c8fbd1, 0x1112c711, 0x1f3ef6eb, 0x00173116, 0x100311f8, 0xf2dfe7db, 0x292ce5f8,
+0x46e1fffb, 0x45c71ef7, 0x2bc31c11, 0x4abcfceb, 0x00e0dd1c, 0x202628f9, 0x42f2f801, 0x0bb41b1a,
+0x0d16e225, 0xd2f11a12, 0xf6ec06e6, 0x13ef1deb, 0x48c51617, 0x09ff1f13, 0x314b1f28, 0x1ecf0823,
+0xf9adf6f7, 0xd4da222a, 0xef0f0501, 0xe146e8e8, 0xfe4308e1, 0x4803dbe5, 0x21bc2025, 0x0fc5f9e4,
+0xd341e813, 0xa9d9fae6, 0xaaf5d1ff, 0xb546d2e3, 0x12e2221f, 0xbee715f6, 0xd325e60f, 0x1adc05fd,
+0xf533f3fb, 0xf3d0e3f6, 0xcb11e5f7, 0x33fb0ce9, 0xa3be0b23, 0x29b8351a, 0x312f0120, 0xebbb0afa,
+0xc31a12e3, 0x0c47150d, 0x21c21be2, 0xe1570715, 0x19e0082e, 0xc8f2f800, 0x2a0b11cd, 0xcd3001a8,
+0x2f1e0bf7, 0x1909071f, 0x1c15f2ed, 0x4612f53b, 0x40021d27, 0x3108e821, 0x0c1108c7, 0xcd0d1ce4,
+0xe51c0b44, 0xb4ebf412, 0xf1dddc04, 0xd6f7e6e1, 0xc32efe56, 0xfd10ea18, 0xdb2eda55, 0x48ff0329,
+0xe2fce12c, 0xd5f9f5df, 0x2cda04fe, 0xdf0dfdcb, 0xc5e70741, 0xdf16eec2, 0x3ce1faf7, 0xcc0eec35,
+0xfa28f450, 0xf1e72210, 0x451de7f5, 0x4dfde324, 0xfdf3db35, 0x31eadc3d, 0x391c09bc, 0xcc09ee1f,
+0xdaf90dd1, 0xf6e1ff09, 0x22f8e1d0, 0xe70efae5, 0x13faf02e, 0x271e15ba, 0x03df0007, 0x11ff2627,
+0xb8e9173f, 0x38ecdfec, 0xc4ed0f3b, 0xe4d91402, 0xd5010c29, 0x050400d3, 0x1e01ba26, 0xe3390b60,
+0xe11d0a0c, 0x2adaaefe, 0x1222e906, 0x0ff6e7ce, 0xebeb3cc4, 0xfd082b31, 0xf52a1e52, 0xf1dde7b4,
+0x0ee8e6c1, 0x0c2ae352, 0x0df3cbca, 0x131bebf2, 0x23214bf9, 0xd6f5ad1c, 0x21fff8d6, 0xe3e00a48,
+0xf00119d8, 0x03d02ca7, 0xf1fcc92c, 0x0c0b1b1c, 0xf4daccb1, 0x131ac50f, 0xd6295250, 0xe4f6f3e2,
+0xe9f91221, 0xe6e0be49, 0xdcebb5c3, 0x1f1bf8f3, 0x27f6b2e3, 0x1a1c0e45, 0x0504d224, 0x0918e20f,
+0xe4dabb4f, 0x0a001d27, 0xec193b42, 0x08e9d1c2, 0x0c09e51e, 0xff28d700, 0x0d0ae5cf, 0x0704202c,
+0xfce0d408, 0x0c0b341e, 0x27ee00ea, 0x1206c7d1, 0x1000e9d8, 0xf8000830, 0xe334f5e1, 0x0bc81ef4,
+0xeed33b10, 0x280050fb, 0x02d1d928, 0x0e3be608, 0xdc130412, 0xf6ffceea, 0x03142a28, 0xfeea2aec,
+0xfdc4d613, 0xf1151aed, 0x1425c4ee, 0xfdd0db04, 0x10df1807, 0x0af7cd07, 0x20c108e2, 0xf61bce17,
+0xe6e6f10e, 0x03d0da0e, 0x20edf808, 0x37dc60eb, 0x1bfd0e04, 0x18b73f24, 0xe8f91021, 0x0ed31ade,
+0x1fe50afc, 0x07e020f3, 0x0c2ccb07, 0xedd91405, 0xf700e202, 0xdce903d9, 0xf4b31c12, 0xfcbbd425,
+0x08d431e2, 0x1f00b905, 0xd04158d9, 0xd2acabe8, 0x18e911d3, 0xedca3c12, 0xe467bb0f, 0xd9c350c2,
+0x00c12816, 0x082220e9, 0xfe692bfa, 0xfc322cc0, 0x0d1ae5f5, 0x1de446f2, 0xe136b80d, 0xf2001af2,
+0x1be3bdd8, 0x013e29f4, 0x272301ea, 0x0a021f04, 0x22d1b5da, 0xedafecfa, 0xf958d0d8, 0xb1f48ad1,
+0xf816d01b, 0xe7caf2ee, 0xf7e11ef1, 0x0ae31df7, 0x0feb180b, 0xece61513, 0x3f10670e, 0x0baa1c17,
+0xf233e6d2, 0xce46a7f5, 0xe6c642e2, 0x033225ee, 0x0b3de20a, 0x00f7d814, 0xf8cccf20, 0xe2ee0bf4,
+0xd93601ea, 0xefdf3a0e, 0x2202fb07, 0xe5c70c25, 0x01da29ee, 0xf8182101, 0xdef7b610, 0xeb0aed1e,
+0x0017d8e2, 0x2fa4a9ef, 0x0c25cd35, 0x05f62304, 0x08e7e01f, 0xe11409f2, 0xf5e81ded, 0xeefeeb10,
+0xfe122b25, 0xe9153f16, 0xe34f44ed, 0x1cca0c27, 0xf3dbcb0e, 0x08c231fc, 0xe2cfea00, 0xf031f5f7,
+0xc7e91809, 0xdfe5ef10, 0x1234fa0e, 0xee28ea0c, 0xc6061700, 0xccb8eede, 0xed190b20, 0x21441510,
+0xb1e007e5, 0xe1c7d9f9, 0xcacbf611, 0x3acb0f0c, 0xd7e4110d, 0x41c2010c, 0xef0418ea, 0xffc917dc,
+0xc7e4270f, 0x40e3eff5, 0xaf4c19f6, 0x413f28db, 0x2e12e616, 0xd1e6fbeb, 0x1008f80f, 0x070719e0,
+0xbdebdfde, 0x16f31b12, 0x2e1c12e6, 0x41eafaf4, 0xccc7e6ef, 0x26ff0bef, 0xc201fed9, 0xe733ead8,
+0x373cf10a, 0xfdd5f213, 0xe1dcdcfc, 0xa9400904, 0xe432d018, 0x15340c0a, 0xcd3aedf4, 0x24210cef,
+0x02d90407, 0x43c827ff, 0x27341c11, 0x1226fef4, 0x192cebfe, 0x280cf204, 0x96ff00e4, 0xb5dd4204,
+0x1a2adc52, 0x1bf00ec8, 0x1d07f320, 0x09ed0a15, 0xb5e3200a, 0x12f7de1f, 0xe915eaee, 0x3bf11219,
+0x3df1ec19, 0xe3ecec13, 0x1ce6f543, 0x0d18f4ef, 0x21ea1a13, 0xc8f507ce, 0x22e511be, 0x0b1cfaf3,
+0xcfe8e3f0, 0xc104f6dc, 0x301817f0, 0xb825084d, 0x3fe920c2, 0xeff3171a, 0xc7e01809, 0x2efc10d3,
+0xb602f92b, 0xdecb215c, 0x0d13053c, 0x3908e5d1, 0xb5efefc7, 0x44e0dcb9, 0xe8161def, 0x1de8f040,
+0x2f140b3c, 0xc5ec07ec, 0xd403ed25, 0x0aeefce9, 0xd412e23b, 0xf4f804e0, 0xf218e5c1, 0xca17e612,
+0xc5050ed3, 0x1afc142b, 0x2e2c0dab, 0x39ecfb13, 0x1de6100e, 0xf81ef4ba, 0xf600211d, 0x12c03968,
+0xe8f90f2e, 0xfbe42c44, 0x260bfee3, 0x051b22be, 0xe50842df, 0xfef6d632, 0x130514d3, 0xe6def24a,
+0x09213107, 0xdfddfa05, 0x0418d310, 0xf00739d1, 0x0afa1ed3, 0x1bfff4d7, 0xfddc2b4c, 0xf1e0c9b8,
+0x04e1d4f6, 0xd423acb5, 0x320c5b1b, 0x160eefcb, 0xe11347ec, 0xedfc16d4, 0x10f8c7e0, 0x220e4ae6,
+0xf0f5c834, 0x272002f8, 0xdf0df9cb, 0xe02ff8a9, 0xd7df5106, 0x152512b2, 0x02fe2bd6, 0x1707112f,
+0x2519b2bf, 0x051e2eba, 0x0bdbcefd, 0xf1eae8c2, 0x08dee007, 0x02142b3c, 0x001628ef, 0xe21fb9f6,
+0xe0e9f7c1, 0x31ed593c, 0xe4ff442a, 0x16e1c247, 0xe6e3be0b, 0xdbfc0324, 0x001110c7, 0xda2affe8,
+0x05b6d302, 0xf94a2023, 0xe5350dde, 0x1ee0f60d, 0x282a00f8, 0x28ba50ff, 0x08e5211f, 0xf1f8190d,
+0xd5abad20, 0x16fbc22c, 0xf8cc1fdd, 0xda1efe0d, 0xeb0ec3f5, 0x014c26e7, 0xf0e118dc, 0x1d11bb08,
+0xe4bc44e8, 0xd4d0541d, 0xe43a44f8, 0x28445112, 0xdae0fde5, 0x13e3c6f8, 0xe11b09f4, 0x2ad2520d,
+0xef59eafb, 0x1dcaf530, 0xde4d06f2, 0xf617e325, 0xf3c5e512, 0xf4b1cc13, 0xf91d2128, 0xd8affff4,
+0xe54d43d8, 0x1a060fdc, 0xe7c3be22, 0x2441b415, 0xf3171a19, 0x180ff011, 0x30e4a919, 0xfaed2ff4,
+0xd54253ec, 0xe7df0e1a, 0x232afa08, 0xe9f7effe, 0x1cb5f31f, 0xf4083422, 0xdfd4b620, 0x2223fc00,
+0xddcf06fb, 0x6cc004f8, 0x041c4418, 0x4b04230d, 0xc6f92225, 0xf61aee22, 0xba001d0d, 0x06c3e2d9,
+0xd5c2dd15, 0x240ffde9, 0x405a0319, 0xe3a01731, 0xde3c0b37, 0x2206faeb, 0x27fcfb22, 0x33af00dc,
+0x3ba60a29, 0x2cc913cd, 0x4ef505f1, 0xccbbda1c, 0x203df4e2, 0xe407f815, 0x1a15f321, 0x18d30eed,
+0x2d1f10fa, 0x3c47fb09, 0x3cf9eb1e, 0x4cf114e0, 0x0caadde6, 0x594ee5d2, 0x1ed6d026, 0x2229f602,
+0x18f4faff, 0xddf5f0e4, 0xaf07fae3, 0xdc0fd8df, 0x14c3fce7, 0xf2d2edea, 0xb106e6fb, 0xdb0ada22,
+0xc6bdfce1, 0xcdf111e4, 0x1dcf0ae7, 0x27c4f6f7, 0xe5e5ffeb, 0x20380d0c, 0x4b3e070f, 0x322300e9,
+0xede80a0f, 0x65f7ebe0, 0xcbddc306, 0x572b0d53, 0xb0082f2f, 0x5d0729e0, 0xbf0f3537, 0x18c2199a,
+0x57e3110c, 0x4512d23b, 0x18f01e17, 0xf9f3f11a, 0xc6f1df37, 0xeae1ef47, 0x0df111c9, 0x19fce6d4,
+0xd3f90fd2, 0x08f70520, 0x15f4e0cc, 0xefff12d8, 0xaee6ea0f, 0xc1db2afd, 0x1cdaeab3, 0xbe0bf433,
+0xe6e01b47, 0x5503f125, 0x30fbd422, 0x3723f7b4, 0xcb1510c3, 0x09fdf4d5, 0xeeee1e39, 0x0ae7ebc0,
+0x02d81d00, 0xbc33db5a, 0xc501e429, 0x12e0edb8, 0x03f1eac8, 0xf0eb25c4, 0x09e4e7bd, 0xd71de0f6,
+0xc8ee0017, 0xdf00f0d9, 0x4209f8e2, 0x3100e6d8, 0xe2190942, 0xd5070921, 0x0b0c02e3, 0xee00e4c7,
+0xf5eaceef, 0x2011f7e9, 0xdf1106c7, 0xfede29fa, 0x1c1f0d0a, 0x1f0d08e6, 0x0d2ccc54, 0xf6e61df3,
+0x121f1647, 0x1610c3c8, 0xded7b6af, 0x1ef8f61f, 0xf9172ef0, 0x391f60f7, 0xf3ebcced, 0x273050a9,
+0x1305ebd3, 0x16221206, 0x12e5c6f4, 0x0006d822, 0xecfa152f, 0xf9f92f2e, 0x1fe2470b, 0x2425fc4e,
+0x33285cb1, 0x070430d3, 0xe421bd48, 0xede1c5b9, 0xf4ea1c12, 0xe1c809a1, 0xfa05d223, 0xedf83a2f,
+0xc4259d03, 0x1f180810, 0xdb10fee8, 0x11daeab2, 0xec2614fe, 0xb31e74ba, 0x14143b14, 0x07ff2fd7,
+0xfb23d305, 0x25fffcda, 0xe7dbbefe, 0x13e43abc, 0x070c301c, 0xff0726d1, 0x16dc3eb3, 0x04ee2dc6,
+0xdeff05d7, 0xf8dfd0fa, 0xde13fb15, 0x0b1acebe, 0xe2f1f6e6, 0xee1d3a0b, 0x3003572b, 0xf9d32fab,
+0x0420ddb8, 0xcef05919, 0xd126a9b2, 0xdac9fda1, 0xe0ee083a, 0x30e259ba, 0xecf1ed19, 0xd0da58fe,
+0x071f2e46, 0xe2da4602, 0xf3cecba5, 0xd8e20045, 0x18d6ef53, 0x11dbe9b3, 0x1819c00e, 0x09f930e0,
+0xf2183640, 0x250bfd1e, 0xcae3a2bb, 0x17d13fa8, 0xefe6c8bf, 0x1ff8f620, 0xfaee22c7, 0x0afdce25,
+0xd9010029, 0x1727c2ff, 0xf2221bf9, 0xd8e10147, 0x0726224d, 0xe0ea4811, 0x1a2e0ea9, 0x0d3635a3,
+0xf0f1e7e8, 0x0c0234d9, 0x0ef8c920, 0xecf4151d, 0xe817c112, 0x0e0637dd, 0xddf305cb, 0x16e2ef0b,
+0xf1c10000, 0xfd2ce717, 0x092ada04, 0xb929e202, 0x2902e1ff, 0xcecaff25, 0xd23c09f2, 0xee2107eb,
+0xd9c0e908, 0xd3bc0018, 0xb3bc051d, 0x29ab261b, 0x0b0bff2c, 0xdf5ae41c, 0xe6ef07cf, 0x2ea10fea,
+0x1db5fac8, 0x083a0cde, 0x4ff5e1ee, 0x4643281c, 0x08dee1e6, 0x1a0e1ffa, 0x2a30f11b, 0x0b4a02f8,
+0xe1f5e321, 0xf5eaf71e, 0x21e3e312, 0xccfffaf6, 0x3932f5d8, 0xe3efeff5, 0x314df518, 0xbdc709db,
+0x1336e5ef, 0xeb2bec0d, 0xc4a6ec02, 0xe3b2eccf, 0x33210b27, 0x1a2b0a08, 0xb536f304, 0x51f7def2,
+0xa946d6e1, 0x0f1fd2e2, 0xd5cee6f8, 0xe60303f5, 0xdc25f225, 0xab360303, 0xd9aa2c0f, 0x30f9ffd2,
+0x611ff8e0, 0xc6fa3909, 0x33241323, 0x023ff505, 0xc3f827e8, 0x1601ebdf, 0x35d91228, 0x0cf70d01,
+0xbc271ce1, 0xbae8e400, 0xed09e310, 0x13ec16e2, 0xbffb1513, 0x3452e724, 0xff010cd7, 0x53ddd9d8,
+0x18da2cfc, 0x3b28f102, 0x1ae1ed00, 0x051c0ff7, 0xe16b23f4, 0xfb4f0844, 0x091fdcd8, 0xbea1e109,
+0xbcdc1a36, 0xd908e5fc, 0xd7f301e1, 0xbd1d02e5, 0x2319e5f4, 0xed0cfbf0, 0xed46eae5, 0x3442ebe2,
+0x0323f4e6, 0xd62a25fb, 0xbec7fd03, 0x3841e6ee, 0xd3cc1018, 0x4d06faf4, 0x31422521, 0x15b1f8e7,
+0x354b12d9, 0xe3ca0dde, 0x1fd30cf1, 0x25ddf705, 0xf5e8fdfb, 0x0a121df0, 0x5bc81e17, 0xd8e8cdef,
+0x000000f1, 0xdfec4a13, 0x0d1e1cba, 0x0ff918d1, 0x00de274a, 0x07242105, 0xe5030cd4, 0xe0f40734,
+0xee02ead7, 0x15dc3d4d, 0x0de3cc46, 0xe817f1ee, 0xfbe3d40b, 0x0d09cbe2, 0xd22256b6, 0x1904bf2d,
+0xea17ee10, 0xe019f842, 0x15ebc33d, 0x39ef6217, 0xe6f8f1df, 0xf1001ad8, 0x1cf90dde, 0x19e40fbc,
+0xe9e6ef0e, 0x0103d72a, 0xeffe3929, 0xf7d83151, 0x11273901, 0x28fdb0dc, 0x07f22f36, 0xddddb505,
+0xe0e3f8ba, 0xf3dc354d, 0xe613f1eb, 0x09f4e2e3, 0xe70df1cc, 0x28d950b1, 0x001128e9, 0xfe312658,
+0xf624cdb5, 0xee1217eb, 0x1ac04268, 0xd414ab15, 0x0d191b0f, 0x0e021b26, 0xe10cba1b, 0xfc09d4cf,
+0x1b2b0c53, 0x0be8343f, 0x04d92c01, 0x01f4d733, 0x0d01cad8, 0x16f2121b, 0xddebfbc4, 0xdff2fa37,
+0x1dea0bee, 0x1b0cf4cd, 0x2ff7a9cf, 0x13da15fd, 0x35fb5c2d, 0x0b0fcd36, 0x0e19ca40, 0xef1e380b,
+0x0303d5db, 0x02fdda24, 0xe30845e0, 0x14fc1424, 0xeef115ca, 0x04e5d40e, 0xde2bfaad, 0x2ddaaaff,
+0xf2e91a3e, 0xd51e530b, 0xdde405f3, 0xd908b11f, 0x0fe0c807, 0xecf0c318, 0x20064723, 0xf814d03c,
+0xe9081120, 0xe0f808cf, 0xdbf4b235, 0xfdf225e6, 0x10da19fd, 0x170fef19, 0xedc53a64, 0xea133e16,
+0x1725effd, 0xe4fbbcdc, 0x0208dadf, 0x1ff50933, 0xf706d0d2, 0x0901cfd6, 0x130515d2, 0x1e1e0909,
+0xe01247e9, 0xbe3f0000, 0x35dbe517, 0xdfcd0d03, 0xff29f9f5, 0xb0c0d900, 0x30eed8e7, 0xdabff816,
+0xaa4203e7, 0xd9f62f19, 0x5453ff1d, 0xdbd32bd6, 0xec07fd06, 0xeedd14df, 0x462debfc, 0x173e1d04,
+0xe423efea, 0x4f6cf505, 0xd701da45, 0xb13602d9, 0xa2fd28f3, 0xeec7c9dc, 0xfae21610, 0xd4c9de0a,
+0xd5db04f0, 0x1503fd03, 0x0360eddb, 0x2abf2639, 0x34fdfde7, 0x462bf5dc, 0x3c1f1e04, 0x1d04ec09,
+0xbdd20cdd, 0x1c561a06, 0xfb1d0c2e, 0x19b824f6, 0xd1f4f120, 0xbe23061b, 0x1dcb1bfb, 0x22f10cf4,
+0xc5f8fa18, 0x5227ec20, 0x33d1d501, 0x03caf6f8, 0xd3fc260d, 0xb9150523, 0x5811e114, 0x211bd0e8,
+0xcd1d08f2, 0x44c2f50b, 0xf3d6e417, 0x0535e5ff, 0xfbccddf2, 0xc102def4, 0xf5d01825, 0xfb27e207,
+0xeff62300, 0x3a1417e1, 0x17b6efec, 0xddd9ef23, 0x2ddefb02, 0x0a2bfbfb, 0xfb561e03, 0x2ceedd2e,
+0x17f50416, 0xc4f3efe3, 0xb9e2ece5, 0xe3e71f0b, 0x47e5f4f1, 0xebdbe1f3, 0xe4e514fc, 0xfc280c0d,
+0xfdbb2501, 0x0508251c, 0x0d0add1f, 0xcb201b1e, 0x2e480df9, 0xf3f2061f, 0xc7181b19, 0xe42310f0,
+0x32b3f4fc, 0xe5c70b26, 0x1ceef3ee, 0x3def0d16, 0x2309ec18, 0x3544fb1e, 0x5050f3e5, 0x000d29d9,
+0xef5b271a, 0x57b0ea33, 0xecc6d0d7, 0xd619ecee, 0xc60101f2, 0x3954efd9, 0xf2db11d4, 0xf7b31afc,
+0x433d20da, 0x0000e515, 0x06f5d234, 0xdef0b6c8, 0xed1dc4f4, 0xe8fef126, 0xe215bb3d, 0x14fcedd5,
+0x0deb1aed, 0xe528f2b0, 0xe0e84840, 0xdd1ab542, 0xe91ec10b, 0xe11ff648, 0xbf0968e0, 0x0ddccab5,
+0x0b1ae30e, 0xe6020ed7, 0x07f42f33, 0xf4e91cef, 0xfbe9d3c0, 0x24e4fb44, 0x12fa162f, 0xe9063f21,
+0x01f6d931, 0x22f806df, 0x1d04f423, 0xdffc4923, 0xe4eff3c8, 0x190af11e, 0x18f4111c, 0x170311da,
+0x16f73e20, 0xdbcb04a2, 0x0dfc1bdc, 0xedf43a1d, 0x10cfc8a6, 0xfb402d68, 0xf2273500, 0x21fc4a24,
+0xfae2d345, 0xe7001028, 0xeaf1ed36, 0x00f329e6, 0x0d1234c6, 0xdf27f8ff, 0xecf8eb20, 0x09f432e5,
+0x0bfacdde, 0xeffbe9de, 0x14e73c40, 0x2007f821, 0xe005b9dc, 0xeafe3eda, 0x0701d0d7, 0x29015027,
+0xe9fdee24, 0xe31ff408, 0x24244db4, 0x03f5dcce, 0xf3151c3c, 0xf5da1e01, 0xe01b0843, 0x02db2b4c,
+0xdcf34c35, 0x07f620e1, 0xf40e1b19, 0x0cffcc27, 0xf9112ec8, 0x3c0e9bca, 0x1615123e, 0xf7ddcf04,
+0xfe0326da, 0x2a26524d, 0x09031fd4, 0xe6dc0dfd, 0xfbf32ecb, 0x18121115, 0x231d050a, 0x011a2abe,
+0xfc0bdc34, 0x0a0632d1, 0xe3dabbb2, 0xeee2c60a, 0x11eae9ee, 0x031ad6bd, 0xf6131e3a, 0x0d22cbb6,
+0x13103c18, 0xf5161c3e, 0xf01ae8f2, 0xf306e42d, 0xed04c623, 0xf1211a08, 0xdbf34d34, 0xe9e6eff2,
+0xd90db1cb, 0x0aedcf3b, 0x3f110000, 0x2dffe818, 0x20fbfbda, 0x08fc07dd, 0xd6182025, 0x9d27fff0,
+0xb5e63c01, 0x295323f2, 0x06d401d5, 0xa0ee22fd, 0x15ec3816, 0xba24ed14, 0xe13be1fb, 0x39360aed,
+0xb60f10f3, 0x15e2dee7, 0x174aedf6, 0x1146ee22, 0xee16171e, 0xed1d1512, 0xd7fdec0b, 0x110200db,
+0xfb5116db, 0xf50923d8, 0xd7bae3e1, 0xc960021e, 0x14400e38, 0x33d01419, 0xc737f407, 0xdc6011f0,
+0xebfd05c8, 0x120ced25, 0x0845e9e4, 0xfaf620e3, 0x394923e1, 0x5217efde, 0xc1c8d6ef, 0x030fe810,
+0xf418db19, 0x0ff3e510, 0x0ec7e71c, 0xfbaae5ef, 0x27c823d2, 0xc3c6ff0f, 0x0ed0ecef, 0xbbd11b07,
+0xb8411cf8, 0x42e6e1e7, 0xafcee50e, 0x29bdd8f7, 0x4cf6ff1b, 0xefe2dc1e, 0xc518e9f5, 0xc313ec10,
+0x0ccfea14, 0xba27e309, 0x0c9ae201, 0x19d31bc3, 0x4aec0e06, 0xfa0e23ec, 0xeac5211b, 0xe9281313,
+0xdd711101, 0xed41fab7, 0xbb2f14e7, 0xd6a1e4fa, 0xb6b3fec9, 0xd0b32324, 0xcbdbf8db, 0x4fb60cfc,
+0x3503d9df, 0x06c3f225, 0xd2c7de15, 0xbefff9ef, 0x0aec1ada, 0xbe401eec, 0xc92fe519, 0xb6bf0ff9,
+0xddbcde1a, 0x2047fb1b, 0xcbbaf91f, 0xa7fdf3e2, 0x30eed025, 0x435b07e9, 0x2efc1b34, 0x0ac70723,
+0xbefce311, 0x4ca719dd, 0x1d04db31, 0xead20a24, 0x2a5b12fa, 0xc613ffce, 0xb52c12ea, 0x03bd23fc,
+0xc9b9dc1b, 0xd0e40e1f, 0x000007f4, 0x0cde354a, 0xd2dcaafc, 0x21d908fe, 0x1bf5f3ce, 0xe40d0d1a,
+0xcd06a42f, 0x0fe7180f, 0xda0c4e35, 0xfe28db00, 0x13efc5e9, 0x08032024, 0xff35275d, 0x22eeb639,
+0xeb2bc3ad, 0xe9ec3e14, 0x2523fd06, 0x06f3d1cc, 0xdb2903b0, 0x0fdfc8f9, 0x18e50ff4, 0x0efbcb2e,
+0x11fae8d3, 0x33e4a545, 0xe22af6ae, 0x1f10ba38, 0xe30bf633, 0x0c06e322, 0x0eeb1b3e, 0x09f1cf18,
+0x10ef1939, 0xe9f21036, 0xee17e9c2, 0x1aec0f13, 0xeff4ea1c, 0x16dbedb4, 0x03eb253d, 0x1400c5d9,
+0xfd00db28, 0xdcda03b2, 0xcdff5a28, 0x0bd6ceae, 0x24f8fbd0, 0xfdecd5c4, 0xdfe4faf3, 0x0cedccec,
+0x0807e030, 0xf6213208, 0xebdfc208, 0xf312cbea, 0x1d21ba49, 0x03f02517, 0xda0e4ee6, 0x14ed3dea,
+0x090ae132, 0xfdefd5c7, 0xe019f9f2, 0xf4121dc7, 0xe7febfda, 0x27ee0116, 0x18fbbf23, 0xff04d625,
+0x252d4eab, 0x271d000c, 0xf8ed3116, 0x2009f831, 0x1b17bd3f, 0x201209c6, 0x2af95220, 0xee0816d0,
+0xd6e352bc, 0x240f04e6, 0xf21d19f6, 0xf41b1cf3, 0x171b3ff4, 0x0c26cd4e, 0xfe05d6d4, 0x021dd7f5,
+0x22cf4a59, 0x14efec39, 0x1c0abbce, 0x12d3c655, 0xe8fb4023, 0x07e82fc1, 0xdae6b30e, 0x1d0af5e1,
+0x27f0ffc8, 0x01ed29eb, 0xe625be02, 0xdfe2490b, 0xf11c1945, 0xca21a1f9, 0xe91810c0, 0x20190842,
+0xf1fec929, 0xe2e9b9ef, 0xe814c0c4, 0x6d0c0000, 0x14d0451b, 0x11aeebf8, 0x393d16d6, 0xa9dbeeec,
+0xdbf7d103, 0xa45e0320, 0x1ab1cbc9, 0x0b25f2d9, 0xbf111e02, 0x2b2e1818, 0xb2000305, 0x1608dbd8,
+0x210e1220, 0xfdf1fa1b, 0x2d9e2519, 0x01d0fcc7, 0xd5b8d9f8, 0x08d603df, 0xce25e0fe, 0xea000a03,
+0x234b12d9, 0xe72ffa23, 0xedf00efa, 0x361614e9, 0x2c3a0e13, 0xe114fd11, 0x2a3a0915, 0xbfe3fdef,
+0xd95a180b, 0xbd20fece, 0xbd391c07, 0x610de4ee, 0xbb0d38e4, 0xee08e4e5, 0x10fe1720, 0x2f0fe8d9,
+0xc92af919, 0xdf24f001, 0x64f0f9fc, 0x1551c317, 0xccf61229, 0xbd39f41e, 0xe9ece511, 0xf9f21214,
+0x1dc5e01a, 0x3ac00aec, 0xbf1012e8, 0x2f00e8e8, 0xdffc07d9, 0x1477f9dc, 0x0c301450, 0xfb0d1cf9,
+0xd92ddd1b, 0x43df0006, 0xcc541cf9, 0x0de40d2d, 0x043c1b0b, 0x48ec24eb, 0xcc27e0eb, 0x2ea1f401,
+0x02e00536, 0xec2c25f7, 0x380dec04, 0xe9faf01c, 0xb01b10de, 0x41f527f3, 0x31a6191c, 0xdfeef6ce,
+0x4632f916, 0x2a2c1ef6, 0xff17fefb, 0x3fc2d9ef, 0xc3e717eb, 0xe70915f2, 0xc7110fe1, 0xe9caf0e9,
+0x3a26eff2, 0x44361301, 0x40f11b0e, 0xedc81818, 0x09d8ebf1, 0x2013e2ff, 0x35ccf8eb, 0xaa2c0ef4,
+0xb033d2fd, 0x03dd280b, 0xd0d926fa, 0x4203f7ff, 0xcff31a25, 0xe8cef7e5, 0x403ef00a, 0x0bd8e817,
+0x30251d00, 0xaa10f8fd, 0x3ea7d218, 0xa708e9ce, 0xdde231e0, 0xc3e5040a, 0xeda7140d, 0xb51715cf,
+0xd2dc22f0, 0xedb70603, 0xfc19ecdf, 0xb2e2ddf1, 0x1e06d90b, 0x28ee0a21, 0xb3c90117, 0x21212510,
+0x31b8f8f8, 0xeae0f8df, 0x48bbeef7, 0xd20e20e2, 0xd029f9e6, 0xdd01f9ff, 0x0726fa27, 0x3a0edf01,
+0x160ced1a, 0x1cb412e3, 0xd24c0b23, 0x01b50624, 0xe1e526dd, 0x321ef7f3, 0x200e0af5, 0x362bf819,
+0x04130efd, 0x1af72315, 0xc7f3f31f, 0x2ad8f0e4, 0x47f1fe00, 0xa9411fe6, 0x0be92ee7, 0x1f2be4ef,
+0x14c30804, 0x5c1214ea, 0xf1cd34ea, 0x5535e7f5, 0x3410d30e, 0xfa2e0c18, 0x4218defa, 0xbcbd19f0,
+0xe6fd1c1c, 0xf5fe0eda, 0xf5e0e426, 0xb1041d08, 0xbf06da24, 0xc0d41823, 0xcfaae8fc, 0x25b0f82e,
+0xd9d5fc29, 0xc8ccff02, 0xf04cf00b, 0x32d0e725, 0xda090af9, 0x5604ff1f, 0x2fef2edd, 0xdce2f818,
+0x1fd30409, 0x4c300afb, 0xe018dcf8, 0xb54308f1, 0x281fdde5, 0xc202fff8, 0x3ca11525, 0xc241ecc9,
+0xc06d15e7, 0xc11ce8bb, 0xf51a180c, 0xb43b1cf2, 0xcd2b2413, 0xefd3f4fc, 0x3e30e8fb, 0x43df1708,
+0xd44ae4fa, 0xe912fd22, 0xeb16eee9, 0xe1aa12ee, 0xe2be0a2e, 0x24f90a19, 0x02b1fbdf, 0x4f33d9d9,
+0x1fe4280c, 0x0336f60c, 0x09bc250e, 0x2b36e11d, 0xf2fffd0e, 0xfd33e727, 0xd2ecdb0c, 0xebdc0614,
+0x16ec13fb, 0x2427ee15, 0x0a5d03ff, 0x2f0a1e36, 0x08e20000, 0xe0eaf813, 0xfe1c2bf5, 0x300c57cc,
+0x13e8c510, 0xe2e50a43, 0x0cdd35fa, 0x040f2c37, 0x0001d828, 0x4404932d, 0xdaddfe4c, 0x012d29ab,
+0xee1ec6ba, 0x1b0ef236, 0x16f6121e, 0xd4faab2d, 0xe9e5eef3, 0xe80d4035, 0xe5f642ce, 0xd8010028,
+0x141d3c0c, 0xe7110fe9, 0x14eac5ee, 0xed1c3af3, 0xd616523f, 0xdef7facf, 0xf2e01b47, 0x2211fa16,
+0x290cb033, 0x29e05007, 0x300d58e5, 0xf82b30ad, 0xf01c370d, 0xd4ebadc4, 0x080c1fe5, 0x1324eb4c,
+0xec13c5eb, 0x08fbcfdc, 0xe8ff4029, 0x08e920ee, 0x02fddb2b, 0xf20ce6cd, 0xe6184140, 0xfd1624c2,
+0x27f0b0e8, 0x1b15423d, 0x151c3d0b, 0x21e0f9f7, 0x16e1c148, 0x11161812, 0x0b0e3435, 0x07fb20dd,
+0xe30045d7, 0xebecc33c, 0xe10b471d, 0x1ceb0cc3, 0xf020e809, 0xf412e53a, 0xe905c124, 0x2eef56c7,
+0x10dbc804, 0x13181541, 0x0913cfc5, 0x0be3cef4, 0x34ed5dc5, 0xff10da37, 0xd827ff4f, 0x11d81701,
+0x13e81540, 0xcddd5a04, 0x090ce233, 0x22db49fd, 0x3d09651f, 0xf5edcc3b, 0x25224c06, 0xf7c8e15f,
+0x190dc0e4, 0xf81fe009, 0x08272fb1, 0xec11c417, 0xefe7e9f2, 0x13e1eab9, 0xe6fdf325, 0xf1f01918,
+0x0c27cb01, 0x0e0d36e6, 0x1a0bbf1c, 0x1122c649, 0x0020d9b8, 0x2120f9f9, 0xd50f531a, 0xdbeeb416,
+0xf0fdc9d5, 0x1ee20bf6, 0x24ebfcec, 0xebf1c31a, 0x00003030, 0xd1570709, 0x5a3707d1, 0x482033f1,
+0xfb262008, 0xb8fddcfd, 0x33301fdb, 0x39fff4f8, 0xf9ac11d8, 0x0115e0d4, 0x0401d814, 0xda3323d8,
+0xc72803f5, 0x0bba1100, 0x48e11de2, 0xe81f1f09, 0xfe3af00a, 0xd105da12, 0xacc1fa23, 0x1bc92d16,
+0x05f90cf1, 0x49f52421, 0x35e6211d, 0xe52f0df3, 0xdf50f3f9, 0xf6c3f9d8, 0xf3df1e15, 0xc45e1bf8,
+0xf9c6ebcb, 0x07ec2111, 0xace8dfed, 0xc606d311, 0x3f161223, 0x3e071712, 0x5e3ae9de, 0xdef5c912,
+0x34fcfae2, 0xd0e9f525, 0x0431f9ee, 0xc2bdddf6, 0x0aee161b, 0x0827e217, 0xdf322001, 0xcfbd06f5,
+0xe0daf71c, 0xde3bf802, 0xe11c0613, 0x013ff7f3, 0x1df1d917, 0x46ecf419, 0x40d41e15, 0xd22618fb,
+0xa1360702, 0x1d25c8f3, 0xe0310a04, 0x0939f8f7, 0xe8a51e11, 0x1fbe10cd, 0x4126091b, 0x3c2ee6fe,
+0xdae21406, 0x2624fff6, 0x37380205, 0xb4db0ff1, 0xfddd2504, 0xe51eda05, 0x09c1f30a, 0x15f420e9,
+0xb138ed1b, 0x26142811, 0xc41e0315, 0xba1eedf7, 0xe3ce1e0a, 0x9cef0b0a, 0xfbe2c4e9, 0x370f23f6,
+0xc4f9f019, 0xdb5fece0, 0x140f03c8, 0x1ec115e6, 0xbecd0be8, 0xd1cce60b, 0xc3b007f4, 0xe9ca1628,
+0x1adbf00e, 0xbdbc0efc, 0xc930e51d, 0xb42cf2f9, 0xc2a723fc, 0x35fa17cf, 0x539b0edd, 0xfaffd63d,
+0xe4b62228, 0xe3fc0d22, 0x4ab40a24, 0x3a0cdd24, 0x13bc121c, 0x15e30000, 0xfcee2c3a, 0xf7f2e1e7,
+0x1528c2b0, 0xe51c0df4, 0xdc03fbdc, 0xffe12af8, 0x1c294451, 0xfc18db10, 0x1f0048d8, 0xdc06032f,
+0x0bdee2fa, 0x04162cef, 0x09e7d0c0, 0x0c24e34b, 0xbddc6bb4, 0x09f72032, 0xe11d4746, 0x0bf2e4e6,
+0x2122fab5, 0xd60653d3, 0x30dda84a, 0xfded2b3a, 0x1de80b10, 0x08ead13f, 0xd3055522, 0x2610fe37,
+0x34fc5cd4, 0x1fecf614, 0x0cf41ce4, 0x16f7ed1f, 0xe6150e12, 0x0c00e427, 0x11ee3917, 0x0eee363a,
+0xe3de0cfa, 0x24054c23, 0x2efb5623, 0x27d00058, 0xe71441eb, 0x231b4bbc, 0xf3141c3d, 0xb9f66f32,
+0xd3ecab3c, 0xeb04122d, 0x1a1ebef7, 0x0c0fcce6, 0xeae81240, 0x14ec3c3c, 0x41ea9711, 0xfeded64a,
+0x00ccd95c, 0x22fef926, 0xec063b2d, 0xeae93f3f, 0x1ffff827, 0x25264cb3, 0x180a101e, 0xdcfc0523,
+0xf1dbe7b2, 0xfbe424f4, 0xe9053ed3, 0xdafc4ddc, 0xea23c2b4, 0xf2fe1a26, 0x252403fd, 0xfd0e2537,
+0xd01b59f3, 0x101be80d, 0xd9dd4fb5, 0x1edf0a08, 0x27e702bf, 0xd9f400cc, 0xf914d214, 0x1debf53e,
+0x1524ee05, 0x121f3a0a, 0x01dcd604, 0x3901a029, 0x1dfef629, 0x11dc1804, 0x23f00538, 0xfd1124c8,
+0x32215a07, 0xf7173112, 0xdc0e4dc9, 0xe00008d8, 0x1c1dbc0b, 0x200c09cc, 0x0805e0dc, 0x14e03bb8,
+0x2bf3ac36, 0x2f0aaacf, 0xeadc124c, 0xff16d8ee, 0x01f3da1a, 0x0000163b, 0xfaf213ed, 0x0a08221a,
+0xcebf1f20, 0x46dd0a1a, 0x3fcd1e05, 0xe7cee8f5, 0xf23410f6, 0xedf0e50b, 0xef42ec17, 0x08fdeae6,
+0x975ce0db, 0xca19bf34, 0x241b0df0, 0x27bd04f2, 0xf8f8001b, 0xccbfdfe0, 0xf607f4e6, 0xec4ce3e0,
+0x17d614db, 0xdfd0effd, 0xf751fa07, 0xc7081fd8, 0x225011e0, 0x16e7fbd8, 0x2af71210, 0xef32fd1e,
+0xf5e9ea0a, 0x11f2e411, 0x26cceae5, 0x4e00fff3, 0x724f2728, 0x29ea4a26, 0x1aca00ee, 0x460df30e,
+0x201c1ee4, 0x46dff7f3, 0xd3d41ffa, 0x3beb04fc, 0x4401ed14, 0xd3b3e4da, 0xc03cfb25, 0x1c1de7eb,
+0xcccc0bf4, 0x2ae10df5, 0x402802f7, 0x0117e901, 0xc201d9f0, 0xf7fc15d9, 0xfedc2024, 0x24c82503,
+0xc1fafdef, 0xfef2e9de, 0xd4c1da1a, 0xaff104e8, 0xc12a29e6, 0xb625e8fd, 0xd7c72204, 0xb5c4ffef,
+0xcd45dd15, 0x25330a1d, 0x3ff0030b, 0xa9b2e917, 0x25c12fd9, 0xc23a0218, 0xd2bfea11, 0xe3170518,
+0x282a0aee, 0xda0300ff, 0xfeb6fe26, 0xebd5db22, 0x1ce6edfd, 0xe4d4f5f2, 0x16f2f404, 0x26c8ee1a,
+0xe2e9feef, 0xa8fbf5ee, 0x01073123, 0xe843d920, 0x1416f0e6, 0x0b24ebed, 0x5123e204, 0x0000d7fa,
+0xbd290000, 0xbef21bfe, 0x19eee7e7, 0x0000f1e9, 0x00000000, 0xfa490000, 0x17e0df22, 0x000012f7,
+0x00000000, 0xbadc0000, 0x0f3fe1fd, 0x00001a17, 0x00000000, 0x31c60000, 0x09ee0000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+hard_output0 =
+0xcddb5769, 0x627f0a91, 0xbcf446fb, 0xc930d133, 0xdd7b82f0, 0xbd591856, 0xb73094b3, 0x32436132,
+0xac268fdc, 0xeeb03845, 0x0087cc79, 0xd372eb62, 0xb595a1bd, 0x511605f7, 0xa428b83f, 0xfb9380a8,
+0xe43c2efb, 0x0a04017a, 0x674608a3, 0xc2464812, 0x208bc693, 0xb03d0580, 0xdc62b803, 0xc2808805,
+0xccaf7f16, 0x848dacef, 0xedf69b49, 0x222d2bd9, 0x78ffa7a5, 0x749cb755, 0x9f4abc69, 0xa27f3a72,
+0x9652d070, 0x8a83be54, 0xa9820b7f, 0x8b00e52a, 0xb02159e4, 0xeddabc6a, 0x47b69064, 0xf161d47f,
+0xc243b0df, 0xebb2ac39, 0x4fd6cddb, 0xc0d38ba3, 0xd9ddef17, 0x8c638875, 0xa132cfef, 0x5893a4f6,
+0x1a29ce5f, 0x9072f3eb, 0x486bda03, 0xf5250cda, 0xdc10edbc, 0x392e6b7f, 0x4664de06, 0xfde2f3f2,
+0x37c7d442, 0x32b60d29, 0xbcb7c8ff, 0xa1542cd0, 0x91b36e18, 0x231f9e19, 0x97cbc4a6, 0x51ceb1df,
+0xc02dedf8, 0x4bfd9728, 0x569deda7, 0xc0790501, 0x132e47b0, 0xb8229185, 0x81cbe103, 0xa30dbf5f,
+0x72c54db6, 0x4abdbdf7, 0x557d21d3, 0x3b75be17, 0xf540476b, 0xc48d78e1, 0x767d44ec, 0x87dc6193,
+0x7a4c52fc, 0x306c3548, 0xa66e51b3, 0xfc627273, 0x5f349268, 0xf5e74974, 0x232388b6, 0x01d8e49e,
+0xbf29f75f, 0x378a9d02, 0x59a45656, 0x46fb25b1, 0x75219b62, 0x4f0d6f71, 0x220c6763, 0xdde47b70,
+0x8c0dce8f, 0x3e3db100, 0xabad4262, 0x800eddcb, 0x32416450, 0x61d260ce, 0x6e2a0fac, 0x73cdb847,
+0xeee01947, 0xe5a3a37f, 0xa710e211, 0x98ecaa36, 0x69197474, 0x6e73e13f, 0xb2100f2e, 0x7714b2fd,
+0xec3d81cb, 0xc50e5194, 0x5c69a3d8, 0xce0bdc13, 0x08e7df1c, 0x5fb014a5, 0x75b5801e, 0xf57d3b75,
+0xac5dd149, 0xa5096b77, 0x4b5da0af, 0x656506d3, 0x3823d675, 0x3840530c, 0x1c0980ba, 0x3bd4150f,
+0x3df8c0f8, 0xa2834aa4, 0x479ea855, 0x4f4557b5, 0x15d730db, 0xe6809738, 0x0aec8f7d, 0xf5e2188e,
+0xa9a0fac7, 0x785c3166, 0x049dd244, 0x72cada2a, 0x5655bab3, 0xff73ca65, 0xb3dc51f1, 0x259f555b,
+0xdaa1933d, 0x0f716b8f, 0x1e29bde6, 0xbe8bf3a9, 0x908b5a60, 0x667636c0, 0xfce80b0b, 0xcf43d154,
+0xfffc60f5, 0x324b1632, 0x1609e45b, 0xf8e09aed, 0x1a01f6ee, 0x013cea78, 0xdd89ba42, 0xfe5bca8f,
+0x894e3aef, 0xda292f76, 0x457a93bd, 0x73a9c254, 0x7b5ca9d1, 0x947355ba, 0xb8a797c8, 0x3b5e97f4,
+0x946889ec, 0xd49316a3, 0xa5383830, 0x55f63bbf, 0x47b3a4ca, 0x415bd007, 0x1227c60a, 0x3610fab0,
+0xa68c75fc, 0xa1441c62, 0x68a02596, 0x6d083d07, 0xceeb9057, 0x915054bc, 0x6f2c7fa8, 0x62be6166,
+0x963703a3, 0x5af6e614, 0x5bc3e4f0, 0xf517a95e, 0x408a2bfd, 0xab7fe7a8, 0x37aac030, 0x9956f2f5
+
+k =
+6144
+
+e =
+10376
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE, RTE_BBDEV_TURBO_CRC_TYPE_24B,
+RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_posllr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_posllr.data
new file mode 100644
index 000000000..fe4f5eefd
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_posllr.data
@@ -0,0 +1,645 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x81814e1f, 0xba81fb11, 0xc4554696, 0xe17e9454, 0x427f8119, 0xa8b355f1, 0x244ba17f, 0x1c816fa1,
+0xc94f5bcc, 0xb5b97fbb, 0x634b8e81, 0x815a6cc1, 0x7f6bb016, 0x2f7249d6, 0x604664f0, 0x31817f81,
+0x6fa66b81, 0xd49763f6, 0x777fa4f1, 0x81aa6da8, 0xf0fea881, 0xaccfbfd0, 0x7f81e582, 0x7f58a2d6,
+0xa77f430e, 0xf47f50f1, 0x997f42f2, 0xd7814f81, 0x037fe14d, 0x81f98125, 0x2d813e55, 0x7f81f0dc,
+0x7f7f8181, 0xc37c723a, 0xbc7a3364, 0x8193817f, 0xe381066d, 0x7fcab836, 0x2481eea2, 0x567f5968,
+0xa07d720c, 0x7fa13343, 0x7f35636d, 0x7f817f78, 0x383d2a69, 0x7f860e2a, 0xca78797f, 0x7f7fe912,
+0xc95a8141, 0x770c9c4e, 0x81e2817f, 0x811b3f81, 0x745f1104, 0x13817e31, 0xb681a63a, 0x8101482a,
+0xbe81818d, 0x8c8181fa, 0x2133de57, 0x8147677f, 0x8a098d7f, 0xd429f1ee, 0x284fc81f, 0x7f5c16d7,
+0xded34e7f, 0x3d60812e, 0xdf817f89, 0x2f33793c, 0x2f7f9961, 0x8181221e, 0x847f59d1, 0x9281a681,
+0x89503793, 0x01817ff0, 0x183a53ba, 0xc99622f6, 0xbc819881, 0xa7ea2ec8, 0x787f957f, 0x26819378,
+0x1e4e4ba1, 0x8bf18138, 0x3adc2c81, 0x3a7d8187, 0x7f22ae8e, 0x307c81d7, 0x7f53a881, 0xc281819f,
+0x38fd2090, 0xdd810a00, 0x74ff7fa2, 0x7fb2f27f, 0x7f9b8211, 0x55d69e44, 0x8d2cd44c, 0x5610c676,
+0x7f815b81, 0xa2811e3d, 0x93135d81, 0x92797f73, 0x8a8192b3, 0xa48a7f66, 0x7f7e4a10, 0x242dfd81,
+0x7fe8b481, 0x810fb0e4, 0xde390fa7, 0xbb5a7f81, 0x65ad3b19, 0xa96a96a2, 0xf681817f, 0xb6a4eba2,
+0x0d81017f, 0x5369080e, 0xfbd1c781, 0x879d7f7f, 0x81818181, 0x7f1d061c, 0x8aa731fd, 0x4386a67f,
+0xba445581, 0x5b81975f, 0x467f7f7a, 0xc85db95e, 0x6f587240, 0x29a07904, 0x7f7f7574, 0x815dbeb2,
+0x81771181, 0x7f54e8c3, 0xc6586fd6, 0x3c6d835a, 0x86b4ed95, 0x7faa72fb, 0x7f7e7fd5, 0x154f81e3,
+0x7c4881b4, 0x0c164a37, 0x7ffdbf69, 0x7f7d43f6, 0x5f47da8a, 0x3236d20f, 0x65818181, 0xa37fcf7f,
+0x7f8116cb, 0xf6947f50, 0x66ab65b1, 0x6d688a6f, 0x537f6bf0, 0x5c864ddc, 0x06a98181, 0x455854c2,
+0x9a6c49ad, 0x129d3c29, 0xe94c327f, 0x7d40247f, 0x9681bc7f, 0x7f288120, 0x81a43b40, 0x08d81689,
+0x457f815d, 0xc27f9ae7, 0x7f819655, 0xdabf8181, 0xf4c07f81, 0x6410e8cc, 0xce4d8181, 0x19b13059,
+0x8181bf99, 0xf2819620, 0x7fc37f4e, 0x7f8efe81, 0xb25a3e8b, 0x7fbbdb22, 0xba7f8181, 0x8135d42f,
+0x817f6836, 0xc381a056, 0x7381547f, 0x1e407f13, 0x9b917f7f, 0x4e526d9b, 0x9323737f, 0x7a20429b,
+0xac6b14a8, 0x3568e8d7, 0xbe621a97, 0x7fbca13b, 0x2dbda9dc, 0x32af4ddd, 0x6e4f978e, 0x10ed8172,
+0x81e76681, 0x7f427fc4, 0x7fab7f81, 0x2c7ffd81, 0xea817f7f, 0xa62fcf2c, 0x8144bfb7, 0x7ffc93a0,
+0x79e9b564, 0x6c449d46, 0x987f8481, 0xee118173, 0x867f0c0a, 0x81819347, 0xb8ddbf82, 0x5c6866b8,
+0x82b48881, 0x5c817fdd, 0x7f6605e0, 0x4181bc81, 0x736b51a4, 0xcd5a7fd2, 0xf939a42b, 0xcd817faf,
+0x5e1b1fa6, 0x7c818ef7, 0x070c47cc, 0x8e5981d1, 0xe661d182, 0x54deb54e, 0x7fba81f4, 0xc1712e73,
+0xb6885086, 0xae9759e2, 0xb12b814e, 0xf5ae9e41, 0x16c736f6, 0xa981c3e2, 0xb06c7f29, 0x497f95b8,
+0xcb3de381, 0x7f7524e3, 0xdcf88147, 0x811e81f9, 0xab7a9c7f, 0x816223d8, 0xf97fe22f, 0xe5cf814e,
+0x744f6312, 0xc797e05a, 0x279b237b, 0x622b01b9, 0x37818181, 0x8174e3ab, 0xfa5a69ff, 0x62cc787f,
+0x81944e7f, 0xc87f7f2f, 0x30839f54, 0x8122090f, 0xf8e98181, 0x28815f40, 0x0262424b, 0x7fc3ccd0,
+0xdf7f7fe2, 0x0c264dfa, 0x5d954581, 0xfb188181, 0x6b810d33, 0x1c7fbee7, 0x8141c17f, 0x7f768155,
+0xbd207f27, 0x794079d7, 0xf34bd97b, 0x7f7f5026, 0xb46c9782, 0x7f81574e, 0x81817f27, 0x75267f6d,
+0x4a7fe97f, 0x7f879ee0, 0x25f8d63f, 0xd481a3c5, 0x747ffd0d, 0xb33530e2, 0x813f5881, 0xbb8181dd,
+0xa2da462a, 0x817f8c0d, 0xd0f061f8, 0x117bda34, 0x1897f8b7, 0x2e477f50, 0x8181814b, 0x7faa1181,
+0x6ee68168, 0x811a98e2, 0xdcb2b784, 0xa20a7fb7, 0x41445681, 0x0bffeefc, 0x02817f9d, 0x743071cf,
+0x387695bd, 0x847ffb4a, 0x0a287f56, 0xf9b4d4d3, 0x2a7fa481, 0xe3eb2e9b, 0x327f91f4, 0xec3981d2,
+0x6681f83c, 0xe675722e, 0x426ac913, 0x4b6154a6, 0x5c30816f, 0x817c8155, 0x277fa781, 0x8dd8a9a3,
+0x48c609a0, 0x4bca47bf, 0x7f3f6d81, 0xea497fb3, 0xc181507f, 0x81bf1ffe, 0x8e818916, 0x6ba83d7f,
+0xb8547f62, 0x5881670e, 0x7f6281fb, 0x6e7f9250, 0xa7bc817f, 0xb19450aa, 0x7f7f9d58, 0x20f69c1e,
+0x7f45815d, 0x817f9319, 0x7a5496b0, 0xb85e8950, 0x72c9337f, 0x81781aba, 0xfecdaf28, 0xe2195ab5,
+0x7fbb0ec7, 0x7f7ff8a7, 0xab818181, 0x978f2e6e, 0x7fc38121, 0x18945319, 0x264a8181, 0x93b1dc81,
+0x630ed781, 0xe27f8e14, 0xc17f5b93, 0x7081fe2d, 0xbb9ac790, 0x7f81ba5c, 0x7f812f32, 0x68bd4f7f,
+0x81217f81, 0x88b87f26, 0x285e7f3e, 0x29817828, 0x747f7f81, 0x159eaacd, 0x8d02b252, 0xa98881e7,
+0x817f1681, 0x367fbd38, 0x8a8441e3, 0x81447f1f, 0x8165424b, 0x811676ee, 0x81a48122, 0x4b02ea7b,
+0x5c267f38, 0x8195acd2, 0x7f7fb581, 0x9eae092d, 0xab12457f, 0x96f8dc31, 0xa89fd810, 0x222b7f7f,
+0x1dd67f65, 0x873a81e0, 0x0e7fd97f, 0x81a83d97, 0x8106d381, 0x7f817f0c, 0x8104d4f9, 0xbb81677f,
+0x01be7f39, 0x297297ab, 0xc2f01b81, 0x9dd57f81, 0x81ff692f, 0x7fc28115, 0x077f547f, 0x717fcf81,
+0x3d81ed83, 0xff6f7fff, 0x7f50f95c, 0x5650a753, 0x81817f09, 0x963b7057, 0x7f817f60, 0x987fa099,
+0xf6207f7e, 0x4c814e98, 0xcd27b681, 0x41bd2ebd, 0x340172b2, 0xbc151ec1, 0xf3b403d2, 0x817f6c81,
+0x7f2f3218, 0x26f2ea5d, 0xcc59bd8a, 0xef857f52, 0xe37bc195, 0x7f2a2e13, 0x7381a51a, 0x31e14c60,
+0xc2e23fc6, 0x8113f40c, 0x9b2d7f81, 0xf6e1147d, 0x813c7fe1, 0x9a9d7f3f, 0x7fb939ac, 0x573181ad,
+0x608a317f, 0xb486b9ee, 0xe67fb10b, 0x62817f8b, 0x7f7f9775, 0x81e6819d, 0x7f6f0f61, 0x4ffd8158,
+0x81ae56d2, 0xbe4aa4f7, 0x6c515581, 0x435d8326, 0x7f0e2a95, 0xc28d81e1, 0x357fa0cf, 0x2b9f7f11,
+0xd491057f, 0xbc7bddd7, 0xe5b57f34, 0xfba68549, 0xb491d2e3, 0x4fb61f49, 0x81bd3e3c, 0xdd9848f3,
+0x81810561, 0x67f5fbdd, 0x8c4dc25b, 0x2ab47f67, 0x68137f5e, 0xcfe53817, 0xa7679d31, 0x501213b4,
+0x7f7f1390, 0xbefeccd8, 0x30fe9044, 0x7fd6812d, 0x813cf0e6, 0xccb82825, 0xfa78ec58, 0x024b90e4,
+0xba25ec7f, 0xc43b50ff, 0x7f7f3e4d, 0x64c38181, 0x81ed1dba, 0xd58b7f64, 0x0b81311f, 0x03563b7f,
+0x817fb491, 0x81e895c7, 0x817f7fb0, 0x1681a581, 0x7f998a50, 0x489b81a9, 0x81bc81a2, 0x3d9e7fde,
+0x7c7c6381, 0x817447ec, 0x6e7fc32b, 0x7fab86c6, 0x95b44181, 0x3a7f756c, 0x81458168, 0xc4787fd3,
+0x731cda81, 0x73127f03, 0xc9077fcf, 0xc37f9c2e, 0x27817f7f, 0xc4361507, 0x7f9b3581, 0x9d357f2d,
+0x7f81166c, 0xb87f815f, 0xb2604f95, 0xc44b5591, 0xcfb8078b, 0x7481e64b, 0x8152a679, 0x53fa387f,
+0xfa7f3f79, 0x7f5b5fe5, 0x1e625d7d, 0x1081ad93, 0x7f5019fe, 0x3d8145a7, 0x629f9918, 0xc1ab3742,
+0x7f66c057, 0x9cb048dd, 0xeb6e859b, 0x8e5fb72c, 0x94d8f5a4, 0xa381280d, 0x67737de6, 0x45817f81,
+0xf055c17f, 0x6a0aafff, 0xdb818cc6, 0x81fc60dc, 0x20377f4c, 0x7feac6de, 0x72e78c7f, 0xdf532124,
+0x81d33356, 0x8881bcf9, 0x95817f32, 0x612eae3b, 0x7b186965, 0x50b77f63, 0x718181b3, 0x42d8b481,
+0x88edaf7f, 0xa3cd25f6, 0x7fdd7f81, 0x7fb79681, 0x7f786e7f, 0x7fbb41c9, 0xd2618121, 0x1cacc6d3,
+0x7fe2a0dc, 0x819e1a46, 0x563081e1, 0xb18d77b1, 0xb4817f7f, 0xa97f81fa, 0x2e81157f, 0x31e67fa4,
+0x5b814281, 0x98b18124, 0x7f0a3540, 0x49d508d1, 0x2693bc71, 0x3aeb81ca, 0x817fc081, 0x6674b9e7,
+0xa1217f23, 0x517f81f1, 0x7fc4ef26, 0x2914ef7f, 0xa9ff7a19, 0x7f7f0ce2, 0x1b485e45, 0x7f70af0d,
+0xd6812a71, 0xc95fc63d, 0xa57f03c8, 0x9dbe7f81, 0x7c978192, 0x81a22306, 0x96447f2f, 0x7faf2728,
+0xc2a494ad, 0xd5c7813a, 0xa02b7bb8, 0x3bc04eed, 0x997fa97f, 0x7768d0d0, 0x8a84817f, 0x8f1102c6,
+0x7f8115be, 0xfb7f7869, 0x7ff25de8, 0x6745f276, 0x0f23b585, 0x52933552, 0x7fab5340, 0xeb4c403f,
+0x7f5465ec, 0x77b0a942, 0x6b67297f, 0xc86a7133, 0x7f8f177f, 0x869e28f4, 0x7a7fb066, 0x81a3b865,
+0x5d7fba81, 0x815fd7ae, 0x60817ff7, 0xa633a381, 0x45813981, 0xade1ccd7, 0x814981a6, 0xaa93770a,
+0x7f83b4dd, 0xc0967f1a, 0xed7f3764, 0x53772ea8, 0x5a81f453, 0xaff56f92, 0x81067f5f, 0xf596ef1f,
+0xd520de7c, 0x81b2bdc8, 0x7f8130dd, 0xfb7f8c41, 0x99816bf6, 0x695a60e3, 0x7f7f817f, 0xed987f26,
+0x8f818166, 0x417fecfc, 0x99ec379b, 0xaf7e7f7f, 0x360dd75f, 0x787f44f6, 0x81837dfb, 0xd481a681,
+0x81819d17, 0x8781322c, 0x7f7fac0b, 0x0fca7f3c, 0x40b5e37f, 0xf27f2ebc, 0x41c19a41, 0xa6c1d381,
+0x066de9ec, 0x32b8a8bc, 0xdac61ba5, 0x812d817f, 0x87b9821c, 0x817f7920, 0x7f557fbc, 0x81738181,
+0x918fb098, 0x81ab890a, 0x81b881bf, 0x7f7fc57c, 0xcdbde77f, 0x7f5f7f3a, 0x36e59a81, 0x19a6818f,
+0xea7fd850, 0x20606e2b, 0x927f9c22, 0xd27f819f, 0x3c4f7f73, 0x168176ce, 0xf0687f81, 0xec5f7faa,
+0x23aa789e, 0x2de996b5, 0x7fd07f7f, 0x9785c156, 0x1eaa3235, 0x9781ea6f, 0xb2de74fb, 0x815a98d6,
+0x8cb77f92, 0xbba85fa1, 0x61afcac8, 0x81817f64, 0x8149865f, 0xa251b7ee, 0xec7f8181, 0xf8ad7f84,
+0x5c8142bf, 0x212981f2, 0x7fc9e381, 0x37338e67, 0x7f3099c6, 0x4fcdb7d1, 0x0381c0fd, 0x778181e4,
+0xe7702cfb, 0x61c21e43, 0x3f987f81, 0x3a0b815c, 0x7d12b8c2, 0x70097f0a, 0x7f244d63, 0x2d81187f,
+0xd87f6f7f, 0x7d267f2c, 0x8eaf2486, 0x87d8013d, 0x85367f7f, 0x81817f85, 0x0a067081, 0xc96f952c,
+0xf3c14485, 0x227f4330, 0x60ec8124, 0x41f181f5, 0xdb6b7fce, 0x819467cf, 0x81bc7fd4, 0x2c7a7f7f,
+0x936ade53, 0x7f81d04a, 0xc4817f81, 0x7fdd78dd, 0x81d3a47f, 0x917fade5, 0x6c81510e, 0x5b16fd74,
+0xbe987f81, 0x7fb17404, 0x7fb8e8f7, 0x7fb381e6, 0xc479b081, 0x5c81eee7, 0xb19b0e81, 0xa381d4df,
+0x81bacf5b, 0xa67fb9a6, 0x817f11a0, 0x8d565870, 0xce818181, 0x7f4aec3f, 0x813ab981, 0x1b495a42,
+0xab7f928d, 0x8106014f, 0x47c3e57f, 0xc418f11e, 0xc9149f6c, 0x1a7f1e25, 0x7f3f2d81, 0xcd5e462d,
+0xa8d57f7f, 0x812481db, 0x7f697f97, 0x69cdb891, 0xc31fc20d, 0xdc812b31, 0x57e37f81, 0xa09681aa,
+0x7f817f88, 0x1ae385f8, 0x81607f7f, 0xfb752e65, 0xd8dd8141, 0xb17f50a9, 0xb8737ffd, 0x1f7f815b,
+0x7f9a9e69, 0x06448b38, 0x8109a225, 0xb69e064b, 0x9881537c, 0x59dee4d8, 0x89c6a692, 0x0e817b7f,
+0x81816b97, 0x5de37fd1, 0x7f2c7ca9, 0x81784402, 0x29bd477f, 0x81a07ffe, 0xe822df7b, 0x7f29813c,
+0x6d81cd81, 0x1a811bd2, 0x6b2c7f26, 0x7881a08f, 0x7fd0e88e, 0x27f87fce, 0x8181a67f, 0x7f7f5558,
+0x81668133, 0x8181bfca, 0xc3792d58, 0x2b7f2d7f, 0xa3d09230, 0x9fa56824, 0x7fd5ce7f, 0x251b3cbd,
+0x7f818117, 0x7fac9e26, 0x7fde26f6, 0x4b7f837f, 0x1fd52b94, 0x067f6698, 0x70817f7d, 0xdd9658c1,
+0xe5a99465, 0xa59cdc55, 0xc1c2c7ad, 0x147fb081, 0x234cc657, 0x7f7fcc0f, 0x7f3d8150, 0x41b68131,
+0x7ff58184, 0x90a57f2b, 0xdd9d9b7f, 0xc4518163, 0x428aa37f, 0xe866ef52, 0x7f6c3644, 0xa09d3b50,
+0xf2c4adad, 0xc87ecb45, 0x7f70bace, 0xd5697f2d, 0x297349a8, 0x6bc11cc9, 0x8cdd0ed3, 0x7f53646b,
+0x8129b9b8, 0xce65a8d3, 0x20208181, 0x817f5272, 0x6ad11bf4, 0xc58151e3, 0x361572c9, 0x81acd996,
+0x6e819466, 0x7e7fbd3f, 0x70bb9ffb, 0x818b810a, 0x879a7f15, 0x8c884edb, 0x9028ae45, 0x81d8f525,
+0xaaa781b9, 0xaf1a0108, 0xe2817f73, 0x24b67f8b, 0xf08fd77b, 0xd21a265f, 0x7f3930ba, 0x5f5d9287,
+0x66218181, 0x7fd219f3, 0x6f44f09e, 0xbcc58157, 0x7f71b94d, 0x817f81c5, 0x877f6064, 0x81647f81,
+0xe5ba2e34, 0x889f8722, 0x27819f0e, 0x7f4c0eed, 0x2d7f79b6, 0x81b1813c, 0x647f3d2b, 0xe92b68be,
+0x81375804, 0x6798c04b, 0x2b596e7f, 0x78c97f7f, 0x812c367f, 0x7f468112, 0xa352d785, 0x3806f2a4,
+0x6886a9a9, 0xa31540ea, 0x5ab2478d, 0x9f5be57f, 0x9ab06481, 0x1586279b, 0x86267f81, 0xb3a50944,
+0x788a485c, 0x838d4c30, 0x8ad44b53, 0x923fb39a, 0x95035381, 0x81817ff2, 0x7f44d5eb, 0xf17f8164,
+0x39d117c0, 0x37ea75f4, 0x81927387, 0x817f0623, 0x909f7f0a, 0x997f7f19, 0xc1983b18, 0x60937f6b,
+0x8829c381, 0x8e6bf066, 0xfb7781ab, 0x43408e7f, 0x7f7f811d, 0x33eb81d0, 0xb86459a9, 0xadba7fe7,
+0xc1967f48, 0xfd0284bd, 0x4bef335d, 0x1b7f5f81, 0xa2c2c237, 0x81b0816a, 0x42ee5c7f, 0x7f009323,
+0xb7ced44c, 0xd90958e2, 0x3af8aae8, 0x7fb82e90, 0x989a7f7f, 0x14a22c68, 0x60ef7dc6, 0x7fb9ad00,
+0xf9e3c69d, 0x5e3bafbe, 0x81178a81, 0x92c4df02, 0x159d7fb6, 0x812b8103, 0x616f9df5, 0xb9a1df61,
+0x454b3944, 0x98931fbe, 0x4aae7061, 0x9572a681, 0x8178a8a8, 0x81fe821f, 0x817f7f6f, 0x7f787f2c,
+0xe584ff82, 0x7b7f5637, 0x9e815970, 0x517d8181, 0x97faba7f, 0xcfe3ce17, 0x9181f55f, 0x857f5f3b,
+0x81b17fbc, 0x7f1d7fbc, 0xae7356c3, 0xe4f77f8b, 0x4695f639, 0x8ddaec55, 0xa5d4a381, 0x7f7fa418,
+0x4d818145, 0x3881723b, 0x7f507f7f, 0xa5357fca, 0x81dbdc3b, 0x0b187f28, 0xb0325181, 0x09dd795f,
+0x2c39b28c, 0x9ac18118, 0xda52b681, 0xa3819da8, 0x7f884525, 0xba0d7ffe, 0x50ce81ad, 0x60e70e69,
+0x110b81ee, 0x8181871e, 0x7fe07f81, 0x8d1c4dde, 0x67649db7, 0x6e4669c2, 0x818144a4, 0x7f6c9cb7,
+0x51b57f81, 0x36aec300, 0x7f7f8141, 0xc5eca67f, 0x14ac7892, 0x7f35e9c2, 0xa1fe9a81, 0x6a867f7f,
+0x767f817f, 0xc447c4bf, 0x067fedca, 0x8c024b57, 0x7ee5707f, 0x52589b51, 0x0f81b28f, 0xae7f00a7,
+0x5244c5ca, 0x9671812e, 0xf0631d15, 0xb4aba1b8, 0x7f9a3488, 0x81b485b8, 0x392f2d7f, 0xed7fad81,
+0x6055a4e1, 0x60f300c7, 0x7feb817f, 0xd1e0917f, 0x544ca57f, 0xd23d7e0d, 0x8110c8c2, 0xbc24a615,
+0x3d817f33, 0xbdabcdfa, 0x5ac3817f, 0x81817fc0, 0x81817f76, 0x837e43d9, 0x7f817581, 0x5da96bcb,
+0x3e1c888f, 0x7f7fa6f5, 0xb769907f, 0x8eb43d8e, 0x3a7f3e81, 0xd5845510, 0xd07f5a54, 0x14816ab2,
+0x8126c62d, 0xbeda8f5c, 0xa0007fa8, 0x818d7281, 0xad72917f, 0x49c2f650, 0x87969baf, 0x7f53e975,
+0xe78de481, 0xe5083e96, 0xb635812c, 0xafdf4bb9, 0x26ac8101, 0x82b0a109, 0x7f8101b8, 0x607fc7cc,
+0xc3b1892f, 0x7d0dd911, 0x396d8195, 0xcb84b67c, 0x3f7d3681, 0x43a07f25, 0xd020297d, 0xb7d65b81,
+0x455a99e2, 0x509e4611, 0x817f81e0, 0x81da81a8, 0x8147b5c1, 0xbc81a5df, 0x489c6781, 0x8150a908,
+0x4fc0e681, 0x814b8163, 0x11457f8b, 0x9a77db7f, 0x81fa0681, 0x7f867010, 0x852b87c5, 0x3d8253dc,
+0x91165c42, 0xc6ac7422, 0x727f0774, 0x7f497f67, 0x1a3fe7c0, 0xb39c81d1, 0x44a47f7f, 0x7f8b066f,
+0x7f787ab5, 0x7ba7e870, 0xb932a3a9, 0xc85c1149, 0x32a28d61, 0x7f8d812c, 0x93819da2, 0x647ae98c,
+0x777f7e9e, 0xbb447fec, 0x2fabd677, 0x3a7f8c08, 0x51707f28, 0x35f81da5, 0x0b3cfc4e, 0xd4179b8a,
+0xef77a6ca, 0x31e02016, 0xdbb81924, 0x7189b4a7, 0x08a671aa, 0x817f2352, 0x81819e81, 0xec7fb7e4,
+0x81699ae5, 0x88817f20, 0x5ee7d181, 0x944d8150, 0x7f7f52d9, 0xc1815114, 0x3281a67a, 0x52fa8181,
+0xc4e47f7f, 0x7f824cbd, 0x728cf0bf, 0xa6b20e46, 0x9ffe631c, 0x639d82cc, 0x7f638136, 0x7f7f3381,
+0x7f8b4794, 0x44b19231, 0x08da5253, 0xaa815d93, 0x7f6a7f69, 0x616331c2, 0xdaa47fcf, 0x7f272255,
+0x3ee4098e, 0x819527f9, 0xcfc187a5, 0x7f81e781, 0xf71402bd, 0x9fecc0d1, 0x2067a67f, 0xa1dace7f,
+0x42817fa8, 0x8181da23, 0x03818181, 0xc35e3af7, 0x941d7ff3, 0x817f33e5, 0x7f2a78f7, 0xbe426494,
+0x0d2d81a4, 0x817f20cf, 0x89b2f4d0, 0x8171ba71, 0x6245be4e, 0x817f8140, 0xed8a7f81, 0xdb097f7f,
+0x81724d42, 0xe0de7bfb, 0xde611f7f, 0x7f54d981, 0xb1d07fd7, 0x487f7fef, 0x7f2c8139, 0x7f7f7f10,
+0x3e812db6, 0x63447ff6, 0x7c7f277f, 0x9f7f8b7f, 0x76d47f81, 0x197faadb, 0x6a596c91, 0xc681a3a3,
+0x7da1d13f, 0x4af8d329, 0xaa819881, 0x7d7f7f4a, 0x3a9d1753, 0xaf818145, 0x5b905350, 0xee313e4c,
+0x3fa881c7, 0x437fc046, 0x817fbd9a, 0x30f77f14, 0x3e81df81, 0xa42f4e53, 0x7f67d481, 0x4f4b819e,
+0xc5474f22, 0x6eed3376, 0x7fb1ed92, 0x5b3e813d, 0x6c8181a7, 0x720df323, 0x2d0e7017, 0xc7448174,
+0x817fb27f, 0xad7f01de, 0x817f10b1, 0xf6231fed, 0xa56d7a81, 0x98817fef, 0x8181e4a0, 0x48aa7fb1,
+0x81727f6a, 0xa4059a04, 0xe0cff64c, 0x5ea7679c, 0x69c1009b, 0x7f816b2a, 0x5cc58181, 0x7f954f3d,
+0x848b7f17, 0xaee99031, 0x7fbb951f, 0xa2da7f73, 0xc5acfb81, 0x2c1ecf2a, 0x6981fdba, 0x19897fb2,
+0x7f4af7a6, 0x85cd8129, 0xe845e0d5, 0xdf658407, 0xd522567f, 0xab242f2e, 0x7fdd70a4, 0x1c9d038c,
+0x2f923f85, 0x27f1b2c5, 0x7f812781, 0x7f818181, 0x7f9603cb, 0xc32881af, 0x5ad1f2a1, 0x61b99a32,
+0x57cd3bfb, 0x7ffc6fd7, 0x9e81c281, 0xfea25f7f, 0x85a2bfe7, 0xf3ef5107, 0x7f81565e, 0x1d447f81,
+0x814e817f, 0x40853b00, 0x6caf3f7f, 0xe13a7fe2, 0x816162c5, 0x81b4e66f, 0x81e18fb8, 0x7da87f66,
+0x7fef667f, 0xea2ba1f4, 0x408181d2, 0xba81676f, 0xdd817481, 0x7f9d7fff, 0xd6544752, 0xb1bd61ce,
+0x3aa26a56, 0x817e9bf8, 0x8158964a, 0xa0d3253c, 0x308130f6, 0x501d7f23, 0x367f34d2, 0x818581eb,
+0x817f4743, 0xdf9e81c8, 0x5c7f13a4, 0x12182965, 0x9cca6c7f, 0x47817f4f, 0x0cbd2918, 0xb05cf048,
+0x28810542, 0xe8a869a0, 0x7fb7682b, 0x3f7fb5d1, 0x813dc581, 0x2ea58dcb, 0x4a4e6881, 0x687681b8,
+0x665c057f, 0xa78127e0, 0x81b28166, 0x817f686e, 0x7f261637, 0x81ad7131, 0x54817f68, 0x2eae6470,
+0xf110f558, 0x8aa44bc2, 0x81f12d55, 0xf37f35cd, 0x7f68679f, 0x3fc481db, 0xe02a5a41, 0x817f8130,
+0x919b6c25, 0x14749815, 0x9d7f6c60, 0xc5777fa4, 0x7f8db49b, 0x524a623d, 0x2ef59cc0, 0xd18f4a24,
+0x37707f92, 0x4af98126, 0x81b43c76, 0x7f965818, 0x7f81c786, 0x057f7f49, 0x1ab3ef1e, 0x1781eb8a,
+0xf0909181, 0x656da3b4, 0x5181cbb9, 0x81e9a237, 0x8ace577f, 0xd19f2c0c, 0x86a7817f, 0xb7628100,
+0x817fcfa2, 0x7f3cddf4, 0x744a96d2, 0x19967ffb, 0x7f7f813a, 0x81f2b043, 0x7d46cd81, 0x7f006e7f,
+0x363a7c9b, 0x9f812dda, 0x77c77f1c, 0x8172274d, 0xa7ba8181, 0xff7f1ea8, 0x817f4e7f, 0x377f9ad7,
+0x81447f7f, 0xf81f3623, 0x58ce7f7f, 0x8a4a208f, 0x4d938115, 0xb0ac7029, 0xf72b23cf, 0x467f9dd3,
+0x81819130, 0x62bb7fc4, 0x84b4b190, 0x2781b070, 0xdc81cda4, 0xcb8145b3, 0xda812b38, 0xda307f7f,
+0xafbc8158, 0x7fcb7205, 0x47e781ae, 0xc056245f, 0x81997f56, 0x51d9d6f7, 0x7f895c4e, 0xb7814beb,
+0x7f658181, 0x757f81bf, 0xdb81816e, 0x582edcb2, 0xb9860711, 0x587f81ca, 0xa45a7f0b, 0x81e68a35,
+0x7f7f3b0f, 0x3c233956, 0x7f5f3e44, 0x81ba915e, 0x9ea4dd81, 0xc323e1bc, 0xb1ac0322, 0x5e7f0e2b,
+0x6b2fb26b, 0x0e92812c, 0x667fc670, 0x7faccae4, 0xce8181be, 0x815e68c5, 0x273e7f69, 0x10f3e868,
+0x47a8b82c, 0xc8817f10, 0x617281b6, 0xe4a44714, 0xe19d4b04, 0xe8818333, 0x81e481fb, 0x58ab1e34,
+0xa68c8168, 0x815f4c12, 0x181be656, 0x817f147f, 0xc87f7f8b, 0x7f7fa1f9, 0x7c787f7f, 0x7f7ff8ae,
+0xcf9200a0, 0x7f65e492, 0xc37fbb89, 0xa234a37f, 0xa27f7fb4, 0x818a6fb3, 0x04817fb5, 0x2e7f636a,
+0x905db630, 0x812bbc0d, 0x8f1beb7f, 0x7f83bb5c, 0x81b96698, 0xbebc8152, 0x6669b181, 0x7f81452e,
+0x6861ca81, 0x8806d040, 0x4570d28b, 0x812681fe, 0x817e3b48, 0xcd3ddb3c, 0x21777fa4, 0x7f3d81cd,
+0xae0d8104, 0x8134b9fe, 0x7fb87fdc, 0x81ac7f6a, 0xbeec5c5d, 0x60cc4dfe, 0x967f82fc, 0x3a8187a2,
+0xe9577fa9, 0x818181a5, 0x8181b4aa, 0x81204f7f, 0x81708146, 0xbe08d127, 0xdec25eca, 0xc3e0db2f,
+0xf7817f4f, 0x7f5da797, 0xc9c44f90, 0xbc5b84c5, 0xda44a681, 0xcc9b810a, 0x38c5c3c1, 0x674294d4,
+0xe47fe181, 0xa4817f54, 0xcd06b70a, 0x5b3d7f7f, 0x7f137fbc, 0x38769bd6, 0x817f811d, 0x6bc4046f,
+0xba9a7f2d, 0xca91ea2a, 0xe881d10b, 0xf9810daf, 0x42e57f81, 0xc87c147f, 0x4f817f7f, 0x66c7bd81,
+0xb991549f, 0x816febec, 0xdc50fd71, 0xaab9aa83, 0x7fbd3952, 0x7f50c6cf, 0x1481f8a2, 0x3ff381ab,
+0xf6b0470a, 0x81e12ebc, 0x817f5f39, 0x3c7fb836, 0x79813781, 0x7fefa2c9, 0x7e81030d, 0xb849bf3e,
+0x81613b40, 0x08817f32, 0xbd5ffe64, 0xd688be81, 0x0166eab3, 0x81077f0a, 0xe5817f56, 0x91b83696,
+0xac8181d6, 0x5732a410, 0x40818181, 0x81915bb3, 0xa87f8145, 0x816a06ce, 0x033f7d7f, 0x86438281,
+0x3afc477f, 0x9cdf8102, 0x786d4383, 0x81ecfe7f, 0x89a7471d, 0x349c7fd7, 0x7f377f3a, 0x51d55daf,
+0x62337f61, 0x547f910e, 0x4bea99d2, 0xbfa9557f, 0x7f2ee96a, 0xcb9ccccd, 0x0fc3a681, 0x687f30fd,
+0xb07f4530, 0x83814334, 0x955bf3c6, 0x7f909981, 0x7b4e617f, 0x7659def0, 0x05565d7f, 0x81f271cc,
+0x31ca8581, 0x1afd6755, 0x818181ff, 0x7f8181ef, 0x7f7f77ce, 0x1d6692cf, 0x73c57f7f, 0xf083d53f,
+0x707f9c09, 0x1ce6813b, 0x17bcb0c6, 0x15b59ba7, 0xde7f817f, 0x7f925801, 0xeba91d81, 0x568190e4,
+0x7f817e72, 0x8d7ffa3c, 0x82f281fb, 0x548a7f7f, 0xe9777fa8, 0x407f16cd, 0x7e8167a8, 0xc5812c04,
+0xeae8e181, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xf481c67a, 0x89b07fc3, 0x2e4d7b44, 0x9181818e, 0x83b88158, 0x8181739b, 0x4aa97f6a, 0xb36d7fa6,
+0x075bb9b8, 0xcf839c97, 0x20ba9176, 0x117a6a6d, 0xc35b571e, 0x8181fb5f, 0xec3a7fa9, 0x3eec7fcb,
+0x53622f7f, 0x8681a07f, 0x0ff39b65, 0xb6c82420, 0xefb381d6, 0xd5390961, 0xf1887f0f, 0xbec2abad,
+0x64d57f81, 0x2281057b, 0x1f7fe936, 0x99038181, 0xc1450b81, 0x65cc5386, 0xb886acc1, 0x109dde08,
+0x6417d0dd, 0xcb7f7f76, 0x9681b397, 0x53c39e81, 0x437fd46e, 0x751c3481, 0xdd4c813c, 0x38817f65,
+0xf0b39281, 0x31357fcc, 0xf37fae31, 0xba8181e7, 0xefc1e23b, 0xa8650162, 0xbb815838, 0xd6eeba30,
+0x8de2db81, 0xc01ca018, 0xed2dfb81, 0x7f84731f, 0x40633968, 0x557f2c0f, 0x5f5c6374, 0x41b02181,
+0x447f6e09, 0x8d56b3a6, 0xe47f81bd, 0xbe712a04, 0x3e7e78b2, 0x470a8128, 0x298981b3, 0xe65e2866,
+0x5bad817f, 0x78884acf, 0xb521287f, 0x81df4b81, 0x33818184, 0xb3d65f30, 0xc2ed7fbc, 0xc4811ccd,
+0xec92a11d, 0x5bc5817b, 0x57ad8103, 0x7f6226e4, 0x07c2d87f, 0x3d7fb181, 0xff73974c, 0x08815f61,
+0x50616fbc, 0x923ec16c, 0x2181c73a, 0xb8f88181, 0x047f7f7c, 0xe87fa53d, 0x399ca775, 0xef139839,
+0x7f217f43, 0x811415c8, 0x37f6b9c6, 0x7f7f817f, 0x11c6ad81, 0x81b3c88d, 0x0ca47c91, 0x024a7604,
+0x2dda2f7f, 0x811c5281, 0xc27f814b, 0x7f37a317, 0x42433381, 0xddfbc9da, 0x23737f7f, 0xe3acaecd,
+0x1d846dc3, 0x7f1bd4e3, 0x4055d37f, 0x7f1e9a81, 0x31d29025, 0x6d90cf64, 0xdf532fea, 0x1a3dc07f,
+0xf997ee19, 0x597f5460, 0x2a0b5b30, 0x5751a381, 0xd27f8489, 0x7f1f9ae4, 0x2bd07f7f, 0x5281923c,
+0xbb7fae6b, 0xd344db7f, 0xb0431bc3, 0x33744f44, 0xd2996981, 0xce048861, 0xd57f36c1, 0x1181819f,
+0xe7592aef, 0x7fbe817f, 0x177f7f04, 0x2cc78381, 0x27558149, 0x7f64746e, 0x2bb97dc7, 0x10aba652,
+0x02f70c7f, 0x7fd8ae81, 0xcd81f07f, 0x9352c65e, 0x344a817f, 0x4f282881, 0x3e2d23fe, 0x69517fb3,
+0x7fd1e4a6, 0x3bf47f7f, 0x33909ff6, 0x81aba30c, 0xaa8181dd, 0xf6f36f81, 0xb57f7fa4, 0xe8b6a572,
+0xb0ac3a81, 0x81817413, 0x104de181, 0xef977fcf, 0x2054acbe, 0xa9013b81, 0x4a7f34fe, 0x49747f6d,
+0x5ad74c74, 0x0e582cc5, 0xa7ea83c9, 0x7f7f750e, 0x38847f81, 0x41817281, 0x3344debd, 0xd229728c,
+0x027f839f, 0x5d9fc4ff, 0xdb1e7f51, 0x439681ca, 0x1b81b581, 0x7f777f9f, 0xd6bfb07f, 0xb050814a,
+0x1981648e, 0x2cca7f56, 0x30814ab8, 0xc48143a5, 0x5bab3c8b, 0x7f97249c, 0xf7f09eb9, 0x074aa055,
+0xc86bbe54, 0x815ed4b2, 0x7fd0b28f, 0xd7e07470, 0xcf815cc6, 0x7e7f7f63, 0x81dfe09b, 0x4098da7f,
+0xc1d5a339, 0x7928937f, 0xa481bf6e, 0x81accdd5, 0x3b9c5cb7, 0x817f81a8, 0xc49b8a56, 0xec817f93,
+0xb7a9306f, 0x43555d59, 0x5f815d7f, 0xb79e7fc8, 0xc9d17fa5, 0x7f9999b8, 0x73467f81, 0x38627fd7,
+0x7a9138ab, 0xbd46b67f, 0x71b5823e, 0x5c81fbb3, 0x3d508f7b, 0x8173c630, 0xd4816172, 0x3f81d92d,
+0xcd6b9d7f, 0x72ee607f, 0x851bd2ce, 0xbc4e7fde, 0x1c6c8193, 0x9252b181, 0xcc217f96, 0x296d7f98,
+0x5957ae75, 0x817f14bb, 0xbf7b8191, 0x44d87f81, 0x352a84fa, 0x524a882e, 0xae66ac81, 0xbc7fc592,
+0x2cb1dc81, 0x42e56887, 0x7981b76a, 0xa5667333, 0xd2ab7e7f, 0xe37f817c, 0x26817f7a, 0x23570c5a,
+0x1a685290, 0x814bb476, 0xf6527bb0, 0x7b810805, 0xe63cd272, 0xc1d97fb5, 0x1e8124d3, 0xd34f157f,
+0x367f82a6, 0x14819e1e, 0x39226087, 0x818681da, 0x8121417f, 0x81186358, 0x57e88e9c, 0x077f6e37,
+0x96087f7f, 0x9a82c77f, 0x0781c4b8, 0x81217f81, 0xc565447f, 0xab41447f, 0xf7915a1f, 0xe58b5a81,
+0xcb817d13, 0x81819181, 0x0d4cc8ee, 0x63b4f36e, 0x587f81b3, 0x47947981, 0xcc7f7f88, 0xa3816781,
+0x2581a481, 0xc750aa5c, 0xcd440151, 0x4d684b81, 0xd8a6b50f, 0x4f7fa9b5, 0x3f1b93cf, 0xb58f812e,
+0xaacd817f, 0x136d7fa9, 0x81b581b9, 0xb75d7fd5, 0xd29a8133, 0x337f8ec0, 0x75ac901a, 0x0a6d7fb2,
+0x2d208186, 0x8186b97f, 0x0cb42af4, 0x03ac9e7f, 0x1167a77f, 0x7f19fad8, 0x2d4781b9, 0xf97f6658,
+0x9081bc81, 0x6f7f4087, 0x8e527f8d, 0x6873d688, 0x817fbc88, 0x4b81608a, 0x22814ea0, 0xe97f81c5,
+0x10bb3de5, 0x818115ed, 0x421b3081, 0xa17f6e52, 0xf46d7f09, 0xd87f8185, 0x68a79c2b, 0x7f7f837f,
+0x4d7f4967, 0xc8507f81, 0xc67881f1, 0x0dad027f, 0xad7f8125, 0xa47fb3aa, 0xc74ceb01, 0x373974a7,
+0x4e7f8153, 0xa87c423b, 0x2ad75081, 0x4a817f35, 0x357f5517, 0x55816581, 0xcb7fa97f, 0x7b797f7f,
+0x504ee981, 0x7adecc6b, 0xce338197, 0xc49ab9bd, 0xe3877f3e, 0x7f817f81, 0xea3624fa, 0xfd889681,
+0xfd7f7ff9, 0xa6732f2f, 0xa81b81e0, 0x817f7fae, 0xbcb4b010, 0xc37f7ff4, 0x9a52819e, 0xc730eaec,
+0x437f817f, 0x8865815a, 0x53337f64, 0x2d817f8f, 0xd7e2417f, 0x2b6ec637, 0x3d819d41, 0xe4877f52,
+0x26a26a63, 0xdc74a867, 0x71433c4d, 0x94b02e35, 0xd6a155f5, 0x3cd37f73, 0x5c89997f, 0x569e7f03,
+0xe0adb53a, 0x49d78e81, 0x9c7f22a4, 0x01385b17, 0x9081db0e, 0x3a8c46a9, 0x1e016448, 0xfebdc287,
+0xf072dec5, 0x9f816429, 0x4bb0817f, 0x5a0ac21a, 0xf74ca8aa, 0x82811b7f, 0x1c08bf81, 0x1fe36842,
+0xbc7f8181, 0x373b7f21, 0x097f8150, 0x54935b9a, 0x3a7f1381, 0xceb77ff1, 0x55ab4e7f, 0xcb1ab47f,
+0x9f17477e, 0x7374b97f, 0xb2512a9d, 0x8148d0d2, 0xc057444f, 0xe94f8162, 0x7f816e40, 0x1da3d14d,
+0xb458eb23, 0x7f907a47, 0xc8657f81, 0xc4f36ba1, 0xbc8181e6, 0x81efd081, 0x53607fa6, 0x51368181,
+0x32b84fdc, 0x8127b27f, 0xd2247f5c, 0x56f77669, 0xecfdfe9d, 0x697fc681, 0x7f7f2781, 0xdb7f371a,
+0x1b8181fb, 0xea78f17f, 0x5a187f7c, 0x7f7c705e, 0x2b58816c, 0x757f607f, 0xc87fc97f, 0xec5b66a6,
+0xb89574c0, 0x77ccb739, 0xe1fd2aa7, 0x7f45d8cf, 0x20283a95, 0x5f45909a, 0xe581748f, 0xf97fab7f,
+0xc8e0357c, 0x73c7da4b, 0x7f0e812e, 0xba01c67c, 0x0324fb81, 0xea2ee62f, 0x253e88ae, 0x077f81cc,
+0x817fc781, 0x94f17fff, 0x0ed6f0f4, 0x84677f8f, 0xb598462a, 0x81a87fec, 0x3dbaa47f, 0xbd62fd81,
+0x277f81ae, 0x0f43ab6c, 0x07c1617f, 0xc7bc8181, 0xba2460fa, 0x6d0df181, 0x92dfa27f, 0xf7d1033d,
+0x53b71860, 0x81b28146, 0x6564b13a, 0x7fcf0981, 0xf9004e81, 0x10229f55, 0xdb7f7f05, 0x281845aa,
+0xca6ddfab, 0x6481d77f, 0x4e4120ab, 0x81006b47, 0x518dce81, 0x907f8145, 0x4d5e7f2a, 0x064076ad,
+0xdc1c8e81, 0x354b2545, 0xc8426706, 0x4447b281, 0x21daad30, 0x6d21a202, 0x04249781, 0x19ac7063,
+0x3a7f00a0, 0x81f41c2f, 0x523c5b36, 0xb6817f43, 0x3f817f86, 0x811234c1, 0xd77fd8a3, 0xc2f2927f,
+0x557f7fb1, 0x41d9e881, 0xeec06dde, 0xe4633caf, 0x3c72fd19, 0x9cffc57f, 0x4b7c8659, 0xcbf6e57c,
+0xd9bb7f7f, 0x5fdd819f, 0x69ecd881, 0x7f817f90, 0xe68181f7, 0x10811439, 0x2a7a2c37, 0x66438157,
+0xbc634044, 0x3fe98163, 0x81ac8166, 0x8143811d, 0x364f63d5, 0x377f4e81, 0x24755bb8, 0x17adfc5a,
+0xdedea8e0, 0x2e6e9e14, 0x0e816188, 0xe56cbe81, 0xb9c85cca, 0x817fb120, 0xae7f8181, 0xe37f7f7f,
+0x0827d377, 0xdc7f815d, 0x9a2a5625, 0xb2ab4736, 0x817f2274, 0x817fb29c, 0xdcece2cf, 0x5bddd988,
+0xcc1e817f, 0x24793971, 0x40ea214f, 0x326f7e64, 0x1a9e3ed0, 0x268c1a7f, 0x314b8548, 0x0f7f8701,
+0x347f7c7f, 0xb9ca13bb, 0x3492187f, 0xc67fa67f, 0x7f49814e, 0xaa7f91d1, 0x18d53577, 0xc88b53a1,
+0x20af691f, 0xe6853f81, 0xcf5d08bf, 0x81705981, 0xe30d47f0, 0xa8c17fa5, 0xdb817fb4, 0x12818172,
+0x83433d81, 0x4a7ff6e4, 0x327f937b, 0xbb6509d3, 0x2c02fc7f, 0xf3b7feb4, 0x415d60ab, 0x136551d0,
+0x0e818181, 0x832eb165, 0x3c7f7f82, 0x817770ae, 0xf9b3a525, 0xddcb3d02, 0x008b6181, 0xdbe55445,
+0xec8137cb, 0xf5e8f76c, 0x61815ac9, 0xc8810fb0, 0x35547799, 0x0d81a035, 0x1c3eea42, 0x88d77f96,
+0x2948677f, 0x0852db6e, 0x42367f74, 0x0d7f867f, 0x3a7fff81, 0xd1d1d271, 0x02a981e5, 0x2bfd2988,
+0xd3818199, 0x4e7f4010, 0x09297fd4, 0x7f816b68, 0xe60a05ca, 0xeb81c97f, 0xa2cf5e81, 0xfd7f7f52,
+0x07057f53, 0x8672147f, 0x389bd281, 0x3a855c79, 0x41328181, 0x21fe5e81, 0x073f7fc3, 0x3654f170,
+0x24bc7f7f, 0x4f816ee1, 0x67427f7f, 0x8140676d, 0xef53e53d, 0xa48bce41, 0xdb5832d8, 0xf64a58dd,
+0x3d3e70ab, 0x53ab4a16, 0x137f2023, 0x74569bad, 0x017f8138, 0x81902bed, 0xbdca8f24, 0xa34d8193,
+0x81cf7f90, 0xab43b32b, 0x003f7f49, 0xbf3d4570, 0xbce67f72, 0x7c197fc0, 0x5376d47f, 0xd53d7fa8,
+0x7e9bb47f, 0xd72aa0f2, 0xde818138, 0x5cc3a981, 0xd57d9c5d, 0xecb2d6a9, 0xf97f81e4, 0xb67f8f33,
+0xb92b577f, 0xc483f97f, 0x469d9481, 0xd4868181, 0x7031e886, 0x95b4ca8f, 0xc6d4bd93, 0x117f227f,
+0xb67e7fe9, 0x7fb35540, 0x07d01f81, 0xb4ce9b40, 0x1b118681, 0x7f657bfc, 0x2bbe817f, 0x287f176e,
+0x6c96bb02, 0xcfff9e59, 0xec7f647f, 0x817f81b6, 0xabd131be, 0x819081e8, 0x4724b87f, 0x5f817f3e,
+0x62b99368, 0x81818110, 0xc99ad3b2, 0x25816734, 0x0702743f, 0xe1b4812f, 0xcb787f81, 0xac864257,
+0xcb928181, 0x55e27b81, 0x26f281a4, 0x63898181, 0xbbe1e54a, 0x58d2f881, 0x49e3cc81, 0xf7ea287f,
+0xe9827f82, 0x81a69a5c, 0xdd81d292, 0x7f935122, 0xd17fdc3f, 0x321a8fa8, 0xfa819a81, 0x1fdb7f79,
+0xc6cf9b09, 0xe181547f, 0x0acacab3, 0x0e7f72ca, 0xf562e081, 0x13d3827f, 0x5692de7f, 0x35b04a5d,
+0xdd818e3a, 0x6b7f6160, 0x29303878, 0xc7687fbf, 0x38508173, 0xa6bd37be, 0x0d339881, 0x5e198614,
+0x67f745e5, 0x81081a7f, 0xa3c77d84, 0xaadb7f81, 0x578d7ff0, 0x75a0b54e, 0x0d01587f, 0xa1cb624b,
+0xf94181b7, 0x819d3a81, 0x37258135, 0x5aa87f3b, 0x0e7f7fd0, 0x5b7f817f, 0xda4ce9b1, 0x40917f81,
+0xc57f7f3e, 0x4115b391, 0x627b816f, 0xa8575f49, 0x99ec8124, 0x33db907f, 0x4973c07f, 0xc9b71548,
+0xde548177, 0xb608bfcc, 0x1d0787bd, 0xd37f793a, 0xfe847f7f, 0x7f3f4111, 0x3dd5de99, 0xbedb817f,
+0x4c65c24d, 0x5d2c813e, 0xd901b37f, 0x974c5c92, 0x7f7f7f7f, 0x812b7f81, 0x0057836f, 0xf0778181,
+0x2881f3c5, 0x35147581, 0x817fb31a, 0x7e7ae063, 0xfa1e4184, 0x7f1e787f, 0x529c5123, 0x553b9a81,
+0x12de4220, 0x1fa92f8f, 0x4d66a52a, 0x554a2f40, 0xad3f637f, 0xbc81257f, 0x04f8976a, 0x2aa1fc7f,
+0x3881b3cb, 0xcfc6ee25, 0xa37f5f60, 0xffddf08e, 0xce817f2a, 0x824f4685, 0x17b8a353, 0xa97f8a81,
+0xfc81dc7f, 0x7f81a5b0, 0x26fab529, 0x811085c4, 0x031c5a76, 0x817d7f95, 0x1a8181cc, 0xe6aa0f7f,
+0x1e454a7f, 0x1c98818c, 0x2b5ef528, 0x7f2b7f5a, 0x4ec7adbe, 0x6981f15d, 0x7f1d4b23, 0x0f337fb9,
+0x1db1b85f, 0xdb7fbe3d, 0x1eb3aff5, 0xba2a7f96, 0xd6a0761a, 0xa97f117f, 0x341781f3, 0x9981817f,
+0x56dd7f44, 0x431981b3, 0x115d7f7b, 0x7f5a818b, 0x943248aa, 0xb78a45db, 0xc2046981, 0x7a330a6f,
+0xedb7817f, 0x81198df6, 0x29e37f9d, 0x74818143, 0xe5147f86, 0x7fac4869, 0x39e2bb4a, 0x422b983d,
+0xdb949bec, 0x2c7f5181, 0xe7539781, 0x7f818ca1, 0x2e815f79, 0x2b199727, 0x28ea3181, 0xe65c7fa5,
+0xfda2810a, 0x7b227ff5, 0xc259caa9, 0xdf9e7f4e, 0x1c7fbc49, 0xce892118, 0x083b81e0, 0x7081b06f,
+0x0c7f507f, 0x637fae31, 0xf2967f40, 0x810181fa, 0x0878b37f, 0x98817f4d, 0xdaa946cb, 0xae813eb4,
+0x67bb97b4, 0xe156b2a5, 0xc97f6dcc, 0xa90bd681, 0x14817f81, 0x7f816058, 0x1d587f76, 0xea425425,
+0xd62e4781, 0x477fdca5, 0xcb667f7f, 0x8169daa2, 0x631cc881, 0x1381fb76, 0xf27f817f, 0xb297434b,
+0x3b1d7bae, 0x89b8d27f, 0x947f8bbe, 0xbc81d770, 0xf94f0724, 0x3cdc817e, 0xf981817f, 0x1b75245a,
+0xab20818c, 0xf2811c81, 0xfc78c27f, 0xb77f0881, 0x838132d7, 0x20818381, 0x127f815a, 0x8e9e267f,
+0x1fa87fc5, 0x1da2bf47, 0x0f81939b, 0x118ba016, 0x52c07c6d, 0x697fdd00, 0x0e617f92, 0xab812b56,
+0xce754988, 0x5e8181db, 0x22814b35, 0xfda981f5, 0xa981e85b, 0x477f93e0, 0x1e73d681, 0xdc748147,
+0x01a1479b, 0x6d4e8164, 0xd37f8b7f, 0xbf6b7f6b, 0xc68110bc, 0x81819156, 0x257f497c, 0xb07fa0c3,
+0xcac10d73, 0x39b9284d, 0xad817fd5, 0x7f8a5781, 0xe37f7f2d, 0x7f7fe7d7, 0x186d2c39, 0xc4813181,
+0x0ac8a47f, 0x569d4cd2, 0x7f3d597f, 0xb87fbe59, 0x35117742, 0xc18c7fa7, 0xb03bd7ce, 0xd77f6829,
+0xec3a7281, 0x81285968, 0xf8a69dd1, 0x81e38181, 0x4e1dbe77, 0x783d4e9e, 0x50bc7f85, 0x4181dd76,
+0xa61a4bac, 0x627dd07f, 0xa08168a3, 0xfefdde94, 0xcdc19d05, 0x39817f7f, 0x18d78181, 0x631681cd,
+0x91d2e1ac, 0xd2bfce81, 0x01f1817f, 0x810681d0, 0xccc18c5a, 0x7f0b617f, 0x563a8345, 0x917f26e1,
+0x87147fad, 0x88161a8c, 0x1481928f, 0x5c96b841, 0x1b7ff206, 0xf1bf4759, 0xc6efdc5b, 0xa1078181,
+0xf52b428b, 0x817f7f10, 0xdcd1c062, 0x0c863afa, 0xe26a27b1, 0xbd5a967f, 0xe8047fa4, 0x5be68181,
+0xef7b2e81, 0x60f47ff1, 0xf9761c7f, 0x8f297a94, 0x2c81096a, 0x7fc40ec0, 0xbb7fb3b8, 0x4494cae8,
+0x5847c916, 0x7d728183, 0xe74d7f81, 0x818d426b, 0x0006ba4d, 0xb4bd9ba6, 0xe00a813e, 0x68032681,
+0x18877f81, 0xb46281d3, 0x3381113e, 0x6a7f57f7, 0xe2a7194d, 0xcb7f7fca, 0x62c66981, 0x5181e082,
+0x6acdde81, 0xbcbbf27f, 0x3e3ea181, 0x81e6c17f, 0xf854097d, 0x307d58c8, 0x2e9e81a7, 0x93ce81ce,
+0xcad4d5a2, 0x1272b081, 0xb84ccf3b, 0x007f9d7f, 0xe294efb0, 0x830c7fb7, 0xca07b17f, 0x3b9a88bc,
+0x09350bd4, 0xae007f48, 0x3a6a8181, 0x38777f48, 0xce7f7f12, 0x9781570e, 0x3766817f, 0x4b607f7f,
+0xe38c2477, 0x9cc64b35, 0x157f0742, 0x6881d981, 0x53c88c81, 0x9f8974ae, 0xa77f8319, 0xfb527fbc,
+0xdf865f22, 0x407f8117, 0x5f5a4c24, 0x14207f77, 0xbfe8e081, 0x667f7f58, 0x31f17f37, 0x467f307f,
+0xed7f7f48, 0x2bc96b81, 0x04816572, 0x8137a081, 0xea407b02, 0x7f06814a, 0x097c819a, 0x3ef22003,
+0x077d1469, 0x32e06181, 0x1e7fa7de, 0xc7508658, 0x2d58ddad, 0x921d7e79, 0x3af381d7, 0x31b971a9,
+0xa7b38de5, 0xf274be04, 0x9690d41d, 0x857f4dff, 0xcf7f5cb0, 0x8117bc7f, 0x1b7f4a91, 0x288181d6,
+0x3f4d7b12, 0x7f7f979c, 0x4581b06d, 0x7faf7f81, 0xaf1dac81, 0x4d068bb7, 0x367f50bc, 0xdb7fbd41,
+0x4f7f7f38, 0x81ac15f8, 0x2c3725a9, 0x98577f4e, 0xb20f8197, 0x6f816981, 0x26c87aa2, 0x1781c2a1,
+0xf5449d24, 0x14cc2651, 0xe33d7f7a, 0x4d7f7ff2, 0x3554512e, 0x25c23b96, 0xde7f8d7f, 0x44bc34b3,
+0x2a7f3050, 0x1aec3857, 0xada98181, 0x2644d0ee, 0xcbc2333e, 0x7f8e7f87, 0x4aa03181, 0x11b736b7,
+0x3abb2381, 0x2f96817f, 0xe1476381, 0x83ca2b85, 0xfc3281ba, 0xa0d62222, 0xefbe354f, 0xa022be81,
+0xd77fb435, 0x17538367, 0xee85d87f, 0xa4a66071, 0xc8402561, 0x818a277f, 0x9d4ddd7f, 0x23bf327f,
+0x32ec1b81, 0x8c138d68, 0x237f1a15, 0x4a0e2b7f, 0x5b7f4981, 0xba747f29, 0xa1d37848, 0x0c7f03df,
+0x923f1d7f, 0x8faa7c7b, 0x35068194, 0x60d2f465, 0x27606681, 0x7fc37f8a, 0x31bd3bd5, 0xcf58445f,
+0xdcce241b, 0x88d9816c, 0xb9b2a7d2, 0x2205817f, 0x01ec81af, 0x4581c8a8, 0xdb0f1b6f, 0xca0628cd,
+0xf63881c7, 0x7fa3697f, 0x5246567f, 0xb77f7fa1, 0x297f897f, 0x4cb8c84b, 0xce9e977f, 0xbf811e0a,
+0x219d746e, 0x7adcfa81, 0xbcce1a61, 0x28987681, 0xfa7faeeb, 0xdb454581, 0xa5a5919d, 0xbf85a57f,
+0x34b68581, 0x925c812d, 0x189a4c7f, 0x3ad03756, 0xf8c97f13, 0x97227f81, 0xfd7f070e, 0x7c7fd41e,
+0xfe81b327, 0x81a6627f, 0x0016cf64, 0xded56665, 0xcc5fbd10, 0x81112f30, 0x4c6c877f, 0xefb9b53f,
+0x33bc2181, 0x5e797cc7, 0x2a10c047, 0x917a7f81, 0x3a81817f, 0x8197ccbd, 0x73df4f32, 0x264f522b,
+0xc1e9528f, 0xbb494681, 0xfbde6eab, 0x4f7f280b, 0x987a7f1d, 0x167f1f7f, 0x0b817f81, 0x8124a87f,
+0x927f8181, 0x7f81ad86, 0xc779dc81, 0xd0f681fb, 0xcfd8fb81, 0x19cf4981, 0xb87f4bf5, 0x4893529b,
+0x0040eb60, 0x7fc78bae, 0x474455dc, 0x0b7f7f7f, 0xa92f7f70, 0x7f3d9c73, 0x137fc699, 0xb4a3c6fa,
+0xcb7f5c1d, 0x9c259c99, 0xdf5183d9, 0xa62181a9, 0x9a273761, 0xa5e8cd8b, 0x41b4bf1b, 0xa9818110,
+0xb27f7f7f, 0x0e6bb7c4, 0x2e3e7f90, 0xa4c68172, 0xf73f7f7f, 0x81818164, 0x5299a157, 0x0a297f5c,
+0x9a46f024, 0x8178d77f, 0x02818181, 0x8181025c, 0xd96828bb, 0x77644a05, 0xb77e4427, 0x407fa650,
+0xab7f7f56, 0xaeeff9fe, 0x2f871d3b, 0xb8d7dd43, 0xe8817f7f, 0x7f4d0a27, 0x036a5b7f, 0xd4a3e67f,
+0x9122dd23, 0x627fb09d, 0x055c6534, 0x0689a1b3, 0x4f484a7f, 0x7f77b1e5, 0xc47f9d06, 0xd381c37f,
+0x3b819a7f, 0x4381827f, 0xed81817f, 0x95c3917f, 0x1b1e9ff3, 0x4c98cf7a, 0x81927f81, 0x703fd644,
+0xed5db0d6, 0x23225674, 0xf95a8187, 0xe6ac7f32, 0x488150e5, 0xf6b5e281, 0x29810449, 0xfdada97f,
+0xa6a19781, 0xfe36879a, 0xc96ac845, 0x3bf937bf, 0xa2812172, 0x84203765, 0x5f9e3403, 0x017f6a34,
+0x2cc6607f, 0x99877f7b, 0x2ad981d2, 0x81933581, 0xdf81338a, 0xd478056f, 0xfa7fa571, 0x1d818352,
+0x17c9db81, 0x9c7f7f52, 0xdf9bd4b1, 0x417f98a5, 0xca5517df, 0xc44b22d0, 0x58727f9e, 0x28817fd5,
+0x477f2fb3, 0x8b3f7f59, 0x0940765f, 0xa970b281, 0x0a0a7828, 0x81319e7f, 0x2dc34181, 0x4081668d,
+0xe7817fcb, 0x3641753a, 0xc17f3d81, 0xb88154b1, 0x73246eb5, 0xb0db8186, 0x09a2ec6a, 0xd82e2c71,
+0x336f7f81, 0xd6817f4e, 0x43814a81, 0xc579811f, 0xc0812803, 0x447fa1e0, 0x81b01b7f, 0x752152b3,
+0x4f15817f, 0xf97f61c0, 0xc99bd9b4, 0x2281307f, 0x607f8181, 0x7342b07f, 0x06bd9181, 0xb8b8bac5,
+0x3b3ca425, 0x8175e89b, 0xa50d7f4a, 0xbb56b781, 0x817fca6c, 0xac0fa7e8, 0x8e7894b7, 0x1d05cf50,
+0xf34f5b7e, 0xb65332e5, 0xc76e9375, 0x66d058a1, 0xe5a09f7f, 0xe493eaa5, 0x05fb81b5, 0x33817f14,
+0xee418105, 0x81a16f2c, 0x367fa849, 0x7aedbecc, 0x100f81c4, 0x81b2fb3c, 0xcc7fb181, 0x1b3ff096,
+0xd3b03a81, 0x4b815f75, 0x497f9c7f, 0x81015625, 0xa0817f81, 0xb0b8167f, 0x7eb7a3fe, 0xe97f6585,
+0x555a877f, 0x4b7f8181, 0x12a95e4a, 0xcb6f5afe, 0xd87b5fad, 0xbe655fa0, 0x8b81300b, 0xccb26381,
+0x39868173, 0xd6817fa0, 0xcf684e81, 0x7f3bae43, 0xfd8c20a8, 0xcfa0a31f, 0xc0307f81, 0x4e7f5d84,
+0xeb941e81, 0x6f77d070, 0xfa0b7f7f, 0x3cb88193, 0xf6818163, 0x3d5f8fbf, 0x40c4c73b, 0x4b7f4e4b,
+0xae968181, 0x818181b2, 0x81148181, 0x6b325381, 0xeae5582e, 0x7630307f, 0x1c0f6ba9, 0xa54a0457,
+0xd37fc693, 0x2345817f, 0xe44f1e7f, 0x3e4cc9cc, 0x3081babf, 0x817f45c7, 0x5265e57f, 0x427f81ca,
+0xe451817f, 0x8190b7de, 0xf0718981, 0x7f9ad381, 0xb9645da5, 0x7f7bed3e, 0x5ce37af9, 0x307f4ecb,
+0x0a7f8135, 0x81ffa7a0, 0x534fa1a5, 0x7f42d641, 0x0e501e61, 0x7f7f6edc, 0xc859c081, 0x377f85f7,
+0x0df9ab94, 0x817f7f7f, 0xfe7f7f81, 0xc1327ff4, 0xe84c842c, 0x7f1e5bc4, 0x1da77cf1, 0x1e817f53,
+0x5f9ab07f, 0x86209e4a, 0x204e81cb, 0x33c9928d, 0x275a2d8d, 0x7f810281, 0xfe7ff7ba, 0xfab77fea,
+0x658145e5, 0x73d57fd6, 0x01ec097f, 0x6d83207f, 0x49810cb5, 0xb5d9ce39, 0xf9e0436a, 0x629c81ed,
+0x48cf2c8c, 0x7fe37f7d, 0x5b257d81, 0x765f50b6, 0x2cc98403, 0x817fbebf, 0x127114c7, 0x347f287f,
+0xd2d72990, 0x81099d9a, 0x8143cac5, 0x8c452fc2, 0xd27f8f6e, 0x61957f25, 0xbc6fc54d, 0xce81f31f,
+0xd381787f, 0xac0e5156, 0xf081afc4, 0xb47f6f2f, 0xef811a81, 0x015ee99c, 0xd46de9d9, 0x30655a6d,
+0x09b2b87e, 0xaf13753a, 0xc6dd2a7d, 0xb9bd8190, 0x81537f7f, 0x669ff8ed, 0x5b810c81, 0x42e5a566,
+0x0c4174cd, 0xbdf9b7bc, 0x1c118e65, 0xe28f9b2a, 0x8c207f3a, 0x1e7f7ff4, 0xd6b57f1c, 0xf0131edf,
+0x38c9a381, 0x7f40817f, 0xb735817d, 0xa1a864de, 0xd99cbf57, 0x811a81f5, 0xb381e381, 0xe88e7fb6,
+0xfb4a5b89, 0x7fc006a3, 0x1c81653d, 0xbceaa09c, 0x8d7799d7, 0x4b407a81, 0xdc81bca1, 0x3437d76c,
+0xd79fe5c9, 0xd9adeea8, 0x163e8164, 0x2cc1b281, 0x3e81e9f1, 0x936504c9, 0x047f6f7f, 0xf981a776,
+0x203b2d68, 0x81dde8d1, 0x13e9e9bd, 0xe04108a3, 0x50304281, 0x486d7fb7, 0xbbff81ce, 0x31d43aa3,
+0x21813c7f, 0x81c8f989, 0x7f481024, 0x0a979b6a, 0x010081d7, 0x7792e641, 0x0654d37f, 0xa53da946,
+0x96c781d2, 0x41524ca6, 0x2ab2d581, 0x1c65bb79, 0xaaa494af, 0x81e09681, 0x3d7facf5, 0x04c3818d,
+0x2c1461c7, 0x788581d9, 0x1d3f2081, 0x49dfaec2, 0xfdf07f61, 0x40396d32, 0xc8835fbf, 0x7fb19f54,
+0x2fcc8142, 0xe7dcb4e1, 0x73c3a807, 0x7fc68137, 0x061e81ac, 0x81c70c7f, 0x1d817f73, 0xfdbace27,
+0xa5fa4081, 0x9b5575ca, 0xee81cc4b, 0xe85a7f53, 0x8daff2e0, 0xd1d1067b, 0x98ec3662, 0xa5818253,
+0xf8266d26, 0x38da26ac, 0x3f98912e, 0x4a10f144, 0xd845a345, 0x811bd786, 0x4b137f7f, 0x3427fa81,
+0xe981eb9f, 0x8f4ce6e7, 0x277f8181, 0xb0a5b03b, 0xd0633788, 0x4781b17f, 0xb27f3ee7, 0xd37f30b6,
+0x21c3a15f, 0x0492a4d0, 0x097a6c7f, 0x047f1c81, 0x994b7f81, 0x818ea981, 0xd46d7fca, 0x2b8a5381,
+0x9d424d91, 0x814d7f81, 0x32aa367f, 0x28ff1b73, 0xbea1dbde, 0x76db7f86, 0x248a8d37, 0x294b8136,
+0x6e8142d6, 0xec65687f, 0x66297f57, 0xdfb563b3, 0xd352ee79, 0x0689d45c, 0xc58123cb, 0x0b62bf8c,
+0x53c6d80b, 0x7fbc9773, 0xe4596e21, 0x2584812f, 0x1793b781, 0xaa815927, 0xb8659035, 0xccbe2281,
+0x5eabb4c9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xb339946b, 0xd7497238, 0xc36e8181, 0xd0816d3e, 0x7f7f2681, 0x6709bf21, 0x92e3bf81, 0xe54358cc,
+0x6bb5a661, 0x3a7f81f9, 0x8140f0fb, 0xc5a67f1c, 0x8d3381a5, 0x817f81c4, 0x72817fd5, 0xa72c76fd,
+0x68dc8b11, 0x9b5f4098, 0xc0f43965, 0x7f0ecf02, 0x7cfdd720, 0xe1a0ac15, 0x087fc3c6, 0x81b66e6a,
+0x410a893b, 0x81c491f4, 0x81d87033, 0x2056562a, 0x7f526cd8, 0x817fe90f, 0x81f78178, 0x81d93134,
+0x3699e0a2, 0x7fa181c9, 0x81f64081, 0x8f816b2e, 0x816ece59, 0xd548fd2c, 0xc4ee3919, 0x6d847f16,
+0x81e423c5, 0xfade4a40, 0x9e29eeb9, 0x7fe450f5, 0x5207177f, 0xf17f710b, 0x8cf291ad, 0xd09f9cf0,
+0x7f022d20, 0xb7ea81c6, 0xbb89cfa5, 0x1c6fd006, 0x7f8481dd, 0x81020914, 0xb14c81e9, 0x4d9b4f08,
+0x7f6064c8, 0x817f7fcc, 0x6b9819e9, 0xb253e7df, 0x724368fa, 0x816fe408, 0x7481a204, 0x0e6fec58,
+0x70449617, 0xf5a1da3f, 0x7f446e7f, 0x1005abce, 0x38664981, 0x8240472c, 0x10f52409, 0x818186dc,
+0xf7810be2, 0x9c2ad304, 0x81817f62, 0xcc40a43d, 0x5e6b81e7, 0x7ff0e2fb, 0x812a7f7f, 0xe3017f51,
+0x817f24dc, 0x85c49997, 0x863c7024, 0x7fc0ce3b, 0x637f8c81, 0x814c9dbe, 0x8ea08156, 0x2cf47f9f,
+0x5b55a9b1, 0x107d7546, 0xcd0381b9, 0xd8617f42, 0x7f81b8f1, 0xb506abd3, 0x745f2b2b, 0x7f81b7d5,
+0xbf7fdb20, 0x1ca3a610, 0x7fe5e9af, 0x20b37f08, 0x810e6f81, 0x9b7fe6ad, 0x1aa35d81, 0x46032cc7,
+0xad7f7f77, 0x8bd48245, 0x3dffaa81, 0x507f91d9, 0x907f9a25, 0x404b81b7, 0xc67f7f97, 0xb1eae864,
+0xed2a18c5, 0x2ea85ef3, 0x8153434e, 0x816daaf3, 0x7f03ad67, 0xa0ec264e, 0x640ca1e5, 0xf0818f2b,
+0xcbd27ff7, 0xa6a39206, 0x4ca811b9, 0x4c57a068, 0x8647e4c9, 0x7f438ad2, 0x7f945029, 0xc168e72c,
+0x7fed4781, 0x81f706cd, 0x62810667, 0x177f7f32, 0xb105d09c, 0x81fa7f16, 0x7f11fa53, 0xc8a6430b,
+0xececbb81, 0xe82644a6, 0x3e82f381, 0x28817feb, 0x90c18135, 0xd0f5810f, 0x507f0ba3, 0xfeb38808,
+0x8e6c66ea, 0x70a0c4c8, 0x8146912c, 0xb8e01cb1, 0x2b817f51, 0x64818207, 0x9f3a4e81, 0x7f4aece1,
+0x84aeafb6, 0xa17f8188, 0x9a7fe759, 0x1cbf5681, 0xad7f6bad, 0x818eebdf, 0x438181e9, 0xa7d07f22,
+0x75dbd318, 0x81817f3f, 0x5457bd92, 0x4b204ffc, 0x7f1c637f, 0x8b4c7ffe, 0xa4d97fe8, 0x6194ca37,
+0xb06c7f06, 0xad2f1ac0, 0xaef07f7f, 0x15818101, 0x22bf8d7f, 0x597f35cd, 0xb155ab0c, 0xc2838b0f,
+0x0f81f4e6, 0x181f7f81, 0x31e1817f, 0x6a2846c0, 0xede8048e, 0x2952c3e3, 0x09187fda, 0xce411cce,
+0xbbc197b5, 0x8181464a, 0x161922d0, 0xc37f292f, 0xbd736439, 0xc881b6fb, 0x81ba557f, 0x9da521f0,
+0x3e7f52dc, 0x3b3a813c, 0x7f544bc3, 0x46b1b3fc, 0xbeb18e34, 0x418156e1, 0xab22e318, 0x7fbe66e3,
+0x2237bfb9, 0x010081be, 0xc159b8df, 0xf449b264, 0x017f9e82, 0x9dbd7ff1, 0x09c7cbd7, 0x81bc537f,
+0x817fe1c7, 0x7f177f60, 0x7474bcdf, 0x3c7f6f70, 0x7f7f987f, 0x81812ecc, 0xca783f94, 0x64cc4da9,
+0xa0ba1d0a, 0x7aeec524, 0x43bb6b81, 0x1a338981, 0x206be419, 0x65819d5a, 0x7f81d73f, 0x81a67f36,
+0x22810442, 0x7fd4cef9, 0x6067ad85, 0xd6d17f30, 0xea7f8166, 0x457f7f84, 0x817f1bc8, 0x6b86be00,
+0x7f8bc555, 0x519d5bfa, 0xd07f97e4, 0x505c81d4, 0xf1eb8115, 0x72bdd002, 0x9da57f77, 0x817f12cc,
+0x81c03652, 0x441872fb, 0x554bdf67, 0x2e46f0d1, 0x81817f8d, 0x7ff5ce55, 0xd2ded97f, 0x817f67af,
+0x0539c336, 0xa37f2f7f, 0x8150637f, 0x8156d068, 0x827fbda5, 0x9f176b2a, 0x81878c0d, 0x81117f07,
+0xc0d15559, 0x869c81c4, 0x7fa498da, 0x46d5d102, 0x81f7a581, 0x816eca47, 0x67ad9d95, 0xccb49c2e,
+0x297c5440, 0x817f7cda, 0x9f55bd08, 0x2b7fc490, 0x817f817f, 0x377a8158, 0x91b5bf7f, 0xc87f4f21,
+0x977fc1d9, 0x7f3088f4, 0xe938b6ca, 0x41707434, 0x81a27fd5, 0xcf818116, 0x817f887f, 0x09cf3bc9,
+0x814edf19, 0x46206509, 0x34a36c81, 0x313fc7da, 0x92f34a81, 0x21e942d8, 0x365c16d1, 0x68907ff1,
+0xcb8190e3, 0x5e7f7fa3, 0x6fb78c98, 0xa1444250, 0x812bb37f, 0x83a26f0d, 0x739bab07, 0xcb2cea1d,
+0x668174ef, 0x288b8965, 0x95849a7f, 0xdc0981b0, 0xd875297f, 0x8153d5b0, 0x9d81e6dd, 0xae81d259,
+0xd981813d, 0x7f64ed35, 0x1f459b0f, 0xb8ebe4e5, 0x72812e81, 0x81909b54, 0x02f54fb3, 0xa87281f4,
+0x7f6381cc, 0x7f3cab5b, 0xb1958152, 0x814b9bfa, 0x81312b5e, 0xc2977f23, 0x347fbb97, 0x3b057fe6,
+0x40208144, 0x7f817fad, 0x54cb9deb, 0x37b34a28, 0x81781b81, 0x7f1b8130, 0x81e194f1, 0x882b7f1f,
+0x81dfc90a, 0xe4a97fa6, 0x9e81ab40, 0x971c2535, 0x5a7f7f3d, 0x47708116, 0xab778160, 0x81ac57e3,
+0xc2854dec, 0x81ea81a1, 0x8b347f7f, 0xe981d130, 0x93c70917, 0x817f812d, 0x81925016, 0x7f813953,
+0x52a5a5fc, 0x7a33d8e1, 0xcbd80281, 0x79df8101, 0x797afc87, 0x7581bbf0, 0x81567f94, 0x472ad4cd,
+0x23e49434, 0x4c7ffc03, 0x41b0717f, 0xcc67b7bc, 0x7f7f48bd, 0x8c1c81b9, 0x3a460d72, 0x9eb5fa34,
+0x03530615, 0x6c7f7754, 0x818167d3, 0x7fc22100, 0x7f3da881, 0xa24e7f61, 0x321bb411, 0xd981c827,
+0x76e8814a, 0x69ca13fb, 0x1390b881, 0xb1d08157, 0x7f4669a2, 0x7f237f13, 0x30268178, 0x0eb87f34,
+0xee1aaa30, 0x816596e1, 0x31813181, 0x88888243, 0x817de70e, 0x84811713, 0xd74d7f52, 0x06b17f35,
+0xed347f1e, 0x66d66058, 0x7f817fee, 0x035edde8, 0x819b18a6, 0x8e8198ee, 0x817fb5f5, 0x311e442b,
+0x957f941d, 0x4e6aa649, 0x7f677f41, 0x8d876acb, 0x7e7bb58f, 0x44c27fce, 0x6f39ec5e, 0x7f7f81d2,
+0xd43ba60f, 0x488150c8, 0x8181e9e8, 0xfe46ec02, 0xa2cc7fd8, 0x7f810781, 0x7f30c356, 0x22c97fc5,
+0xbcc97f40, 0xf2b2ce1e, 0x7b59537f, 0x46d994ea, 0x4ae2273a, 0x7f36d92d, 0x818ad281, 0xbf7f2b7f,
+0x8181abf8, 0x924f4eb0, 0xa62c81b6, 0x812b99aa, 0x447f817f, 0x2c7f5746, 0x0859b34d, 0x83e652db,
+0x7fc781ca, 0x819e5cfe, 0x55c5d07f, 0xb4bb3dff, 0xc24b8178, 0x93d28123, 0x15e63a7f, 0x7fc87f40,
+0x812fd94c, 0x991b8170, 0xb13593c6, 0x3b9a5119, 0x3b752581, 0x20b89686, 0xcac17f7f, 0x81237f6f,
+0x99ec643e, 0x02813100, 0x81124724, 0x3455436b, 0x8155cc81, 0x68136028, 0x81517f5d, 0xc57481f6,
+0xe4c88159, 0x81fba227, 0xaa814381, 0xb3818ebc, 0x457f8b51, 0x118181a1, 0x575b7fe7, 0x53571239,
+0xa7d35d43, 0x4b577f89, 0x1f817fc2, 0x6c7f9609, 0x9714813b, 0x81d723b6, 0x6c7f377f, 0xa3cf6826,
+0x08b27f45, 0xbf7f8184, 0x814de5a0, 0x8181a2fd, 0x167f3c70, 0x8a7fa9e4, 0x65ac4b7f, 0x7fd367c5,
+0x81112d7f, 0x8170811d, 0x817f589e, 0x8b7f7f44, 0xba2ab081, 0x527f5bf6, 0x2faad6e3, 0xc335a82e,
+0xb862c003, 0x81715776, 0x5081817f, 0xdd7585c0, 0xb7989d7c, 0x367f81b1, 0xa0818129, 0xc6f37f55,
+0x5006be1d, 0x817faac3, 0x7e667f81, 0xaf2c7f99, 0x347f897f, 0x2bb1aac8, 0x8112eee8, 0x7f5c62de,
+0x007f14d1, 0xa1a2140b, 0x95446419, 0x5e7fc82a, 0x7a7ff07f, 0x81fe7d31, 0x010a8149, 0x7f3e7fb6,
+0x397f81ae, 0x7b7f7fba, 0x797f5981, 0x7f7f170a, 0xb9cf087f, 0x0be6cb28, 0xdd97cf4e, 0x92520625,
+0x817f3ae4, 0x6c81c381, 0x440cc5ae, 0x2b7fb8b7, 0xe94a2081, 0x81967f4a, 0x7f817f9d, 0x7f81a7a1,
+0x815b52cd, 0xd59d57f6, 0x899e827f, 0x7f7f9aa0, 0x52819e7f, 0xda3a2223, 0x8b81073c, 0x818132d0,
+0x55638800, 0x9804bcb5, 0xc3810a7f, 0x6ddab6e3, 0x7fcae34b, 0x7f814a2d, 0xea7fed91, 0x3b9bb0d9,
+0x87d97f1e, 0x16535739, 0xcc2f7f81, 0x7f98813a, 0x5873bbe6, 0x241781f3, 0xbcc7cb33, 0x7ff69847,
+0x8d11c0dd, 0x9ac9d787, 0x66cff992, 0x7f7fc312, 0xaa4fe681, 0x39967f26, 0x201c7f7f, 0x9a7f4849,
+0x5768a814, 0x814d731b, 0x81917f81, 0x6eea7d7f, 0xad7f65fe, 0x3d3e81d3, 0xae672981, 0x7f1c81a0,
+0x9881053a, 0x81a16307, 0xf64c4063, 0xbc7b97d9, 0xa29dc0a1, 0x8161189c, 0x7478b3db, 0x87b330e1,
+0x817f0598, 0xcf422b0b, 0xc29b7ac8, 0xc2817faf, 0x8185581c, 0x81d0b675, 0xc93f7fa9, 0x814e3a02,
+0x815d6511, 0x5d81075f, 0xd768c13e, 0x89815437, 0xac810d85, 0x1a7fa5e9, 0x14a6bb81, 0x54531dfd,
+0x81dafd24, 0x978133dd, 0x818130be, 0xb67f5bb3, 0x2c7f4179, 0x81b281f4, 0xf3a463fb, 0xda36c4d4,
+0xb17f811d, 0x37ca75f1, 0x53257f7f, 0x3ef0208b, 0xdc71817f, 0x978181ef, 0x7f81d17f, 0x1197810f,
+0x277f7f47, 0x7ff6b1b0, 0x4562fca6, 0x725d89e3, 0x888197cf, 0x05477fd3, 0x4988077f, 0x81cbb5d9,
+0x047fcaa8, 0xdb7f7fc9, 0x81ccfe5f, 0xd91643ff, 0x7f3f7f7f, 0x03815ed4, 0x697c7f81, 0x815b814d,
+0x287f0d32, 0x7881a041, 0x247f95f4, 0xc87048e8, 0x3d815e7f, 0x71ba7f0b, 0x50815075, 0x7e53dc30,
+0x3f7755fe, 0x1d032571, 0x818cbaf0, 0xbda97f50, 0x7ffc0aad, 0xbf457f42, 0x66b48f81, 0x072c3f1c,
+0x433d9cfc, 0x71077f76, 0xac2d5564, 0xdc523811, 0x7f54a538, 0x7f707f00, 0x8c10a6f1, 0xf4a581d3,
+0xae875d1d, 0xd37f9747, 0x8124b869, 0x81a17745, 0x61bb8b7f, 0x227f8129, 0xa77fc381, 0x997f8119,
+0x817f812b, 0x81a78836, 0xdd557fc6, 0x907f6418, 0xbfa9accd, 0x4f815762, 0x97818181, 0xa0524fa6,
+0x815b5721, 0xc77f7f7f, 0x7f725efb, 0x437f614e, 0x81f15c6f, 0x7fb77f28, 0x473f7a1c, 0x7f81d71b,
+0x7f5133e9, 0x7cd17f32, 0xfb7572e3, 0x16c35e62, 0xc961a649, 0xdec47c37, 0x6d442844, 0x386b4616,
+0x9583c437, 0x81d57fae, 0x8114357f, 0x818f9db4, 0x7ff181d7, 0x773fb601, 0x4032fb29, 0x8613b71f,
+0x7f81b3f4, 0x1256f605, 0x297f817f, 0x9a7f2996, 0x5d81b87f, 0xc8907ffd, 0x817f7f35, 0xf6719ac7,
+0x7b7f523d, 0x18d8ca2e, 0x2681b97f, 0xc02a810d, 0x34cda181, 0x32e081bc, 0x016f7f08, 0x461bdaec,
+0x04330900, 0x633f61ac, 0xa3815204, 0xa534dda9, 0x7f81814f, 0x91a66329, 0x7f51aacd, 0x7ff681a7,
+0xabe476e8, 0xb57f9cae, 0x177f27c0, 0x7f2f8b0a, 0x1281a9ba, 0xd991af49, 0xea527f82, 0x9be09d46,
+0x28b2a2bc, 0x81c8a1d6, 0x5e1f4e71, 0x817f812e, 0x28b981cc, 0xb071cf04, 0x82cb8139, 0x81608181,
+0x819381ae, 0x818f90c8, 0x817f64c6, 0xd169c7c9, 0x8f548381, 0x87f7b03e, 0x6657817f, 0x81be8102,
+0x0d078c5f, 0x7ff97fd4, 0x7f814981, 0xb3bb7faf, 0x37c3dd6b, 0x4c6930b7, 0xb56ba479, 0xfc82520f,
+0x3494f934, 0xa2016c53, 0xc513eeba, 0x8c283bcf, 0x7fa6047f, 0x54319236, 0x42b2c19c, 0xf965c947,
+0x60777fca, 0x02767f47, 0x4921bb04, 0x81818fa9, 0x8eab7f5d, 0x81f4aa14, 0x1abdf97f, 0xbdaa220d,
+0xac368139, 0xddb1c212, 0x81d9fd99, 0x90b77f3f, 0x029ec8ca, 0x7f93d9db, 0x8563627f, 0xc5b72d52,
+0x2e6eacc0, 0x7f66815b, 0x50db375b, 0x4529813f, 0x7f8d817f, 0x44486f52, 0xbcd64c9a, 0x7fd2bf33,
+0x43507f58, 0x7281a4d3, 0x7ca82149, 0x29817fd0, 0x653544b9, 0x88c681a1, 0xd93c2bfe, 0x530835cf,
+0x5be26556, 0x7fb37fd1, 0x81e68174, 0xe88c0c42, 0xb63b817f, 0x394a81c9, 0x407f8107, 0x747f1f52,
+0x91816dcf, 0x5f818161, 0x8514aebe, 0x7f496bac, 0x5e818181, 0xe8e358ee, 0xae1a7f0b, 0xa4c97f05,
+0x77a77f52, 0x818160fd, 0x6bab7f81, 0xcec7e121, 0xf4810196, 0x4a7f68e3, 0xe56d5a7d, 0x813d2c6b,
+0x7d0b7ff5, 0x7bbd6760, 0x67812b81, 0x188197d7, 0x8146057f, 0x811eff1d, 0x818ecc4d, 0x4a786245,
+0x72593331, 0x2e81556a, 0x66aad481, 0x94818128, 0xde89ba81, 0x4df07227, 0x7f73ff8f, 0x7f44b981,
+0x9bf9e707, 0x46811bff, 0x85a96a36, 0xc13b7f15, 0x6670ba65, 0x81fcefee, 0xae8187b9, 0x73c3baa9,
+0x819e8123, 0x9cfbc6aa, 0x7f89c73a, 0x7fde9812, 0x97136581, 0xc38181e6, 0x81de9c0c, 0x4994ab0e,
+0x30977f06, 0x59dda72a, 0xc9f87fd1, 0x8186b4d7, 0xba86de81, 0x98a24c3b, 0x12157f3f, 0xd7674b1d,
+0x81816042, 0x8da8926e, 0x397f81f6, 0x3dd281b1, 0x7f6570ba, 0x7f875412, 0xd74f5be9, 0xab81f207,
+0x7feaa863, 0xab81da0d, 0x7ae79023, 0x357f8111, 0x654a468e, 0x521c2306, 0x2f817f37, 0xdb818a41,
+0x50b5b30c, 0x71817fdc, 0x7f7f7f04, 0xb13471fa, 0xd1843f7f, 0xb700ece6, 0x109064ea, 0x989b4b03,
+0x27556fd8, 0x5ecee700, 0x5f5a2281, 0xa81c81dd, 0xac54b6bb, 0xe60f1ae8, 0x139dc4dc, 0x22818109,
+0x2c7fc74f, 0xa69cf331, 0x9d272281, 0x7f9a6da8, 0xb1bb8f45, 0x81815a6e, 0x8315517b, 0x638181f0,
+0x273db266, 0x90777f18, 0x047d763a, 0xbdf50a4e, 0x7f5f5c12, 0x817f7f53, 0xcb177385, 0xb2ca7f22,
+0x818eaa17, 0x815d4c81, 0xa67fc281, 0x7fd856eb, 0x01becb84, 0xa8e2685d, 0x7fadbe7f, 0x1b7f6a05,
+0xef47f495, 0x817f1b1b, 0x8c8d0b81, 0x57b9a5d4, 0xdc298159, 0x5e81a7e2, 0x81467f5b, 0x370f6df0,
+0xc49c30a1, 0x7a545710, 0x974b81ff, 0x458c814a, 0x237f17dd, 0x427fb6da, 0x1a7fe5de, 0x817f8121,
+0x817f1c96, 0x9c817f90, 0x0e7fd365, 0x818aa15b, 0x7fd302f2, 0xdb7c138e, 0x7fe68181, 0xbf818112,
+0x7f2e7fc8, 0x81728101, 0x6482d830, 0x59e24b0b, 0x9b67c284, 0x6e811018, 0x81a42c32, 0xd87a4da2,
+0x817f2d41, 0x3e2fbce2, 0xd1d44623, 0x7464b44c, 0xcc255f95, 0x56c93b38, 0xa87f1491, 0x04819c5c,
+0x7f457fd8, 0x8d6bb866, 0x819c8181, 0xbc118166, 0x3d4c2a5f, 0x7a6d51fe, 0x79065067, 0x8181d1fb,
+0xff6f2b08, 0xf5be7f35, 0x9fa567f5, 0xabb581b4, 0x81819a5e, 0x7f8187c5, 0xaa7f5669, 0xdf526044,
+0x7f6ea5f5, 0x7f3a68c7, 0x4feb7fb5, 0x627f2850, 0x39f49181, 0x71ec22ea, 0xc17f4c44, 0x56f4db23,
+0x7f08cc95, 0x977fde95, 0x7f4f7f81, 0x81e07f1c, 0x5e7c7fe9, 0x1c3534ce, 0x7f907f2b, 0x7f83418b,
+0xeb81daec, 0xa6fc892a, 0x757f7ffb, 0x6281cc2c, 0xb826cecb, 0xc7810a2e, 0x60d1906e, 0x7f8175ed,
+0xd085cb36, 0x88c4811a, 0x5e3e707f, 0xaba57fff, 0x099c127a, 0xbac67fb7, 0xa9817d82, 0x4f6c7faf,
+0x43d17a0b, 0x92a13dc8, 0x81995d8d, 0xab7f90fd, 0x5f1f8189, 0x767f8101, 0xb7caa2bc, 0x7f8177cd,
+0xe0655857, 0x81cfebeb, 0x81af6fc0, 0x57ac6dae, 0x437f8176, 0x513c60fb, 0x9ef3c081, 0x78d0d12e,
+0xa40c7f0e, 0x438101c0, 0x81816405, 0x6f527f04, 0x8d0fa47f, 0x6d7fbb7f, 0x39187f74, 0x3c7f5f06,
+0x677f7fdc, 0x8114250d, 0xe08373c7, 0x9c7f7dd8, 0x816341a3, 0xdf7f073e, 0x7f818174, 0xca84e8ff,
+0xd6ff70ef, 0x7fa1a3c7, 0x7f7f8148, 0x81de7fa2, 0x4d323671, 0x5aaafbff, 0x05ac7f7f, 0xd58102e8,
+0xad6c45e4, 0x81677f27, 0x818132ce, 0x7fa55a1c, 0x553029ce, 0x81a47f06, 0x81ca6189, 0x5cd581af,
+0x70f34733, 0x676d431f, 0x81387f66, 0xef916df0, 0x72099950, 0x867f81fe, 0xaa7f657f, 0xd7521bef,
+0x81d573c6, 0x7f76bcd6, 0xaba4c10b, 0xe394b7d7, 0x82579781, 0x88f5715a, 0xf7815cda, 0x65817727,
+0xeab07f22, 0xbb5f7c40, 0xc0a48139, 0x95442a2d, 0x857f7d81, 0xcd7a81ee, 0x7971819e, 0x3a31f0fe,
+0x537f6181, 0xc307bed6, 0x8936627f, 0x98b18136, 0xd07c817f, 0x7f7f8126, 0x133a607f, 0x98d40015,
+0x368a8123, 0xe181501d, 0xc9817681, 0xa27b2e00, 0x47dd81e1, 0x0e7f81d3, 0xf3287fce, 0x7f3400c9,
+0x8d65c745, 0x4c8148c4, 0x21817f7f, 0x81ac0af0, 0x4462c1fa, 0xa99e4e8e, 0x7f153ad8, 0x8168bb47,
+0x8370e19d, 0x7f3281ca, 0xf2437283, 0x667f279d, 0x9cb4c17f, 0xde814315, 0x72d3a17f, 0xac113b66,
+0x6c13abef, 0x7f816cb5, 0xc8c7c37f, 0xa7d1862e, 0x8b7fb87f, 0x9dd9a384, 0xb69b22f0, 0x157f710a,
+0x9007c13f, 0x4518caf0, 0x836c4246, 0x03f981d1, 0x817f7f7f, 0x4581b92f, 0xb4718193, 0xa8815e05,
+0x437f81fe, 0x52817fdd, 0xb1477f54, 0xc12e3cba, 0x7f81815f, 0x4e737f32, 0x817fc141, 0xa67f7f58,
+0xd19dab37, 0x8b9eb14b, 0x7fe8be30, 0x905d7fba, 0x16ae520b, 0x81015d10, 0x71812450, 0x1de37f1b,
+0x811fa6af, 0xdf77b8e9, 0x647ff1bf, 0x17be7fbb, 0x817f6224, 0x8115e99f, 0x7fca7f7f, 0xd48f0fa2,
+0xda7fc4ac, 0x10649756, 0x2f89af26, 0xdb5f3ec4, 0x817fde7f, 0xbde94df1, 0x9a707fb7, 0x7f7a656b,
+0xfad88c3f, 0x7ccc7f5c, 0x7f8cc477, 0x7fc26452, 0x28c7812f, 0x85b7a1ab, 0x818181ad, 0x404ce719,
+0x540fe3e5, 0x705bf0fd, 0x6206a54a, 0x89486861, 0x75e25f81, 0x3c9bc93d, 0x3457c36d, 0x57ab2f25,
+0x3cd9bd13, 0x81769cbe, 0x87557fae, 0x025c7109, 0x05457f64, 0x5f427f13, 0x5c7f26be, 0xb9818130,
+0x34e63305, 0x8a81ebcd, 0x673326ba, 0x05647ff7, 0x818b8181, 0x8c81782a, 0x4bc0b30f, 0x759749c7,
+0x399e99f6, 0x7fdb4313, 0x9c7f5cae, 0x6cc2a611, 0x811dab81, 0x7f7f413b, 0x4fb37081, 0x818c8164,
+0xac4c01d8, 0x1f63813e, 0x81db7881, 0x8194404b, 0xcc9bc55f, 0x542900eb, 0x87ff34c5, 0x507f7fa2,
+0x7fd97f03, 0x79e428e3, 0x2f7f7c6c, 0x57813f13, 0x7f7f817a, 0x61c40926, 0x68a9457f, 0x63ea9f2f,
+0xea81a8ec, 0xfd81301c, 0x81cd8181, 0x812cf7fc, 0xc996b697, 0x81895df8, 0x8d4ae3ca, 0x4c5de834,
+0x81643d19, 0x202babce, 0x55a89081, 0x64ba81f9, 0x7481db7f, 0xa0eba6bf, 0x81c12ee3, 0x8181a75d,
+0xc8e9939c, 0x0981295a, 0xf22e527f, 0x817f3314, 0xc4f17f5e, 0x8c83651a, 0x7f74a17d, 0xbdd28405,
+0xb6bc4795, 0x388c7cdd, 0x957f7f7f, 0x1db7ec29, 0x68f59c45, 0x8142eaa1, 0x81f0b543, 0xa48163fe,
+0x81d08134, 0x7d673f5d, 0x8ecdcf94, 0x6e56195a, 0x7f222687, 0x7fd8fb10, 0x81aa977b, 0x22014258,
+0xd541be81, 0x817f62fb, 0x707fea79, 0x7f817f60, 0x4b7f3c7f, 0x60a4032c, 0x1c68c2ae, 0x7fc27f19,
+0xd5a55cd4, 0x09a651f4, 0xb5447f7f, 0x7f815bfe, 0xe681d381, 0x1781f900, 0x8eb6b0d7, 0x1d90fdf8,
+0x528147c4, 0x816b7f46, 0x7f6381c3, 0xd5d2088b, 0xcce4ae52, 0xdf4ec304, 0x967e5e1f, 0x567f1439,
+0x317f810a, 0x815f814b, 0xe13ee67f, 0x7f8177a3, 0xac69c42a, 0x7f5837e7, 0x61b481c8, 0x777f812f,
+0xcea38116, 0x6b6b7f37, 0x8feac838, 0xf9457f3c, 0xe5107f74, 0xcc957f56, 0xa3ab7f81, 0x81817f6e,
+0xc5817f2b, 0x197d0d99, 0x7ad0c84a, 0x81ada865, 0x81b31c81, 0xee7f9b54, 0x815a3406, 0x3f617fce,
+0x3d4db8c2, 0x5ac39e72, 0xd390812f, 0x27c6ede7, 0x6f69d981, 0x2981f141, 0x7faa2681, 0x787f6668,
+0xc24ec00e, 0x7f008142, 0xfa811aad, 0x2d567fb0, 0x5adb7f65, 0x8a864fc5, 0x6d817f85, 0x307f7f1f,
+0x5c817f47, 0xcc7f43b6, 0x9bb08159, 0x496f7f2f, 0x41e383c2, 0x4e7f7f88, 0x71ce63e4, 0xe07f4c7f,
+0x857c58ad, 0x8599641d, 0x655c687f, 0x97a64fde, 0xdd42707f, 0x29ced6b6, 0xdf25c153, 0x7f047fbb,
+0x7c5f462e, 0x61d08548, 0x7f7fab7f, 0x48b1ecb0, 0x93c63349, 0x039c7fe3, 0x817fce1a, 0x29bb7112,
+0x7f3bbaf0, 0x81818d2f, 0x7f5b3d41, 0x1fa18160, 0xc481af81, 0xfc818130, 0xdae2bd73, 0x4d3c81cc,
+0xa47f5f0a, 0x5e3ad1a6, 0x1a816eab, 0xb307dbd0, 0xa8798b88, 0x7f81252a, 0x6d7f2899, 0x4d7fa214,
+0xc375762c, 0x7fb655ab, 0x5bb98185, 0x1381682c, 0x5281ca7f, 0xc56d7fc8, 0xa81d8170, 0x8daa50f4,
+0x8bbf7f03, 0xcf7fb0c2, 0x3b733caf, 0x7f756442, 0x8c81353c, 0xf7e82f0f, 0xa5a620f2, 0x8ae39fea,
+0xada55ad4, 0x74f1de4c, 0x37714753, 0x538193e3, 0xb1811481, 0xe5bd81cb, 0x70fc4ea8, 0x888473eb,
+0x30b57f1a, 0x90c3f010, 0x81817577, 0xea8c4ae4, 0x6977547f, 0x549481a8, 0xf27f54b8, 0xf87f7fd3,
+0xef81843e, 0x5a437fbb, 0xa77f8181, 0x77354c05, 0x9781667f, 0x7fc2ae7f, 0x0b81b868, 0x1267b5e3,
+0xa0de743b, 0xb4cce348, 0x8192819d, 0xf0817faf, 0xecc781ab, 0x7f57af2a, 0x499e13c0, 0x7f3d632a,
+0xac96fcc8, 0x81727829, 0x7f7ff281, 0x81819bb4, 0xc5bfd358, 0x76553120, 0xb57dbcb5, 0x9b425d12,
+0xb0814cc1, 0xea3d393b, 0x1dde5e27, 0x03a6f127, 0x39a9a981, 0x94304751, 0x3af97f00, 0xceaa49d8,
+0x3c8124d1, 0x7f24b547, 0x2830e08d, 0x3d7a8f0e, 0x456ffc4c, 0x814e7f4a, 0x357f817f, 0x7f61bc51,
+0xd7097f44, 0x213ecf47, 0x815281bd, 0xa9a58187, 0x0c3cbfb2, 0x18f92fa4, 0x307f7f52, 0x727f3361,
+0x6cdc8e37, 0x7f9d9e24, 0x64466e7f, 0x2491328c, 0xd58181cb, 0xc97ff4b1, 0x1890627b, 0xa48168b3,
+0x7fad44dc, 0x411b7f43, 0x6681647c, 0xc5171bcd, 0x4a6d7fd9, 0x7e369d2b, 0xf8124f61, 0xa71515f1,
+0xb381ec09, 0xc4ab71c0, 0x9e2e977f, 0x7f7f0d58, 0x1cdb7b16, 0x81f87f81, 0x517f7f60, 0xf4a3ea33,
+0x5c2112c3, 0xc67f7e06, 0x9d7f78c6, 0x811730e4, 0xa29b6170, 0x81817fd1, 0xb6637f87, 0x4f1c540d,
+0xe57f7707, 0x277d5c28, 0x7f817f21, 0x5e31e1ab, 0x7f81cd81, 0x815daab2, 0xec5284bc, 0xb45d7b63,
+0x7f4d815e, 0x0860494f, 0x81874034, 0x81d0f00a, 0x5b4274ea, 0xdce04fd7, 0x8188680f, 0x827f7fc7,
+0x8137e715, 0x9f7f6699, 0x786e75eb, 0x8253202d, 0xb2813ddd, 0x7315a11a, 0x81c18164, 0x7f7f8141,
+0x6870da25, 0x117f3efd, 0x7f1c5f1f, 0xcb6d63bf, 0x45561890, 0xc3df8136, 0x23275f32, 0x81817f5d,
+0xa50f7fde, 0x7f3ba6ae, 0x37a4bbf4, 0x81a6fd1a, 0x9b9bb6ec, 0x8b2cff0a, 0x2035d781, 0xa1c47fce,
+0x095dee2d, 0x7f3a2d51, 0x69727f7f, 0xec8aad61, 0xb0dbcc42, 0x2e706fee, 0x962a9d53, 0x81814554,
+0x759026dd, 0xb38851cf, 0x817fa70b, 0x7f462fb9, 0xcc7faf23, 0xa2981632, 0x3e8d8160, 0x07815dd2,
+0x82817f22, 0x5a755325, 0x45c77f81, 0x81653cac, 0x93f73dd9, 0x3d81c4cd, 0xf67aa181, 0x467e7f1f,
+0xe6c10cfa, 0x9bd4c12f, 0x6c51ca85, 0x4d7f2835, 0xc0bb341b, 0x81812aed, 0x87a181be, 0x4f7f7f6d,
+0x81c9e3c4, 0x117f95bf, 0xd457e634, 0xb84b567d, 0x5618f922, 0xda7fc1ed, 0x7f7f81d6, 0xa07da0b1,
+0x2e627f0a, 0x814ee836, 0xb65bff90, 0x3e29b6de, 0xb1b78f5d, 0x1724a1f0, 0x81484221, 0xe16d7fb6,
+0x578181f2, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+hard_output0=
+0xb5bc6ac8, 0xf5373664, 0x1310345c, 0xd5bae4e7, 0x1fc9e83e, 0xebfdfded, 0x84bd86ab, 0xb7aabe00,
+0x60b44fea, 0xb9067464, 0x30325378, 0xa9195955, 0xf70c6e5c, 0x90922632, 0xc90b1cdb, 0xf2f5fb69,
+0x73056b63, 0x1a33bf3f, 0x17755b5c, 0xc58bff6d, 0x2f4390b2, 0x2869d508, 0xe7c7dfe8, 0x38552963,
+0x21da5367, 0x07282b9b, 0xa4767105, 0x1e294251, 0xe350a940, 0xb8a6aa27, 0xed12d778, 0xf10d9ece,
+0xab93527f, 0xcf2da7e7, 0x68f6d0b1, 0x811f4bca, 0x577b06b2, 0x3234f13e, 0x30bab7df, 0x8dc47655,
+0xbb843bed, 0x86da3aba, 0x30950c97, 0xdd096d7a, 0xa871fd6c, 0x8bee4e6b, 0x8fea30d0, 0x6c05b4d2,
+0xf3e144d3, 0xd24ebb1f, 0x065635e5, 0x8d3f2cf9, 0x536c6c6a, 0xfbb0a5d0, 0x3d707b42, 0xc44d5982,
+0xa5f4ad8f, 0xf32c0970, 0x1bccf1a6, 0x05916020, 0xa64fb176, 0x5ede6a35, 0xaf4966da, 0x9df5e0e7,
+0x75042abc, 0x9ef10481, 0x11ddcbc8, 0xa0f5518c, 0xd5c23418, 0x2393d558, 0xfbe7dfeb, 0xed1c64c2,
+0x86a36508, 0xde2dfb1e, 0xb8d0fef9, 0x24505232, 0xc894e71c, 0xbcc752a0, 0x40b74e83, 0x90d23c8c,
+0x728e4a61, 0x108f0b08, 0x66f522ee, 0xc258d851, 0x35a31c44, 0x11311b5b, 0xfd3d5be9, 0x5ae448ff,
+0x4f64994b, 0x5b8247a9, 0x4021114d, 0x2f0b6e82, 0x5eaa9828, 0x50ac71c0, 0xfb86ee52, 0x0dc1ac9b,
+0xbbd47645, 0x8f357115, 0x978ceea0, 0xd557db99, 0x99b30388, 0xfc9a8a1c, 0x0f75be1a, 0x50143e22,
+0x8840989b, 0x738ec50e, 0xe6b2783d, 0xf67899c8, 0x27ebed69, 0x6c415a16, 0x3a6cc2dc, 0xcd4e4e5d,
+0x6cb12b2e, 0xdb88d7c0, 0x79cd1582, 0xbc422413, 0xe72ad2f4, 0x8eaac30f, 0x0bd86747, 0x6d87f69d,
+0x15d62038, 0x4b375630, 0x0d51b859, 0x16db2cb2, 0xf210603a, 0x0abeb833, 0x55c694d0, 0xe57ca43b,
+0x0ba94428, 0x1398a406, 0xe47d3889, 0x5a20203d, 0x250d7a1a, 0xd930ffec, 0x03992e79, 0xf2759376,
+0x024ec121, 0x91fc3a2c, 0xb7e11cc5, 0x4ff7d459, 0xb8700134, 0xd6e61758, 0x4eba0a32, 0xb747e3ec,
+0x7073fad7, 0xded80f99, 0x331e2f1b, 0xfa1f1bed, 0x056424a2, 0x1d1d95e0, 0x550b9ec8, 0x51ee2a38,
+0x19525153, 0xd70c4cd5, 0x0d6cd7ad, 0xe44d1cf2, 0x30dfecda, 0xdacd7fe8, 0x7321d795, 0xddf48ef4,
+0xe271e6a4, 0x9c1feecb, 0x951fcd7b, 0x8acc5a03, 0x3fb83527, 0xe306de74, 0x7b9cd6ee, 0x8e140885,
+0xd4c91e8d, 0xe8c39733, 0x0f02f87f, 0xfb06b1b9, 0x0dc9349c, 0xf76bae8e, 0x4f642a07, 0x3d48a9aa,
+0xe3ea323a, 0xa1cd5c8a, 0x40aa0e70, 0x132042d3, 0xa9732f6c, 0xd15a00c4, 0x43d3b046, 0x9a51ebd4,
+0xc46ee0ed, 0xe2a2148b, 0xf5c478f0, 0x1fb01cf3, 0xf4f321ec, 0xd973811f, 0x11ad11b9, 0x5c67adda
+
+e =
+34560
+
+k =
+6144
+
+rv_index =
+0
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_negllr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_negllr.data
new file mode 100644
index 000000000..b5ef62461
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_negllr.data
@@ -0,0 +1,1224 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x0a45ef00, 0xb2bdc60f, 0xc810d206, 0xf21cc300, 0xb0c93da1, 0xaae019d7, 0x23ba3c29, 0xa61d1e09,
+0x202906d1, 0xd2b61ef3, 0x59e7f241, 0x2ec8daec, 0x68015520, 0x0912f4a3, 0x01282329, 0xa1fd1439,
+0x0701231b, 0x0fdcba0a, 0xbe97c6c3, 0x0438e652, 0xd5f644d4, 0xbd0e5f4b, 0xfcb6d0d4, 0x0825b15a,
+0x362e2fc8, 0xbbd5abda, 0x0df8c12d, 0xd016b5de, 0x1e439a0c, 0x44c94242, 0x00e2e8c5, 0x0639d241,
+0xef6aa40b, 0x90de9def, 0x43e0ea14, 0x31dd07cf, 0xbad70a05, 0xcffc228a, 0x00293bd7, 0x6038080c,
+0xdaeb3e20, 0xdd260c4c, 0xaa41fb3c, 0x6eeef0d4, 0x5b02c0f3, 0x14d6ac69, 0xfef0ce44, 0xc5abccf2,
+0x2a0f00c4, 0xd6cadb30, 0x38e212cf, 0x5e9abc29, 0xf105fce4, 0xde34e024, 0xb9d42365, 0x281eb22e,
+0xb219c055, 0x6504b01e, 0x465602ab, 0x1233a4e7, 0xa9ebf4cf, 0x63c1ed3f, 0xdbe9b71f, 0xf994579c,
+0x22f359b5, 0x3606379d, 0xae30fa1e, 0x1d6e290c, 0xc6e0440a, 0x2f129132, 0x1b317bf6, 0xcfdbc119,
+0x32022857, 0xaef168dc, 0xa1251d37, 0x65eec43b, 0x9630e70e, 0xe9e1fd98, 0x3e02d8ab, 0xf348af3e,
+0xf7b0f027, 0x2ff021db, 0xecae5bd4, 0x1b2f3e34, 0xbb2511c0, 0xd611ddad, 0xf951d2d6, 0xb1dd0191,
+0xc325cf35, 0x58bdf4b7, 0x36094dd7, 0x07cd3b44, 0x02c4ae4d, 0x812af6d9, 0x32f63731, 0x31103329,
+0xac0033ff, 0x817f583f, 0xc4817f88, 0x8d81790a, 0xa6a2817f, 0x7f81910a, 0x7fc5ed7f, 0xbf2f7f8d,
+0x7ff14707, 0x49cc3bda, 0xb04d5a2d, 0xd8d392b0, 0x7f69d3e1, 0x83ae43ad, 0x99b7da75, 0x3a7f7fd3,
+0xd46d6fd2, 0x4f7fc524, 0x137f812f, 0x587fcd8a, 0x81c481bf, 0x9caa6184, 0x0bc3a499, 0xe2901a23,
+0xfeb59b6f, 0x7f818171, 0xf68ed39d, 0x8113a975, 0x81dd6681, 0x7ffe707f, 0x5836757f, 0x48a98122,
+0x7f724081, 0x81588447, 0x59f8b799, 0x7f6dbab0, 0x817f8f09, 0x13c3ecb6, 0x7ff98d64, 0xc4911e81,
+0x33922f9b, 0x05c9e85c, 0xa19071b3, 0xec1ca24e, 0x02a48181, 0x813b8196, 0x7fca7d51, 0x7f81814d,
+0x00815911, 0x242a7f5f, 0x29d6ee98, 0x8a61887f, 0x4e815e7f, 0x773e811d, 0x8e65d1a7, 0x8d514860,
+0x3081b248, 0x7f2393ab, 0x815d2e31, 0x817f4be2, 0x81818519, 0xa07f677f, 0x0defa853, 0x22811c4c,
+0xbe81d32d, 0x2d7fdc7f, 0xd8f3195c, 0xf69bc13a, 0x7f7fdae1, 0x2a56717f, 0xd4811c7c, 0xbe218c81,
+0x81a556d3, 0x3f43a8c4, 0x6a95b0cf, 0x427f79db, 0x959cbc5c, 0x9f00dd19, 0xa1e8c5d4, 0x59814997,
+0x4e35eb7f, 0xf87f348b, 0x76749124, 0xab7f7f1c, 0xf0816c81, 0x8c62b45d, 0x744ec34f, 0x329a7fce,
+0x9048b815, 0x0076dcd0, 0x812d2981, 0x98d5cb15, 0xd29652cc, 0x2cd15e33, 0xc2557f91, 0x03517f6a,
+0xfc1cc134, 0x0f7f6a00, 0x81939c0e, 0x7f4677a9, 0x7f597f5e, 0x4f972a86, 0x81b2ab81, 0x207f7f69,
+0x85b9b234, 0xc1857fac, 0xedaa7c08, 0x7f50057f, 0x7f1dc26d, 0x7fa47f81, 0x7ff57f76, 0xb3bca5cc,
+0x6b31d550, 0xce3a6583, 0xdac01f7f, 0x81184838, 0x65239c09, 0xde415bf5, 0x7f7f3881, 0x097fdc7a,
+0x81698160, 0xa8da57db, 0x3281530a, 0x628d057f, 0xad7381f2, 0x18a35579, 0x3d909f7f, 0xbf7f7f81,
+0x8181eb36, 0x6bd45881, 0x578c7520, 0x417fdc89, 0x307f5bad, 0x667f8181, 0xe1b44f6e, 0x817f7f2b,
+0xd55cb62e, 0x8aa0ab9a, 0x81e42e47, 0xbc925270, 0x77aa4a90, 0x56247581, 0x8ff5f670, 0x7d7f9cc7,
+0x3a013a2e, 0x10810005, 0x815eab7e, 0x812fe1c6, 0x81f0b47f, 0x7f2b8c03, 0x7f7fc07f, 0x7e497281,
+0xd1d70cd5, 0xd981b501, 0x0c63b57f, 0xd8a8ea7f, 0xdeaece7f, 0xa08107f0, 0x9f54e62e, 0xa8cfc431,
+0x7f985ee1, 0x811ae887, 0x7f81df4d, 0xc081d1bb, 0x81a15a9a, 0x7f44bf05, 0x037f057f, 0xf22c7f9d,
+0x7f7f7f7f, 0x81856e03, 0xbcb08381, 0x46bb372d, 0x7f7bd59c, 0x8157e815, 0xa1910b3a, 0x5c537f7f,
+0x3e81717f, 0x4851ac7f, 0x813b7f83, 0x867fb25e, 0x098131ca, 0xb06fc77f, 0x7f60e97f, 0xa25f5c46,
+0xe82eae48, 0x40bf987f, 0x817f81e2, 0xf5b2c831, 0x810597de, 0x045c7f4b, 0x81e33f36, 0x81aaf35e,
+0x81817fc6, 0xe700587f, 0x93b37fea, 0x9f81fc97, 0x4def727f, 0x6bc07fe7, 0x7f811076, 0x81248175,
+0x0a7e5cf6, 0xcd7f7f81, 0x7f49f37e, 0x8181917f, 0x7f70df81, 0xd17f81b5, 0x1f6b4ef7, 0xa21d6b8b,
+0x7fb0461a, 0x5c027581, 0x81819bb4, 0x816ee78f, 0xad7f817b, 0xe481a10a, 0xa1cb8d81, 0x32813e3a,
+0x947f7f81, 0x8184bff3, 0xa96cd072, 0xeb0c5881, 0x814ab385, 0xe3f67f7f, 0x584a81c9, 0xdbc5c781,
+0x78816e49, 0x817f8a81, 0x7f3f7fff, 0x56d89f40, 0x4397e427, 0x7f29b20d, 0x7f597fad, 0x35817f65,
+0x0a7f3b19, 0x61c97f81, 0xc6817a65, 0xaa5ceb7f, 0xfc427fef, 0xb8684c75, 0x447fbaa3, 0x4d7fae7f,
+0x8196e3bb, 0xe1588132, 0x7ff27f34, 0x8173bff4, 0x7f705f6d, 0x7f7f817f, 0xa353354c, 0x7f58ca67,
+0x7a5a7f9c, 0x1e81ee7f, 0x98d681d9, 0x9e60c443, 0x7f7f39a3, 0xc79bc87f, 0x3ae8827d, 0x9f812e81,
+0x7f6f8170, 0xa987947f, 0x2481aa81, 0x538fdd7f, 0x237f1442, 0x14e99a84, 0x6e62b068, 0x7b810541,
+0x73a57fad, 0x69977881, 0x9be9cd7f, 0x9a48537c, 0xfccc7f47, 0x7f40a457, 0xbc63b4b8, 0x74bb447e,
+0x36817f12, 0xd371cd1f, 0x7f1ed17f, 0x36624bbe, 0x726c811b, 0x4abe5c58, 0x81de39c1, 0x7b5ae996,
+0xaa818105, 0xa881bebd, 0x5e7f6edb, 0xa8d08165, 0xd495f17f, 0x7fd06098, 0x7fb157fc, 0xc0f661d3,
+0xd09f812a, 0x7f8ef77f, 0x69477f00, 0xf45f8481, 0x0f7fa07f, 0x97f17f7f, 0x6ceaac7f, 0x7f7f8163,
+0x7fbcbe98, 0x698b697f, 0x79c0da81, 0x8b81e681, 0x81817f36, 0x6b814881, 0x7f918ec6, 0xb67aed0e,
+0xc5020b85, 0x81ee8c18, 0x7ff650a5, 0x814f6233, 0x508139a1, 0x814e6aa1, 0xa055487f, 0x3ed75817,
+0x4f7f81da, 0x1ddcfa81, 0x7f7f1dbc, 0x825b6454, 0x2ee6819b, 0x73eb6861, 0xf7fe9516, 0xe3816dc5,
+0x527f3f7f, 0x550d8fb9, 0xf3f82681, 0x5954b562, 0x7e7f20bc, 0x817f6b4f, 0x8108bc22, 0x17fb8113,
+0x7b040f33, 0x586282d5, 0x078c5c7f, 0xe17fc493, 0xdd813545, 0x9ba17f6e, 0x7fccfad5, 0x916f7fa3,
+0x21ce7f1f, 0x1a037f81, 0x8e4d0081, 0x7a360731, 0x167fd77f, 0x96762a84, 0xca5660e3, 0x45f0d87a,
+0x7fd151ae, 0x9e7f22a6, 0x7f817f8c, 0x1501b9cb, 0x886c4184, 0xea627f6c, 0xc53e7f08, 0x1a63d6eb,
+0x481b4a73, 0xca816575, 0x167f7f7f, 0x15814549, 0x6d985e81, 0xa60b1f62, 0xa1818181, 0x33af7f7f,
+0x816c7ff7, 0x7f81b67f, 0x08602281, 0x9a81815b, 0xe6787f3f, 0x7aba4f81, 0x5015817f, 0x1d02d55e,
+0xbaf3e826, 0xc34ca8cb, 0x503e7c82, 0x647a7f60, 0x7f810873, 0x81149d63, 0x7f818181, 0x7f7ff3d1,
+0x11d8dce2, 0x7fe3634c, 0xb63c535b, 0x810e6181, 0x81277f54, 0x817fa2dd, 0x34c34476, 0x848a65f8,
+0x96f911b0, 0x9aa76464, 0x8200816e, 0x6d7f56a6, 0xcdb9e57f, 0x874e836a, 0x93a363a6, 0x41c09883,
+0x8144c072, 0x52a77fef, 0xe8ded5e2, 0xf6857f81, 0x81b79f4c, 0x7f7f71a2, 0x2b5852bc, 0x1f7b43b0,
+0x4c5aa37f, 0x557f3d2a, 0xa17fb581, 0x7349d204, 0x4042ec2b, 0x89cd96bb, 0xd3368281, 0x7f7b8181,
+0x0f28f5cd, 0xe8aa4d23, 0x88628b33, 0x8181817f, 0x758197af, 0x37b43b4a, 0xc081c1a5, 0x8e3c4881,
+0x7fcb0983, 0x55fe14e4, 0x734c7f20, 0x89267c21, 0x7781a4b7, 0x7f7f4eb3, 0x81ac8fa2, 0xddc20981,
+0x7f9b2659, 0x2d7fc65e, 0x818181e8, 0x6a176a89, 0xaa7fb68e, 0x5c5446d2, 0xda7dcc81, 0xc3a5e054,
+0x7881477f, 0x7057146f, 0x00764b7f, 0x7fa87f7f, 0xa4ff8181, 0xf07f7f7f, 0xa37a5cd3, 0x28a881b1,
+0x13e0cb4f, 0x8f7f9804, 0x3d343181, 0x567fda8a, 0x5828c7d0, 0x434fe70a, 0x7fd5fe78, 0x1f818181,
+0x686103cf, 0x62aab5ee, 0x5506cb88, 0x5428ad7f, 0x51908c1a, 0x6d5db4ef, 0x3f7f686a, 0xa6a15a8d,
+0x917f7f53, 0xb77fea86, 0x7f816aa2, 0x6ae581d7, 0x54ad634a, 0xd59ca328, 0x6d815bfa, 0x5f470046,
+0x23818188, 0x817a9419, 0x7f57dc81, 0xb02a81ad, 0xe986757e, 0xd9810681, 0x81f7be26, 0xbcb5cf7f,
+0x63776b56, 0x4358bc47, 0x528aa47b, 0x9e7f7181, 0xd0818100, 0x0d811a7f, 0x7f818155, 0xbe207fc3,
+0xb70d393c, 0x812bbd48, 0x7f7f7d0e, 0x81b5ab00, 0x1ecb8681, 0x24c67fcd, 0x2fc7ed01, 0x5503a881,
+0x7f3d7fb4, 0x9a81559e, 0x6508d5f4, 0x08b56b7d, 0x96d84e10, 0x7fac9ec1, 0x817ca281, 0xd9b01081,
+0xaf81d3a7, 0x8102b34b, 0xa0f98181, 0x7f7f929e, 0x3cf6d023, 0x990ed581, 0x147f817f, 0x81483a81,
+0x68375130, 0x487f1451, 0xa0973d81, 0x87d4d4f7, 0x90633e22, 0xbc7f45e0, 0x2c4ea77f, 0x0811896e,
+0x8d7f52e9, 0x8120aeb0, 0x3d159d81, 0x93cb0097, 0xce81bb81, 0x74194855, 0x4e7f3f26, 0x817f819f,
+0x4531814f, 0x517f7fbb, 0x4981a87f, 0x4c810f4e, 0x3239b67f, 0xa17f194c, 0x81e58e81, 0x7f4890e5,
+0xb07ffa3c, 0x937fa181, 0x447fa516, 0xbab5000e, 0x887f7f7f, 0x8181b17f, 0x7f82d4ad, 0x7f828159,
+0x81b35c57, 0x23bcb1dd, 0x819446c7, 0x7fbf9ea6, 0x817f7fc1, 0x33817f81, 0x5cfe7fb6, 0x7f81fc61,
+0x91477f4c, 0x88994381, 0x65bb447f, 0x198d61ae, 0x817f9f7f, 0x557cbcb8, 0x81fab781, 0x1bab3f7d,
+0x7f812298, 0x7f44fadc, 0x1dc1c665, 0x7fde3a8d, 0x94c37f2b, 0xc7d8eb23, 0xdaae8181, 0x129c68bc,
+0x7f819111, 0x7f32ce2c, 0xf0d17f02, 0x7f6a817f, 0x5cd564e0, 0x7f7fc47f, 0xd6995c9d, 0x70a7d476,
+0x3b7ff299, 0x7f2f237f, 0x4381ac1f, 0x0bd67fb2, 0x81ba594d, 0xa6777fd5, 0x881cc254, 0x8189977f,
+0x7f813b3e, 0xc17f7f7f, 0x3baa3dc9, 0x81007f57, 0x7f810295, 0x81f7a1c3, 0x7f65de7f, 0x4ca87f53,
+0x407f81b9, 0x7f436fa6, 0x399f9581, 0x7f177f86, 0xbc698194, 0x447fd081, 0x81663d37, 0x01faee9b,
+0xc485ff7f, 0xed6ff281, 0x4c6713c4, 0x28b0487f, 0x7f88e8c9, 0x8169016d, 0x7f7f71dd, 0x474bf37f,
+0xb756b143, 0x95caeed0, 0xec7f872d, 0x437f23e1, 0xb42b3030, 0x662f8d76, 0xd4818f71, 0x8161fd50,
+0x8863663e, 0x78256b06, 0x661b549c, 0x8e817fb4, 0x06b98354, 0x5a905ec1, 0xec960281, 0x2c30bbe3,
+0x937f7f63, 0x6ade543f, 0x7f7f9f5e, 0x98dac336, 0x81327f73, 0x677f6d46, 0x637f5c7a, 0x82478181,
+0xedbc9014, 0x9a7f431b, 0xb2d25981, 0x7f898181, 0x81815ab1, 0x2d7fa683, 0x7f03b2b0, 0x89bc7f18,
+0x81947fb8, 0x1995817f, 0x78e54c17, 0x816cb1c3, 0x1a2681e0, 0xac3a7f8a, 0xdff245bb, 0x422ada81,
+0x1ed1e07f, 0x7f6f5276, 0x8481db81, 0x9a817fe4, 0x1e132dab, 0x5c7fdf7f, 0x7d81ac7f, 0x937f7fe0,
+0x49568171, 0x3f81907f, 0x81466896, 0x7f667f2b, 0x577f9a7f, 0x7fd73c0b, 0xc946df59, 0xd72f767a,
+0xb51d326a, 0xc77f4f7c, 0xbc814bf5, 0xdae47fab, 0x40a64f73, 0x898188ea, 0x1c751c97, 0x7f8ed37f,
+0x81b9585f, 0x6eb6758e, 0x5e11b233, 0xf0a47f81, 0x81709065, 0x447fbcc6, 0x58d1819b, 0x9fa36e74,
+0x817fa9f3, 0x9f506f66, 0x81cd047f, 0x187f8136, 0x9d810500, 0x64cd8eb0, 0x7f817f7f, 0xf850e2f6,
+0x81b61869, 0x606a66c4, 0x81638118, 0x20dca772, 0x6287b381, 0x8e056874, 0x086d99b9, 0x54438172,
+0xb281697f, 0x5c470c16, 0xb0340523, 0x7f81b96b, 0x4451b8a1, 0x7f7fe6db, 0x57887f3a, 0x14438129,
+0x927758ce, 0xe27fa16a, 0x8c30bd81, 0x7b7fff47, 0x41e58175, 0x35812462, 0xe7ff4358, 0xb4c04079,
+0xa87c108b, 0x81aae151, 0x3d797f8e, 0x33007f3c, 0x27c2715a, 0x188c7fba, 0xb481e081, 0xe026d96e,
+0x402d8185, 0x7066ffcd, 0xc5914e7f, 0x977f655f, 0x7f68b5d9, 0xcad3235d, 0xc77f8e81, 0x1cb4817f,
+0x7f473044, 0x15168159, 0x7f5c81d2, 0x7f99bd6f, 0xb7ab0006, 0xf2487f41, 0xd2de0f82, 0x6a81627f,
+0x2e8e87fa, 0x25187fb3, 0x6d31b393, 0xdd3d4b81, 0xa942a11d, 0xd21281d0, 0xe6b0e17f, 0x8a5646ad,
+0x907f8124, 0x7f81d2e2, 0xd8c8e17f, 0xeb8b7f81, 0x3ad8bb1a, 0x7f7fbf81, 0xcb30ddf4, 0xa09134d8,
+0x8187d2bc, 0x4949168a, 0x53998181, 0xd5e21412, 0x81811cb0, 0x11349a98, 0xdab2afe4, 0xd97f7f7f,
+0x7f7f8181, 0x327e7fd4, 0x97818114, 0x827b6517, 0x5f0aabbd, 0x7f905b81, 0xafdde37f, 0xcd40cf7e,
+0x7f56817f, 0x95810db2, 0xaf7fd131, 0x8181811a, 0x9e7f8f73, 0xe250d481, 0x7f2abb90, 0x5f7d981f,
+0xb3257f91, 0xec657f2f, 0xfa815e3a, 0x6e223481, 0x6c00eaa8, 0x7fb19394, 0x8799c181, 0x810e7fde,
+0x7d478181, 0x7fdc76bd, 0x035f8102, 0x627f447f, 0x7ff7ff7f, 0x81265db0, 0x6e81ac2c, 0x8802d277,
+0x81c3f781, 0xec81d259, 0x817b7d81, 0x7a5b7f7f, 0x4953ab64, 0x896a52a0, 0xb28111f8, 0xd25d8f0e,
+0x7f818174, 0x813f7f3b, 0x7fff7f72, 0x0fa87f88, 0xbcfad248, 0x507dd360, 0x7fae817f, 0x81f27f81,
+0x72fa4d1b, 0x5a21d2a1, 0x6381817f, 0x5fb55ab3, 0x8ec3816f, 0x257f4ab5, 0x4c74ef81, 0x19a3f27f,
+0x752746c6, 0xe17f8181, 0x7f7c8199, 0xdb9981a1, 0xcb984bd7, 0x815ea881, 0xdc50e0d9, 0xb9366f24,
+0x7f455dec, 0x817cb181, 0x424856f3, 0x67ab02a5, 0x0081657f, 0x105e8191, 0xeab817a7, 0x3a7f6d5a,
+0x425a1503, 0xeaac317f, 0x7fbe2cd0, 0xd2819a6d, 0x34887f6b, 0xef7f817f, 0xc3577f8f, 0xb124a664,
+0x9981167f, 0xb4946031, 0xb8817f7f, 0x81c570ed, 0xc9c88181, 0x3a4cdf81, 0xd9514781, 0x8948c0fe,
+0x2d5a8111, 0x68817f7f, 0x6be87f81, 0xa62c0381, 0x857f7fba, 0xa8c4ab7f, 0x279cc57f, 0x98816e0b,
+0x817ff70e, 0x21536d81, 0x875ca181, 0x008164f2, 0x96955a53, 0x57a53917, 0x6517faad, 0xdecd7f49,
+0x81819c32, 0x7f7fc25d, 0xfd81b181, 0x9f818166, 0x9c7f107f, 0x7f15b67f, 0x81636692, 0x18f276b5,
+0xbb9d08e2, 0x6c25797f, 0x417f43fc, 0xd0a37eca, 0xd4702b8f, 0x5c72ba00, 0x7f9dcdbe, 0xd4ad8122,
+0x39f1a381, 0x9b419181, 0xac816ace, 0xfb7c81e6, 0xdd7f7fb9, 0x2a27bb61, 0x3781499f, 0x7f6a7f93,
+0x4bbf81a5, 0x4a07e527, 0xab4f8143, 0xc2703e81, 0xb1813d81, 0x81747ba3, 0x11cb7f81, 0xd7a385fd,
+0xc9d0c981, 0x647fe554, 0x811d3681, 0x18817fdc, 0x81811bef, 0xd381845e, 0x466539da, 0x1081617f,
+0xb5b99261, 0x56cd7f8d, 0xaaa79076, 0x7f814a81, 0x7f7fe313, 0x7f7f8170, 0x5df9817f, 0x102fe72a,
+0x0c7f79ae, 0x4368d9e1, 0x6b0af013, 0xc13ed920, 0x98ed6a7f, 0xc494d37f, 0x81816a35, 0xc27f7f4f,
+0x451a7f3a, 0x4c812e15, 0x032f49b1, 0xbd7f02a1, 0x507f0d67, 0x9c5f007f, 0x8712c21b, 0x6ba7385a,
+0x7fb62c58, 0x7f818bcf, 0x7f7fc57f, 0x4141698d, 0x1e817f5c, 0x813fbe97, 0x6f817fa8, 0x51637759,
+0x7f4ed17f, 0x81ac2c28, 0xf1c75bfd, 0x1463c260, 0xcb7f7fcf, 0x7483675a, 0x40eb7f7f, 0xad7f81a2,
+0x7f817f50, 0x66816683, 0x407f8c81, 0xaf8190b3, 0x81d347f2, 0x5a215a81, 0xca7f8132, 0xd0528ef2,
+0x8129c3a0, 0xa4a7c52b, 0x0b816383, 0xbc7faf5d, 0x38d34e66, 0xff65a68b, 0x817999d7, 0x5a620463,
+0x885a817f, 0xad947f81, 0x7f1c902c, 0xaa0e9003, 0xd7ccb971, 0x64a68198, 0xb2337f11, 0x81a4d5dd,
+0x817f81fd, 0x7e814f81, 0x817f3da2, 0x8381fd08, 0x81a35a81, 0x7f0099e3, 0xfa1f5850, 0x6773efd6,
+0x6e7e5268, 0x138e7fc5, 0x81449526, 0x815781c2, 0xca2faff4, 0xf37f7f64, 0xaa080369, 0x7fb07f5c,
+0x81397fcd, 0x972dbbbe, 0x813f8e81, 0x812ed669, 0xbf76e310, 0x0be7f981, 0x81929781, 0x577f8644,
+0x0cc7e94b, 0x7e1d2995, 0x7ace8119, 0x81814867, 0x617f505c, 0xb9ad7f3e, 0x3ad56e18, 0x81e5b75d,
+0xca874729, 0x7f81ad9c, 0x5881813e, 0xbb240a46, 0xcc908863, 0x6fc2815b, 0xfa4bca7f, 0x8f817319,
+0xfe819dae, 0x81814281, 0x867f21e9, 0xfdaa0500, 0xd08c9e41, 0x99ea3b94, 0x7fa9394c, 0x81337f7f,
+0xb57f23f9, 0xc59a8181, 0x815a7fa4, 0x16c9c781, 0x9f17b97f, 0xb2817f89, 0x7fbd95a5, 0xb27f7f8e,
+0xa5e0b5c9, 0xefabff4c, 0x7fb7ea7f, 0x9aec9841, 0xb0e1784b, 0x81b29d1d, 0x7fba1781, 0x81f7086b,
+0x8129f27f, 0x818181ea, 0xc1ce8113, 0xfbfbaacf, 0x9d4c14ed, 0x40c1ea26, 0x6051cd3f, 0x6cd681be,
+0x4c469beb, 0x17637f22, 0x81882850, 0xbc91d4be, 0x6e318122, 0x95628181, 0x6c7f7f33, 0x6c47537f,
+0xa8d27f7f, 0x3de9b857, 0xc73a2c81, 0x4e7f8101, 0x3b7f817f, 0x3a78815c, 0x1a67771c, 0x5a8286a4,
+0xf7b98166, 0xd3b37f81, 0x4eb17f2f, 0xc1098181, 0x969a7fc5, 0x0bfbfbb9, 0x316f8194, 0x7f6f8184,
+0x484ec57f, 0x364a007f, 0x1f81817f, 0xc5b9ac81, 0xbb81b97f, 0x1f82647b, 0x2c4b4600, 0x89813d0c,
+0x75ffc374, 0xad7f5e23, 0x0af481a5, 0x3d0e3eee, 0xa49481cb, 0x39815284, 0x8187f438, 0x1a7c7f7f,
+0x817fa8b5, 0x7fca781e, 0xb401d779, 0x424c7fda, 0x3c429944, 0x488d7f7f, 0x78966481, 0xaf687f5d,
+0x89052b37, 0xbf7f407f, 0xe07fce79, 0x9fdf45d3, 0x8181de83, 0xe67f7f5a, 0x7fe6a3fa, 0x38705b81,
+0x81518232, 0x7d5d9978, 0x270372c9, 0x818568a2, 0xca7f66c8, 0x43a06a3c, 0x831b4281, 0x853a7fb0,
+0x8178cf45, 0x7f7f7fbc, 0xbdb69d20, 0x525c5392, 0xc081d97b, 0x18217f16, 0xb6ec7659, 0x0861819b,
+0xc48b819e, 0x817f38f2, 0x7f7f787f, 0x7f365c81, 0x64a9f87f, 0xe4e67dac, 0xd1580073, 0x81817f54,
+0x597f2ced, 0x575cabd0, 0xce81d781, 0x819c81a4, 0x7f5aceb2, 0x7f57ac33, 0x81e4d87f, 0x1df5d24d,
+0x7f4f7f7f, 0x7feb81e8, 0x6a81816a, 0x7f668144, 0x3431b13e, 0x3cc6b82b, 0x815dc38c, 0xc65781b0,
+0xae897f81, 0x9751537a, 0x817f0e88, 0xb15e69ea, 0x6f7f7f90, 0x24e681a4, 0xd97fa74f, 0x1881fa61,
+0x2e743b95, 0xeb817f7f, 0x7fcd677f, 0x317f7fec, 0x9246f573, 0x2e7fae81, 0x7eb72b7d, 0x4d8144bd,
+0x3f7fcb81, 0x7f619f9d, 0x51e7b87f, 0x81688e5c, 0x0d3d55d4, 0xb9b0817f, 0xaec17fd2, 0x017f2ffb,
+0xa8af3550, 0x81187f3d, 0xa033427f, 0x38c83442, 0x7f7f8181, 0xe38a35cc, 0x1f00c081, 0x7f297f7f,
+0xd17f7f81, 0x6e81c637, 0xc4387945, 0x26839381, 0xd481e281, 0x0b72bf12, 0x057f9e7f, 0x5eef2c81,
+0x9216b507, 0xd7906948, 0x637f627f, 0x0a11bfaa, 0xd605bd9e, 0x81ea9c81, 0x72f03c3d, 0x4f819f7f,
+0xc563d7b7, 0xad5a3899, 0x7ff15105, 0x7f692e81, 0xbf79c6c9, 0x3c738181, 0x7f4a0597, 0xecb5d588,
+0x7f7f2b3c, 0x888144dc, 0xbd7f6e61, 0x6b6e81e5, 0x5d5b1caf, 0x4c743b73, 0x7f727f2f, 0x667f3551,
+0x8fc63881, 0x81565a6c, 0x61817f3d, 0x0aa5d083, 0x81215ea2, 0x60461f02, 0x0d7fc1ee, 0xe77f813b,
+0x40d9767f, 0x1c817fa8, 0x7f815e7f, 0xa5447f7f, 0x2ac45607, 0x81417f7f, 0x00aceb81, 0x8181cfe4,
+0x817f81aa, 0xaa3eda6e, 0x7fbd4adc, 0xf8bb5deb, 0xf0867fe7, 0x3f33a481, 0x819e1bb7, 0x81458b81,
+0x9573148c, 0x986d1ee0, 0x45deb557, 0xcf7f688f, 0x23d5b1a9, 0xc3fdfeb0, 0x3fad633c, 0xe4be21bb,
+0x81819acf, 0x567f1571, 0x5a2c130b, 0x7f14e77f, 0x37d38908, 0xe55da5d4, 0xf2e16033, 0x23db8181,
+0x7f8160bf, 0x177fa17f, 0xa00f4dc8, 0x47818153, 0xf7817b81, 0x529681a0, 0xeca34413, 0x7f49a081,
+0x2c9c81c3, 0x8181ae14, 0x8125425f, 0x39b1123a, 0xe4e781b8, 0x4f83e39f, 0xd298507f, 0x49e92f7f,
+0x26bac981, 0xf0a27f49, 0x81d281a8, 0x993dc681, 0x48c19a95, 0x98af7a6f, 0x3baa107f, 0x899d3c00,
+0x7f814467, 0xc6e821df, 0x05226d8c, 0x9a813aba, 0x8d818117, 0x81688142, 0xd9244ff9, 0xdb0da3d0,
+0xbef62430, 0x55868181, 0x8176d83f, 0x33813ef2, 0x941a6534, 0x81d0741b, 0x4e37927f, 0x6b2515e2,
+0x8181aa81, 0x9581605b, 0x678113a0, 0x6e7f2681, 0xc1819f81, 0x813ca072, 0x7f81b97f, 0x3d95817f,
+0x81233f81, 0x911e90e0, 0x76a6d5d9, 0xc6b5057f, 0x5262b67f, 0x81812681, 0xa68110fa, 0xc74a6049,
+0x478eef7f, 0x8ea225d1, 0x77fd31f8, 0x7f568422, 0x81207f81, 0x94628118, 0x81a47fc0, 0x7f637f7f,
+0xa8898caf, 0x8125b97c, 0x3de89f9a, 0x7f81bb71, 0x24183337, 0x88c0437f, 0xe97f6bb5, 0xa0dc007e,
+0x36dcd381, 0x887cd84a, 0x0a817381, 0x9b818176, 0x46327ffa, 0x487f926d, 0x07508107, 0x7f7ffe06,
+0xcefe7f7f, 0x028172d9, 0x7f7381da, 0x81f97f58, 0x81818d0d, 0x06597fcb, 0x817f7ff5, 0x8e999e7f,
+0x7fd22e8f, 0x81766ae5, 0x817f7f86, 0xca81bf7f, 0xfd144e10, 0x947ff681, 0xa9817f4f, 0x7f187748,
+0x81819081, 0x8170ca74, 0x7a5d9c79, 0xbe483f81, 0x6f7f9fa0, 0x7fb0505b, 0x7fc7f15f, 0x81793081,
+0xbc7bb830, 0xce7ff56d, 0x81e02681, 0xa5968113, 0xa47fd381, 0x81a68197, 0xf4ca2a7f, 0xd220acb6,
+0x7f837ae6, 0x5c812609, 0x847fd94f, 0x6adf9afc, 0xb17fc822, 0xfd1b82ec, 0x8dfbf181, 0xbe008215,
+0x1dfd1081, 0xd1768cc8, 0x76818144, 0x7a917f9b, 0x0c6aada1, 0x16d3654e, 0xea1a8d7a, 0x9508c955,
+0xbfe88c4c, 0x593fa4d6, 0x8c45818e, 0x7f7f557f, 0x7f1dcc7f, 0x984c8181, 0x6b817f7f, 0x6c8131d9,
+0x4c8185e0, 0x678457da, 0xa6bb81f1, 0x79c0ca67, 0x7fe2c433, 0x257b8381, 0x37323c7f, 0xd768283d,
+0xdde15d81, 0x7996d7be, 0x7fd38110, 0x81706b66, 0x7feb685e, 0x817fba69, 0x8182ec99, 0x53c67fac,
+0x7f7fc1da, 0xf8afcee6, 0x09816181, 0x8a4f9e6c, 0x5b94c2c6, 0x812b3b97, 0xd0237f7b, 0x81817f64,
+0x81768181, 0x7f24b359, 0x1f326247, 0x7f7f5e38, 0x81267f42, 0xff8781be, 0x85817758, 0x7f172281,
+0x81599137, 0x22423760, 0x81c8e277, 0x7f46f381, 0xbb668184, 0x7f547f7f, 0x4aa27e87, 0x217f8c35,
+0x925eb643, 0x48b89ac8, 0x7f9d8181, 0xffe3a47f, 0x3e810ac3, 0x7f2c7fa0, 0x847f4681, 0x8106818d,
+0x81787f10, 0x3e2a5fa5, 0x81a38181, 0xfa7f712b, 0x74dd166f, 0x0d2819a4, 0x557f426d, 0x7f818158,
+0x1b817f93, 0x927f0e81, 0x7f1b9a56, 0x78c78898, 0xbb07493f, 0xd4b37f1b, 0xae8aafef, 0x7fc2c3a0,
+0xb1bb3d19, 0x1189816f, 0xc2813c7f, 0xc27ff3be, 0x7f3bc183, 0xd1817c7f, 0xc6817fa9, 0x0f9ad87f,
+0x7f10c96f, 0x517f7fca, 0xb9958181, 0x9870315a, 0x1c091752, 0x7f0a4746, 0x509ec654, 0x168190cf,
+0x8e3d0000, 0xc0817f69, 0x7f8a6f85, 0x7fe8b634, 0x2631815a, 0x67942d85, 0x5a7f8b38, 0xa2a07e1d,
+0xfa816e81, 0x3c81bc7f, 0x813b7fed, 0x81aae601, 0x7f81ba4e, 0x81817fa7, 0x32453b81, 0x8e8aa579,
+0x7f81d1e2, 0x78a4847f, 0x81819b57, 0x13137779, 0x81c5557f, 0x7fd18195, 0x049928a6, 0xedd7897f,
+0xa0816adf, 0xb0815ab9, 0xb2c73281, 0x7f01a4b5, 0x5ebacf94, 0x7fbb8181, 0xa97f7fd1, 0xec9d5661,
+0x3da381ec, 0x4445a98f, 0x291ca97f, 0x9d948d9b, 0xf9f0d592, 0x8b1fcd81, 0x81d54fea, 0xdb81600e,
+0x69a781c0, 0x817f78f0, 0x818181a4, 0x36810aa0, 0x646f9f7f, 0x70c25f34, 0x9471817f, 0x3e5081db,
+0x5cc37f74, 0x7f0a814d, 0x990ba07f, 0xe55babcf, 0x59813a5b, 0x26b96e7f, 0x199c8125, 0x812e0db3,
+0xe581b498, 0x8174a97f, 0x440f7ff0, 0x812d487d, 0x227f9881, 0x7fcb77b8, 0x157fc3e9, 0xdbfcff7f,
+0x81085d64, 0x44a9bdaf, 0x42998481, 0xb885b098, 0x94817f94, 0x81d3367f, 0x48394f81, 0x817a697f,
+0x64671052, 0xbd81153c, 0xd8637f02, 0x558cd081, 0x8485d766, 0x9ea7c1ae, 0x81b2afc6, 0x81657f40,
+0x62d4f31b, 0xbd7f7f8b, 0x7b909c60, 0x2f81734e, 0x5060ab22, 0x10b62281, 0x1d83812a, 0xc7aa8866,
+0x31444bc6, 0x815d6281, 0x822f8f58, 0xb75aa477, 0xc21f9a27, 0xd3545a36, 0xad30af19, 0x6b813f7f,
+0x0000188d, 0x7fa14165, 0x177a549f, 0x8f9e037f, 0x1cd8f7f1, 0x1e7fb9d0, 0x557363c3, 0x7f9c1a26,
+0x769fda1c, 0x7f7f8192, 0x157f7e7f, 0xcb61817f, 0x4a9d3d64, 0x8148aa58, 0x637fd2d0, 0x308481d2,
+0x95a8324b, 0x7f7f3681, 0xbe407f4b, 0x2b769128, 0x8156657b, 0x7f7f7f7f, 0x45c97f0c, 0x81577f8d,
+0xe90f8181, 0x817f689e, 0x2781f97f, 0x7fd1a966, 0xa07f6a14, 0xddbb7fab, 0xa53f57fe, 0x56c77f81,
+0x35e0837f, 0xde818164, 0x7f5bb62f, 0x7ffe814c, 0x4a8fe8cb, 0x7f7f5b81, 0x81137fbf, 0x8157a240,
+0x81048171, 0xa9d17f18, 0x8458817f, 0x81424a81, 0x9d817fb2, 0x31ef5181, 0xd081507f, 0x567b6e81,
+0x91a3276b, 0x7f257f81, 0x98d9a897, 0x8eb301e8, 0x7f8a11a8, 0xac7fb482, 0x1420dd00, 0xa629e6aa,
+0x98628159, 0x4a815981, 0xf081eda7, 0xaf5ac540, 0xde387936, 0xf6f2cc49, 0x7fa88152, 0x4587a0b6,
+0x0549f981, 0x7f6a817f, 0x7fde8f79, 0x7fd77f81, 0xbd58b276, 0x477f5db5, 0xa3d0817f, 0xb3811743,
+0x378d5f7f, 0x889c8175, 0x00d9bffb, 0xa386f71b, 0x9b9b5a7f, 0x05301691, 0x077afd81, 0xc9813d20,
+0x655b8118, 0xb1810fc4, 0x2ae18160, 0x7f818141, 0x81c2db39, 0x7f3cd124, 0x52c77f7f, 0xcfdb5141,
+0x8113b964, 0x0c0bd10c, 0x8137637f, 0x56bf8149, 0x5fceb17f, 0x01857f81, 0xea81917a, 0xd67a3c7f,
+0x5fd93fa4, 0x93720000, 0x31e08193, 0x957faa7f, 0x30e1b019, 0x557f19fc, 0x327f5c1c, 0x81e98181,
+0x567f6f7f, 0x817f60bc, 0xe4f481a2, 0xb1f2aa31, 0xba5b7f36, 0x4d2bd790, 0x914d4e38, 0x817f7722,
+0x10fb7fcd, 0x2f7f3026, 0x8c7f3c92, 0xbe81392b, 0x1cae7f78, 0xb6cb6581, 0x2f52db43, 0x49cb7f71,
+0x7fe6dfe9, 0x232e7e66, 0x1497965f, 0x67316ca2, 0xaf71c384, 0x727fbd7f, 0x5e7f6ab9, 0x7b5181bd,
+0x38e38170, 0x48cae97f, 0x4a81669c, 0x3d2d7f7f, 0x69508352, 0xac988181, 0xe093a587, 0xbd907753,
+0x817fb87f, 0x894ac8c0, 0x9f7f9ccc, 0x6336a2de, 0x7f7fd741, 0x75b723c5, 0x396e7fc6, 0xc5c0819d,
+0x813c7172, 0x816a7fa6, 0x95bdf475, 0x69b21f5f, 0x817f7f06, 0x4c90685e, 0x7fea7f7f, 0x7f958f0b,
+0xf6a7937f, 0x5b6caa7f, 0x5fbf7f30, 0x4c6cb506, 0x7f097f95, 0x8181d881, 0x817f34b8, 0x937f7089,
+0x830181a8, 0xa6b2817f, 0x4912930e, 0x7f8fd67b, 0xf69bd281, 0x7a5fd981, 0xc4aa7f7f, 0x817f819b,
+0x9c05c2f5, 0x8f579881, 0x5aa4818e, 0xc14dc0bd, 0x7fce0981, 0x147fcd41, 0x817fe75b, 0xf8e1a54f,
+0x817f8981, 0x1334585f, 0x810281db, 0x146db1bd, 0x25347f7f, 0x9cbf987f, 0xb6736d0c, 0x814ab481,
+0x0fd1653e, 0x7fd67170, 0xe564ce22, 0xd05df37f, 0x10871f96, 0x9dc9e03e, 0x53bc03ad, 0xc47fd1c5,
+0xaa4dd88d, 0x00004ad1, 0x8a35a85a, 0xcff89253, 0x64d0819b, 0x149ab17f, 0x819f7a33, 0x49fc81c7,
+0x1881d433, 0x196171c4, 0x784dbdae, 0x8193148e, 0x75b63674, 0xdf81e4ab, 0xad299a6d, 0x8168b3d3,
+0xeea6426e, 0x81c99981, 0xb17f647f, 0x814ec5d2, 0x2e3b16a8, 0x81597f81, 0xa97f8181, 0x2caec714,
+0x387906fd, 0x818181be, 0x7f7fbcb3, 0xd55a81e6, 0x8134ae81, 0x7fc3817f, 0x9853ee56, 0x5881999d,
+0x9ea98184, 0xfa8181a6, 0xceff5978, 0x688e505f, 0x7fbbb830, 0xc678d06a, 0x3c90e3ae, 0x4b6d7f23,
+0x24cd7f58, 0x7f92c181, 0xb1a97fc2, 0xba872981, 0x66ec49a3, 0x7f7f26b5, 0x7f8163b8, 0xae7f7f7f,
+0xde7f3781, 0x4147d381, 0xe191cb81, 0xd45b81c3, 0x474c9e91, 0x55b546db, 0x0e81b5a6, 0xb5b976aa,
+0x7f7f7f3d, 0x968a81d7, 0x7f1f9333, 0xb37f7f7f, 0x2f7f6418, 0x2532a07e, 0x8b81bf44, 0x89818144,
+0xa1572ffd, 0xfebf182a, 0xe54d7f5f, 0x107f8949, 0x00210081, 0xc53345a1, 0xa2818ff6, 0x81c181e2,
+0x9b81f1d5, 0xd1061965, 0xb7a47ff0, 0x81817fb0, 0x18bc6181, 0x7ccc5981, 0xbe2b9dae, 0x038f8173,
+0x7f3bec4d, 0x81ec81b0, 0x817b9a6a, 0x817cb47f, 0x7fa98fb5, 0xb0355e36, 0x8dad6109, 0x4b138116,
+0xa3e19d81, 0x449ab793, 0x984acd21, 0x168aeb94, 0x85baac5d, 0x7fac8173, 0x81ad81d9, 0xa34abb7f,
+0x81ca817f, 0x817f6074, 0x7fbc0000, 0xc79b108a, 0xc06990ca, 0x317f12cf, 0x9281e743, 0x90c681fd,
+0x17b57f3a, 0xbdd05681, 0xfafcef3d, 0x6f0a0d81, 0x4337197f, 0x7f4881af, 0xb592de71, 0x44c24881,
+0x536f9532, 0x21506996, 0x68489d79, 0x4aaf4312, 0x740c9447, 0x657f6673, 0x637f7f0f, 0x81205569,
+0x8fb3fe9c, 0x4881995c, 0x8163cfb0, 0x17a4817f, 0x7f59ad84, 0x6d0c30d2, 0xbdc6b981, 0x1bfa8155,
+0x7f22a8ca, 0x9c9a817f, 0x3bdba778, 0xf6817eb1, 0x07858141, 0xc037817e, 0x3f2c868c, 0x8181d07f,
+0x02b704dd, 0x467f6bc8, 0x4881ab7f, 0xa25c814e, 0xcb4d8e6e, 0x477c7f88, 0xd991aecb, 0x9c81b243,
+0x12d6b7e6, 0x03d745a0, 0xdf0bc9d8, 0x52637f85, 0xd557817f, 0x96342cc0, 0x81423981, 0x70657f81,
+0xde8181cb, 0x8a81de2b, 0xf55d3e2f, 0x2d717f81, 0xba81289e, 0x99c27f7f, 0x81c5817f, 0x90be817f,
+0x918ea3dc, 0x8de39c22, 0xce577f93, 0x3f7f8186, 0x9e817f7f, 0x816c8aeb, 0x3d818e2e, 0x8181be9f,
+0x0fb9429c, 0x3c7f5155, 0x81275b24, 0xa47fda70, 0x84cc88c5, 0x70797f81, 0x812eaebb, 0x16a1314f,
+0x7f7f817f, 0x38b61a4c, 0x7fb7388b, 0x7fb6e681, 0x5581987f, 0x9281c37f, 0xc45b7f7f, 0x8b35b97f,
+0x7f7f7f81, 0xa23c0e3b, 0x7f9b2083, 0x9cc39283, 0x8843699c, 0xc07f81dc, 0xa1f98b7f, 0x81d245b5,
+0x8181597f, 0x1aa93681, 0x000001df, 0x81574196, 0x7f3f3df1, 0x6fc8c7c4, 0x5e4d7f8c, 0x81b4dc44,
+0xd56f7f8b, 0x8116a381, 0xb03f5f81, 0xf5020639, 0x7f02b25c, 0x55818143, 0xab658147, 0x357f1daa,
+0x296ac18e, 0x8186e57f, 0x7464272d, 0x417863e1, 0xeae67831, 0x1a605547, 0x45ffb1d5, 0x7f066c81,
+0x81bfb062, 0x4cb8f381, 0x81817f7f, 0x145a4bc0, 0x2e813d7f, 0xc6524d71, 0x81818181, 0xc9d681fb,
+0x2a5db57f, 0x12c97fa7, 0x317f7f48, 0xf9b88131, 0x354c1389, 0xd77f8155, 0x811b4dbe, 0x9d3d457f,
+0xf9dc2f28, 0xb01c8181, 0x5a81716d, 0x7f7f3d81, 0xd87f867f, 0x817f0581, 0x564f8181, 0x7f678181,
+0x5cdd7f91, 0x07ad3f96, 0xb4dd9e34, 0x7f7fd50d, 0xa67f81b6, 0x01353420, 0x6481798a, 0xa5a68181,
+0x9c7f816e, 0xafc73c84, 0x427b8d32, 0x1bbb817f, 0xd45c7fa5, 0xb0c2ec48, 0xb459aa7f, 0x70818181,
+0x5ec983e7, 0x81294066, 0x81447f6f, 0x9b819f5e, 0x7fb1a47f, 0x81b8a081, 0x5f91c62b, 0x7f63de81,
+0xdc813ff2, 0x817f81ce, 0x3d677f0b, 0x4da9dae5, 0xcc8190d9, 0x1d7fbbfa, 0x5ffdd2b7, 0x69624b8f,
+0x50963e7f, 0x7f7fa281, 0xcc4b8149, 0x8102da7f, 0x3f7f9df5, 0x435732c5, 0x7f07d881, 0xb20fe07f,
+0x4896ac46, 0x44b3ed39, 0x7f7f8127, 0x9e7f81e4, 0x8181b15f, 0x7c818132, 0x7f41980b, 0x299ea18d,
+0x7f196381, 0x7fc95f36, 0xbecb7f35, 0xdaa80000, 0x292a7fe2, 0x3292947f, 0x7f98e9c5, 0xb77c984e,
+0x74847f81, 0x917f487f, 0x537766db, 0x30b71c7f, 0x81237f81, 0x9d7f9542, 0xfc75737f, 0x72499c3a,
+0x6885625b, 0x7f061c6d, 0x818e7f81, 0x5b814381, 0x81f17f4d, 0x4d81b6cd, 0xd2f7d778, 0xe5e9d5db,
+0xf7f081c2, 0xb80b0481, 0x975658f2, 0xe8b1197f, 0x81634b1a, 0x7f6bd994, 0xdbd67f7f, 0x757f3406,
+0xc4d07f7f, 0x63e7507a, 0x102b7709, 0xe08cf836, 0x1db26230, 0x1a814510, 0x40679bdb, 0xf336a87f,
+0x7fc3bf7f, 0x818e69c8, 0xf67aa2a3, 0x75425b7f, 0xa4b654c1, 0x7f7f5ac1, 0x5f10488d, 0x57dc7f30,
+0x7d817f81, 0xfc81237c, 0x388a81d6, 0xbce67f42, 0x7f7a7f56, 0xfbb7ff87, 0x467f4681, 0x22dc9b7f,
+0xba939029, 0x4a44c1a5, 0xa4be71d3, 0x7ffb3589, 0xfefae9a6, 0xa1963e4f, 0x66b3d6b3, 0x81506f83,
+0xee7f32ee, 0x7ffe7f7f, 0xbf505c53, 0xd769ca7f, 0x69c267d2, 0x7f9f8346, 0x3f7f7f7f, 0x48813f51,
+0x7fed8115, 0x9e81aef0, 0x7f7f22e3, 0x819fa190, 0x55457f81, 0x7f813b81, 0x251b4a0d, 0x6476818e,
+0xc4d8da21, 0x52fd2d4b, 0x81943c7f, 0x273ce481, 0x7d53817f, 0xcd9d9058, 0x754151d2, 0xcb9f365b,
+0xac73ecd4, 0x7ffd9a4b, 0x577f2d92, 0x41c60481, 0x81297fa9, 0x9f7f850f, 0x8c513329, 0xe854c39f,
+0x34bb4a20, 0xc37f5178, 0x0787cc22, 0x6c86717f, 0x75815a48, 0x2023777f, 0xd37fdd7f, 0x6a819cf7,
+0xdc44f5e3, 0x258157bd, 0xe8e7813d, 0xb9118195, 0x9a5a4581, 0x2d8c517f, 0x0c728161, 0xaec769ac,
+0x1f554191, 0xfc8be381, 0xca703b7f, 0xab813d5a, 0x3f7faced, 0x707a2181, 0x7f1b8c7f, 0x7fad7f99,
+0xb307377f, 0x6c9d5b81, 0x7f3bfac6, 0x8182567f, 0x5a246cdd, 0x55408105, 0x277f7f84, 0x7fa09c52,
+0x817fa355, 0x404fd360, 0xecbc4281, 0xc6897f20, 0x7881ae81, 0x407f81e1, 0xfb35587f, 0x9b67fb81,
+0x7f8103ad, 0x36708155, 0xab81f381, 0xa3fe6417, 0xa97f7f98, 0x3cf7cd7e, 0xae1b4dc6, 0x8ac2f749,
+0x7fb35e89, 0x07e0743b, 0x7f818135, 0x81a15481, 0x93819bbc, 0x81f68114, 0x194ccd81, 0x81527f7f,
+0x583ba074, 0x91654d78, 0x4e81398d, 0x0c54567f, 0xe453d054, 0xd37f8175, 0xd57f81ea, 0x345e5b7f,
+0x3589262c, 0xa8b886de, 0x811b8197, 0xbbc890ee, 0x8db0b9dc, 0x9fcb817f, 0x39817f7f, 0x55391fe5,
+0x7f7f3f92, 0x5a7f55d9, 0x747f3c71, 0x43e31da0, 0x67dccd81, 0x81ddffaa, 0xc32a5881, 0xb9816d7f,
+0x424d7f7f, 0xb97fa435, 0x7fdb7f81, 0x48fb8182, 0x8181407f, 0xba7fa88d, 0xa16d467f, 0x81cb8a81,
+0x8181a66c, 0x8c747c1b, 0xb4810470, 0x8133dc82, 0xbc77727f, 0xee981437, 0x7f2e8981, 0x26be1939,
+0x12da817f, 0x81a1da61, 0x1d2af46f, 0x7f3781f5, 0x29500000, 0x657fc67d, 0x81817f7f, 0x49e406cb,
+0x0b787faa, 0x7bc2643b, 0xe4e4f0ec, 0xd28175e5, 0x7f425abc, 0x900c1828, 0x7fa85f7f, 0xe8365361,
+0xc5d87fa2, 0x81baffab, 0x81818612, 0xbcb5af1b, 0x7a7e5d7f, 0x81b07f7f, 0xa27aba93, 0x817fd881,
+0x818481b0, 0x7f8d1c22, 0xb48c869b, 0x977f9429, 0x9a8c7fc5, 0xb8d9b270, 0x6e340e88, 0x670f7f39,
+0x7f4efebd, 0x41b5b57f, 0x7f277f0c, 0x5f177f23, 0x94818592, 0x68362b87, 0x6681ea7b, 0x7f187fd2,
+0xa38131ae, 0xc97f698e, 0x25bd8155, 0xe37d88d6, 0x2d018f4d, 0x391e7f7f, 0x7f7f845a, 0xe8f8ee81,
+0x4beb9d63, 0x7fd47ff8, 0x5e5781ec, 0x237ffe3a, 0x8e818168, 0xa1e781e7, 0x85de7f81, 0xbaaad281,
+0xa7486481, 0x555e737f, 0xa2b28f7f, 0x70635a47, 0x7f837fd8, 0x64ea8641, 0xc20c7f81, 0x0b9e738e,
+0x698e8145, 0x783a5a00, 0x7f376e81, 0x7f8cbd20, 0x7f548181, 0x81149934, 0x3dad456a, 0xb4561fed,
+0x815d8127, 0xaea4bb24, 0x2187755a, 0x847ff0b7, 0x7fdb9039, 0x81887695, 0x8781e111, 0xe0de037f,
+0xc879f7ca, 0x7fc18381, 0x7f7ff7bf, 0x958b7f81, 0xa65fe7ad, 0x3481817f, 0x9f897b7f, 0xa2bb7f7f,
+0x31018170, 0x70e08c81, 0x4c1da62b, 0x16f27ff7, 0xdf0781ed, 0xbf4081c0, 0x3a233c53, 0xf8aed938,
+0xef24617b, 0x812681ab, 0xa66e4db4, 0xef9b65b3, 0x00007f44, 0x7f7f997f, 0x7f341fc7, 0x0f9b2be4,
+0x7ff67f81, 0x81817e2a, 0x4b4d7f81, 0xc0706505, 0x81fc60e1, 0x30d87f9c, 0x7fff9c0d, 0xa789757f,
+0x3881d769, 0x6367bf81, 0x9bae7f8d, 0x8e81bbb6, 0x61e88127, 0xc96c7fbf, 0xdf813181, 0x7f7f7de7,
+0x3e817f81, 0xb97f817f, 0x8b927f81, 0x5e74742d, 0x7c49817f, 0xbc1172b1, 0x81818181, 0x6dd2d4bb,
+0x98f3e058, 0x7f81efde, 0xaeee76df, 0xd57fca01, 0xf5817f81, 0x26747f81, 0xdc3f8181, 0xc335c749,
+0x7f2f7f7f, 0x7f02e67f, 0xfb706975, 0x8f4efde7, 0x819b414c, 0xb14cde70, 0x22e6812e, 0x3843892d,
+0x6f81ce60, 0x50c12725, 0xb4e279d5, 0x7fb1ac7f, 0xbc7f8183, 0xc7767881, 0xb6e71854, 0xb37f7f77,
+0x3d7f7f7f, 0x817f6824, 0x4981ae81, 0x7f811a7f, 0x58c37f74, 0xbef5a27f, 0x92a62541, 0x8643aa3c,
+0x8f838181, 0x397fe4f4, 0x8a814677, 0x93e3affa, 0xa6fa21e9, 0x7a3e7f7f, 0x332a7872, 0xf28c8176,
+0x227f573d, 0xbbbb6348, 0x7fefb2de, 0x43817f69, 0xc4c37b31, 0x747fa118, 0xacb3819c, 0x7f689f89,
+0x74e0604b, 0x81b57f88, 0xe925a0cf, 0x81be2181, 0x126d34f1, 0x7648d74e, 0xd760b29b, 0x04d0fda1,
+0x3b858181, 0x1be20981, 0x8127ac7f, 0x8a6b8181, 0x7f616ca2, 0x37e6e881, 0x7f9b82c0, 0x7f6e7f93,
+0x8dc72420, 0x752f3d39, 0x5e7fd2e5, 0x7f25c372, 0xe97f2677, 0x307f0000, 0x81383b86, 0x713de0fd,
+0xe47c817f, 0xf0214e8f, 0x8108349e, 0xe0c92881, 0x7fafb0e2, 0xe939b48c, 0x4855d8ae, 0xb581e469,
+0x967feb6a, 0xba543d20, 0xc47f0c62, 0x2a28e6b2, 0xd27fb09a, 0xbadf7f7a, 0xbf98d54c, 0x5f54cfa3,
+0x4881248d, 0xc97f7f53, 0x17816966, 0x3450877f, 0x4ff681c8, 0xfdb8786d, 0x0209730d, 0x7fbbba84,
+0xc5994cff, 0x4d31cc44, 0x7fb99400, 0x239d757f, 0xa2bd517f, 0xd5558194, 0x93818191, 0x819b8190,
+0x447f9289, 0x777f3e81, 0xc2c04a7b, 0x27c38eaa, 0x437a383d, 0x7f812432, 0xbd77707f, 0x7f81ea6d,
+0x40256698, 0x81a95b58, 0x2fb47f81, 0x74b64d86, 0x70f07f23, 0xd7d6bbd5, 0x817f18a6, 0xe862327f,
+0x3ff56cff, 0x7f7f8197, 0xcb75c381, 0x58954f57, 0x43818176, 0xa903811d, 0x7f6abbfa, 0x8cd7a77a,
+0x55814473, 0x7f819e1a, 0x557f9e89, 0xa9c955e0, 0x648191b0, 0x81a97f51, 0x1dbc1181, 0x685a6b36,
+0x7f2e5ef2, 0x59819afb, 0x3f30fd68, 0xe986702b, 0x810a2581, 0xfedf7781, 0x947ffb3a, 0xa9777f29,
+0x9c547f3d, 0xe36d7f07, 0x81909281, 0x2b87817f, 0x07aa817f, 0xd9137f30, 0xb791d3ff, 0xb84869c5,
+0x4db4e1ce, 0x81beed66, 0x1637adce, 0x10a1897d, 0xfd817fbb, 0x5771c343, 0x3b16dc58, 0x7fbf813f,
+0x7f9ba269, 0x353a7e21, 0x14f07fa6, 0x7f81815b, 0x484bb301, 0x0000c27c, 0x59141b93, 0x7f637f3e,
+0x3012937f, 0xf2a2b350, 0x1d7f7f7f, 0x81b6d4ed, 0x4fc3ba54, 0x3f7f107f, 0x02af3855, 0x598c814a,
+0x3eb09fd7, 0x636832b6, 0x7f9e817f, 0x7f939c7f, 0x7fa99581, 0x7f817fb1, 0x387f3475, 0x9893f771,
+0x52813581, 0xc5c75881, 0x7f787887, 0xb97981d0, 0x27436262, 0xfae6f21d, 0x81cacf5d, 0x41a5de81,
+0x81817d81, 0x3b2f7f9e, 0x5dc0ade8, 0x3d0e8154, 0x81bd3a0a, 0x6e818153, 0x7f818123, 0x817fc575,
+0x811b669b, 0x7f037929, 0x26acac81, 0x7fb3efb6, 0x82817fc3, 0x0c81f981, 0x607a677f, 0xc8258116,
+0x0ae77a50, 0x816fba35, 0x7f256549, 0x04c57f89, 0x4381075f, 0x81cd3b56, 0x8ccdad7f, 0x7fa45cd5,
+0x817fb67f, 0xb7698dbe, 0x5562298b, 0x688c257f, 0x9d7fde81, 0xe57f4e81, 0x7f81c9ea, 0x281a41f9,
+0x7ffdfc6c, 0xaa32217f, 0x81a08166, 0x8181b1ae, 0xc447880e, 0x2b81367f, 0x2944a47f, 0xc6de9b49,
+0x81816841, 0x54fa7fa8, 0x587beb7f, 0xe3475a81, 0x81dc2cb1, 0xa95dc06d, 0x8bd7477f, 0xb05d7f81,
+0xb4c19d7f, 0x43817f53, 0xde7f5c7f, 0xe3d2817f, 0x8948aadf, 0xc17f7ffb, 0xd08188c1, 0x8181204e,
+0xb3b6d781, 0x7381b381, 0x787f7681, 0xee640849, 0x657f8181, 0x811b329b, 0x5c728eed, 0x0c7f59c9,
+0x4cc3b12c, 0x814f7e3d, 0x5f7f7f46, 0xf9817fd9, 0xb1b5ba76, 0x1f42609e, 0x3db30000, 0x400d7f46,
+0x7f7f7f81, 0x45d36281, 0x81df9581, 0x7a7f7f53, 0x8181330a, 0x7ff5c3ab, 0x9e81b4bd, 0x7f70c27f,
+0xac1666b3, 0xcf7f52e2, 0x817fea30, 0x8c4b3f7f, 0xa085bde5, 0xabae307f, 0x817f7fde, 0x17bc61b4,
+0x914ccc4b, 0xe1e56bae, 0xac294f88, 0x75e562cd, 0xbfbd35cd, 0xed507f81, 0x81afcf81, 0x7fdc819b,
+0x5a0385e8, 0x4f2aabf2, 0x569c7f3f, 0x7fbee1bf, 0xb0407fc4, 0x6b548214, 0xbcd6877f, 0x3d6e7716,
+0x9a8134a3, 0x0a7f7f81, 0x29d73eca, 0xadbe7f65, 0x7fc1bb81, 0x7f63dc7f, 0x7f815430, 0x810e2366,
+0x7f36057f, 0xda39d7d0, 0xe9855ddb, 0x7fffa2f9, 0x3b9a8181, 0x7f06b781, 0x844db0a2, 0x7b1d7fa3,
+0x99a795ad, 0x7b819a6a, 0x3781819a, 0x867fc788, 0xa181817f, 0xfcc3637f, 0x747f5a5a, 0xf27f690f,
+0x2f8a9c2f, 0x617f7fb3, 0x81b4b1c2, 0xa2818b96, 0x7f7f7fa6, 0x20707f81, 0x7fc9817f, 0x55577fc3,
+0x777b40b9, 0xdffa3781, 0x38ba0e4e, 0x4f667d32, 0x9cf081ea, 0x8187d122, 0x79af9ebc, 0x647f99c2,
+0xd1a47f79, 0xaba67f7f, 0x6b270e96, 0x90c07265, 0x817f4b81, 0x71f31f65, 0x2d818692, 0x65570681,
+0x81f59b98, 0xe6b181ec, 0xc5b1a58f, 0x7fb2c981, 0x7fdb5914, 0xe37f81bd, 0x7fefd823, 0x9a7f9ccb,
+0x631762c2, 0x7f4e81b8, 0x813d88c1, 0x9768c97f, 0xbb867f81, 0x2cd79456, 0x00004aa7, 0x8ec66e57,
+0x7f7af878, 0x747f3cb4, 0x8c774fa4, 0x7f8df013, 0x8c5c7264, 0x3aade68d, 0x81819c30, 0xb0d38147,
+0xbd816181, 0x4f415cbc, 0x7f21f710, 0xf7ba5565, 0x81df367f, 0x637f7f9a, 0x7f182e7f, 0x6f81996f,
+0xca547fe5, 0x637f8db9, 0xccb4fe59, 0x55ca7f81, 0x7f7f7fae, 0xceffc677, 0x2955d0f8, 0x91a07f7f,
+0x7f818181, 0xebc2f87f, 0x7f213646, 0x94a2a981, 0xd1819bdc, 0x7f866084, 0x2381ff8b, 0x75b58114,
+0x447f162b, 0x5275e0a3, 0x37578cc2, 0x0dc1ec31, 0xb73681a8, 0xb081978a, 0x74429a2c, 0x698859dc,
+0x937fb91d, 0x7fcdc06e, 0x81b4ffff, 0x7e2b168d, 0x4b649aa9, 0xe648be08, 0x44e37b7f, 0xc0fc27e9,
+0x1b16521e, 0x81577fc5, 0x7f8152a8, 0x2981ee7f, 0xf08dd19f, 0x7d93ed81, 0x814435c5, 0xe6c67f29,
+0x7ffc8111, 0x87f65881, 0x3f62563a, 0xa09a81f9, 0x490f5781, 0xc70d6284, 0xfb818181, 0x56817f38,
+0x87420960, 0x0d2dedb3, 0x8ef18143, 0x4c5b4a62, 0x8f947f81, 0x667f8121, 0xcc817f81, 0xb567a44c,
+0x7996b182, 0x736e9881, 0x81627f7f, 0x7f8e7f81, 0x725ee43d, 0x9f436a50, 0x7f055d88, 0x93498181,
+0x21d08f7f, 0x26f17f3c, 0x581d939b, 0x90595ba7, 0xf5200e81, 0x4b91b78f, 0xcb7fc693, 0xe87fd04b,
+0xaf81087f, 0x14ac4a01, 0x7f7d7f81, 0xe014dd7f, 0xc2816aed, 0x79760a93, 0x7f9b817f, 0x81480000,
+0x844d73a5, 0x7f8181bb, 0x819dae3f, 0xc87f8e82, 0x9d81a23e, 0x7fbd813a, 0x8181702e, 0x4fab7a67,
+0xd57f70b6, 0x817c53ac, 0x1355de7f, 0x4264437f, 0x81b0ff2f, 0x16d6e094, 0x7fc40f55, 0x7f9b7edf,
+0x7f5a7f81, 0x7f996e66, 0x8e932881, 0x7f817f81, 0x6d4ca679, 0x815f871e, 0x81b4817f, 0x7fa97f81,
+0x5e03827f, 0xbcd8b6a8, 0xc5683edc, 0xbb007fdc, 0xea266973, 0x498e467f, 0x86b1cc7f, 0x17814738,
+0x81b7ae62, 0x56fea8f3, 0x5eac534d, 0x54f67f81, 0x24add4ce, 0x811a7881, 0x81cfc383, 0x9f2f81ef,
+0x7f1f41fe, 0x819e3781, 0xcc73a3b0, 0xee148181, 0x7181d87c, 0x81c1c9e2, 0xfee4727f, 0x9b608139,
+0xa2ec4ace, 0x7f810c7f, 0x9a7f2288, 0x46b169e4, 0x9b40817f, 0x547f2f7f, 0x81ef4f81, 0x243fffe3,
+0x8181dd3f, 0x347f6596, 0x7f59c3fa, 0xa26cc7ac, 0xf7384881, 0xbdc0a118, 0x7f8173a8, 0xabf1b3e3,
+0x7e3e8eac, 0x30c07bce, 0xbca0b981, 0x75816414, 0x81377f81, 0x7f7feaa1, 0xd8287f86, 0xfbd98bd1,
+0x7f987fc1, 0x81b8347f, 0x8c7f37e2, 0x987f3c7f, 0xb5f681ab, 0x347f1adc, 0x1b815481, 0x91f17f60,
+0xbf85a67f, 0x6d7f2374, 0x587f3c1b, 0x74b0ae9c, 0x97a64fb4, 0x1437697f, 0xc77f3b81, 0xf4e0bbad,
+0xb6892b64, 0x5ed0e47f, 0xa55c8100, 0xbbe24e10, 0x50bb6551, 0x6db5349d, 0xaaae405f, 0x4d7f4f6d,
+0x989e95a5, 0xcae9bf2b, 0x811e7f4d, 0x90538181, 0x7f9f096e, 0x4126a5df, 0x1369537c, 0x81a73581,
+0x722f1409, 0x8b297c54, 0xf17f5081, 0xc22b4595, 0x7f6fde57, 0xdea96095, 0x7f98814f, 0x40f8fb81,
+0x697fd77f, 0x35e07f33, 0x27459a7f, 0xc0818181, 0x3e817fb2, 0xdd5eae81, 0x8a8efd53, 0x13e91281,
+0x2c486ba8, 0x7f6b447f, 0x7f818120, 0x1c496781, 0xf8e45993, 0x48817f81, 0x009db045, 0x7fd9c722,
+0xab817fe2, 0x73bd7951, 0x687fa97f, 0x7f7f7fb8, 0x4f447ffb, 0xfc31d9c2, 0xc1d5d865, 0x526abd82,
+0x7f6e7f47, 0x6b31817e, 0x8509817f, 0x5581fcbf, 0x7f9bd8ac, 0xcc22f37f, 0x547fa07f, 0xbd4fd2bb,
+0x6f49a523, 0x835e896c, 0x65458e81, 0xd0e37fd2, 0x81587fe0, 0xd95fb08b, 0xd938d43f, 0x11e67fc6,
+0x7fec3c2e, 0x7f8581d5, 0x017981b9, 0x812c8133, 0x307415cb, 0x2081bd7a, 0x994d5c83, 0x53812ab3,
+0x7f8190bc, 0xad811645, 0x73c1ca14, 0x94c87d32, 0xbd4a7063, 0x7f442f7f, 0x06812617, 0xc481acc0,
+0xc7bacc81, 0x81de5481, 0x7fa3167f, 0x4a3a385f, 0x2b817f37, 0xae912b7f, 0x32c4cfeb, 0xc3bf3bb1,
+0xa4a63e50, 0x846c7b7a, 0x5c81816a, 0x75813daf, 0xd0665307, 0x6031117f, 0x507f5429, 0x29bfc44e,
+0x81b69437, 0xa4c54d61, 0x81391b7f, 0x98347fec, 0xf7da5b06, 0x7e3d8b7f, 0x7f7f1abe, 0xa955d23a,
+0xb7810000, 0xa1608164, 0x5f813cfb, 0x16602281, 0x5fb6814d, 0x3c3fd67f, 0x5dae83eb, 0x58ac2c2c,
+0x097f5d25, 0x6081da52, 0x7fd4818c, 0xe181d13c, 0xc66d7f2c, 0xe94a00a3, 0x2cec12a0, 0xe84c6398,
+0x64398162, 0xd056816f, 0x8147e081, 0x9ceb75c0, 0x7fbec481, 0x16d15734, 0x8158cd7f, 0x369c8172,
+0x2a479b81, 0x7f4e9686, 0xb1494e0f, 0xe5816226, 0x057f7f55, 0x81dba929, 0x8f1890e4, 0x5e7f817f,
+0x7f7f8162, 0xfced63c7, 0x370aadc1, 0x5f09b34f, 0x7fc0be25, 0x36927fec, 0x814d0ab6, 0xfd077f60,
+0x8162f9ab, 0x8185597f, 0x2bac2f66, 0x28e6aa9f, 0x814dc1c6, 0x717f3841, 0xffd1078b, 0x4f5b8a12,
+0x7f429a7f, 0x7f734d7f, 0x43817faf, 0x7f4e7f52, 0x232e0524, 0x7f4158e4, 0x327f7f7f, 0x89b464d8,
+0x8130a3a7, 0x7fe6ac32, 0xd1818e81, 0x427f957f, 0x8150c60e, 0x3cb50481, 0x31955f7f, 0xec427f9f,
+0x99eb5f69, 0x8ac893da, 0xf97da17f, 0x7f847f73, 0x7f97ce7f, 0x7f7fe806, 0x8984629e, 0x34539cba,
+0x8a64a575, 0x25297f49, 0x1c509d07, 0xd5aa7f7e, 0x74817f79, 0x81819981, 0x95815a8b, 0x9518a19f,
+0x3d9183ce, 0x817f00a1, 0x30306781, 0xc67f7f7f, 0x81594a49, 0x3d620f81, 0x3481bd81, 0xc3af8e63,
+0xc249dc8b, 0xe5fa637f, 0x81185512, 0xa0b48307, 0x814c817f, 0xc6dac58b, 0x8b5c781a, 0x81982c81,
+0x0000b269, 0x8105f78d, 0x81ad60f7, 0x81ffb8cc, 0x917ffed4, 0x104fc0a1, 0xfa38b45b, 0xb5318137,
+0xbd781466, 0x0bd8068c, 0x72c57f91, 0x8181b48e, 0x7f81aedc, 0x43677f7f, 0x7f4f7f3a, 0x437f8178,
+0xe99d0b81, 0x868792bc, 0x17727f57, 0xada05e06, 0x694d707f, 0x9081e59b, 0x7f3a8181, 0xb2bae481,
+0x7f81dde5, 0x3e307f7f, 0xcaa07f3a, 0x2e1a8170, 0xed0f4881, 0x297f7f61, 0x81cc815e, 0x4fec813b,
+0x1a4f02b2, 0xc6e66a4e, 0xe9817f6f, 0xc2c36a02, 0x302e9f60, 0x4ea28137, 0xb9d57f32, 0x462a7f81,
+0x9085bb36, 0x7f7f817f, 0x3c714908, 0x70c9c17e, 0x5a7f204b, 0x8fbf6f70, 0x97880981, 0x0cbacfdb,
+0xb80f6d81, 0xb6bb3aef, 0x81691db8, 0x1081e2df, 0x7f0504a0, 0x797d5e7f, 0x006de423, 0x7f19f16f,
+0x1eb28181, 0x819f7f81, 0x7f6a84b9, 0x936537f2, 0x14a87f81, 0x7fa9cb81, 0x81813a8c, 0x8182c47f,
+0x56758144, 0x81c55c97, 0x86de0b81, 0x818181d9, 0x7f386281, 0x7fbb2738, 0xffd18d81, 0x17e1eb34,
+0x656449b7, 0x7f7fbe33, 0xd7f681b6, 0x77313c4f, 0x7dc9151e, 0x28debefb, 0x7f7f5c62, 0xa850b25f,
+0x81166b59, 0x7aea7f05, 0x325d81a1, 0x7fd06471, 0x93137fbb, 0x43a51892, 0x3e326cfe, 0xab81a942,
+0xb208d017, 0x817f0781, 0x08fcca86, 0xa31a7f81, 0xeb93206a, 0xd4fa21f4, 0x684f9029, 0x7f817f57,
+0xdca7812c, 0x7f7f0000, 0xf2dc5a96, 0x7f62aa7f, 0x918d1c7f, 0xfbb5add6, 0x407fc0da, 0x4d5d9f7f,
+0x935d8166, 0x817da9b1, 0x205d7f3a, 0xe08b4181, 0xd8bd7f7f, 0x4f33818c, 0x8105b781, 0x2f81cd81,
+0xbaf8a48d, 0x2b81aa7f, 0x90b5810d, 0xbc62c181, 0x1592f72a, 0x4d81b5fe, 0x7f81e447, 0x99d22181,
+0x303e3ea5, 0xa23078a5, 0xba8a7995, 0xd5282790, 0x6681453a, 0x7ff7ab7f, 0x7f4e8195, 0x8bc48181,
+0x817fd481, 0x81b98142, 0x265a8182, 0x81f768a7, 0x85f11690, 0x7f957f7a, 0x109981a4, 0xeabba365,
+0x577f9057, 0x5f7fae65, 0x817f8199, 0x718e3daf, 0xd6818181, 0xd1a1cc81, 0x97a48187, 0xd8d14520,
+0x497b7f10, 0x7f81d781, 0xb77f747f, 0x7f813974, 0xc52a7f7f, 0x7a292226, 0x81602ef8, 0xe481cc7f,
+0x0b4266a9, 0x4722287f, 0x7648747f, 0x9c861ec6, 0x4ba9efbe, 0x2063813f, 0x5b277f81, 0x54608181,
+0x81b3ae7a, 0x5b812281, 0x6c306f81, 0x4fa0bcd5, 0x540c85d5, 0x2f81817f, 0xd2c9078a, 0x4281a39a,
+0x3e7fa1d8, 0xa47fb881, 0x3efe9c7f, 0x7f5f6c23, 0x4681d46f, 0x49cb81c9, 0x7f4eaa68, 0x2e7f7fac,
+0xbb497fd0, 0x3a4253a8, 0x91a6aaaa, 0x4f7f5a52, 0xf9375fad, 0x8b2a7f2d, 0x746e7f81, 0x7fb0cbe0,
+0x5a917fd1, 0x5b65867f, 0xe9606f9c, 0xe9f8814e, 0x3045cf65, 0x937fad52, 0x760f5a81, 0x9be4ba50,
+0xb59d81e5, 0x0000d77f, 0xd481bd81, 0x27224a55, 0x61467c81, 0x91d865df, 0xffa17fe4, 0x7f8a0c68,
+0x1640fd52, 0x987f7f6e, 0x4d815a5a, 0x3081b65b, 0x7d7f6c8e, 0x5b26bf60, 0x44814281, 0x5a813427,
+0x81f47a3b, 0xef9281eb, 0x81994ca6, 0x7081317f, 0x7f7fd49a, 0xfb8c8e7d, 0x546ad581, 0xd6817f16,
+0x7f3e4b81, 0x4f4c4898, 0x817fe22f, 0x819a37c9, 0x387f1a55, 0x8cfddd03, 0x318aa9bb, 0xcb6e2d90,
+0xa47f0d1b, 0xae81c204, 0x7f797f27, 0x0a7f65ad, 0xe4ac81af, 0xb2d74d81, 0xca0fad81, 0x357f69a8,
+0xad71a581, 0x5be9d4de, 0xaebe8181, 0x95817fd8, 0x8f7aedb6, 0x0a81e59e, 0xa07f20eb, 0x7e66427f,
+0x56769b04, 0x2e8149f1, 0x81f6f87f, 0xc3813768, 0xbcc28850, 0x6cbd3dac, 0x7fda99dc, 0x657f7fd5,
+0x7fcf7f60, 0x81233698, 0x81daf17f, 0x867f7f7f, 0x7fda7f36, 0x0c7fae20, 0x7f817d78, 0x7fd09481,
+0x818f30e0, 0x7f437c7f, 0xaecc2b3e, 0xcf427fca, 0xccfd2cce, 0xefd898bc, 0x7f5b81e2, 0x1d4b812c,
+0x865871ae, 0x553ab4ae, 0x69817f7f, 0x811a745a, 0xa32a163d, 0x2e967f57, 0xff817f7d, 0x70d43e9a,
+0x814681ae, 0x9f817f31, 0x819b8110, 0xfca3819d, 0xc4fc45b2, 0x56b2817f, 0x7c811d7b, 0x997f8181,
+0xbe0dc3d8, 0x9f5b56a6, 0x7f8181e2, 0x5d59eb29, 0xa357e4c6, 0x8161817f, 0x3c7e7f32, 0x7fd07f06,
+0x817f82ad, 0x93de8341, 0x92850000, 0x0c65c06f, 0x0a4d2817, 0x7705d752, 0xbcd8687f, 0xc4397f7f,
+0x1b7ffd47, 0xada5012d, 0x7f8158e5, 0xba617e10, 0xa97d811f, 0x1fb61081, 0xac41e74e, 0x8c7ea7a3,
+0x997f452e, 0xb5858149, 0x5c3cb0a0, 0xc8ffab38, 0x49d65d7f, 0xbbd07c81, 0x35b06b7f, 0xcc7f7f7f,
+0x50c42881, 0x707f7fde, 0x7fd67f7f, 0x7f819981, 0xd4d6a781, 0xcb103b7f, 0x7f4fee9f, 0xb3997fe0,
+0x7f9381a5, 0xbc7f9a28, 0xf4aa819f, 0x7fe862df, 0x316dd1f8, 0xb4a66f81, 0x98816581, 0xdb817f2e,
+0x34819ee0, 0x746c817f, 0xdc9cd3e1, 0x8e7fab2d, 0xec368b2e, 0x7f8381c8, 0x817f7f7f, 0x814de179,
+0xed5b7f4d, 0x274bdfa1, 0x5851250b, 0xec811a81, 0x7f365569, 0x57935681, 0x08757781, 0x196d813e,
+0xa67581b5, 0x83a7d981, 0x73988163, 0x816eb57f, 0x2ce47e40, 0x5bef6481, 0xb131155f, 0xc2f9817f,
+0x519b67b4, 0x7d2c7f59, 0x7fdb8150, 0x5c7fc881, 0xca285c9d, 0x7f7f7fe6, 0x39aabd59, 0xb9b494e6,
+0x81401831, 0x74247792, 0xab7dfaab, 0x817fcd81, 0x819b25e3, 0x587f337f, 0x817fd238, 0x818a332c,
+0x9db6bcc3, 0x1681c227, 0x7058306d, 0x50a27f64, 0x8181a4b2, 0x7fe2a57f, 0x8d5f4777, 0x7f7f8f81,
+0x6e8381f7, 0x22518136, 0xae72d0d6, 0x7f9bba7f, 0x8117d27f, 0x792b7ff0, 0xe45892e0, 0x8e6f5c34,
+0x3994817f, 0xa981afca, 0x0000a592, 0x7f811d81, 0x09548181, 0x0ea8127f, 0x7f7fb49d, 0xd6690b81,
+0xa1846059, 0x81d15d81, 0x6ccaf481, 0x81ddef83, 0x7fccc681, 0xab502722, 0x4620e862, 0x3981de76,
+0x7f81889f, 0x5b818154, 0x797222dc, 0x4b8153a6, 0xa470816d, 0x7fb2657f, 0x81150b64, 0x89dc1f57,
+0xaa636e7f, 0xe59cba67, 0xb3b2da41, 0xc7818192, 0x7637d0d9, 0x1a78a78c, 0xaf5e3f5c, 0x8181a581,
+0x56285469, 0xeed47f7a, 0x697ff6a5, 0x7f7b7f1e, 0x398181cb, 0x999fe4a0, 0xc17f8816, 0x5c815aa2,
+0x78717fce, 0x7f7f842c, 0xf07f4c43, 0x7f818148, 0xbc66c134, 0x8168ce22, 0xaf1791a8, 0x3522ae40,
+0x95afa97d, 0x435d4e69, 0x2ab59d7f, 0x8197c47f, 0x93cfe645, 0x8dba727f, 0x227f7f81, 0xb17feb7f,
+0x702a7f81, 0xebd463b7, 0x5381e929, 0x817dba7f, 0x5c811a24, 0xfa7f814d, 0x817f8197, 0x2f7f704f,
+0x36817f7d, 0xe87f0d7f, 0x54b07fb6, 0x81733686, 0x8fcb7fcf, 0xd888c623, 0x2de5ebc5, 0x8f6f6569,
+0x7f7981f9, 0x908136b1, 0xa93a7fb5, 0x405f8141, 0x01a54dbc, 0xb6815763, 0x8ccc3ffc, 0x5681105b,
+0x4a1498bf, 0x4c6f82e5, 0xa67f556c, 0x7f5d564f, 0xdb8132d0, 0x1e958139, 0xe386811b, 0x04845a40,
+0x7fbd8109, 0x833b62ec, 0x81f40717, 0x701d8181, 0x8191ee44, 0xae2d9d7f, 0x3fa17854, 0xcbcad981,
+0x73c2d681, 0x5f738681, 0xb87081dd, 0x817f0000, 0x037fcda9, 0x922caef5, 0x7cc7f91e, 0x9a7fbd88,
+0x81819528, 0xf2cd7f53, 0xfd7c8170, 0xfb7fb997, 0x7f7f3f7f, 0xe4818154, 0x18c4414b, 0x4fa48da4,
+0x81718181, 0x817c957f, 0x7f2e1582, 0x09bc81bf, 0x5e4b817f, 0xd5590d7f, 0x7f818b44, 0x88abcf7f,
+0x39508181, 0x81ab86bf, 0xba58c325, 0x65bc83ed, 0x3402857f, 0x81c61e7f, 0x8bbab505, 0x81b2aba0,
+0x8153ec32, 0x6803d681, 0x819d817f, 0xb6de31a4, 0x367f7fc2, 0xb1048db9, 0x6389815b, 0x7ffb7b01,
+0x8f1b817f, 0xc1817f7f, 0x04187f64, 0x45cfac7a, 0x0f1b578c, 0x0f209f24, 0x33817f7f, 0x7f7f7f81,
+0xac814781, 0x5a9d3dbf, 0x62a65581, 0xcb8a7353, 0x7f81c5b8, 0xba447fa1, 0x9081774d, 0x7af9ed38,
+0xb6849bce, 0xacf07c18, 0xa1894581, 0xd7634242, 0x2d0e8174, 0xdbf799d9, 0x7fe7b446, 0x84110cf7,
+0x6474da81, 0x8185e120, 0x9da4f123, 0xd07fce54, 0xa9cdf7af, 0x84db817f, 0x9e9a23b7, 0x81774c7f,
+0x7f818152, 0x817f5243, 0x39058181, 0xbbc91e81, 0xe3d87581, 0x81b66581, 0x7fb06a61, 0x0bcd0fdf,
+0x8188dee9, 0x1cd87f92, 0xf036977f, 0x977f4d61, 0x1da12581, 0x3a7fbee0, 0x87467fa8, 0x7fe27fa3,
+0x89d37f7c, 0x397c7ff4, 0x57e64171, 0xc4819181, 0x93677f41, 0x65be2517, 0xbe6c7f7f, 0xaa7f7f81,
+0x255d650e, 0x098181c9, 0xe8124525, 0xc73a4949, 0x24d14b47, 0x6730f681, 0xfe251c6e, 0xbc7fa092,
+0x81917f5f, 0x81d1ab81, 0xd6128193, 0x13d62e52, 0x941c14f4, 0x25b452c6, 0x7f9c947d, 0x815d3f42,
+0x81c8c9d0, 0x7f524663, 0x40ae7524, 0x2f81c77e, 0x815c8483, 0x7f7fb27f, 0x7fc37f44, 0xe07f9db7,
+0x7b812117, 0x1c965b7f, 0x1822ad4b, 0xccb9e67f, 0xc5b18115, 0x7f8c377f, 0xd13939cb, 0x38e8147f,
+0x4e722d21, 0x9e81ef00, 0x81c0fa81, 0x812d8158, 0x9d84a57f, 0xefc32797, 0x7fc9987f, 0xa37f8199,
+0x81812681, 0x81818190, 0x89a9814c, 0x7945c381, 0xa57f816d, 0x7d65af81, 0x81bb7f72, 0x1c81cd7f,
+0x6d3e4e7f, 0x6cbef90d, 0xca24894d, 0xb04892b6, 0x7f7f1e81, 0xf57f5965, 0x0769a7b0, 0x698562b9,
+0x16817f7f, 0xabb94bb7, 0xc35c81f3, 0xb9b5728e, 0x8181641f, 0x81d2d2be, 0x9181bb37, 0xf82b9222,
+0x7bdc7ff5, 0x9b812fa1, 0x8173f4ec, 0x94810185, 0x2bd00d63, 0x814c50dd, 0x9be376e5, 0xed7f90dc,
+0x817bf98c, 0xe1df634d, 0x287f81ae, 0x27a4f115, 0x62101a81, 0x2723b481, 0x9c507f66, 0x44a01769,
+0xbfd13025, 0x7f815b81, 0x5d5c817f, 0xb37f7fa5, 0x7f79b2c6, 0xa1e2847f, 0x813ac57f, 0x417f8b7f,
+0x4b505b55, 0x22d47fbb, 0x7f886ad7, 0xf78c7f48, 0x53a5245d, 0xdfd37f1b, 0xb37f81c4, 0x907fc99f,
+0xa393f1c0, 0x7f5f7015, 0x37be3fb3, 0x7f4c9e28, 0x7f770000, 0x9b7a0531, 0x7f35cdde, 0x5b4047cf,
+0x81881773, 0xdc6e9ea5, 0x517f477f, 0xb2a77f81, 0x9981472d, 0xd4c57f81, 0x6ef2a77f, 0x81d481a3,
+0x3d87307f, 0x214321bd, 0x7b7f7f8e, 0x997f1cbe, 0x266681ec, 0x3639f87f, 0x687f7fed, 0xf17f8191,
+0x1558ae38, 0x815ac086, 0x81247f78, 0x7f612db7, 0x128d7fc9, 0x187fbf81, 0x4a898116, 0x3a6c818d,
+0x7f7fdcf1, 0x60cb3e9c, 0x81bf627f, 0xe7c17fa1, 0x52247fd2, 0x814781dc, 0x6eb67f1a, 0x9d0b7f7d,
+0xc2b238f8, 0x81b1427a, 0xa1555aad, 0x103c0c29, 0x97319c81, 0x05ab3a7f, 0x811f1d7f, 0x817f8195,
+0x40bffc7f, 0x3aa38f4a, 0x46e17fcb, 0x6781fc31, 0xb725a5e4, 0x427f8cbd, 0x7f857fd4, 0xca1f7f9d,
+0x2f77c6b9, 0xdde30a0e, 0x7f93fca2, 0xc6aa7fc7, 0x7f9e7f7f, 0x9b78012e, 0xdda0d07f, 0x0b4c7f83,
+0x7fee4b44, 0x81640552, 0x40d573c0, 0x390efbce, 0x327fb881, 0xf5e69aec, 0x81e9c7d1, 0x81717f74,
+0x81817d78, 0xac6eba86, 0x41a2d07f, 0x8981da45, 0x5264b681, 0x527f46f2, 0x949e7f52, 0x7fdd7fbd,
+0x81678102, 0x87756c64, 0x3d2a81ca, 0xc87f8107, 0xd17fb64a, 0xa7b553b5, 0x8191812a, 0x55ddbf7f,
+0x517f7b7f, 0x897aad7f, 0x63817f8d, 0xd9547f7f, 0x43437351, 0x84818181, 0x3a7f8127, 0xccbfdf7f,
+0xe1191588, 0x81c80c65, 0x7ffcf571, 0xcc147b7f, 0x00007081, 0x2b7f7f7f, 0x889b3a2b, 0x5358e78b,
+0xfcb917ab, 0x81c3f74d, 0xd57faa18, 0x69937f23, 0xd7321b81, 0x5db1ad81, 0x17577f0a, 0xf48118bf,
+0x81822681, 0x2981e87f, 0xc16e6c7f, 0x891d38ae, 0xf37f813f, 0x81b96b55, 0x2fcd81b1, 0x23b5f981,
+0x695c4d28, 0xa0810fab, 0x6cd5ea3d, 0xefc68ec4, 0xae32887e, 0xa27f0b17, 0x7f8baa97, 0x8116b3a1,
+0xa393817f, 0x817019f0, 0x1d7f8193, 0x18f0d764, 0xb27fb7c9, 0xc4da637f, 0xcd586f56, 0x7f23810d,
+0x572f25f3, 0x05df7f15, 0x817f815c, 0x8b147f84, 0x0f817f6b, 0x7f1f7f7f, 0xbccee4a8, 0xcb5ad7ed,
+0x33a5f88b, 0xc7817ecd, 0x8781817f, 0x817e6444, 0x6697817f, 0xf9490257, 0x83d5f581, 0x7168b332,
+0xf4ed4781, 0x17e0c1c4, 0x16b9c997, 0x8581247f, 0x81887b3f, 0x2281a5c7, 0xce437f0f, 0x994c6f81,
+0xbcd09735, 0x9269d57d, 0x449a7e61, 0x8c6e7f81, 0x81b38c7f, 0x81db7791, 0x62602681, 0x3246817f,
+0x81bb2881, 0x6d2510b4, 0xb07fbf69, 0x49ea817f, 0x938153e7, 0xf17f425b, 0x3b817f89, 0x36b48181,
+0x837c1d0a, 0x853cbd2c, 0x2950527f, 0x388de1bc, 0xfa1c7f54, 0x7b507f7f, 0xad311c42, 0x8d8ae6c3,
+0x9081677f, 0x58810e81, 0x984b4881, 0x4b9f407f, 0x819a00ff, 0x857faee2, 0xa06d9fb5, 0x448979b8,
+0x9cc0f17f, 0x7f2fce7f, 0xa0b9ad7f, 0x428a7f7f, 0xdf562afa, 0x7f6f0000, 0xe04a5bef, 0xa7ad2867,
+0x23818146, 0x7f7f0642, 0x7f481981, 0x7f810f81, 0x99a9db81, 0x64d437cd, 0xaf7fcb6d, 0x81815311,
+0x723c81bd, 0xcc7fc729, 0x81a47e49, 0x9abce744, 0x7385eb5b, 0x7f7f5b7f, 0x2bb3819d, 0x81fd7f49,
+0x7f5f8198, 0x7fb6a2f3, 0xe97fc33c, 0x436c79d3, 0x5ea67fff, 0x5a7ff2ac, 0x28aa713c, 0x8181c681,
+0x7f7c8846, 0xaf817f39, 0x90bcc57f, 0x841c7f4a, 0x817f8181, 0x7f4e811b, 0xb53a81ce, 0x7f451a7f,
+0x5f38027f, 0x7b81e4f3, 0x817f87c6, 0x8141318c, 0x532c81a4, 0x817fc84c, 0x919d33db, 0x29f2b781,
+0x7f568139, 0x4658b1a6, 0x7f69342d, 0x81ab9582, 0x367fa301, 0x47468181, 0x7f8c8181, 0x81216a81,
+0x9b577f7f, 0x7f447f7f, 0x72ef4649, 0x45418103, 0xee48bb81, 0xa7027c7f, 0x0ea4237f, 0x6b717cf4,
+0xa296a17f, 0x17007f7f, 0x869835c8, 0x8a7f77ec, 0x5d7b8139, 0x32688f81, 0x7fdab0b3, 0x815c7f7d,
+0x06a01fb6, 0x814981de, 0xa1c681d8, 0xdc6ff522, 0xd13081b1, 0x9c5a7ff5, 0x7f7f7f5c, 0x86faa148,
+0x811a696b, 0xbb7fa2c5, 0x815779bf, 0xae3b7f48, 0x8c45d6de, 0x7f867f9a, 0x3e359b7f, 0xb7c48181,
+0x78c27f95, 0xc4818181, 0x81cd7f3f, 0x558a8193, 0x7f4ca874, 0x4e1eb447, 0x2744355f, 0x9020ead4,
+0x16e47ff6, 0x708123b7, 0xbeb61418, 0x27fcdd50, 0xde21e5d8, 0x9500a3db, 0xefc29f4d, 0x5ef0c542,
+0xe02a3bc8, 0xe91a38bf, 0x24f81e3c, 0xe0fe4f11, 0x3be6891d, 0x7fef09ae, 0x16977ff0, 0xe8b74a18,
+0x1a50fa2e, 0x24c04bf9, 0x39c84714, 0xbed7f6c1, 0xaeddab44, 0xa7f9ca2d, 0x275dc01b, 0x1df6e74b,
+0xc3171107, 0xbcc93481, 0x1403f685, 0xcc1c0439, 0xb602ebaa, 0xe235d0e1, 0xf1afe3e3, 0x0814c025,
+0xb4f93607, 0xa709c243, 0xbbfabdd8, 0xfd3e81e7, 0x2f9ae335, 0x1c1d52e9, 0x00f133a5, 0x23eee238,
+0xc625eced, 0xefd56878, 0xe3cadc03, 0x585db90a, 0x024ace2b, 0xe3d804ef, 0xdf54d5a1, 0xc9e11709,
+0xc3a20ccb, 0x18c0005f, 0x52424437, 0xccaba110, 0xc75736d6, 0xa8f1401a, 0x3186aa67, 0x0b1aaebe,
+0xf952cf90, 0xfa4edd16, 0x9d72bee5, 0x2824f455, 0x9a3cb150, 0x6bbfe929, 0x6a6f5f9d, 0xbfa5385f,
+0xf89828bc, 0x6b6d0baf, 0xcab514c5, 0xa9baf505, 0x24cff2c2, 0x1c2511d8, 0x3abccde9, 0x7f60deef,
+0xbbf4dddd, 0x11366331, 0x0241c141, 0x5111c984, 0xc17f54da, 0xed4c1bb8, 0x0af6fb57, 0xfd2c28c0,
+0xe790142d, 0x6bff6403, 0x7fd8cce3, 0x3c282cc0, 0xea48f68b, 0x3ecdd5e3, 0xb917f2e5, 0xd2b25334,
+0xf65b10b5, 0xfdd0d4be, 0xe6e22cc9, 0xc59ec206, 0x3f3238cc, 0xbcbe2fd0, 0x2418c910, 0x3d07f7cc,
+0xa25bf9cf, 0xdb81ebfc, 0xd35b2203, 0xde2d23cc, 0x3cd706d5, 0x0e34f6f5, 0xc2d20000, 0xfef1e4e0,
+0xd26ad6e1, 0xfa130b0d, 0x324b211c, 0xc5dfc3a9, 0xf83ebec9, 0x0dd627c0, 0xcee99850, 0x4fcd1533,
+0x04597ff0, 0x40d0ff25, 0x045cd181, 0x908f9ca1, 0xd0417f7b, 0x2f0a2c87, 0xfef998c7, 0xcc3370f3,
+0xb0f4267f, 0x1bbe5072, 0xd8d6063a, 0xd058cb32, 0x448fffad, 0xa9b50064, 0x184ebdf7, 0xfe2e3538,
+0x561f16a6, 0xe7f20181, 0x449b95f9, 0x0338f7b2, 0x4012bcae, 0xd67f6797, 0x4966f6f2, 0x1dcc60c0,
+0xeecec631, 0x279f81c4, 0xc9f751be, 0x75994dc8, 0x01001ded, 0xb0ba1822, 0xbb14eff9, 0xb2dae837,
+0x4cf69e23, 0xf35d6ad7, 0xf69e57c9, 0x3727d2e3, 0x31b3517f, 0xc1da575d, 0x30e2c1d5, 0x54d7beef,
+0x293edf19, 0xeb37d80e, 0x296cee35, 0xeff14f04, 0x232d06de, 0xb2815853, 0x2c601508, 0xa5ecb6ff,
+0xb407f524, 0x4ccd9a19, 0xe448b0c2, 0x01ebd4c6, 0x52fc03a1, 0x286afce2, 0xe4d45ebb, 0x2953101d,
+0xca12d31f, 0x10cb00dd, 0xd2ae6347, 0x46e82f44, 0x45d64600, 0xae393c05, 0xf7219fb9, 0xeffe09d2,
+0xedfbb5d1, 0x07070413, 0xd7d6ec37, 0xa0f7a621, 0x75bd023f, 0xc45b5d37, 0x19ca9b39, 0xd1ee50b7,
+0x50062231, 0x301ca07f, 0xbeadd410, 0x1ce01d02, 0x51a5fbff, 0xd9104c7f, 0x79e4f23a, 0x33e47449,
+0x1ceda8ea, 0xf6d65581, 0x418dd3e3, 0x9fc1e612, 0x54f747d9, 0x839acbce, 0x0000221c, 0x031434b6,
+0xcc48960f, 0x1045ea23, 0xa8d7f8a1, 0xaf01243e, 0x2bf461c7, 0x9c2139dd, 0xd42bd5d5, 0xf8c2f5d5,
+0xdeb61f4b, 0xf12ac9cd, 0x107f3209, 0x818d1d3c, 0xca34572c, 0x34da0052, 0xf9a951e2, 0xdf34d209,
+0x0f8b37c1, 0xa7dee3d3, 0x1a390c98, 0x1d16e135, 0x33c3ad66, 0xd9e2cca4, 0xcbabcce4, 0x2eadd581,
+0x81383b81, 0xc0db251b, 0x0a6e91c3, 0xdab3c725, 0xd2293bfc, 0x22d6abb5, 0xdb524adc, 0x30cf5f24,
+0xb92527e8, 0x6000b7bf, 0xfefe1fe4, 0x2cf9035e, 0x2743f125, 0xd007b3ad, 0x2dd5e43a, 0x5a35e7b9,
+0xea06e5b7, 0x39f3e1aa, 0x592614f3, 0x7fc3bab7, 0xf1aefe00, 0xf3e9b9fc, 0xcd81aee6, 0xae3e31cc,
+0x95d8fbc7, 0x7f26bbf8, 0xf20e57e3, 0xf9eee307, 0xfde2bff2, 0x10e8f7db, 0xfbb0de50, 0xdfaa10e8,
+0x5e18ee3a, 0x0520a445, 0xddd2bc9e, 0x13c97536, 0x33cf5159, 0xfac6d2f7, 0x18ca01e5, 0x112251da,
+0x0211d9b6, 0x375feb63, 0x9a25b9cf, 0xfb5bf632, 0xe5b4a803, 0x95f55e8d, 0xdbede748, 0x39aed0bf,
+0x5efd9c49, 0xcc7fd13c, 0xfba1a3d7, 0xa8a80206, 0x08f7e7d3, 0xd1fac77f, 0x32fb9272, 0xe1829834,
+0x45408175, 0x34e4eec0, 0x0ca4ecae, 0x15e31638, 0x1d072d02, 0xee44d6ee, 0xafa5282c, 0x4d4d9f2a,
+0xcdfc0f24, 0x9dfaf345, 0xbf3839c3, 0x3268a3e3, 0x2e4eacb5, 0x93dce12c, 0x4a484f3b, 0xdf7d0000,
+0xeb113c3d, 0xd4bdf13f, 0xecc0f511, 0xd4cdf8c2, 0x42fc05f9, 0x53be2def, 0xb22e49cf, 0xead92e2e,
+0xf956f1cc, 0x02c821e0, 0x1da533e5, 0x1fc50531, 0x34c30f37, 0x7ccba6e4, 0xab1afe2e, 0xb93bd67f,
+0xea28a8a8, 0xf3ef282e, 0xac0c507f, 0xd0cbdd53, 0xd344ea1d, 0x472a1029, 0xed099f70, 0x1240edc6,
+0x7f143244, 0xbae0d3d5, 0x7a4bddfd, 0x5f07d846, 0x1cdf4aaf, 0x4fc40ac1, 0xcfca381a, 0xb67fd847,
+0xd381dde6, 0xdad40d1d, 0x64cb2d07, 0x171a8bc6, 0x11110cbf, 0x2c442dff, 0xbe90f52b, 0xd75500e5,
+0xd8459ef9, 0xff0bc92f, 0x44a903c8, 0xb767d7f2, 0xc281fc02, 0xca534906, 0x25fdec32, 0x5f2aaeb2,
+0x121b376c, 0xe3e41dd2, 0x12ecd9f8, 0xc5071a9d, 0xfaaeee7d, 0x183a1a57, 0xadcb921d, 0x1e33a3b2,
+0x72e52634, 0xc8d4e81e, 0x3b1e0200, 0x321e1608, 0x49add232, 0x0516ff41, 0xc23181d3, 0xfa4e0151,
+0xa63502cb, 0xda381204, 0x72d92da5, 0x7cd7ebff, 0xce08d106, 0x61c6f034, 0x55310f68, 0xed66c357,
+0xc527d609, 0xdab11518, 0x41b808e5, 0x5f21e65e, 0xd4f6f036, 0xfc40008d, 0xaa7f19a0, 0xbff0ac1b,
+0x78283b60, 0x1d0a4a03, 0xd6d0d016, 0xf1f23847, 0x58d93518, 0xd6d481b7, 0xaf11e02e, 0x5c74b67f,
+0xd5734f27, 0x2fb07fc2, 0x29564eff, 0xcafae603, 0x1228f673, 0x3367ce30, 0x132d1342, 0xc80c10e9,
+0x68ad07f9, 0x379c0c9c, 0x3a73c010, 0xc1a534bc, 0x69b0fc14, 0xf0d3ba81, 0x0d07bbe3, 0x3319fa45,
+0x38815afe, 0xc1a67850, 0x7fe740fe, 0xc43fb638, 0xa0864249, 0x07a7dc33, 0x05e606d4, 0x3c6a81ca,
+0x0cdb2635, 0x5dd3f756, 0xcbf09b70, 0x53b2a5b3, 0x5f035ab0, 0xfdda1fbd, 0x0510ac20, 0xa8611f44,
+0x38ceb74c, 0x5048e2e5, 0x907f0238, 0xd9ad00d9, 0x7c247736, 0x8aabe3c6, 0xf5443d27, 0x7ff84622,
+0x4bcc0a34, 0x797dc7e0, 0xf914e5f2, 0xa12df5d7, 0x0fdc23f9, 0x377f50c3, 0x8f47bf82, 0xb9948a4a,
+0x8135ca9e, 0x523ace17, 0xd299fb23, 0x523b5407, 0x38b42a22, 0xadee2cd8, 0xee04b9c8, 0x2de3a5e2,
+0x9f132faa, 0xa0030325, 0x019996f4, 0xd6c5562a, 0xf3e19255, 0x00ff2432, 0xe8f6cf36, 0xe55a7f14,
+0x7079f06f, 0x1e11ff0b, 0xcbe89aa8, 0x6b363996, 0xe61dd6f7, 0x15133821, 0xf35940f9, 0xd9b139c1,
+0x2ad6e10b, 0x2a29c0c6, 0x3c6ee3ce, 0x4b0a3624, 0x23cc10df, 0x17cdb502, 0xa46eaa3f, 0x42350300,
+0xed66334e, 0x1d6fc255, 0x3213e4c5, 0x23d4a65a, 0x05b9a3e9, 0xbacd0c19, 0xc9c5b5b1, 0x8e12670d,
+0x4aabbe2d, 0xb815e3c7, 0x5a2dd152, 0x3ef6551c, 0xf0a1b4f3, 0xb8b8459b, 0xc52dd72e, 0xb9f4b9f7,
+0xbd05dcc8, 0xfae04029, 0xb16ad8df, 0x03d167d4, 0xaf08525b, 0xdbdf3117, 0x4192d163, 0x00a2caad
+
+hard_output0 =
+0xb5bc6ac8, 0xf5373664, 0x1310345c, 0xd5bae4e7, 0x1fc9e83e, 0xebfdfded, 0x84bd86ab, 0xb7aabe00,
+0x60b44fea, 0xb9067464, 0x30325378, 0xa9195955, 0xf70c6e5c, 0x90922632, 0xc90b1cdb, 0xf2f5fb69,
+0x73056b63, 0x1a33bf3f, 0x17755b5c, 0xc58bff6d, 0x2f4390b2, 0x2869d508, 0xe7c7dfe8, 0x38552963,
+0x21da5367, 0x07282b9b, 0xa4767105, 0x1e294251, 0xe350a940, 0xb8a6aa27, 0xed12d778, 0xf10d9ece,
+0xab93527f, 0xcf2da7e7, 0x68f6d0b1, 0x811f4bca, 0x577b06b2, 0x3234f13e, 0x30bab7df, 0x8dc47655,
+0xbb843bed, 0x86da3aba, 0x30950c97, 0xdd096d7a, 0xa871fd6c, 0x8bee4e6b, 0x8fea30d0, 0x6c05b4d2,
+0xf3e144d3, 0xd24ebb1f, 0x065635e5, 0x8d3f2cf9, 0x536c6c6a, 0xfbb0a5d0, 0x3d707b42, 0xc44d5982,
+0xa5f4ad8f, 0xf32c0970, 0x1bccf1a6, 0x05916020, 0xa64fb176, 0x5ede6a35, 0xaf4966da, 0x9df5e0e7,
+0x75042abc, 0x9ef10481, 0x11ddcbc8, 0xa0f5518c, 0xd5c23418, 0x2393d558, 0xfbe7dfeb, 0xed1c64c2,
+0x86a36508, 0xde2dfb1e, 0xb8d0fef9, 0x24505232, 0xc894e71c, 0xbcc752a0, 0x40b74e83, 0x90d23c8c,
+0x728e4a61, 0x108f0b08, 0x66f522ee, 0xc258d851, 0x35a31c44, 0x11311b5b, 0xfd3d5be9, 0x5ae448ff,
+0x4f64994b, 0x5b8247a9, 0x4021114d, 0x2f0b6e82, 0x5eaa9828, 0x50ac71c0, 0xfb86ee52, 0x0dc1ac9b,
+0xbbd47645, 0x8f357115, 0x978ceea0, 0xd557db99, 0x99b30388, 0xfc9a8a1c, 0x0f75be1a, 0x50143e22,
+0x8840989b, 0x738ec50e, 0xe6b2783d, 0xf67899c8, 0x27ebed69, 0x6c415a16, 0x3a6cc2dc, 0xcd4e4e5d,
+0x6cb12b2e, 0xdb88d7c0, 0x79cd1582, 0xbc422413, 0xe72ad2f4, 0x8eaac30f, 0x0bd86747, 0x6d87f69d,
+0x15d62038, 0x4b375630, 0x0d51b859, 0x16db2cb2, 0xf210603a, 0x0abeb833, 0x55c694d0, 0xe57ca43b,
+0x0ba94428, 0x1398a406, 0xe47d3889, 0x5a20203d, 0x250d7a1a, 0xd930ffec, 0x03992e79, 0xf2759376,
+0x024ec121, 0x91fc3a2c, 0xb7e11cc5, 0x4ff7d459, 0xb8700134, 0xd6e61758, 0x4eba0a32, 0xb747e3ec,
+0x7073fad7, 0xded80f99, 0x331e2f1b, 0xfa1f1bed, 0x056424a2, 0x1d1d95e0, 0x550b9ec8, 0x51ee2a38,
+0x19525153, 0xd70c4cd5, 0x0d6cd7ad, 0xe44d1cf2, 0x30dfecda, 0xdacd7fe8, 0x7321d795, 0xddf48ef4,
+0xe271e6a4, 0x9c1feecb, 0x951fcd7b, 0x8acc5a03, 0x3fb83527, 0xe306de74, 0x7b9cd6ee, 0x8e140885,
+0xd4c91e8d, 0xe8c39733, 0x0f02f87f, 0xfb06b1b9, 0x0dc9349c, 0xf76bae8e, 0x4f642a07, 0x3d48a9aa,
+0xe3ea323a, 0xa1cd5c8a, 0x40aa0e70, 0x132042d3, 0xa9732f6c, 0xd15a00c4, 0x43d3b046, 0x9a51ebd4,
+0xc46ee0ed, 0xe2a2148b, 0xf5c478f0, 0x1fb01cf3, 0xf4f321ec, 0xd973811f, 0x11ad11b9, 0x5c67adda
+
+soft_output0 =
+0x81818181, 0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x817f817f, 0x81817f81,
+0x7f817f81, 0x7f817f81, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x817f8181, 0x81817f81,
+0x7f7f7f81, 0x817f7f81, 0x7f7f8181, 0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x817f8181, 0x7f7f8181,
+0x81817f7f, 0x81817f7f, 0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x8181817f, 0x81818181, 0x7f817f7f, 0x7f7f817f, 0x81817f81, 0x7f7f8181, 0x817f817f,
+0x7f817f81, 0x7f7f8181, 0x817f7f81, 0x81818181, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f8181,
+0x8181817f, 0x817f7f81, 0x81818181, 0x817f8181, 0x7f7f817f, 0x7f7f7f81, 0x7f81817f, 0x7f81817f,
+0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x817f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f, 0x7f81817f,
+0x817f7f81, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f, 0x7f81817f, 0x7f7f817f,
+0x81817f81, 0x81817f81, 0x81817f81, 0x817f817f, 0x7f817f7f, 0x7f81817f, 0x81818181, 0x8181817f,
+0x7f817f7f, 0x817f7f7f, 0x7f7f817f, 0x817f7f81, 0x7f7f7f81, 0x81818181, 0x817f8181, 0x7f7f7f81,
+0x7f817f81, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x7f7f8181, 0x81817f7f, 0x7f7f8181, 0x7f7f817f,
+0x7f7f817f, 0x81817f7f, 0x8181817f, 0x817f8181, 0x81817f81, 0x817f7f7f, 0x817f7f81, 0x7f81817f,
+0x7f7f7f7f, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x81818181, 0x817f7f81, 0x7f817f81, 0x7f817f81,
+0x817f7f81, 0x7f818181, 0x7f81817f, 0x817f817f, 0x7f7f817f, 0x81818181, 0x7f818181, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x7f7f7f7f, 0x81817f81, 0x817f8181, 0x7f818181, 0x817f8181, 0x81817f7f,
+0x7f7f8181, 0x81817f81, 0x7f7f817f, 0x817f817f, 0x81818181, 0x7f81817f, 0x817f817f, 0x81818181,
+0x817f8181, 0x817f8181, 0x817f8181, 0x7f817f81, 0x7f7f7f81, 0x7f7f8181, 0x7f817f7f, 0x7f7f817f,
+0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f7f, 0x817f817f, 0x7f817f81, 0x7f817f81, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x81817f81,
+0x817f7f81, 0x7f818181, 0x7f7f8181, 0x817f7f81, 0x7f817f81, 0x817f7f7f, 0x7f7f8181, 0x81817f7f,
+0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f,
+0x8181817f, 0x817f8181, 0x81817f81, 0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x81817f81, 0x7f7f8181,
+0x8181817f, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x8181817f, 0x8181817f, 0x81817f81, 0x817f8181,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x8181817f, 0x817f8181,
+0x817f7f81, 0x817f7f81, 0x7f817f81, 0x817f8181, 0x7f7f7f81, 0x7f81817f, 0x81818181, 0x8181817f,
+0x7f7f8181, 0x7f7f7f81, 0x81817f7f, 0x7f818181, 0x817f7f7f, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f,
+0x8181817f, 0x7f81817f, 0x817f7f7f, 0x817f817f, 0x7f7f7f7f, 0x7f817f81, 0x8181817f, 0x7f81817f,
+0x7f81817f, 0x81817f7f, 0x817f7f81, 0x7f817f81, 0x7f81817f, 0x7f7f7f7f, 0x81817f81, 0x81817f7f,
+0x81817f7f, 0x81817f7f, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x7f7f8181, 0x7f7f8181,
+0x817f7f7f, 0x81818181, 0x7f818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f817f,
+0x7f7f8181, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x7f7f817f, 0x81817f81, 0x817f8181, 0x7f7f817f,
+0x81817f7f, 0x7f7f7f81, 0x7f81817f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x817f817f, 0x81817f7f,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f81817f, 0x7f818181, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f81,
+0x7f7f7f7f, 0x7f7f8181, 0x7f817f81, 0x7f818181, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x8181817f,
+0x817f817f, 0x7f7f7f81, 0x7f818181, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f817f, 0x81817f7f,
+0x817f7f7f, 0x81818181, 0x8181817f, 0x81817f7f, 0x7f7f7f7f, 0x817f8181, 0x7f817f81, 0x817f8181,
+0x817f7f7f, 0x7f7f7f81, 0x817f8181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f81817f, 0x817f817f,
+0x7f817f7f, 0x7f818181, 0x7f818181, 0x7f817f7f, 0x81817f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f81,
+0x81817f81, 0x817f7f7f, 0x81817f7f, 0x81817f81, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f,
+0x7f817f81, 0x81817f81, 0x7f7f7f81, 0x817f8181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f817f7f,
+0x817f7f81, 0x7f7f817f, 0x7f7f8181, 0x7f7f8181, 0x81818181, 0x7f81817f, 0x7f81817f, 0x817f8181,
+0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f817f81, 0x7f817f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81,
+0x8181817f, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x81817f81, 0x7f818181, 0x7f7f7f7f, 0x7f81817f,
+0x8181817f, 0x8181817f, 0x7f7f7f7f, 0x7f818181, 0x817f7f81, 0x7f7f817f, 0x817f7f81, 0x81818181,
+0x817f817f, 0x7f818181, 0x81817f81, 0x81818181, 0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x817f817f,
+0x817f7f7f, 0x817f8181, 0x81817f81, 0x81818181, 0x817f817f, 0x7f817f7f, 0x7f817f7f, 0x7f817f81,
+0x817f7f7f, 0x81817f81, 0x817f7f81, 0x7f7f817f, 0x7f817f7f, 0x7f81817f, 0x8181817f, 0x81817f81,
+0x81817f7f, 0x7f817f81, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x817f7f7f, 0x7f817f81, 0x8181817f,
+0x817f8181, 0x7f81817f, 0x81817f7f, 0x7f817f81, 0x81818181, 0x7f81817f, 0x7f81817f, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f81817f, 0x817f7f81, 0x7f81817f, 0x81818181, 0x7f7f8181, 0x7f818181,
+0x8181817f, 0x81818181, 0x8181817f, 0x817f817f, 0x7f81817f, 0x81817f7f, 0x7f81817f, 0x7f817f7f,
+0x81817f81, 0x7f81817f, 0x7f7f817f, 0x817f8181, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f817f7f,
+0x817f7f7f, 0x7f7f817f, 0x7f818181, 0x817f8181, 0x7f7f7f81, 0x81817f7f, 0x81817f7f, 0x7f7f7f7f,
+0x7f818181, 0x7f7f8181, 0x7f81817f, 0x7f7f817f, 0x8181817f, 0x7f81817f, 0x8181817f, 0x81817f7f,
+0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x817f8181, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x81818181,
+0x817f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x81817f81, 0x81817f7f,
+0x7f818181, 0x817f7f81, 0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f817f, 0x7f817f81, 0x7f7f7f81,
+0x7f818181, 0x7f7f817f, 0x81818181, 0x817f7f81, 0x81817f7f, 0x8181817f, 0x817f8181, 0x8181817f,
+0x7f818181, 0x7f817f81, 0x8181817f, 0x7f817f7f, 0x8181817f, 0x7f817f7f, 0x7f7f7f81, 0x817f7f7f,
+0x817f8181, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x81817f7f, 0x7f7f8181, 0x81817f81, 0x7f7f7f7f,
+0x7f818181, 0x7f818181, 0x7f7f7f7f, 0x8181817f, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f7f817f,
+0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f817f, 0x7f817f81, 0x81818181, 0x817f8181,
+0x7f7f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f, 0x81817f81, 0x7f7f7f81,
+0x817f8181, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x7f7f7f81, 0x7f818181, 0x817f7f7f, 0x7f7f7f7f,
+0x817f7f81, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x81817f81, 0x81817f81, 0x7f7f7f81,
+0x8181817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f81, 0x81818181, 0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x817f817f, 0x8181817f, 0x7f818181,
+0x817f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f7f8181, 0x81817f7f, 0x7f7f8181, 0x7f7f8181, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f,
+0x817f817f, 0x7f81817f, 0x817f7f81, 0x8181817f, 0x81817f7f, 0x81818181, 0x817f817f, 0x7f7f817f,
+0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x81817f81, 0x7f7f7f81, 0x7f81817f, 0x7f7f7f81,
+0x8181817f, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f, 0x7f7f8181, 0x817f817f,
+0x7f7f8181, 0x7f7f7f81, 0x817f8181, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x7f7f817f, 0x7f817f81,
+0x7f817f81, 0x7f817f81, 0x7f817f81, 0x817f8181, 0x7f7f7f7f, 0x7f817f81, 0x817f7f81, 0x7f7f7f81,
+0x7f7f817f, 0x7f817f7f, 0x7f7f7f7f, 0x817f7f81, 0x81817f7f, 0x81817f7f, 0x81818181, 0x7f81817f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f817f7f,
+0x81818181, 0x7f817f7f, 0x7f7f817f, 0x81818181, 0x8181817f, 0x81817f7f, 0x81818181, 0x817f817f,
+0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f818181, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x81817f7f,
+0x8181817f, 0x817f817f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x817f7f7f, 0x817f817f,
+0x817f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f7f81, 0x7f817f7f, 0x81817f7f, 0x81817f81, 0x7f817f81,
+0x817f7f7f, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x81817f81, 0x81818181, 0x7f817f7f,
+0x8181817f, 0x817f7f7f, 0x81817f7f, 0x7f817f7f, 0x817f7f7f, 0x817f7f81, 0x7f7f7f81, 0x81817f7f,
+0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x817f7f7f, 0x81818181, 0x7f7f817f,
+0x817f817f, 0x81817f81, 0x817f7f81, 0x81817f7f, 0x7f7f7f81, 0x7f817f7f, 0x81817f7f, 0x817f817f,
+0x7f817f7f, 0x7f817f7f, 0x81817f7f, 0x817f7f7f, 0x81818181, 0x8181817f, 0x7f7f8181, 0x7f817f7f,
+0x7f817f81, 0x7f7f8181, 0x81817f81, 0x817f7f81, 0x7f818181, 0x7f817f81, 0x7f7f7f81, 0x8181817f,
+0x81817f7f, 0x817f7f7f, 0x7f818181, 0x7f818181, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x7f817f81,
+0x81817f7f, 0x81818181, 0x7f81817f, 0x7f7f8181, 0x817f817f, 0x817f7f81, 0x81817f81, 0x817f7f81,
+0x81818181, 0x817f7f7f, 0x7f818181, 0x81818181, 0x7f7f817f, 0x817f817f, 0x7f7f817f, 0x7f817f7f,
+0x7f817f81, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x817f8181, 0x817f817f, 0x7f818181,
+0x817f7f81, 0x817f7f7f, 0x81817f81, 0x81818181, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f8181,
+0x7f818181, 0x81817f81, 0x7f817f7f, 0x7f7f7f81, 0x7f7f817f, 0x817f7f81, 0x7f7f7f81, 0x81818181,
+0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x7f81817f, 0x817f8181, 0x7f81817f,
+0x8181817f, 0x81818181, 0x7f7f817f, 0x817f8181, 0x7f817f7f, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f,
+0x8181817f, 0x7f7f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x817f7f81, 0x7f7f817f, 0x7f81817f,
+0x81817f81, 0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f7f, 0x7f817f81, 0x7f817f81, 0x7f7f817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f81817f, 0x7f7f8181, 0x7f7f8181, 0x81817f7f,
+0x7f817f81, 0x817f817f, 0x7f817f7f, 0x81818181, 0x7f817f7f, 0x81817f7f, 0x7f817f81, 0x81817f81,
+0x7f7f7f81, 0x81818181, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f7f81, 0x7f818181, 0x7f7f8181,
+0x7f7f7f81, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x817f8181, 0x817f8181, 0x817f7f81,
+0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x81817f81, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x81817f7f, 0x7f817f7f, 0x81817f7f, 0x81817f7f, 0x7f817f81, 0x7f7f8181, 0x7f7f817f, 0x7f7f7f7f,
+0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x7f817f81, 0x81818181, 0x81817f81, 0x817f7f7f, 0x7f7f817f,
+0x817f7f7f, 0x7f7f7f81, 0x81817f81, 0x817f8181, 0x7f7f817f, 0x7f7f817f, 0x7f7f8181, 0x817f7f81,
+0x8181817f, 0x8181817f, 0x7f7f7f81, 0x7f7f817f, 0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x817f817f,
+0x7f7f7f81, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81,
+0x81817f7f, 0x8181817f, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x81817f7f, 0x7f818181, 0x7f817f81,
+0x8181817f, 0x7f81817f, 0x817f7f7f, 0x817f7f7f, 0x8181817f, 0x817f817f, 0x81817f81, 0x7f7f8181,
+0x7f7f7f7f, 0x7f81817f, 0x817f817f, 0x81817f81, 0x81817f81, 0x81817f7f, 0x81817f81, 0x81817f81,
+0x7f7f817f, 0x7f7f7f7f, 0x817f7f7f, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x7f7f8181, 0x817f7f7f,
+0x7f7f7f81, 0x7f817f81, 0x7f7f7f7f, 0x7f817f81, 0x7f81817f, 0x7f817f7f, 0x81817f7f, 0x7f817f7f,
+0x81817f81, 0x7f7f7f81, 0x7f81817f, 0x81817f81, 0x7f817f81, 0x817f8181, 0x7f817f81, 0x7f817f7f,
+0x81818181, 0x817f817f, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x81818181, 0x8181817f, 0x7f817f81,
+0x81817f7f, 0x7f7f7f7f, 0x7f7f817f, 0x7f81817f, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f817f81,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f7f, 0x817f7f81, 0x817f8181, 0x81817f7f, 0x81817f7f,
+0x7f7f817f, 0x817f817f, 0x7f817f81, 0x7f817f81, 0x81818181, 0x817f817f, 0x7f7f7f81, 0x81817f7f,
+0x817f817f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f7f, 0x817f7f81, 0x817f7f81, 0x817f8181, 0x8181817f,
+0x81818181, 0x81817f7f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f817f, 0x7f7f7f7f, 0x7f817f81,
+0x8181817f, 0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x81817f7f,
+0x7f7f7f81, 0x81817f81, 0x7f818181, 0x81817f7f, 0x7f7f817f, 0x7f818181, 0x81818181, 0x7f818181,
+0x7f7f7f81, 0x81817f7f, 0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x7f817f7f, 0x7f817f7f, 0x7f817f7f,
+0x7f7f817f, 0x7f817f81, 0x7f81817f, 0x7f7f7f81, 0x81818181, 0x7f7f8181, 0x817f8181, 0x7f817f81,
+0x7f817f81, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x817f7f7f, 0x7f81817f, 0x7f817f7f,
+0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x817f817f, 0x81817f81, 0x7f7f817f, 0x7f817f7f, 0x817f817f,
+0x7f7f7f7f, 0x817f7f81, 0x817f8181, 0x7f7f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x7f7f817f, 0x8181817f,
+0x817f7f81, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x817f7f7f,
+0x817f817f, 0x81817f7f, 0x81818181, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x817f817f, 0x81817f81,
+0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x8181817f, 0x7f7f817f, 0x817f7f81, 0x817f7f81, 0x7f818181,
+0x817f7f7f, 0x8181817f, 0x817f8181, 0x7f7f817f, 0x7f818181, 0x817f8181, 0x7f7f7f81, 0x817f8181,
+0x8181817f, 0x7f817f81, 0x81817f7f, 0x817f8181, 0x817f817f, 0x817f7f81, 0x81818181, 0x81818181,
+0x8181817f, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x817f817f, 0x7f818181, 0x817f8181, 0x7f7f817f,
+0x7f7f7f81, 0x7f818181, 0x7f818181, 0x7f81817f, 0x81817f81, 0x7f818181, 0x7f7f8181, 0x7f817f7f,
+0x8181817f, 0x7f817f7f, 0x817f7f81, 0x7f817f81, 0x8181817f, 0x81818181, 0x817f7f7f, 0x817f817f,
+0x7f7f7f7f, 0x817f8181, 0x81818181, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x817f7f81, 0x81817f81,
+0x7f818181, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x7f81817f,
+0x81817f81, 0x817f7f7f, 0x817f817f, 0x7f7f817f, 0x7f7f8181, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f,
+0x7f81817f, 0x7f81817f, 0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x8181817f, 0x817f7f81, 0x7f818181,
+0x7f818181, 0x817f7f81, 0x7f817f81, 0x7f7f7f7f, 0x81817f81, 0x81818181, 0x7f818181, 0x7f81817f,
+0x81817f81, 0x817f7f7f, 0x7f7f817f, 0x7f7f817f, 0x81817f81, 0x7f817f81, 0x7f7f8181, 0x81817f7f,
+0x817f817f, 0x81817f7f, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f817f81, 0x817f7f7f,
+0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x7f818181, 0x7f817f81, 0x81818181, 0x817f817f, 0x7f7f7f7f,
+0x81818181, 0x7f7f8181, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x8181817f, 0x81817f7f, 0x817f817f,
+0x817f7f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x817f8181, 0x81818181, 0x7f7f7f7f, 0x7f7f817f,
+0x817f7f7f, 0x7f7f817f, 0x817f8181, 0x7f817f81, 0x7f818181, 0x7f81817f, 0x7f81817f, 0x81818181,
+0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x81818181, 0x7f817f81, 0x81818181, 0x7f817f81, 0x81818181,
+0x817f8181, 0x7f7f7f81, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x817f7f81,
+0x7f81817f, 0x817f7f7f, 0x81817f81, 0x817f7f81, 0x81818181, 0x7f7f7f7f, 0x81817f7f, 0x81817f81,
+0x81817f81, 0x81817f81, 0x7f817f81, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f7f817f, 0x81817f81,
+0x7f7f817f, 0x8181817f, 0x817f7f81, 0x81818181, 0x817f7f7f, 0x817f8181, 0x7f7f817f, 0x817f7f7f,
+0x8181817f, 0x81817f7f, 0x7f817f7f, 0x817f7f81, 0x81817f81, 0x817f7f7f, 0x81818181, 0x817f7f7f,
+0x81817f81, 0x7f81817f, 0x7f81817f, 0x7f818181, 0x817f7f81, 0x817f817f, 0x7f81817f, 0x81818181,
+0x81817f81, 0x81818181, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x8181817f, 0x8181817f, 0x81818181,
+0x81818181, 0x81818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f7f81, 0x7f818181,
+0x817f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x7f817f81, 0x817f7f7f, 0x81817f81,
+0x7f7f7f7f, 0x817f7f81, 0x817f7f7f, 0x7f817f81, 0x81817f7f, 0x81817f81, 0x817f7f81, 0x81817f81,
+0x817f817f, 0x7f817f81, 0x81817f7f, 0x7f7f7f81, 0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x7f81817f,
+0x817f8181, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x7f7f817f, 0x7f817f7f, 0x7f818181, 0x81817f7f,
+0x81817f7f, 0x8181817f, 0x817f817f, 0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f818181, 0x7f81817f,
+0x817f7f7f, 0x7f817f7f, 0x81817f81, 0x8181817f, 0x8181817f, 0x7f817f81, 0x8181817f, 0x8181817f,
+0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x7f817f7f, 0x81817f81, 0x7f7f7f81, 0x817f7f7f, 0x7f817f81,
+0x7f818181, 0x7f817f81, 0x81818181, 0x817f817f, 0x817f817f, 0x7f818181, 0x817f8181, 0x7f7f817f,
+0x7f7f7f81, 0x817f7f7f, 0x7f81817f, 0x7f81817f, 0x7f81817f, 0x81817f81, 0x817f817f, 0x7f7f817f,
+0x7f817f81, 0x817f817f, 0x7f817f7f, 0x7f81817f, 0x8181817f, 0x817f7f7f, 0x8181817f, 0x7f7f8181,
+0x7f818181, 0x7f817f81, 0x7f7f817f, 0x817f8181, 0x817f817f, 0x817f7f81, 0x7f7f7f81, 0x81817f81,
+0x817f8181, 0x81818181, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f7f7f81,
+0x7f818181, 0x817f7f81, 0x7f817f7f, 0x81818181, 0x7f817f7f, 0x7f7f817f, 0x7f7f8181, 0x8181817f,
+0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x7f81817f, 0x81817f81, 0x7f817f81, 0x817f8181, 0x817f817f,
+0x817f7f7f, 0x81817f7f, 0x7f818181, 0x81818181, 0x817f7f81, 0x81817f7f, 0x817f8181, 0x817f8181,
+0x81817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x7f7f7f7f, 0x817f8181,
+0x81817f7f, 0x7f818181, 0x7f7f7f81, 0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x7f817f81, 0x817f8181,
+0x817f817f, 0x7f7f7f7f, 0x81818181, 0x81818181, 0x81818181, 0x7f817f7f, 0x81818181, 0x7f81817f,
+0x7f817f81, 0x8181817f, 0x817f7f7f, 0x817f817f, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x81817f81,
+0x7f7f8181, 0x7f817f7f, 0x817f7f7f, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x817f7f81,
+0x817f7f7f, 0x7f817f81, 0x7f817f7f, 0x817f817f, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x8181817f,
+0x7f817f7f, 0x8181817f, 0x7f817f81, 0x7f81817f, 0x7f7f7f81, 0x7f7f7f81, 0x817f817f, 0x81818181,
+0x7f817f81, 0x7f81817f, 0x7f7f8181, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f818181, 0x7f7f7f7f,
+0x7f7f8181, 0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f7f, 0x7f7f8181,
+0x817f7f7f, 0x81817f81, 0x7f818181, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x7f817f81,
+0x7f7f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x8181817f, 0x817f7f7f, 0x7f817f7f, 0x817f8181,
+0x7f817f7f, 0x817f8181, 0x7f818181, 0x81817f7f, 0x7f817f7f, 0x8181817f, 0x7f81817f, 0x7f7f7f7f,
+0x7f81817f, 0x7f817f81, 0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f818181, 0x817f7f7f, 0x7f81817f,
+0x81817f81, 0x7f7f7f81, 0x7f818181, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x817f8181,
+0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x8181817f, 0x81817f81,
+0x817f8181, 0x817f8181, 0x7f7f8181, 0x7f7f8181, 0x8181817f, 0x7f817f7f, 0x8181817f, 0x7f81817f,
+0x7f7f7f81, 0x817f817f, 0x81817f7f, 0x817f7f81, 0x81817f7f, 0x817f7f81, 0x81817f81, 0x7f817f81,
+0x817f8181, 0x7f818181, 0x7f817f81, 0x81817f81, 0x81817f81, 0x817f8181, 0x7f818181, 0x81818181,
+0x817f7f81, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x8181817f, 0x81818181, 0x817f7f81, 0x7f818181,
+0x81817f81, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x81817f81, 0x7f817f81, 0x7f7f817f, 0x8181817f,
+0x817f7f7f, 0x7f7f817f, 0x7f817f81, 0x817f7f7f, 0x7f7f817f, 0x81818181, 0x817f7f81, 0x7f7f8181,
+0x7f7f8181, 0x8181817f, 0x7f7f8181, 0x817f8181, 0x817f7f7f, 0x817f7f7f, 0x7f7f7f7f, 0x81817f81,
+0x817f7f81, 0x7f7f8181, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f7f7f81, 0x81817f7f,
+0x817f817f, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f,
+0x7f7f8181, 0x817f817f, 0x7f7f7f81, 0x7f7f817f, 0x817f8181, 0x7f81817f, 0x7f81817f, 0x817f7f7f,
+0x7f817f7f, 0x817f817f, 0x817f7f81, 0x817f7f81, 0x81817f81, 0x7f817f81, 0x817f817f, 0x7f81817f,
+0x7f7f8181, 0x7f818181, 0x7f818181, 0x817f817f, 0x7f81817f, 0x817f8181, 0x8181817f, 0x7f817f7f,
+0x817f8181, 0x817f7f81, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x7f7f7f7f, 0x81818181, 0x7f7f8181,
+0x7f817f7f, 0x7f7f8181, 0x81817f7f, 0x817f817f, 0x81818181, 0x817f7f7f, 0x8181817f, 0x81817f81,
+0x817f817f, 0x817f817f, 0x7f7f817f, 0x7f7f7f81, 0x7f818181, 0x7f817f7f, 0x7f7f7f81, 0x817f817f,
+0x7f818181, 0x7f7f8181, 0x7f817f7f, 0x81817f81, 0x7f7f8181, 0x817f7f81, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f7f81, 0x81817f81, 0x817f8181, 0x817f7f7f,
+0x7f7f7f81, 0x817f8181, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x7f7f7f7f, 0x81817f7f,
+0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f7f,
+0x8181817f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x817f8181, 0x7f7f7f81, 0x7f817f81, 0x7f817f7f,
+0x7f818181, 0x817f7f7f, 0x81817f81, 0x817f8181, 0x7f818181, 0x81817f7f, 0x817f8181, 0x7f7f8181,
+0x81817f7f, 0x7f7f7f7f, 0x81818181, 0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x817f8181,
+0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f,
+0x7f817f81, 0x817f8181, 0x7f7f7f7f, 0x7f818181, 0x7f7f7f81, 0x7f7f817f, 0x7f817f81, 0x817f8181,
+0x81818181, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f81817f, 0x7f7f817f, 0x81817f81, 0x7f7f8181,
+0x81818181, 0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x817f7f81, 0x81817f81, 0x7f817f7f, 0x817f817f,
+0x7f81817f, 0x7f818181, 0x817f8181, 0x81817f7f, 0x817f8181, 0x7f7f7f81, 0x7f818181, 0x7f7f817f,
+0x817f8181, 0x817f8181, 0x7f817f81, 0x7f81817f, 0x8181817f, 0x817f7f81, 0x817f817f, 0x81818181,
+0x7f817f7f, 0x817f817f, 0x817f817f, 0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x7f81817f, 0x81818181,
+0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f81817f, 0x7f7f7f81, 0x817f7f81, 0x817f8181, 0x7f818181,
+0x7f7f7f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f818181, 0x817f7f81, 0x81817f7f, 0x81817f7f, 0x81817f81,
+0x7f7f7f81, 0x8181817f, 0x7f7f8181, 0x7f81817f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f817f7f, 0x81818181, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x817f817f, 0x81818181, 0x81817f81,
+0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x81818181, 0x81818181, 0x7f7f7f7f, 0x817f7f81, 0x7f81817f,
+0x7f81817f, 0x7f7f8181, 0x7f818181, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x81817f81, 0x817f7f81,
+0x7f7f7f81, 0x7f81817f, 0x817f7f81, 0x817f8181, 0x7f81817f, 0x817f8181, 0x81817f7f, 0x7f817f81,
+0x81818181, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x7f7f8181, 0x8181817f, 0x81818181, 0x81818181,
+0x81818181, 0x817f8181, 0x81817f81, 0x817f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x7f81817f,
+0x7f7f7f81, 0x7f7f7f7f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x817f7f7f,
+0x7f817f7f, 0x81818181, 0x81818181, 0x7f7f817f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x817f7f81,
+0x81818181, 0x7f817f7f, 0x81817f7f, 0x81817f81, 0x817f817f, 0x817f7f7f, 0x7f7f817f, 0x7f7f817f,
+0x7f7f8181, 0x817f7f81, 0x7f81817f, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f7f8181, 0x817f8181, 0x817f817f, 0x7f7f7f81, 0x81818181, 0x81817f81,
+0x7f7f7f7f, 0x817f817f, 0x81818181, 0x7f7f817f, 0x7f818181, 0x7f7f8181, 0x817f8181, 0x817f7f7f,
+0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x817f8181, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81,
+0x7f818181, 0x7f817f7f, 0x81817f81, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f817f, 0x7f7f7f7f,
+0x817f8181, 0x7f7f7f7f, 0x7f81817f, 0x7f817f81, 0x81818181, 0x817f817f, 0x817f7f7f, 0x81817f7f,
+0x7f81817f, 0x817f817f, 0x7f818181, 0x8181817f, 0x817f817f, 0x81818181, 0x817f7f7f, 0x817f7f81,
+0x7f7f8181, 0x817f817f, 0x817f7f81, 0x7f81817f, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x81817f81, 0x7f81817f, 0x7f7f7f7f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x81817f7f,
+0x7f81817f, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x817f817f, 0x81817f81,
+0x7f7f7f81, 0x817f7f81, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x81817f81, 0x7f817f7f, 0x7f818181,
+0x7f818181, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x81817f81, 0x817f7f7f, 0x817f8181, 0x7f7f817f,
+0x81818181, 0x81817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f, 0x817f7f81, 0x817f7f7f,
+0x81817f7f, 0x7f81817f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x817f7f81,
+0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x7f7f7f7f, 0x7f817f81, 0x7f7f7f81, 0x817f7f7f, 0x81817f81,
+0x7f817f7f, 0x817f7f81, 0x817f817f, 0x81817f7f, 0x7f818181, 0x7f81817f, 0x7f817f81, 0x7f817f81,
+0x7f81817f, 0x7f7f7f7f, 0x7f817f81, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f7f7f81, 0x7f818181, 0x7f818181, 0x7f818181, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x81818181,
+0x7f81817f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x81817f81, 0x7f818181, 0x81817f81, 0x7f7f7f7f, 0x7f81817f,
+0x81817f81, 0x7f817f7f, 0x7f81817f, 0x81817f81, 0x81818181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x7f7f817f, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x81817f81, 0x8181817f, 0x7f817f81, 0x81817f7f,
+0x817f7f7f, 0x7f7f8181, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x817f817f, 0x817f7f81, 0x7f7f817f,
+0x7f7f8181, 0x7f818181, 0x7f7f8181, 0x81817f7f, 0x8181817f, 0x817f7f7f, 0x7f7f8181, 0x7f817f81,
+0x817f817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x81818181, 0x81817f81,
+0x81817f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f817f, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f,
+0x7f81817f, 0x817f7f81, 0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x7f7f817f,
+0x7f817f7f, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x81818181, 0x8181817f, 0x7f7f7f81, 0x7f818181,
+0x8181817f, 0x7f7f7f7f, 0x817f817f, 0x7f818181, 0x81817f81, 0x7f818181, 0x7f81817f, 0x817f7f81,
+0x81818181, 0x7f7f7f81, 0x81817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x8181817f, 0x7f817f7f,
+0x7f7f8181, 0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f818181,
+0x81817f81, 0x7f818181, 0x81817f81, 0x7f818181, 0x7f7f7f81, 0x817f817f, 0x81817f7f, 0x7f7f7f81,
+0x817f817f, 0x7f817f81, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f81, 0x8181817f, 0x817f8181,
+0x7f7f7f7f, 0x8181817f, 0x817f8181, 0x81818181, 0x7f818181, 0x81818181, 0x7f7f7f81, 0x817f817f,
+0x81817f81, 0x8181817f, 0x8181817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x8181817f, 0x817f7f7f,
+0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81817f81, 0x81817f7f, 0x8181817f,
+0x817f817f, 0x7f817f7f, 0x817f7f7f, 0x7f7f7f81, 0x817f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f7f,
+0x817f817f, 0x817f8181, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f, 0x7f818181, 0x7f7f8181, 0x817f817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x817f8181, 0x817f817f, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f,
+0x7f7f7f7f, 0x7f817f7f, 0x817f817f, 0x817f817f, 0x7f817f81, 0x81818181, 0x7f817f7f, 0x7f7f8181,
+0x7f7f8181, 0x81817f7f, 0x81817f7f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f, 0x81817f7f, 0x7f7f817f,
+0x817f7f81, 0x8181817f, 0x81817f81, 0x7f7f8181, 0x7f7f8181, 0x7f7f7f81, 0x81817f7f, 0x7f7f817f,
+0x81817f81, 0x7f817f81, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f8181, 0x7f817f7f, 0x7f7f8181,
+0x817f817f, 0x817f7f7f, 0x7f817f7f, 0x817f8181, 0x817f7f7f, 0x7f81817f, 0x7f7f817f, 0x817f817f,
+0x7f7f8181, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f7f817f, 0x81817f81, 0x7f817f81, 0x7f817f7f,
+0x817f7f81, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x81817f81, 0x7f817f7f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f7f7f7f, 0x7f818181, 0x817f7f81, 0x817f817f, 0x8181817f,
+0x817f7f7f, 0x817f8181, 0x8181817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x81817f7f, 0x7f7f8181,
+0x81818181, 0x81818181, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f7f81, 0x8181817f, 0x7f81817f,
+0x7f7f817f, 0x7f818181, 0x81817f7f, 0x7f817f81, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x817f7f7f,
+0x7f818181, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x7f818181, 0x81817f81, 0x817f7f7f, 0x7f818181,
+0x7f817f81, 0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x817f817f, 0x81818181, 0x7f817f7f, 0x7f817f81,
+0x817f7f81, 0x7f7f817f, 0x81817f81, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x817f817f, 0x81817f81,
+0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x7f818181, 0x7f818181, 0x7f7f7f7f, 0x817f7f81,
+0x817f7f81, 0x7f7f7f81, 0x8181817f, 0x7f7f7f7f, 0x817f817f, 0x7f817f7f, 0x817f817f, 0x7f7f7f7f,
+0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x7f81817f,
+0x7f817f7f, 0x81817f81, 0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x817f7f7f,
+0x81817f81, 0x817f7f7f, 0x81817f81, 0x7f81817f, 0x7f818181, 0x7f818181, 0x7f818181, 0x7f81817f,
+0x7f7f8181, 0x817f7f81, 0x817f8181, 0x7f817f81, 0x7f817f7f, 0x81818181, 0x7f817f81, 0x81818181,
+0x81817f7f, 0x81818181, 0x817f7f81, 0x81817f81, 0x81817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f81817f,
+0x7f7f8181, 0x81818181, 0x7f7f7f7f, 0x7f7f8181, 0x81817f7f, 0x81817f81, 0x7f7f7f81, 0x8181817f,
+0x8181817f, 0x7f7f817f, 0x81817f81, 0x817f817f, 0x817f7f7f, 0x817f817f, 0x817f817f, 0x7f81817f,
+0x8181817f, 0x817f7f7f, 0x7f818181, 0x817f7f7f, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x817f817f,
+0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81, 0x8181817f, 0x7f818181, 0x7f7f8181, 0x7f81817f, 0x817f8181,
+0x7f81817f, 0x7f7f8181, 0x8181817f, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x8181817f, 0x81817f81,
+0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x7f81817f, 0x7f817f7f, 0x81817f7f, 0x7f7f8181, 0x817f7f7f,
+0x7f7f7f81, 0x817f8181, 0x7f817f81, 0x817f7f81, 0x817f7f81, 0x81818181, 0x81818181, 0x81818181,
+0x7f7f8181, 0x7f81817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81,
+0x7f817f81, 0x817f8181, 0x7f81817f, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x7f81817f, 0x8181817f, 0x8181817f, 0x7f81817f,
+0x7f817f81, 0x7f7f817f, 0x817f817f, 0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x817f7f81, 0x817f817f,
+0x817f817f, 0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x817f817f,
+0x8181817f, 0x81818181, 0x81817f81, 0x817f8181, 0x81818181, 0x81817f7f, 0x817f8181, 0x7f7f8181,
+0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x81817f7f, 0x7f7f7f7f, 0x817f817f,
+0x817f7f7f, 0x7f7f817f, 0x7f817f81, 0x7f7f817f, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x7f817f7f,
+0x7f81817f, 0x7f7f8181, 0x7f817f81, 0x817f7f7f, 0x7f7f817f, 0x7f818181, 0x7f7f817f, 0x81818181,
+0x7f81817f, 0x817f8181, 0x81818181, 0x81817f81, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f7f, 0x7f817f81, 0x7f817f7f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f7f, 0x7f81817f, 0x7f818181,
+0x7f818181, 0x817f7f7f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x817f7f81, 0x7f7f7f81, 0x817f7f81,
+0x7f817f7f, 0x7f7f7f7f, 0x7f818181, 0x7f817f81, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x81818181,
+0x7f7f817f, 0x81817f81, 0x8181817f, 0x7f7f7f81, 0x81817f7f, 0x7f817f81, 0x81818181, 0x817f817f,
+0x7f7f7f81, 0x7f81817f, 0x7f7f817f, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x8181817f,
+0x7f7f7f7f, 0x81817f81, 0x7f7f7f7f, 0x7f7f7f7f, 0x81817f7f, 0x7f817f81, 0x7f81817f, 0x81817f81,
+0x817f817f, 0x81817f81, 0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f817f, 0x7f818181, 0x817f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x8181817f, 0x817f7f7f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f81, 0x7f7f8181, 0x8181817f, 0x7f818181, 0x7f817f7f, 0x817f817f, 0x7f7f7f81, 0x817f817f,
+0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x7f817f81,
+0x7f817f7f, 0x817f817f, 0x7f7f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x81818181, 0x817f7f7f,
+0x817f7f81, 0x817f7f7f, 0x817f7f7f, 0x8181817f, 0x7f7f7f81, 0x7f7f8181, 0x817f7f81, 0x817f7f81,
+0x7f817f7f, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x7f818181, 0x7f7f817f, 0x7f817f81, 0x7f7f817f,
+0x7f817f7f, 0x7f817f81, 0x8181817f, 0x81818181, 0x7f7f7f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f,
+0x817f8181, 0x7f818181, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f818181, 0x81818181, 0x7f7f7f7f,
+0x8181817f, 0x81817f81, 0x817f7f81, 0x81818181, 0x81817f7f, 0x8181817f, 0x7f817f7f, 0x7f7f7f7f,
+0x817f7f81, 0x817f7f81, 0x817f7f7f, 0x7f7f7f81, 0x7f7f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f817f,
+0x81818181, 0x7f7f7f81, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x7f818181, 0x817f817f, 0x7f7f7f81,
+0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x8181817f, 0x7f81817f, 0x817f817f, 0x8181817f, 0x7f7f7f7f,
+0x817f7f7f, 0x7f818181, 0x817f7f81, 0x7f7f8181, 0x817f7f7f, 0x8181817f, 0x817f8181, 0x8181817f,
+0x81817f81, 0x817f8181, 0x817f7f81, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x7f7f7f81, 0x7f818181,
+0x7f817f7f, 0x7f7f8181, 0x7f7f817f, 0x81817f81, 0x81817f7f, 0x81817f7f, 0x81817f7f, 0x817f817f,
+0x7f81817f, 0x7f7f7f7f, 0x817f8181, 0x8181817f, 0x7f817f81, 0x7f817f7f, 0x817f7f7f, 0x7f7f8181,
+0x7f7f8181, 0x7f7f7f81, 0x7f818181, 0x81817f7f, 0x8181817f, 0x817f7f81, 0x7f7f7f7f, 0x7f81817f,
+0x817f8181, 0x7f81817f, 0x8181817f, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f7f7f81, 0x817f7f7f,
+0x81818181, 0x7f7f7f7f, 0x81818181, 0x81818181, 0x7f7f8181, 0x7f817f81, 0x81818181, 0x817f8181,
+0x81817f81, 0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x81817f81, 0x81817f81,
+0x7f7f8181, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x81818181, 0x7f7f7f7f,
+0x81817f7f, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x817f8181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f81, 0x817f7f81, 0x7f81817f, 0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x81817f7f, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f7f7f81, 0x817f7f7f, 0x81818181, 0x7f7f817f, 0x7f818181,
+0x7f7f7f7f, 0x81818181, 0x7f7f7f81, 0x81818181, 0x8181817f, 0x7f817f81, 0x7f7f7f7f, 0x7f817f81,
+0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x8181817f, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f817f,
+0x7f7f7f81, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x81817f81,
+0x817f7f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x817f7f81, 0x817f8181, 0x7f7f7f7f,
+0x7f818181, 0x81817f7f, 0x7f817f7f, 0x817f817f, 0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x7f7f8181,
+0x817f7f81, 0x81817f81, 0x817f8181, 0x817f817f, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f7f8181,
+0x7f7f7f81, 0x817f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x81818181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f7f7f,
+0x81818181, 0x8181817f, 0x7f7f7f7f, 0x7f7f817f, 0x817f8181, 0x817f817f, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x7f817f81, 0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f,
+0x7f7f7f7f, 0x817f8181, 0x817f8181, 0x7f7f817f, 0x81817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f,
+0x817f7f7f, 0x817f817f, 0x7f7f8181, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81, 0x7f81817f,
+0x81817f7f, 0x817f7f7f, 0x7f817f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f7f817f, 0x7f817f81,
+0x81817f81, 0x81818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f81, 0x81817f7f, 0x81818181, 0x817f8181,
+0x7f7f817f, 0x7f817f7f, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x7f818181, 0x7f817f81, 0x7f817f81,
+0x7f818181, 0x81817f7f, 0x817f7f81, 0x8181817f, 0x7f7f7f81, 0x81817f7f, 0x7f817f81, 0x8181817f,
+0x7f7f817f, 0x817f817f, 0x81817f81, 0x81817f81, 0x81817f7f, 0x7f818181, 0x817f7f81, 0x817f7f81,
+0x7f7f7f7f, 0x7f81817f, 0x7f817f81, 0x7f7f817f, 0x7f818181, 0x8181817f, 0x81817f81, 0x7f817f81,
+0x7f81817f, 0x817f7f81, 0x7f818181, 0x817f817f, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f,
+0x81817f7f, 0x7f7f8181, 0x81817f81, 0x81817f7f, 0x8181817f, 0x7f7f817f, 0x8181817f, 0x7f818181,
+0x7f817f7f, 0x817f7f7f, 0x81817f81, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x7f7f817f, 0x7f7f7f81,
+0x817f7f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f8181, 0x7f817f81, 0x7f817f81, 0x7f81817f, 0x81818181,
+0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x817f7f81, 0x8181817f,
+0x81818181, 0x8181817f, 0x8181817f, 0x817f7f81, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x817f7f7f,
+0x81818181, 0x81818181, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x817f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x817f8181, 0x7f7f7f81, 0x817f7f7f, 0x7f817f81, 0x7f7f817f, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x817f817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x817f8181, 0x817f7f7f,
+0x81818181, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x817f817f, 0x817f7f7f, 0x7f7f817f, 0x8181817f,
+0x7f7f7f7f, 0x81817f81, 0x8181817f, 0x7f81817f, 0x817f7f81, 0x7f7f7f7f, 0x817f7f7f, 0x817f817f,
+0x81818181, 0x8181817f, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x8181817f,
+0x7f818181, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x81817f7f, 0x7f818181, 0x81818181, 0x8181817f,
+0x817f817f, 0x7f7f7f7f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81, 0x7f7f817f, 0x7f818181, 0x81818181,
+0x81818181, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x81817f7f, 0x7f7f817f, 0x8181817f, 0x7f7f7f7f,
+0x7f7f8181, 0x7f7f817f, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x817f8181, 0x81818181,
+0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f7f7f, 0x8181817f, 0x7f817f7f, 0x7f7f817f, 0x81818181,
+0x7f817f7f, 0x817f8181, 0x817f7f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f8181,
+0x81817f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f81817f, 0x8181817f, 0x81818181, 0x81817f7f,
+0x7f81817f, 0x81818181, 0x7f7f8181, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x817f817f, 0x7f818181,
+0x7f817f7f, 0x7f7f7f7f, 0x817f817f, 0x817f7f7f, 0x7f81817f, 0x817f7f81, 0x81818181, 0x7f7f817f,
+0x817f817f, 0x81817f81, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x7f81817f, 0x7f817f81, 0x81817f81,
+0x7f7f817f, 0x8181817f, 0x7f818181, 0x7f7f7f7f, 0x81818181, 0x8181817f, 0x7f817f81, 0x8181817f,
+0x7f81817f, 0x7f7f8181, 0x817f817f, 0x817f7f81, 0x7f817f81, 0x81817f7f, 0x7f818181, 0x81818181,
+0x81817f81, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x81817f81, 0x7f7f7f81, 0x7f818181, 0x81817f81,
+0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f817f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f817f,
+0x817f817f, 0x817f817f, 0x817f8181, 0x7f7f7f81, 0x817f7f81, 0x817f8181, 0x7f7f7f81, 0x8181817f,
+0x81817f7f, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x817f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f7f, 0x81818181, 0x81818181, 0x7f7f7f81, 0x81817f7f, 0x8181817f, 0x7f818181, 0x7f817f7f,
+0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x7f817f7f, 0x81817f7f, 0x8181817f, 0x817f8181, 0x817f7f81,
+0x7f7f7f7f, 0x81817f7f, 0x81817f81, 0x81818181, 0x81817f7f, 0x817f817f, 0x817f817f, 0x7f7f817f,
+0x7f81817f, 0x81818181, 0x7f817f81, 0x7f7f8181, 0x7f7f817f, 0x7f7f7f81, 0x81817f7f, 0x817f8181,
+0x7f817f7f, 0x8181817f, 0x817f8181, 0x817f7f7f, 0x7f7f7f81, 0x8181817f, 0x817f7f81, 0x7f817f81,
+0x7f7f8181, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f, 0x8181817f,
+0x7f81817f, 0x817f817f, 0x7f817f81, 0x8181817f, 0x7f818181, 0x81817f81, 0x7f818181, 0x81818181,
+0x7f7f7f81, 0x817f7f7f, 0x817f8181, 0x7f817f7f, 0x7f817f81, 0x817f7f81, 0x81818181, 0x7f7f7f81,
+0x7f7f7f81, 0x7f7f7f81, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f817f7f, 0x7f817f81, 0x7f818181,
+0x7f7f8181, 0x817f8181, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x817f8181, 0x7f817f7f, 0x7f817f7f,
+0x7f7f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f817f7f, 0x817f817f, 0x7f817f81, 0x7f7f8181, 0x81817f81,
+0x7f7f8181, 0x7f818181, 0x817f7f81, 0x7f818181, 0x81817f7f, 0x817f7f7f, 0x7f7f8181, 0x81817f7f,
+0x7f817f7f, 0x7f818181, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x7f818181, 0x7f817f7f, 0x81817f81,
+0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f, 0x7f817f81, 0x7f81817f,
+0x7f7f7f81, 0x7f7f7f81, 0x817f817f, 0x7f7f7f81, 0x81818181, 0x7f7f7f81, 0x8181817f, 0x817f7f81,
+0x7f7f817f, 0x817f817f, 0x817f8181, 0x7f7f8181, 0x81817f7f, 0x7f817f81, 0x8181817f, 0x7f81817f,
+0x7f818181, 0x7f818181, 0x7f817f81, 0x7f7f7f7f, 0x7f81817f, 0x817f7f81, 0x7f7f7f81, 0x81818181,
+0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f81817f,
+0x81817f81, 0x7f817f81, 0x81817f7f, 0x81818181, 0x817f817f, 0x817f7f7f, 0x817f8181, 0x81818181,
+0x7f81817f, 0x81818181, 0x81818181, 0x7f818181, 0x7f7f7f7f, 0x81817f81, 0x8181817f, 0x7f7f817f,
+0x817f7f81, 0x817f7f81, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x7f7f7f81, 0x817f7f81, 0x81818181,
+0x8181817f, 0x81817f81, 0x7f7f8181, 0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x7f81817f,
+0x81817f7f, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x7f7f7f81, 0x817f7f81, 0x81818181, 0x7f7f7f81,
+0x7f7f8181, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x81817f81, 0x7f81817f, 0x81817f81, 0x7f7f8181,
+0x817f817f, 0x7f817f81, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x7f7f817f,
+0x817f8181, 0x7f7f817f, 0x8181817f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f7f,
+0x7f7f817f, 0x7f81817f, 0x81818181, 0x81817f81, 0x8181817f, 0x7f817f7f, 0x81818181, 0x7f7f7f81,
+0x7f7f7f7f, 0x81817f7f, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x81818181, 0x7f7f7f81,
+0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x817f8181,
+0x7f817f7f, 0x7f817f7f, 0x7f7f817f, 0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x7f818181, 0x817f7f81,
+0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f7f, 0x81817f7f, 0x7f81817f, 0x81818181,
+0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81817f81, 0x8181817f, 0x7f818181, 0x81817f81,
+0x817f7f81, 0x817f7f7f, 0x7f7f7f81, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x7f7f817f, 0x7f7f817f,
+0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f81817f, 0x7f7f8181,
+0x7f818181, 0x817f8181, 0x7f7f8181, 0x7f817f81, 0x81818181, 0x7f817f81, 0x817f7f7f, 0x7f817f7f,
+0x7f7f8181, 0x817f8181, 0x7f818181, 0x81817f81, 0x7f818181, 0x8181817f, 0x8181817f, 0x7f818181,
+0x8181817f, 0x7f7f7f7f, 0x7f7f817f, 0x7f818181, 0x7f7f7f81, 0x7f7f817f, 0x81818181, 0x817f7f7f,
+0x8181817f, 0x817f817f, 0x7f7f8181, 0x7f7f7f81, 0x81818181, 0x8181817f, 0x817f817f, 0x817f817f,
+0x7f818181, 0x7f7f8181, 0x8181817f, 0x817f817f, 0x81817f7f, 0x81818181, 0x7f81817f, 0x817f817f,
+0x7f7f7f7f, 0x7f817f81, 0x7f818181, 0x817f7f7f, 0x817f7f81, 0x7f817f81, 0x7f7f817f, 0x7f7f7f7f,
+0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f817f, 0x8181817f, 0x7f81817f, 0x7f818181, 0x7f7f7f7f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x817f7f81, 0x7f817f7f,
+0x817f7f7f, 0x7f7f7f81, 0x7f7f8181, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f81,
+0x817f817f, 0x817f7f7f, 0x81818181, 0x7f818181, 0x81818181, 0x81818181, 0x7f7f7f81, 0x8181817f,
+0x81818181, 0x7f817f7f, 0x817f7f81, 0x7f7f8181, 0x7f818181, 0x8181817f, 0x8181817f, 0x817f7f81,
+0x7f817f7f, 0x81817f7f, 0x817f8181, 0x7f817f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f, 0x817f7f7f,
+0x817f7f7f, 0x7f817f81, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x7f7f7f81,
+0x7f817f81, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x7f818181, 0x81817f81,
+0x817f8181, 0x7f817f7f, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x81817f81, 0x81817f81,
+0x81817f7f, 0x7f81817f, 0x81818181, 0x7f7f8181, 0x817f817f, 0x817f8181, 0x817f7f7f, 0x8181817f,
+0x81817f7f, 0x8181817f, 0x7f817f81, 0x81817f7f, 0x81818181, 0x817f7f7f, 0x7f81817f, 0x817f817f,
+0x81818181, 0x817f7f81, 0x817f817f, 0x817f7f7f, 0x81817f7f, 0x7f7f8181, 0x817f7f81, 0x8181817f,
+0x7f818181, 0x7f817f81, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x7f7f8181, 0x7f7f7f7f,
+0x7f81817f, 0x817f8181, 0x817f817f, 0x7f81817f, 0x81818181, 0x7f817f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+0x7f7f8181, 0x817f8181, 0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f, 0x817f8181,
+0x81817f81, 0x817f8181, 0x7f81817f, 0x817f8181, 0x817f8181, 0x817f7f81, 0x7f7f817f, 0x7f818181,
+0x7f7f817f, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f7f, 0x8181817f, 0x817f8181, 0x81818181, 0x817f7f7f,
+0x7f7f817f, 0x817f7f7f, 0x817f817f, 0x7f818181, 0x8181817f, 0x817f817f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f81, 0x81818181, 0x7f817f7f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x81817f81,
+0x81818181, 0x81817f81, 0x7f7f817f, 0x81818181, 0x817f8181, 0x7f81817f, 0x81817f7f, 0x7f81817f,
+0x817f8181, 0x81818181, 0x7f7f7f81, 0x81817f81, 0x817f7f7f, 0x817f8181, 0x7f7f817f, 0x7f7f8181,
+0x7f81817f, 0x7f818181, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x7f81817f, 0x817f8181,
+0x81817f81, 0x81818181, 0x817f8181, 0x81818181, 0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x81817f81,
+0x7f818181, 0x81818181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x81818181,
+0x81817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f7f, 0x8181817f, 0x81817f81, 0x81817f81, 0x8181817f,
+0x817f817f, 0x81817f7f, 0x7f817f7f, 0x817f817f, 0x817f7f7f, 0x8181817f, 0x7f7f7f7f, 0x817f817f,
+0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f7f,
+0x7f81817f, 0x817f817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x81818181,
+0x7f7f817f, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f8181, 0x81818181, 0x817f7f7f, 0x81818181,
+0x81817f81, 0x817f817f, 0x7f817f81, 0x7f7f8181, 0x7f7f7f81, 0x81817f81, 0x7f7f7f81, 0x817f7f7f,
+0x817f817f, 0x817f8181, 0x7f817f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f81,
+0x7f817f7f, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x7f817f81, 0x817f817f, 0x81817f7f, 0x7f81817f, 0x8181817f,
+0x817f7f81, 0x7f7f7f81, 0x81818181, 0x7f817f81, 0x81818181, 0x7f818181, 0x817f7f7f, 0x81818181,
+0x81818181, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f81817f,
+0x817f817f, 0x7f7f7f81, 0x7f81817f, 0x7f81817f, 0x7f818181, 0x817f817f, 0x81817f7f, 0x7f7f817f,
+0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x817f817f, 0x81817f7f, 0x7f7f7f81, 0x817f817f, 0x7f7f817f,
+0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x7f7f8181, 0x7f7f817f, 0x7f81817f,
+0x81817f81, 0x817f7f81, 0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x81817f81, 0x817f817f, 0x81817f81, 0x7f7f7f7f, 0x817f817f, 0x817f7f81, 0x81817f81,
+0x817f7f81, 0x817f7f7f, 0x81817f81, 0x817f7f81, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x8181817f,
+0x7f7f7f81, 0x81817f81, 0x7f817f81, 0x81818181, 0x817f8181, 0x7f7f8181, 0x81818181, 0x817f7f81,
+0x817f8181, 0x81817f7f, 0x8181817f, 0x817f817f, 0x8181817f, 0x7f818181, 0x81817f81, 0x81818181,
+0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x7f7f8181, 0x8181817f,
+0x817f7f81, 0x7f818181, 0x7f7f817f, 0x7f81817f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x817f8181,
+0x7f7f8181, 0x81817f81, 0x7f7f8181, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x81817f81,
+0x7f7f817f, 0x817f817f, 0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x8181817f, 0x817f8181, 0x817f7f7f,
+0x817f7f81, 0x817f8181, 0x8181817f, 0x7f818181, 0x7f818181, 0x7f7f7f81, 0x817f7f81, 0x7f817f81,
+0x81817f81, 0x817f8181, 0x817f7f7f, 0x817f7f7f, 0x81818181, 0x7f7f7f81, 0x817f817f, 0x817f7f81,
+0x81817f7f, 0x7f818181, 0x7f7f817f, 0x7f818181, 0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x81817f7f, 0x7f817f7f,
+0x7f7f8181, 0x817f8181, 0x7f818181, 0x8181817f, 0x81817f81, 0x817f7f7f, 0x7f817f81, 0x81818181,
+0x817f817f, 0x81818181, 0x817f7f81, 0x817f7f7f, 0x817f817f, 0x7f817f81, 0x7f817f7f, 0x817f7f81,
+0x7f818181, 0x817f7f7f, 0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x81818181, 0x817f7f81,
+0x7f7f817f, 0x81817f7f, 0x8181817f, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x817f7f81, 0x7f81817f,
+0x817f817f, 0x7f7f817f, 0x817f7f7f, 0x8181817f, 0x7f7f817f, 0x7f81817f, 0x8181817f, 0x7f81817f,
+0x81818181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f818181, 0x817f7f7f,
+0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x7f7f7f7f, 0x817f7f81, 0x81817f81, 0x817f817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x81818181,
+0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x8181817f, 0x7f7f7f81, 0x817f7f7f, 0x81818181, 0x81817f7f,
+0x7f817f7f, 0x817f7f7f, 0x81817f7f, 0x81817f7f, 0x817f7f7f, 0x81817f7f, 0x817f8181, 0x7f81817f,
+0x7f7f7f7f, 0x817f817f, 0x817f7f81, 0x8181817f, 0x817f7f7f, 0x7f817f7f, 0x8181817f, 0x81817f81,
+0x817f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f818181, 0x7f817f81, 0x81818181, 0x817f8181, 0x8181817f,
+0x7f817f7f, 0x817f8181, 0x7f818181, 0x817f7f81, 0x7f817f7f, 0x7f7f8181, 0x817f817f, 0x817f8181,
+0x7f81817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x81817f81, 0x817f8181, 0x7f7f7f81,
+0x8181817f, 0x8181817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x7f818181, 0x81818181, 0x7f7f7f81,
+0x7f817f7f, 0x81818181, 0x817f8181, 0x817f8181, 0x7f7f7f7f, 0x817f7f81, 0x817f817f, 0x817f7f81,
+0x81818181, 0x817f8181, 0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x817f8181,
+0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f818181, 0x7f81817f, 0x81817f7f, 0x817f8181,
+0x817f8181, 0x7f818181, 0x8181817f, 0x7f817f7f, 0x81817f81, 0x7f7f8181, 0x817f7f81, 0x817f8181,
+0x7f7f7f7f, 0x817f7f7f, 0x7f817f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x81817f81,
+0x7f817f7f, 0x7f818181, 0x817f7f81, 0x8181817f, 0x81817f7f, 0x8181817f, 0x7f81817f, 0x7f817f81,
+0x817f8181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f818181, 0x7f81817f, 0x7f7f8181, 0x7f7f7f81,
+0x817f817f, 0x81817f7f, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x817f8181, 0x81818181, 0x8181817f,
+0x81817f7f, 0x7f817f7f, 0x817f8181, 0x81817f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f817f,
+0x817f8181, 0x81817f81, 0x81817f81, 0x7f817f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f,
+0x81817f81, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f817f7f, 0x7f7f817f, 0x81817f81, 0x817f8181,
+0x81817f81, 0x8181817f, 0x7f7f7f81, 0x817f8181, 0x81817f7f, 0x81817f81, 0x817f8181, 0x817f8181,
+0x817f817f, 0x817f7f7f, 0x81817f7f, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f818181, 0x81817f81,
+0x817f8181, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x81818181, 0x7f817f81, 0x81817f7f, 0x81818181,
+0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x817f817f, 0x7f7f7f7f, 0x817f7f7f,
+0x817f7f7f, 0x7f817f81, 0x7f7f817f, 0x81817f7f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f817f,
+0x817f817f, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81818181, 0x7f817f7f,
+0x7f7f7f81, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f7f, 0x817f817f,
+0x81818181, 0x81818181, 0x8181817f, 0x81817f81, 0x81818181, 0x817f8181, 0x7f817f7f, 0x7f817f81,
+0x817f8181, 0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x7f817f7f,
+0x7f7f7f7f, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x81817f81, 0x817f8181, 0x7f817f81, 0x817f8181,
+0x81818181, 0x817f817f, 0x81817f81, 0x817f817f, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+0x81817f81, 0x7f81817f, 0x817f7f81, 0x7f818181, 0x81817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f,
+0x8181817f, 0x7f81817f, 0x8181817f, 0x81818181, 0x81817f7f, 0x7f7f817f, 0x81817f81, 0x8181817f,
+0x7f81817f, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x81817f81, 0x7f7f7f7f,
+0x7f817f7f, 0x81817f7f, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x7f818181, 0x7f7f8181,
+0x7f817f81, 0x7f817f7f, 0x8181817f, 0x7f7f7f81, 0x7f7f8181, 0x81818181, 0x7f7f8181, 0x7f817f7f,
+0x7f7f8181, 0x7f81817f, 0x7f7f8181, 0x81818181, 0x7f817f7f, 0x7f7f8181, 0x7f817f7f, 0x8181817f,
+0x7f817f7f, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x817f817f, 0x7f817f81, 0x7f817f7f, 0x81818181,
+0x7f817f81, 0x7f7f8181, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x7f817f81,
+0x7f81817f, 0x817f7f7f, 0x817f8181, 0x7f817f7f, 0x817f7f81, 0x7f7f7f7f, 0x7f817f7f, 0x7f817f81,
+0x817f7f7f, 0x817f8181, 0x7f7f7f7f, 0x817f7f81, 0x81817f7f, 0x81818181, 0x817f817f, 0x81818181,
+0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f,
+0x817f7f81, 0x817f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f, 0x81817f7f, 0x7f7f7f7f, 0x7f818181,
+0x7f818181, 0x81818181, 0x817f8181, 0x81817f7f, 0x7f7f8181, 0x817f817f, 0x7f818181, 0x7f7f8181,
+0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x8181817f, 0x81818181, 0x817f8181, 0x7f7f7f7f, 0x7f81817f,
+0x81817f7f, 0x7f7f8181, 0x81817f81, 0x817f7f7f, 0x817f7f7f, 0x7f817f81, 0x817f7f7f, 0x81817f7f,
+0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x817f817f, 0x817f7f7f, 0x817f8181, 0x81818181, 0x7f81817f,
+0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x81817f81, 0x817f7f81, 0x7f7f8181, 0x7f817f81,
+0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x817f8181, 0x8181817f, 0x817f7f81, 0x817f7f81, 0x7f817f81,
+0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f817f81, 0x81818181, 0x81818181, 0x7f7f7f7f, 0x81818181,
+0x7f817f7f, 0x81818181, 0x7f81817f, 0x7f817f81, 0x81817f7f, 0x817f7f81, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x7f7f817f, 0x7f817f7f, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x817f7f81, 0x7f7f7f81,
+0x81818181, 0x7f817f7f, 0x81818181, 0x7f818181, 0x817f7f81, 0x7f817f7f, 0x81818181, 0x81818181,
+0x7f817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f818181, 0x81817f7f, 0x81817f81, 0x8181817f, 0x817f817f,
+0x817f817f, 0x817f7f81, 0x7f7f8181, 0x817f7f7f, 0x817f8181, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f81,
+0x817f7f7f, 0x7f7f8181, 0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f817f,
+0x817f7f7f, 0x81818181, 0x8181817f, 0x7f817f7f, 0x7f7f8181, 0x81817f81, 0x7f81817f, 0x7f7f8181,
+0x817f7f7f, 0x817f7f81, 0x7f81817f, 0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x817f7f81, 0x7f817f81,
+0x81817f81, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x7f817f81,
+0x817f7f81, 0x7f7f817f, 0x7f7f817f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f817f, 0x8181817f, 0x817f7f7f,
+0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x81817f81, 0x7f817f7f, 0x7f81817f, 0x81817f7f, 0x7f7f7f7f,
+0x817f817f, 0x7f7f7f7f, 0x7f81817f, 0x817f8181, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x8181817f,
+0x817f817f, 0x81818181, 0x81817f81, 0x81817f81, 0x7f7f8181, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f,
+0x7f817f81, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x81817f7f, 0x81818181, 0x7f81817f, 0x7f7f7f7f,
+0x81818181, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f8181, 0x81818181,
+0x81818181, 0x7f7f8181, 0x7f817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f81, 0x7f7f817f, 0x817f817f,
+0x81817f7f, 0x7f7f817f, 0x7f7f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f8181,
+0x7f817f7f, 0x7f817f81, 0x817f8181, 0x817f7f7f, 0x7f818181, 0x7f81817f, 0x817f817f, 0x7f7f8181,
+0x81817f7f, 0x7f7f7f7f, 0x817f7f81, 0x8181817f, 0x81818181, 0x7f817f81, 0x7f817f81, 0x7f81817f,
+0x7f81817f, 0x7f7f817f, 0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f7f7f7f,
+0x7f81817f, 0x7f7f817f, 0x817f817f, 0x817f817f, 0x7f817f7f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f8181,
+0x817f7f81, 0x7f7f7f81, 0x7f818181, 0x817f817f, 0x7f7f817f, 0x7f817f81, 0x817f7f81, 0x81818181,
+0x81817f81, 0x7f7f7f81, 0x7f817f7f, 0x7f818181, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x7f81817f,
+0x817f7f81, 0x81818181, 0x7f817f81, 0x7f7f7f81, 0x7f81817f, 0x7f818181, 0x7f817f7f, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f7f817f, 0x817f8181, 0x81818181, 0x7f81817f,
+0x81817f81, 0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x817f7f7f, 0x8181817f, 0x81817f81, 0x81818181,
+0x7f817f81, 0x7f7f7f7f, 0x81818181, 0x7f7f8181, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x7f7f7f7f,
+0x7f7f7f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f81, 0x817f8181, 0x7f7f817f, 0x7f7f7f7f,
+0x817f817f, 0x8181817f, 0x817f8181, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f81817f, 0x7f7f7f81, 0x817f8181, 0x81817f81, 0x817f7f81, 0x7f7f817f, 0x7f81817f, 0x7f7f7f7f,
+0x81818181, 0x81817f81, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x7f81817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x81817f7f, 0x81818181, 0x817f7f7f, 0x7f7f7f81, 0x817f7f7f,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f81, 0x7f818181, 0x81817f7f, 0x817f817f, 0x7f81817f,
+0x817f7f81, 0x7f81817f, 0x8181817f, 0x7f7f7f7f, 0x8181817f, 0x7f7f817f, 0x7f817f7f, 0x817f7f7f,
+0x7f818181, 0x817f8181, 0x7f7f817f, 0x817f7f81, 0x7f817f81, 0x81817f81, 0x7f7f8181, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f7f81, 0x81818181, 0x7f7f817f,
+0x817f8181, 0x7f81817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x81818181,
+0x81817f7f, 0x7f817f7f, 0x817f8181, 0x7f7f8181, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x7f817f7f,
+0x7f817f7f, 0x817f817f, 0x817f7f81, 0x81817f81, 0x7f7f8181, 0x817f7f7f, 0x7f7f8181, 0x81817f81,
+0x7f817f7f, 0x817f8181, 0x817f817f, 0x81817f81, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f81, 0x7f81817f, 0x7f7f8181, 0x81818181, 0x817f7f7f, 0x7f81817f, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x7f81817f, 0x817f8181, 0x7f7f7f7f, 0x7f81817f, 0x7f818181, 0x817f817f, 0x81818181,
+0x7f818181, 0x7f817f81, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x7f81817f, 0x7f7f7f81,
+0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f818181, 0x81818181, 0x817f7f81, 0x817f8181,
+0x7f7f7f7f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f81, 0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f818181,
+0x81818181, 0x7f7f817f, 0x81818181, 0x7f818181, 0x7f817f7f, 0x7f817f81, 0x7f7f8181, 0x81818181,
+0x7f7f7f81, 0x817f8181, 0x7f7f7f7f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x7f817f7f, 0x817f817f,
+0x7f817f81, 0x817f8181, 0x817f817f, 0x817f817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81,
+0x7f7f7f7f, 0x7f7f7f7f, 0x8181817f
+
+e =
+34560
+
+k =
+6144
+
+rv_index =
+0
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_SOFT_OUTPUT, RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE, RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN,
+RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_posllr.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_posllr.data
new file mode 100644
index 000000000..13ad0908c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c1_k6144_r0_e34560_sbd_posllr.data
@@ -0,0 +1,1225 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0xf6bb1100, 0x4e433af1, 0x38f02efa, 0x0ee43d00, 0x5037c35f, 0x5620e729, 0xdd46c4d7, 0x5ae3e2f7,
+0xe0d7fa2f, 0x2e4ae20d, 0xa7190ebf, 0xd2382614, 0x98ffabe0, 0xf7ee0c5d, 0xffd8ddd7, 0x5f03ecc7,
+0xf9ffdde5, 0xf12446f6, 0x42693a3d, 0xfcc81aae, 0x2b0abc2c, 0x43f2a1b5, 0x044a302c, 0xf8db4fa6,
+0xcad2d138, 0x452b5526, 0xf3083fd3, 0x30ea4b22, 0xe2bd66f4, 0xbc37bebe, 0x001e183b, 0xfac72ebf,
+0x11965cf5, 0x70226311, 0xbd2016ec, 0xcf23f931, 0x4629f6fb, 0x3104de76, 0x00d7c529, 0xa0c8f8f4,
+0x2615c2e0, 0x23daf4b4, 0x56bf05c4, 0x9212102c, 0xa5fe400d, 0xec2a5497, 0x021032bc, 0x3b55340e,
+0xd6f1003c, 0x2a3625d0, 0xc81eee31, 0xa26644d7, 0x0ffb041c, 0x22cc20dc, 0x472cdd9b, 0xd8e24ed2,
+0x4ee740ab, 0x9bfc50e2, 0xbaaafe55, 0xeecd5c19, 0x57150c31, 0x9d3f13c1, 0x251749e1, 0x076ca964,
+0xde0da74b, 0xcafac963, 0x52d006e2, 0xe392d7f4, 0x3a20bcf6, 0xd1ee6fce, 0xe5cf850a, 0x31253fe7,
+0xcefed8a9, 0x520f9824, 0x5fdbe3c9, 0x9b123cc5, 0x6ad019f2, 0x171f0368, 0xc2fe2855, 0x0db851c2,
+0x095010d9, 0xd110df25, 0x1452a52c, 0xe5d1c2cc, 0x45dbef40, 0x2aef2353, 0x07af2e2a, 0x4f23ff6f,
+0x3ddb31cb, 0xa8430c49, 0xcaf7b329, 0xf933c5bc, 0xfe3c52b3, 0x7fd60a27, 0xce0ac9cf, 0xcff0cdd7,
+0x5400cd01, 0x7f81a8c1, 0x3c7f8178, 0x737f87f6, 0x5a5e7f81, 0x817f6ff6, 0x813b1381, 0x41d18173,
+0x810fb9f9, 0xb734c526, 0x50b3a6d3, 0x282d6e50, 0x81972d1f, 0x7d52bd53, 0x6749268b, 0xc681812d,
+0x2c93912e, 0xb1813bdc, 0xed817fd1, 0xa8813376, 0x7f3c7f41, 0x64569f7c, 0xf53d5c67, 0x1e70e6dd,
+0x024b6591, 0x817f7f8f, 0x0a722d63, 0x7fed578b, 0x7f239a7f, 0x81029081, 0xa8ca8b81, 0xb8577fde,
+0x818ec07f, 0x7fa87cb9, 0xa7084967, 0x81934650, 0x7f8171f7, 0xed3d144a, 0x8107739c, 0x3c6fe27f,
+0xcd6ed165, 0xfb3718a4, 0x5f708f4d, 0x14e45eb2, 0xfe5c7f7f, 0x7fc57f6a, 0x813683af, 0x817f7fb3,
+0x007fa7ef, 0xdcd681a1, 0xd72a1268, 0x769f7881, 0xb27fa281, 0x89c27fe3, 0x729b2f59, 0x73afb8a0,
+0xd07f4eb8, 0x81dd6d55, 0x7fa3d2cf, 0x7f81b51e, 0x7f7f7be7, 0x60819981, 0xf31158ad, 0xde7fe4b4,
+0x427f2dd3, 0xd3812481, 0x280de7a4, 0x0a653fc6, 0x8181261f, 0xd6aa8f81, 0x2c7fe484, 0x42df747f,
+0x7f5baa2d, 0xc1bd583c, 0x966b5031, 0xbe818725, 0x6b6444a4, 0x610023e7, 0x5f183b2c, 0xa77fb769,
+0xb2cb1581, 0x0881cc75, 0x8a8c6fdc, 0x558181e4, 0x107f947f, 0x749e4ca3, 0x8cb23db1, 0xce668132,
+0x70b848eb, 0x008a2430, 0x7fd3d77f, 0x682b35eb, 0x2e6aae34, 0xd42fa2cd, 0x3eab816f, 0xfdaf8196,
+0x04e43fcc, 0xf1819600, 0x7f6d64f2, 0x81ba8957, 0x81a781a2, 0xb169d67a, 0x7f4e557f, 0xe0818197,
+0x7b474ecc, 0x3f7b8154, 0x135684f8, 0x81b0fb81, 0x81e33e93, 0x815c817f, 0x810b818a, 0x4d445b34,
+0x95cf2bb0, 0x32c69b7d, 0x2640e181, 0x7fe8b8c8, 0x9bdd64f7, 0x22bfa50b, 0x8181c87f, 0xf7812486,
+0x7f977fa0, 0x5826a925, 0xce7fadf6, 0x9e73fb81, 0x538d7f0e, 0xe85dab87, 0xc3706181, 0x4181817f,
+0x7f7f15ca, 0x952ca87f, 0xa9748be0, 0xbf812477, 0xd081a553, 0x9a817f7f, 0x1f4cb192, 0x7f8181d5,
+0x2ba44ad2, 0x76605566, 0x7f1cd2b9, 0x446eae90, 0x8956b670, 0xaadc8b7f, 0x710b0a90, 0x83816439,
+0xc6ffc6d2, 0xf07f00fb, 0x7fa25582, 0x7fd11f3a, 0x7f104c81, 0x81d574fd, 0x81814081, 0x82b78e7f,
+0x2f29f42b, 0x277f4bff, 0xf49d4b81, 0x28581681, 0x22523281, 0x607ff910, 0x61ac1ad2, 0x58313ccf,
+0x8168a21f, 0x7fe61879, 0x817f21b3, 0x407f2f45, 0x7f5fa666, 0x81bc41fb, 0xfd81fb81, 0x0ed48163,
+0x81818181, 0x7f7b92fd, 0x44507d7f, 0xba45c9d3, 0x81852b64, 0x7fa918eb, 0x5f6ff5c6, 0xa4ad8181,
+0xc27f8f81, 0xb8af5481, 0x7fc5817d, 0x7a814ea2, 0xf77fcf36, 0x50913981, 0x81a01781, 0x5ea1a4ba,
+0x18d252b8, 0xc0416881, 0x7f817f1e, 0x0b4e38cf, 0x7ffb6922, 0xfca481b5, 0x7f1dc1ca, 0x7f560da2,
+0x7f7f813a, 0x1900a881, 0x6d4d8116, 0x617f0469, 0xb3118e81, 0x95408119, 0x817ff08a, 0x7fdc7f8b,
+0xf682a40a, 0x3381817f, 0x81b70d82, 0x7f7f6f81, 0x8190217f, 0x2f817f4b, 0xe195b209, 0x5ee39575,
+0x8150bae6, 0xa4fe8b7f, 0x7f7f654c, 0x7f921971, 0x53817f85, 0x1c7f5ff6, 0x5f35737f, 0xce7fc2c6,
+0x6c81817f, 0x7f7c410d, 0x5794308e, 0x15f4a87f, 0x7fb64d7b, 0x1d0a8181, 0xa8b67f37, 0x253b397f,
+0x887f92b7, 0x7f81767f, 0x81c18101, 0xaa2861c0, 0xbd691cd9, 0x81d74ef3, 0x81a78153, 0xcb7f819b,
+0xf681c5e7, 0x9f37817f, 0x3a7f869b, 0x56a41581, 0x04be8111, 0x4898b48b, 0xbc81465d, 0xb3815281,
+0x7f6a1d45, 0x1fa87fce, 0x810e81cc, 0x7f8d410c, 0x8190a193, 0x81817f81, 0x5dadcbb4, 0x81a83699,
+0x86a68164, 0xe27f1281, 0x682a7f27, 0x62a03cbd, 0x8181c75d, 0x39653881, 0xc6187e83, 0x617fd27f,
+0x81917f90, 0x57796c81, 0xdc7f567f, 0xad712381, 0xdd81ecbe, 0xec17667c, 0x929e5098, 0x857ffbbf,
+0x8d5b8153, 0x9769887f, 0x65173381, 0x66b8ad84, 0x043481b9, 0x81c05ca9, 0x449d4c48, 0x8c45bc82,
+0xca7f81ee, 0x2d8f33e1, 0x81e22f81, 0xca9eb542, 0x8e947fe5, 0xb642a4a8, 0x7f22c73f, 0x85a6176a,
+0x567f7ffb, 0x587f4243, 0xa2819225, 0x58307f9b, 0x2c6b0f81, 0x8130a068, 0x814fa904, 0x400a9f2d,
+0x30617fd6, 0x81720981, 0x97b98100, 0x0ca17c7f, 0xf1816081, 0x690f8181, 0x94165481, 0x81817f9d,
+0x81444268, 0x97759781, 0x8740267f, 0x757f1a7f, 0x7f7f81ca, 0x957fb87f, 0x816f723a, 0x4a8613f2,
+0x3bfef57b, 0x7f1274e8, 0x810ab05b, 0x7fb19ecd, 0xb07fc75f, 0x7fb2965f, 0x60abb881, 0xc229a8e9,
+0xb1817f26, 0xe324067f, 0x8181e344, 0x7ea59cac, 0xd21a7f65, 0x8d15989f, 0x09026bea, 0x1d7f933b,
+0xae81c181, 0xabf37147, 0x0d08da7f, 0xa7ac4b9e, 0x8281e044, 0x7f8195b1, 0x7ff844de, 0xe9057fed,
+0x85fcf1cd, 0xa89e7e2b, 0xf974a481, 0x1f813c6d, 0x237fcbbb, 0x655f8192, 0x8134062b, 0x6f91815d,
+0xdf3281e1, 0xe6fd817f, 0x72b3007f, 0x86caf9cf, 0xea812981, 0x6a8ad67c, 0x36aaa01d, 0xbb102886,
+0x812faf52, 0x6281de5a, 0x817f8174, 0xebff4735, 0x7894bf7c, 0x169e8194, 0x3bc281f8, 0xe69d2a15,
+0xb8e5b68d, 0x367f9b8b, 0xea818181, 0xeb7fbbb7, 0x9368a27f, 0x5af5e19e, 0x5f7f7f7f, 0xcd518181,
+0x7f948109, 0x817f4a81, 0xf8a0de7f, 0x667f7fa5, 0x1a8881c1, 0x8646b17f, 0xb0eb7f81, 0xe3fe2ba2,
+0x460d18da, 0x3db45835, 0xb0c2847e, 0x9c8681a0, 0x817ff88d, 0x7fec639d, 0x817f7f7f, 0x81810d2f,
+0xef28241e, 0x811d9db4, 0x4ac4ada5, 0x7ff29f7f, 0x7fd981ac, 0x7f815e23, 0xcc3dbc8a, 0x7c769b08,
+0x6a07ef50, 0x66599c9c, 0x7e007f92, 0x9381aa5a, 0x33471b81, 0x79b27d96, 0x6d5d9d5a, 0xbf40687d,
+0x7fbc408e, 0xae598111, 0x18222b1e, 0x0a7b817f, 0x7f4961b4, 0x81818f5e, 0xd5a8ae44, 0xe185bd50,
+0xb4a65d81, 0xab81c3d6, 0x5f814b7f, 0x8db72efc, 0xc0be14d5, 0x77336a45, 0x2dca7e7f, 0x81857f7f,
+0xf1d80b33, 0x1856b3dd, 0x789e75cd, 0x7f7f7f81, 0x8b7f6951, 0xc94cc5b6, 0x407f3f5b, 0x72c4b87f,
+0x8135f77d, 0xab02ec1c, 0x8db481e0, 0x77da84df, 0x897f5c49, 0x8181b24d, 0x7f54715e, 0x233ef77f,
+0x8165daa7, 0xd3813aa2, 0x7f7f7f18, 0x96e99677, 0x56814a72, 0xa4acba2e, 0x2683347f, 0x3d5b20ac,
+0x887fb981, 0x90a9ec91, 0x008ab581, 0x81588181, 0x5c017f7f, 0x10818181, 0x5d86a42d, 0xd8587f4f,
+0xed2035b1, 0x718168fc, 0xc3cccf7f, 0xaa812676, 0xa8d83930, 0xbdb119f6, 0x812b0288, 0xe17f7f7f,
+0x989ffd31, 0x9e564b12, 0xabfa3578, 0xacd85381, 0xaf7074e6, 0x93a34c11, 0xc1819896, 0x5a5fa673,
+0x6f8181ad, 0x4981167a, 0x817f965e, 0x961b7f29, 0xac539db6, 0x2b645dd8, 0x937fa506, 0xa1b900ba,
+0xdd7f7f78, 0x7f866ce7, 0x81a9247f, 0x50d67f53, 0x177a8b82, 0x277ffa7f, 0x7f0942da, 0x444b3181,
+0x9d8995aa, 0xbda844b9, 0xae765c85, 0x62818f7f, 0x307f7f00, 0xf37fe681, 0x817f7fab, 0x42e0813d,
+0x49f3c7c4, 0x7fd543b8, 0x818183f2, 0x7f4b5500, 0xe2357a7f, 0xdc3a8133, 0xd13913ff, 0xabfd587f,
+0x81c3814c, 0x667fab62, 0x9bf82b0c, 0xf84b9583, 0x6a28b2f0, 0x8154623f, 0x7f845e7f, 0x2750f07f,
+0x517f2d59, 0x7ffe4db5, 0x60077f7f, 0x81816e62, 0xc40a30dd, 0x67f22b7f, 0xec817f81, 0x7fb8c67f,
+0x98c9afd0, 0xb881ecaf, 0x6069c37f, 0x792c2c09, 0x709dc2de, 0x4481bb20, 0xd4b25981, 0xf8ef7792,
+0x7381ae17, 0x7fe05250, 0xc3eb637f, 0x6d350069, 0x327f457f, 0x8ce7b8ab, 0xb281c1da, 0x7f817f61,
+0xbbcf7fb1, 0xaf818145, 0xb77f5881, 0xb47ff1b2, 0xcec74a81, 0x5f81e7b4, 0x7f1b727f, 0x81b8701b,
+0x508106c4, 0x6d815f7f, 0xbc815bea, 0x464b00f2, 0x78818181, 0x7f7f4f81, 0x817e2c53, 0x817e7fa7,
+0x7f4da4a9, 0xdd444f23, 0x7f6cba39, 0x8141625a, 0x7f81813f, 0xcd7f817f, 0xa402814a, 0x817f049f,
+0x6fb981b4, 0x7867bd7f, 0x9b45bc81, 0xe7739f52, 0x7f816181, 0xab844448, 0x7f06497f, 0xe555c183,
+0x817fde68, 0x81bc0624, 0xe33f3a9b, 0x8122c673, 0x6c3d81d5, 0x392815dd, 0x26527f7f, 0xee649844,
+0x817f6fef, 0x81ce32d4, 0x102f81fe, 0x81967f81, 0xa42b9c20, 0x81813c81, 0x2a67a463, 0x90592c8a,
+0xc5810e67, 0x81d1dd81, 0xbd7f54e1, 0xf52a814e, 0x7f46a7b3, 0x5a89812b, 0x78e43eac, 0x7f776981,
+0x817fc5c2, 0x3f818181, 0xc556c337, 0x7f0081a9, 0x817ffe6b, 0x7f095f3d, 0x819b2281, 0xb45881ad,
+0xc0817f47, 0x81bd915a, 0xc7616b7f, 0x81e9817a, 0x44977f6c, 0xbc81307f, 0x7f9ac3c9, 0xff061265,
+0x3c7b0181, 0x13910e7f, 0xb499ed3c, 0xd850b881, 0x81781837, 0x7f97ff93, 0x81818f23, 0xb9b50d81,
+0x49aa4fbd, 0x6b361230, 0x148179d3, 0xbd81dd1f, 0x4cd5d0d0, 0x9ad1738a, 0x2c7f718f, 0x7f9f03b0,
+0x789d9ac2, 0x88db95fa, 0x9ae5ac64, 0x727f814c, 0xfa477dac, 0xa670a23f, 0x146afe7f, 0xd4d0451d,
+0x6d81819d, 0x9622acc1, 0x818161a2, 0x68263dca, 0x7fce818d, 0x998193ba, 0x9d81a486, 0x7eb97f7f,
+0x134470ec, 0x6681bde5, 0x4e2ea77f, 0x81777f7f, 0x7f7fa64f, 0xd3815a7d, 0x81fd4e50, 0x774481e8,
+0x7f6c8148, 0xe76b7f81, 0x881bb4e9, 0x7f944f3d, 0xe6da7f20, 0x54c68176, 0x210ebb45, 0xbed6267f,
+0xe22f2081, 0x8191ae8a, 0x7c7f257f, 0x667f811c, 0xe2edd355, 0xa4812181, 0x837f5481, 0x6d818120,
+0xb7aa7f8f, 0xc17f7081, 0x7fba986a, 0x819a81d5, 0xa9816681, 0x8129c4f5, 0x37ba21a7, 0x29d18a86,
+0x4be3ce96, 0x3981b184, 0x447fb50b, 0x261c8155, 0xc05ab18d, 0x777f7816, 0xe48be469, 0x81722d81,
+0x7f47a8a1, 0x924a8b72, 0xa2ef4ecd, 0x105c817f, 0x7f90709b, 0xbc81443a, 0xa82f7f65, 0x615d928c,
+0x7f81570d, 0x61b0919a, 0x7f33fc81, 0xe8817fca, 0x637ffb00, 0x9c337250, 0x817f8181, 0x08b01e0a,
+0x7f4ae897, 0xa0969a3c, 0x7f9d7fe8, 0xe024598e, 0x9e794d7f, 0x72fb988c, 0xf8936747, 0xacbd7f8e,
+0x4e7f9781, 0xa4b9f4ea, 0x50ccfbdd, 0x817f4795, 0xbcaf485f, 0x81811a25, 0xa97881c6, 0xecbd7fd7,
+0x6e89a832, 0x1e815f96, 0x74d0437f, 0x858101b9, 0xbf1b7f8b, 0xcb7fdc9e, 0x1901bda8, 0x4c40c087,
+0x5884f075, 0x7f561faf, 0xc3878172, 0xcd0081c4, 0xd93e8fa6, 0xe8748146, 0x4c7f207f, 0x20da2792,
+0xc0d37f7b, 0x909a0133, 0x3b6fb281, 0x69819ba1, 0x81984b27, 0x362ddda3, 0x3981727f, 0xe44c7f81,
+0x81b9d0bc, 0xebea7fa7, 0x81a47f2e, 0x81674391, 0x495500fa, 0x0eb881bf, 0x2e22f17e, 0x967f9e81,
+0xd2727906, 0xdbe8814d, 0x93cf4d6d, 0x23c3b57f, 0x57be5fe3, 0x2eee7f30, 0x1a501f81, 0x76aaba53,
+0x70817fdc, 0x817f2e1e, 0x28381f81, 0x1575817f, 0xc62845e6, 0x8181417f, 0x35d0230c, 0x606fcc28,
+0x7f792e44, 0xb7b7ea76, 0xad677f7f, 0x2b1eecee, 0x7f7fe450, 0xefcc6668, 0x264e511c, 0x27818181,
+0x81817f7f, 0xce82812c, 0x697f7fec, 0x7e859be9, 0xa1f65543, 0x8170a57f, 0x51231d81, 0x33c03182,
+0x81aa7f81, 0x6b7ff34e, 0x51812fcf, 0x7f7f7fe6, 0x6281718d, 0x1eb02c7f, 0x81d64570, 0xa18368e1,
+0x4ddb816f, 0x149b81d1, 0x067fa2c6, 0x92decc7f, 0x94001658, 0x814f6d6c, 0x79673f7f, 0x7ff28122,
+0x83b97f7f, 0x81248a43, 0xfda17ffe, 0x9e81bc81, 0x81090181, 0x7fdaa350, 0x927f54d4, 0x78fe2e89,
+0x7f3d097f, 0x147f2ea7, 0x7f85837f, 0x86a58181, 0xb7ad559c, 0x7796ae60, 0x4e7fef08, 0x2ea371f2,
+0x817f7f8c, 0x7fc181c5, 0x8101818e, 0xf1588178, 0x44062eb8, 0xb0832da0, 0x81527f81, 0x7f0e817f,
+0x8e06b3e5, 0xa6df2e5f, 0x9d7f7f81, 0xa14ba64d, 0x723d7f91, 0xdb81b64b, 0xb48c117f, 0xe75d0e81,
+0x8bd9ba3a, 0x1f817f7f, 0x81847f67, 0x25677f5f, 0x3568b529, 0x7fa2587f, 0x24b02027, 0x47ca91dc,
+0x81bba314, 0x7f844f7f, 0xbeb8aa0d, 0x9955fe5b, 0x007f9b81, 0xf0a27f6f, 0x1648e959, 0xc68193a6,
+0xbea6ebfd, 0x1654cf81, 0x8142d430, 0x2e7f6693, 0xcc788195, 0x11817f81, 0x3da98171, 0x4fdc5a9c,
+0x677fea81, 0x4c6ca0cf, 0x487f8181, 0x7f3b9013, 0x37387f7f, 0xc6b4217f, 0x27afb97f, 0x77b84002,
+0xd3a67fef, 0x987f8181, 0x9518817f, 0x5ad4fd7f, 0x7b818146, 0x583c5581, 0xd9643b81, 0x687f92f5,
+0x7f8109f2, 0xdfad937f, 0x79a45f7f, 0x007f9c0e, 0x6a6ba6ad, 0xa95bc7e9, 0x9be90653, 0x223381b7,
+0x7f7f64ce, 0x81813ea3, 0x037f4f7f, 0x617f7f9a, 0x6481f081, 0x81eb4a81, 0x7f9d9a6e, 0xe80e8a4b,
+0x4563f81e, 0x94db8781, 0xbf81bd04, 0x305d8236, 0x2c90d571, 0xa48e4600, 0x81633342, 0x2c537fde,
+0xc70f5d7f, 0x65bf6f7f, 0x547f9632, 0x05847f1a, 0x23818147, 0xd6d9459f, 0xc97fb761, 0x8196816d,
+0xb5417f5b, 0xb6f91bd9, 0x55b17fbd, 0x3e90c27f, 0x4f7fc37f, 0x7f8c855d, 0xef35817f, 0x295d7b03,
+0x3730377f, 0x9c811bac, 0x7fe3ca7f, 0xe87f8124, 0x7f7fe511, 0x2d7f7ca2, 0xba9bc726, 0xf07f9f81,
+0x4b476e9f, 0xaa338173, 0x5659708a, 0x817fb67f, 0x81811ded, 0x81817f90, 0xa3077f81, 0xf0d119d6,
+0xf4818752, 0xbd98271f, 0x95f610ed, 0x3fc227e0, 0x68139681, 0x3c6c2d81, 0x7f7f96cb, 0x3e8181b1,
+0xbbe681c6, 0xb47fd2eb, 0xfdd1b74f, 0x4381fe5f, 0xb081f399, 0x64a10081, 0x79ee3ee5, 0x9559c8a6,
+0x814ad4a8, 0x817f7531, 0x81813b81, 0xbfbf9773, 0xe27f81a4, 0x7fc14269, 0x917f8158, 0xaf9d89a7,
+0x81b22f81, 0x7f54d4d8, 0x0f39a503, 0xec9d3ea0, 0x35818131, 0x8c7d99a6, 0xc0158181, 0x53817f5e,
+0x817f81b0, 0x9a7f9a7d, 0xc081747f, 0x517f704d, 0x7f2db90e, 0xa6dfa67f, 0x36817fce, 0x30ae720e,
+0x7fd73d60, 0x5c593bd5, 0xf57f9d7d, 0x448151a3, 0xc82db29a, 0x019b5a75, 0x7f876729, 0xa69efc9d,
+0x78a67f81, 0x536c817f, 0x81e470d4, 0x56f270fd, 0x2934478f, 0x9c5a7f68, 0x4ecd81ef, 0x7f5c2b23,
+0x7f817f03, 0x827fb17f, 0x7f81c35e, 0x7d7f03f8, 0x7f5da67f, 0x8100671d, 0x06e1a8b0, 0x998d112a,
+0x9282ae98, 0xed72813b, 0x7fbc6bda, 0x7fa97f3e, 0x36d1510c, 0x0d81819c, 0x56f8fd97, 0x815081a4,
+0x7fc78133, 0x69d34542, 0x7fc1727f, 0x7fd22a97, 0x418a1df0, 0xf519077f, 0x7f6e697f, 0xa9817abc,
+0xf43917b5, 0x82e3d76b, 0x86327fe7, 0x7f7fb899, 0x9f81b0a4, 0x475381c2, 0xc62b92e8, 0x7f1b49a3,
+0x3679b9d7, 0x817f5364, 0xa87f7fc2, 0x45dcf6ba, 0x3470789d, 0x913e7fa5, 0x06b53681, 0x717f8de7,
+0x027f6352, 0x7f7fbe7f, 0x7a81df17, 0x0356fb00, 0x307462bf, 0x6716c56c, 0x8157c7b4, 0x7fcd8181,
+0x4b81dd07, 0x3b667f7f, 0x7fa6815c, 0xea37397f, 0x61e94781, 0x4e7f8177, 0x81436b5b, 0x4e818172,
+0x5b204b37, 0x115501b4, 0x81491681, 0x661468bf, 0x501f88b5, 0x7f4e63e3, 0x8146e97f, 0x7f09f895,
+0x7fd70e81, 0x7f7f7f16, 0x3f327fed, 0x05055631, 0x63b4ec13, 0xc03f16da, 0xa0af33c1, 0x942a7f42,
+0xb4ba6515, 0xe99d81de, 0x7f78d8b0, 0x446f2c42, 0x92cf7fde, 0x6b9e7f7f, 0x948181cd, 0x94b9ad81,
+0x582e8181, 0xc31748a9, 0x39c6d47f, 0xb2817fff, 0xc5817f81, 0xc6887fa4, 0xe69989e4, 0xa67e7a5c,
+0x09477f9a, 0x2d4d817f, 0xb24f81d1, 0x3ff77f7f, 0x6a66813b, 0xf5050547, 0xcf917f6c, 0x81917f7c,
+0xb8b23b81, 0xcab60081, 0xe17f7f81, 0x3b47547f, 0x457f4781, 0xe17e9c85, 0xd4b5ba00, 0x777fc3f4,
+0x8b013d8c, 0x5381a2dd, 0xf60c7f5b, 0xc3f2c212, 0x5c6c7f35, 0xc77fae7c, 0x7f790cc8, 0xe6848181,
+0x7f81584b, 0x813688e2, 0x4cff2987, 0xbeb48126, 0xc4be67bc, 0xb8738181, 0x886a9c7f, 0x519881a3,
+0x77fbd5c9, 0x4181c081, 0x20813287, 0x6121bb2d, 0x7f7f227d, 0x1a8181a6, 0x811a5d06, 0xc890a57f,
+0x7faf7ece, 0x83a36788, 0xd9fd8e37, 0x7f7b985e, 0x36819a38, 0xbd6096c4, 0x7de5be7f, 0x7bc68150,
+0x7f8831bb, 0x81818144, 0x434a63e0, 0xaea4ad6e, 0x407f2785, 0xe8df81ea, 0x4a148aa7, 0xf89f7f65,
+0x3c757f62, 0x7f81c80e, 0x81818881, 0x81caa47f, 0x9c570881, 0x1c1a8354, 0x2fa8008d, 0x7f7f81ac,
+0xa781d413, 0xa9a45530, 0x327f297f, 0x7f647f5c, 0x81a6324e, 0x81a954cd, 0x7f1c2881, 0xe30b2eb3,
+0x81b18181, 0x81157f18, 0x967f7f96, 0x819a7fbc, 0xcccf4fc2, 0xc43a48d5, 0x7fa33d74, 0x3aa97f50,
+0x5277817f, 0x69afad86, 0x7f81f278, 0x4fa29716, 0x91818170, 0xdc1a7f5c, 0x278159b1, 0xe87f069f,
+0xd28cc56b, 0x157f8181, 0x81339981, 0xcf818114, 0x6eba0b8d, 0xd281527f, 0x8249d583, 0xb37fbc43,
+0xc181357f, 0x819f6163, 0xaf194881, 0x7f9872a4, 0xf3c3ab2c, 0x47507f81, 0x523f812e, 0xff81d105,
+0x5851cbb0, 0x7fe881c3, 0x60cdbe81, 0xc838ccbe, 0x81817f7f, 0x1d76cb34, 0xe100407f, 0x81d78181,
+0x2f81817f, 0x927f3ac9, 0x3cc887bb, 0xda7d6d7f, 0x2c7f1e7f, 0xf58e41ee, 0xfb816281, 0xa211d47f,
+0x6eea4bf9, 0x297097b8, 0x9d819e81, 0xf6ef4156, 0x2afb4362, 0x7f16647f, 0x8e10c4c3, 0xb17f6181,
+0x3b9d2949, 0x53a6c867, 0x810faffb, 0x8197d27f, 0x41873a37, 0xc48d7f7f, 0x81b6fb69, 0x144b2b78,
+0x8181d5c4, 0x787fbc24, 0x4381929f, 0x95927f1b, 0xa3a5e451, 0xb48cc58d, 0x818e81d1, 0x9a81cbaf,
+0x713ac87f, 0x7faaa694, 0x9f7f81c3, 0xf65b307d, 0x7fdfa25e, 0xa0bae1fe, 0xf3813f12, 0x19817fc5,
+0xc0278a81, 0xe47f8158, 0x817fa281, 0x5bbc8181, 0xd63caaf9, 0x7fbf8181, 0x0054157f, 0x7f7f311c,
+0x7f817f56, 0x56c22692, 0x8143b624, 0x0845a315, 0x107a8119, 0xc1cd5c7f, 0x7f62e549, 0x7fbb757f,
+0x6b8dec74, 0x6893e220, 0xbb224ba9, 0x31819871, 0xdd2b4f57, 0x3d030250, 0xc1539dc4, 0x1c42df45,
+0x7f7f6631, 0xaa81eb8f, 0xa6d4edf5, 0x81ec1981, 0xc92d77f8, 0x1ba35b2c, 0x0e1fa0cd, 0xdd257f7f,
+0x817fa041, 0xe9815f81, 0x60f1b338, 0xb97f7fad, 0x097f857f, 0xae6a7f60, 0x145dbced, 0x81b7607f,
+0xd4647f3d, 0x7f7f52ec, 0x7fdbbea1, 0xc74feec6, 0x1c197f48, 0xb17d1d61, 0x2e68b081, 0xb717d181,
+0xda46377f, 0x105e81b7, 0x7f2e7f58, 0x67c33a7f, 0xb83f666b, 0x68518691, 0xc556f081, 0x7763c400,
+0x817fbc99, 0x3a18df21, 0xfbde9374, 0x667fc646, 0x737f7fe9, 0x7f987fbe, 0x27dcb107, 0x25f35d30,
+0x420adcd0, 0xab7a7f7f, 0x7f8a28c1, 0xcd7fc20e, 0x6ce69bcc, 0x7f308ce5, 0xb2c96e81, 0x95dbeb1e,
+0x7f7f567f, 0x6b7fa0a5, 0x997fed60, 0x9281da7f, 0x3f7f617f, 0x7fc4608e, 0x817f4781, 0xc36b7f81,
+0x7fddc17f, 0x6fe27020, 0x8a5a2b27, 0x3a4bfb81, 0xae9e4a81, 0x7f7fda7f, 0x5a7ff006, 0x39b6a0b7,
+0xb9721181, 0x725edb2f, 0x8903cf08, 0x81aa7cde, 0x7fe0817f, 0x6c9e7fe8, 0x7f5c8140, 0x819d8181,
+0x58777451, 0x7fdb4784, 0xc3186166, 0x817f458f, 0xdce8cdc9, 0x7840bd81, 0x1781954b, 0x60240082,
+0xca242d7f, 0x788428b6, 0xf67f8d7f, 0x657f7f8a, 0xbace8106, 0xb8816e93, 0xf9b07ff9, 0x818102fa,
+0x32028181, 0xfe7f8e27, 0x818d7f26, 0x7f0781a8, 0x7f7f73f3, 0xfaa78135, 0x7f81810b, 0x72676281,
+0x812ed271, 0x7f8a961b, 0x7f81817a, 0x367f4181, 0x03ecb2f0, 0x6c810a7f, 0x577f81b1, 0x81e889b8,
+0x7f7f707f, 0x7f90368c, 0x86a36487, 0x42b8c17f, 0x91816160, 0x8150b0a5, 0x81390fa1, 0x7f87d07f,
+0x448548d0, 0x32810b93, 0x7f20da7f, 0x5b6a7fed, 0x5c812d7f, 0x7f5a7f69, 0x0c36d681, 0x2ee0544a,
+0x817d861a, 0xa47fdaf7, 0x7c8127b1, 0x96216604, 0x4f8138de, 0x03e57e14, 0x73050f7f, 0x42007eeb,
+0xe303f07f, 0x2f8a7438, 0x8a7f7fbc, 0x866f8165, 0xf496535f, 0xea2d9bb2, 0x16e67386, 0x6bf837ab,
+0x411874b4, 0xa7c15c2a, 0x74bb7f72, 0x8181ab81, 0x81e33481, 0x68b47f7f, 0x957f8181, 0x947fcf27,
+0xb47f7b20, 0x997ca926, 0x5a457f0f, 0x87403699, 0x811e3ccd, 0xdb857d7f, 0xc9cec481, 0x2998d8c3,
+0x231fa37f, 0x876a2942, 0x812d7ff0, 0x7f90959a, 0x811598a2, 0x7f814697, 0x7f7e1467, 0xad3a8154,
+0x81813f26, 0x0851321a, 0xf77f9f7f, 0x76b16294, 0xa56c3e3a, 0x7fd5c569, 0x30dd8185, 0x7f7f819c,
+0x7f8a7f7f, 0x81dc4da7, 0xe1ce9eb9, 0x8181a2c8, 0x7fda81be, 0x01797f42, 0x7b7f89a8, 0x81e9de7f,
+0x7fa76fc9, 0xdebec9a0, 0x7f381e89, 0x81ba0d7f, 0x459a7f7c, 0x81ac8181, 0xb65e8279, 0xdf8174cb,
+0x6ea24abd, 0xb8486638, 0x81637f7f, 0x011d5c81, 0xc27ff63d, 0x81d48160, 0x7c81ba7f, 0x7ffa7f73,
+0x7f8881f0, 0xc2d6a15b, 0x7f5d7f7f, 0x06818fd5, 0x8c23ea91, 0xf3d8e75c, 0xab81be93, 0x817f7fa8,
+0xe57f816d, 0x6e81f27f, 0x81e566aa, 0x88397868, 0x45f9b7c1, 0x2c4d81e5, 0x52765111, 0x813e3d60,
+0x4f45c3e7, 0xef777f91, 0x3e7fc481, 0x3e810d42, 0x81c53f7d, 0x2f7f8481, 0x3a7f8157, 0xf1662881,
+0x81f03791, 0xaf818136, 0x476b7f7f, 0x6890cfa6, 0xe4f7e9ae, 0x81f6b9ba, 0xb0623aac, 0xea7f7031,
+0x72c30000, 0x407f8197, 0x8176917b, 0x81184acc, 0xdacf7fa6, 0x996cd37b, 0xa68175c8, 0x5e6082e3,
+0x067f927f, 0xc47f4481, 0x7fc58113, 0x7f561aff, 0x817f46b2, 0x7f7f8159, 0xcebbc57f, 0x72765b87,
+0x817f2f1e, 0x885c7c81, 0x7f7f65a9, 0xeded8987, 0x7f3bab81, 0x812f7f6b, 0xfc67d85a, 0x13297781,
+0x607f9621, 0x507fa647, 0x4e39ce7f, 0x81ff5c4b, 0xa246316c, 0x81457f7f, 0x5781812f, 0x1463aa9f,
+0xc35d7f14, 0xbcbb5771, 0xd7e45781, 0x636c7365, 0x07102b6e, 0x75e1337f, 0x7f2bb116, 0x257fa0f2,
+0x97597f40, 0x7f818810, 0x7f7f7f5c, 0xca7ff660, 0x9c916181, 0x903ea1cc, 0x6c8f7f81, 0xc2b07f25,
+0xa43d818c, 0x81f67fb3, 0x67f56081, 0x1ba55531, 0xa77fc6a5, 0xda479281, 0xe7647fdb, 0x7fd2f34d,
+0x1b7f4c68, 0x7f8c5781, 0xbcf18110, 0x7fd3b883, 0xde81687f, 0x81358948, 0xeb813d17, 0x25040181,
+0x7ff8a39c, 0xbc574351, 0xbe677c7f, 0x487b5068, 0x6c7f816c, 0x7f2dca81, 0xb8c7b17f, 0x7f869781,
+0x9c99f0ae, 0x437febc4, 0x289d81fe, 0xab74307f, 0x7c7b299a, 0x62593f52, 0x7f4e513a, 0x7f9b81c0,
+0x9e2c0de5, 0x43818175, 0x857064a0, 0xd17f8db2, 0xb0a055de, 0xf04ade7f, 0xe37d7fd6, 0x3956789a,
+0xcfbcb53a, 0x7fa39e7f, 0x7ed171a8, 0x49a65c89, 0x3ee166d9, 0x2daca6ca, 0x53d051e7, 0x957fc181,
+0x0000e873, 0x815fbf9b, 0xe986ac61, 0x7162fd81, 0xe428090f, 0xe2814730, 0xab8d9d3d, 0x8164e6da,
+0x8a6126e4, 0x81817f6e, 0xeb818281, 0x359f7f81, 0xb663c39c, 0x7fb856a8, 0x9d812e30, 0xd07c7f2e,
+0x6b58ceb5, 0x8181ca7f, 0x42c081b5, 0xd58a6fd8, 0x7faa9b85, 0x81818181, 0xbb3781f4, 0x7fa98173,
+0x17f17f7f, 0x7f819862, 0xd97f0781, 0x812f579a, 0x608196ec, 0x23458155, 0x5bc1a902, 0xaa39817f,
+0xcb207d81, 0x227f7f9c, 0x81a54ad1, 0x81027fb4, 0xb6711835, 0x8181a57f, 0x7fed8141, 0x7fa95ec0,
+0x7ffc7f8f, 0x572f81e8, 0x7ca87f81, 0x7fbeb67f, 0x637f814e, 0xcf11af7f, 0x307fb081, 0xaa85927f,
+0x6f5dd995, 0x81db817f, 0x68275869, 0x724dff18, 0x8176ef58, 0x54814c7e, 0xece02300, 0x5ad71a56,
+0x689e7fa7, 0xb67fa77f, 0x107f1359, 0x51a63bc0, 0x22c887ca, 0x0a0e34b7, 0x81587fae, 0xbb79604a,
+0xfbb7077f, 0x81967f81, 0x81227187, 0x8129817f, 0x43a84e8a, 0xb981a34b, 0x5d307f81, 0x4d7fe9bd,
+0xc973a181, 0x78647f8b, 0x00274105, 0x5d7a09e5, 0x6565a681, 0xfbd0ea6f, 0xf986037f, 0x377fc3e0,
+0x9ba57fe8, 0x4f7ff13c, 0xd61f7fa0, 0x817f7fbf, 0x7f3e25c7, 0x81c42fdc, 0xae398181, 0x3125afbf,
+0x7fed479c, 0xf4f52ff4, 0x7fc99d81, 0xaa417fb7, 0xa1324f81, 0xff7b817f, 0x167f6f86, 0x2a86c481,
+0xa127c15c, 0x6d8e0000, 0xcf207f6d, 0x6b815681, 0xd01f50e7, 0xab81e704, 0xce81a4e4, 0x7f177f7f,
+0xaa819181, 0x7f81a044, 0x1c0c7f5e, 0x4f0e56cf, 0x46a581ca, 0xb3d52970, 0x6fb3b2c8, 0x7f8189de,
+0xf0058133, 0xd181d0da, 0x7481c46e, 0x427fc7d5, 0xe4528188, 0x4a359b7f, 0xd1ae25bd, 0xb735818f,
+0x811a2117, 0xddd2829a, 0xec696aa1, 0x99cf945e, 0x518f3d7c, 0x8e814381, 0xa2819647, 0x85af7f43,
+0xc81d7f90, 0xb8361781, 0xb67f9a64, 0xc3d38181, 0x97b07dae, 0x54687f7f, 0x206d5b79, 0x437089ad,
+0x7f814881, 0x77b63840, 0x61816434, 0x9dca5e22, 0x818129bf, 0x8b49dd3b, 0xc792813a, 0x3b407f63,
+0x7fc48f8e, 0x7f96815a, 0x6b430c8b, 0x974ee1a1, 0x7f8181fa, 0xb47098a2, 0x81168181, 0x816b71f5,
+0x0a596d81, 0xa5945681, 0xa14181d0, 0xb4944bfa, 0x81f7816b, 0x7f7f287f, 0x7f81cc48, 0x6d819077,
+0x7dff7f58, 0x5a4e7f81, 0xb7ee6df2, 0x81712a85, 0x0a652e7f, 0x86a1277f, 0x3c568181, 0x7f817f65,
+0x64fb3e0b, 0x71a9687f, 0xa65c7f72, 0x3fb34043, 0x8132f77f, 0xec8133bf, 0x7f8119a5, 0x081f5bb1,
+0x7f81777f, 0xedcca8a1, 0x7ffe7f25, 0xec934f43, 0xdbcc8181, 0x64416881, 0x4a8d93f4, 0x7fb64c7f,
+0xf12f9bc2, 0x812a8f90, 0x1b9c32de, 0x30a30d81, 0xf079e16a, 0x633720c2, 0xad44fd53, 0x3c812f3b,
+0x56b32873, 0x0000b62f, 0x76cb58a6, 0x31086ead, 0x9c307f65, 0xec664f81, 0x7f6186cd, 0xb7047f39,
+0xe87f2ccd, 0xe79f8f3c, 0x88b34352, 0x7f6dec72, 0x8b4aca8c, 0x217f1c55, 0x53d76693, 0x7f984d2d,
+0x125abe92, 0x7f37677f, 0x4f819c81, 0x7fb23b2e, 0xd2c5ea58, 0x7fa7817f, 0x57817f7f, 0xd45239ec,
+0xc887fa03, 0x7f7f7f42, 0x8181444d, 0x2ba67f1a, 0x7fcc527f, 0x813d7f81, 0x68ad12aa, 0xa87f6763,
+0x62577f7c, 0x067f7f5a, 0x3201a788, 0x9872b0a1, 0x814548d0, 0x3a883096, 0xc4701d52, 0xb59381dd,
+0xdc3381a8, 0x816e3f7f, 0x4f57813e, 0x4679d77f, 0x9a14b75d, 0x8181da4b, 0x817f9d48, 0x52818181,
+0x2281c97f, 0xbfb92d7f, 0x1f6f357f, 0x2ca57f3d, 0xb9b4626f, 0xab4bba25, 0xf27f4b5a, 0x4b478a56,
+0x818181c3, 0x6a767f29, 0x81e16dcd, 0x4d818181, 0xd1819ce8, 0xdbce6082, 0x757f41bc, 0x777f7fbc,
+0x5fa9d103, 0x0241e8d6, 0x1bb381a1, 0xf08177b7, 0x00df007f, 0x3bcdbb5f, 0x5e7f710a, 0x7f3f7f1e,
+0x657f0f2b, 0x2ffae79b, 0x495c8110, 0x7f7f8150, 0xe8449f7f, 0x8434a77f, 0x42d56352, 0xfd717f8d,
+0x81c514b3, 0x7f147f50, 0x7f856696, 0x7f844c81, 0x8157714b, 0x50cba2ca, 0x73539ff7, 0xb5ed7fea,
+0x5d1f637f, 0xbc66496d, 0x68b633df, 0xea76156c, 0x7b4654a3, 0x81547f8d, 0x7f537f27, 0x5db64581,
+0x7f367f81, 0x7f81a08c, 0x81440000, 0x3965f076, 0x40977036, 0xcf81ee31, 0x6e7f19bd, 0x703a7f03,
+0xe94b81c6, 0x4330aa7f, 0x060411c3, 0x91f6f37f, 0xbdc9e781, 0x81b87f51, 0x4b6e228f, 0xbc3eb87f,
+0xad916bce, 0xdfb0976a, 0x98b86387, 0xb651bdee, 0x8cf46cb9, 0x9b819a8d, 0x9d8181f1, 0x7fe0ab97,
+0x714d0264, 0xb87f67a4, 0x7f9d3150, 0xe95c7f81, 0x81a7537c, 0x93f4d02e, 0x433a477f, 0xe5067fab,
+0x81de5836, 0x64667f81, 0xc5255988, 0x0a7f824f, 0xf97b7fbf, 0x40c97f82, 0xc1d47a74, 0x7f7f3081,
+0xfe49fc23, 0xba819538, 0xb87f5581, 0x5ea47fb2, 0x35b37292, 0xb9848178, 0x276f5235, 0x647f4ebd,
+0xee2a491a, 0xfd29bb60, 0x21f53728, 0xae9d817b, 0x2ba97f81, 0x6accd440, 0x7fbec77f, 0x909b817f,
+0x227f7f35, 0x767f22d5, 0x0ba3c2d1, 0xd38f817f, 0x467fd862, 0x673e8181, 0x7f3b7f81, 0x70427f81,
+0x6f725d24, 0x731d64de, 0x32a9816d, 0xc1817f7a, 0x627f8181, 0x7f947615, 0xc37f72d2, 0x7f7f4261,
+0xf147be64, 0xc481afab, 0x7fd9a5dc, 0x5c812690, 0x7c34783b, 0x9087817f, 0x7fd25245, 0xea5fcfb1,
+0x81817f81, 0xc84ae6b4, 0x8149c875, 0x814a1a7f, 0xab7f6881, 0x6e7f3d81, 0x3ca58181, 0x75cb4781,
+0x8181817f, 0x5ec4f2c5, 0x8165e07d, 0x643d6e7d, 0x78bd9764, 0x40817f24, 0x5f077581, 0x7f2ebb4b,
+0x7f7fa781, 0xe657ca7f, 0x0000ff21, 0x7fa9bf6a, 0x81c1c30f, 0x9138393c, 0xa2b38174, 0x7f4c24bc,
+0x2b918175, 0x7fea5d7f, 0x50c1a17f, 0x0bfefac7, 0x81fe4ea4, 0xab7f7fbd, 0x559b7fb9, 0xcb81e356,
+0xd7963f72, 0x7f7a1b81, 0x8c9cd9d3, 0xbf889d1f, 0x161a88cf, 0xe6a0abb9, 0xbb014f2b, 0x81fa947f,
+0x7f41509e, 0xb4480d7f, 0x7f7f8181, 0xeca6b540, 0xd27fc381, 0x3aaeb38f, 0x7f7f7f7f, 0x372a7f05,
+0xd6a34b81, 0xee378159, 0xcf8181b8, 0x07487fcf, 0xcbb4ed77, 0x29817fab, 0x7fe5b342, 0x63c3bb81,
+0x0724d1d8, 0x50e47f7f, 0xa67f8f93, 0x8181c37f, 0x28817a81, 0x7f81fb7f, 0xaab17f7f, 0x81997f7f,
+0xa423816f, 0xf953c16a, 0x4c2362cc, 0x81812bf3, 0x5a817f4a, 0xffcbcce0, 0x9c7f8776, 0x5b5a7f7f,
+0x64817f92, 0x5139c47c, 0xbe8573ce, 0xe5457f81, 0x2ca4815b, 0x503e14b8, 0x4ca75681, 0x907f7f7f,
+0xa2377d19, 0x7fd7c09a, 0x7fbc8191, 0x657f61a2, 0x814f5c81, 0x7f48607f, 0xa16f3ad5, 0x819d227f,
+0x247fc10e, 0x7f817f32, 0xc39981f5, 0xb357261b, 0x347f7027, 0xe3814506, 0xa1032e49, 0x979eb571,
+0xb06ac281, 0x81815e7f, 0x34b57fb7, 0x7ffe2681, 0xc181630b, 0xbda9ce3b, 0x81f9287f, 0x4ef12081,
+0xb86a54ba, 0xbc4d13c7, 0x81817fd9, 0x62817f1c, 0x7f7f4fa1, 0x847f7fce, 0x81bf68f5, 0xd7625f73,
+0x81e79d7f, 0x8137a1ca, 0x423581cb, 0x26580000, 0xd7d6811e, 0xce6e6c81, 0x8168173b, 0x498468b2,
+0x8c7c817f, 0x6f81b881, 0xad899a25, 0xd049e481, 0x7fdd817f, 0x63816bbe, 0x048b8d81, 0x8eb764c6,
+0x987b9ea5, 0x81fae493, 0x7f72817f, 0xa57fbd7f, 0x7f0f81b3, 0xb37f4a33, 0x2e092988, 0x1b172b25,
+0x09107f3e, 0x48f5fc7f, 0x69aaa80e, 0x184fe781, 0x7f9db5e6, 0x8195276c, 0x252a8181, 0x8b81ccfa,
+0x3c308181, 0x9d19b086, 0xf0d589f7, 0x207408ca, 0xe34e9ed0, 0xe67fbbf0, 0xc0996525, 0x0dca5881,
+0x813d4181, 0x7f729738, 0x0a865e5d, 0x8bbea581, 0x5c4aac3f, 0x8181a63f, 0xa1f0b873, 0xa92481d0,
+0x837f817f, 0x047fdd84, 0xc8767f2a, 0x441a81be, 0x818681aa, 0x05490179, 0xba81ba7f, 0xde246581,
+0x466d70d7, 0xb6bc3f5b, 0x5c428f2d, 0x8105cb77, 0x0206175a, 0x5f6ac2b1, 0x9a4d2a4d, 0x7fb0917d,
+0x1281ce12, 0x81028181, 0x41b0a4ad, 0x29973681, 0x973e992e, 0x81617dba, 0xc1818181, 0xb87fc1af,
+0x81137feb, 0x627f5210, 0x8181de1d, 0x7f615f70, 0xabbb817f, 0x817fc57f, 0xdbe5b6f3, 0x9c8a7f72,
+0x3c2826df, 0xae03d3b5, 0x7f6cc481, 0xd9c41c7f, 0x83ad7f81, 0x336370a8, 0x8bbfaf2e, 0x3561caa5,
+0x548d142c, 0x810366b5, 0xa981d36e, 0xbf3afc7f, 0x7fd78157, 0x61817bf1, 0x74afcdd7, 0x18ac3d61,
+0xcc45b6e0, 0x3d81af88, 0xf97934de, 0x947a8f81, 0x8b7fa6b8, 0xe0dd8981, 0x2d812381, 0x967f6409,
+0x24bc0b1d, 0xdb7fa943, 0x18197fc3, 0x47ef7f6b, 0x66a6bb7f, 0xd374af81, 0xf48e7f9f, 0x52399754,
+0xe1abbf6f, 0x04751d7f, 0x3690c581, 0x557fc3a6, 0xc1815413, 0x9086df7f, 0x81e57481, 0x81538167,
+0x4df9c981, 0x9463a57f, 0x81c5063a, 0x7f7eaa81, 0xa6dc9423, 0xabc07ffb, 0xd981817c, 0x816064ae,
+0x7f815dab, 0xc0b12da0, 0x1444be7f, 0x3a7781e0, 0x887f527f, 0xc0817f1f, 0x05cba881, 0x6599057f,
+0x817ffd53, 0xca907fab, 0x557f0d7f, 0x5d029ce9, 0x57818168, 0xc4093382, 0x52e5b33a, 0x763e09b7,
+0x814da277, 0xf9208cc5, 0x817f7fcb, 0x7f5fac7f, 0x6d7f6544, 0x7f0a7fec, 0xe7b4337f, 0x7fae8181,
+0xa8c5608c, 0x6f9bb388, 0xb27fc773, 0xf4acaa81, 0x1cad30ac, 0x2d817f8b, 0x2b817f16, 0xcca2a581,
+0xcb77dad4, 0x58487a22, 0x7fe57f69, 0x45387012, 0x73504724, 0x61357f81, 0xc77f8181, 0xabc7e11b,
+0x8181c16e, 0xa681ab27, 0x8c81c48f, 0xbd1de360, 0x9924337f, 0x7f230156, 0x3dd6a87f, 0x477f9381,
+0xbeb38181, 0x47815ccb, 0x8125817f, 0xb8057f7e, 0x7f7fc081, 0x46815873, 0x5f93ba81, 0x7f35767f,
+0x7f7f5a94, 0x748c84e5, 0x4c7ffc90, 0x7fcd247e, 0x44898e81, 0x1268ecc9, 0x81d2777f, 0xda42e7c7,
+0xee267f81, 0x7f5f269f, 0xe3d60c91, 0x81c97f0b, 0xd7b00000, 0x9b813a83, 0x7f7f8181, 0xb71cfa35,
+0xf5888156, 0x853e9cc5, 0x1c1c1014, 0x2e7f8b1b, 0x81bea644, 0x70f4e8d8, 0x8158a181, 0x18caad9f,
+0x3b28815e, 0x7f460155, 0x7f7f7aee, 0x444b51e5, 0x8682a381, 0x7f508181, 0x5e86466d, 0x7f81287f,
+0x7f7c7f50, 0x8173e4de, 0x4c747a65, 0x69816cd7, 0x6674813b, 0x48274e90, 0x92ccf278, 0x99f181c7,
+0x81b20243, 0xbf4b4b81, 0x81d981f4, 0xa1e981dd, 0x6c7f7b6e, 0x98cad579, 0x9a7f1685, 0x81e8812e,
+0x5d7fcf52, 0x37819772, 0xdb437fab, 0x1d83782a, 0xd3ff71b3, 0xc7e28181, 0x81817ca6, 0x1808127f,
+0xb515639d, 0x812c8108, 0xa2a97f14, 0xdd8102c6, 0x727f7f98, 0x5f197f19, 0x7b22817f, 0x46562e7f,
+0x59b89c7f, 0xaba28d81, 0x5e4e7181, 0x909da6b9, 0x817d8128, 0x9c167abf, 0x3ef4817f, 0xf5628d72,
+0x97727fbb, 0x88c6a600, 0x81c9927f, 0x817443e0, 0x81ac7f7f, 0x7fec67cc, 0xc353bb96, 0x4caae113,
+0x7fa37fd9, 0x525c45dc, 0xdf798ba6, 0x7c811049, 0x812570c7, 0x7f788a6b, 0x797f1fef, 0x2022fd81,
+0x38870936, 0x813f7d7f, 0x81810941, 0x6b75817f, 0x5aa11953, 0xcc7f7f81, 0x61778581, 0x5e458181,
+0xcfff7f90, 0x9020747f, 0xb4e35ad5, 0xea0e8109, 0x21f97f13, 0x41c07f40, 0xc6ddc4ad, 0x085227c8,
+0x11dc9f85, 0x7fda7f55, 0x5a92b34c, 0x11659b4d, 0x000081bc, 0x81816781, 0x81cce139, 0xf165d51c,
+0x810a817f, 0x7f7f82d6, 0xb5b3817f, 0x40909bfb, 0x7f04a01f, 0xd0288164, 0x810164f3, 0x59778b81,
+0xc87f2997, 0x9d99417f, 0x65528173, 0x727f454a, 0x9f187fd9, 0x37948141, 0x217fcf7f, 0x81818319,
+0xc27f817f, 0x47817f81, 0x756e817f, 0xa28c8cd3, 0x84b77f81, 0x44ef8e4f, 0x7f7f7f7f, 0x932e2c45,
+0x680d20a8, 0x817f1122, 0x52128a21, 0x2b8136ff, 0x0b7f817f, 0xda8c817f, 0x24c17f7f, 0x3dcb39b7,
+0x81d18181, 0x81fe1a81, 0x0590978b, 0x71b20319, 0x7f65bfb4, 0x4fb42290, 0xde1a7fd2, 0xc8bd77d3,
+0x917f32a0, 0xb03fd9db, 0x4c1e872b, 0x814f5481, 0x44817f7d, 0x398a887f, 0x4a19e8ac, 0x4d818189,
+0xc3818181, 0x7f8198dc, 0xb77f527f, 0x817fe681, 0xa83d818c, 0x420b5e81, 0x6e5adbbf, 0x7abd56c4,
+0x717d7f7f, 0xc7811c0c, 0x767fba89, 0x6d1d5106, 0x5a06df17, 0x86c28181, 0xcdd6888e, 0x0e747f8a,
+0xde81a9c3, 0x45459db8, 0x81114e22, 0xbd7f8197, 0x3c3d85cf, 0x8c815fe8, 0x544d7f64, 0x81986177,
+0x8c20a0b5, 0x7f4b8178, 0x17db6031, 0x7f42df7f, 0xee93cc0f, 0x8ab829b2, 0x29a04e65, 0xfc30035f,
+0xc57b7f7f, 0xe51ef77f, 0x7fd95481, 0x76957f7f, 0x819f945e, 0xc91a187f, 0x81657e40, 0x8192816d,
+0x7339dce0, 0x8bd1c3c7, 0xa2812e1b, 0x81db3d8e, 0x1781da89, 0xd0810000, 0x7fc8c57a, 0x8fc32003,
+0x1c847f81, 0x10dfb271, 0x7ff8cc62, 0x2037d87f, 0x8151501e, 0x17c74c74, 0xb8ab2852, 0x4b7f1c97,
+0x6a811596, 0x46acc3e0, 0x3c81f49e, 0xd6d81a4e, 0x2e815066, 0x46218186, 0x41682bb4, 0xa1ac315d,
+0xb87fdc73, 0x378181ad, 0xe97f979a, 0xccb07981, 0xb10a7f38, 0x03488893, 0xfef78df3, 0x8145467c,
+0x3b67b401, 0xb3cf34bc, 0x81476c00, 0xdd638b81, 0x5e43af81, 0x2bab7f6c, 0x6d7f7f6f, 0x7f657f70,
+0xbc816e77, 0x8981c27f, 0x3e40b685, 0xd93d7256, 0xbd86c8c3, 0x817fdcce, 0x43899081, 0x817f1693,
+0xc0db9a68, 0x7f57a5a8, 0xd14c817f, 0x8c4ab37a, 0x901081dd, 0x292a452b, 0x7f81e85a, 0x189ece81,
+0xc10b9401, 0x81817f69, 0x358b3d7f, 0xa86bb1a9, 0xbd7f7f8a, 0x57fd7fe3, 0x81964506, 0x74295986,
+0xab7fbc8d, 0x817f62e6, 0xab816277, 0x5737ab20, 0x9c7f6f50, 0x7f5781af, 0xe344ef7f, 0x98a695ca,
+0x81d2a20e, 0xa77f6605, 0xc1d00398, 0x177a90d5, 0x7ff6db7f, 0x0221897f, 0x6c8105c6, 0x578981d7,
+0x64ac81c3, 0x1d9381f9, 0x7f706e7f, 0xd5797f81, 0xf9567f81, 0x27ed81d0, 0x496f2d01, 0x48b8973b,
+0xb34c1f32, 0x7f42139a, 0xeac95332, 0xf05f7783, 0x037f8145, 0xa98f3dbd, 0xc5ea24a8, 0x81417fc1,
+0x81655e97, 0xcbc682df, 0xec10815a, 0x817f7fa5, 0xb8b54dff, 0x00003e84, 0xa7ece56d, 0x819d81c2,
+0xd0ee6d81, 0x0e5e4db0, 0xe3818181, 0x7f4a2c13, 0xb13d46ac, 0xc181f081, 0xfe51c8ab, 0xa7747fb6,
+0xc2506129, 0x9d98ce4a, 0x81627f81, 0x816d6481, 0x81576b7f, 0x817f814f, 0xc881cc8b, 0x686d098f,
+0xae7fcb7f, 0x3b39a87f, 0x81888879, 0x47877f30, 0xd9bd9e9e, 0x061a0ee3, 0x7f3631a3, 0xbf5b227f,
+0x7f7f837f, 0xc5d18162, 0xa3405318, 0xc3f27fac, 0x7f43c6f6, 0x927f7fad, 0x817f7fdd, 0x7f813b8b,
+0x7fe59a65, 0x81fd87d7, 0xda54547f, 0x814d114a, 0x7e7f813d, 0xf47f077f, 0xa0869981, 0x38db7fea,
+0xf61986b0, 0x7f9146cb, 0x81db9bb7, 0xfc3b8177, 0xbd7ff9a1, 0x7f33c5aa, 0x74335381, 0x815ca42b,
+0x7f814a81, 0x49977342, 0xab9ed775, 0x9874db81, 0x6381227f, 0x1b81b27f, 0x817f3716, 0xd8e6bf07,
+0x81030494, 0x56cedf81, 0x7f607f9a, 0x7f7f4f52, 0x3cb978f2, 0xd57fca81, 0xd7bc5c81, 0x3a2265b7,
+0x7f7f98bf, 0xac068158, 0xa8851581, 0x1db9a67f, 0x7f24d44f, 0x57a34093, 0x7529b981, 0x50a3817f,
+0x4c3f6381, 0xbd7f81ad, 0x2281a481, 0x1d2e7f81, 0x77b85621, 0x3f818105, 0x307f783f, 0x7f7fe0b2,
+0x4d4a297f, 0x8d7f4d7f, 0x88818a7f, 0x129cf8b7, 0x9b817f7f, 0x7fe5ce65, 0xa48e7213, 0xf481a737,
+0xb43d4fd4, 0x7fb182c3, 0xa18181ba, 0x077f8127, 0x4f4b468a, 0xe1bea062, 0xc34d0000, 0xc0f381ba,
+0x8181817f, 0xbb2d9e7f, 0x7f216b7f, 0x868181ad, 0x7f7fcdf6, 0x810b3d55, 0x627f4c43, 0x81903e81,
+0x54ea9a4d, 0x3181ae1e, 0x7f8116d0, 0x74b5c181, 0x607b431b, 0x5552d081, 0x7f818122, 0xe9449f4c,
+0x6fb434b5, 0x1f1b9552, 0x54d7b178, 0x8b1b9e33, 0x4143cb33, 0x13b0817f, 0x7f51317f, 0x81247f65,
+0xa6fd7b18, 0xb1d6550e, 0xaa6481c1, 0x81421f41, 0x50c0813c, 0x95ac7eec, 0x442a7981, 0xc39289ea,
+0x667fcc5d, 0xf681817f, 0xd729c236, 0x5342819b, 0x813f457f, 0x819d2481, 0x817facd0, 0x7ff2dd9a,
+0x81cafb81, 0x26c72930, 0x177ba325, 0x81015e07, 0xc5667f7f, 0x81fa497f, 0x7cb3505e, 0x85e3815d,
+0x67596b53, 0x857f6696, 0xc97f7f66, 0x7a813978, 0x5f7f7f81, 0x043d9d81, 0x8c81a6a6, 0x0e8197f1,
+0xd17664d1, 0x9f81814d, 0x7f4c4f3e, 0x5e7f756a, 0x8181815a, 0xe090817f, 0x81377f81, 0xaba9813d,
+0x8985c047, 0x2106c97f, 0xc846f2b2, 0xb19a83ce, 0x64107f16, 0x7f792fde, 0x87516244, 0x9c81673e,
+0x2f5c8187, 0x555a8181, 0x95d9f26a, 0x70408e9b, 0x7f81b57f, 0x8f0de19b, 0xd37f7a6e, 0x9ba9fa7f,
+0x7f0b6568, 0x1a4f7f14, 0x3b4f5b71, 0x814e377f, 0x8125a7ec, 0x1d817f43, 0x811128dd, 0x66816435,
+0x9de99e3e, 0x81b27f48, 0x7fc3783f, 0x69983781, 0x457a817f, 0xd4296caa, 0x0000b659, 0x723a92a9,
+0x81860888, 0x8c81c44c, 0x7489b15c, 0x817310ed, 0x74a48e9c, 0xc6531a73, 0x7f7f64d0, 0x502d7fb9,
+0x437f9f7f, 0xb1bfa444, 0x81df09f0, 0x0946ab9b, 0x7f21ca81, 0x9d818166, 0x81e8d281, 0x917f6791,
+0x36ac811b, 0x9d817347, 0x344c02a7, 0xab36817f, 0x81818152, 0x32013a89, 0xd7ab3008, 0x6f608181,
+0x817f7f7f, 0x153e0881, 0x81dfcaba, 0x6c5e577f, 0x2f7f6524, 0x817aa07c, 0xdd7f0175, 0x8b4b7fec,
+0xbc81ead5, 0xae8b205d, 0xc9a9743e, 0xf33f14cf, 0x49ca7f58, 0x507f6976, 0x8cbe66d4, 0x9778a724,
+0x6d8147e3, 0x81334092, 0x7f4c0101, 0x82d5ea73, 0xb59c6657, 0x1ab842f8, 0xbc1d8581, 0x4004d917,
+0xe5eaaee2, 0x7fa9813b, 0x817fae58, 0xd77f1281, 0x10732f61, 0x836d137f, 0x7fbccb3b, 0x1a3a81d7,
+0x81047fef, 0x790aa87f, 0xc19eaac6, 0x60667f07, 0xb7f1a97f, 0x39f39e7c, 0x057f7f7f, 0xaa7f81c8,
+0x79bef7a0, 0xf3d3134d, 0x720f7fbd, 0xb4a5b69e, 0x716c817f, 0x9a817fdf, 0x347f817f, 0x4b995cb4,
+0x876a4f7e, 0x8d92687f, 0x7f9e8181, 0x8172817f, 0x8ea21cc3, 0x61bd96b0, 0x81fba378, 0x6db77f7f,
+0xdf307181, 0xda0f81c4, 0xa8e36d65, 0x70a7a559, 0x0be0f27f, 0xb56f4971, 0x35813a6d, 0x188130b5,
+0x517ff881, 0xec54b6ff, 0x8183817f, 0x20ec2381, 0x3e7f9613, 0x878af66d, 0x81657f81, 0x7fb80000,
+0x7cb38d5b, 0x817f7f45, 0x7f6352c1, 0x3881727e, 0x637f5ec2, 0x81437fc6, 0x7f7f90d2, 0xb1558699,
+0x2b81904a, 0x7f84ad54, 0xedab2281, 0xbe9cbd81, 0x7f5001d1, 0xea2a206c, 0x813cf1ab, 0x81658221,
+0x81a6817f, 0x8167929a, 0x726dd87f, 0x817f817f, 0x93b45a87, 0x7fa179e2, 0x7f4c7f81, 0x8157817f,
+0xa2fd7e81, 0x44284a58, 0x3b98c224, 0x45008124, 0x16da978d, 0xb772ba81, 0x7a4f3481, 0xe97fb9c8,
+0x7f49529e, 0xaa02580d, 0xa254adb3, 0xac0a817f, 0xdc532c32, 0x7fe6887f, 0x7f313d7d, 0x61d17f11,
+0x81e1bf02, 0x7f62c97f, 0x348d5d50, 0x12ec7f7f, 0x8f7f2884, 0x7f3f371e, 0x021c8e81, 0x65a07fc7,
+0x5e14b632, 0x817ff481, 0x6681de78, 0xba4f971c, 0x65c07f81, 0xac81d181, 0x7f11b17f, 0xdcc1011d,
+0x7f7f23c1, 0xcc819b6a, 0x81a73d06, 0x5e943954, 0x09c8b87f, 0x43405fe8, 0x817f8d58, 0x550f4d1d,
+0x82c27254, 0xd0408532, 0x4460477f, 0x8b7f9cec, 0x7fc9817f, 0x8181165f, 0x28d8817a, 0x0527752f,
+0x8168813f, 0x7f48cc81, 0x7481c91e, 0x6881c481, 0x4b0a7f55, 0xcc81e624, 0xe57fac7f, 0x6f0f81a0,
+0x417b5a81, 0x9381dd8c, 0xa881c4e5, 0x8c505264, 0x695ab14c, 0xecc99781, 0x3981c57f, 0x0c204553,
+0x4a77d59c, 0xa2301c81, 0x5ba47f00, 0x451eb2f0, 0xb0459baf, 0x934bcc63, 0x5652c0a1, 0xb381b193,
+0x68626b5b, 0x361741d5, 0x7fe281b3, 0x70ad7f7f, 0x8161f792, 0xbfda5b21, 0xed97ad84, 0x7f59cb7f,
+0x8ed1ecf7, 0x75d784ac, 0x0f81b07f, 0x3ed5bb6b, 0x819122a9, 0x2257a06b, 0x81687fb1, 0xc008057f,
+0x97812981, 0xcb2081cd, 0xd9bb6681, 0x407f7f7f, 0xc27f814e, 0x23a2527f, 0x767203ad, 0xed17ee7f,
+0xd4b89558, 0x8195bc81, 0x817f7fe0, 0xe4b7997f, 0x081ca76d, 0xb87f817f, 0x006350bb, 0x812739de,
+0x557f811e, 0x8d4387af, 0x98815781, 0x81818148, 0xb1bc8105, 0x04cf273e, 0x3f2b289b, 0xae96437e,
+0x819281b9, 0x95cf7f82, 0x7bf77f81, 0xab7f0441, 0x81652854, 0x34de0d81, 0xac816081, 0x43b12e45,
+0x91b75bdd, 0x7da27794, 0x9bbb727f, 0x301d812e, 0x7fa88120, 0x27a15075, 0x27c82cc1, 0xef1a813a,
+0x8114c4d2, 0x817b7f2b, 0xff877f47, 0x7fd47fcd, 0xd08ceb35, 0xe07f4386, 0x67b3a47d, 0xad7fd64d,
+0x817f7044, 0x537feabb, 0x8d3f36ec, 0x6c3883ce, 0x43b6909d, 0x81bcd181, 0xfa7fdae9, 0x3c7f5440,
+0x3946347f, 0x7f22ac7f, 0x815dea81, 0xb6c6c8a1, 0xd57f81c9, 0x526fd581, 0xce3c3115, 0x3d41c54f,
+0x5c5ac2b0, 0x7c948586, 0xa47f7f96, 0x8b7fc351, 0x309aadf9, 0xa0cfef81, 0xb081acd7, 0xd7413cb2,
+0x7f4a6cc9, 0x5c3bb39f, 0x7fc7e581, 0x68cc8114, 0x0926a5fa, 0x82c37581, 0x8181e642, 0x57ab2ec6,
+0x497f0000, 0x5fa07f9c, 0xa17fc405, 0xeaa0de7f, 0xa14a7fb3, 0xc4c12a81, 0xa3527d15, 0xa854d4d4,
+0xf781a3db, 0xa07f26ae, 0x812c7f74, 0x1f7f2fc4, 0x3a9381d4, 0x17b6005d, 0xd414ee60, 0x18b49d68,
+0x9cc77f9e, 0x30aa7f91, 0x7fb9207f, 0x64158b40, 0x81423c7f, 0xea2fa9cc, 0x7fa83381, 0xca647f8e,
+0xd6b9657f, 0x81b26a7a, 0x4fb7b2f1, 0x1b7f9eda, 0xfb8181ab, 0x7f2557d7, 0x71e8701c, 0xa2817f81,
+0x81817f9e, 0x04139d39, 0xc9f6533f, 0xa1f74db1, 0x814042db, 0xca6e8114, 0x7fb3f64a, 0x03f981a0,
+0x7f9e0755, 0x7f7ba781, 0xd554d19a, 0xd81a5661, 0x7fb33f3a, 0x8f81c8bf, 0x012ff975, 0xb1a576ee,
+0x81be6681, 0x818db381, 0xbd7f8151, 0x81b281ae, 0xddd2fbdc, 0x81bfa81c, 0xce818181, 0x774c9c28,
+0x7fd05d59, 0x811a54ce, 0x2f7f727f, 0xbe816b81, 0x7fb03af2, 0xc44bfc7f, 0xcf6ba181, 0x14be8161,
+0x6715a197, 0x76386d26, 0x07835f81, 0x817c818d, 0x81693281, 0x818118fa, 0x777c9e62, 0xccad6446,
+0x769c5b8b, 0xdbd781b7, 0xe4b063f9, 0x2b568182, 0x8c7f8187, 0x7f7f677f, 0x6b7fa675, 0x6be85f61,
+0xc36f7d32, 0x7f81005f, 0xd0d0997f, 0x3a818181, 0x7fa7b6b7, 0xc39ef17f, 0xcc7f437f, 0x3d51729d,
+0x3eb72475, 0x1b069d81, 0x7fe8abee, 0x604c7df9, 0x7fb47f81, 0x3a263b75, 0x75a488e6, 0x7f68d47f,
+0x00004e97, 0x7ffb0973, 0x7f53a009, 0x7f014834, 0x6f81022c, 0xf0b1405f, 0x06c84ca5, 0x4bcf7fc9,
+0x4388ec9a, 0xf528fa74, 0x8e3b816f, 0x7f7f4c72, 0x817f5224, 0xbd998181, 0x81b181c6, 0xbd817f88,
+0x1763f57f, 0x7a796e44, 0xe98e81a9, 0x5360a2fa, 0x97b39081, 0x707f1b65, 0x81c67f7f, 0x4e461c7f,
+0x817f231b, 0xc2d08181, 0x366081c6, 0xd2e67f90, 0x13f1b87f, 0xd781819f, 0x7f347fa2, 0xb1147fc5,
+0xe6b1fe4e, 0x3a1a96b2, 0x177f8191, 0x3e3d96fe, 0xd0d261a0, 0xb25e7fc9, 0x472b81ce, 0xbad6817f,
+0x707b45ca, 0x81817f81, 0xc48fb7f8, 0x90373f82, 0xa681e0b5, 0x71419190, 0x6978f77f, 0xf4463125,
+0x48f1937f, 0x4a45c611, 0x7f97e348, 0xf07f1e21, 0x81fbfc60, 0x8783a281, 0x00931cdd, 0x81e70f91,
+0xe24e7f7f, 0x7f61817f, 0x81967c47, 0x6d9bc90e, 0xec58817f, 0x8157357f, 0x7f7fc674, 0x7f7e3c81,
+0xaa8b7fbc, 0x7f3ba469, 0x7a22f57f, 0x7f7f7f27, 0x81c89e7f, 0x8145d9c8, 0x012f737f, 0xe91f15cc,
+0x9b9cb749, 0x818142cd, 0x290a7f4a, 0x89cfc4b1, 0x8337ebe2, 0xd8224205, 0x8181a49e, 0x58b04ea1,
+0x7fea95a7, 0x861681fb, 0xcea37f5f, 0x81309c8f, 0x6ded8145, 0xbd5be86e, 0xc2ce9402, 0x557f57be,
+0x4ef830e9, 0x7f81f97f, 0xf804367a, 0x5de6817f, 0x156de096, 0x2c06df0c, 0x98b170d7, 0x817f81a9,
+0x24597fd4, 0x81810000, 0x0e24a66a, 0x819e5681, 0x6f73e481, 0x054b532a, 0xc0814026, 0xb3a36181,
+0x6da37f9a, 0x7f83574f, 0xe0a381c6, 0x2075bf7f, 0x28438181, 0xb1cd7f74, 0x7ffb497f, 0xd17f337f,
+0x46085c73, 0xd57f5681, 0x704b7ff3, 0x449e3f7f, 0xeb6e09d6, 0xb37f4b02, 0x817f1cb9, 0x672edf7f,
+0xd0c2c25b, 0x5ed0885b, 0x4676876b, 0x2bd8d970, 0x9a7fbbc6, 0x81095581, 0x81b27f6b, 0x753c7f7f,
+0x7f812c7f, 0x7f477fbe, 0xdaa67f7e, 0x7f099859, 0x7b0fea70, 0x816b8186, 0xf0677f5c, 0x16455d9b,
+0xa98170a9, 0xa181529b, 0x7f817f67, 0x8f72c351, 0x2a7f7f7f, 0x2f5f347f, 0x695c7f79, 0x282fbbe0,
+0xb78581f0, 0x817f297f, 0x49818c81, 0x817fc78c, 0x3bd68181, 0x86d7deda, 0x7fa0d208, 0x1c7f3481,
+0xf5be9a57, 0xb9ded881, 0x8ab88c81, 0x647ae23a, 0xb5571142, 0xe09d7fc1, 0xa5d9817f, 0xaca07f7f,
+0x7f4d5286, 0xa57fde7f, 0x94d0917f, 0xb160442b, 0xacf47b2b, 0xd17f7f81, 0x2e37f976, 0xbe7f5d66,
+0xc2815f28, 0x5c81487f, 0xc2026481, 0x81a194dd, 0xba7f2c91, 0xb7357f37, 0x81b25698, 0xd2818154,
+0x45b78130, 0xc6bead58, 0x6f5a5656, 0xb181a6ae, 0x07c9a153, 0x75d681d3, 0x8c92817f, 0x81503520,
+0xa66f812f, 0xa59b7a81, 0x17a09164, 0x17087fb2, 0xd0bb319b, 0x6d8153ae, 0x8af1a67f, 0x651c46b0,
+0x4b637f1b, 0x00002981, 0x2c7f437f, 0xd9deb6ab, 0x9fba847f, 0x6f289b21, 0x015f811c, 0x8176f498,
+0xeac003ae, 0x68818192, 0xb37fa6a6, 0xd07f4aa5, 0x83819472, 0xa5da41a0, 0xbc7fbe7f, 0xa67fccd9,
+0x7f0c86c5, 0x116e7f15, 0x7f67b45a, 0x907fcf81, 0x81812c66, 0x05747283, 0xac962b7f, 0x2a7f81ea,
+0x81c2b57f, 0xb1b4b868, 0x7f811ed1, 0x7f66c937, 0xc881e6ab, 0x740323fd, 0xcf765745, 0x3592d370,
+0x5c81f3e5, 0x527f3efc, 0x818781d9, 0xf6819b53, 0x1c547f51, 0x4e29b37f, 0x36f1537f, 0xcb819758,
+0x538f5b7f, 0xa5172c22, 0x52427f7f, 0x6b7f8128, 0x7186134a, 0xf67f1b62, 0x6081e015, 0x829abe81,
+0xaa8a65fc, 0xd27fb70f, 0x7f0a0881, 0x3d7fc998, 0x443e78b0, 0x9443c354, 0x81266724, 0x9b81812b,
+0x813181a0, 0x7fddca68, 0x7f260f81, 0x7a818181, 0x812681ca, 0xf48152e0, 0x817f8388, 0x81306c7f,
+0x7f71d020, 0x81bd8481, 0x5234d5c2, 0x31be8136, 0x3403d432, 0x11286844, 0x81a57f1e, 0xe3b57fd4,
+0x7aa88f52, 0xabc64c52, 0x977f8181, 0x7fe68ca6, 0x5dd6eac3, 0xd26a81a9, 0x017f8183, 0x902cc266,
+0x7fba7f52, 0x617f81cf, 0x7f657ff0, 0x045d7f63, 0x3c04bb4e, 0xaa4e7f81, 0x847fe385, 0x67817f7f,
+0x42f33d28, 0x61a5aa5a, 0x817f7f1e, 0xa3a715d7, 0x5da91c3a, 0x7f9f7f81, 0xc48281ce, 0x813081fa,
+0x7f817e53, 0x6d227dbf, 0x6e7b0000, 0xf49b4091, 0xf6b3d8e9, 0x89fb29ae, 0x44289881, 0x3cc78181,
+0xe58103b9, 0x535bffd3, 0x817fa81b, 0x469f82f0, 0x57837fe1, 0xe14af07f, 0x54bf19b2, 0x7482595d,
+0x6781bbd2, 0x4b7b7fb7, 0xa4c45060, 0x380155c8, 0xb72aa381, 0x4530847f, 0xcb509581, 0x34818181,
+0xb03cd87f, 0x90818122, 0x812a8181, 0x817f677f, 0x2c2a597f, 0x35f0c581, 0x81b11261, 0x4d678120,
+0x816d7f5b, 0x448166d8, 0x0c567f61, 0x81189e21, 0xcf932f08, 0x4c5a917f, 0x687f9b7f, 0x257f81d2,
+0xcc7f6220, 0x8c947f81, 0x24642d1f, 0x728155d3, 0x14ca75d2, 0x817d7f38, 0x7f818181, 0x7fb31f87,
+0x13a581b3, 0xd9b5215f, 0xa8afdbf5, 0x147fe67f, 0x81caab97, 0xa96daa7f, 0xf88b897f, 0xe7937fc2,
+0x5a8b7f4b, 0x7d59277f, 0x8d687f9d, 0x7f924b81, 0xd41c82c0, 0xa5119c7f, 0x4fcfeba1, 0x3e077f81,
+0xaf65994c, 0x83d481a7, 0x81257fb0, 0xa481387f, 0x36d8a463, 0x8181811a, 0xc75643a7, 0x474c6c1a,
+0x7fc0e8cf, 0x8cdc896e, 0x55830655, 0x7f81337f, 0x7f65db1d, 0xa881cd81, 0x7f812ec8, 0x7f76cdd4,
+0x634a443d, 0xea7f3ed9, 0x90a8d093, 0xb05e819c, 0x7f7f5c4e, 0x811e5b81, 0x73a1b989, 0x8181717f,
+0x927d7f09, 0xdeaf7fca, 0x528e302a, 0x81654681, 0x7fe92e81, 0x87d58110, 0x1ca86e20, 0x7291a4cc,
+0xc76c7f81, 0x577f5136, 0x00005b6e, 0x817fe37f, 0xf7ac7f7f, 0xf258ee81, 0x81814c63, 0x2a97f57f,
+0x5f7ca0a7, 0x7f2fa37f, 0x94360c7f, 0x7f23117d, 0x81343a7f, 0x55b0d9de, 0xbae0189e, 0xc77f228a,
+0x817f7861, 0xa57f7fac, 0x878ede24, 0xb57fad5a, 0x5c907f93, 0x814e9b81, 0x7febf59c, 0x7724e1a9,
+0x569d9281, 0x1b644699, 0x4d4e26bf, 0x397f7f6e, 0x8ac93027, 0xe6885974, 0x51a2c1a4, 0x7f7f5b7f,
+0xaad8ac97, 0x122c8186, 0x97810a5b, 0x818581e2, 0xc77f7f35, 0x67611c60, 0x3f8178ea, 0xa47fa65e,
+0x888f8132, 0x81817cd4, 0x1081b4bd, 0x817f7fb8, 0x449a3fcc, 0x7f9832de, 0x51e96f58, 0xcbde52c0,
+0x6b515783, 0xbda3b297, 0xd64b6381, 0x7f693c81, 0x6d311abb, 0x73468e81, 0xde81817f, 0x4f811581,
+0x90d6817f, 0x152c9d49, 0xad7f17d7, 0x7f834681, 0xa47fe6dc, 0x06817fb3, 0x7f817f69, 0xd18190b1,
+0xca7f8183, 0x1881f381, 0xac50814a, 0x7f8dca7a, 0x71358131, 0x28783add, 0xd31b153b, 0x71919b97,
+0x81877f07, 0x707fca4f, 0x57c6814b, 0xc0a17fbf, 0xff5bb344, 0x4a7fa99d, 0x7434c104, 0xaa7ff0a5,
+0xb6ec6841, 0xb4917e1b, 0x5a81ab94, 0x81a3aab1, 0x257fce30, 0xe26b7fc7, 0x1d7a7fe5, 0xfc7ca6c0,
+0x81437ff7, 0x7dc59e14, 0x7f0cf9e9, 0x90e37f7f, 0x7f6f12bc, 0x52d36381, 0xc15f88ac, 0x3536277f,
+0x8d3e2a7f, 0xa18d7a7f, 0x48907f23, 0x7f810000, 0xfd813357, 0x6ed4520b, 0x843907e2, 0x66814378,
+0x7f7f6bd8, 0x0e3381ad, 0x03847f90, 0x05814769, 0x8181c181, 0x1c7f7fac, 0xe83cbfb5, 0xb15c735c,
+0x7f8f7f7f, 0x7f846b81, 0x81d2eb7e, 0xf7447f41, 0xa2b57f81, 0x2ba7f381, 0x817f75bc, 0x78553181,
+0xc7b07f7f, 0x7f557a41, 0x46a83ddb, 0x9b447d13, 0xccfe7b81, 0x7f3ae281, 0x75464bfb, 0x7f4e5560,
+0x7fad14ce, 0x98fd2a7f, 0x7f637f81, 0x4a22cf5c, 0xca81813e, 0x4ffc7347, 0x9d777fa5, 0x810585ff,
+0x71e57f81, 0x3f7f8181, 0xfce8819c, 0xbb315486, 0xf1e5a974, 0xf1e061dc, 0xcd7f8181, 0x8181817f,
+0x547fb97f, 0xa663c341, 0x9e5aab7f, 0x35768dad, 0x817f3b48, 0x46bc815f, 0x707f89b3, 0x860713c8,
+0x4a7c6532, 0x541084e8, 0x5f77bb7f, 0x299dbebe, 0xd3f27f8c, 0x25096727, 0x81194cba, 0x7ceff409,
+0x9c8c267f, 0x7f7b1fe0, 0x635c0fdd, 0x308132ac, 0x57330951, 0x7c257f81, 0x6266dd49, 0x7f89b481,
+0x817f7fae, 0x7f81aebd, 0xc7fb7f7f, 0x4537e27f, 0x1d288b7f, 0x7f4a9b7f, 0x8150969f, 0xf533f121,
+0x7f782217, 0xe428816e, 0x10ca6981, 0x6981b39f, 0xe35fdb7f, 0xc6814220, 0x79ba8158, 0x811e815d,
+0x772d8184, 0xc784810c, 0xa91abf8f, 0x3c7f6f7f, 0x6d9981bf, 0x9b42dbe9, 0x42948181, 0x5681817f,
+0xdba39bf2, 0xf77f7f37, 0x18eebbdb, 0x39c6b7b7, 0xdc2fb5b9, 0x99d00a7f, 0x02dbe492, 0x4481606e,
+0x7f6f81a1, 0x7f2f557f, 0x2aee7f6d, 0xed2ad2ae, 0x6ce4ec0c, 0xdb4cae3a, 0x81646c83, 0x7fa3c1be,
+0x7f383730, 0x81aeba9d, 0xc0528bdc, 0xd17f3982, 0x7fa47c7d, 0x81814e81, 0x813d81bc, 0x20816349,
+0x857fdfe9, 0xe46aa581, 0xe8de53b5, 0x34471a81, 0x3b4f7feb, 0x8174c981, 0x2fc7c735, 0xc818ec81,
+0xb28ed3df, 0x627f1100, 0x7f40067f, 0x7fd37fa8, 0x637c5b81, 0x113dd969, 0x81376881, 0x5d817f67,
+0x7f7fda7f, 0x7f7f7f70, 0x77577fb4, 0x87bb3d7f, 0x5b817f93, 0x839b517f, 0x7f45818e, 0xe47f3381,
+0x93c2b281, 0x944207f3, 0x36dc77b3, 0x50b86e4a, 0x8181e27f, 0x0b81a79b, 0xf9975950, 0x977b9e47,
+0xea7f8181, 0x5547b549, 0x3da47f0d, 0x474b8e72, 0x7f7f9ce1, 0x7f2e2e42, 0x6f7f45c9, 0x08d56ede,
+0x8524810b, 0x657fd15f, 0x7f8d0c14, 0x6c7fff7b, 0xd530f39d, 0x7fb4b023, 0x651d8a1b, 0x13817024,
+0x7f850774, 0x1f219db3, 0xd8817f52, 0xd95c0feb, 0x9ef0e67f, 0xd9dd4c7f, 0x64b0819a, 0xbc60e997,
+0x412fd0db, 0x817fa57f, 0xa3a47f81, 0x4d81815b, 0x81874e3a, 0x5f1e7c81, 0x7fc63b81, 0xbf817581,
+0xb5b0a5ab, 0xde2c8145, 0x81789629, 0x097481b8, 0xad5bdca3, 0x212d81e5, 0x4d817f3c, 0x70813761,
+0x5d6d0f40, 0x81a190eb, 0xc942c14d, 0x81b462d8, 0x81890000, 0x6586fbcf, 0x81cb3322, 0xa5c0b931,
+0x7f78e98d, 0x2492625b, 0xaf81b981, 0x4e59817f, 0x677fb9d3, 0x2c3b817f, 0x920e5981, 0x7f2c7f5d,
+0xc379d081, 0xdfbddf43, 0x85818172, 0x6781e442, 0xda9a7f14, 0xcac70881, 0x98818113, 0x0f817f6f,
+0xeba852c8, 0x7fa6407a, 0x7fdc8188, 0x819fd349, 0xee738137, 0xe881417f, 0xb6777fea, 0xc6947f73,
+0x8181240f, 0xa035c264, 0x7f419e81, 0x193f815f, 0xaedc812e, 0x7fb97f24, 0x924a81e6, 0x63f58183,
+0x3e4ec808, 0x7f4fbe86, 0x5faba653, 0xf0c4f4d7, 0x69cf647f, 0xfb55c681, 0x7fe1e381, 0x7f817f6b,
+0xc0410481, 0xc65d71b6, 0xba1f8135, 0x997f04cf, 0x49db5b1c, 0xbe817443, 0x817b812c, 0x36e18163,
+0xd1893a47, 0x231df6f2, 0x816d045e, 0x3a568139, 0x81628181, 0x6588ffd2, 0x23603081, 0xf5b4817d,
+0x8112b5bc, 0x7f9cfbae, 0xc02b8d40, 0xc7f20532, 0xce81487f, 0x0b1a6614, 0x7f17392f, 0x7f8f818c,
+0x7f7f8388, 0x5492467a, 0xbf5e3081, 0x777f26bb, 0xae9c4a7f, 0xae81ba0e, 0x6c6281ae, 0x81238143,
+0x7f997ffe, 0x798b949c, 0xc3d67f36, 0x38817ff9, 0x2f814ab6, 0x594bad4b, 0x7f6f7fd6, 0xab234181,
+0xaf818581, 0x77865381, 0x9d7f8173, 0x27ac8181, 0xbdbd8daf, 0x7c7f7f7f, 0xc6817fd9, 0x34412181,
+0x1fe7eb78, 0x7f38f49b, 0x81040b8f, 0x34ec8581, 0x0000907f, 0xd5818181, 0x7865c6d5, 0xada81975,
+0x0447e955, 0x7f3d09b3, 0x2b8156e8, 0x976d81dd, 0x29cee57f, 0xa34f537f, 0xe9a981f6, 0x0c7fe841,
+0x7f7eda7f, 0xd77f1881, 0x3f929481, 0x77e3c852, 0x0d817fc1, 0x7f4795ab, 0xd1337f4f, 0xdd4b077f,
+0x97a4b3d8, 0x607ff155, 0x942b16c3, 0x113a723c, 0x52ce7882, 0x5e81f5e9, 0x81755669, 0x7fea4d5f,
+0x5d6d7f81, 0x7f90e710, 0xe3817f6d, 0xe810299c, 0x4e814937, 0x3c269d81, 0x33a891aa, 0x81dd7ff3,
+0xa9d1db0d, 0xfb2181eb, 0x7f817fa4, 0x75ec817c, 0xf17f8195, 0x81e18181, 0x44321c58, 0x35a62913,
+0xcd5b0875, 0x397f8233, 0x797f7f81, 0x7f829cbc, 0x9a697f81, 0x07b7fea9, 0x7d2b0b7f, 0x8f984dce,
+0x0c13b97f, 0xe9203f3c, 0xea473769, 0x7b7fdc81, 0x7f7885c1, 0xde7f5b39, 0x32bd81f1, 0x67b4917f,
+0x443069cb, 0x6e972b83, 0xbc66829f, 0x7492817f, 0x7f4d7481, 0x7f25896f, 0x9ea0da7f, 0xceba7f81,
+0x7f45d87f, 0x93dbf04c, 0x50814197, 0xb7167f81, 0x6d7fad19, 0x0f81bea5, 0xc57f8177, 0xca4c7f7f,
+0x7d84e3f6, 0x7bc443d4, 0xd7b0ae81, 0xc8731f44, 0x06e481ac, 0x85b08181, 0x53cfe4be, 0x73761a3d,
+0x707f9981, 0xa87ff27f, 0x68b5b87f, 0xb561c081, 0x7f660001, 0x7b81521e, 0x6093614b, 0xbc778748,
+0x64400f81, 0x81d13281, 0x60475381, 0xbe768181, 0x21aad606, 0x81910000, 0x20b6a511, 0x5953d899,
+0xdd7f7fba, 0x8181fabe, 0x81b8e77f, 0x817ff17f, 0x6757257f, 0x9c2cc933, 0x51813593, 0x7f7fadef,
+0x8ec47f43, 0x348139d7, 0x7f5c82b7, 0x664419bc, 0x8d7b15a5, 0x8181a581, 0xd54d7f63, 0x7f0381b7,
+0x81a17f68, 0x814a5e0d, 0x17813dc4, 0xbd94872d, 0xa25a8101, 0xa6810e54, 0xd8568fc4, 0x7f7f3a7f,
+0x818478ba, 0x517f81c7, 0x70443b81, 0x7ce481b6, 0x7f817f7f, 0x81b27fe5, 0x4bc67f32, 0x81bbe681,
+0xa1c8fe81, 0x857f1c0d, 0x7f81793a, 0x7fbfcf74, 0xadd47f5c, 0x7f8138b4, 0x6f63cd25, 0xd70e497f,
+0x81aa7fc7, 0xbaa84f5a, 0x8197ccd3, 0x7f556b7e, 0xca815dff, 0xb9ba7f7f, 0x81747f7f, 0x7fdf967f,
+0x65a98181, 0x81bc8181, 0x8e11bab7, 0xbbbf7ffd, 0x12b8457f, 0x59fe8481, 0xf25cdd81, 0x958f840c,
+0x5e6a5f81, 0xe9008181, 0x7a68cb38, 0x76818914, 0xa3857fc7, 0xce98717f, 0x8126504d, 0x7fa48183,
+0xfa60e14a, 0x7fb77f22, 0x5f3a7f28, 0x24910bde, 0x2fd07f4f, 0x64a6810b, 0x818181a4, 0x7a065fb8,
+0x7fe69795, 0x45815e3b, 0x7fa98741, 0x52c581b8, 0x74bb2a22, 0x817a8166, 0xc2cb6581, 0x493c7f7f,
+0x883e816b, 0x3c7f7f7f, 0x7f3381c1, 0xab767f6d, 0x81b4588c, 0xb2e24cb9, 0xd9bccba1, 0x70e0162c,
+0xea1c810a, 0x907fdd49, 0x424aece8, 0xd90423b0, 0x22df1b28, 0x6b005d25, 0x113e61b3, 0xa2103bbe,
+0x20d6c538, 0x17e6c841, 0xdc08e2c4, 0x2002b1ef, 0xc51a77e3, 0x8111f752, 0xea698110, 0x1849b6e8,
+0xe6b006d2, 0xdc40b507, 0xc738b9ec, 0x42290a3f, 0x522355bc, 0x590736d3, 0xd9a340e5, 0xe30a19b5,
+0x3de9eff9, 0x4437cc7f, 0xecfd0a7b, 0x34e4fcc7, 0x4afe1556, 0x1ecb301f, 0x0f511d1d, 0xf8ec40db,
+0x4c07caf9, 0x59f73ebd, 0x45064328, 0x03c27f19, 0xd1661dcb, 0xe4e3ae17, 0x000fcd5b, 0xdd121ec8,
+0x3adb1413, 0x112b9888, 0x1d3624fd, 0xa8a347f6, 0xfeb632d5, 0x1d28fc11, 0x21ac2b5f, 0x371fe9f7,
+0x3d5ef435, 0xe84000a1, 0xaebebcc9, 0x34555ff0, 0x39a9ca2a, 0x580fc0e6, 0xcf7a5699, 0xf5e65242,
+0x07ae3170, 0x06b223ea, 0x638e421b, 0xd8dc0cab, 0x66c44fb0, 0x954117d7, 0x9691a163, 0x415bc8a1,
+0x0868d844, 0x9593f551, 0x364bec3b, 0x57460bfb, 0xdc310e3e, 0xe4dbef28, 0xc6443317, 0x81a02211,
+0x450c2323, 0xefca9dcf, 0xfebf3fbf, 0xafef377c, 0x3f81ac26, 0x13b4e548, 0xf60a05a9, 0x03d4d840,
+0x1970ecd3, 0x95019cfd, 0x8128341d, 0xc4d8d440, 0x16b80a75, 0xc2332b1d, 0x47e90e1b, 0x2e4eadcc,
+0x0aa5f04b, 0x03302c42, 0x1a1ed437, 0x3b623efa, 0xc1cec834, 0x4442d130, 0xdce837f0, 0xc3f90934,
+0x5ea50731, 0x257f1504, 0x2da5defd, 0x22d3dd34, 0xc429fa2b, 0xf2cc0a0b, 0x3e2e0000, 0x020f1c20,
+0x2e962a1f, 0x06edf5f3, 0xceb5dfe4, 0x3b213d57, 0x08c24237, 0xf32ad940, 0x321768b0, 0xb133ebcd,
+0xfca78110, 0xc03001db, 0xfca42f7f, 0x7071645f, 0x30bf8185, 0xd1f6d479, 0x02076839, 0x34cd900d,
+0x500cda81, 0xe542b08e, 0x282afac6, 0x30a835ce, 0xbc710153, 0x574b009c, 0xe8b24309, 0x02d2cbc8,
+0xaae1ea5a, 0x190eff7f, 0xbc656b07, 0xfdc8094e, 0xc0ee4452, 0x2a819969, 0xb79a0a0e, 0xe334a040,
+0x12323acf, 0xd9617f3c, 0x3709af42, 0x8b67b338, 0xff00e313, 0x5046e8de, 0x45ec1107, 0x4e2618c9,
+0xb40a62dd, 0x0da39629, 0x0a62a937, 0xc9d92e1d, 0xcf4daf81, 0x3f26a9a3, 0xd01e3f2b, 0xac294211,
+0xd7c221e7, 0x15c928f2, 0xd79412cb, 0x110fb1fc, 0xddd3fa22, 0x4e7fa8ad, 0xd4a0ebf8, 0x5b144a01,
+0x4cf90bdc, 0xb43366e7, 0x1cb8503e, 0xff152c3a, 0xae04fd5f, 0xd896041e, 0x1c2ca245, 0xd7adf0e3,
+0x36ee2de1, 0xf0350023, 0x2e529db9, 0xba18d1bc, 0xbb2aba00, 0x52c7c4fb, 0x09df6147, 0x1102f72e,
+0x13054b2f, 0xf9f9fced, 0x292a14c9, 0x60095adf, 0x8b43fec1, 0x3ca5a3c9, 0xe73665c7, 0x2f12b049,
+0xb0fadecf, 0xd0e46081, 0x42532cf0, 0xe420e3fe, 0xaf5b0501, 0x27f0b481, 0x871c0ec6, 0xcd1c8cb7,
+0xe4135816, 0x0a2aab7f, 0xbf732d1d, 0x613f1aee, 0xac09b927, 0x7d663532, 0x0000dee4, 0xfdeccc4a,
+0x34b86af1, 0xf0bb16dd, 0x5829085f, 0x51ffdcc2, 0xd50c9f39, 0x64dfc723, 0x2cd52b2b, 0x083e0b2b,
+0x224ae1b5, 0x0fd63733, 0xf081cef7, 0x7f73e3c4, 0x36cca9d4, 0xcc2600ae, 0x0757af1e, 0x21cc2ef7,
+0xf175c93f, 0x59221d2d, 0xe6c7f468, 0xe3ea1fcb, 0xcd3d539a, 0x271e345c, 0x3555341c, 0xd2532b7f,
+0x7fc8c57f, 0x4025dbe5, 0xf6926f3d, 0x264d39db, 0x2ed7c504, 0xde2a554b, 0x25aeb624, 0xd031a1dc,
+0x47dbd918, 0xa0004941, 0x0202e11c, 0xd407fda2, 0xd9bd0fdb, 0x30f94d53, 0xd32b1cc6, 0xa6cb1947,
+0x16fa1b49, 0xc70d1f56, 0xa7daec0d, 0x813d4649, 0x0f520200, 0x0d174704, 0x337f521a, 0x52c2cf34,
+0x6b280539, 0x81da4508, 0x0ef2a91d, 0x07121df9, 0x031e410e, 0xf0180925, 0x055022b0, 0x2156f018,
+0xa2e812c6, 0xfbe05cbb, 0x232e4462, 0xed378bca, 0xcd31afa7, 0x063a2e09, 0xe836ff1b, 0xefdeaf26,
+0xfeef274a, 0xc9a1159d, 0x66db4731, 0x05a50ace, 0x1b4c58fd, 0x6b0ba273, 0x251319b8, 0xc7523041,
+0xa20364b7, 0x34812fc4, 0x055f5d29, 0x5858fefa, 0xf809192d, 0x2f063981, 0xce056e8e, 0x1f7e68cc,
+0xbbc07f8b, 0xcc1c1240, 0xf45c1452, 0xeb1deac8, 0xe3f9d3fe, 0x12bc2a12, 0x515bd8d4, 0xb3b361d6,
+0x3304f1dc, 0x63060dbb, 0x41c8c73d, 0xce985d1d, 0xd2b2544b, 0x6d241fd4, 0xb6b8b1c5, 0x21830000,
+0x15efc4c3, 0x2c430fc1, 0x14400bef, 0x2c33083e, 0xbe04fb07, 0xad42d311, 0x4ed2b731, 0x1627d2d2,
+0x07aa0f34, 0xfe38df20, 0xe35bcd1b, 0xe13bfbcf, 0xcc3df1c9, 0x84355a1c, 0x55e602d2, 0x47c52a81,
+0x16d85858, 0x0d11d8d2, 0x54f4b081, 0x303523ad, 0x2dbc16e3, 0xb9d6f0d7, 0x13f76190, 0xeec0133a,
+0x81eccebc, 0x46202d2b, 0x86b52303, 0xa1f928ba, 0xe421b651, 0xb13cf63f, 0x3136c8e6, 0x4a8128b9,
+0x2d7f231a, 0x262cf3e3, 0x9c35d3f9, 0xe9e6753a, 0xefeff441, 0xd4bcd301, 0x42700bd5, 0x29ab001b,
+0x28bb6207, 0x01f537d1, 0xbc57fd38, 0x4999290e, 0x3e7f04fe, 0x36adb7fa, 0xdb0314ce, 0xa1d6524e,
+0xeee5c994, 0x1d1ce32e, 0xee142708, 0x3bf9e663, 0x06521283, 0xe8c6e6a9, 0x53356ee3, 0xe2cd5d4e,
+0x8e1bdacc, 0x382c18e2, 0xc5e2fe00, 0xcee2eaf8, 0xb7532ece, 0xfbea01bf, 0x3ecf7f2d, 0x06b2ffaf,
+0x5acbfe35, 0x26c8eefc, 0x8e27d35b, 0x84291501, 0x32f82ffa, 0x9f3a10cc, 0xabcff198, 0x139a3da9,
+0x3bd92af7, 0x264febe8, 0xbf48f81b, 0xa1df1aa2, 0x2c0a10ca, 0x04c00073, 0x5681e760, 0x411054e5,
+0x88d8c5a0, 0xe3f6b6fd, 0x2a3030ea, 0x0f0ec8b9, 0xa827cbe8, 0x2a2c7f49, 0x51ef20d2, 0xa48c4a81,
+0x2b8db1d9, 0xd150813e, 0xd7aab201, 0x36061afd, 0xeed80a8d, 0xcd9932d0, 0xedd3edbe, 0x38f4f017,
+0x9853f907, 0xc964f464, 0xc68d40f0, 0x3f5bcc44, 0x975004ec, 0x102d467f, 0xf3f9451d, 0xcde706bb,
+0xc87fa602, 0x3f5a88b0, 0x8119c002, 0x3cc14ac8, 0x607abeb7, 0xf95924cd, 0xfb1afa2c, 0xc4967f36,
+0xf425dacb, 0xa32d09aa, 0x35106590, 0xad4e5b4d, 0xa1fda650, 0x0326e143, 0xfbf054e0, 0x589fe1bc,
+0xc83249b4, 0xb0b81e1b, 0x7081fec8, 0x27530027, 0x84dc89ca, 0x76551d3a, 0x0bbcc3d9, 0x8108bade,
+0xb534f6cc, 0x87833920, 0x07ec1b0e, 0x5fd30b29, 0xf124dd07, 0xc981b03d, 0x71b9417e, 0x476c76b6,
+0x7fcb3662, 0xaec632e9, 0x2e6705dd, 0xaec5acf9, 0xc84cd6de, 0x5312d428, 0x12fc4738, 0xd31d5b1e,
+0x61edd156, 0x60fdfddb, 0xff676a0c, 0x2a3baad6, 0x0d1f6eab, 0x0001dcce, 0x180a31ca, 0x1ba681ec,
+0x90871091, 0xe2ef01f5, 0x35186658, 0x95cac76a, 0x1ae32a09, 0xebedc8df, 0x0da7c007, 0x274fc73f,
+0xd62a1ff5, 0xd6d7403a, 0xc4921d32, 0xb5f6cadc, 0xdd34f021, 0xe9334bfe, 0x5c9256c1, 0xbecbfd00,
+0x139acdb2, 0xe3913eab, 0xceed1c3b, 0xdd2c5aa6, 0xfb475d17, 0x4633f4e7, 0x373b4b4f, 0x72ee99f3,
+0xb65542d3, 0x48eb1d39, 0xa6d32fae, 0xc20aabe4, 0x105f4c0d, 0x4848bb65, 0x3bd329d2, 0x470c4709,
+0x43fb2438, 0x0620c0d7, 0x4f962821, 0xfd2f992c, 0x51f8aea5, 0x2521cfe9, 0xbf6e2f9d, 0x005e3653
+
+hard_output0 =
+0xb5bc6ac8, 0xf5373664, 0x1310345c, 0xd5bae4e7, 0x1fc9e83e, 0xebfdfded, 0x84bd86ab, 0xb7aabe00,
+0x60b44fea, 0xb9067464, 0x30325378, 0xa9195955, 0xf70c6e5c, 0x90922632, 0xc90b1cdb, 0xf2f5fb69,
+0x73056b63, 0x1a33bf3f, 0x17755b5c, 0xc58bff6d, 0x2f4390b2, 0x2869d508, 0xe7c7dfe8, 0x38552963,
+0x21da5367, 0x07282b9b, 0xa4767105, 0x1e294251, 0xe350a940, 0xb8a6aa27, 0xed12d778, 0xf10d9ece,
+0xab93527f, 0xcf2da7e7, 0x68f6d0b1, 0x811f4bca, 0x577b06b2, 0x3234f13e, 0x30bab7df, 0x8dc47655,
+0xbb843bed, 0x86da3aba, 0x30950c97, 0xdd096d7a, 0xa871fd6c, 0x8bee4e6b, 0x8fea30d0, 0x6c05b4d2,
+0xf3e144d3, 0xd24ebb1f, 0x065635e5, 0x8d3f2cf9, 0x536c6c6a, 0xfbb0a5d0, 0x3d707b42, 0xc44d5982,
+0xa5f4ad8f, 0xf32c0970, 0x1bccf1a6, 0x05916020, 0xa64fb176, 0x5ede6a35, 0xaf4966da, 0x9df5e0e7,
+0x75042abc, 0x9ef10481, 0x11ddcbc8, 0xa0f5518c, 0xd5c23418, 0x2393d558, 0xfbe7dfeb, 0xed1c64c2,
+0x86a36508, 0xde2dfb1e, 0xb8d0fef9, 0x24505232, 0xc894e71c, 0xbcc752a0, 0x40b74e83, 0x90d23c8c,
+0x728e4a61, 0x108f0b08, 0x66f522ee, 0xc258d851, 0x35a31c44, 0x11311b5b, 0xfd3d5be9, 0x5ae448ff,
+0x4f64994b, 0x5b8247a9, 0x4021114d, 0x2f0b6e82, 0x5eaa9828, 0x50ac71c0, 0xfb86ee52, 0x0dc1ac9b,
+0xbbd47645, 0x8f357115, 0x978ceea0, 0xd557db99, 0x99b30388, 0xfc9a8a1c, 0x0f75be1a, 0x50143e22,
+0x8840989b, 0x738ec50e, 0xe6b2783d, 0xf67899c8, 0x27ebed69, 0x6c415a16, 0x3a6cc2dc, 0xcd4e4e5d,
+0x6cb12b2e, 0xdb88d7c0, 0x79cd1582, 0xbc422413, 0xe72ad2f4, 0x8eaac30f, 0x0bd86747, 0x6d87f69d,
+0x15d62038, 0x4b375630, 0x0d51b859, 0x16db2cb2, 0xf210603a, 0x0abeb833, 0x55c694d0, 0xe57ca43b,
+0x0ba94428, 0x1398a406, 0xe47d3889, 0x5a20203d, 0x250d7a1a, 0xd930ffec, 0x03992e79, 0xf2759376,
+0x024ec121, 0x91fc3a2c, 0xb7e11cc5, 0x4ff7d459, 0xb8700134, 0xd6e61758, 0x4eba0a32, 0xb747e3ec,
+0x7073fad7, 0xded80f99, 0x331e2f1b, 0xfa1f1bed, 0x056424a2, 0x1d1d95e0, 0x550b9ec8, 0x51ee2a38,
+0x19525153, 0xd70c4cd5, 0x0d6cd7ad, 0xe44d1cf2, 0x30dfecda, 0xdacd7fe8, 0x7321d795, 0xddf48ef4,
+0xe271e6a4, 0x9c1feecb, 0x951fcd7b, 0x8acc5a03, 0x3fb83527, 0xe306de74, 0x7b9cd6ee, 0x8e140885,
+0xd4c91e8d, 0xe8c39733, 0x0f02f87f, 0xfb06b1b9, 0x0dc9349c, 0xf76bae8e, 0x4f642a07, 0x3d48a9aa,
+0xe3ea323a, 0xa1cd5c8a, 0x40aa0e70, 0x132042d3, 0xa9732f6c, 0xd15a00c4, 0x43d3b046, 0x9a51ebd4,
+0xc46ee0ed, 0xe2a2148b, 0xf5c478f0, 0x1fb01cf3, 0xf4f321ec, 0xd973811f, 0x11ad11b9, 0x5c67adda
+
+soft_output0 =
+0x81818181, 0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x817f817f, 0x81817f81,
+0x7f817f81, 0x7f817f81, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x817f8181, 0x81817f81,
+0x7f7f7f81, 0x817f7f81, 0x7f7f8181, 0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x817f8181, 0x7f7f8181,
+0x81817f7f, 0x81817f7f, 0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x8181817f, 0x81818181, 0x7f817f7f, 0x7f7f817f, 0x81817f81, 0x7f7f8181, 0x817f817f,
+0x7f817f81, 0x7f7f8181, 0x817f7f81, 0x81818181, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f8181,
+0x8181817f, 0x817f7f81, 0x81818181, 0x817f8181, 0x7f7f817f, 0x7f7f7f81, 0x7f81817f, 0x7f81817f,
+0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x817f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f, 0x7f81817f,
+0x817f7f81, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f, 0x7f81817f, 0x7f7f817f,
+0x81817f81, 0x81817f81, 0x81817f81, 0x817f817f, 0x7f817f7f, 0x7f81817f, 0x81818181, 0x8181817f,
+0x7f817f7f, 0x817f7f7f, 0x7f7f817f, 0x817f7f81, 0x7f7f7f81, 0x81818181, 0x817f8181, 0x7f7f7f81,
+0x7f817f81, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x7f7f8181, 0x81817f7f, 0x7f7f8181, 0x7f7f817f,
+0x7f7f817f, 0x81817f7f, 0x8181817f, 0x817f8181, 0x81817f81, 0x817f7f7f, 0x817f7f81, 0x7f81817f,
+0x7f7f7f7f, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x81818181, 0x817f7f81, 0x7f817f81, 0x7f817f81,
+0x817f7f81, 0x7f818181, 0x7f81817f, 0x817f817f, 0x7f7f817f, 0x81818181, 0x7f818181, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x7f7f7f7f, 0x81817f81, 0x817f8181, 0x7f818181, 0x817f8181, 0x81817f7f,
+0x7f7f8181, 0x81817f81, 0x7f7f817f, 0x817f817f, 0x81818181, 0x7f81817f, 0x817f817f, 0x81818181,
+0x817f8181, 0x817f8181, 0x817f8181, 0x7f817f81, 0x7f7f7f81, 0x7f7f8181, 0x7f817f7f, 0x7f7f817f,
+0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f7f, 0x817f817f, 0x7f817f81, 0x7f817f81, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x81817f81,
+0x817f7f81, 0x7f818181, 0x7f7f8181, 0x817f7f81, 0x7f817f81, 0x817f7f7f, 0x7f7f8181, 0x81817f7f,
+0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f,
+0x8181817f, 0x817f8181, 0x81817f81, 0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x81817f81, 0x7f7f8181,
+0x8181817f, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x8181817f, 0x8181817f, 0x81817f81, 0x817f8181,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x8181817f, 0x817f8181,
+0x817f7f81, 0x817f7f81, 0x7f817f81, 0x817f8181, 0x7f7f7f81, 0x7f81817f, 0x81818181, 0x8181817f,
+0x7f7f8181, 0x7f7f7f81, 0x81817f7f, 0x7f818181, 0x817f7f7f, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f,
+0x8181817f, 0x7f81817f, 0x817f7f7f, 0x817f817f, 0x7f7f7f7f, 0x7f817f81, 0x8181817f, 0x7f81817f,
+0x7f81817f, 0x81817f7f, 0x817f7f81, 0x7f817f81, 0x7f81817f, 0x7f7f7f7f, 0x81817f81, 0x81817f7f,
+0x81817f7f, 0x81817f7f, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x7f7f8181, 0x7f7f8181,
+0x817f7f7f, 0x81818181, 0x7f818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f817f,
+0x7f7f8181, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x7f7f817f, 0x81817f81, 0x817f8181, 0x7f7f817f,
+0x81817f7f, 0x7f7f7f81, 0x7f81817f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x817f817f, 0x81817f7f,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f81817f, 0x7f818181, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f81,
+0x7f7f7f7f, 0x7f7f8181, 0x7f817f81, 0x7f818181, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x8181817f,
+0x817f817f, 0x7f7f7f81, 0x7f818181, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f817f, 0x81817f7f,
+0x817f7f7f, 0x81818181, 0x8181817f, 0x81817f7f, 0x7f7f7f7f, 0x817f8181, 0x7f817f81, 0x817f8181,
+0x817f7f7f, 0x7f7f7f81, 0x817f8181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f81817f, 0x817f817f,
+0x7f817f7f, 0x7f818181, 0x7f818181, 0x7f817f7f, 0x81817f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f81,
+0x81817f81, 0x817f7f7f, 0x81817f7f, 0x81817f81, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f,
+0x7f817f81, 0x81817f81, 0x7f7f7f81, 0x817f8181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f817f7f,
+0x817f7f81, 0x7f7f817f, 0x7f7f8181, 0x7f7f8181, 0x81818181, 0x7f81817f, 0x7f81817f, 0x817f8181,
+0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f817f81, 0x7f817f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81,
+0x8181817f, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x81817f81, 0x7f818181, 0x7f7f7f7f, 0x7f81817f,
+0x8181817f, 0x8181817f, 0x7f7f7f7f, 0x7f818181, 0x817f7f81, 0x7f7f817f, 0x817f7f81, 0x81818181,
+0x817f817f, 0x7f818181, 0x81817f81, 0x81818181, 0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x817f817f,
+0x817f7f7f, 0x817f8181, 0x81817f81, 0x81818181, 0x817f817f, 0x7f817f7f, 0x7f817f7f, 0x7f817f81,
+0x817f7f7f, 0x81817f81, 0x817f7f81, 0x7f7f817f, 0x7f817f7f, 0x7f81817f, 0x8181817f, 0x81817f81,
+0x81817f7f, 0x7f817f81, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x817f7f7f, 0x7f817f81, 0x8181817f,
+0x817f8181, 0x7f81817f, 0x81817f7f, 0x7f817f81, 0x81818181, 0x7f81817f, 0x7f81817f, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f81817f, 0x817f7f81, 0x7f81817f, 0x81818181, 0x7f7f8181, 0x7f818181,
+0x8181817f, 0x81818181, 0x8181817f, 0x817f817f, 0x7f81817f, 0x81817f7f, 0x7f81817f, 0x7f817f7f,
+0x81817f81, 0x7f81817f, 0x7f7f817f, 0x817f8181, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f817f7f,
+0x817f7f7f, 0x7f7f817f, 0x7f818181, 0x817f8181, 0x7f7f7f81, 0x81817f7f, 0x81817f7f, 0x7f7f7f7f,
+0x7f818181, 0x7f7f8181, 0x7f81817f, 0x7f7f817f, 0x8181817f, 0x7f81817f, 0x8181817f, 0x81817f7f,
+0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x817f8181, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x81818181,
+0x817f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x81817f81, 0x81817f7f,
+0x7f818181, 0x817f7f81, 0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f817f, 0x7f817f81, 0x7f7f7f81,
+0x7f818181, 0x7f7f817f, 0x81818181, 0x817f7f81, 0x81817f7f, 0x8181817f, 0x817f8181, 0x8181817f,
+0x7f818181, 0x7f817f81, 0x8181817f, 0x7f817f7f, 0x8181817f, 0x7f817f7f, 0x7f7f7f81, 0x817f7f7f,
+0x817f8181, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x81817f7f, 0x7f7f8181, 0x81817f81, 0x7f7f7f7f,
+0x7f818181, 0x7f818181, 0x7f7f7f7f, 0x8181817f, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f7f817f,
+0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f817f, 0x7f817f81, 0x81818181, 0x817f8181,
+0x7f7f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f, 0x81817f81, 0x7f7f7f81,
+0x817f8181, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x7f7f7f81, 0x7f818181, 0x817f7f7f, 0x7f7f7f7f,
+0x817f7f81, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x81817f81, 0x81817f81, 0x7f7f7f81,
+0x8181817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f81, 0x81818181, 0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x817f817f, 0x8181817f, 0x7f818181,
+0x817f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f7f8181, 0x81817f7f, 0x7f7f8181, 0x7f7f8181, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f,
+0x817f817f, 0x7f81817f, 0x817f7f81, 0x8181817f, 0x81817f7f, 0x81818181, 0x817f817f, 0x7f7f817f,
+0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x81817f81, 0x7f7f7f81, 0x7f81817f, 0x7f7f7f81,
+0x8181817f, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f, 0x7f7f8181, 0x817f817f,
+0x7f7f8181, 0x7f7f7f81, 0x817f8181, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x7f7f817f, 0x7f817f81,
+0x7f817f81, 0x7f817f81, 0x7f817f81, 0x817f8181, 0x7f7f7f7f, 0x7f817f81, 0x817f7f81, 0x7f7f7f81,
+0x7f7f817f, 0x7f817f7f, 0x7f7f7f7f, 0x817f7f81, 0x81817f7f, 0x81817f7f, 0x81818181, 0x7f81817f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f817f7f,
+0x81818181, 0x7f817f7f, 0x7f7f817f, 0x81818181, 0x8181817f, 0x81817f7f, 0x81818181, 0x817f817f,
+0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f818181, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x81817f7f,
+0x8181817f, 0x817f817f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x817f7f7f, 0x817f817f,
+0x817f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f7f81, 0x7f817f7f, 0x81817f7f, 0x81817f81, 0x7f817f81,
+0x817f7f7f, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x81817f81, 0x81818181, 0x7f817f7f,
+0x8181817f, 0x817f7f7f, 0x81817f7f, 0x7f817f7f, 0x817f7f7f, 0x817f7f81, 0x7f7f7f81, 0x81817f7f,
+0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x817f7f7f, 0x81818181, 0x7f7f817f,
+0x817f817f, 0x81817f81, 0x817f7f81, 0x81817f7f, 0x7f7f7f81, 0x7f817f7f, 0x81817f7f, 0x817f817f,
+0x7f817f7f, 0x7f817f7f, 0x81817f7f, 0x817f7f7f, 0x81818181, 0x8181817f, 0x7f7f8181, 0x7f817f7f,
+0x7f817f81, 0x7f7f8181, 0x81817f81, 0x817f7f81, 0x7f818181, 0x7f817f81, 0x7f7f7f81, 0x8181817f,
+0x81817f7f, 0x817f7f7f, 0x7f818181, 0x7f818181, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x7f817f81,
+0x81817f7f, 0x81818181, 0x7f81817f, 0x7f7f8181, 0x817f817f, 0x817f7f81, 0x81817f81, 0x817f7f81,
+0x81818181, 0x817f7f7f, 0x7f818181, 0x81818181, 0x7f7f817f, 0x817f817f, 0x7f7f817f, 0x7f817f7f,
+0x7f817f81, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x817f8181, 0x817f817f, 0x7f818181,
+0x817f7f81, 0x817f7f7f, 0x81817f81, 0x81818181, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f8181,
+0x7f818181, 0x81817f81, 0x7f817f7f, 0x7f7f7f81, 0x7f7f817f, 0x817f7f81, 0x7f7f7f81, 0x81818181,
+0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x7f81817f, 0x817f8181, 0x7f81817f,
+0x8181817f, 0x81818181, 0x7f7f817f, 0x817f8181, 0x7f817f7f, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f,
+0x8181817f, 0x7f7f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x817f7f81, 0x7f7f817f, 0x7f81817f,
+0x81817f81, 0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f7f, 0x7f817f81, 0x7f817f81, 0x7f7f817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f81817f, 0x7f7f8181, 0x7f7f8181, 0x81817f7f,
+0x7f817f81, 0x817f817f, 0x7f817f7f, 0x81818181, 0x7f817f7f, 0x81817f7f, 0x7f817f81, 0x81817f81,
+0x7f7f7f81, 0x81818181, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f7f81, 0x7f818181, 0x7f7f8181,
+0x7f7f7f81, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x817f8181, 0x817f8181, 0x817f7f81,
+0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x81817f81, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x81817f7f, 0x7f817f7f, 0x81817f7f, 0x81817f7f, 0x7f817f81, 0x7f7f8181, 0x7f7f817f, 0x7f7f7f7f,
+0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x7f817f81, 0x81818181, 0x81817f81, 0x817f7f7f, 0x7f7f817f,
+0x817f7f7f, 0x7f7f7f81, 0x81817f81, 0x817f8181, 0x7f7f817f, 0x7f7f817f, 0x7f7f8181, 0x817f7f81,
+0x8181817f, 0x8181817f, 0x7f7f7f81, 0x7f7f817f, 0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x817f817f,
+0x7f7f7f81, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81,
+0x81817f7f, 0x8181817f, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x81817f7f, 0x7f818181, 0x7f817f81,
+0x8181817f, 0x7f81817f, 0x817f7f7f, 0x817f7f7f, 0x8181817f, 0x817f817f, 0x81817f81, 0x7f7f8181,
+0x7f7f7f7f, 0x7f81817f, 0x817f817f, 0x81817f81, 0x81817f81, 0x81817f7f, 0x81817f81, 0x81817f81,
+0x7f7f817f, 0x7f7f7f7f, 0x817f7f7f, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x7f7f8181, 0x817f7f7f,
+0x7f7f7f81, 0x7f817f81, 0x7f7f7f7f, 0x7f817f81, 0x7f81817f, 0x7f817f7f, 0x81817f7f, 0x7f817f7f,
+0x81817f81, 0x7f7f7f81, 0x7f81817f, 0x81817f81, 0x7f817f81, 0x817f8181, 0x7f817f81, 0x7f817f7f,
+0x81818181, 0x817f817f, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x81818181, 0x8181817f, 0x7f817f81,
+0x81817f7f, 0x7f7f7f7f, 0x7f7f817f, 0x7f81817f, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x7f817f81,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f7f, 0x817f7f81, 0x817f8181, 0x81817f7f, 0x81817f7f,
+0x7f7f817f, 0x817f817f, 0x7f817f81, 0x7f817f81, 0x81818181, 0x817f817f, 0x7f7f7f81, 0x81817f7f,
+0x817f817f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f7f, 0x817f7f81, 0x817f7f81, 0x817f8181, 0x8181817f,
+0x81818181, 0x81817f7f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f817f, 0x7f7f7f7f, 0x7f817f81,
+0x8181817f, 0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x81817f7f,
+0x7f7f7f81, 0x81817f81, 0x7f818181, 0x81817f7f, 0x7f7f817f, 0x7f818181, 0x81818181, 0x7f818181,
+0x7f7f7f81, 0x81817f7f, 0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x7f817f7f, 0x7f817f7f, 0x7f817f7f,
+0x7f7f817f, 0x7f817f81, 0x7f81817f, 0x7f7f7f81, 0x81818181, 0x7f7f8181, 0x817f8181, 0x7f817f81,
+0x7f817f81, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x817f7f7f, 0x7f81817f, 0x7f817f7f,
+0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x817f817f, 0x81817f81, 0x7f7f817f, 0x7f817f7f, 0x817f817f,
+0x7f7f7f7f, 0x817f7f81, 0x817f8181, 0x7f7f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x7f7f817f, 0x8181817f,
+0x817f7f81, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x817f7f7f,
+0x817f817f, 0x81817f7f, 0x81818181, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x817f817f, 0x81817f81,
+0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x8181817f, 0x7f7f817f, 0x817f7f81, 0x817f7f81, 0x7f818181,
+0x817f7f7f, 0x8181817f, 0x817f8181, 0x7f7f817f, 0x7f818181, 0x817f8181, 0x7f7f7f81, 0x817f8181,
+0x8181817f, 0x7f817f81, 0x81817f7f, 0x817f8181, 0x817f817f, 0x817f7f81, 0x81818181, 0x81818181,
+0x8181817f, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x817f817f, 0x7f818181, 0x817f8181, 0x7f7f817f,
+0x7f7f7f81, 0x7f818181, 0x7f818181, 0x7f81817f, 0x81817f81, 0x7f818181, 0x7f7f8181, 0x7f817f7f,
+0x8181817f, 0x7f817f7f, 0x817f7f81, 0x7f817f81, 0x8181817f, 0x81818181, 0x817f7f7f, 0x817f817f,
+0x7f7f7f7f, 0x817f8181, 0x81818181, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x817f7f81, 0x81817f81,
+0x7f818181, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x7f81817f,
+0x81817f81, 0x817f7f7f, 0x817f817f, 0x7f7f817f, 0x7f7f8181, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f,
+0x7f81817f, 0x7f81817f, 0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x8181817f, 0x817f7f81, 0x7f818181,
+0x7f818181, 0x817f7f81, 0x7f817f81, 0x7f7f7f7f, 0x81817f81, 0x81818181, 0x7f818181, 0x7f81817f,
+0x81817f81, 0x817f7f7f, 0x7f7f817f, 0x7f7f817f, 0x81817f81, 0x7f817f81, 0x7f7f8181, 0x81817f7f,
+0x817f817f, 0x81817f7f, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f817f81, 0x817f7f7f,
+0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x7f818181, 0x7f817f81, 0x81818181, 0x817f817f, 0x7f7f7f7f,
+0x81818181, 0x7f7f8181, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x8181817f, 0x81817f7f, 0x817f817f,
+0x817f7f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x817f8181, 0x81818181, 0x7f7f7f7f, 0x7f7f817f,
+0x817f7f7f, 0x7f7f817f, 0x817f8181, 0x7f817f81, 0x7f818181, 0x7f81817f, 0x7f81817f, 0x81818181,
+0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x81818181, 0x7f817f81, 0x81818181, 0x7f817f81, 0x81818181,
+0x817f8181, 0x7f7f7f81, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x817f7f81,
+0x7f81817f, 0x817f7f7f, 0x81817f81, 0x817f7f81, 0x81818181, 0x7f7f7f7f, 0x81817f7f, 0x81817f81,
+0x81817f81, 0x81817f81, 0x7f817f81, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f7f817f, 0x81817f81,
+0x7f7f817f, 0x8181817f, 0x817f7f81, 0x81818181, 0x817f7f7f, 0x817f8181, 0x7f7f817f, 0x817f7f7f,
+0x8181817f, 0x81817f7f, 0x7f817f7f, 0x817f7f81, 0x81817f81, 0x817f7f7f, 0x81818181, 0x817f7f7f,
+0x81817f81, 0x7f81817f, 0x7f81817f, 0x7f818181, 0x817f7f81, 0x817f817f, 0x7f81817f, 0x81818181,
+0x81817f81, 0x81818181, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x8181817f, 0x8181817f, 0x81818181,
+0x81818181, 0x81818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f7f81, 0x7f818181,
+0x817f7f7f, 0x7f817f81, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x7f817f81, 0x817f7f7f, 0x81817f81,
+0x7f7f7f7f, 0x817f7f81, 0x817f7f7f, 0x7f817f81, 0x81817f7f, 0x81817f81, 0x817f7f81, 0x81817f81,
+0x817f817f, 0x7f817f81, 0x81817f7f, 0x7f7f7f81, 0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x7f81817f,
+0x817f8181, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x7f7f817f, 0x7f817f7f, 0x7f818181, 0x81817f7f,
+0x81817f7f, 0x8181817f, 0x817f817f, 0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f818181, 0x7f81817f,
+0x817f7f7f, 0x7f817f7f, 0x81817f81, 0x8181817f, 0x8181817f, 0x7f817f81, 0x8181817f, 0x8181817f,
+0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x7f817f7f, 0x81817f81, 0x7f7f7f81, 0x817f7f7f, 0x7f817f81,
+0x7f818181, 0x7f817f81, 0x81818181, 0x817f817f, 0x817f817f, 0x7f818181, 0x817f8181, 0x7f7f817f,
+0x7f7f7f81, 0x817f7f7f, 0x7f81817f, 0x7f81817f, 0x7f81817f, 0x81817f81, 0x817f817f, 0x7f7f817f,
+0x7f817f81, 0x817f817f, 0x7f817f7f, 0x7f81817f, 0x8181817f, 0x817f7f7f, 0x8181817f, 0x7f7f8181,
+0x7f818181, 0x7f817f81, 0x7f7f817f, 0x817f8181, 0x817f817f, 0x817f7f81, 0x7f7f7f81, 0x81817f81,
+0x817f8181, 0x81818181, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f7f7f81,
+0x7f818181, 0x817f7f81, 0x7f817f7f, 0x81818181, 0x7f817f7f, 0x7f7f817f, 0x7f7f8181, 0x8181817f,
+0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x7f81817f, 0x81817f81, 0x7f817f81, 0x817f8181, 0x817f817f,
+0x817f7f7f, 0x81817f7f, 0x7f818181, 0x81818181, 0x817f7f81, 0x81817f7f, 0x817f8181, 0x817f8181,
+0x81817f7f, 0x8181817f, 0x7f7f817f, 0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x7f7f7f7f, 0x817f8181,
+0x81817f7f, 0x7f818181, 0x7f7f7f81, 0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x7f817f81, 0x817f8181,
+0x817f817f, 0x7f7f7f7f, 0x81818181, 0x81818181, 0x81818181, 0x7f817f7f, 0x81818181, 0x7f81817f,
+0x7f817f81, 0x8181817f, 0x817f7f7f, 0x817f817f, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x81817f81,
+0x7f7f8181, 0x7f817f7f, 0x817f7f7f, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x817f7f81,
+0x817f7f7f, 0x7f817f81, 0x7f817f7f, 0x817f817f, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x8181817f,
+0x7f817f7f, 0x8181817f, 0x7f817f81, 0x7f81817f, 0x7f7f7f81, 0x7f7f7f81, 0x817f817f, 0x81818181,
+0x7f817f81, 0x7f81817f, 0x7f7f8181, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f818181, 0x7f7f7f7f,
+0x7f7f8181, 0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f7f, 0x7f7f8181,
+0x817f7f7f, 0x81817f81, 0x7f818181, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x7f817f81,
+0x7f7f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x8181817f, 0x817f7f7f, 0x7f817f7f, 0x817f8181,
+0x7f817f7f, 0x817f8181, 0x7f818181, 0x81817f7f, 0x7f817f7f, 0x8181817f, 0x7f81817f, 0x7f7f7f7f,
+0x7f81817f, 0x7f817f81, 0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f818181, 0x817f7f7f, 0x7f81817f,
+0x81817f81, 0x7f7f7f81, 0x7f818181, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x817f8181,
+0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x8181817f, 0x81817f81,
+0x817f8181, 0x817f8181, 0x7f7f8181, 0x7f7f8181, 0x8181817f, 0x7f817f7f, 0x8181817f, 0x7f81817f,
+0x7f7f7f81, 0x817f817f, 0x81817f7f, 0x817f7f81, 0x81817f7f, 0x817f7f81, 0x81817f81, 0x7f817f81,
+0x817f8181, 0x7f818181, 0x7f817f81, 0x81817f81, 0x81817f81, 0x817f8181, 0x7f818181, 0x81818181,
+0x817f7f81, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x8181817f, 0x81818181, 0x817f7f81, 0x7f818181,
+0x81817f81, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x81817f81, 0x7f817f81, 0x7f7f817f, 0x8181817f,
+0x817f7f7f, 0x7f7f817f, 0x7f817f81, 0x817f7f7f, 0x7f7f817f, 0x81818181, 0x817f7f81, 0x7f7f8181,
+0x7f7f8181, 0x8181817f, 0x7f7f8181, 0x817f8181, 0x817f7f7f, 0x817f7f7f, 0x7f7f7f7f, 0x81817f81,
+0x817f7f81, 0x7f7f8181, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f7f7f81, 0x81817f7f,
+0x817f817f, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f,
+0x7f7f8181, 0x817f817f, 0x7f7f7f81, 0x7f7f817f, 0x817f8181, 0x7f81817f, 0x7f81817f, 0x817f7f7f,
+0x7f817f7f, 0x817f817f, 0x817f7f81, 0x817f7f81, 0x81817f81, 0x7f817f81, 0x817f817f, 0x7f81817f,
+0x7f7f8181, 0x7f818181, 0x7f818181, 0x817f817f, 0x7f81817f, 0x817f8181, 0x8181817f, 0x7f817f7f,
+0x817f8181, 0x817f7f81, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x7f7f7f7f, 0x81818181, 0x7f7f8181,
+0x7f817f7f, 0x7f7f8181, 0x81817f7f, 0x817f817f, 0x81818181, 0x817f7f7f, 0x8181817f, 0x81817f81,
+0x817f817f, 0x817f817f, 0x7f7f817f, 0x7f7f7f81, 0x7f818181, 0x7f817f7f, 0x7f7f7f81, 0x817f817f,
+0x7f818181, 0x7f7f8181, 0x7f817f7f, 0x81817f81, 0x7f7f8181, 0x817f7f81, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f7f81, 0x81817f81, 0x817f8181, 0x817f7f7f,
+0x7f7f7f81, 0x817f8181, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x7f7f7f7f, 0x81817f7f,
+0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f7f,
+0x8181817f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x817f8181, 0x7f7f7f81, 0x7f817f81, 0x7f817f7f,
+0x7f818181, 0x817f7f7f, 0x81817f81, 0x817f8181, 0x7f818181, 0x81817f7f, 0x817f8181, 0x7f7f8181,
+0x81817f7f, 0x7f7f7f7f, 0x81818181, 0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x817f8181,
+0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f,
+0x7f817f81, 0x817f8181, 0x7f7f7f7f, 0x7f818181, 0x7f7f7f81, 0x7f7f817f, 0x7f817f81, 0x817f8181,
+0x81818181, 0x7f818181, 0x7f7f7f7f, 0x7f818181, 0x7f81817f, 0x7f7f817f, 0x81817f81, 0x7f7f8181,
+0x81818181, 0x817f7f81, 0x7f817f81, 0x7f7f8181, 0x817f7f81, 0x81817f81, 0x7f817f7f, 0x817f817f,
+0x7f81817f, 0x7f818181, 0x817f8181, 0x81817f7f, 0x817f8181, 0x7f7f7f81, 0x7f818181, 0x7f7f817f,
+0x817f8181, 0x817f8181, 0x7f817f81, 0x7f81817f, 0x8181817f, 0x817f7f81, 0x817f817f, 0x81818181,
+0x7f817f7f, 0x817f817f, 0x817f817f, 0x7f817f7f, 0x7f817f7f, 0x817f817f, 0x7f81817f, 0x81818181,
+0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f81, 0x7f81817f, 0x7f7f7f81, 0x817f7f81, 0x817f8181, 0x7f818181,
+0x7f7f7f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f818181, 0x817f7f81, 0x81817f7f, 0x81817f7f, 0x81817f81,
+0x7f7f7f81, 0x8181817f, 0x7f7f8181, 0x7f81817f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f817f7f, 0x81818181, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x817f817f, 0x81818181, 0x81817f81,
+0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x81818181, 0x81818181, 0x7f7f7f7f, 0x817f7f81, 0x7f81817f,
+0x7f81817f, 0x7f7f8181, 0x7f818181, 0x7f818181, 0x7f817f7f, 0x8181817f, 0x81817f81, 0x817f7f81,
+0x7f7f7f81, 0x7f81817f, 0x817f7f81, 0x817f8181, 0x7f81817f, 0x817f8181, 0x81817f7f, 0x7f817f81,
+0x81818181, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x7f7f8181, 0x8181817f, 0x81818181, 0x81818181,
+0x81818181, 0x817f8181, 0x81817f81, 0x817f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x7f81817f,
+0x7f7f7f81, 0x7f7f7f7f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x817f7f7f,
+0x7f817f7f, 0x81818181, 0x81818181, 0x7f7f817f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x817f7f81,
+0x81818181, 0x7f817f7f, 0x81817f7f, 0x81817f81, 0x817f817f, 0x817f7f7f, 0x7f7f817f, 0x7f7f817f,
+0x7f7f8181, 0x817f7f81, 0x7f81817f, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f7f8181, 0x817f8181, 0x817f817f, 0x7f7f7f81, 0x81818181, 0x81817f81,
+0x7f7f7f7f, 0x817f817f, 0x81818181, 0x7f7f817f, 0x7f818181, 0x7f7f8181, 0x817f8181, 0x817f7f7f,
+0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x817f8181, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81,
+0x7f818181, 0x7f817f7f, 0x81817f81, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f817f, 0x7f7f7f7f,
+0x817f8181, 0x7f7f7f7f, 0x7f81817f, 0x7f817f81, 0x81818181, 0x817f817f, 0x817f7f7f, 0x81817f7f,
+0x7f81817f, 0x817f817f, 0x7f818181, 0x8181817f, 0x817f817f, 0x81818181, 0x817f7f7f, 0x817f7f81,
+0x7f7f8181, 0x817f817f, 0x817f7f81, 0x7f81817f, 0x7f818181, 0x7f7f817f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x81817f81, 0x7f81817f, 0x7f7f7f7f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x81817f7f,
+0x7f81817f, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x817f817f, 0x81817f81,
+0x7f7f7f81, 0x817f7f81, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x81817f81, 0x7f817f7f, 0x7f818181,
+0x7f818181, 0x81818181, 0x7f7f817f, 0x7f7f7f81, 0x81817f81, 0x817f7f7f, 0x817f8181, 0x7f7f817f,
+0x81818181, 0x81817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f818181, 0x7f7f817f, 0x817f7f81, 0x817f7f7f,
+0x81817f7f, 0x7f81817f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x817f7f81,
+0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x7f7f7f7f, 0x7f817f81, 0x7f7f7f81, 0x817f7f7f, 0x81817f81,
+0x7f817f7f, 0x817f7f81, 0x817f817f, 0x81817f7f, 0x7f818181, 0x7f81817f, 0x7f817f81, 0x7f817f81,
+0x7f81817f, 0x7f7f7f7f, 0x7f817f81, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f7f7f81, 0x7f818181, 0x7f818181, 0x7f818181, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x81818181,
+0x7f81817f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x81817f81, 0x7f818181, 0x81817f81, 0x7f7f7f7f, 0x7f81817f,
+0x81817f81, 0x7f817f7f, 0x7f81817f, 0x81817f81, 0x81818181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x7f7f817f, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x81817f81, 0x8181817f, 0x7f817f81, 0x81817f7f,
+0x817f7f7f, 0x7f7f8181, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x817f817f, 0x817f7f81, 0x7f7f817f,
+0x7f7f8181, 0x7f818181, 0x7f7f8181, 0x81817f7f, 0x8181817f, 0x817f7f7f, 0x7f7f8181, 0x7f817f81,
+0x817f817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x81818181, 0x81817f81,
+0x81817f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f817f, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f,
+0x7f81817f, 0x817f7f81, 0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x7f7f817f,
+0x7f817f7f, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x81818181, 0x8181817f, 0x7f7f7f81, 0x7f818181,
+0x8181817f, 0x7f7f7f7f, 0x817f817f, 0x7f818181, 0x81817f81, 0x7f818181, 0x7f81817f, 0x817f7f81,
+0x81818181, 0x7f7f7f81, 0x81817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x8181817f, 0x7f817f7f,
+0x7f7f8181, 0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f818181,
+0x81817f81, 0x7f818181, 0x81817f81, 0x7f818181, 0x7f7f7f81, 0x817f817f, 0x81817f7f, 0x7f7f7f81,
+0x817f817f, 0x7f817f81, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f81, 0x8181817f, 0x817f8181,
+0x7f7f7f7f, 0x8181817f, 0x817f8181, 0x81818181, 0x7f818181, 0x81818181, 0x7f7f7f81, 0x817f817f,
+0x81817f81, 0x8181817f, 0x8181817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x8181817f, 0x817f7f7f,
+0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81817f81, 0x81817f7f, 0x8181817f,
+0x817f817f, 0x7f817f7f, 0x817f7f7f, 0x7f7f7f81, 0x817f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f7f,
+0x817f817f, 0x817f8181, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f, 0x7f818181, 0x7f7f8181, 0x817f817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x817f8181, 0x817f817f, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f,
+0x7f7f7f7f, 0x7f817f7f, 0x817f817f, 0x817f817f, 0x7f817f81, 0x81818181, 0x7f817f7f, 0x7f7f8181,
+0x7f7f8181, 0x81817f7f, 0x81817f7f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f, 0x81817f7f, 0x7f7f817f,
+0x817f7f81, 0x8181817f, 0x81817f81, 0x7f7f8181, 0x7f7f8181, 0x7f7f7f81, 0x81817f7f, 0x7f7f817f,
+0x81817f81, 0x7f817f81, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f8181, 0x7f817f7f, 0x7f7f8181,
+0x817f817f, 0x817f7f7f, 0x7f817f7f, 0x817f8181, 0x817f7f7f, 0x7f81817f, 0x7f7f817f, 0x817f817f,
+0x7f7f8181, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f7f817f, 0x81817f81, 0x7f817f81, 0x7f817f7f,
+0x817f7f81, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x81817f81, 0x7f817f7f, 0x817f7f7f, 0x7f7f7f7f,
+0x7f817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f7f7f7f, 0x7f818181, 0x817f7f81, 0x817f817f, 0x8181817f,
+0x817f7f7f, 0x817f8181, 0x8181817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x81817f7f, 0x7f7f8181,
+0x81818181, 0x81818181, 0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f7f81, 0x8181817f, 0x7f81817f,
+0x7f7f817f, 0x7f818181, 0x81817f7f, 0x7f817f81, 0x817f8181, 0x7f7f7f81, 0x7f7f8181, 0x817f7f7f,
+0x7f818181, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x7f818181, 0x81817f81, 0x817f7f7f, 0x7f818181,
+0x7f817f81, 0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x817f817f, 0x81818181, 0x7f817f7f, 0x7f817f81,
+0x817f7f81, 0x7f7f817f, 0x81817f81, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x817f817f, 0x81817f81,
+0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x7f818181, 0x7f818181, 0x7f7f7f7f, 0x817f7f81,
+0x817f7f81, 0x7f7f7f81, 0x8181817f, 0x7f7f7f7f, 0x817f817f, 0x7f817f7f, 0x817f817f, 0x7f7f7f7f,
+0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x7f81817f,
+0x7f817f7f, 0x81817f81, 0x8181817f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x817f7f7f,
+0x81817f81, 0x817f7f7f, 0x81817f81, 0x7f81817f, 0x7f818181, 0x7f818181, 0x7f818181, 0x7f81817f,
+0x7f7f8181, 0x817f7f81, 0x817f8181, 0x7f817f81, 0x7f817f7f, 0x81818181, 0x7f817f81, 0x81818181,
+0x81817f7f, 0x81818181, 0x817f7f81, 0x81817f81, 0x81817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f81817f,
+0x7f7f8181, 0x81818181, 0x7f7f7f7f, 0x7f7f8181, 0x81817f7f, 0x81817f81, 0x7f7f7f81, 0x8181817f,
+0x8181817f, 0x7f7f817f, 0x81817f81, 0x817f817f, 0x817f7f7f, 0x817f817f, 0x817f817f, 0x7f81817f,
+0x8181817f, 0x817f7f7f, 0x7f818181, 0x817f7f7f, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x817f817f,
+0x817f7f81, 0x7f7f7f7f, 0x7f7f7f81, 0x8181817f, 0x7f818181, 0x7f7f8181, 0x7f81817f, 0x817f8181,
+0x7f81817f, 0x7f7f8181, 0x8181817f, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x8181817f, 0x81817f81,
+0x7f7f817f, 0x7f817f7f, 0x817f817f, 0x7f81817f, 0x7f817f7f, 0x81817f7f, 0x7f7f8181, 0x817f7f7f,
+0x7f7f7f81, 0x817f8181, 0x7f817f81, 0x817f7f81, 0x817f7f81, 0x81818181, 0x81818181, 0x81818181,
+0x7f7f8181, 0x7f81817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81,
+0x7f817f81, 0x817f8181, 0x7f81817f, 0x81817f81, 0x7f7f7f81, 0x817f7f81, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x7f81817f, 0x8181817f, 0x8181817f, 0x7f81817f,
+0x7f817f81, 0x7f7f817f, 0x817f817f, 0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x817f7f81, 0x817f817f,
+0x817f817f, 0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x817f817f,
+0x8181817f, 0x81818181, 0x81817f81, 0x817f8181, 0x81818181, 0x81817f7f, 0x817f8181, 0x7f7f8181,
+0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x81817f7f, 0x7f7f7f7f, 0x817f817f,
+0x817f7f7f, 0x7f7f817f, 0x7f817f81, 0x7f7f817f, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x7f817f7f,
+0x7f81817f, 0x7f7f8181, 0x7f817f81, 0x817f7f7f, 0x7f7f817f, 0x7f818181, 0x7f7f817f, 0x81818181,
+0x7f81817f, 0x817f8181, 0x81818181, 0x81817f81, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f7f, 0x7f817f81, 0x7f817f7f, 0x7f7f7f7f, 0x7f7f8181, 0x817f7f7f, 0x7f81817f, 0x7f818181,
+0x7f818181, 0x817f7f7f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x817f7f81, 0x7f7f7f81, 0x817f7f81,
+0x7f817f7f, 0x7f7f7f7f, 0x7f818181, 0x7f817f81, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x81818181,
+0x7f7f817f, 0x81817f81, 0x8181817f, 0x7f7f7f81, 0x81817f7f, 0x7f817f81, 0x81818181, 0x817f817f,
+0x7f7f7f81, 0x7f81817f, 0x7f7f817f, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x8181817f,
+0x7f7f7f7f, 0x81817f81, 0x7f7f7f7f, 0x7f7f7f7f, 0x81817f7f, 0x7f817f81, 0x7f81817f, 0x81817f81,
+0x817f817f, 0x81817f81, 0x81817f7f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f817f, 0x7f818181, 0x817f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x8181817f, 0x817f7f7f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x817f7f7f,
+0x7f817f81, 0x7f7f8181, 0x8181817f, 0x7f818181, 0x7f817f7f, 0x817f817f, 0x7f7f7f81, 0x817f817f,
+0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f818181, 0x7f7f817f, 0x817f7f81, 0x7f818181, 0x817f8181, 0x7f817f81,
+0x7f817f7f, 0x817f817f, 0x7f7f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x81818181, 0x817f7f7f,
+0x817f7f81, 0x817f7f7f, 0x817f7f7f, 0x8181817f, 0x7f7f7f81, 0x7f7f8181, 0x817f7f81, 0x817f7f81,
+0x7f817f7f, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x7f818181, 0x7f7f817f, 0x7f817f81, 0x7f7f817f,
+0x7f817f7f, 0x7f817f81, 0x8181817f, 0x81818181, 0x7f7f7f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f,
+0x817f8181, 0x7f818181, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x7f818181, 0x81818181, 0x7f7f7f7f,
+0x8181817f, 0x81817f81, 0x817f7f81, 0x81818181, 0x81817f7f, 0x8181817f, 0x7f817f7f, 0x7f7f7f7f,
+0x817f7f81, 0x817f7f81, 0x817f7f7f, 0x7f7f7f81, 0x7f7f817f, 0x81817f7f, 0x7f7f8181, 0x7f7f817f,
+0x81818181, 0x7f7f7f81, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x7f818181, 0x817f817f, 0x7f7f7f81,
+0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x8181817f, 0x7f81817f, 0x817f817f, 0x8181817f, 0x7f7f7f7f,
+0x817f7f7f, 0x7f818181, 0x817f7f81, 0x7f7f8181, 0x817f7f7f, 0x8181817f, 0x817f8181, 0x8181817f,
+0x81817f81, 0x817f8181, 0x817f7f81, 0x7f7f8181, 0x817f8181, 0x7f817f81, 0x7f7f7f81, 0x7f818181,
+0x7f817f7f, 0x7f7f8181, 0x7f7f817f, 0x81817f81, 0x81817f7f, 0x81817f7f, 0x81817f7f, 0x817f817f,
+0x7f81817f, 0x7f7f7f7f, 0x817f8181, 0x8181817f, 0x7f817f81, 0x7f817f7f, 0x817f7f7f, 0x7f7f8181,
+0x7f7f8181, 0x7f7f7f81, 0x7f818181, 0x81817f7f, 0x8181817f, 0x817f7f81, 0x7f7f7f7f, 0x7f81817f,
+0x817f8181, 0x7f81817f, 0x8181817f, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f7f7f81, 0x817f7f7f,
+0x81818181, 0x7f7f7f7f, 0x81818181, 0x81818181, 0x7f7f8181, 0x7f817f81, 0x81818181, 0x817f8181,
+0x81817f81, 0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x81817f81, 0x81817f81,
+0x7f7f8181, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f, 0x7f7f8181, 0x7f818181, 0x81818181, 0x7f7f7f7f,
+0x81817f7f, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x817f8181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f81, 0x817f7f81, 0x7f81817f, 0x817f7f81, 0x817f817f, 0x7f7f7f7f, 0x81817f7f, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f7f7f81, 0x817f7f7f, 0x81818181, 0x7f7f817f, 0x7f818181,
+0x7f7f7f7f, 0x81818181, 0x7f7f7f81, 0x81818181, 0x8181817f, 0x7f817f81, 0x7f7f7f7f, 0x7f817f81,
+0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x8181817f, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f817f,
+0x7f7f7f81, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x81817f81,
+0x817f7f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x817f7f81, 0x817f8181, 0x7f7f7f7f,
+0x7f818181, 0x81817f7f, 0x7f817f7f, 0x817f817f, 0x7f7f8181, 0x7f7f817f, 0x817f7f81, 0x7f7f8181,
+0x817f7f81, 0x81817f81, 0x817f8181, 0x817f817f, 0x81818181, 0x7f817f81, 0x81817f81, 0x7f7f8181,
+0x7f7f7f81, 0x817f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x81818181, 0x7f7f7f7f, 0x7f817f7f, 0x7f7f7f7f,
+0x81818181, 0x8181817f, 0x7f7f7f7f, 0x7f7f817f, 0x817f8181, 0x817f817f, 0x817f7f7f, 0x817f8181,
+0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x7f817f81, 0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f,
+0x7f7f7f7f, 0x817f8181, 0x817f8181, 0x7f7f817f, 0x81817f81, 0x7f7f8181, 0x7f81817f, 0x81817f7f,
+0x817f7f7f, 0x817f817f, 0x7f7f8181, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f81, 0x7f81817f,
+0x81817f7f, 0x817f7f7f, 0x7f817f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f7f817f, 0x7f817f81,
+0x81817f81, 0x81818181, 0x7f7f8181, 0x817f7f7f, 0x7f7f7f81, 0x81817f7f, 0x81818181, 0x817f8181,
+0x7f7f817f, 0x7f817f7f, 0x7f817f81, 0x817f7f81, 0x7f7f817f, 0x7f818181, 0x7f817f81, 0x7f817f81,
+0x7f818181, 0x81817f7f, 0x817f7f81, 0x8181817f, 0x7f7f7f81, 0x81817f7f, 0x7f817f81, 0x8181817f,
+0x7f7f817f, 0x817f817f, 0x81817f81, 0x81817f81, 0x81817f7f, 0x7f818181, 0x817f7f81, 0x817f7f81,
+0x7f7f7f7f, 0x7f81817f, 0x7f817f81, 0x7f7f817f, 0x7f818181, 0x8181817f, 0x81817f81, 0x7f817f81,
+0x7f81817f, 0x817f7f81, 0x7f818181, 0x817f817f, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f,
+0x81817f7f, 0x7f7f8181, 0x81817f81, 0x81817f7f, 0x8181817f, 0x7f7f817f, 0x8181817f, 0x7f818181,
+0x7f817f7f, 0x817f7f7f, 0x81817f81, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x7f7f817f, 0x7f7f7f81,
+0x817f7f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f8181, 0x7f817f81, 0x7f817f81, 0x7f81817f, 0x81818181,
+0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x817f7f81, 0x8181817f,
+0x81818181, 0x8181817f, 0x8181817f, 0x817f7f81, 0x7f7f8181, 0x817f7f81, 0x7f817f7f, 0x817f7f7f,
+0x81818181, 0x81818181, 0x81817f7f, 0x7f81817f, 0x7f817f81, 0x81817f81, 0x7f7f7f7f, 0x817f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x817f8181, 0x7f7f7f81, 0x817f7f7f, 0x7f817f81, 0x7f7f817f, 0x8181817f,
+0x817f7f81, 0x7f81817f, 0x817f817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x817f8181, 0x817f7f7f,
+0x81818181, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x817f817f, 0x817f7f7f, 0x7f7f817f, 0x8181817f,
+0x7f7f7f7f, 0x81817f81, 0x8181817f, 0x7f81817f, 0x817f7f81, 0x7f7f7f7f, 0x817f7f7f, 0x817f817f,
+0x81818181, 0x8181817f, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x8181817f,
+0x7f818181, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x81817f7f, 0x7f818181, 0x81818181, 0x8181817f,
+0x817f817f, 0x7f7f7f7f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81, 0x7f7f817f, 0x7f818181, 0x81818181,
+0x81818181, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x81817f7f, 0x7f7f817f, 0x8181817f, 0x7f7f7f7f,
+0x7f7f8181, 0x7f7f817f, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x817f8181, 0x81818181,
+0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f7f7f, 0x8181817f, 0x7f817f7f, 0x7f7f817f, 0x81818181,
+0x7f817f7f, 0x817f8181, 0x817f7f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f8181,
+0x81817f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f81817f, 0x8181817f, 0x81818181, 0x81817f7f,
+0x7f81817f, 0x81818181, 0x7f7f8181, 0x7f817f81, 0x7f817f81, 0x7f817f7f, 0x817f817f, 0x7f818181,
+0x7f817f7f, 0x7f7f7f7f, 0x817f817f, 0x817f7f7f, 0x7f81817f, 0x817f7f81, 0x81818181, 0x7f7f817f,
+0x817f817f, 0x81817f81, 0x817f7f81, 0x81817f7f, 0x7f81817f, 0x7f81817f, 0x7f817f81, 0x81817f81,
+0x7f7f817f, 0x8181817f, 0x7f818181, 0x7f7f7f7f, 0x81818181, 0x8181817f, 0x7f817f81, 0x8181817f,
+0x7f81817f, 0x7f7f8181, 0x817f817f, 0x817f7f81, 0x7f817f81, 0x81817f7f, 0x7f818181, 0x81818181,
+0x81817f81, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x81817f81, 0x7f7f7f81, 0x7f818181, 0x81817f81,
+0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f817f7f, 0x817f817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f817f,
+0x817f817f, 0x817f817f, 0x817f8181, 0x7f7f7f81, 0x817f7f81, 0x817f8181, 0x7f7f7f81, 0x8181817f,
+0x81817f7f, 0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x817f817f, 0x81817f7f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f7f, 0x81818181, 0x81818181, 0x7f7f7f81, 0x81817f7f, 0x8181817f, 0x7f818181, 0x7f817f7f,
+0x81817f81, 0x817f7f7f, 0x7f7f8181, 0x7f817f7f, 0x81817f7f, 0x8181817f, 0x817f8181, 0x817f7f81,
+0x7f7f7f7f, 0x81817f7f, 0x81817f81, 0x81818181, 0x81817f7f, 0x817f817f, 0x817f817f, 0x7f7f817f,
+0x7f81817f, 0x81818181, 0x7f817f81, 0x7f7f8181, 0x7f7f817f, 0x7f7f7f81, 0x81817f7f, 0x817f8181,
+0x7f817f7f, 0x8181817f, 0x817f8181, 0x817f7f7f, 0x7f7f7f81, 0x8181817f, 0x817f7f81, 0x7f817f81,
+0x7f7f8181, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f817f7f, 0x7f7f7f81, 0x7f817f7f, 0x8181817f,
+0x7f81817f, 0x817f817f, 0x7f817f81, 0x8181817f, 0x7f818181, 0x81817f81, 0x7f818181, 0x81818181,
+0x7f7f7f81, 0x817f7f7f, 0x817f8181, 0x7f817f7f, 0x7f817f81, 0x817f7f81, 0x81818181, 0x7f7f7f81,
+0x7f7f7f81, 0x7f7f7f81, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f817f7f, 0x7f817f81, 0x7f818181,
+0x7f7f8181, 0x817f8181, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f81, 0x817f8181, 0x7f817f7f, 0x7f817f7f,
+0x7f7f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f817f7f, 0x817f817f, 0x7f817f81, 0x7f7f8181, 0x81817f81,
+0x7f7f8181, 0x7f818181, 0x817f7f81, 0x7f818181, 0x81817f7f, 0x817f7f7f, 0x7f7f8181, 0x81817f7f,
+0x7f817f7f, 0x7f818181, 0x7f81817f, 0x81818181, 0x7f7f817f, 0x7f818181, 0x7f817f7f, 0x81817f81,
+0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f, 0x7f817f81, 0x7f81817f,
+0x7f7f7f81, 0x7f7f7f81, 0x817f817f, 0x7f7f7f81, 0x81818181, 0x7f7f7f81, 0x8181817f, 0x817f7f81,
+0x7f7f817f, 0x817f817f, 0x817f8181, 0x7f7f8181, 0x81817f7f, 0x7f817f81, 0x8181817f, 0x7f81817f,
+0x7f818181, 0x7f818181, 0x7f817f81, 0x7f7f7f7f, 0x7f81817f, 0x817f7f81, 0x7f7f7f81, 0x81818181,
+0x7f7f7f81, 0x817f8181, 0x7f81817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f81817f,
+0x81817f81, 0x7f817f81, 0x81817f7f, 0x81818181, 0x817f817f, 0x817f7f7f, 0x817f8181, 0x81818181,
+0x7f81817f, 0x81818181, 0x81818181, 0x7f818181, 0x7f7f7f7f, 0x81817f81, 0x8181817f, 0x7f7f817f,
+0x817f7f81, 0x817f7f81, 0x817f8181, 0x7f7f8181, 0x817f8181, 0x7f7f7f81, 0x817f7f81, 0x81818181,
+0x8181817f, 0x81817f81, 0x7f7f8181, 0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x7f81817f,
+0x81817f7f, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x7f7f7f81, 0x817f7f81, 0x81818181, 0x7f7f7f81,
+0x7f7f8181, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x81817f81, 0x7f81817f, 0x81817f81, 0x7f7f8181,
+0x817f817f, 0x7f817f81, 0x7f7f8181, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x7f7f7f81, 0x7f7f817f,
+0x817f8181, 0x7f7f817f, 0x8181817f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x7f7f817f, 0x81817f7f,
+0x7f7f817f, 0x7f81817f, 0x81818181, 0x81817f81, 0x8181817f, 0x7f817f7f, 0x81818181, 0x7f7f7f81,
+0x7f7f7f7f, 0x81817f7f, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x8181817f, 0x81818181, 0x7f7f7f81,
+0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x817f8181,
+0x7f817f7f, 0x7f817f7f, 0x7f7f817f, 0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x7f818181, 0x817f7f81,
+0x7f81817f, 0x7f817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f7f, 0x81817f7f, 0x7f81817f, 0x81818181,
+0x7f7f8181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81817f81, 0x8181817f, 0x7f818181, 0x81817f81,
+0x817f7f81, 0x817f7f7f, 0x7f7f7f81, 0x7f7f7f7f, 0x7f7f8181, 0x7f81817f, 0x7f7f817f, 0x7f7f817f,
+0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x817f817f, 0x817f817f, 0x817f817f, 0x7f81817f, 0x7f7f8181,
+0x7f818181, 0x817f8181, 0x7f7f8181, 0x7f817f81, 0x81818181, 0x7f817f81, 0x817f7f7f, 0x7f817f7f,
+0x7f7f8181, 0x817f8181, 0x7f818181, 0x81817f81, 0x7f818181, 0x8181817f, 0x8181817f, 0x7f818181,
+0x8181817f, 0x7f7f7f7f, 0x7f7f817f, 0x7f818181, 0x7f7f7f81, 0x7f7f817f, 0x81818181, 0x817f7f7f,
+0x8181817f, 0x817f817f, 0x7f7f8181, 0x7f7f7f81, 0x81818181, 0x8181817f, 0x817f817f, 0x817f817f,
+0x7f818181, 0x7f7f8181, 0x8181817f, 0x817f817f, 0x81817f7f, 0x81818181, 0x7f81817f, 0x817f817f,
+0x7f7f7f7f, 0x7f817f81, 0x7f818181, 0x817f7f7f, 0x817f7f81, 0x7f817f81, 0x7f7f817f, 0x7f7f7f7f,
+0x81817f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f817f, 0x8181817f, 0x7f81817f, 0x7f818181, 0x7f7f7f7f,
+0x7f7f7f7f, 0x7f7f7f81, 0x7f818181, 0x7f818181, 0x8181817f, 0x7f7f8181, 0x817f7f81, 0x7f817f7f,
+0x817f7f7f, 0x7f7f7f81, 0x7f7f8181, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f81,
+0x817f817f, 0x817f7f7f, 0x81818181, 0x7f818181, 0x81818181, 0x81818181, 0x7f7f7f81, 0x8181817f,
+0x81818181, 0x7f817f7f, 0x817f7f81, 0x7f7f8181, 0x7f818181, 0x8181817f, 0x8181817f, 0x817f7f81,
+0x7f817f7f, 0x81817f7f, 0x817f8181, 0x7f817f7f, 0x7f81817f, 0x81817f7f, 0x7f817f7f, 0x817f7f7f,
+0x817f7f7f, 0x7f817f81, 0x8181817f, 0x817f7f7f, 0x7f817f81, 0x81817f81, 0x817f817f, 0x7f7f7f81,
+0x7f817f81, 0x7f817f7f, 0x817f817f, 0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x7f818181, 0x81817f81,
+0x817f8181, 0x7f817f7f, 0x81817f81, 0x817f7f81, 0x7f7f7f7f, 0x81817f81, 0x81817f81, 0x81817f81,
+0x81817f7f, 0x7f81817f, 0x81818181, 0x7f7f8181, 0x817f817f, 0x817f8181, 0x817f7f7f, 0x8181817f,
+0x81817f7f, 0x8181817f, 0x7f817f81, 0x81817f7f, 0x81818181, 0x817f7f7f, 0x7f81817f, 0x817f817f,
+0x81818181, 0x817f7f81, 0x817f817f, 0x817f7f7f, 0x81817f7f, 0x7f7f8181, 0x817f7f81, 0x8181817f,
+0x7f818181, 0x7f817f81, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x81818181, 0x7f7f8181, 0x7f7f7f7f,
+0x7f81817f, 0x817f8181, 0x817f817f, 0x7f81817f, 0x81818181, 0x7f817f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+0x7f7f8181, 0x817f8181, 0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x7f7f817f, 0x7f817f7f, 0x817f8181,
+0x81817f81, 0x817f8181, 0x7f81817f, 0x817f8181, 0x817f8181, 0x817f7f81, 0x7f7f817f, 0x7f818181,
+0x7f7f817f, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f7f, 0x8181817f, 0x817f8181, 0x81818181, 0x817f7f7f,
+0x7f7f817f, 0x817f7f7f, 0x817f817f, 0x7f818181, 0x8181817f, 0x817f817f, 0x7f7f7f7f, 0x7f81817f,
+0x7f817f81, 0x81818181, 0x7f817f7f, 0x817f817f, 0x7f7f7f7f, 0x817f7f81, 0x7f7f8181, 0x81817f81,
+0x81818181, 0x81817f81, 0x7f7f817f, 0x81818181, 0x817f8181, 0x7f81817f, 0x81817f7f, 0x7f81817f,
+0x817f8181, 0x81818181, 0x7f7f7f81, 0x81817f81, 0x817f7f7f, 0x817f8181, 0x7f7f817f, 0x7f7f8181,
+0x7f81817f, 0x7f818181, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x7f7f7f81, 0x7f81817f, 0x817f8181,
+0x81817f81, 0x81818181, 0x817f8181, 0x81818181, 0x7f81817f, 0x7f7f8181, 0x7f81817f, 0x81817f81,
+0x7f818181, 0x81818181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x81817f7f, 0x7f81817f, 0x81818181,
+0x81817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f7f, 0x8181817f, 0x81817f81, 0x81817f81, 0x8181817f,
+0x817f817f, 0x81817f7f, 0x7f817f7f, 0x817f817f, 0x817f7f7f, 0x8181817f, 0x7f7f7f7f, 0x817f817f,
+0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x7f81817f, 0x7f7f817f, 0x7f817f7f, 0x7f7f8181, 0x7f7f7f7f,
+0x7f81817f, 0x817f817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f81817f, 0x81818181,
+0x7f7f817f, 0x7f81817f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f8181, 0x81818181, 0x817f7f7f, 0x81818181,
+0x81817f81, 0x817f817f, 0x7f817f81, 0x7f7f8181, 0x7f7f7f81, 0x81817f81, 0x7f7f7f81, 0x817f7f7f,
+0x817f817f, 0x817f8181, 0x7f817f81, 0x817f7f7f, 0x7f817f7f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f81,
+0x7f817f7f, 0x7f81817f, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f7f7f7f, 0x7f817f7f, 0x7f7f817f, 0x7f817f81, 0x817f817f, 0x81817f7f, 0x7f81817f, 0x8181817f,
+0x817f7f81, 0x7f7f7f81, 0x81818181, 0x7f817f81, 0x81818181, 0x7f818181, 0x817f7f7f, 0x81818181,
+0x81818181, 0x7f7f7f7f, 0x8181817f, 0x7f7f7f81, 0x81818181, 0x7f7f817f, 0x817f7f81, 0x7f81817f,
+0x817f817f, 0x7f7f7f81, 0x7f81817f, 0x7f81817f, 0x7f818181, 0x817f817f, 0x81817f7f, 0x7f7f817f,
+0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x817f817f, 0x81817f7f, 0x7f7f7f81, 0x817f817f, 0x7f7f817f,
+0x81817f7f, 0x7f7f7f7f, 0x7f81817f, 0x817f7f7f, 0x7f7f8181, 0x7f7f8181, 0x7f7f817f, 0x7f81817f,
+0x81817f81, 0x817f7f81, 0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f,
+0x7f7f7f7f, 0x81817f81, 0x817f817f, 0x81817f81, 0x7f7f7f7f, 0x817f817f, 0x817f7f81, 0x81817f81,
+0x817f7f81, 0x817f7f7f, 0x81817f81, 0x817f7f81, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x8181817f,
+0x7f7f7f81, 0x81817f81, 0x7f817f81, 0x81818181, 0x817f8181, 0x7f7f8181, 0x81818181, 0x817f7f81,
+0x817f8181, 0x81817f7f, 0x8181817f, 0x817f817f, 0x8181817f, 0x7f818181, 0x81817f81, 0x81818181,
+0x817f817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x7f7f8181, 0x8181817f,
+0x817f7f81, 0x7f818181, 0x7f7f817f, 0x7f81817f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x817f8181,
+0x7f7f8181, 0x81817f81, 0x7f7f8181, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f817f7f, 0x81817f81,
+0x7f7f817f, 0x817f817f, 0x817f8181, 0x7f817f7f, 0x7f817f7f, 0x8181817f, 0x817f8181, 0x817f7f7f,
+0x817f7f81, 0x817f8181, 0x8181817f, 0x7f818181, 0x7f818181, 0x7f7f7f81, 0x817f7f81, 0x7f817f81,
+0x81817f81, 0x817f8181, 0x817f7f7f, 0x817f7f7f, 0x81818181, 0x7f7f7f81, 0x817f817f, 0x817f7f81,
+0x81817f7f, 0x7f818181, 0x7f7f817f, 0x7f818181, 0x7f7f8181, 0x7f817f7f, 0x817f8181, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x7f817f81, 0x817f7f81, 0x7f7f7f81, 0x81817f7f, 0x7f817f7f,
+0x7f7f8181, 0x817f8181, 0x7f818181, 0x8181817f, 0x81817f81, 0x817f7f7f, 0x7f817f81, 0x81818181,
+0x817f817f, 0x81818181, 0x817f7f81, 0x817f7f7f, 0x817f817f, 0x7f817f81, 0x7f817f7f, 0x817f7f81,
+0x7f818181, 0x817f7f7f, 0x7f81817f, 0x81817f7f, 0x817f8181, 0x817f8181, 0x81818181, 0x817f7f81,
+0x7f7f817f, 0x81817f7f, 0x8181817f, 0x7f7f8181, 0x7f81817f, 0x8181817f, 0x817f7f81, 0x7f81817f,
+0x817f817f, 0x7f7f817f, 0x817f7f7f, 0x8181817f, 0x7f7f817f, 0x7f81817f, 0x8181817f, 0x7f81817f,
+0x81818181, 0x81818181, 0x7f81817f, 0x817f7f7f, 0x817f7f7f, 0x817f7f81, 0x7f818181, 0x817f7f7f,
+0x817f7f7f, 0x81817f81, 0x7f817f81, 0x7f817f7f, 0x817f8181, 0x7f81817f, 0x7f7f817f, 0x81817f7f,
+0x7f7f7f7f, 0x817f7f81, 0x81817f81, 0x817f817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x81818181,
+0x7f7f7f81, 0x81817f7f, 0x817f7f81, 0x8181817f, 0x7f7f7f81, 0x817f7f7f, 0x81818181, 0x81817f7f,
+0x7f817f7f, 0x817f7f7f, 0x81817f7f, 0x81817f7f, 0x817f7f7f, 0x81817f7f, 0x817f8181, 0x7f81817f,
+0x7f7f7f7f, 0x817f817f, 0x817f7f81, 0x8181817f, 0x817f7f7f, 0x7f817f7f, 0x8181817f, 0x81817f81,
+0x817f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f818181, 0x7f817f81, 0x81818181, 0x817f8181, 0x8181817f,
+0x7f817f7f, 0x817f8181, 0x7f818181, 0x817f7f81, 0x7f817f7f, 0x7f7f8181, 0x817f817f, 0x817f8181,
+0x7f81817f, 0x7f7f817f, 0x7f7f8181, 0x7f7f817f, 0x8181817f, 0x81817f81, 0x817f8181, 0x7f7f7f81,
+0x8181817f, 0x8181817f, 0x8181817f, 0x7f7f7f81, 0x8181817f, 0x7f818181, 0x81818181, 0x7f7f7f81,
+0x7f817f7f, 0x81818181, 0x817f8181, 0x817f8181, 0x7f7f7f7f, 0x817f7f81, 0x817f817f, 0x817f7f81,
+0x81818181, 0x817f8181, 0x7f7f8181, 0x7f7f8181, 0x817f817f, 0x81817f7f, 0x7f7f8181, 0x817f8181,
+0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f818181, 0x7f81817f, 0x81817f7f, 0x817f8181,
+0x817f8181, 0x7f818181, 0x8181817f, 0x7f817f7f, 0x81817f81, 0x7f7f8181, 0x817f7f81, 0x817f8181,
+0x7f7f7f7f, 0x817f7f7f, 0x7f817f81, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f81, 0x81818181, 0x81817f81,
+0x7f817f7f, 0x7f818181, 0x817f7f81, 0x8181817f, 0x81817f7f, 0x8181817f, 0x7f81817f, 0x7f817f81,
+0x817f8181, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f818181, 0x7f81817f, 0x7f7f8181, 0x7f7f7f81,
+0x817f817f, 0x81817f7f, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x817f8181, 0x81818181, 0x8181817f,
+0x81817f7f, 0x7f817f7f, 0x817f8181, 0x81817f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x81817f81, 0x817f817f,
+0x817f8181, 0x81817f81, 0x81817f81, 0x7f817f7f, 0x7f7f817f, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f,
+0x81817f81, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f817f7f, 0x7f7f817f, 0x81817f81, 0x817f8181,
+0x81817f81, 0x8181817f, 0x7f7f7f81, 0x817f8181, 0x81817f7f, 0x81817f81, 0x817f8181, 0x817f8181,
+0x817f817f, 0x817f7f7f, 0x81817f7f, 0x7f817f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f818181, 0x81817f81,
+0x817f8181, 0x817f7f7f, 0x817f817f, 0x8181817f, 0x81818181, 0x7f817f81, 0x81817f7f, 0x81818181,
+0x7f818181, 0x817f817f, 0x7f7f7f81, 0x817f817f, 0x7f7f817f, 0x817f817f, 0x7f7f7f7f, 0x817f7f7f,
+0x817f7f7f, 0x7f817f81, 0x7f7f817f, 0x81817f7f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f817f,
+0x817f817f, 0x7f817f81, 0x7f818181, 0x7f7f7f81, 0x7f817f81, 0x81817f81, 0x81818181, 0x7f817f7f,
+0x7f7f7f81, 0x817f817f, 0x7f817f7f, 0x817f7f81, 0x7f7f7f7f, 0x817f8181, 0x7f7f7f7f, 0x817f817f,
+0x81818181, 0x81818181, 0x8181817f, 0x81817f81, 0x81818181, 0x817f8181, 0x7f817f7f, 0x7f817f81,
+0x817f8181, 0x7f818181, 0x817f7f81, 0x817f7f7f, 0x7f7f817f, 0x8181817f, 0x817f7f7f, 0x7f817f7f,
+0x7f7f7f7f, 0x7f81817f, 0x7f7f817f, 0x7f81817f, 0x81817f81, 0x817f8181, 0x7f817f81, 0x817f8181,
+0x81818181, 0x817f817f, 0x81817f81, 0x817f817f, 0x817f8181, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
+0x81817f81, 0x7f81817f, 0x817f7f81, 0x7f818181, 0x81817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f817f7f,
+0x8181817f, 0x7f81817f, 0x8181817f, 0x81818181, 0x81817f7f, 0x7f7f817f, 0x81817f81, 0x8181817f,
+0x7f81817f, 0x7f817f81, 0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x817f8181, 0x81817f81, 0x7f7f7f7f,
+0x7f817f7f, 0x81817f7f, 0x7f7f7f7f, 0x817f817f, 0x7f7f7f81, 0x817f7f81, 0x7f818181, 0x7f7f8181,
+0x7f817f81, 0x7f817f7f, 0x8181817f, 0x7f7f7f81, 0x7f7f8181, 0x81818181, 0x7f7f8181, 0x7f817f7f,
+0x7f7f8181, 0x7f81817f, 0x7f7f8181, 0x81818181, 0x7f817f7f, 0x7f7f8181, 0x7f817f7f, 0x8181817f,
+0x7f817f7f, 0x817f7f7f, 0x81817f81, 0x7f817f81, 0x817f817f, 0x7f817f81, 0x7f817f7f, 0x81818181,
+0x7f817f81, 0x7f7f8181, 0x7f81817f, 0x81818181, 0x7f7f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x7f817f81,
+0x7f81817f, 0x817f7f7f, 0x817f8181, 0x7f817f7f, 0x817f7f81, 0x7f7f7f7f, 0x7f817f7f, 0x7f817f81,
+0x817f7f7f, 0x817f8181, 0x7f7f7f7f, 0x817f7f81, 0x81817f7f, 0x81818181, 0x817f817f, 0x81818181,
+0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x81817f81, 0x7f81817f, 0x7f7f7f81, 0x7f7f7f81, 0x81817f7f,
+0x817f7f81, 0x817f7f81, 0x7f817f7f, 0x7f7f7f7f, 0x8181817f, 0x81817f7f, 0x7f7f7f7f, 0x7f818181,
+0x7f818181, 0x81818181, 0x817f8181, 0x81817f7f, 0x7f7f8181, 0x817f817f, 0x7f818181, 0x7f7f8181,
+0x7f7f817f, 0x7f7f8181, 0x7f7f7f7f, 0x8181817f, 0x81818181, 0x817f8181, 0x7f7f7f7f, 0x7f81817f,
+0x81817f7f, 0x7f7f8181, 0x81817f81, 0x817f7f7f, 0x817f7f7f, 0x7f817f81, 0x817f7f7f, 0x81817f7f,
+0x817f817f, 0x7f7f7f81, 0x817f7f7f, 0x817f817f, 0x817f7f7f, 0x817f8181, 0x81818181, 0x7f81817f,
+0x7f7f8181, 0x7f81817f, 0x81817f7f, 0x7f818181, 0x81817f81, 0x817f7f81, 0x7f7f8181, 0x7f817f81,
+0x7f7f7f81, 0x7f7f7f81, 0x7f7f7f7f, 0x817f8181, 0x8181817f, 0x817f7f81, 0x817f7f81, 0x7f817f81,
+0x7f7f817f, 0x7f817f81, 0x7f817f7f, 0x7f817f81, 0x81818181, 0x81818181, 0x7f7f7f7f, 0x81818181,
+0x7f817f7f, 0x81818181, 0x7f81817f, 0x7f817f81, 0x81817f7f, 0x817f7f81, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x7f7f817f, 0x7f817f7f, 0x7f7f7f7f, 0x817f8181, 0x81817f81, 0x817f7f81, 0x7f7f7f81,
+0x81818181, 0x7f817f7f, 0x81818181, 0x7f818181, 0x817f7f81, 0x7f817f7f, 0x81818181, 0x81818181,
+0x7f817f81, 0x7f7f7f7f, 0x81817f7f, 0x7f818181, 0x81817f7f, 0x81817f81, 0x8181817f, 0x817f817f,
+0x817f817f, 0x817f7f81, 0x7f7f8181, 0x817f7f7f, 0x817f8181, 0x7f7f7f7f, 0x7f7f7f7f, 0x817f7f81,
+0x817f7f7f, 0x7f7f8181, 0x7f817f81, 0x7f81817f, 0x817f7f7f, 0x7f7f7f7f, 0x7f7f8181, 0x7f7f817f,
+0x817f7f7f, 0x81818181, 0x8181817f, 0x7f817f7f, 0x7f7f8181, 0x81817f81, 0x7f81817f, 0x7f7f8181,
+0x817f7f7f, 0x817f7f81, 0x7f81817f, 0x7f7f7f81, 0x7f817f81, 0x8181817f, 0x817f7f81, 0x7f817f81,
+0x81817f81, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f81, 0x7f81817f, 0x817f817f, 0x7f817f81,
+0x817f7f81, 0x7f7f817f, 0x7f7f817f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f817f, 0x8181817f, 0x817f7f7f,
+0x7f817f81, 0x7f817f7f, 0x7f81817f, 0x81817f81, 0x7f817f7f, 0x7f81817f, 0x81817f7f, 0x7f7f7f7f,
+0x817f817f, 0x7f7f7f7f, 0x7f81817f, 0x817f8181, 0x81818181, 0x7f81817f, 0x7f817f7f, 0x8181817f,
+0x817f817f, 0x81818181, 0x81817f81, 0x81817f81, 0x7f7f8181, 0x7f7f7f81, 0x7f7f7f7f, 0x8181817f,
+0x7f817f81, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x81817f7f, 0x81818181, 0x7f81817f, 0x7f7f7f7f,
+0x81818181, 0x7f81817f, 0x7f7f7f81, 0x8181817f, 0x7f7f7f81, 0x7f7f7f81, 0x7f7f8181, 0x81818181,
+0x81818181, 0x7f7f8181, 0x7f817f81, 0x81817f7f, 0x7f7f817f, 0x817f7f81, 0x7f7f817f, 0x817f817f,
+0x81817f7f, 0x7f7f817f, 0x7f7f7f7f, 0x81817f81, 0x817f7f7f, 0x7f7f7f7f, 0x8181817f, 0x7f7f8181,
+0x7f817f7f, 0x7f817f81, 0x817f8181, 0x817f7f7f, 0x7f818181, 0x7f81817f, 0x817f817f, 0x7f7f8181,
+0x81817f7f, 0x7f7f7f7f, 0x817f7f81, 0x8181817f, 0x81818181, 0x7f817f81, 0x7f817f81, 0x7f81817f,
+0x7f81817f, 0x7f7f817f, 0x817f7f7f, 0x7f817f7f, 0x817f7f81, 0x7f7f817f, 0x817f8181, 0x7f7f7f7f,
+0x7f81817f, 0x7f7f817f, 0x817f817f, 0x817f817f, 0x7f817f7f, 0x7f7f7f7f, 0x7f81817f, 0x7f7f8181,
+0x817f7f81, 0x7f7f7f81, 0x7f818181, 0x817f817f, 0x7f7f817f, 0x7f817f81, 0x817f7f81, 0x81818181,
+0x81817f81, 0x7f7f7f81, 0x7f817f7f, 0x7f818181, 0x817f817f, 0x7f7f8181, 0x7f81817f, 0x7f81817f,
+0x817f7f81, 0x81818181, 0x7f817f81, 0x7f7f7f81, 0x7f81817f, 0x7f818181, 0x7f817f7f, 0x81817f81,
+0x81818181, 0x7f817f7f, 0x81817f81, 0x81817f81, 0x7f7f817f, 0x817f8181, 0x81818181, 0x7f81817f,
+0x81817f81, 0x7f7f817f, 0x7f7f817f, 0x7f817f81, 0x817f7f7f, 0x8181817f, 0x81817f81, 0x81818181,
+0x7f817f81, 0x7f7f7f7f, 0x81818181, 0x7f7f8181, 0x81817f81, 0x81817f7f, 0x7f7f817f, 0x7f7f7f7f,
+0x7f7f7f81, 0x7f7f8181, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f81, 0x817f8181, 0x7f7f817f, 0x7f7f7f7f,
+0x817f817f, 0x8181817f, 0x817f8181, 0x7f7f7f7f, 0x7f7f7f81, 0x81817f7f, 0x7f7f7f7f, 0x7f7f817f,
+0x7f81817f, 0x7f7f7f81, 0x817f8181, 0x81817f81, 0x817f7f81, 0x7f7f817f, 0x7f81817f, 0x7f7f7f7f,
+0x81818181, 0x81817f81, 0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x81817f81, 0x8181817f, 0x7f81817f,
+0x81818181, 0x7f818181, 0x817f7f81, 0x81817f7f, 0x81818181, 0x817f7f7f, 0x7f7f7f81, 0x817f7f7f,
+0x817f817f, 0x817f7f81, 0x81818181, 0x81817f81, 0x7f818181, 0x81817f7f, 0x817f817f, 0x7f81817f,
+0x817f7f81, 0x7f81817f, 0x8181817f, 0x7f7f7f7f, 0x8181817f, 0x7f7f817f, 0x7f817f7f, 0x817f7f7f,
+0x7f818181, 0x817f8181, 0x7f7f817f, 0x817f7f81, 0x7f817f81, 0x81817f81, 0x7f7f8181, 0x7f81817f,
+0x7f7f817f, 0x7f817f7f, 0x7f817f7f, 0x817f7f81, 0x817f817f, 0x817f7f81, 0x81818181, 0x7f7f817f,
+0x817f8181, 0x7f81817f, 0x7f817f7f, 0x81817f81, 0x7f7f817f, 0x81817f81, 0x7f7f817f, 0x81818181,
+0x81817f7f, 0x7f817f7f, 0x817f8181, 0x7f7f8181, 0x817f7f81, 0x81818181, 0x7f7f8181, 0x7f817f7f,
+0x7f817f7f, 0x817f817f, 0x817f7f81, 0x81817f81, 0x7f7f8181, 0x817f7f7f, 0x7f7f8181, 0x81817f81,
+0x7f817f7f, 0x817f8181, 0x817f817f, 0x81817f81, 0x81817f81, 0x7f7f817f, 0x7f7f8181, 0x7f7f7f81,
+0x81817f81, 0x7f81817f, 0x7f7f8181, 0x81818181, 0x817f7f7f, 0x7f81817f, 0x7f7f817f, 0x7f817f7f,
+0x7f818181, 0x7f81817f, 0x817f8181, 0x7f7f7f7f, 0x7f81817f, 0x7f818181, 0x817f817f, 0x81818181,
+0x7f818181, 0x7f817f81, 0x7f81817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x7f81817f, 0x7f7f7f81,
+0x7f818181, 0x7f817f7f, 0x7f7f8181, 0x7f7f8181, 0x7f818181, 0x81818181, 0x817f7f81, 0x817f8181,
+0x7f7f7f7f, 0x7f818181, 0x7f7f7f7f, 0x7f7f7f81, 0x817f8181, 0x7f7f7f7f, 0x817f7f7f, 0x7f818181,
+0x81818181, 0x7f7f817f, 0x81818181, 0x7f818181, 0x7f817f7f, 0x7f817f81, 0x7f7f8181, 0x81818181,
+0x7f7f7f81, 0x817f8181, 0x7f7f7f7f, 0x81818181, 0x81817f7f, 0x7f817f7f, 0x7f817f7f, 0x817f817f,
+0x7f817f81, 0x817f8181, 0x817f817f, 0x817f817f, 0x7f7f8181, 0x817f7f81, 0x7f7f8181, 0x7f7f7f81,
+0x7f7f7f7f, 0x7f7f7f7f, 0x8181817f
+
+e =
+34560
+
+k =
+6144
+
+rv_index =
+0
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_SOFT_OUTPUT, RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE, RTE_BBDEV_TURBO_POS_LLR_1_BIT_IN,
+RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c2_k3136_r0_e4920_sbd_negllr_crc24b.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c2_k3136_r0_e4920_sbd_negllr_crc24b.data
new file mode 100644
index 000000000..cfff56ad9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_dec_c2_k3136_r0_e4920_sbd_negllr_crc24b.data
@@ -0,0 +1,680 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_DEC
+
+input0 =
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xD0000000, 0x33CDC8CE, 0x4FAEE4CC, 0xC7DC23C3, 0xC306D6CA, 0x2B360A24, 0xE91C423D,
+0x1F323427, 0x4B1C33B6, 0x3EC9D0E7, 0x39204DD1, 0xCCD73C37, 0xC6F6D8E1, 0x1DF828F3, 0xDEE34025,
+0xC41EC235, 0xD035E1D8, 0x3CC32843, 0x29B60C3C, 0xE92E122E, 0x454BD4C8, 0x35D02543, 0x33E4D0AC,
+0x07AF2228, 0x38C62DD1, 0x233800C5, 0x3CC02DD1, 0x35E73B19, 0xDEBED026, 0x33C5EDD9, 0x33E51527,
+0x1F21EA18, 0xCC3E3BD2, 0x013CC14C, 0x3724D23B, 0x23CDED2D, 0x21424630, 0xC5B0E64D, 0xCFC03BEF,
+0x24294241, 0x46C526BC, 0xD82F334C, 0x1E283DCB, 0x3F3F33C7, 0x4A14D2A1, 0xD92F2AF3, 0xCFA820CC,
+0xDD30C6CB, 0x2B3ACAB7, 0x4AFE29CD, 0x25BD3200, 0x2D293323, 0xD32A3B29, 0x29E64D0C, 0xBE4BFB3C,
+0xB1DD242D, 0x0427F11D, 0x3046CFDA, 0xD633C0D5, 0xC0DDBE01, 0xDA3DD9B4, 0x3BCE3638, 0x23262CC6,
+0x432BD2AE, 0x23A9E1C7, 0x1BE45609, 0x22CD35AA, 0x32D6371F, 0xCE27352A, 0xE2B73F40, 0xC2D0CE2C,
+0xE72E3A3E, 0x2FF52147, 0xEFCF2E33, 0x003103CA, 0xC6C14A33, 0x45CAC0CF, 0x011E1FD3, 0x23D3C72B,
+0x2EB644C4, 0x484BD930, 0x3AC22E1A, 0x1AB6DD42, 0xCEDDE232, 0x3ACCCC31, 0xB830CA2D, 0xC930D2D7,
+0xD0E049BB, 0xE6243524, 0x3EF53914, 0xCB083BE3, 0x411EDBE9, 0x30C3C3E8, 0x3721F5E7, 0xBBDF3FD9,
+0x2AD21F33, 0xEE402858, 0xD3AFD237, 0x3D39401D, 0x30003623, 0x4734DC46, 0x192ACD32, 0x3324CAC2,
+0xD714D4B5, 0xDC2E21D0, 0x2327CDBA, 0x15B739C3, 0x31C9EEB8, 0xFAB5372E, 0xC239B5DA, 0xE628440F,
+0x34D425C6, 0x293BE6FD, 0xBDC04BBC, 0xE0DDB7CF, 0xD627BC34, 0xA5422FCB, 0x13211ABC, 0x1708E51C,
+0xCE33DAD1, 0x51AEC731, 0x2E383824, 0xC722D0D3, 0xCB32292B, 0xCECC402B, 0x1B312EF0, 0x34CF46CA,
+0xE3BD252C, 0x0C21EC36, 0x4ADFECBE, 0xC4D2E62C, 0xADE5BAD3, 0xDDCC1D18, 0x521AC135, 0x3F302D37,
+0x22CE2DCC, 0x262A1BCF, 0x4EE7D7CA, 0xD43D3526, 0x1840E020, 0xC3201F2F, 0x3ACB453E, 0x41EAD5B6,
+0xB6C4CF17, 0x243A55D4, 0xC7501E28, 0x351DCD1C, 0xE3A8D502, 0x3235271C, 0xAC342F00, 0x34B4E3D8,
+0x36473AE4, 0xAE403CEB, 0xBC3FDA3F, 0x552CDBEC, 0xE7C42B5C, 0xE743E13D, 0x18D44650, 0xBA2EDF31,
+0xB5C3EC42, 0x432EBE2E, 0xADDE4F2A, 0x401BCAD6, 0x03D6EAEB, 0xD0DEB133, 0x153FC4D4, 0x30DA2FD3,
+0xEE282FD9, 0x242ADC39, 0xD72B42D9, 0x44C7E0D5, 0xC72CB3C7, 0x27C9472B, 0x0036DFB6, 0xD9C53112,
+0xC0360E0E, 0x4EEA0E27, 0xEDCF27C1, 0x1739D5DC, 0x22DE2CE1, 0xDCCAF633, 0x31D02417, 0xD7DCD0DA,
+0xDE1DE0DC, 0xD827DD22, 0x1CDBD7EC, 0xCE171BCB, 0xEE2347CF, 0xC22C312D, 0xDBCC2A38, 0xBE0ADED4,
+0xDC20CC2D, 0xD5380DB2, 0x2A32C701, 0x3EC7D41E, 0xCDD7D74C, 0xE83E2A44, 0xC12B26E6, 0xE70046D7,
+0xD626D1EC, 0x35DDE41D, 0x303F27BD, 0xC94D4517, 0x31D1E229, 0xAD3529BF, 0x3AC5D21C, 0xCF1DB731,
+0x2738DBEB, 0x1F382B33, 0x1ED52213, 0xFCE22CD2, 0x1330331E, 0x4A30BA0F, 0x1F38B42A, 0x2E34CB1F,
+0xE3E125D5, 0x3AC72D17, 0xBD3C342C, 0x37272810, 0x1D34E4C7, 0xE5CC2EF8, 0x1E2FF1DF, 0xB9294236,
+0x26F10017, 0xBDE3FBD1, 0xB7DB52D0, 0x2E3CB8E9, 0xB3343D3C, 0x3E3BDFDD, 0x1F46393A, 0x25FA20C1,
+0x2D194CD1, 0xE9471D26, 0x34C3242E, 0xAE012034, 0xC8F3FED7, 0xB825362B, 0x322DC136, 0x42F41511,
+0x181855C2, 0x4937D5EB, 0xE13CDC23, 0x08242A28, 0x2DCCDFC0, 0x13CEC64F, 0xB3E6F7ED, 0xD93401EE,
+0x3D02DEE0, 0xCFC52300, 0xD2F1BE38, 0x2D092924, 0x253E2AF0, 0x37DACAD0, 0xDB1ECFE7, 0x40CED84D,
+0x3706C42A, 0x4231D91A, 0xDD30471D, 0xBD272DC8, 0xCB1941D9, 0xC22FC7C5, 0x333F3C0C, 0x3F3D2518,
+0xDDCCD143, 0xB3D834D5, 0xD231BEE4, 0x2BDB3B3D, 0x2F2754E7, 0xEAF3CE64, 0x3632E4C0, 0xD83324C2,
+0x11A4D5CC, 0x00D627D3, 0xD51F2731, 0x17C92BE2, 0x1AD62E1E, 0x16DB2418, 0x16B83823, 0x2711D54B,
+0xDFB02BDF, 0x28CDA600, 0x2AE9ED3E, 0xD314CD20, 0xD04F272D, 0xD0F9CD37, 0xCC1735E5, 0xD328EC37,
+0xA7D31A26, 0x214BD9A5, 0xCFCB4226, 0x233C4AD5, 0x26EF37D8, 0xD83E3230, 0x3EC8C93C, 0x07B9282B,
+0xD1E6DAF2, 0x31C52EDD, 0x3A0038A5, 0x56C1E0DF, 0x22E437C0, 0xDBC8143B, 0xCF1DB03F, 0x1D4BE636,
+0xB8D3C23A, 0xBCC3372E, 0xAF284228, 0xDCE02F1E, 0xB9D4E3D4, 0x56D3D0D8, 0x494816C1, 0xFB1240C3,
+0x23B1BDD2, 0x1236322E, 0xC2CBCB47, 0x102FE7C8, 0xBB0AE1D9, 0x3831BC29, 0x39AECBD9, 0xC7CF1ED2,
+0x0AE43913, 0xDDD62F2C, 0x4FD522E6, 0x3CB90A55, 0x2101C8EC, 0x432604BD, 0x29E3E31E, 0xC25B3C29,
+0x20E927D4, 0xD4300C41, 0xD9AECBD5, 0x48D8E143, 0x2CEE272F, 0xD2C11FBA, 0x2F2DB8D7, 0x1CF4DFE6,
+0xCCDCCEBF, 0xE052D0EA, 0xDADDEB1E, 0xC72ACB3A, 0x332E2B1B, 0x2D26E827, 0x2A29E6A6, 0xE614D6D5,
+0x221D1CC5, 0x51102031, 0x1735C248, 0x31D4DCD5, 0x3C20DC00, 0x2D231732, 0xE54AD9CD, 0x1D24D826,
+0xE936373A, 0x20C0D3C9, 0x2B231520, 0xD6CED133, 0xDFC8C7B5, 0xDC2FE8B8, 0x3332249B, 0xC6E6E11F,
+0xB7DA17AF, 0x1FD91321, 0xEE29CD41, 0xE1262FEF, 0xB6181DC6, 0x24F618C6, 0x3BE5DA2D, 0xFC2C35C8,
+0x51C232CC, 0x36183EDF, 0x2B2CD6EF, 0x2F2DBDB9, 0x00D03413, 0xCDC9CBC4, 0xDB3309CC, 0x264EB22C,
+0xCED1EAC9, 0x38D53F27, 0x2EE7D6F3, 0xC7232C23, 0xCCD42515, 0xC9C8C8E3, 0x231E3930, 0x5BBEDFCA,
+0x34D7E5D7, 0x25CCE9A7, 0xCD4BF1E8, 0x5E2542E6, 0x38DCE43E, 0xDA34F0CA, 0x2EBFF841, 0xDA422D3E,
+0x13CA2231, 0xD5C6DA27, 0xBAC0C6B6, 0xC82C49FF, 0x31312123, 0xBF00DFBF, 0xE8F23819, 0x2C34E81E,
+0xDC4C2B0C, 0x3A5650F2, 0x2CCB0FD0, 0xC42D4C28, 0x4F19DA4B, 0xF63DE630, 0x29F51C1F, 0xD6BE14C4,
+0xD2DDCDD6, 0xE0D02825, 0x2FE0E3D1, 0x41342FE8, 0x25D547ED, 0xC5A732B5, 0x19BD503F, 0x4CD9DA3D,
+0x24D013BF, 0x4FE93FCA, 0x12DBE8B9, 0x33DF151F, 0x1E24AECD, 0x2E2E3656, 0x133500AD, 0x3641403C,
+0xBDDF2BD4, 0xE33130E0, 0x3DC02726, 0x18390C3C, 0x26C04DC9, 0xDBF22D35, 0xC3E1EC45, 0xCED12623,
+0x1CE92E39, 0xCF2FD222, 0xD8DE31E6, 0x1EE916D1, 0x35DCB621, 0x19C2EB54, 0x41B34ED4, 0xD9373BDF,
+0x203ED6D8, 0x2CD4A8C8, 0x14E0C6C6, 0xDF242131, 0xCDD921CF, 0x33AACBCC, 0x2AD1A5C6, 0x3ED42B00,
+0xBF181FD0, 0xC0CC2329, 0x1BD1EDC9, 0x3A2D47CB, 0xDD27D8CB, 0xD8E8BAE6, 0xD5DE3FF5, 0x2C30D641,
+0xDCDCDF26, 0xC2C34433, 0x2837F53D, 0x29D8E12D, 0xBF3FEBD0, 0x34CACC45, 0x30E1DA21, 0x39DDDCB3,
+0x30193518, 0xC0132E19, 0x313D3736, 0xB2D4FF34, 0xF4D92945, 0xC70D3AEA, 0x3E3034F0, 0x00DA2F07,
+0x1DD415EB, 0xCC1AC4B2, 0x232EB21C, 0xD7431E16, 0x2FCE0835, 0xCF39242C, 0x1BCA2CD4, 0xD8B6D0FA,
+0x18C3262F, 0x2CE3BDCB, 0xD839DC38, 0x26161D24, 0x1223B3DC, 0xD6D63515, 0xCFBABFC6, 0xC1BF18C7,
+0x2637C715, 0x264020EA, 0xD024D3C4, 0x4126A11D, 0x2E34442D, 0x32BB1CC9, 0x36E7DD40, 0x3113C3C5,
+0xD100C8CE, 0xD21651E8, 0xC3CFCDD9, 0x403139F1, 0xD3D02119, 0x32171AC8, 0xD2F9B62E, 0xB5B335D4,
+0xC1462835, 0x1F1C2C35, 0xD8DDBF35, 0x422D2DDA, 0x38ED19D7, 0x3326BD2F, 0x4534DFCE, 0x46403132,
+0x19CDD51E, 0xCBC3CBC0, 0xE3CF2139, 0xC646ECD8, 0x29E7C7DD, 0xE94CCAF8, 0xB8C6EA37, 0xEC2B09DA,
+0xC8C82738, 0xC6CCDDFB, 0x3FCA3B4D, 0xC6482BD1, 0x2DE1D333, 0x3530BB3A, 0xBF4838EA, 0xE4411ACB,
+0x3514D939, 0xCD372B27, 0x4BEC1C39, 0xAB21C221, 0xD8D83F37, 0xCCE0512D, 0xDA4640C2, 0x36AE1CD6,
+0xBC2F303B, 0x20C3B8CD, 0xBFE6D4E0, 0xBECCC4EB, 0xC7CC1E4E, 0xCC2BD03C, 0x3738C518, 0x23B824CC,
+0x2BECD0BC, 0x2107B945, 0x2AC21B00, 0xBE49F2EB, 0x31D2E3DC, 0xDAD23F11, 0xCDED3137, 0x3ABADA3A,
+0xD9C0C12C, 0x36CEE8CF, 0xD0D5BDD3, 0x2AC9CFCC, 0xE61FD747, 0xC7B7B12A, 0x2BD520DF, 0xD5BC1D31,
+0xE6D8423B, 0xCC21EB43, 0x1F46292D, 0x171EE038, 0xDFA5E244, 0x1BD5C4AD, 0xC622C2B5, 0x4E33CFD3,
+0x3F263F30, 0x34E4CF15, 0x0041CC36, 0x4021DB29, 0xD62E2231, 0x2C22AE21, 0x1A201F44, 0xC6D7C100,
+0x3A335125, 0x42473A2A, 0xDF32DA1F, 0xE5D8B51F, 0x3049E832, 0xE6DED531, 0x315DD01E, 0xDDD92034,
+0x2EBF0AEB, 0x4B4639DD, 0xBED6C8DA, 0xDABA3714, 0xDD133BD7, 0xC934EACF, 0x0D35C3E2, 0xB4CCC213,
+0x37EE202B, 0x0AD21AD9, 0x28D2C9CD, 0xD800DB2D, 0xD34B274A, 0xBDD33644, 0x38EFF1CC, 0xBDABD734,
+0xB11E3E32, 0x2F1C23DC, 0xE80BD7DE, 0xDBE7D6F7, 0x240248BF, 0x23CEF1F6, 0x1F56E634, 0x33CD2230,
+0xB4DB182F, 0xD338BA36, 0x33392B24, 0xBB3B3649, 0x282F30E7, 0x45CC35B1, 0x46261B30, 0x1FD9A722,
+0x3BE3E1C3, 0x25334FF0, 0xB8BB28C0, 0xD751E2CC, 0x403600E1, 0x461FC3ED, 0xCB30C202, 0xD8D2B92A,
+0x2923D71B, 0xB9DDE6CC, 0xB935CB0A, 0xEF37D723, 0xD1DA06CD, 0x303CE928, 0xF8B9BA27, 0x37370A1F,
+0xD6C1DDD9, 0x18B6463F, 0x28C71FC3, 0x38D8B53A, 0xD22DE9A1, 0x18DDB236, 0x0A28D515, 0x363B263D,
+0x1F3A122D, 0x202AE323, 0xC72337E8, 0x32ED08CC, 0x2658C347, 0xC6F4E200, 0x45D1C2C3, 0xF92D343A,
+0x3EBE1E65, 0x10EB2FD3, 0xC64FD5E5, 0xC5D3F521, 0xE9CA1A37, 0xD736CDD6, 0xDCC7C233, 0xC9C8E2D4,
+0x2B99D60A, 0x1EE3DA0D, 0x30BDD8E1, 0x16D3BE1F, 0x1C4524D4, 0xC8D5D432, 0x19AEDA3D, 0xCDD4CAD5,
+0xD835332E, 0x2412DA1B, 0xD0CBEBD7, 0xC3CEF425, 0xD1D743E3, 0x000A163B, 0x23DC3129, 0x202332D1,
+0x322F2216, 0x28F5131A, 0xD316CF0D, 0xD0344C30, 0x423325D7, 0x37204237, 0xEEDDC721, 0x2038E805,
+0xD525C522, 0xBEDDE327, 0x3AC8BCC5, 0x45402E27, 0x34DFC1D9, 0x2DB0D049, 0x322F2ACF, 0xDB3AC3C5,
+0xD8D0EB4F, 0x2A1DCCCC, 0xD0D33DC2, 0x1349DC45, 0x39CBBC32, 0x30301EBF, 0x2C00DFC0, 0x5DD0CA11,
+0xD0220C3A, 0xC527CD1A, 0x31CD372C, 0x2E0ED7DC, 0xC6F92338, 0xF537E8D0, 0x3626DBBF, 0xC9C3C6C3,
+0x30DDBE17, 0x50394C39, 0x3A11343B, 0x27E8DC2E, 0x0DDB303F, 0x1818BCF0, 0xC5DC17DB, 0x24C53A26,
+0xECB0E7E2, 0xC21B1928, 0x15D7C920, 0x4126AACE, 0xE214D8C7, 0xD40BCD42, 0xB2CBD018, 0x554436DB,
+0x3C2D25D9, 0x21CEC0DC, 0xE9251919, 0xE41ACDC3, 0xDECF67C3, 0xEDDE3225, 0xCA30EEDD, 0xCFE01E37,
+0xD231BF41, 0x34DF1EBD, 0x1DD2CC2C, 0x21142E29, 0xEA322B37, 0xCEC311DE, 0xF0F738DD, 0xEBED1A40,
+0xDCE640E8, 0xD0D1BA2B, 0xE906D6DB, 0xC71938B1, 0x13C59F39, 0x1ED6DBB6, 0x231BD3A9, 0x2C2B30DC,
+0x0ED50000, 0x2DD4EED6, 0xD9D21BEE, 0xE1442E36, 0x38CEC4AE, 0xC626CCF4, 0xC2CD3F36, 0xD71F2BD9,
+0x2F421837, 0x31B11A23, 0xD4D5282D, 0xD0E6BED7, 0x30D737CB, 0xC8142A09, 0xD8D2CFDC, 0xC22D3C44,
+0xF62DF1C9, 0x3D38DBC9, 0xBFC2E5D3, 0xDCE42128, 0x3A304038, 0xDBE6D626, 0x28250FE0, 0x27B52BCF,
+0xE0D8DC3C, 0xC8DA09DA, 0x2DF02FD4, 0xE539D7D1, 0xCDE729C2, 0x4816E313, 0x4E392AC5, 0x112CF50F,
+0x3AD94924, 0x4B22273A, 0x43D2DE9E, 0xDA22DE30, 0x3FE324DB, 0xD9CC2811, 0x29D253D4, 0xE2BC353C,
+0x0CC92147, 0xB8F0C6F5, 0x3D35DEBF, 0xED4ACBEB, 0xAC34E532, 0xEA2AC526, 0xEAC0BFC8, 0x4431D9DD,
+0xC0CE4E21, 0x0000F2DD, 0xE0D8C7BA, 0xDDDC2E36, 0xDA42C22B, 0x2B312614, 0xDC391EF4, 0xCC2E31D8,
+0x3DF4D630, 0xC72C21D9, 0xDB2BD531, 0xD916DB3C, 0xBEC11DD2, 0xD1D5CEA4, 0xBA072ED7, 0x402F2829,
+0xE3C0F627, 0xC7CC3CBD, 0xF41D3345, 0xD706DB14, 0xB2DF36AC, 0xEBC4551F, 0x32B01929, 0xC5B6DDEC,
+0xD91DE130, 0xE1213222, 0x4126D927, 0xAF52300D, 0x291B301C, 0x241A1843, 0xE43C1FDC, 0xBBCC191C,
+0x2C25E011, 0xBD3EE9DB, 0xC9BF1345, 0x2F333AD2, 0x1CD822DB, 0x23BE43EA, 0x2527EADC, 0xB52E1C1E,
+0x391CCF17, 0xD2C82C0C, 0x242E3830, 0xD328D808, 0x35CEF4CD, 0xD81BE035, 0xD0DF38DA, 0xD1D3C42E,
+0x3A2C1EEA, 0xC6D03AD2, 0x1E362E4E, 0xE6080000, 0xD018C312, 0xEFAA323B, 0xD1294BD2, 0xBAD52C3B,
+0xE0373E10, 0x260CDDE2, 0xC902E040, 0x30472BD5, 0x534BE7D2, 0x20CCB523, 0x21CCD843, 0x2259E24E,
+0xDE35FDD1, 0xD4D91D3E, 0xCFCA11D5, 0x35D724BD, 0x3C3F0CB8, 0x3EC447CB, 0xE835DDC4, 0xC3C73E31,
+0xDD432B2F, 0x2FDCBDC2, 0x2D3CCE17, 0x25B8AB31, 0x2ACCFFE5, 0x40E03C2B, 0xE7DA1841, 0x17E53020,
+0xD44E0B2F, 0x46DA22EC, 0x33422425, 0x211840C5, 0x23C1CFD5, 0xC8350BE5, 0xD833CDD0, 0xE63DC528,
+0x292ADC17, 0xD8BCD3C1, 0xCD39F02E, 0xA71EC343, 0xD6CC3A3E, 0x2E12D2CF, 0xC40B1FB1, 0x37DCDC33,
+0x20E52EEA, 0x271629E5, 0xC4BEE0C2, 0x1B3CDBD6, 0x00004934, 0x18E145C7, 0x4BE93522, 0x3029C309,
+0x31D1D50F, 0x3DB42C1A, 0x21A643B2, 0x3E26D8C2, 0xCDDE28D1, 0x44E835E1, 0xEDC4DED1, 0xC4F9C9ED,
+0xC5E1BBCC, 0x4426C1D4, 0xD9BB372B, 0x37232E0D, 0xE5D0D0AE, 0xC9D23CC5, 0xF638E2C7, 0x2DB6E6D9,
+0xC0C9B72D, 0xDF28E6D0, 0x11E2DCC8, 0xD8E2F31C, 0xEA3937DE, 0x2741B953, 0x19D5CEE6, 0x33DDC22D,
+0x2BF72326, 0x2143363C, 0x13CA1A1F, 0xB9D7DAC9, 0x22C6B72E, 0xC5DA2631, 0xCB32ECCF, 0x032D15D4,
+0xBB1EE613, 0x38C42452, 0xDBCD2726, 0x1AF44039, 0x22CF2EC6, 0xCAEDE6B4, 0x2823D423, 0xDCC61C39,
+0xC12D19BF, 0xC612C31B, 0x31F1D32D, 0x3E1C09E4, 0xD824C5E7, 0xDFFC2839, 0x2AD40000, 0xDFCCBBBC,
+0x3FC9CC12, 0xEF2626E1, 0x0FCDEA2A, 0xEBD735CF, 0x4E1A2834, 0xCDEDE1D5, 0x31CCCD29, 0x2F4618DF,
+0x48C11936, 0x29DADE41, 0xD71C1AE0, 0xDDD2285A, 0xB13DCDC8, 0xF020B8DB, 0xD0B837C2, 0xDC3B48E8,
+0x18C3C530, 0x192C2940, 0x2ADA3AE4, 0xEA34C55A, 0xDAB2BED4, 0x1A51E838, 0xC832AEBE, 0x10DE2DE2,
+0x3B2408CC, 0x22CEBD1E, 0xC919D6BE, 0x21D2D128, 0xCFE03A2A, 0xB7DEDC3B, 0x33C630ED, 0x5A0EEAD1,
+0x3CB03FCE, 0x24EC15E4, 0xD0385BBF, 0x20CB4E4B, 0x30E0C535, 0x301BCD3C, 0x3642DDD3, 0xD90FDC50,
+0xCA35BBCC, 0x393B3B2F, 0xE2BE352D, 0x362BE3BF, 0x1922B73D, 0xDE3448BD, 0xF7C0C02D, 0x00002F43,
+0x2FCAD0E4, 0xDE412A34, 0xFBF339DA, 0x2BB94330, 0x39B521D5, 0x2DE31F43, 0x382C4F23, 0x35314C2D,
+0x2DE3DBDC, 0x3A18EAB9, 0xD0DF131C, 0x45EA41E0, 0x48BBC1BF, 0x2220D7E4, 0x29C8D0C5, 0x3C0527CA,
+0xC1ED061C, 0xCB48CA3E, 0xE846E633, 0x0EB2D7CF, 0x44C42335, 0x27F0D440, 0x332FD847, 0xD72F2CE3,
+0xD7ECD6C9, 0x4026D51F, 0xD334BEE6, 0xE01B40C5, 0xD62BDA2F, 0xDEEA36AF, 0xABD039C7, 0x2E123FCE,
+0xFD3924A8, 0xD0C6D529, 0xD52AEED4, 0x211D2A35, 0x1EE9C5F1, 0xCECAF921, 0x38C92740, 0x3E4E2A1A,
+0xB8FAC7C3, 0xF11F1C36, 0xD4DA163A, 0x2701DC38, 0x0E3019D5, 0x57DB23E1, 0x43CD26D0, 0xADCC4934,
+0xE0D3D706, 0x403A0000, 0xDECED5E1, 0xDAE6CF1D, 0xD5E33C40, 0x35B3D038, 0x24D73231, 0x2EC01D40,
+0xC2D23CDC, 0x44C20BC6, 0x44C1D7A8, 0xE9D1C745, 0x36E5C2C6, 0xB81B2D42, 0x413917CC, 0xD8E031BA,
+0xCE3CC1C4, 0x3EC91AC5, 0x0DE406CE, 0x35D1DA27, 0xC8E5CAE3, 0x313EC127, 0xB61631CA, 0xD73B3444,
+0xD834C850, 0x37D31DE2, 0xCCC9153D, 0xBF41E9CA, 0xD649F9DC, 0x3A31D501, 0x50CD1DE3, 0xC8E54012,
+0x4432D4D5, 0xCBB93023, 0xE8FCD6C2, 0xCEE0CAD1, 0xE41B2E39, 0x28CC0E40, 0xDFEAEFFD, 0xB3EA2723,
+0x3534B935, 0x42D12A09, 0xED3DCA0A, 0x263C352B, 0xAD224EDF, 0x2CDF2A10, 0xF0BE4CAD, 0xBD45D8D5,
+0x263F27D4, 0xE2372FB4, 0xC35240DF, 0x1EF3DCDA, 0x3AD0D224, 0x27DAD527, 0x303A2CBE, 0xCDDCC829,
+0xE22B35C9, 0xD5DC222F, 0xEEBDCB63, 0x2042DAD8, 0x06CC3524, 0xD11BBB3E, 0xAE2229E6, 0x1FC81E1F,
+0xEF4B12DA, 0xE1D846DD, 0xBA3B1CDA, 0xE154C801, 0xD6092CD2, 0xD0F132CB, 0x3A40D027, 0x123530BB,
+0x1EC5B4DC, 0xD11825CB, 0xC603DECC, 0x28BCC5ED, 0x2C03E1CD, 0xE9AA12A5, 0xDB2DD53A, 0xCA32D01E,
+0x2F4A09C5, 0xFE411E26, 0x1354CEC8, 0x3736C5F4, 0xC62F3C3B, 0x252DDFB9, 0xD0353723, 0xD8DDC21E,
+0xE3DF21ED, 0xDAE33AC0, 0x2ADA323E, 0xDC43E1D9, 0x3A23463E, 0xD71934F8, 0xDB1037C8, 0x38B7BCCC,
+0xDA2C1CC1, 0x3EEEE349, 0x2ACB2A26, 0xD4BCBCD8, 0x4AB50000, 0x9EC941D8, 0x3824C9D0, 0x203CCD36,
+0x0DCDEDD8, 0x5B333036, 0x3125C7DD, 0xD7383F30, 0xD6C72617, 0xE1C245DD, 0xBDD3E818, 0x3210422F,
+0xD00ECF2E, 0x44411A3A, 0x02E72E22, 0xF106D24C, 0xCFC847CF, 0x0421AFCF, 0xD2C525A9, 0x3CBCE63A,
+0xE02A1E36, 0xE036E3E4, 0xDDC22B25, 0x2EC7452E, 0xE1E3EFE3, 0xD82ED6CE, 0x36C1E115, 0xD129E026,
+0x251E1C44, 0xE8E5D7CA, 0xDDE7D40F, 0xC5D8D9D8, 0xA1C52550, 0x3ACDDA25, 0x3548C4E1, 0x2913D9C8,
+0x1E28243A, 0xCA3324E2, 0xD0D7D1C0, 0xBDE9D0C4, 0x35BF4FE0, 0xCA42E33C, 0xBBFA33DA, 0xD753C9CD,
+0xDA2CE11D, 0xD9BEE407, 0xE31DD4C1, 0xCBCCD51B, 0x3BB8D6C9, 0x0000DDDD, 0x28D3CDDC, 0xD62445B5,
+0xB3211F13, 0xD7B9BF29, 0xD429D5E5, 0xB9C23CCE, 0xC219EDC1, 0x211E0B34, 0xB8F0E1C1, 0x33C0EF4C,
+0xD8D6C7D0, 0x30E8D3D8, 0xB06514D1, 0x21B9D915, 0xE2323DCD, 0xDA41311F, 0xE24AB11F, 0xE9B92BE7,
+0x33EA23C3, 0x04C430C0, 0xE849EF0D, 0xD1232C2C, 0x260FD13E, 0x002DCBDD, 0xEB3129E2, 0x20B4C7C6,
+0x25D32335, 0x2CCB39D0, 0xEA13DAC6, 0xCDEE2E14, 0xCDAA2CD0, 0xE1D339E6, 0x36DCD03B, 0xF5453114,
+0x34D428ED, 0xEAEDF458, 0xD226CC2D, 0xEDD03AD8, 0xEE1CC83D, 0x10DBB5E5, 0xF018CBDB, 0x5E33E31E,
+0xC6D9232B, 0x1A373130, 0xDFE7DDCB, 0xB21FC5C6, 0xC1CDB1B7, 0x3F2DF128, 0x482BB426, 0x323E0000,
+0xF5D43741, 0xCC1C1FB9, 0x00004E2E, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x13000000, 0xC9112F26, 0xE3DF1FED, 0x284020CF, 0xC6ED13CA, 0x38B1E217, 0xD90FE8DB,
+0xD7C0C3B7, 0x341336CE, 0x45E2D239, 0x3E22F0D8, 0x461D2C29, 0x3825D628, 0xD733E5F1, 0xD7B6C532,
+0xC62B28C7, 0xD0BF3024, 0xF0BA3A26, 0x2D1D2836, 0x1BCF2DDE, 0xD02B251A, 0xB938CD2C, 0x34E220D9,
+0xC2BEC23B, 0xCC2908CD, 0x1D080039, 0x42BB25C5, 0x32EB3206, 0x36D3D1E0, 0xC32E10C3, 0x243B13E6,
+0xC02A1FF0, 0xC325D6DD, 0x23E33D2C, 0xDCD7DED5, 0x9C23C21D, 0x32E62056, 0x06314421, 0xE9E4ED24,
+0xC0C9C233, 0x44BE3FDD, 0xD25134E5, 0x292EE2E7, 0x4EE0D1DF, 0x29C82E3A, 0xF5392A22, 0x4BE2D133,
+0x58C2C4C8, 0xD2212920, 0x2935D4DB, 0xDECF4400, 0x31D7CCC9, 0x12DCFB2D, 0x2B2F0723, 0x2DE7B54E,
+0x2AD24ADA, 0x261E2931, 0xD538CEDF, 0xE12A1C2C, 0x33DDEDE9, 0x2FFC36C4, 0xE61823CE, 0xC225E1DF,
+0xC2102FEF, 0xCFD22617, 0x3EFBDA37, 0xDAD6BCD8, 0x110623E7, 0x3320E2D1, 0x1932B8D5, 0xCCEBBFC9,
+0x47234011, 0x0A2B45D8, 0x25C11244, 0x00EF3221, 0xC634CC38, 0x0F34D0E6, 0x1A3F40EA, 0x2DEDC82D,
+0xFFD2C8BD, 0x40E321CD, 0x24441BD3, 0xD932EDDD, 0x48362127, 0x1230EADE, 0x39E632F9, 0xD0D451DC,
+0x18DD2DC0, 0xC22AC72E, 0xD71E172E, 0xAFDED12B, 0x1DBAA948, 0xF927B647, 0xD7C31C23, 0x3328E73B,
+0xDBD72DD9, 0x3E23D424, 0xCB09E025, 0x16BA21CF, 0xDD00B9CB, 0x29E3CAD7, 0x3A19D011, 0xEA0EC4E0,
+0xD51CDDBF, 0x2AD1C640, 0x2CD6CBD3, 0x36D6D43C, 0xA72851C2, 0xE7EE3C3F, 0x432A4721, 0x46C726E5,
+0x253FD426, 0xD03B2C27, 0x1AEC343B, 0x5A2BC735, 0xCE31D2D2, 0xCFEDF30D, 0x492B4141, 0x20DC1BAD,
+0xDAF81CD9, 0xD6EAD21D, 0x2339CD25, 0xA31546BB, 0xD0C0F63F, 0x382BE719, 0xDA34BFDB, 0x1EDBBADF,
+0x5151E646, 0xC164D5E2, 0xD8292FCA, 0x33CF1F3B, 0x3FF531F4, 0xD3EB3453, 0xD433E236, 0x1B102B1C,
+0xC6C320E8, 0xD8393C2E, 0x17EAB7EB, 0xE0C42CE5, 0x313720CC, 0x3F39C42D, 0x33374AD5, 0xCE1ED41E,
+0xF7D2BE0D, 0xF114311E, 0xE22CD6EB, 0x4E23CA2A, 0xCDCF36D3, 0x463B1EC4, 0x312DE400, 0x1A1219CE,
+0x0CD1E2C3, 0x3850CBEA, 0x31D7CCCD, 0x3F2D3936, 0xC518E33E, 0xC31F31B7, 0xC0AED6C9, 0x2AC6E5D9,
+0xC334B8BF, 0x35EFD72E, 0xD72B3AD8, 0x31073AD7, 0x25E22D38, 0xF0CD4A64, 0x28DFDB2D, 0x22D9E714,
+0xB8E43935, 0x35FCBFEC, 0x1DC1391E, 0xD6E731A5, 0xBBC8B837, 0xBD3FBE3A, 0x00BADC53, 0x28C43F33,
+0x1CE0BAC2, 0xE0E125D9, 0x3BD6CB3D, 0x313230BE, 0xC4243D34, 0x1F24D2B1, 0x2058384C, 0x2AE9192D,
+0x302CCCEE, 0xD435C4C7, 0xB0D53217, 0xE52D32D9, 0xE0AF2127, 0x3E47D0CA, 0x4112BFCA, 0x27D0D0BD,
+0xE81E5CF9, 0xD50CBCE5, 0x2DC9B4F7, 0x3FBA33BC, 0xCBCC2821, 0xDFD51326, 0xD20ADA3A, 0x2000C3BB,
+0xC4DC4BE5, 0xCD39D7A7, 0xC40FF54F, 0xCC3BD1CC, 0x2C19EACC, 0xCD2E2129, 0x44D9F0DB, 0x2B40E11C,
+0x31343F4C, 0x0E142817, 0xD0104135, 0xE304CAC7, 0x259A1FD4, 0xC3EAED3C, 0x1A311AD7, 0xD8242BEE,
+0x20BF4EFD, 0x3FCA16C5, 0xDDEED03A, 0x0A22C52E, 0xD53B2D3A, 0xE22A2CB5, 0x291D3228, 0x2CCC2E45,
+0x48BA00D5, 0x4FE12D1D, 0xD8D91DD1, 0xCEDBEC31, 0xFBD526B9, 0x3C1DE845, 0xAFDCE91C, 0xD622D31E,
+0xCF2620D9, 0x28D63427, 0x362C3DDF, 0xD72C2530, 0xD6A7C203, 0x442C3233, 0x29B24E3F, 0xDD21412C,
+0x400BD6D0, 0xC8D4B831, 0x171EF12A, 0x34FFC9D0, 0x3B3ED02D, 0x0BC7E2CB, 0xC43D28C6, 0x42F6C948,
+0xD24AD429, 0xCB2C2A00, 0x43E2A236, 0xBC353312, 0xD91324B5, 0x30B4D013, 0xC92FDE2F, 0xBFD6D432,
+0xC82DCABC, 0xC032DC1D, 0x30C9D2CB, 0xE0341DC5, 0xDDCEBE39, 0x2CC41D58, 0xE213BF14, 0xDFCDCBD9,
+0x2E3C36DD, 0xE5262833, 0xF841291D, 0x15E324F5, 0x0315D732, 0xD1C5C5CA, 0xD73144D3, 0x2ABEBA1A,
+0xBCF42E2C, 0x00E1E53B, 0x4423AD2C, 0xB021CF20, 0xD8D5EEB6, 0xBD35BCCD, 0xE6D85334, 0xD549DF2D,
+0x35C74D19, 0x3F4BBE3D, 0x1F3FA3EB, 0xCEB2B335, 0x35D0BCBA, 0xD5D8CF27, 0xB11DCFC4, 0x24D3D408,
+0x183B35D0, 0x1C14D619, 0x35D445BB, 0xDE452444, 0xC83315C5, 0x3F2122D0, 0xB623C737, 0x33321DD0,
+0xD6DF33DE, 0xDE39AA20, 0xCF00F239, 0x412410D5, 0xC5DC2339, 0x1D3BD1B6, 0xC0E3481E, 0x1030451A,
+0x30EA30D1, 0xC6DCB9C7, 0x2C36DC17, 0xCBB0ED30, 0x26C20FBE, 0x35D6D528, 0xD6CC2242, 0xEDE4241E,
+0xC036DED9, 0x26303627, 0xB6B6371B, 0x26E3D6DF, 0x0D36C729, 0xBEEE4FD7, 0xE3C839D1, 0xC0313031,
+0xAEAD2828, 0x36323D23, 0x13342728, 0x2904EE20, 0x261DDCD6, 0x0CBCE1E1, 0xD2CBD5C3, 0xFD1C4B2C,
+0x1CD8CDDB, 0xD4BE53B1, 0x2BD6CDDE, 0xC61A01E1, 0x3D41BED3, 0xE0333BD0, 0x4040E821, 0xC4A32449,
+0xD3D3A8BF, 0x36E11C2C, 0x3CC1321B, 0xC5D03E1C, 0xB813D9DD, 0xD6C51838, 0xCEBED141, 0x1FEA3813,
+0x3611CAC0, 0xD12EE2C6, 0xE1BFD22D, 0xD0DAE9CC, 0x0E03DB00, 0xBC37393F, 0x422BC916, 0x49C4D72A,
+0xBFC0243B, 0xC1C2F1C3, 0xDF36CC32, 0x49E53EE4, 0xBFC02CDF, 0x2BEE2BE1, 0xC23224C5, 0xD63F16DA,
+0x15DBC21F, 0x49E4CC57, 0xBE272CC7, 0x274E0643, 0x5C1DDBE7, 0x34B73DF0, 0xCD2D2EB9, 0x1AD43BCD,
+0xFD3047D3, 0xDAC53936, 0x1328DCC8, 0xBC32331D, 0x001F2634, 0xC845410F, 0xDBDB1C2B, 0xD1D819D0,
+0xEBDDE12D, 0x37E335D7, 0xCDA84635, 0x0F362FBE, 0x30C229C4, 0xBC1DC43E, 0x3CD02F3D, 0x2EF5F5F4,
+0x462D15E6, 0x362F1FC5, 0xC0C9CD49, 0x14C92639, 0x2BD135D0, 0x49C6B8DA, 0xDBC7E1D9, 0xC6382328,
+0xEDC217BC, 0xE4D1331C, 0xDCC741CF, 0x283A341C, 0x38B93420, 0x46001BE7, 0x3E1030C4, 0x42A8C1CD,
+0xBB3339C5, 0xE538DD20, 0xDF3F2602, 0xE52BE5C1, 0xBE2B41BA, 0x3BD4D337, 0x2D39C3DB, 0xC3BB36F0,
+0xD12CCF17, 0x4130B93A, 0xE31DEAEC, 0xF9DEF52D, 0xADD35231, 0xD62ED0EF, 0xBE303521, 0x1E2ADB41,
+0x310AC62F, 0x22DA2DC5, 0x26E1D9D0, 0x1F4D2AC1, 0xC8E6DCE1, 0xC6B3D62E, 0xD6D20019, 0x4EDC2D39,
+0x342AE224, 0x07CBD4CB, 0xE43FB3BE, 0x1BE53748, 0xDD44C8A2, 0xBC34B7BA, 0xA1DD1D43, 0x23D31827,
+0x3519E93F, 0xC83B3720, 0x1BF0B72A, 0xEAC7DCC0, 0xCA4B28EC, 0xD54D242F, 0xF35435D1, 0x3DDEC824,
+0xC31128CE, 0x0B0FD136, 0x442D1E2B, 0xCBD1C3EC, 0xD635341B, 0xDD1F2931, 0x3442CDD0, 0xDADD3600,
+0xC31E40E3, 0xB0BD1B22, 0x38CA1F0D, 0xD42D3043, 0xE65127E4, 0x2F15C9D6, 0x3E360B30, 0xB2CB1524,
+0xC7BBC4DF, 0x38D244C7, 0x483B31C0, 0xDB43C8D1, 0x43DCDBBC, 0xDCC7571D, 0x24BAC2C6, 0x3B4ED6DC,
+0x3AE03245, 0x0C40E1E2, 0x493724C0, 0xD4ECC537, 0x36CC30BA, 0x1C303FC6, 0xD12F27D5, 0x00C4272F,
+0xFFFD061D, 0xC2D9251D, 0xC1D7D625, 0xBFCD3AD3, 0xB42E11D4, 0xC7230E1E, 0x24CD2C21, 0x0BD436F9,
+0xCECCD331, 0xE6BDE0D5, 0xD2C6C941, 0xE1D1D3EF, 0xEB4123CD, 0xDA1755E5, 0xCEE4C529, 0xDC43C5D1,
+0xD8FDDFEA, 0x1AC9C317, 0x22E13DCE, 0x01D7BA29, 0x1551E449, 0x43CD363E, 0xC6281B24, 0xCBD23725,
+0x3200D61C, 0x35D6CCBC, 0x262CB22C, 0xE2E43DB1, 0x26493335, 0x3AD72ACA, 0xC4244430, 0x3AD7C9C3,
+0xC91ED8D1, 0x40EAD2AC, 0x38C9CDAC, 0x413BC137, 0xCD304B1F, 0xEFCA2323, 0xAC3FE4CD, 0x3616F6E0,
+0x41C2272A, 0xDCD7B2E2, 0x27D9E018, 0xDEE2D943, 0xD5C01F22, 0xB0D93540, 0xB411C13D, 0xDE39CBE0,
+0xE2C6F126, 0x31450828, 0xD2BC2927, 0xBACA1DD1, 0x34DDCDC3, 0xD8302AD5, 0xE2D02824, 0x0B2BE03E,
+0x3BCAFD2C, 0x2E461D45, 0xBBF6F32E, 0x31E5DED2, 0x2ED4E847, 0x3BDDCD29, 0x231331D8, 0xF521CF2E,
+0xD024C718, 0x20D91011, 0xDB1E0F34, 0xD931C0BB, 0xBB310837, 0x29B7C5CB, 0x3B31DEE0, 0x0836B926,
+0x28CB1FD4, 0x31072A30, 0xEE41F300, 0x35CB501E, 0x603A2B47, 0x2C2739CE, 0xC0CFC4D9, 0xE0CED43C,
+0x22BDC9CA, 0xBAEC122D, 0x4D16F2C5, 0xB6E5C3DA, 0x19D5C9D0, 0x1D1DDFC2, 0x223A23FB, 0xCD382B09,
+0x3025C2E6, 0x3918BDD5, 0x33DFEF0E, 0x291A302B, 0x14184930, 0xD414D233, 0x473CCED7, 0xD2D318B7,
+0x3E2738D2, 0x2928D537, 0x002E14BB, 0xE2E03734, 0x1B1EDFD1, 0xCF483FD8, 0x3D043844, 0xD52E1C4C,
+0x2823EAD6, 0x1F2D241A, 0xBC4B22E6, 0x2EE7DFB8, 0x3424E2F0, 0xD41BD7CB, 0x2BBCDF1E, 0x155B5033,
+0xB527D543, 0xE3C5E9F4, 0xD9B5C92B, 0xD3CAE0DF, 0x31C4CED7, 0x0BD33B25, 0xCF3B111D, 0xE62F241F,
+0x22D93D22, 0xCF27EF43, 0xDAD2C5DD, 0xC60019BE, 0x2935D5C3, 0x2D0BCD22, 0x224714EA, 0xE7CAB817,
+0xD1282222, 0x3C25EBD0, 0x45F0A8DC, 0x3ACFB92D, 0x34B4E7E6, 0xE93523E0, 0x2C292FCA, 0x44D4C7AC,
+0xEA22C3FE, 0xEF37E524, 0x313ADCDA, 0x2212D846, 0x1BE0FF4B, 0x1CBC2E34, 0x174AF041, 0xD245223E,
+0xE1DB2BDC, 0xF2E9A515, 0xE3C33BCC, 0x43DBD5CE, 0xF11700DB, 0xDE44DD36, 0x26E1D604, 0xC2ACE419,
+0xB9D8C7D4, 0x37EFE21E, 0xE2BAC2D1, 0x3926E91A, 0xD013E8BC, 0x2C43ECD9, 0x232B30F8, 0xD6C9E0BD,
+0x26A718BC, 0xEFF6C840, 0xC13332C2, 0xC4B9BD36, 0x1B4921BD, 0xD0EBECE0, 0xBCE4D647, 0x35D4DCD5,
+0x1BBE4C27, 0xECC1B7CB, 0xD820284D, 0x0BC33DBF, 0x34D03140, 0x38EC3900, 0x29EBDBC9, 0xD43A3041,
+0x3AE0DD0C, 0x09CFCFDB, 0x44E0C7CE, 0x20DBC4E3, 0x26DC41DE, 0xBA3AD2E5, 0x2ABA34E1, 0xD70FBEB7,
+0x40E03FE2, 0xF8D62041, 0xBD47B7EA, 0xD2E03E34, 0x1FC6D2DE, 0xCF1CD155, 0x32D52630, 0x3C463D2C,
+0x253130E3, 0x1ED8BB4A, 0x411BDFDD, 0x3FD8EE35, 0x33D02BBB, 0x002ECAAE, 0xDF1FDFEB, 0x2CD8DA3C,
+0xB6352D59, 0xD5BDD3B9, 0x1946630D, 0xD9181731, 0xD419D31F, 0xCE2FB7D0, 0x32EFE3C3, 0xCDDB2FD3,
+0xD247BB3E, 0xBA41DECA, 0x23244AD2, 0xDEAAF2B2, 0xB8D525F2, 0xD327A4D0, 0x3718C0E2, 0x2D3E20D9,
+0x24CFDF12, 0x26D0BE1C, 0xC8D9282E, 0xEB54CADF, 0x44DB1AED, 0xC927BF29, 0x2E002B39, 0xBB2625E4,
+0xBB4421D2, 0x18CBAA3A, 0x213ECD37, 0x0F33163C, 0x3622E432, 0xE5C7C62B, 0xDE39E7C7, 0xF3151CCA,
+0x2ACED6D2, 0x2ADADFC4, 0xD6241ACC, 0xB92F0622, 0x1BC639E4, 0x33D92BC4, 0xAF14E0DD, 0xE6EEC2C9,
+0x16BDCAE3, 0x272E1AC3, 0x292E1EBE, 0xDCE439B1, 0x4225E1C6, 0xCD372420, 0x27D716B1, 0xD83EE339,
+0xDBCAD4B3, 0x26385033, 0xC5373528, 0x2DD2C936, 0xF9D5BAE6, 0x2E2DC7C2, 0xCD4BD045, 0x1DDF2DE8,
+0x0E3740CE, 0xE5D82C36, 0x29D1360A, 0xCD03C8C6, 0x37CCCCD8, 0xD83AD330, 0xBFD619CD, 0xDEDDC432,
+0xD0DADAEC, 0xD3E14F26, 0xA8CD35D9, 0xA3F325BD, 0xBC1626D7, 0x3AB81BD5, 0xBBFF1832, 0xC9DB2126,
+0x16250000, 0xE003BB39, 0x35D533CE, 0x1801C610, 0xD9D44644, 0x474BD3C3, 0x1C30C51E, 0x2E3342C6,
+0xB7D6B3E9, 0x5AE44BD2, 0x46D62830, 0xDBDD4B0C, 0x38CF2F1D, 0x2D331ACB, 0x36CCDED6, 0x10D7DA10,
+0xD42246E0, 0x0FC73FC0, 0x2C3E1E37, 0x2CF0D1B8, 0x17412EDD, 0x2630D0DD, 0xDBD535E4, 0xD927DA43,
+0xB636C11E, 0x25CBE2D8, 0x4711F64B, 0xBC2C2029, 0xD0E3F538, 0xB92C27DF, 0x272DE2D2, 0x0CC5BCEB,
+0xC0BC2EDF, 0x26D131C9, 0x1F092FEE, 0x2D342B34, 0x31B825D5, 0xC6BBC9C1, 0x38F1D0E4, 0xCBF7FDC7,
+0xC3CAC9B6, 0xDBC436C6, 0x19DC1FD8, 0x28CCAED1, 0x1921BDB4, 0x24BCBF33, 0x301EE244, 0x36BDBDE1,
+0x31C5B724, 0x00003ECD, 0x220B1EE7, 0xDEBAD3DC, 0x21CAB942, 0xC9193B33, 0xE3CD3A0A, 0x0DC22CC3,
+0x3EC0C7CB, 0x43F2BFE4, 0x0ECFE9C6, 0x3ECA2FD5, 0xCB492DD9, 0x23E7BDC9, 0xD33DC151, 0xFCBE2933,
+0x5ACEC51E, 0xF2172E1C, 0x3C24DE23, 0x3320D4D5, 0x2AB53C20, 0xC328323A, 0x45EA4133, 0x24391A32,
+0xC7D8DA2B, 0xF4EAAF39, 0xDFCA36E3, 0xDEBED5C8, 0x36252C36, 0x04D7DBC7, 0x30CAC23D, 0xB60BF73D,
+0xEACA2A30, 0x34C12ABE, 0xE2D747D8, 0x19D21FE3, 0x1DFD24EC, 0xB6B5D9C4, 0xBF2C1DD2, 0xD2B442E0,
+0x37CCE1BD, 0x2AD1E1CC, 0x18DAC6BD, 0x213AD93E, 0x2031D8CB, 0xD82F2D12, 0xD112D2F2, 0x19CD43F1,
+0x36BCB9CA, 0xD7C5DDFC, 0x34011D28, 0x3BDB0000, 0xCD00E1AA, 0x5228252C, 0x3512CA34, 0x0EE53A41,
+0x242CD2C2, 0xF425DD2A, 0xF02FDDF8, 0xD82026D3, 0x4ABEE7B8, 0x2DC9DDDC, 0x3BEECD3C, 0x2ED1442A,
+0xC713E92A, 0x310CC12B, 0xE128D520, 0x48E5C1CF, 0xC91CE3ED, 0xCCCBC72F, 0x0B23E3E9, 0xC1D2C8B6,
+0x511ED534, 0x2AC7D4C3, 0xCFDCE335, 0xD4C9F643, 0xD433EBF1, 0x1BF8DA31, 0x223FC515, 0xCC2F13C2,
+0xF825FFC8, 0x35E51633, 0x36293C4A, 0xC72ACA36, 0x4544E736, 0x1BD9315C, 0xCF16DFD4, 0xD0AFEFC3,
+0xCECBBDE2, 0x05D6AA32, 0xD851F045, 0x240FD948, 0x3D35B2E6, 0x17D7C7EE, 0x0B22DACE, 0xF53AD637,
+0xB2372DDB, 0xF6DF14CB, 0xBED95B24, 0xD4D5190B, 0x0000CB29, 0x3DC1ECF5, 0x30C6B34F, 0x1D2629B6,
+0xD429D1CC, 0xD50716E3, 0xD0C3C2CC, 0xC82CC7D4, 0x5F27C718, 0xE6201BE4, 0xDACFD42F, 0x2E2EE9D4,
+0x3AD036C0, 0x3828DB20, 0x27D63439, 0xD21026DE, 0xD60710BC, 0x13AEB9E9, 0x28C41944, 0x49D5E3D7,
+0x27163429, 0x1BBAD528, 0xB12A14BC, 0xC72FD9E2, 0x1F43213A, 0x133B3EE5, 0x3622FE21, 0xD438DCBE,
+0x41CB25E8, 0xD0D83E2C, 0x32BFC2CE, 0x362BE1DA, 0xC3CBCE24, 0x22DECDC2, 0x30CBD5CD, 0xD42DBC26,
+0xDDF6AAD0, 0xCADC0EC8, 0xDC333434, 0x333114F5, 0xCE24361A, 0xB1C5D123, 0x4B25380B, 0x2FEC3634,
+0x3EE2A610, 0xB4CEE72F, 0x29BCC721, 0xB23850CD, 0xA51AE4DD, 0xC81BBC2F, 0xD4DF0000, 0x2DE5D1E8,
+0x2E0A28D0, 0x29E3C1E1, 0x56F62DD6, 0x3828DD4B, 0xC41ACFDF, 0xD2390A3A, 0xDF3028CC, 0xE8C5E22B,
+0xD11CDCC1, 0x44D1CBEC, 0x33C73DDC, 0x1D25B7DC, 0xE7DD0525, 0x2743C41A, 0x2AE2D3DC, 0x21D6E82A,
+0x133CBAC7, 0x593F34B0, 0xDA5FE339, 0x5206252C, 0x394FD5BD, 0x21D2C92C, 0x292426E0, 0x48E0362B,
+0xCC272DE4, 0xC815C4DE, 0x49BD5D37, 0x1912342F, 0x2CE9E01B, 0x30D8D2D9, 0xDEBF46E8, 0x392F473A,
+0x3A18D324, 0x2FE31FD0, 0x2B2B2710, 0xB53B2AC7, 0xB3481CFF, 0x2DD7CFBC, 0x2232351A, 0xD7C91C16,
+0x1CB4DA16, 0x1BCBDF3C, 0xD2213822, 0x2121DB1F, 0xDBD1C02A, 0x27DA33C7, 0x351FC4CD, 0x0000B9D8,
+0xC2142C29, 0x38B9DD31, 0x54E60CDF, 0x2A4A42DB, 0x35CF2BB5, 0x0CEA3323, 0xC2D8BEE2, 0xC61F3B33,
+0x10CE11D0, 0x3336CE2E, 0x303ADD25, 0x3347B7D9, 0x33222C1A, 0x1A43E4C1, 0x4326E019, 0x2AE2E92E,
+0xD2C5DC40, 0xBA45D7D6, 0xDF341BDC, 0x3A361925, 0xD4FEF4D2, 0x3018DA31, 0xDDC12817, 0x3038DE24,
+0xEDC0292B, 0x3E3E3336, 0xCB1BEF17, 0xE10B2EBF, 0x2B20BABF, 0xC80C421B, 0xC2411D21, 0xECD8C7D6,
+0xC824E4AD, 0x65B53DD7, 0x304325D4, 0xDD1DEAE6, 0xD33131CF, 0x2F36452B, 0x23B219E9, 0xC1C23529,
+0x21DC3836, 0xD618E933, 0x393E2C14, 0x362ACA3A, 0xD6E2C237, 0xD6085111, 0xD721FCB1, 0xCCE6DEBC,
+0xD1DCD920, 0xC3320000, 0xEA26CB19, 0x18BB26B7, 0x233BDF4F, 0xDE23FD3F, 0x2ADA1ECB, 0x3122E839,
+0xEF42D7D7, 0xCAC7202D, 0xCD4CDED1, 0x2633C824, 0xD0123E4E, 0x104429B6, 0xC8CD4B00, 0x5136B738,
+0xCFC8202B, 0x163135DD, 0x2C3821E8, 0x29314CE0, 0x0F3CE4EC, 0xE5432DAF, 0xC63AE340, 0x4639DB18,
+0xDF282511, 0x25B5CBD3, 0xCAF50F37, 0x1E443B33, 0xE32CD32D, 0x10DA47B9, 0xDA410526, 0x34F0E4EA,
+0xCEED3134, 0xC0B31AA7, 0xD12B1AD3, 0xC722C743, 0xBFBEDD1F, 0xD328D52B, 0xCC384024, 0x18B43FB8,
+0x281742BB, 0xD8322FD2, 0xB5D628C6, 0xE420C0CB, 0xC9EB391D, 0x41E6B419, 0xBCC543E1, 0x2C37DDEF,
+0x1F2D41E9, 0xD0F0D205, 0x1FEAE5C5, 0x15DF14B8, 0x47E327D9, 0xD328CE25, 0x36DB2E24, 0xD92E1EBF,
+0x2B3230F4, 0xD1EAD5D9, 0xC7212ADA, 0xCD1235DC, 0xC519D5DB, 0xBFC631DF, 0xD5222B35, 0x35B6DEC6,
+0x153C4428, 0xC5C3E42F, 0x1B2E2D2A, 0x3CD422A6, 0xC22842CC, 0xCADAC43D, 0x2C10DAD2, 0x18C708B5,
+0x36D636BD, 0xCD29C5D3, 0xBFED433A, 0xE0384939, 0x005629F2, 0x36E2C425, 0x2830DF1C, 0xC9CB351C,
+0xB0D7D3E6, 0xF3CEC214, 0xDC25D1C7, 0x1BD5CBCC, 0x19DD21C9, 0xC854EE30, 0x4FE14EE3, 0x38D5D3E8,
+0xC9D126E4, 0x2FDD2130, 0xCE2130D1, 0xCFCAB0C9, 0xC71F0E1A, 0x2627D4DE, 0xCBE9DACD, 0xE7121F22,
+0x2CC8E435, 0x3838391D, 0xDD37242E, 0xEBBE2F10, 0x233C0000, 0xAFC91CE7, 0xCE3536F6, 0x0F25D248,
+0x2D04EBE4, 0x3FF634E5, 0xE929CE26, 0x24E0BABE, 0x302CD52B, 0xD1E2073F, 0x4333D11C, 0xDA48C2D1,
+0x2D33F315, 0x29B2C8C3, 0x3B26E3EB, 0x3821C6DA, 0x32163DD6, 0x1DC737BC, 0x463CCD24, 0x19D63DDD,
+0x200BDDB7, 0xBDD41E22, 0xC40A444F, 0x34BF49ED, 0xD4C0C0F4, 0xA41FB721, 0xBEDF51E8, 0x15D82A17,
+0x383FDF21, 0x2B2918D0, 0xE6EB4718, 0x244530DB, 0x25DD3919, 0x3BA819BE, 0xDAEFBE38, 0xEB3FCCD9,
+0xD1DF2E1C, 0x2520C3E3, 0x32D0BFD5, 0x37312BD5, 0xDC29D0C9, 0xBED02432, 0x310C3A18, 0x411ED8D7,
+0xA4E5CE22, 0x163CBD30, 0xC3E2BE45, 0xCFBBAAC3, 0xC8C0E4CF, 0x0000CEFC, 0xE8CC2433, 0x39ED223F,
+0x243AD83B, 0xD44D39C6, 0xCABF24DE, 0x252050EB, 0x29C73B40, 0xD4F434CF, 0xCAE4D5DF, 0xC5F2EEF1,
+0x2919C8D2, 0x2FC4D20B, 0x1CBF5528, 0x3DBBD52D, 0xE03AD031, 0x3D2CCA17, 0xBE23BDB8, 0xE7DA3B30,
+0xD1D2D331, 0xCC1825EA, 0x2F2D39D2, 0xF9313526, 0xCFBCC2E1, 0xE5BE3AD4, 0xBF59BE1C, 0x22FFC8B5,
+0x32B14015, 0x31D6BEE6, 0x46DF3843, 0xDCD1D8B2, 0xE728C8BE, 0xEA1E2A28, 0xD1D8C7D2, 0x30CAF134,
+0xEDD0EADA, 0x13C1E3D0, 0xB9D7DC29, 0xEAB93624, 0x24E49F38, 0x2E3FDEDC, 0xE6D0D23D, 0x1FBB3ED2,
+0x23D540DD, 0xD727D92B, 0x251E33E6, 0x4BA7EECE, 0xC1CD203C, 0xC5CFED32, 0xB9CF35C3, 0x29710000,
+0x29D7C636, 0x3A3ED1D0, 0xCC1B271F, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
+
+hard_output0 =
+0x42441F44, 0x006DFAE9, 0xDBB63AC2, 0xA3365CB3, 0xFA44372B, 0xC2603862, 0xA6C86E09, 0x416F0BF7,
+0x8E58011D, 0x47C54B99, 0x269AD14C, 0x0B286902, 0x093E4C64, 0x8D84D8E1, 0xB8AE0993, 0x49567118,
+0x8CEAABD2, 0x12D33409, 0xE3358237, 0x130176F6, 0x0986718F, 0xA18C83B5, 0x04EEF058, 0x59704040,
+0x7478FE81, 0x01D27193, 0xEA1AD7F3, 0x21E6C2B9, 0x6478A1FF, 0xED9959AD, 0xE39E57BE, 0x4D859105,
+0x056EF72D, 0xBD170BB7, 0xF01F9ADD, 0x99BF0C05, 0x44BAD09F, 0xF6ABDD61, 0xC0F8F116, 0x2972B53C,
+0x0FEC944B, 0xD1675432, 0x0025F563, 0xF42B2EA8, 0x808E5C37, 0xB6E79AD5, 0x3706284D, 0xB9C0AFA5,
+0xFF0E7E28, 0x5FA45C6F, 0x9CD5244E, 0xA013DDEA, 0x0D27D1A2, 0x2AE414AD, 0x41614379, 0xE6B68872,
+0x5585D926, 0x5098D45B, 0xF8980ABD, 0x65821418, 0xEF8968A3, 0x301DEC3A, 0x57EF2A7F, 0xC17BE446,
+0x94B65D62, 0xC9E6F350, 0x2E6130BC, 0x235F2E5E, 0xF1C13241, 0x94B291D6, 0x8C342458, 0x175B1FCA,
+0xE07310FD, 0xD24934DD, 0x3CE8D053, 0x5C8F243D, 0x945B0AB3, 0x50EB8CC1, 0x8EF499D4, 0xA67801BF,
+0x1680F061, 0x283FE705, 0xB8D7E773, 0x13AD3D2F, 0x4A6C305B, 0x1C1E5B12, 0x6F57D880, 0x8A666E5E,
+0x26511296, 0xFFC09750, 0xFF91760A, 0xAC26795C, 0x75F321FD, 0x4221B9CB, 0x2E119188, 0x0772A832,
+0x74D6036B, 0x505D6D64, 0x16A001B7, 0xF5F0D728, 0x48CBE119, 0x91C5D6B2, 0x8E1BBAB0, 0xB11BBE51,
+0x52C647DC, 0x65240CE2, 0xAB3F8AAE, 0x62E0CDEA, 0x6CBE7240, 0x7F572063, 0x7FC816E6, 0xB38E5A6C,
+0xDF9E2738, 0x752419CB, 0xC3A6BF9B, 0x8D48B21F, 0xA88C4AED, 0xE3C1D8BC, 0x8501353D, 0x20A99D7D,
+0x8D9C6DDD, 0x77A65039, 0x834E7E57, 0x1F623FA1, 0x6CF02B26, 0x1FF0BBA6, 0x9035AC70, 0xBED818E5,
+0x437CA713, 0x91011537, 0x3CD1302B, 0x7755459E, 0x5963FDA6, 0x49ECF937, 0xDEBBE0E3, 0xE873FD4F,
+0x735C48C9, 0x7C70F46F, 0xA00B1543, 0x789F4159, 0xE17C343E, 0x51B3D085, 0xD9042663, 0x771933DA,
+0xE183AF8C, 0xF62AC11B, 0xF776C25C, 0x22083E6C, 0x8400DDBA, 0x6D6AD2F2, 0x5DF87DBC, 0xBD7D40B4,
+0x356EBF21, 0xD8972E85, 0x3A632B51, 0x4D5BFBA2, 0x58CDF1D4, 0xD1117491, 0x5906DC45, 0xF793D63A,
+0x8F9D0552, 0xD261C804, 0x70BFDE9F, 0xDC77827B, 0xE9FFB130, 0x4FF18BBC, 0x17D50C32, 0xC315521E,
+0x4C7D2470, 0xAB5EE34C, 0x692AC0C8, 0x15B22832, 0xD34107FE, 0xA7E6DA1E, 0x2966A2A3, 0xD0B204B4,
+0x500E02F9, 0x02E5A455, 0x81EAF941, 0x6818F57A, 0x978EEC9C, 0xBFD575F3, 0x3FFC1BE8, 0x97104E07,
+0x4ADF219F, 0x182EC93D, 0x386033EE, 0x87C1351A, 0x31420C6A, 0xE20B5DC8, 0x83D90D23, 0x3C13B9E8,
+0xCCCD65BE, 0x7EDB17A9, 0x81C73C2A, 0xE202E332
+
+c =
+2
+
+cab =
+1
+
+ea =
+4918
+
+eb =
+4920
+
+c_neg =
+0
+
+k_neg =
+3072
+
+k_pos =
+3136
+
+rv_index =
+0
+
+iter_max =
+8
+
+iter_min =
+4
+
+expected_iter_count =
+8
+
+ext_scale =
+15
+
+num_maps =
+0
+
+r =
+0
+
+code_block_mode =
+0
+
+op_flags =
+RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE, RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN,
+RTE_BBDEV_TURBO_CRC_TYPE_24B, RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1190_rm.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1190_rm.data
new file mode 100644
index 000000000..6221756ae
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1190_rm.data
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11D2BCAC, 0x4D
+
+output0 =
+0xD2399179, 0x640EB999, 0x2CBAF577, 0xAF224AE2, 0x9D139927, 0xE6909B29, 0xA25B7F47, 0x2AA224CE,
+0x399179F2, 0x0EB999D2, 0xBAF57764, 0x224AE22C, 0x139927AF, 0x909B299D, 0x5B7F47E6, 0xA224CEA2,
+0x9179F22A, 0xB999D239, 0xF577640E, 0x4AE22CBA, 0x9927AF22, 0x9B299D13, 0x7F47E690, 0x24CEA25B,
+0x79F22AA2, 0x99D23991, 0x77640EB9, 0xE22CBAF5, 0x27AF224A, 0x299D1399, 0x47E6909B, 0xCEA25B7F,
+0xF22AA224, 0xD2399179, 0x640EB999, 0x2CBAF577, 0xAF224AE2, 0x24
+
+e =
+1190
+
+k =
+40
+
+ncb =
+192
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1194_rm.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1194_rm.data
new file mode 100644
index 000000000..c569abd78
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1194_rm.data
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11D2BCAC, 0x4D
+
+output0 =
+0xB3E8D6DF, 0xBC8A2889, 0x744E649E, 0x99436EA6, 0x8B6EFD1D, 0xAB889238, 0xE744E6C9, 0x39E4664A,
+0xE8D6DF91, 0x8A2889B3, 0x4E649EBC, 0x436EA674, 0x6EFD1D99, 0x8892388B, 0x44E6C9AB, 0xE4664AE7,
+0xD6DF9139, 0x2889B3E8, 0x649EBC8A, 0x6EA6744E, 0xFD1D9943, 0x92388B6E, 0xE6C9AB88, 0x664AE744,
+0xDF9139E4, 0x89B3E8D6, 0x9EBC8A28, 0xA6744E64, 0x1D99436E, 0x388B6EFD, 0xC9AB8892, 0x4AE744E6,
+0x9139E466, 0xB3E8D6DF, 0xBC8A2889, 0x744E649E, 0x99436EA6, 0xC01D
+
+e =
+1194
+
+k =
+40
+
+ncb =
+192
+
+rv_index =
+2
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1196_rm.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1196_rm.data
new file mode 100644
index 000000000..72be6f5d3
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e1196_rm.data
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11D2BCAC, 0x4D
+
+output0 =
+0xBC8A2889, 0x744E649E, 0x99436EA6, 0x8B6EFD1D, 0xAB889238, 0xE744E6C9, 0x39E4664A, 0xE8D6DF91,
+0x8A2889B3, 0x4E649EBC, 0x436EA674, 0x6EFD1D99, 0x8892388B, 0x44E6C9AB, 0xE4664AE7, 0xD6DF9139,
+0x2889B3E8, 0x649EBC8A, 0x6EA6744E, 0xFD1D9943, 0x92388B6E, 0xE6C9AB88, 0x664AE744, 0xDF9139E4,
+0x89B3E8D6, 0x9EBC8A28, 0xA6744E64, 0x1D99436E, 0x388B6EFD, 0xC9AB8892, 0x4AE744E6, 0x9139E466,
+0xB3E8D6DF, 0xBC8A2889, 0x744E649E, 0x99436EA6, 0x8B6EFD1D, 0x9038
+
+e =
+1196
+
+k =
+40
+
+ncb =
+192
+
+rv_index =
+3
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e272_rm.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e272_rm.data
new file mode 100644
index 000000000..883a76cf8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k40_r0_e272_rm.data
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11d2bcac, 0x4d
+
+output0 =
+0xd2399179, 0x640eb999, 0x2cbaf577, 0xaf224ae2, 0x9d139927, 0xe6909b29, 0xa25b7f47, 0x2aa224ce,
+0x79f2
+
+e =
+272
+
+k =
+40
+
+ncb =
+192
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e120_rm_rvidx.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e120_rm_rvidx.data
new file mode 100644
index 000000000..b3867f35f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e120_rm_rvidx.data
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11d2bcac, 0x7715ae4d, 0xc9f4dbc6, 0x2fda3c1a, 0x09349b16, 0x2cd3c189,
+0xe5650429, 0xc73c42c1, 0xe7336bb7, 0xbb7de593, 0x83f986aa, 0xc0ade12e,
+0x6730b095, 0x78f7c059, 0xaa907199, 0x75c323d1, 0x7061f9ba, 0x97e067bf,
+0xc155cd55, 0x6a4cb08d, 0x4260e2fa, 0xff35e496, 0x37f251d3, 0x02fd9f9e,
+0x6f53345c, 0x790cda6d, 0x3b8549e4, 0x56d0c6ea, 0x70a38006, 0xfff18223,
+0x6f2035b5, 0x6cf508d3, 0x98a0a308, 0x432353fc, 0x0eb818eb, 0xdd9a128b,
+0xf92431b2, 0xad788286, 0xda07d5de, 0x44b4b3a8, 0xbe62fd67, 0x61a4eb54,
+0x90d7ac9f, 0xc4d9a930, 0xfddc3c24, 0xf5e3b1c8, 0x38143538, 0xcb1d3062,
+0xcae36df3, 0x50a73437, 0x542dcab7, 0x875973a0, 0x34690309, 0x49cb1ddb,
+0xf8a62b92, 0x82af6103, 0xc9f8c928, 0x3835b822, 0x16b044a6, 0xdae89096,
+0xa5be47d4, 0xaf61189e, 0x5cd70faf, 0x037331cf, 0xef7fa5f6, 0xb2f2b41a,
+0xa6f222c6, 0xdb60fe4c, 0x2a857a9a, 0x0b821f9d, 0x348afd17, 0x7eecbaeb,
+0x92bb9509, 0x8a3cec24, 0xd02549a2, 0x155ffa81, 0x2b7feac6, 0x3ee461e7,
+0xc981f936, 0x89b544c7, 0x9a431e36, 0x62511734, 0x769f9647, 0x211a747e,
+0x567abef4, 0xad87e2b4, 0xa3e0c3bf, 0x6d325dd5, 0xf561cc46, 0x39925735,
+0x3d8abbfd, 0xc3724c88, 0x8bdf03c9, 0x1b02a12a, 0x4f233a0c, 0x9ca9444a,
+0xc5d1f7e6, 0x4d995f37, 0xd9aefb32, 0xd0465248, 0x0f3a3b21, 0x62ea8c0c,
+0x91f8d54e, 0x5cf75514, 0x14618a01, 0x8fe9b87e, 0xf2b424f9, 0x49724ce2,
+0xa1464587, 0x5e00dc83, 0x59475455, 0x444119b1, 0x4fb9f036, 0x65fcbc1a,
+0x1c63a990, 0x767a6114, 0xb0ede06a, 0xcfb91ae3, 0x7874af5f, 0xf78772a3,
+0xa2932c81, 0x77f2759d, 0x930dc8f1, 0x95ce14a5, 0x134363ee, 0x61ee143f,
+0xf0034b35, 0xfdc75fce, 0x3be2dcf3, 0xff3a07eb, 0xdc43f0eb, 0x23ba73bb,
+0x45f7649e, 0xcacc297c, 0xa3dd98db, 0x058d46a9, 0x6bcfc154, 0x7be8e1e6,
+0x618a4754, 0x8d193c46, 0xba39e1ce, 0xc3b85cfc, 0xd80d853b, 0x38d6440d,
+0x9c1a6185, 0x90c9dfcb, 0x01c6e841, 0xeedfe6ac, 0x7b61a3ae, 0xad3924dd,
+0x514bc1a8, 0x6ed60d7e, 0x1b74b79b, 0xea295947, 0x5f9a5d33, 0xcd24311f,
+0x0bd3d10c, 0xd214ecfe, 0xcb37035d, 0x8ce95168, 0x7020cb52, 0xe432107d,
+0x042d63ac, 0x6201c8dd, 0x4bea65a2, 0x1a3cf453, 0x5b8e868d, 0x3d653bb0,
+0x24c1967e, 0x37f183a9, 0x3700e703, 0xb168a02b, 0x2592cd82, 0x5c0cdb66,
+0x70b64ebd, 0xf8dcb9a7, 0x634a8335, 0x06642398, 0xfe2f4497, 0x2e775256,
+0x30f85cbe, 0xf4d2fdaf, 0x46ca6c9d, 0x022097d6, 0xcedeb03e, 0x3d8353bc,
+0x0d005559, 0xd457eb38, 0xb1931313, 0xd4f12824, 0xcc444f1b, 0xfaa42c5f
+
+output0 =
+0xd0d936d6, 0x870c26f3, 0x3f12805d, 0x4a6016
+
+e =
+120
+
+k =
+6144
+
+ncb =
+18528
+
+rv_index =
+1
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH, RTE_BBDEV_TURBO_RV_INDEX_BYPASS
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18444.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18444.data
new file mode 100644
index 000000000..dcad55878
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18444.data
@@ -0,0 +1,156 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11d2bcac, 0x7715ae4d, 0xc9f4dbc6, 0x2fda3c1a, 0x09349b16, 0x2cd3c189,
+0xe5650429, 0xc73c42c1, 0xe7336bb7, 0xbb7de593, 0x83f986aa, 0xc0ade12e,
+0x6730b095, 0x78f7c059, 0xaa907199, 0x75c323d1, 0x7061f9ba, 0x97e067bf,
+0xc155cd55, 0x6a4cb08d, 0x4260e2fa, 0xff35e496, 0x37f251d3, 0x02fd9f9e,
+0x6f53345c, 0x790cda6d, 0x3b8549e4, 0x56d0c6ea, 0x70a38006, 0xfff18223,
+0x6f2035b5, 0x6cf508d3, 0x98a0a308, 0x432353fc, 0x0eb818eb, 0xdd9a128b,
+0xf92431b2, 0xad788286, 0xda07d5de, 0x44b4b3a8, 0xbe62fd67, 0x61a4eb54,
+0x90d7ac9f, 0xc4d9a930, 0xfddc3c24, 0xf5e3b1c8, 0x38143538, 0xcb1d3062,
+0xcae36df3, 0x50a73437, 0x542dcab7, 0x875973a0, 0x34690309, 0x49cb1ddb,
+0xf8a62b92, 0x82af6103, 0xc9f8c928, 0x3835b822, 0x16b044a6, 0xdae89096,
+0xa5be47d4, 0xaf61189e, 0x5cd70faf, 0x037331cf, 0xef7fa5f6, 0xb2f2b41a,
+0xa6f222c6, 0xdb60fe4c, 0x2a857a9a, 0x0b821f9d, 0x348afd17, 0x7eecbaeb,
+0x92bb9509, 0x8a3cec24, 0xd02549a2, 0x155ffa81, 0x2b7feac6, 0x3ee461e7,
+0xc981f936, 0x89b544c7, 0x9a431e36, 0x62511734, 0x769f9647, 0x211a747e,
+0x567abef4, 0xad87e2b4, 0xa3e0c3bf, 0x6d325dd5, 0xf561cc46, 0x39925735,
+0x3d8abbfd, 0xc3724c88, 0x8bdf03c9, 0x1b02a12a, 0x4f233a0c, 0x9ca9444a,
+0xc5d1f7e6, 0x4d995f37, 0xd9aefb32, 0xd0465248, 0x0f3a3b21, 0x62ea8c0c,
+0x91f8d54e, 0x5cf75514, 0x14618a01, 0x8fe9b87e, 0xf2b424f9, 0x49724ce2,
+0xa1464587, 0x5e00dc83, 0x59475455, 0x444119b1, 0x4fb9f036, 0x65fcbc1a,
+0x1c63a990, 0x767a6114, 0xb0ede06a, 0xcfb91ae3, 0x7874af5f, 0xf78772a3,
+0xa2932c81, 0x77f2759d, 0x930dc8f1, 0x95ce14a5, 0x134363ee, 0x61ee143f,
+0xf0034b35, 0xfdc75fce, 0x3be2dcf3, 0xff3a07eb, 0xdc43f0eb, 0x23ba73bb,
+0x45f7649e, 0xcacc297c, 0xa3dd98db, 0x058d46a9, 0x6bcfc154, 0x7be8e1e6,
+0x618a4754, 0x8d193c46, 0xba39e1ce, 0xc3b85cfc, 0xd80d853b, 0x38d6440d,
+0x9c1a6185, 0x90c9dfcb, 0x01c6e841, 0xeedfe6ac, 0x7b61a3ae, 0xad3924dd,
+0x514bc1a8, 0x6ed60d7e, 0x1b74b79b, 0xea295947, 0x5f9a5d33, 0xcd24311f,
+0x0bd3d10c, 0xd214ecfe, 0xcb37035d, 0x8ce95168, 0x7020cb52, 0xe432107d,
+0x042d63ac, 0x6201c8dd, 0x4bea65a2, 0x1a3cf453, 0x5b8e868d, 0x3d653bb0,
+0x24c1967e, 0x37f183a9, 0x3700e703, 0xb168a02b, 0x2592cd82, 0x5c0cdb66,
+0x70b64ebd, 0xf8dcb9a7, 0x634a8335, 0x06642398, 0xfe2f4497, 0x2e775256,
+0x30f85cbe, 0xf4d2fdaf, 0x46ca6c9d, 0x022097d6, 0xcedeb03e, 0x3d8353bc,
+0x0d005559, 0xd457eb38, 0xb1931313, 0xd4f12824, 0xcc444f1b, 0xfaa42c5f
+
+output0 =
+0x11d2bcac, 0x7715ae4d, 0xc9f4dbc6, 0x2fda3c1a, 0x09349b16, 0x2cd3c189,
+0xe5650429, 0xc73c42c1, 0xe7336bb7, 0xbb7de593, 0x83f986aa, 0xc0ade12e,
+0x6730b095, 0x78f7c059, 0xaa907199, 0x75c323d1, 0x7061f9ba, 0x97e067bf,
+0xc155cd55, 0x6a4cb08d, 0x4260e2fa, 0xff35e496, 0x37f251d3, 0x02fd9f9e,
+0x6f53345c, 0x790cda6d, 0x3b8549e4, 0x56d0c6ea, 0x70a38006, 0xfff18223,
+0x6f2035b5, 0x6cf508d3, 0x98a0a308, 0x432353fc, 0x0eb818eb, 0xdd9a128b,
+0xf92431b2, 0xad788286, 0xda07d5de, 0x44b4b3a8, 0xbe62fd67, 0x61a4eb54,
+0x90d7ac9f, 0xc4d9a930, 0xfddc3c24, 0xf5e3b1c8, 0x38143538, 0xcb1d3062,
+0xcae36df3, 0x50a73437, 0x542dcab7, 0x875973a0, 0x34690309, 0x49cb1ddb,
+0xf8a62b92, 0x82af6103, 0xc9f8c928, 0x3835b822, 0x16b044a6, 0xdae89096,
+0xa5be47d4, 0xaf61189e, 0x5cd70faf, 0x037331cf, 0xef7fa5f6, 0xb2f2b41a,
+0xa6f222c6, 0xdb60fe4c, 0x2a857a9a, 0x0b821f9d, 0x348afd17, 0x7eecbaeb,
+0x92bb9509, 0x8a3cec24, 0xd02549a2, 0x155ffa81, 0x2b7feac6, 0x3ee461e7,
+0xc981f936, 0x89b544c7, 0x9a431e36, 0x62511734, 0x769f9647, 0x211a747e,
+0x567abef4, 0xad87e2b4, 0xa3e0c3bf, 0x6d325dd5, 0xf561cc46, 0x39925735,
+0x3d8abbfd, 0xc3724c88, 0x8bdf03c9, 0x1b02a12a, 0x4f233a0c, 0x9ca9444a,
+0xc5d1f7e6, 0x4d995f37, 0xd9aefb32, 0xd0465248, 0x0f3a3b21, 0x62ea8c0c,
+0x91f8d54e, 0x5cf75514, 0x14618a01, 0x8fe9b87e, 0xf2b424f9, 0x49724ce2,
+0xa1464587, 0x5e00dc83, 0x59475455, 0x444119b1, 0x4fb9f036, 0x65fcbc1a,
+0x1c63a990, 0x767a6114, 0xb0ede06a, 0xcfb91ae3, 0x7874af5f, 0xf78772a3,
+0xa2932c81, 0x77f2759d, 0x930dc8f1, 0x95ce14a5, 0x134363ee, 0x61ee143f,
+0xf0034b35, 0xfdc75fce, 0x3be2dcf3, 0xff3a07eb, 0xdc43f0eb, 0x23ba73bb,
+0x45f7649e, 0xcacc297c, 0xa3dd98db, 0x058d46a9, 0x6bcfc154, 0x7be8e1e6,
+0x618a4754, 0x8d193c46, 0xba39e1ce, 0xc3b85cfc, 0xd80d853b, 0x38d6440d,
+0x9c1a6185, 0x90c9dfcb, 0x01c6e841, 0xeedfe6ac, 0x7b61a3ae, 0xad3924dd,
+0x514bc1a8, 0x6ed60d7e, 0x1b74b79b, 0xea295947, 0x5f9a5d33, 0xcd24311f,
+0x0bd3d10c, 0xd214ecfe, 0xcb37035d, 0x8ce95168, 0x7020cb52, 0xe432107d,
+0x042d63ac, 0x6201c8dd, 0x4bea65a2, 0x1a3cf453, 0x5b8e868d, 0x3d653bb0,
+0x24c1967e, 0x37f183a9, 0x3700e703, 0xb168a02b, 0x2592cd82, 0x5c0cdb66,
+0x70b64ebd, 0xf8dcb9a7, 0x634a8335, 0x06642398, 0xfe2f4497, 0x2e775256,
+0x30f85cbe, 0xf4d2fdaf, 0x46ca6c9d, 0x022097d6, 0xcedeb03e, 0x3d8353bc,
+0x0d005559, 0xd457eb38, 0xb1931313, 0xd4f12824, 0xcc444f1b, 0xfaa42c5f,
+0x4fde636c, 0x10ea20a0, 0xe6da8721, 0xbfde5b08, 0x9c3739da, 0xb6dc015a,
+0x427db088, 0xdfdb8e6f, 0x756be6c1, 0x21f5297b, 0x06135665, 0xc1602b7d,
+0x049536c5, 0xbbb3b801, 0x0cdb0c19, 0x7b2ad622, 0xfee8218f, 0xc5c7f123,
+0x8abd3301, 0xa15b534d, 0x29dd2053, 0xd409abf9, 0x3ef19d6b, 0x70a3cbc2,
+0x7a51423a, 0x4505b2ad, 0xdc74c75e, 0x068751a9, 0xb0b56437, 0x14a10371,
+0x76af806f, 0xa8a47e19, 0x7c97a26e, 0x7998a3d6, 0xdc1ad1e2, 0xb532a301,
+0xca8a3e7d, 0xd0aef374, 0x204990c0, 0xc7011aec, 0xa69151ea, 0x53390026,
+0x7bf0d762, 0x735c2202, 0x64159e54, 0x5a3b1a56, 0x9ef1def2, 0x0ab8a961,
+0x587b0886, 0xb8cc5975, 0x2a5a0f23, 0x069d05be, 0x9cc3c207, 0x40ef1a02,
+0x4fae3f5b, 0x1f127aae, 0xd4e6d411, 0x17ac43ef, 0xe4bf891b, 0xfbb21765,
+0x2c560c7e, 0x8561988c, 0x73a01032, 0x0cfef73a, 0x694c4991, 0x885d7a3f,
+0x4218d1ff, 0xc2efaffb, 0xaf9d9715, 0xf76de6b2, 0xcce8e8ff, 0x370e3800,
+0x493675eb, 0xd8fbcbda, 0xa5b382c2, 0x86c8f1ea, 0x3d724ea4, 0xb067034c,
+0x6491d87e, 0x1a745ce4, 0xbb27180b, 0x1a2f0acc, 0xac4b7b3b, 0xe324578b,
+0xc87928df, 0x9c1de566, 0x0ce2a17d, 0xaf2e13ce, 0x146a8659, 0x8727f6ae,
+0xe2df7d03, 0x1a8e4cb4, 0xfa590976, 0x13a7c236, 0xc07489d0, 0xbe905e17,
+0xafeb3d4b, 0x201e73f2, 0x5bdca12e, 0x3e15a852, 0xbcfc3271, 0x5d398410,
+0x6bfacc15, 0x011fc61f, 0x43e43fd7, 0x0640717c, 0x96bfb3ff, 0x158eac19,
+0x3b852e91, 0x74f9ceda, 0xcac71326, 0xfc0e312a, 0x20e8137b, 0xa1162611,
+0x239ac7fe, 0xb9d00f8a, 0xea0b5241, 0x019f0d25, 0xc5153264, 0xb48a5547,
+0xe54e339f, 0x17a6cca5, 0x5065af0d, 0x5ce648b9, 0xb457b342, 0xc1cb3f0e,
+0x28d03c8b, 0x5144ed7a, 0xdb80779f, 0x53ce1b87, 0xbc071147, 0xbfe46c11,
+0x7296785e, 0x83e4a63e, 0xc58982e9, 0x9538c5b9, 0xf14abaaa, 0xd915124c,
+0x73540cd6, 0xe333696b, 0x58f9e00a, 0xd4dad10f, 0xc0de1420, 0x355e2bdc,
+0xb2faa8fd, 0xbe6a12f1, 0x45d415cc, 0x47f5aed9, 0x4754e770, 0x2bb07385,
+0x41374352, 0xf80beb47, 0xef02f35c, 0xc9c1b86e, 0x94b5785b, 0xba33123f,
+0x7e39f0c9, 0x028a9286, 0x7d52c9f1, 0x06f04da6, 0xbc6a68d1, 0xfc70bace,
+0x95b6a129, 0xfff224bb, 0x701ef3fb, 0x3309286f, 0x544ae8c1, 0xdca62c4a,
+0xf8862ee2, 0xf9e3cd29, 0x2c07cce2, 0x8d93652a, 0xf47e4611, 0x4635f586,
+0x1c03e0f4, 0x819724c7, 0x96b2a3f0, 0xeeb1ad95, 0xff08e517, 0xbd4ba6ed,
+0x49ddb12d, 0x365734b5, 0x5edf7459, 0x2ee117a9, 0x067b9462, 0xb703685f,
+0x72499876, 0xb71dd772, 0x5d02b478, 0x4b6fed1d, 0x2df232c1, 0x733eaaff,
+0x1618c029, 0x0adda94b, 0xd271e560, 0xd120ba30, 0x6dfecc73, 0x4e751af7,
+0x0e7a6b63, 0xa1ad5dad, 0xb41201b1, 0x245f3e86, 0x3a5114ac, 0x5cd532c9,
+0x27ff9c3a, 0x7a847392, 0x6b2d0514, 0x82d0cc45, 0x0c779ba2, 0x8690f3ef,
+0x0c058474, 0x47a8ee9a, 0xac4c2475, 0x496b67a5, 0x033f43f5, 0x6e6ce3c9,
+0x644f5163, 0x8f4b92d9, 0x217798ee, 0x4b8e5368, 0xce751989, 0x7ab05365,
+0xe227cee3, 0xf35e2851, 0x6f304c87, 0x1389c81d, 0x6ebc3989, 0x2b32ac3e,
+0x59c5d111, 0xa8e8699c, 0xa5b15150, 0x8cacebe8, 0x40c2ede6, 0x71ea78c9,
+0xa9e40f49, 0x58309eab, 0xd2eb879c, 0x54b9086f, 0xce206d93, 0x47e7087a,
+0xac1e1dd9, 0x1d3a7bf1, 0x07d21fd4, 0x3a84a2a7, 0xe3ce33de, 0x55c94ddf,
+0xd827c1ea, 0x3b4dcf5a, 0x7d5fbeb6, 0xd71ccdae, 0x516a9035, 0x33b3bee0,
+0x61201364, 0xcf344f8d, 0x8c887934, 0x1998c127, 0xe24f1190, 0x75e8ea20,
+0x8a379eda, 0x8a894b14, 0xa3d7c264, 0xa62b0119, 0x87f4d316, 0xecdc5f2b,
+0xbc2424ec, 0x71169a71, 0x61aa2d5d, 0xb5f5f160, 0xc15a4969, 0xc5419315,
+0xbf84483e, 0x2b1687c1, 0xd1aa06df, 0x22d5befd, 0x8b09b15f, 0xa88ffc01,
+0xbb33617f, 0xb01a3e2e, 0x912a939c, 0xc649d802, 0xeba14b11, 0x3c902b57,
+0xbcf35a8d, 0x45a964a1, 0x0c9416ef, 0xec9ae2d1, 0xc5e56fee, 0x88bfa336,
+0x653cfe85, 0x92d21037, 0x96bc60e4, 0xf5317c1e, 0x5e7118f4, 0x91a9e04b,
+0x43f0cfec, 0xb763dc3c, 0xad6bac40, 0x21685f69, 0x5e4d6f70, 0xd8d5a4c4,
+0x15ed5efe, 0x3bbefa38, 0xbf7cf912, 0xb1427ffd, 0x652235ff, 0x927a7046,
+0x8806625f, 0x56967b59, 0x6ec3dba6, 0x0ee31e0f, 0x25111a51, 0x091c763e,
+0x1867732b, 0x28365594, 0xa589c975, 0x585b906f, 0xb85c4f20, 0xced98475,
+0x52f29d16, 0x1ca0de39, 0xede3c4c8, 0xda808e91, 0x449784ab, 0xe3caf590,
+0xabf23939, 0xe97f259a, 0x0a879f81, 0x5c6268ac, 0x0a4f1b62, 0xfe15825e,
+0xbea5e6f9, 0x0d2db98f, 0xeec8cd64, 0x1747ddf5, 0x8b4f161c, 0xd236c9f6,
+0x1a5b5a2f, 0x08918e6d, 0xdde43ad9, 0x8c316d0f, 0x7f1b3342, 0x3e385cee,
+0x55ff6f87, 0x89bbe534, 0x67c23afe, 0x250dc97a, 0x06b3b332, 0x61a03930,
+0x2ca17159, 0x3260c4f6, 0x3c810bde, 0x28d94372, 0xa9701f5a, 0x3880475b,
+0x352ff389, 0x2bf653e0, 0xa4a6cc35, 0x4d211cfc, 0xeda0b37d, 0x14c0e6d8,
+0xe457aaea, 0x1c6ed15f, 0x155d3b90, 0x7f43aed4, 0x289a98f9, 0x42246910,
+0x62d047f5, 0x75714462, 0xe2c2a4df, 0x9dfc0f13, 0x03361f4c, 0xc55b5ca7,
+0x9dd89720, 0x17376073, 0xfb6ee849, 0x280e697e, 0x57b24f3a, 0x2089b956,
+0xa8baa602, 0x5b7ab88c, 0xd69f8b56, 0x64f80d52, 0x223427b9, 0xfd393c95,
+0xb074
+
+e =
+18444
+
+k =
+6144
+
+ncb =
+18528
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18448_crc24a.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18448_crc24a.data
new file mode 100644
index 000000000..345d1410f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e18448_crc24a.data
@@ -0,0 +1,159 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0x11d2bcac, 0x7715ae4d, 0xc9f4dbc6, 0x2fda3c1a, 0x09349b16, 0x2cd3c189,
+0xe5650429, 0xc73c42c1, 0xe7336bb7, 0xbb7de593, 0x83f986aa, 0xc0ade12e,
+0x6730b095, 0x78f7c059, 0xaa907199, 0x75c323d1, 0x7061f9ba, 0x97e067bf,
+0xc155cd55, 0x6a4cb08d, 0x4260e2fa, 0xff35e496, 0x37f251d3, 0x02fd9f9e,
+0x6f53345c, 0x790cda6d, 0x3b8549e4, 0x56d0c6ea, 0x70a38006, 0xfff18223,
+0x6f2035b5, 0x6cf508d3, 0x98a0a308, 0x432353fc, 0x0eb818eb, 0xdd9a128b,
+0xf92431b2, 0xad788286, 0xda07d5de, 0x44b4b3a8, 0xbe62fd67, 0x61a4eb54,
+0x90d7ac9f, 0xc4d9a930, 0xfddc3c24, 0xf5e3b1c8, 0x38143538, 0xcb1d3062,
+0xcae36df3, 0x50a73437, 0x542dcab7, 0x875973a0, 0x34690309, 0x49cb1ddb,
+0xf8a62b92, 0x82af6103, 0xc9f8c928, 0x3835b822, 0x16b044a6, 0xdae89096,
+0xa5be47d4, 0xaf61189e, 0x5cd70faf, 0x037331cf, 0xef7fa5f6, 0xb2f2b41a,
+0xa6f222c6, 0xdb60fe4c, 0x2a857a9a, 0x0b821f9d, 0x348afd17, 0x7eecbaeb,
+0x92bb9509, 0x8a3cec24, 0xd02549a2, 0x155ffa81, 0x2b7feac6, 0x3ee461e7,
+0xc981f936, 0x89b544c7, 0x9a431e36, 0x62511734, 0x769f9647, 0x211a747e,
+0x567abef4, 0xad87e2b4, 0xa3e0c3bf, 0x6d325dd5, 0xf561cc46, 0x39925735,
+0x3d8abbfd, 0xc3724c88, 0x8bdf03c9, 0x1b02a12a, 0x4f233a0c, 0x9ca9444a,
+0xc5d1f7e6, 0x4d995f37, 0xd9aefb32, 0xd0465248, 0x0f3a3b21, 0x62ea8c0c,
+0x91f8d54e, 0x5cf75514, 0x14618a01, 0x8fe9b87e, 0xf2b424f9, 0x49724ce2,
+0xa1464587, 0x5e00dc83, 0x59475455, 0x444119b1, 0x4fb9f036, 0x65fcbc1a,
+0x1c63a990, 0x767a6114, 0xb0ede06a, 0xcfb91ae3, 0x7874af5f, 0xf78772a3,
+0xa2932c81, 0x77f2759d, 0x930dc8f1, 0x95ce14a5, 0x134363ee, 0x61ee143f,
+0xf0034b35, 0xfdc75fce, 0x3be2dcf3, 0xff3a07eb, 0xdc43f0eb, 0x23ba73bb,
+0x45f7649e, 0xcacc297c, 0xa3dd98db, 0x058d46a9, 0x6bcfc154, 0x7be8e1e6,
+0x618a4754, 0x8d193c46, 0xba39e1ce, 0xc3b85cfc, 0xd80d853b, 0x38d6440d,
+0x9c1a6185, 0x90c9dfcb, 0x01c6e841, 0xeedfe6ac, 0x7b61a3ae, 0xad3924dd,
+0x514bc1a8, 0x6ed60d7e, 0x1b74b79b, 0xea295947, 0x5f9a5d33, 0xcd24311f,
+0x0bd3d10c, 0xd214ecfe, 0xcb37035d, 0x8ce95168, 0x7020cb52, 0xe432107d,
+0x042d63ac, 0x6201c8dd, 0x4bea65a2, 0x1a3cf453, 0x5b8e868d, 0x3d653bb0,
+0x24c1967e, 0x37f183a9, 0x3700e703, 0xb168a02b, 0x2592cd82, 0x5c0cdb66,
+0x70b64ebd, 0xf8dcb9a7, 0x634a8335, 0x06642398, 0xfe2f4497, 0x2e775256,
+0x30f85cbe, 0xf4d2fdaf, 0x46ca6c9d, 0x022097d6, 0xcedeb03e, 0x3d8353bc,
+0x0d005559, 0xd457eb38, 0xb1931313, 0xd4f12824, 0xcc444f1b, 0x5f
+
+output0 =
+0x11d2bcac, 0x7715ae4d, 0xc9f4dbc6, 0x2fda3c1a, 0x09349b16, 0x2cd3c189,
+0xe5650429, 0xc73c42c1, 0xe7336bb7, 0xbb7de593, 0x83f986aa, 0xc0ade12e,
+0x6730b095, 0x78f7c059, 0xaa907199, 0x75c323d1, 0x7061f9ba, 0x97e067bf,
+0xc155cd55, 0x6a4cb08d, 0x4260e2fa, 0xff35e496, 0x37f251d3, 0x02fd9f9e,
+0x6f53345c, 0x790cda6d, 0x3b8549e4, 0x56d0c6ea, 0x70a38006, 0xfff18223,
+0x6f2035b5, 0x6cf508d3, 0x98a0a308, 0x432353fc, 0x0eb818eb, 0xdd9a128b,
+0xf92431b2, 0xad788286, 0xda07d5de, 0x44b4b3a8, 0xbe62fd67, 0x61a4eb54,
+0x90d7ac9f, 0xc4d9a930, 0xfddc3c24, 0xf5e3b1c8, 0x38143538, 0xcb1d3062,
+0xcae36df3, 0x50a73437, 0x542dcab7, 0x875973a0, 0x34690309, 0x49cb1ddb,
+0xf8a62b92, 0x82af6103, 0xc9f8c928, 0x3835b822, 0x16b044a6, 0xdae89096,
+0xa5be47d4, 0xaf61189e, 0x5cd70faf, 0x037331cf, 0xef7fa5f6, 0xb2f2b41a,
+0xa6f222c6, 0xdb60fe4c, 0x2a857a9a, 0x0b821f9d, 0x348afd17, 0x7eecbaeb,
+0x92bb9509, 0x8a3cec24, 0xd02549a2, 0x155ffa81, 0x2b7feac6, 0x3ee461e7,
+0xc981f936, 0x89b544c7, 0x9a431e36, 0x62511734, 0x769f9647, 0x211a747e,
+0x567abef4, 0xad87e2b4, 0xa3e0c3bf, 0x6d325dd5, 0xf561cc46, 0x39925735,
+0x3d8abbfd, 0xc3724c88, 0x8bdf03c9, 0x1b02a12a, 0x4f233a0c, 0x9ca9444a,
+0xc5d1f7e6, 0x4d995f37, 0xd9aefb32, 0xd0465248, 0x0f3a3b21, 0x62ea8c0c,
+0x91f8d54e, 0x5cf75514, 0x14618a01, 0x8fe9b87e, 0xf2b424f9, 0x49724ce2,
+0xa1464587, 0x5e00dc83, 0x59475455, 0x444119b1, 0x4fb9f036, 0x65fcbc1a,
+0x1c63a990, 0x767a6114, 0xb0ede06a, 0xcfb91ae3, 0x7874af5f, 0xf78772a3,
+0xa2932c81, 0x77f2759d, 0x930dc8f1, 0x95ce14a5, 0x134363ee, 0x61ee143f,
+0xf0034b35, 0xfdc75fce, 0x3be2dcf3, 0xff3a07eb, 0xdc43f0eb, 0x23ba73bb,
+0x45f7649e, 0xcacc297c, 0xa3dd98db, 0x058d46a9, 0x6bcfc154, 0x7be8e1e6,
+0x618a4754, 0x8d193c46, 0xba39e1ce, 0xc3b85cfc, 0xd80d853b, 0x38d6440d,
+0x9c1a6185, 0x90c9dfcb, 0x01c6e841, 0xeedfe6ac, 0x7b61a3ae, 0xad3924dd,
+0x514bc1a8, 0x6ed60d7e, 0x1b74b79b, 0xea295947, 0x5f9a5d33, 0xcd24311f,
+0x0bd3d10c, 0xd214ecfe, 0xcb37035d, 0x8ce95168, 0x7020cb52, 0xe432107d,
+0x042d63ac, 0x6201c8dd, 0x4bea65a2, 0x1a3cf453, 0x5b8e868d, 0x3d653bb0,
+0x24c1967e, 0x37f183a9, 0x3700e703, 0xb168a02b, 0x2592cd82, 0x5c0cdb66,
+0x70b64ebd, 0xf8dcb9a7, 0x634a8335, 0x06642398, 0xfe2f4497, 0x2e775256,
+0x30f85cbe, 0xf4d2fdaf, 0x46ca6c9d, 0x022097d6, 0xcedeb03e, 0x3d8353bc,
+0x0d005559, 0xd457eb38, 0xb1931313, 0xd4f12824, 0xcc444f1b, 0xa533d85f,
+0x4fde63ac, 0x10ea20a0, 0xe6da8721, 0xbfde5b08, 0x9c3739da, 0xb6dc015a,
+0x427db088, 0xdfdb8e6f, 0x756be6c1, 0x21f5297b, 0x06135665, 0xc1602b7d,
+0x049536c5, 0xbbb3b801, 0x0cdb0c19, 0x7b2ad622, 0xfee8218f, 0xc5c7f123,
+0x8abd3301, 0xa15b534d, 0x29dd2053, 0xd409abf9, 0x3ef19d6b, 0x70a3cbc2,
+0x7a51423a, 0x4505b2ad, 0xdc74c75e, 0x068751a9, 0xb0b56437, 0x14a10371,
+0x76af806f, 0xa8a47e19, 0x7c97a26e, 0x7998a3d6, 0xdc1ad1e2, 0xb532a301,
+0xca8a3e7d, 0xd0aef374, 0x204990c0, 0xc7011aec, 0xa69151ea, 0x53390026,
+0x7bf0d762, 0x735c2202, 0x64159e54, 0x5a3b1a56, 0x9ef1def2, 0x0ab8a961,
+0x587b0886, 0xb8cc5975, 0x2a5a0f23, 0x069d05be, 0x9cc3c207, 0x40ef1a02,
+0x4fae3f5b, 0x1f127aae, 0xd4e6d411, 0x17ac43ef, 0xe4bf891b, 0xfbb21765,
+0x2c560c7e, 0x8561988c, 0x73a01032, 0x0cfef73a, 0x694c4991, 0x885d7a3f,
+0x4218d1ff, 0xc2efaffb, 0xaf9d9715, 0xf76de6b2, 0xcce8e8ff, 0x370e3800,
+0x493675eb, 0xd8fbcbda, 0xa5b382c2, 0x86c8f1ea, 0x3d724ea4, 0xb067034c,
+0x6491d87e, 0x1a745ce4, 0xbb27180b, 0x1a2f0acc, 0xac4b7b3b, 0xe324578b,
+0xc87928df, 0x9c1de566, 0x0ce2a17d, 0xaf2e13ce, 0x146a8659, 0x8727f6ae,
+0xe2df7d03, 0x1a8e4cb4, 0xfa590976, 0x13a7c236, 0xc07489d0, 0xbe905e17,
+0xafeb3d4b, 0x201e73f2, 0x5bdca12e, 0x3e15a852, 0xbcfc3271, 0x5d398410,
+0x6bfacc15, 0x011fc61f, 0x43e43fd7, 0x0640717c, 0x96bfb3ff, 0x158eac19,
+0x3b852e91, 0x74f9ceda, 0xcac71326, 0xfc0e312a, 0x20e8137b, 0xa1162611,
+0x239ac7fe, 0xb9d00f8a, 0xea0b5241, 0x019f0d25, 0xc5153264, 0xb48a5547,
+0xe54e339f, 0x17a6cca5, 0x5065af0d, 0x5ce648b9, 0xb457b342, 0xc1cb3f0e,
+0x28d03c8b, 0x5144ed7a, 0xdb80779f, 0x53ce1b87, 0xbc071147, 0xbfe46c11,
+0x7296785e, 0x83e4a63e, 0xc58982e9, 0x9538c5b9, 0xf14abaaa, 0xd915124c,
+0x73540cd6, 0xe333696b, 0x58f9e00a, 0xd4dad10f, 0xc0de1420, 0x355e2bdc,
+0xb2faa8fd, 0xbe6a12f1, 0x45d415cc, 0x47f5aed9, 0x4754e770, 0x2bb07385,
+0x41374352, 0xf80beb47, 0xef02f35c, 0xc9c1b86e, 0x94b5785b, 0xba33123f,
+0x7e39f0c9, 0x028a9286, 0x7d52c9f1, 0x06f04da6, 0xbc6a68d1, 0xfc70bace,
+0x95b6a129, 0xfff224bb, 0x701ef3fb, 0x3309286f, 0x544ae8c1, 0xdca62c4a,
+0xf8862ee2, 0xf9e3cd29, 0x2c07cce2, 0x8d93652a, 0xf47e4611, 0x4635f586,
+0x1c03e0f4, 0x819724c7, 0x96b2a3f0, 0xeeb1ad95, 0xff08e517, 0xbd4ba6ed,
+0x49ddb12d, 0x365734b5, 0x5edf7459, 0x2ee117a9, 0x067b9462, 0xb703685f,
+0x72499876, 0xb71dd772, 0x5d02b478, 0x4b6fed1d, 0x2df232c1, 0xb9dea0ff,
+0x1618c046, 0x0adda94b, 0xd271e560, 0xd120ba30, 0x6dfecc73, 0x4e751af7,
+0x0e7a6b63, 0xa1ad5dad, 0xb41201b1, 0x245f3e86, 0x3a5114ac, 0x5cd532c9,
+0x27ff9c3a, 0x7a847392, 0x6b2d0514, 0x82d0cc45, 0x30779ba2, 0x3f0c8156,
+0x9bce6106, 0x3511b2b4, 0x82dbef90, 0xac19def9, 0x5f11d43e, 0xa5899170,
+0xdd137ff4, 0x188077ab, 0x53cec4c0, 0x6519988d, 0x2b07a0d5, 0x269ec4ae,
+0x29c2bc5a, 0x4a0206c6, 0xf8fba9f5, 0x61309433, 0x402bf26c, 0xce401562,
+0xf7eb46da, 0x4d9ad0c0, 0xf99fc69b, 0x1b670e56, 0x327bb1c8, 0x5f7db32c,
+0x4c96b615, 0x041e0960, 0x190ef525, 0xede526f8, 0x59eb88e1, 0x355e5454,
+0x8289d63c, 0xf848c2ad, 0x5bfc881f, 0xf161d01e, 0x5a921d49, 0xc202a8ad,
+0xaa9e9dc4, 0x8211e14d, 0xea945bc4, 0xa5a59180, 0x7ffd5bd0, 0xd6c107bc,
+0x3d0e84af, 0x04d13d34, 0xa21f54a3, 0xfcea787b, 0xbe61865b, 0xbe0d9899,
+0x336bb04d, 0xf843ae66, 0x8d400981, 0x4359b845, 0xdbda44dd, 0x27392d92,
+0x05780a7b, 0xe6dd7f03, 0x13137173, 0x9b623a85, 0x2428f035, 0x996f04de,
+0x74613a87, 0x924aa956, 0x4661e3ad, 0x506ce2d3, 0xa59e7aba, 0x34fd455d,
+0x70d613c6, 0x094610b9, 0x06e176ee, 0xb4f0842c, 0xc53680f4, 0xd9e2920b,
+0xe0ddcd46, 0x8e4c1618, 0xb5c83878, 0x7b5107a3, 0xb75c33c0, 0xa62868d3,
+0x804e47d9, 0xcefc87fc, 0xca5e125d, 0x3ed40ea7, 0xe72d3663, 0x06620539,
+0x314993c2, 0x99f417d9, 0x4819151c, 0x7d46c8a2, 0x95a81dc9, 0x61898a53,
+0x8226bb8c, 0x4907a616, 0x91eb32f7, 0x5430c6a1, 0x390ca234, 0x599f02ff,
+0x315a4cc8, 0xc15d9e2b, 0x1c7a8788, 0x2074d5ea, 0xc063a30d, 0x5532e1f5,
+0xd3820192, 0x916a7b03, 0x32422c07, 0x2ae2cc41, 0x96cb84c5, 0x2bab3d29,
+0x0edc0add, 0x408e4981, 0x2606b671, 0x63dca006, 0x8f4261d9, 0xbfe4623b,
+0x60174b80, 0x50230b0d, 0x9d4c7af3, 0x2edb3482, 0x24d8d087, 0x1b673b02,
+0xe28b7132, 0xc6c8cb36, 0x5794e3f3, 0x808c3887, 0xf9f64a32, 0xfca10213,
+0xff29e373, 0x54bf19a6, 0x16014860, 0x356d4398, 0xe8d0d630, 0x4c8100c0,
+0x7b68a462, 0x6cc95c68, 0x3becad35, 0xb2c6b4c3, 0x740aef1c, 0x4f37f2d5,
+0xc9d3c805, 0x6e4e533d, 0xf7647967, 0x91856de5, 0x87e7e428, 0xddf2fe07,
+0x69016442, 0xe0132159, 0x1afae2a2, 0x63b6d719, 0x08d20a21, 0x48ee7113,
+0x2fb2d853, 0xa532ffc8, 0x8296dee2, 0x0dfaf2fa, 0x060d531c, 0xa756d04c,
+0x3efed03e, 0xbe9436db, 0x5b9e8a48, 0x0a37ea61, 0x718f4362, 0xebcc9742,
+0x78aa2e7c, 0x4b19f7b8, 0x308b9af0, 0x915247e9, 0xc079aa48, 0x5230e578,
+0x862d6de7, 0xbe0801d0, 0x8ab11c9d, 0xaf1d7feb, 0xe9d15530, 0x44651202,
+0xc006
+
+e =
+18448
+
+k =
+6144
+
+ncb =
+18528
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_CRC_24A_ATTACH
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e32256_crc24b_rm.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e32256_crc24b_rm.data
new file mode 100644
index 000000000..9ce68b723
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c1_k6144_r0_e32256_crc24b_rm.data
@@ -0,0 +1,180 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0xe5e0a392, 0x6f5468f1, 0xc8f1c505, 0x4502caf2, 0x23df5578, 0xc2f29afe, 0x06838d34, 0x264eab9b,
+0x1e97c133, 0xabad27aa, 0x684fa9b4, 0x0fed735e, 0x6ab6bcad, 0x9c3e401a, 0x66a63035, 0xa72f7f6b,
+0x509d2953, 0xf03c574a, 0x48f12185, 0x27318395, 0x008fc1ce, 0x7efcf19d, 0x0120de12, 0x6ed28bff,
+0x2044547a, 0x04d95124, 0x6baf2e1e, 0x60d93509, 0x299aa27f, 0x8b67d93a, 0xc33d9631, 0xe468dbe1,
+0x1a82d0b6, 0x8ee2ff7b, 0x39298170, 0x33a90b6a, 0x273d17f7, 0xb4368615, 0x60c390b8, 0x24696570,
+0xa1f4abcc, 0x08b68dd0, 0x91f8c883, 0xc9ceed85, 0x6467da9b, 0x48dfae24, 0xf4ff4992, 0x8c8200cf,
+0xaac02792, 0xf506f71d, 0x096df98a, 0x3074be38, 0x9b675626, 0x4ccace33, 0x50f0f60d, 0xf4b59cc4,
+0x748a8799, 0x9032c151, 0x1fb945f6, 0x01bd098a, 0x90a7907b, 0xe086172c, 0x7ed3dc8d, 0xea0dd126,
+0xf9b35bc1, 0x8ad4e233, 0x37b5e1a1, 0x95bf8c3a, 0x9d288b43, 0x23a860f1, 0x4e993fc3, 0x3c774bd4,
+0xe411be48, 0x22ab80c7, 0x9dd09a47, 0xc9e6988e, 0xb4cbf0b2, 0xb9e2a389, 0xf1494438, 0x2c87638b,
+0x892468ec, 0x7915d1aa, 0x4d9cb9c4, 0x643a388e, 0x48c4358f, 0x937ad5a1, 0xdae53508, 0xa1305607,
+0xbfb63a5c, 0xb4bb9324, 0x71daab0b, 0xa582346b, 0x0e5402e1, 0x75af83e7, 0x2b241b17, 0xfa17aca1,
+0x9637cb2e, 0xc61fe511, 0x093934f7, 0x4b703b44, 0x992ab229, 0x4ddc99b5, 0xe2be6b60, 0xa2217861,
+0x8f621931, 0x272c0ec6, 0x23a4d5b2, 0xc6f4e002, 0xb76397c0, 0xc00e3c01, 0xb89d29b3, 0x5e9bc984,
+0x00391d56, 0x55fae02f, 0x4bc4bc9d, 0x9a147b22, 0x0fb492ed, 0x753dc9a6, 0x9f493eec, 0x6e135dc2,
+0x0eeca515, 0x1c1512f9, 0xb88075e3, 0x326a97f0, 0xc755faf5, 0x06b7961b, 0xbd50fd69, 0x5f071c92,
+0x2806c099, 0xe364f4ab, 0x2c4a114a, 0x7655b100, 0xf5e66750, 0xf9212705, 0x245e3b8d, 0xb0f1fb0d,
+0xd7be9558, 0x27030e24, 0x9ea9b62e, 0xbde9be45, 0xce0adae6, 0xc28780a4, 0x1664ccde, 0xa7a62e3f,
+0xa4f8ec00, 0x964e813c, 0x108c95e0, 0x097fe10b, 0x08da3505, 0xde413158, 0x046a31c0, 0xd9cdd804,
+0xdfbdff9a, 0xfd77493f, 0xdffb2388, 0xe2ffa111, 0x29eb6ac7, 0xf9e1ac68, 0xc2ed68c7, 0x34d65405,
+0x25f187ba, 0x3df23a2c, 0x96a2a5a9, 0x2bef4b26, 0x28d1c41d, 0xf380c0f1, 0xc4d5456e, 0x6b699c28,
+0x0aafd6b3, 0xf88f3078, 0x114438d0, 0x93836544, 0xebd5767d, 0x9185b5c2, 0x593e4fe7, 0x29d3348c,
+0x881f16c4, 0x77e33d03, 0x6794bbf5, 0x6b6c38f3, 0xa860673a, 0xb1d2d152, 0x08f9f310, 0x82c37500,
+0xce0ae34c, 0xd5478e86, 0xcfe1adfc, 0xfaf06d37, 0xf7e21bfc, 0x3b077287, 0x45b33c08, 0x41
+
+output0 =
+0x25832957, 0x1235fe50, 0xa3b0b09b, 0x0bb7c797, 0xce815b03, 0x7b702251, 0x2c25fc60, 0x23ac55e0,
+0x8bea35cb, 0xe33b833c, 0xec1d38a4, 0xb59acb59, 0x0f1fa8b7, 0xcb77fce6, 0x6564fc78, 0x9e6c39cc,
+0x94f1bed1, 0xe02684ad, 0x074045a4, 0x4dc9b344, 0xd187bed8, 0x2a129ecb, 0xf6c5bd4d, 0xf98d5c26,
+0x78addaae, 0xbe87f7d2, 0xf42a7df6, 0xa4683306, 0xbfa9b509, 0x3a67ddfe, 0x013d68d5, 0xb2a1fb8a,
+0x0dfc5da7, 0x792f6b24, 0xaa220ec2, 0x6cb0a7a4, 0xd6e5ea4a, 0x1cd6156c, 0x9bac3cad, 0x926a3950,
+0x658815b0, 0x2a2e4349, 0x9684d70f, 0x67a62f63, 0x7a8aae48, 0x8aa046e5, 0x3cad66d5, 0xe7e269b8,
+0x95a9a8ca, 0x426f46ae, 0xf780d265, 0x2e0d244d, 0x5480bc07, 0x66554568, 0x938aeda7, 0x1144006c,
+0x450320b3, 0xce9dfce9, 0x59a277a8, 0xde38cc1a, 0x1cd2bd60, 0x0079ca20, 0x58dd4633, 0x55398bbd,
+0x5fcf982f, 0xdbbd3e30, 0xdcaab5e4, 0xc368c59f, 0xfba8e7d2, 0x9902b581, 0x2ec0a87f, 0x0ebea4ee,
+0x13bb2fd2, 0xbc1df5be, 0xe34baa5e, 0x4a66fc5d, 0x7fc9d926, 0x1d2dc178, 0xe780752f, 0x160e82fd,
+0x2e6205ba, 0x3d2fd1d7, 0x22b03620, 0x1c1ce57b, 0x5a8f8e09, 0xc9522523, 0x712e5cc0, 0xa27b10ad,
+0x52d2df01, 0x3fe886d6, 0x29f37f12, 0x479e3783, 0xa37a445c, 0x338f9df1, 0x74dca176, 0x11acbbc4,
+0xac50920a, 0xe9375593, 0xc483a084, 0xed281b58, 0x21ea3cd3, 0x5cf2e76a, 0x50c5e5f4, 0x68d14253,
+0x374cea8e, 0xf3533631, 0xb8f1bece, 0x3a188078, 0xb15325de, 0x989b4e70, 0x40f142f9, 0x4a55cc30,
+0x72a442b2, 0xe583a6c7, 0x4cb90a7d, 0xe19187c0, 0x899ea4e0, 0x42598555, 0x7d012357, 0x3e9cd281,
+0x75094cbb, 0x80afef50, 0x8a834f90, 0xa6182605, 0xdfb7c49e, 0xde57caf6, 0x62720457, 0x5a40705e,
+0x2728f823, 0xde22d20c, 0x8389268a, 0x2aad9f81, 0xa376314c, 0xd9288769, 0xa7a1cc5d, 0x1dcdb0ed,
+0x0b23e2d8, 0x024e9165, 0x0e375ea5, 0x27c561c7, 0x48687976, 0xe97021bc, 0xbf82aea2, 0x6cb87bd3,
+0xaa3f7ed5, 0x1e5c3aaf, 0xccad60b5, 0xb672d5da, 0xde0ff047, 0xf7cd4216, 0x45220a3b, 0x060d16c7,
+0xb6dc8617, 0xc10d9dc7, 0x3d229a69, 0x8deea79a, 0xda6883e1, 0x610f41f9, 0xfa0f57f0, 0x6f97b547,
+0xf00577ee, 0xe1be3d28, 0x809810e0, 0x7d4b8416, 0xdcc82557, 0xce6a01b1, 0xbc4cb663, 0x8bc88eac,
+0xab9e918d, 0x6ec29c41, 0xbd0e745e, 0xa97bc23e, 0x1e1370c2, 0xc2744139, 0xf5d2f67b, 0x9d5ae9dd,
+0x1040a10a, 0x1b54944c, 0x9a6810b1, 0xc7079d11, 0x8c89d60d, 0xc9523c76, 0x304b7adc, 0x2fd915eb,
+0x076192e8, 0x8cbd3bc1, 0x90440a9c, 0x81961a26, 0x6a53f026, 0xd2b07ce5, 0xc72e767a, 0x9d47c3d9,
+0xab2b7cb3, 0xf4b3aeec, 0x18441c12, 0x56b3007f, 0x81c3cfff, 0x128b72ed, 0x214dee41, 0xc735baeb,
+0x89cf54e7, 0xcdfce851, 0x77cc0a00, 0x57cc6e0a, 0x7ffc8dad, 0xb036445b, 0x0699a9f7, 0x8781d7b5,
+0xdd0f9d01, 0x43f01de8, 0x6a2e7dee, 0xf802d6b3, 0x10094fc1, 0x954cf6ad, 0xd7aee91a, 0x1e3369c8,
+0x2acd8c15, 0x3303a61d, 0x79344e4d, 0x1253cd91, 0x34c34c77, 0xbd075dce, 0xe0fdd1cc, 0xf9015c56,
+0x931b9096, 0x604f4bbf, 0x3b1d991a, 0x24007891, 0x7c0c1709, 0xe0d43230, 0x11821166, 0xf21e2558,
+0x2c37009d, 0x98718786, 0xa9a112e6, 0xd7e20b10, 0xfe917f72, 0xb76101ff, 0x42a8d327, 0x9039f71b,
+0x6d1628cb, 0xfd01251c, 0x6f0572a2, 0xb36a7e7a, 0x2b1a4556, 0xe679b027, 0x313573d0, 0xb5f7c20c,
+0xc8d1530a, 0x338e756e, 0xe6befc47, 0xfe12dccd, 0x6ad1e5b7, 0x40b078ff, 0x96aaacba, 0xedfdeb8f,
+0x8da3673a, 0xc965882e, 0xa4dec6e9, 0x7bace08f, 0xf144852a, 0xd5d787d0, 0x204d32e6, 0x733098aa,
+0x12f3a53a, 0xe060086d, 0x3ab1739a, 0xd391e860, 0xc23d9687, 0x0d3a84e0, 0x855ea4cf, 0x0d0ea5b7,
+0xfd082430, 0x70df7cb4, 0xe712f026, 0x84ce32ac, 0x67b04602, 0xac0b1faa, 0xed119dcd, 0x184afb0b,
+0x9abbefd2, 0x41b3e2f9, 0xe18d5703, 0x6e5f4de7, 0xb47380a2, 0x239a3714, 0x810bb522, 0x5ad95c77,
+0xe4b37e0c, 0x1cc200a6, 0x404c4390, 0x90533af1, 0xb49f2403, 0x1dada65f, 0x96f86d1b, 0x58f679a9,
+0x1fe3c66d, 0xcc5eb28d, 0x504b7aff, 0x7c18a397, 0x47ad4d5f, 0x348f12c5, 0x80bac6e0, 0x47bb3c74,
+0xccf16f02, 0xa932a5af, 0x51ebb452, 0x25808fcc, 0x47d14a43, 0xf0c2a0af, 0x30f938b5, 0x428420c7,
+0x61a66d9c, 0x082caa4f, 0xd9c74e3d, 0xb4d161b9, 0xb409f331, 0x14245a44, 0xddb67f1e, 0x1018c62c,
+0xc1e58e6d, 0x4ba86bd6, 0xf4a282aa, 0x4a85f90d, 0xbf0efb7b, 0x03706f08, 0xbe06a5f2, 0xe37f45f1,
+0xcbc4001c, 0x14decb05, 0xf3c6050f, 0xd1df33d7, 0xdab729c7, 0x8898dad3, 0x4a44a313, 0x30bee51e,
+0xd67b07ef, 0xf233eb19, 0x4c52bca3, 0x5d824a4b, 0x275faf2b, 0x428f8a95, 0x03f70c8b, 0x609e4036,
+0x59ce2147, 0xc7eecc6b, 0xa22d21c2, 0xc5764d9a, 0xb4524bc6, 0x6d9bdfc9, 0x0918b4f7, 0x62bb8022,
+0x7a98bdcc, 0xc963131d, 0x949036b8, 0x649ae51d, 0x93038d33, 0xe26cb45e, 0x4813516a, 0xc06c759c,
+0xfa6a9793, 0xdd59c686, 0x37b4b5b0, 0x66a02fac, 0xde159ecf, 0x90cdb66e, 0x1c9f7f94, 0x3a31f69e,
+0xcd93bc45, 0x32744ee0, 0x0f6ae2b1, 0x3bc9e963, 0x8cddbae4, 0x8f9517ff, 0x7d304ec1, 0x344e0357,
+0x7cd2ed30, 0x1f9fa3a4, 0x9dbeb67b, 0x59253b51, 0x41b6911a, 0x12b574af, 0x62a777da, 0x9a6c834a,
+0xaa16081d, 0x3f105c37, 0x6eac5dc0, 0x76e56fd1, 0x67bffbfb, 0xce069b80, 0x8fe970b1, 0x61945ee0,
+0xaf9d44c2, 0xf2cd16cc, 0x07a768c5, 0xd6eecaa6, 0x6e8ce063, 0x4b30b443, 0x360822c9, 0xa6442b33,
+0xf02d09a0, 0x22056421, 0xc552aa94, 0x1346ea1a, 0xab6c54a1, 0x35a69bdf, 0xfc6095ea, 0xbde0d55a,
+0x1b433ec0, 0x137483a0, 0x8c1cb29d, 0xf2bc4e17, 0x45df6882, 0xbd702bc9, 0xabbead61, 0xc97ef61d,
+0x01b68438, 0xbdd10231, 0x2e046323, 0x80e619bd, 0xa5126a2a, 0x74106e0d, 0x9e57b499, 0xcb275127,
+0x9e01f21e, 0xbaf4a744, 0x38604f7e, 0xa85493d6, 0x9a4b4541, 0x3f397269, 0xdde71734, 0x157dfe98,
+0x40334ad9, 0xc889f52f, 0xbddf4d23, 0xd2200018, 0x2a4b7180, 0x8a1a357f, 0xcd6af7e4, 0x1426b52b,
+0x2a45481f, 0xfc38394c, 0x05123e4e, 0xa0215834, 0xe2c2306e, 0x4ee9fe1a, 0x6bbbf30c, 0x19a39072,
+0x846b0bdf, 0xde4ef7f9, 0x47f1d67c, 0xf507e9e8, 0x14c1f617, 0xaa756ccf, 0xececc02a, 0x183cd616,
+0x9d4bac81, 0xd959d1ea, 0xefb81e2b, 0xd8ca27fc, 0x5c7e9eb4, 0x64d5d550, 0x32ed3c41, 0x8f62e8a8,
+0x5e2b65c5, 0x0a7e5e1b, 0x88abb657, 0x781ee74a, 0x840c27fd, 0xec83df4c, 0x163acaf0, 0xb2649960,
+0x2a706f9a, 0x5226c811, 0x5bcb501c, 0xb87caa99, 0xecb4a37e, 0x8927c424, 0xfea9ac62, 0x17da41d1,
+0x571c5987, 0x4217ea55, 0x5043b664, 0x18fb3ece, 0xfb2d13b9, 0xb6599d4b, 0xbb8a536d, 0xa719683f,
+0x81cc2d0f, 0xc888f1d3, 0xccb0a428, 0xd2cdff48, 0x0b3440e6, 0x45700619, 0xcea80987, 0xa5ad1cc3,
+0xd29deaf7, 0x4a8c95af, 0x9ac63a98, 0xf46d26b0, 0xf9a09352, 0x5f8b3fb7, 0x367c8da1, 0x3244b6a2,
+0x9634b973, 0x27292ae5, 0xc4f7ae33, 0x9b73a4f7, 0x086a8bb4, 0x616cd17b, 0x74fdb210, 0x5f483d60,
+0xf7666630, 0x107cd026, 0xfa2a4a07, 0x171b319e, 0x509d50c8, 0xf2d15061, 0x981d5759, 0xf23bc5c6,
+0xe9befe22, 0x1e784009, 0x7cda3751, 0x1c5b2b69, 0x3ba09115, 0x756f1ef5, 0x2b47353b, 0x553a33d9,
+0x1f029262, 0x6393d0ee, 0x97e01180, 0x0c53980c, 0x5da79e34, 0x1e0b53c4, 0x06a9f2ba, 0x622181b0,
+0x4898ac50, 0x874c780e, 0xf8cc5072, 0x4a5a63ca, 0xf6dea6a2, 0xc3134004, 0x4505bae6, 0xc3f4b638,
+0x0dda8e07, 0x0c4135bf, 0x61e80f25, 0x4b31a76c, 0xd91f0d09, 0x4ba0d577, 0xc95d0086, 0x21a61725,
+0x16862c1f, 0x9588795d, 0x6ecde7c4, 0x353288cd, 0x94e4647e, 0xeceaba51, 0x7c602ff8, 0xbba48cef,
+0x6556c6bf, 0xde912190, 0x86602d55, 0xf549554a, 0xd4d52081, 0x9728c5db, 0x7d09e129, 0x068008ab,
+0x353a6ea4, 0x90b44e4e, 0x5c97a08a, 0x6293b3c7, 0xa3e4114b, 0x7ce44646, 0x8f2b0269, 0x291ca1bb,
+0x98721528, 0xe30f5532, 0x0bbb2951, 0x7b7c390a, 0xb835b070, 0x2712e51c, 0xc20fb607, 0x5a05ce52,
+0x5eb33cc2, 0x33c8b3a8, 0x81433abe, 0xb99cc5de, 0x817a5bab, 0xc76ffef0, 0xc68fb77c, 0x96c35c46,
+0xef1bedc9, 0x42d84a19, 0x54440a6e, 0x3c4b7400, 0xe88bdd94, 0xe1b91c7d, 0xdcdba422, 0xc865625f,
+0xaaed9adf, 0x782f8dd7, 0xd267ef7b, 0x366340af, 0x5a9b408a, 0xd6edff9b, 0x8356ad73, 0xbaaf18d0,
+0xdf752a1b, 0xb246d2c0, 0xe2209cf7, 0x7b4aaa2a, 0xaeaec406, 0x5dc1665d, 0xcad3ca61, 0x9603b5c9,
+0x58012ba9, 0x32945486, 0x78fda0e2, 0xfa326649, 0xe88a7466, 0x6a54aea7, 0x6a56ad08, 0x9e86cbd3,
+0x8aaa7c2e, 0x66e45a99, 0x285d26f4, 0x40d2740f, 0xc87be0d2, 0x55844605, 0xd87e6a56, 0x04c036a9,
+0x00321b41, 0xc99f5e34, 0x7a87eadc, 0xc3ac9125, 0xdd0be68d, 0xa70cc221, 0x6d340390, 0xb3d88bd5,
+0x8cf95295, 0xeb03f3f5, 0x5a4bbedd, 0x56fcc9ad, 0x7a2e3d8c, 0x501bb88f, 0x8cfa9729, 0x4beaee02,
+0xfb22ede0, 0x51ef3bb1, 0xa4eac5db, 0xc6df35be, 0x9c6da264, 0x128cf797, 0x58f7d2d1, 0x20d87f0e,
+0x56a06be1, 0x127ded22, 0x6b03d2f3, 0x51be2702, 0xe898c0c1, 0x5532a2f5, 0xc2059c2c, 0x07d11ae7,
+0xfd1d20ba, 0x6e682d25, 0xff27f183, 0x79339832, 0x47c475e4, 0xd8193faa, 0x1d6a37f3, 0xba4b4cc7,
+0x25a910c1, 0x5335c90a, 0x084a987e, 0xb281453c, 0xce33dd8e, 0x7fae16a2, 0x5c4ecf25, 0x2d340555,
+0xa4ee8816, 0x651373c3, 0xefeb3c3f, 0x0188871b, 0x55e2ad83, 0xe904173b, 0x2f948fb9, 0xc50c0314,
+0x2a24ab54, 0x687a2c47, 0xabd0573e, 0x7908cc94, 0x490a1e1e, 0x555895e8, 0x30722594, 0x291dd817,
+0xc0b4ebc3, 0xfa0e5597, 0xf80409f8, 0x6152a038, 0x4bec698a, 0xa56cff7d, 0x4770e57d, 0x04e72526,
+0x823fa205, 0x22cd7082, 0x68a2e82d, 0xfa193898, 0x17c3a4d2, 0x7298366a, 0xcadc958d, 0x0cdb7e1a,
+0x228eddd1, 0x1459b630, 0xe3552ae0, 0x1c76ec70, 0x96677752, 0x17c28b84, 0xe82a9a0e, 0xbb37fd2b,
+0xe357cd86, 0xa5f3aafa, 0x0a56ebc1, 0x57adcddc, 0x007f642b, 0x2c64e1fd, 0xa2b073df, 0x60715c24,
+0x6d7861d0, 0xd0796ccb, 0xa29916dc, 0x7eaad923, 0x3618dee8, 0x1094af8d, 0x70051ff6, 0x597ba4ff,
+0x70e7fe76, 0xdb83025f, 0x09011eee, 0x44680188, 0x5c72d5b7, 0x1610cb8d, 0x643be6ac, 0xecc8cacb,
+0x19d9b888, 0xcc19b4ea, 0x40e7e526, 0x27ecd3eb, 0x01279cba, 0x1794e331, 0x6dbf274c, 0x95de5d2f,
+0x14aad0a9, 0x45c90401, 0x0611bb41, 0xd019a189, 0x68dd707c, 0xc563c798, 0xa4c79d2c, 0x5db10eb3,
+0x2689fe92, 0xbb137c10, 0xa4c0c9d8, 0xa9610249, 0x056f1268, 0xcb57ae36, 0x62a7270d, 0x349c7dec,
+0xc237db79, 0xebcabeba, 0xc421413f, 0x0bf08741, 0xfcfc6f35, 0x28d71e38, 0xe41e24b1, 0xa3bb1ed2,
+0x4c757e5c, 0x8f1e95f8, 0xac00d0cc, 0xeca670c7, 0xdfd87ac5, 0x43b4f5c7, 0x997a0f6b, 0x785d6b90,
+0xd0197018, 0xdf81defd, 0xd2e73e04, 0x603dabe6, 0xf0148c2f, 0x64df0a91, 0x9aae51c9, 0x93867ced,
+0xcc58e131, 0x60daa1d2, 0xe3d43433, 0xd51c9947, 0xcc742731, 0xd0e54c33, 0x1fcddc7b, 0xc06505de,
+0x0169991f, 0xb4f43bb9, 0x91a901f6, 0x8017b9d3, 0x70914002, 0x2d03c3c7, 0x1861064e, 0x51821521,
+0x03d029ef, 0x7768c872, 0x2a618e19, 0xbe00911a, 0xf927772d, 0x16f0ef1f, 0x3a7d721b, 0x73bf2184,
+0x81b20c99, 0x50c2d166, 0x2027da1f, 0xe6a7f756, 0x516435ab, 0x077bb2a2, 0x33076d9e, 0x2fcc1053,
+0x3da5507b, 0x58e7861c, 0xcb7f34e3, 0xc1dd6cee, 0x5d7eeb2f, 0x8bf7af16, 0xcaaa0b04, 0xbffe68a9,
+0x7aa6d3de, 0x86e8d238, 0x6d9c9e5c, 0x0afe48ea, 0x54a8b2c7, 0x7d081d4f, 0x24635e7d, 0x83a90ad2,
+0x5faa3307, 0x86d02631, 0x3ba7090e, 0x890ea613, 0x6379381d, 0x43082edc, 0x45fadca0, 0x507a5be8,
+0x4002d3e0, 0xcd47db8f, 0x016f02f7, 0x2cc37a2e, 0x6b2440e8, 0xf0a17a06, 0xd1d9ccba, 0xb4bfd01e,
+0xfb2e8da1, 0x2b9eafb9, 0x78351034, 0xd5741ede, 0x0728eaf6, 0x7943413b, 0x502b32a2, 0xcd7517b8,
+0xebc7a095, 0x0c604a3e, 0x3404c921, 0xa5130fc4, 0x49320039, 0x6afa45fb, 0xdfb6d1d1, 0x9f976a89,
+0x6edc8665, 0x25dbf831, 0xa4f7cfec, 0x317a09b5, 0xdaf4c587, 0x28517cd4, 0x6b0c4ef3, 0xcb4307a8,
+0xff2670b4, 0x53faca1c, 0x4e2b952a, 0xf8c81cb5, 0xad345402, 0x0cfa7a14, 0x8f530b2f, 0x08720c93,
+0xdac62944, 0xa2fa1466, 0xecd483c0, 0x1d969b7d, 0x301f431b, 0xa245449b, 0xfbe74141, 0x61ccd26d,
+0xeed80681, 0xba661d5c, 0x2aa8ba84, 0x98df402f, 0xb0bfa754, 0xf786f0eb, 0x502a3f00, 0x5714ef6b,
+0x0cc031fe, 0xbd5cb04c, 0x5cf040e1, 0x3d733d6f, 0x9b721cfd, 0xa93dad7d, 0x343a8188, 0x5beea144,
+0x77f00ee3, 0xb39e61bd, 0xc53b2a3f, 0xa8b4c424, 0xf5bad225, 0xa85879f2, 0xcfb028f4, 0x09643370,
+0x1c7204e6, 0xcebc96e5, 0x12227cec, 0xd7a429da, 0xb5645c6c, 0xf99d4c2b, 0x417bdfb6, 0x0b289280,
+0xd9cb2cb6, 0x36d1a187, 0x69839b3c, 0x59de4109, 0xd03843a6, 0x46eb3539, 0x11a526ce, 0x56c78934,
+0x763909cc, 0x656ca8af, 0x5b0bdb9d, 0xfac27a43, 0xe1f96c06, 0x6cebe65d, 0xf94709d9, 0x63efc9f1,
+0xc95ba413, 0xe704de3c, 0x261e2b43, 0x9c3ef6a0, 0xad4bbe93, 0x79f1cfd8, 0xe314fc58, 0x3470d507,
+0xdd0e43e3, 0x394aca27, 0x6bbbf7f1, 0xb213d5e9, 0x1ba99155, 0x4bf71a64, 0x7aa72d51, 0x36a82476,
+0x81d0a1c9, 0xc175a36a, 0xda05fc03, 0xfe16edc6, 0xbbbf6f57, 0xb00978f6, 0x0e17eb6c, 0xe905fe98,
+0x49241c46, 0x6cc1fcda, 0x8a562cdf, 0xae6c7a70, 0x083e66ed, 0x433be4c6, 0x2092bc04, 0xb4326383,
+0x92006a4a, 0x401602df, 0xa54a2952, 0xa4ae512c, 0x46153a61, 0xbaf9bdca, 0x56a95e63, 0x5eadc50f,
+0xe403dc0b, 0x3708ba31, 0x21db3941, 0xeb74c1c8, 0x8d2628cf, 0xb7925cf4, 0xdb1ad60b, 0x67dfb1ea,
+0x4b8893ec, 0x2d101360, 0x3036d21b, 0x9ed1eb42, 0xa1a60268, 0xe1d6502a, 0x459b4907, 0x1275e279,
+0x20efb17c, 0x7f4ae419, 0xf6e4a74b, 0x35698d03, 0x5414844a, 0x2397a6b9, 0x7e41f393, 0xe78fd97d
+
+e =
+32256
+
+k =
+6144
+
+ncb =
+18528
+
+rv_index =
+0
+
+code_block_mode =
+1
+
+op_flags =
+RTE_BBDEV_TURBO_RATE_MATCH, RTE_BBDEV_TURBO_CRC_24B_ATTACH
+
+expected_status =
+OK
diff --git a/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c3_k4800_r2_e14412_crc24b.data b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c3_k4800_r2_e14412_crc24b.data
new file mode 100644
index 000000000..9e17429d3
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/test_vectors/turbo_enc_c3_k4800_r2_e14412_crc24b.data
@@ -0,0 +1,153 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+op_type =
+RTE_BBDEV_OP_TURBO_ENC
+
+input0 =
+0xb0fe86aa, 0xffbf2968, 0x4f55a631, 0xf2152dbc, 0x195a49a5, 0xa4aa7c6c,
+0x48a7be38, 0xd32c84f2, 0xb040da60, 0xb39eb07c, 0x3443aad6, 0x19f52e13,
+0xb2914341, 0x0d5dfdb3, 0x1ba8aec0, 0x62d0c7be, 0x1d55475c, 0x10f7dd79,
+0x967e5333, 0xc0d524c1, 0xdca8da87, 0x1146ecf7, 0xfa09a85c, 0x83be800f,
+0x11b814cc, 0x362a4704, 0x4f22e7ce, 0x9985a0e2, 0x9de4be72, 0x488a45b3,
+0x6996ade2, 0xdb18c09a, 0x487d62a3, 0x94f82d13, 0xa0743f83, 0x75d2f5dd,
+0x0e470346, 0x6e2ec2e5, 0x1a67fe5f, 0xc369330d, 0x860e8766, 0x42c110f6,
+0x804a9985, 0x55db02b4, 0xb899fc5c, 0x57811d20, 0xda4f1f9d, 0x2a2efc30,
+0x953e7487, 0x4b0c3065, 0x247d5d47, 0xdde382e7, 0x1d6d2ad7, 0x4358ac24,
+0x2d0fd97f, 0x1483821e, 0xf6c74ee5, 0x23b5c2f4, 0x95d4a5fc, 0x486f370b,
+0x8dbae43d, 0x248f17d5, 0x2df76099, 0xd19ec872, 0xf592aa0e, 0x8de04c3c,
+0x3ada94fb, 0x9dd001a3, 0x2b4db6d1, 0x791cf495, 0x57dc764b, 0x21789f1f,
+0x0d38adf5, 0xd8cefdc2, 0xed98f8bf, 0x024bc4ed, 0x4f9d3062, 0x332d27c5,
+0xde70ad4e, 0xd85872d2, 0x5d0e29c0, 0xa4fd1887, 0x3fa67ba1, 0x46b9b008,
+0x055bbf61, 0xf78e59f0, 0x287d2e3b, 0x5b473fe7, 0xd7ad6e04, 0x9cdf4986,
+0x830432ae, 0xffded1ba, 0x35c00f77, 0xcf0a6648, 0x196c03aa, 0xba4e2dd3,
+0xdaf70fe4, 0x883de2cd, 0xedc3b52e, 0x14e638c1, 0xe607103a, 0xc4cfb700,
+0x4ed9843d, 0xc442a0cb, 0xc0d3bba2, 0x36789ba8, 0x9c9b7a24, 0xb943b6a4,
+0x8f2c6879, 0x0fb16a0c, 0x2677bada, 0xd14f2f7e, 0x662ec398, 0x1e37b7ae,
+0x8ad0312d, 0x21adb6a1, 0x072a11fd, 0x7ae828d1, 0xb510655f, 0x09f7b477,
+0x10a175fc, 0xb7086f51, 0x24546af3, 0xfae81b50, 0xcb328832, 0x63693615,
+0xa37c3678, 0x15fb6364, 0xb5f75a78, 0xfa9aa5f6, 0x03804a0e, 0x1d245890,
+0x06d6cdcd, 0x7485a3c7, 0x35a008ae, 0x1abeaf1c, 0xd9c55966, 0x2b694666,
+0x5341f2df, 0xcb647280, 0xfb88d81e, 0xf99a44d0, 0xb0585534, 0x0877b530,
+0x752ab39a, 0xd493d8bc, 0xfaa6a57a, 0xccb7c008, 0x9c35994b, 0xb8
+
+output0 =
+0xb0fe86aa, 0xffbf2968, 0x4f55a631, 0xf2152dbc, 0x195a49a5, 0xa4aa7c6c,
+0x48a7be38, 0xd32c84f2, 0xb040da60, 0xb39eb07c, 0x3443aad6, 0x19f52e13,
+0xb2914341, 0x0d5dfdb3, 0x1ba8aec0, 0x62d0c7be, 0x1d55475c, 0x10f7dd79,
+0x967e5333, 0xc0d524c1, 0xdca8da87, 0x1146ecf7, 0xfa09a85c, 0x83be800f,
+0x11b814cc, 0x362a4704, 0x4f22e7ce, 0x9985a0e2, 0x9de4be72, 0x488a45b3,
+0x6996ade2, 0xdb18c09a, 0x487d62a3, 0x94f82d13, 0xa0743f83, 0x75d2f5dd,
+0x0e470346, 0x6e2ec2e5, 0x1a67fe5f, 0xc369330d, 0x860e8766, 0x42c110f6,
+0x804a9985, 0x55db02b4, 0xb899fc5c, 0x57811d20, 0xda4f1f9d, 0x2a2efc30,
+0x953e7487, 0x4b0c3065, 0x247d5d47, 0xdde382e7, 0x1d6d2ad7, 0x4358ac24,
+0x2d0fd97f, 0x1483821e, 0xf6c74ee5, 0x23b5c2f4, 0x95d4a5fc, 0x486f370b,
+0x8dbae43d, 0x248f17d5, 0x2df76099, 0xd19ec872, 0xf592aa0e, 0x8de04c3c,
+0x3ada94fb, 0x9dd001a3, 0x2b4db6d1, 0x791cf495, 0x57dc764b, 0x21789f1f,
+0x0d38adf5, 0xd8cefdc2, 0xed98f8bf, 0x024bc4ed, 0x4f9d3062, 0x332d27c5,
+0xde70ad4e, 0xd85872d2, 0x5d0e29c0, 0xa4fd1887, 0x3fa67ba1, 0x46b9b008,
+0x055bbf61, 0xf78e59f0, 0x287d2e3b, 0x5b473fe7, 0xd7ad6e04, 0x9cdf4986,
+0x830432ae, 0xffded1ba, 0x35c00f77, 0xcf0a6648, 0x196c03aa, 0xba4e2dd3,
+0xdaf70fe4, 0x883de2cd, 0xedc3b52e, 0x14e638c1, 0xe607103a, 0xc4cfb700,
+0x4ed9843d, 0xc442a0cb, 0xc0d3bba2, 0x36789ba8, 0x9c9b7a24, 0xb943b6a4,
+0x8f2c6879, 0x0fb16a0c, 0x2677bada, 0xd14f2f7e, 0x662ec398, 0x1e37b7ae,
+0x8ad0312d, 0x21adb6a1, 0x072a11fd, 0x7ae828d1, 0xb510655f, 0x09f7b477,
+0x10a175fc, 0xb7086f51, 0x24546af3, 0xfae81b50, 0xcb328832, 0x63693615,
+0xa37c3678, 0x15fb6364, 0xb5f75a78, 0xfa9aa5f6, 0x03804a0e, 0x1d245890,
+0x06d6cdcd, 0x7485a3c7, 0x35a008ae, 0x1abeaf1c, 0xd9c55966, 0x2b694666,
+0x5341f2df, 0xcb647280, 0xfb88d81e, 0xf99a44d0, 0xb0585534, 0x0877b530,
+0x752ab39a, 0xd493d8bc, 0xfaa6a57a, 0xccb7c008, 0x9c35994b, 0x47ee26b8,
+0x94f624ac, 0xa3bd4876, 0xf7d4854e, 0x8871d433, 0x9321d942, 0x7b626be8,
+0x72c934b0, 0x3b7af8a4, 0x5102c29f, 0x710e4dbc, 0x99708292, 0x1458c4c1,
+0x61026bc5, 0xe776e388, 0x4a0222b3, 0x760e5aaf, 0x662f3583, 0x5ab1005b,
+0xe527ef70, 0x4170d611, 0x307bebc4, 0xfdd00caf, 0xbaae1044, 0xcab4d459,
+0x38281dcf, 0x90580c89, 0x49cf5986, 0xa27da769, 0xceced49b, 0x5ea37953,
+0x8a7e6c1c, 0x1e01b4e2, 0xe08026ae, 0x3754534a, 0x903b0ecf, 0x65f97a55,
+0x90798ed9, 0x9d1133bc, 0xe356a39f, 0xe47acbce, 0x01ccf326, 0x1954fd3d,
+0x240e69f8, 0x1da20bb4, 0xe1ab1684, 0x44c65d48, 0xd265e6c2, 0x51d4ef07,
+0x000970ef, 0xfeb939f4, 0x5dcc0132, 0x2bd27ae5, 0xba5dbd25, 0xa9d190e4,
+0x61556bec, 0x7fd6caba, 0x7fe312cb, 0xdd319413, 0x92a5dbbf, 0x17e61915,
+0x56067b67, 0x3dc348c0, 0x58c17fe0, 0xbe6bffcc, 0xd379026c, 0xc4174780,
+0xcce7f026, 0xb74b7eb0, 0xe4d5f625, 0x6bc16d3b, 0xff3e300e, 0x83f0d55a,
+0xf2e537df, 0x75c18f78, 0xa5458d1a, 0x47c778b0, 0x92eb8716, 0xcb5816fd,
+0xc2cc7079, 0xa7f1dc75, 0xed9e5ffa, 0xb7d6747f, 0xa2dc6907, 0x99b4d187,
+0x69f3138a, 0xbd285a1f, 0xb8ee18e0, 0x734b77a5, 0xc0700f69, 0x6c72a77a,
+0x76609ba9, 0xcfae9b73, 0x2cd329f0, 0x0d45aa12, 0x419fbcd7, 0x03e00f00,
+0x0effee99, 0x7f879eb4, 0x29a4c8df, 0x4432400a, 0x22b9cf55, 0xa1c4c645,
+0x200251b0, 0xff293906, 0xe11288e2, 0xde1e8ec7, 0x675752d1, 0x9630743e,
+0xd848c67e, 0x1eedfda9, 0x58b954fc, 0xa0dc7f1c, 0x0aea313e, 0x062b9449,
+0x0f17e57f, 0x96def6ec, 0x2ba45f14, 0xd9a5f8c5, 0x231483c8, 0x29b8783e,
+0xa6d24594, 0x1a62ffcd, 0x54c87a7f, 0x6fa9ca9a, 0xfff0f890, 0x51d6ae46,
+0xa96e82b0, 0x68cd9808, 0x56214df5, 0x2169defa, 0x72c1ecce, 0x2448e3c9,
+0x8eb2b3b3, 0x62c89c11, 0xbba20ee2, 0xea33f53a, 0x8b96a6b8, 0x9d33d551,
+0x363bd14e, 0x5fdd2b5f, 0xf8187546, 0xb692beab, 0x8df6b4c0, 0x753e2302,
+0xb90f7a37, 0x2b6bac6a, 0x13a07bc5, 0xb67f6d2b, 0x47b21569, 0xc2ab143f,
+0xf86ce30a, 0xde2dab70, 0x6f258860, 0x2878735c, 0x2aaeac20, 0xda80fb3e,
+0xe7a8ccf6, 0xbf011844, 0x40a610f8, 0x82f3fdf7, 0xadc4ec2c, 0xb8551030,
+0x76004380, 0xa384ff18, 0x080cf587, 0x6c4991d3, 0x2daea9aa, 0xa92d0c4f,
+0x4a9d117e, 0x2761f025, 0x96b40443, 0x57a82be4, 0x62374c44, 0x55dc64ae,
+0x28aa9f0c, 0x03a3b963, 0x41dbaa26, 0xb3c23735, 0x971cbd31, 0x939a9f80,
+0x76439fdc, 0xa9df79d6, 0x926ae3e2, 0x5ee75745, 0xf2396e52, 0xe18bd816,
+0x3f9834b9, 0x816a07bc, 0x8f873310, 0x45cf9b96, 0x0ce634dd, 0xe64a16d9,
+0x2733775a, 0x2b648c7e, 0xe600ee8e, 0xd99d8ae3, 0x10dadf2a, 0x904d3f87,
+0x3963e9e7, 0x47fcce89, 0xc256c898, 0x7db6cb66, 0xe1611a8b, 0xed81b10d,
+0x75eff974, 0x8a0a3d67, 0xa44311ff, 0x6f876783, 0x43dc93ce, 0x88616a33,
+0xa8706e8f, 0x33a2cbed, 0x3a6d20c3, 0x55175086, 0x39680945, 0x2d779a7b,
+0x0818a4ce, 0x55558918, 0xf7c08d35, 0x980a3038, 0x9cf068db, 0x3385d333,
+0xd81b33fb, 0x188018d5, 0x47c57bd3, 0x9ec2324f, 0x6901cd77, 0xc3bac44f,
+0x4d96aba8, 0x9094da5b, 0xa67a1353, 0x1fdfc4db, 0xa2fbeefa, 0xab4828e3,
+0x37d1db45, 0x0d33b3e9, 0x1ad72bb9, 0x7257bf9c, 0x2ec35167, 0xa4488b7f,
+0xf9dae588, 0x1038905a, 0x88ddf410, 0xaac11693, 0x24ac025d, 0x56cefbb5,
+0x6afe7f59, 0xc7f989e8, 0x15872570, 0x1bf16cdb, 0xfe9c93ce, 0x1fc9a076,
+0x85d37185, 0x1078cd31, 0xe1cd0327, 0x6d5315bc, 0x298cd836, 0xc8e21f06,
+0xe561c32d, 0x8ec404b4, 0x4d39bfbb, 0x24ede8c8, 0x451d6034, 0x3bafeea2,
+0x202f0ccf, 0x1fad37ce, 0xf04b5693, 0xeee57cd9, 0x5ef70007, 0x018e8a4f,
+0xfa61c9a9, 0x09989fcf, 0xe66b558b, 0x966efd48, 0x7525021d, 0xe7978b5e,
+0x7eb1d6dc, 0xa10c5e5b, 0xb7815e69, 0x7d486cfb, 0xcffdeb2a, 0x7375cb32,
+0x599008dc, 0xff91c796, 0x560ed4ad, 0x14e9a876, 0xfccf6a66, 0xa58be028,
+0xea9d408b, 0x3afc373b, 0xee008458, 0x19b6042e, 0x84806314, 0x431a4ba4,
+0x009ad6a1, 0xd7c62bf4, 0x1bebecba, 0x5c662f69, 0x83bfdea1, 0x45872a9a,
+0x00c9
+
+
+ea =
+14412
+
+eb =
+14412
+
+cab =
+4
+
+c =
+4
+
+c_neg =
+0
+
+k_pos =
+4800
+
+k_neg =
+4736
+
+ncb_pos =
+14496
+
+ncb_neg =
+14304
+
+r =
+2
+
+rv_index =
+0
+
+code_block_mode =
+0
+
+op_flags =
+RTE_BBDEV_TURBO_CRC_24B_ATTACH
+
+expected_status =
+OK \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/turbo_dec_default.data b/src/spdk/dpdk/app/test-bbdev/turbo_dec_default.data
new file mode 120000
index 000000000..371cbc692
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/turbo_dec_default.data
@@ -0,0 +1 @@
+test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-bbdev/turbo_enc_default.data b/src/spdk/dpdk/app/test-bbdev/turbo_enc_default.data
new file mode 120000
index 000000000..a2bc833c1
--- /dev/null
+++ b/src/spdk/dpdk/app/test-bbdev/turbo_enc_default.data
@@ -0,0 +1 @@
+test_vectors/turbo_enc_c1_k6144_r0_e18444.data \ No newline at end of file
diff --git a/src/spdk/dpdk/app/test-cmdline/Makefile b/src/spdk/dpdk/app/test-cmdline/Makefile
new file mode 100644
index 000000000..3e7421906
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/Makefile
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_CMDLINE),y)
+
+#
+# library name
+#
+APP = cmdline_test
+
+#
+# all sources are stored in SRCS-y
+#
+SRCS-y += cmdline_test.c
+SRCS-y += commands.c
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-cmdline/cmdline_test.c b/src/spdk/dpdk/app/test-cmdline/cmdline_test.c
new file mode 100644
index 000000000..89f4260cb
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/cmdline_test.c
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <termios.h>
+#include <ctype.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include "cmdline_test.h"
+
+int
+main(int __rte_unused argc, char __rte_unused ** argv)
+{
+ struct cmdline *cl;
+
+ cl = cmdline_stdin_new(main_ctx, "CMDLINE_TEST>>");
+ if (cl == NULL) {
+ return -1;
+ }
+ cmdline_interact(cl);
+ cmdline_stdin_exit(cl);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-cmdline/cmdline_test.h b/src/spdk/dpdk/app/test-cmdline/cmdline_test.h
new file mode 100644
index 000000000..13af4f3dc
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/cmdline_test.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _CMDLINE_TEST_H_
+#define _CMDLINE_TEST_H_
+
+extern cmdline_parse_ctx_t main_ctx[];
+
+#endif
diff --git a/src/spdk/dpdk/app/test-cmdline/cmdline_test.py b/src/spdk/dpdk/app/test-cmdline/cmdline_test.py
new file mode 100755
index 000000000..3a8fac426
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/cmdline_test.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# Script that runs cmdline_test app and feeds keystrokes into it.
+from __future__ import print_function
+import cmdline_test_data
+import os
+import pexpect
+import sys
+
+
+#
+# function to run test
+#
+def runTest(child, test):
+ child.send(test["Sequence"])
+ if test["Result"] is None:
+ return 0
+ child.expect(test["Result"], 1)
+
+
+#
+# history test is a special case
+#
+# This test does the following:
+# 1) fills the history with garbage up to its full capacity
+# (just enough to remove last entry)
+# 2) scrolls back history to the very beginning
+# 3) checks if the output is as expected, that is, the first
+# number in the sequence (not the last entry before it)
+#
+# This is a self-contained test, it needs only a pexpect child
+#
+def runHistoryTest(child):
+ # find out history size
+ child.sendline(cmdline_test_data.CMD_GET_BUFSIZE)
+ child.expect("History buffer size: \\d+", timeout=1)
+ history_size = int(child.after[len(cmdline_test_data.BUFSIZE_TEMPLATE):])
+ i = 0
+
+ # fill the history with numbers
+ while i < history_size / 10:
+ # add 1 to prevent from parsing as octals
+ child.send("1" + str(i).zfill(8) + cmdline_test_data.ENTER)
+ # the app will simply print out the number
+ child.expect(str(i + 100000000), timeout=1)
+ i += 1
+ # scroll back history
+ child.send(cmdline_test_data.UP * (i + 2) + cmdline_test_data.ENTER)
+ child.expect("100000000", timeout=1)
+
+# the path to cmdline_test executable is supplied via command-line.
+if len(sys.argv) < 2:
+ print("Error: please supply cmdline_test app path")
+ sys.exit(1)
+
+test_app_path = sys.argv[1]
+
+if not os.path.exists(test_app_path):
+ print("Error: please supply cmdline_test app path")
+ sys.exit(1)
+
+child = pexpect.spawn(test_app_path)
+
+print("Running command-line tests...")
+for test in cmdline_test_data.tests:
+ testname = (test["Name"] + ":").ljust(30)
+ try:
+ runTest(child, test)
+ print(testname, "PASS")
+ except:
+ print(testname, "FAIL")
+ print(child)
+ sys.exit(1)
+
+# since last test quits the app, run new instance
+child = pexpect.spawn(test_app_path)
+
+testname = ("History fill test:").ljust(30)
+try:
+ runHistoryTest(child)
+ print(testname, "PASS")
+except:
+ print(testname, "FAIL")
+ print(child)
+ sys.exit(1)
+child.close()
+sys.exit(0)
diff --git a/src/spdk/dpdk/app/test-cmdline/cmdline_test_data.py b/src/spdk/dpdk/app/test-cmdline/cmdline_test_data.py
new file mode 100644
index 000000000..114d2cb6a
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/cmdline_test_data.py
@@ -0,0 +1,282 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# collection of static data
+
+# keycode constants
+CTRL_A = chr(1)
+CTRL_B = chr(2)
+CTRL_C = chr(3)
+CTRL_D = chr(4)
+CTRL_E = chr(5)
+CTRL_F = chr(6)
+CTRL_K = chr(11)
+CTRL_L = chr(12)
+CTRL_N = chr(14)
+CTRL_P = chr(16)
+CTRL_W = chr(23)
+CTRL_Y = chr(25)
+ALT_B = chr(27) + chr(98)
+ALT_D = chr(27) + chr(100)
+ALT_F = chr(27) + chr(102)
+ALT_BKSPACE = chr(27) + chr(127)
+DEL = chr(27) + chr(91) + chr(51) + chr(126)
+TAB = chr(9)
+HELP = chr(63)
+BKSPACE = chr(127)
+RIGHT = chr(27) + chr(91) + chr(67)
+DOWN = chr(27) + chr(91) + chr(66)
+LEFT = chr(27) + chr(91) + chr(68)
+UP = chr(27) + chr(91) + chr(65)
+ENTER2 = '\r'
+ENTER = '\n'
+
+# expected result constants
+NOT_FOUND = "Command not found"
+BAD_ARG = "Bad arguments"
+AMBIG = "Ambiguous command"
+CMD1 = "Command 1 parsed!"
+CMD2 = "Command 2 parsed!"
+SINGLE = "Single word command parsed!"
+SINGLE_LONG = "Single long word command parsed!"
+AUTO1 = "Autocomplete command 1 parsed!"
+AUTO2 = "Autocomplete command 2 parsed!"
+
+# misc defines
+CMD_QUIT = "quit"
+CMD_GET_BUFSIZE = "get_history_bufsize"
+BUFSIZE_TEMPLATE = "History buffer size: "
+PROMPT = "CMDLINE_TEST>>"
+
+# test defines
+# each test tests progressively diverse set of keys. this way for example
+# if we want to use some key sequence in the test, we first need to test
+# that it itself does what it is expected to do. Most of the tests are
+# designed that way.
+#
+# example: "arrows & delete test 1". we enter a partially valid command,
+# then move 3 chars left and use delete three times. this way we get to
+# know that "delete", "left" and "ctrl+B" all work (because if any of
+# them fails, the whole test will fail and next tests won't be run).
+#
+# each test consists of name, character sequence to send to child,
+# and expected output (if any).
+
+tests = [
+ # test basic commands
+ {"Name": "command test 1",
+ "Sequence": "ambiguous first" + ENTER,
+ "Result": CMD1},
+ {"Name": "command test 2",
+ "Sequence": "ambiguous second" + ENTER,
+ "Result": CMD2},
+ {"Name": "command test 3",
+ "Sequence": "ambiguous ambiguous" + ENTER,
+ "Result": AMBIG},
+ {"Name": "command test 4",
+ "Sequence": "ambiguous ambiguous2" + ENTER,
+ "Result": AMBIG},
+
+ {"Name": "invalid command test 1",
+ "Sequence": "ambiguous invalid" + ENTER,
+ "Result": BAD_ARG},
+ # test invalid commands
+ {"Name": "invalid command test 2",
+ "Sequence": "invalid" + ENTER,
+ "Result": NOT_FOUND},
+ {"Name": "invalid command test 3",
+ "Sequence": "ambiguousinvalid" + ENTER2,
+ "Result": NOT_FOUND},
+
+ # test arrows and deletes
+ {"Name": "arrows & delete test 1",
+ "Sequence": "singlebad" + LEFT*2 + CTRL_B + DEL*3 + ENTER,
+ "Result": SINGLE},
+ {"Name": "arrows & delete test 2",
+ "Sequence": "singlebad" + LEFT*5 + RIGHT + CTRL_F + DEL*3 + ENTER,
+ "Result": SINGLE},
+
+ # test backspace
+ {"Name": "backspace test",
+ "Sequence": "singlebad" + BKSPACE*3 + ENTER,
+ "Result": SINGLE},
+
+ # test goto left and goto right
+ {"Name": "goto left test",
+ "Sequence": "biguous first" + CTRL_A + "am" + ENTER,
+ "Result": CMD1},
+ {"Name": "goto right test",
+ "Sequence": "biguous fir" + CTRL_A + "am" + CTRL_E + "st" + ENTER,
+ "Result": CMD1},
+
+ # test goto words
+ {"Name": "goto left word test",
+ "Sequence": "ambiguous st" + ALT_B + "fir" + ENTER,
+ "Result": CMD1},
+ {"Name": "goto right word test",
+ "Sequence": "ambig first" + CTRL_A + ALT_F + "uous" + ENTER,
+ "Result": CMD1},
+
+ # test removing words
+ {"Name": "remove left word 1",
+ "Sequence": "single invalid" + CTRL_W + ENTER,
+ "Result": SINGLE},
+ {"Name": "remove left word 2",
+ "Sequence": "single invalid" + ALT_BKSPACE + ENTER,
+ "Result": SINGLE},
+ {"Name": "remove right word",
+ "Sequence": "single invalid" + ALT_B + ALT_D + ENTER,
+ "Result": SINGLE},
+
+ # test kill buffer (copy and paste)
+ {"Name": "killbuffer test 1",
+ "Sequence": "ambiguous" + CTRL_A + CTRL_K + " first" + CTRL_A +
+ CTRL_Y + ENTER,
+ "Result": CMD1},
+ {"Name": "killbuffer test 2",
+ "Sequence": "ambiguous" + CTRL_A + CTRL_K + CTRL_Y*26 + ENTER,
+ "Result": NOT_FOUND},
+
+ # test newline
+ {"Name": "newline test",
+ "Sequence": "invalid" + CTRL_C + "single" + ENTER,
+ "Result": SINGLE},
+
+ # test redisplay (nothing should really happen)
+ {"Name": "redisplay test",
+ "Sequence": "single" + CTRL_L + ENTER,
+ "Result": SINGLE},
+
+ # test autocomplete
+ {"Name": "autocomplete test 1",
+ "Sequence": "si" + TAB + ENTER,
+ "Result": SINGLE},
+ {"Name": "autocomplete test 2",
+ "Sequence": "si" + TAB + "_" + TAB + ENTER,
+ "Result": SINGLE_LONG},
+ {"Name": "autocomplete test 3",
+ "Sequence": "in" + TAB + ENTER,
+ "Result": NOT_FOUND},
+ {"Name": "autocomplete test 4",
+ "Sequence": "am" + TAB + ENTER,
+ "Result": BAD_ARG},
+ {"Name": "autocomplete test 5",
+ "Sequence": "am" + TAB + "fir" + TAB + ENTER,
+ "Result": CMD1},
+ {"Name": "autocomplete test 6",
+ "Sequence": "am" + TAB + "fir" + TAB + TAB + ENTER,
+ "Result": CMD1},
+ {"Name": "autocomplete test 7",
+ "Sequence": "am" + TAB + "fir" + TAB + " " + TAB + ENTER,
+ "Result": CMD1},
+ {"Name": "autocomplete test 8",
+ "Sequence": "am" + TAB + " am" + TAB + " " + ENTER,
+ "Result": AMBIG},
+ {"Name": "autocomplete test 9",
+ "Sequence": "am" + TAB + "inv" + TAB + ENTER,
+ "Result": BAD_ARG},
+ {"Name": "autocomplete test 10",
+ "Sequence": "au" + TAB + ENTER,
+ "Result": NOT_FOUND},
+ {"Name": "autocomplete test 11",
+ "Sequence": "au" + TAB + "1" + ENTER,
+ "Result": AUTO1},
+ {"Name": "autocomplete test 12",
+ "Sequence": "au" + TAB + "2" + ENTER,
+ "Result": AUTO2},
+ {"Name": "autocomplete test 13",
+ "Sequence": "au" + TAB + "2" + TAB + ENTER,
+ "Result": AUTO2},
+ {"Name": "autocomplete test 14",
+ "Sequence": "au" + TAB + "2 " + TAB + ENTER,
+ "Result": AUTO2},
+ {"Name": "autocomplete test 15",
+ "Sequence": "24" + TAB + ENTER,
+ "Result": "24"},
+
+ # test history
+ {"Name": "history test 1",
+ "Sequence": "invalid" + ENTER + "single" + ENTER + "invalid" +
+ ENTER + UP + CTRL_P + ENTER,
+ "Result": SINGLE},
+ {"Name": "history test 2",
+ "Sequence": "invalid" + ENTER + "ambiguous first" + ENTER + "invalid" +
+ ENTER + "single" + ENTER + UP * 3 + CTRL_N + DOWN + ENTER,
+ "Result": SINGLE},
+
+ #
+ # tests that improve coverage
+ #
+
+ # empty space tests
+ {"Name": "empty space test 1",
+ "Sequence": RIGHT + LEFT + CTRL_B + CTRL_F + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 2",
+ "Sequence": BKSPACE + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 3",
+ "Sequence": CTRL_E*2 + CTRL_A*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 4",
+ "Sequence": ALT_F*2 + ALT_B*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 5",
+ "Sequence": " " + CTRL_E*2 + CTRL_A*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 6",
+ "Sequence": " " + CTRL_A + ALT_F*2 + ALT_B*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 7",
+ "Sequence": " " + CTRL_A + CTRL_D + CTRL_E + CTRL_D + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 8",
+ "Sequence": " space" + CTRL_W*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 9",
+ "Sequence": " space" + ALT_BKSPACE*2 + ENTER,
+ "Result": PROMPT},
+ {"Name": "empty space test 10",
+ "Sequence": " space " + CTRL_A + ALT_D*3 + ENTER,
+ "Result": PROMPT},
+
+ # non-printable char tests
+ {"Name": "non-printable test 1",
+ "Sequence": chr(27) + chr(47) + ENTER,
+ "Result": PROMPT},
+ {"Name": "non-printable test 2",
+ "Sequence": chr(27) + chr(128) + ENTER*7,
+ "Result": PROMPT},
+ {"Name": "non-printable test 3",
+ "Sequence": chr(27) + chr(91) + chr(127) + ENTER*6,
+ "Result": PROMPT},
+
+ # miscellaneous tests
+ {"Name": "misc test 1",
+ "Sequence": ENTER,
+ "Result": PROMPT},
+ {"Name": "misc test 2",
+ "Sequence": "single #comment" + ENTER,
+ "Result": SINGLE},
+ {"Name": "misc test 3",
+ "Sequence": "#empty line" + ENTER,
+ "Result": PROMPT},
+ {"Name": "misc test 4",
+ "Sequence": " single " + ENTER,
+ "Result": SINGLE},
+ {"Name": "misc test 5",
+ "Sequence": "single#" + ENTER,
+ "Result": SINGLE},
+ {"Name": "misc test 6",
+ "Sequence": 'a' * 257 + ENTER,
+ "Result": NOT_FOUND},
+ {"Name": "misc test 7",
+ "Sequence": "clear_history" + UP*5 + DOWN*5 + ENTER,
+ "Result": PROMPT},
+ {"Name": "misc test 8",
+ "Sequence": "a" + HELP + CTRL_C,
+ "Result": PROMPT},
+ {"Name": "misc test 9",
+ "Sequence": CTRL_D*3,
+ "Result": None},
+]
diff --git a/src/spdk/dpdk/app/test-cmdline/commands.c b/src/spdk/dpdk/app/test-cmdline/commands.c
new file mode 100644
index 000000000..d67c0ca6a
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/commands.c
@@ -0,0 +1,362 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_num.h>
+#include <cmdline.h>
+
+#include "cmdline_test.h"
+
+/*** quit ***/
+/* exit application */
+
+struct cmd_quit_result {
+ cmdline_fixed_string_t quit;
+};
+
+static void
+cmd_quit_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_quit(cl);
+}
+
+cmdline_parse_token_string_t cmd_quit_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit,
+ "quit");
+
+cmdline_parse_inst_t cmd_quit = {
+ .f = cmd_quit_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "exit application",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_quit_tok,
+ NULL,
+ },
+};
+
+
+
+/*** single ***/
+/* a simple single-word command */
+
+struct cmd_single_result {
+ cmdline_fixed_string_t single;
+};
+
+static void
+cmd_single_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Single word command parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_single_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_single_result, single,
+ "single");
+
+cmdline_parse_inst_t cmd_single = {
+ .f = cmd_single_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "a simple single-word command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_single_tok,
+ NULL,
+ },
+};
+
+
+
+/*** single_long ***/
+/* a variant of "single" command. useful to test autocomplete */
+
+struct cmd_single_long_result {
+ cmdline_fixed_string_t single_long;
+};
+
+static void
+cmd_single_long_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Single long word command parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_single_long_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_single_long_result, single_long,
+ "single_long");
+
+cmdline_parse_inst_t cmd_single_long = {
+ .f = cmd_single_long_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "a variant of \"single\" command, useful to test autocomplete",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_single_long_tok,
+ NULL,
+ },
+};
+
+
+
+/*** autocomplete_1 ***/
+/* first command to test autocomplete when multiple commands have chars
+ * in common but none should complete due to ambiguity
+ */
+
+struct cmd_autocomplete_1_result {
+ cmdline_fixed_string_t token;
+};
+
+static void
+cmd_autocomplete_1_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Autocomplete command 1 parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_autocomplete_1_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_1_result, token,
+ "autocomplete_1");
+
+cmdline_parse_inst_t cmd_autocomplete_1 = {
+ .f = cmd_autocomplete_1_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "first ambiguous autocomplete command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_autocomplete_1_tok,
+ NULL,
+ },
+};
+
+
+
+/*** autocomplete_2 ***/
+/* second command to test autocomplete when multiple commands have chars
+ * in common but none should complete due to ambiguity
+ */
+
+struct cmd_autocomplete_2_result {
+ cmdline_fixed_string_t token;
+};
+
+static void
+cmd_autocomplete_2_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Autocomplete command 2 parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_autocomplete_2_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_2_result, token,
+ "autocomplete_2");
+
+cmdline_parse_inst_t cmd_autocomplete_2 = {
+ .f = cmd_autocomplete_2_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "second ambiguous autocomplete command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_autocomplete_2_tok,
+ NULL,
+ },
+};
+
+
+
+/*** number command ***/
+/* a command that simply returns whatever (uint32) number is supplied to it */
+
+struct cmd_num_result {
+ unsigned num;
+};
+
+static void
+cmd_num_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ unsigned result = ((struct cmd_num_result*)parsed_result)->num;
+ cmdline_printf(cl, "%u\n", result);
+}
+
+cmdline_parse_token_num_t cmd_num_tok =
+ TOKEN_NUM_INITIALIZER(struct cmd_num_result, num, UINT32);
+
+cmdline_parse_inst_t cmd_num = {
+ .f = cmd_num_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "a command that simply returns whatever number is entered",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_num_tok,
+ NULL,
+ },
+};
+
+
+
+/*** ambiguous first|ambiguous ***/
+/* first command used to test command ambiguity */
+
+struct cmd_ambig_result_1 {
+ cmdline_fixed_string_t common_part;
+ cmdline_fixed_string_t ambig_part;
+};
+
+static void
+cmd_ambig_1_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Command 1 parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_ambig_common_1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, common_part,
+ "ambiguous");
+cmdline_parse_token_string_t cmd_ambig_ambig_1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, ambig_part,
+ "first#ambiguous#ambiguous2");
+
+cmdline_parse_inst_t cmd_ambig_1 = {
+ .f = cmd_ambig_1_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "first command used to test command ambiguity",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_ambig_common_1,
+ (void*)&cmd_ambig_ambig_1,
+ NULL,
+ },
+};
+
+
+
+/*** ambiguous second|ambiguous ***/
+/* second command used to test command ambiguity */
+
+struct cmd_ambig_result_2 {
+ cmdline_fixed_string_t common_part;
+ cmdline_fixed_string_t ambig_part;
+};
+
+static void
+cmd_ambig_2_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Command 2 parsed!\n");
+}
+
+cmdline_parse_token_string_t cmd_ambig_common_2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, common_part,
+ "ambiguous");
+cmdline_parse_token_string_t cmd_ambig_ambig_2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, ambig_part,
+ "second#ambiguous#ambiguous2");
+
+cmdline_parse_inst_t cmd_ambig_2 = {
+ .f = cmd_ambig_2_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "second command used to test command ambiguity",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_ambig_common_2,
+ (void*)&cmd_ambig_ambig_2,
+ NULL,
+ },
+};
+
+
+
+/*** get_history_bufsize ***/
+/* command that displays total space in history buffer
+ * this will be useful for testing history (to fill it up just enough to
+ * remove the last entry, we need to know how big it is).
+ */
+
+struct cmd_get_history_bufsize_result {
+ cmdline_fixed_string_t str;
+};
+
+static void
+cmd_get_history_bufsize_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "History buffer size: %zu\n",
+ sizeof(cl->rdl.history_buf));
+}
+
+cmdline_parse_token_string_t cmd_get_history_bufsize_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str,
+ "get_history_bufsize");
+
+cmdline_parse_inst_t cmd_get_history_bufsize = {
+ .f = cmd_get_history_bufsize_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "command that displays total space in history buffer",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_get_history_bufsize_tok,
+ NULL,
+ },
+};
+
+
+
+/*** clear_history ***/
+/* clears history buffer */
+
+struct cmd_clear_history_result {
+ cmdline_fixed_string_t str;
+};
+
+static void
+cmd_clear_history_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ rdline_clear_history(&cl->rdl);
+}
+
+cmdline_parse_token_string_t cmd_clear_history_tok =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str,
+ "clear_history");
+
+cmdline_parse_inst_t cmd_clear_history = {
+ .f = cmd_clear_history_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "clear command history",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_clear_history_tok,
+ NULL,
+ },
+};
+
+
+
+/****************/
+
+cmdline_parse_ctx_t main_ctx[] = {
+ (cmdline_parse_inst_t *)&cmd_quit,
+ (cmdline_parse_inst_t *)&cmd_ambig_1,
+ (cmdline_parse_inst_t *)&cmd_ambig_2,
+ (cmdline_parse_inst_t *)&cmd_single,
+ (cmdline_parse_inst_t *)&cmd_single_long,
+ (cmdline_parse_inst_t *)&cmd_num,
+ (cmdline_parse_inst_t *)&cmd_get_history_bufsize,
+ (cmdline_parse_inst_t *)&cmd_clear_history,
+ (cmdline_parse_inst_t *)&cmd_autocomplete_1,
+ (cmdline_parse_inst_t *)&cmd_autocomplete_2,
+ NULL,
+};
diff --git a/src/spdk/dpdk/app/test-cmdline/meson.build b/src/spdk/dpdk/app/test-cmdline/meson.build
new file mode 100644
index 000000000..9d0a9aeb6
--- /dev/null
+++ b/src/spdk/dpdk/app/test-cmdline/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+sources = files('commands.c', 'cmdline_test.c')
+deps += 'cmdline'
diff --git a/src/spdk/dpdk/app/test-compress-perf/Makefile b/src/spdk/dpdk/app/test-compress-perf/Makefile
new file mode 100644
index 000000000..2bff53183
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/Makefile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+APP = dpdk-test-compress-perf
+
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -O3
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+SRCS-y += comp_perf_options_parse.c
+SRCS-y += comp_perf_test_verify.c
+SRCS-y += comp_perf_test_throughput.c
+SRCS-y += comp_perf_test_cyclecount.c
+SRCS-y += comp_perf_test_common.c
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf.h
new file mode 100644
index 000000000..997d46b59
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_
+#define _COMP_PERF_
+
+#include <rte_mempool.h>
+
+struct comp_test_data;
+
+typedef void *(*cperf_constructor_t)(
+ uint8_t dev_id,
+ uint16_t qp_id,
+ struct comp_test_data *options);
+
+typedef int (*cperf_runner_t)(void *test_ctx);
+typedef void (*cperf_destructor_t)(void *test_ctx);
+
+struct cperf_test {
+ cperf_constructor_t constructor;
+ cperf_runner_t runner;
+ cperf_destructor_t destructor;
+};
+
+/* Needed for weak functions*/
+
+void *
+cperf_throughput_test_constructor(uint8_t dev_id __rte_unused,
+ uint16_t qp_id __rte_unused,
+ struct comp_test_data *options __rte_unused);
+
+void
+cperf_throughput_test_destructor(void *arg __rte_unused);
+
+int
+cperf_throughput_test_runner(void *test_ctx __rte_unused);
+
+void *
+cperf_verify_test_constructor(uint8_t dev_id __rte_unused,
+ uint16_t qp_id __rte_unused,
+ struct comp_test_data *options __rte_unused);
+
+void
+cperf_verify_test_destructor(void *arg __rte_unused);
+
+int
+cperf_verify_test_runner(void *test_ctx __rte_unused);
+
+#endif /* _COMP_PERF_ */
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_options.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf_options.h
new file mode 100644
index 000000000..0b777521c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_options.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_OPS_
+#define _COMP_PERF_OPS_
+
+#define MAX_LIST 32
+#define MIN_COMPRESSED_BUF_SIZE 8
+#define EXPANSE_RATIO 1.1
+#define MAX_MBUF_DATA_SIZE (UINT16_MAX - RTE_PKTMBUF_HEADROOM)
+#define MAX_SEG_SIZE ((int)(MAX_MBUF_DATA_SIZE / EXPANSE_RATIO))
+
+extern const char *comp_perf_test_type_strs[];
+
+/* Cleanup state machine */
+enum cleanup_st {
+ ST_CLEAR = 0,
+ ST_TEST_DATA,
+ ST_COMPDEV,
+ ST_INPUT_DATA,
+ ST_MEMORY_ALLOC,
+ ST_DURING_TEST
+};
+
+enum cperf_test_type {
+ CPERF_TEST_TYPE_THROUGHPUT,
+ CPERF_TEST_TYPE_VERIFY,
+ CPERF_TEST_TYPE_PMDCC
+};
+
+enum comp_operation {
+ COMPRESS_ONLY,
+ DECOMPRESS_ONLY,
+ COMPRESS_DECOMPRESS
+};
+
+struct range_list {
+ uint8_t min;
+ uint8_t max;
+ uint8_t inc;
+ uint8_t count;
+ uint8_t list[MAX_LIST];
+};
+
+struct comp_test_data {
+ char driver_name[RTE_DEV_NAME_MAX_LEN];
+ char input_file[PATH_MAX];
+ enum cperf_test_type test;
+
+ uint8_t *input_data;
+ size_t input_data_sz;
+ uint16_t nb_qps;
+ uint16_t seg_sz;
+ uint16_t out_seg_sz;
+ uint16_t burst_sz;
+ uint32_t pool_sz;
+ uint32_t num_iter;
+ uint16_t max_sgl_segs;
+ uint32_t total_segs;
+
+ enum rte_comp_huffman huffman_enc;
+ enum comp_operation test_op;
+ int window_sz;
+ struct range_list level_lst;
+ uint8_t level;
+ int use_external_mbufs;
+
+ double ratio;
+ enum cleanup_st cleanup;
+ int perf_comp_force_stop;
+
+ uint32_t cyclecount_delay;
+};
+
+int
+comp_perf_options_parse(struct comp_test_data *test_data, int argc,
+ char **argv);
+
+void
+comp_perf_options_default(struct comp_test_data *test_data);
+
+int
+comp_perf_options_check(struct comp_test_data *test_data);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_options_parse.c b/src/spdk/dpdk/app/test-compress-perf/comp_perf_options_parse.c
new file mode 100644
index 000000000..04a8d2fbe
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_options_parse.c
@@ -0,0 +1,675 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <rte_string_fns.h>
+#include <rte_comp.h>
+
+#include "comp_perf_options.h"
+
+#define CPERF_PTEST_TYPE ("ptest")
+#define CPERF_DRIVER_NAME ("driver-name")
+#define CPERF_TEST_FILE ("input-file")
+#define CPERF_SEG_SIZE ("seg-sz")
+#define CPERF_BURST_SIZE ("burst-sz")
+#define CPERF_EXTENDED_SIZE ("extended-input-sz")
+#define CPERF_POOL_SIZE ("pool-sz")
+#define CPERF_MAX_SGL_SEGS ("max-num-sgl-segs")
+#define CPERF_NUM_ITER ("num-iter")
+#define CPERF_OPTYPE ("operation")
+#define CPERF_HUFFMAN_ENC ("huffman-enc")
+#define CPERF_LEVEL ("compress-level")
+#define CPERF_WINDOW_SIZE ("window-sz")
+#define CPERF_EXTERNAL_MBUFS ("external-mbufs")
+
+/* cyclecount-specific options */
+#define CPERF_CYCLECOUNT_DELAY_US ("cc-delay-us")
+
+struct name_id_map {
+ const char *name;
+ uint32_t id;
+};
+
+static void
+usage(char *progname)
+{
+ printf("%s [EAL options] --\n"
+ " --ptest throughput / verify / pmd-cyclecount\n"
+ " --driver-name NAME: compress driver to use\n"
+ " --input-file NAME: file to compress and decompress\n"
+ " --extended-input-sz N: extend file data up to this size (default: no extension)\n"
+ " --seg-sz N: size of segment to store the data (default: 2048)\n"
+ " --burst-sz N: compress operation burst size\n"
+ " --pool-sz N: mempool size for compress operations/mbufs\n"
+ " (default: 8192)\n"
+ " --max-num-sgl-segs N: maximum number of segments for each mbuf\n"
+ " (default: 16)\n"
+ " --num-iter N: number of times the file will be\n"
+ " compressed/decompressed (default: 10000)\n"
+ " --operation [comp/decomp/comp_and_decomp]: perform test on\n"
+ " compression, decompression or both operations\n"
+ " --huffman-enc [fixed/dynamic/default]: Huffman encoding\n"
+ " (default: dynamic)\n"
+ " --compress-level N: compression level, which could be a single value, list or range\n"
+ " (default: range between 1 and 9)\n"
+ " --window-sz N: base two log value of compression window size\n"
+ " (e.g.: 15 => 32k, default: max supported by PMD)\n"
+ " --external-mbufs: use memzones as external buffers instead of\n"
+ " keeping the data directly in mbuf area\n"
+ " --cc-delay-us N: delay between enqueue and dequeue operations in microseconds\n"
+ " valid only for cyclecount perf test (default: 500 us)\n"
+ " -h: prints this help\n",
+ progname);
+}
+
+static int
+get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
+ const char *str_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < map_len; i++) {
+
+ if (strcmp(str_key, map[i].name) == 0)
+ return map[i].id;
+ }
+
+ return -1;
+}
+
+static int
+parse_cperf_test_type(struct comp_test_data *test_data, const char *arg)
+{
+ struct name_id_map cperftest_namemap[] = {
+ {
+ comp_perf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
+ CPERF_TEST_TYPE_THROUGHPUT
+ },
+ {
+ comp_perf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
+ CPERF_TEST_TYPE_VERIFY
+ },
+ {
+ comp_perf_test_type_strs[CPERF_TEST_TYPE_PMDCC],
+ CPERF_TEST_TYPE_PMDCC
+ }
+ };
+
+ int id = get_str_key_id_mapping(
+ (struct name_id_map *)cperftest_namemap,
+ RTE_DIM(cperftest_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse test type");
+ return -1;
+ }
+
+ test_data->test = (enum cperf_test_type)id;
+
+ return 0;
+}
+
+static int
+parse_uint32_t(uint32_t *value, const char *arg)
+{
+ char *end = NULL;
+ unsigned long n = strtoul(arg, &end, 10);
+
+ if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (n > UINT32_MAX)
+ return -ERANGE;
+
+ *value = (uint32_t) n;
+
+ return 0;
+}
+
+static int
+parse_uint16_t(uint16_t *value, const char *arg)
+{
+ uint32_t val = 0;
+ int ret = parse_uint32_t(&val, arg);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = (uint16_t) val;
+
+ return 0;
+}
+
+static int
+parse_range(const char *arg, uint8_t *min, uint8_t *max, uint8_t *inc)
+{
+ char *token;
+ uint8_t number;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ errno = 0;
+ token = strtok(copy_arg, ":");
+
+ /* Parse minimum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE)
+ goto err_range;
+
+ *min = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse increment value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_range;
+
+ *inc = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse maximum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number < *min)
+ goto err_range;
+
+ *max = number;
+ } else
+ goto err_range;
+
+ if (strtok(NULL, ":") != NULL)
+ goto err_range;
+
+ free(copy_arg);
+ return 0;
+
+err_range:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_list(const char *arg, uint8_t *list, uint8_t *min, uint8_t *max)
+{
+ char *token;
+ uint32_t number;
+ uint8_t count = 0;
+ uint32_t temp_min;
+ uint32_t temp_max;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ errno = 0;
+ token = strtok(copy_arg, ",");
+
+ /* Parse first value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE)
+ goto err_list;
+
+ list[count++] = number;
+ temp_min = number;
+ temp_max = number;
+ } else
+ goto err_list;
+
+ token = strtok(NULL, ",");
+
+ while (token != NULL) {
+ if (count == MAX_LIST) {
+ RTE_LOG(WARNING, USER1,
+ "Using only the first %u sizes\n",
+ MAX_LIST);
+ break;
+ }
+
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE)
+ goto err_list;
+
+ list[count++] = number;
+
+ if (number < temp_min)
+ temp_min = number;
+ if (number > temp_max)
+ temp_max = number;
+
+ token = strtok(NULL, ",");
+ }
+
+ if (min)
+ *min = temp_min;
+ if (max)
+ *max = temp_max;
+
+ free(copy_arg);
+ return count;
+
+err_list:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_num_iter(struct comp_test_data *test_data, const char *arg)
+{
+ int ret = parse_uint32_t(&test_data->num_iter, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse total iteration count\n");
+ return -1;
+ }
+
+ if (test_data->num_iter == 0) {
+ RTE_LOG(ERR, USER1,
+ "Total number of iterations must be higher than 0\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int
+parse_pool_sz(struct comp_test_data *test_data, const char *arg)
+{
+ int ret = parse_uint32_t(&test_data->pool_sz, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse pool size");
+ return -1;
+ }
+
+ if (test_data->pool_sz == 0) {
+ RTE_LOG(ERR, USER1, "Pool size must be higher than 0\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int
+parse_burst_sz(struct comp_test_data *test_data, const char *arg)
+{
+ int ret = parse_uint16_t(&test_data->burst_sz, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse burst size/s\n");
+ return -1;
+ }
+
+ if (test_data->burst_sz == 0) {
+ RTE_LOG(ERR, USER1, "Burst size must be higher than 0\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_extended_input_sz(struct comp_test_data *test_data, const char *arg)
+{
+ uint32_t tmp;
+ int ret = parse_uint32_t(&tmp, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse extended input size\n");
+ return -1;
+ }
+ test_data->input_data_sz = tmp;
+
+ if (tmp == 0) {
+ RTE_LOG(ERR, USER1,
+ "Extended file size must be higher than 0\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+parse_seg_sz(struct comp_test_data *test_data, const char *arg)
+{
+ int ret = parse_uint16_t(&test_data->seg_sz, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse segment size\n");
+ return -1;
+ }
+
+ if (test_data->seg_sz < MIN_COMPRESSED_BUF_SIZE) {
+ RTE_LOG(ERR, USER1, "Segment size must be higher than %d\n",
+ MIN_COMPRESSED_BUF_SIZE - 1);
+ return -1;
+ }
+
+ if (test_data->seg_sz > MAX_SEG_SIZE) {
+ RTE_LOG(ERR, USER1, "Segment size must be lower than %d\n",
+ MAX_SEG_SIZE + 1);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_max_num_sgl_segs(struct comp_test_data *test_data, const char *arg)
+{
+ int ret = parse_uint16_t(&test_data->max_sgl_segs, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1,
+ "Failed to parse max number of segments per mbuf chain\n");
+ return -1;
+ }
+
+ if (test_data->max_sgl_segs == 0) {
+ RTE_LOG(ERR, USER1, "Max number of segments per mbuf chain "
+ "must be higher than 0\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_window_sz(struct comp_test_data *test_data, const char *arg)
+{
+ uint16_t tmp;
+ int ret = parse_uint16_t(&tmp, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse window size\n");
+ return -1;
+ }
+ test_data->window_sz = (int)tmp;
+
+ return 0;
+}
+
+static int
+parse_driver_name(struct comp_test_data *test_data, const char *arg)
+{
+ if (strlen(arg) > (sizeof(test_data->driver_name) - 1))
+ return -1;
+
+ strlcpy(test_data->driver_name, arg,
+ sizeof(test_data->driver_name));
+
+ return 0;
+}
+
+static int
+parse_test_file(struct comp_test_data *test_data, const char *arg)
+{
+ if (strlen(arg) > (sizeof(test_data->input_file) - 1))
+ return -1;
+
+ strlcpy(test_data->input_file, arg, sizeof(test_data->input_file));
+
+ return 0;
+}
+
+static int
+parse_op_type(struct comp_test_data *test_data, const char *arg)
+{
+ struct name_id_map optype_namemap[] = {
+ {
+ "comp",
+ COMPRESS_ONLY
+ },
+ {
+ "decomp",
+ DECOMPRESS_ONLY
+ },
+ {
+ "comp_and_decomp",
+ COMPRESS_DECOMPRESS
+ }
+ };
+
+ int id = get_str_key_id_mapping(optype_namemap,
+ RTE_DIM(optype_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "Invalid operation type specified\n");
+ return -1;
+ }
+
+ test_data->test_op = (enum comp_operation)id;
+
+ return 0;
+}
+
+static int
+parse_huffman_enc(struct comp_test_data *test_data, const char *arg)
+{
+ struct name_id_map huffman_namemap[] = {
+ {
+ "default",
+ RTE_COMP_HUFFMAN_DEFAULT
+ },
+ {
+ "fixed",
+ RTE_COMP_HUFFMAN_FIXED
+ },
+ {
+ "dynamic",
+ RTE_COMP_HUFFMAN_DYNAMIC
+ }
+ };
+
+ int id = get_str_key_id_mapping(huffman_namemap,
+ RTE_DIM(huffman_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "Invalid Huffmane encoding specified\n");
+ return -1;
+ }
+
+ test_data->huffman_enc = (enum rte_comp_huffman)id;
+
+ return 0;
+}
+
+static int
+parse_level(struct comp_test_data *test_data, const char *arg)
+{
+ int ret;
+
+ /*
+ * Try parsing the argument as a range, if it fails,
+ * arse it as a list
+ */
+ if (parse_range(arg, &test_data->level_lst.min,
+ &test_data->level_lst.max,
+ &test_data->level_lst.inc) < 0) {
+ ret = parse_list(arg, test_data->level_lst.list,
+ &test_data->level_lst.min,
+ &test_data->level_lst.max);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to parse compression level/s\n");
+ return -1;
+ }
+ test_data->level_lst.count = ret;
+
+ if (test_data->level_lst.max > RTE_COMP_LEVEL_MAX) {
+ RTE_LOG(ERR, USER1, "Level cannot be higher than %u\n",
+ RTE_COMP_LEVEL_MAX);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_external_mbufs(struct comp_test_data *test_data,
+ const char *arg __rte_unused)
+{
+ test_data->use_external_mbufs = 1;
+ return 0;
+}
+
+static int
+parse_cyclecount_delay_us(struct comp_test_data *test_data,
+ const char *arg)
+{
+ int ret = parse_uint32_t(&(test_data->cyclecount_delay), arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to parse cyclecount delay\n");
+ return -1;
+ }
+ return 0;
+}
+
+typedef int (*option_parser_t)(struct comp_test_data *test_data,
+ const char *arg);
+
+struct long_opt_parser {
+ const char *lgopt_name;
+ option_parser_t parser_fn;
+};
+
+static struct option lgopts[] = {
+ { CPERF_PTEST_TYPE, required_argument, 0, 0 },
+ { CPERF_DRIVER_NAME, required_argument, 0, 0 },
+ { CPERF_TEST_FILE, required_argument, 0, 0 },
+ { CPERF_SEG_SIZE, required_argument, 0, 0 },
+ { CPERF_BURST_SIZE, required_argument, 0, 0 },
+ { CPERF_EXTENDED_SIZE, required_argument, 0, 0 },
+ { CPERF_POOL_SIZE, required_argument, 0, 0 },
+ { CPERF_MAX_SGL_SEGS, required_argument, 0, 0},
+ { CPERF_NUM_ITER, required_argument, 0, 0 },
+ { CPERF_OPTYPE, required_argument, 0, 0 },
+ { CPERF_HUFFMAN_ENC, required_argument, 0, 0 },
+ { CPERF_LEVEL, required_argument, 0, 0 },
+ { CPERF_WINDOW_SIZE, required_argument, 0, 0 },
+ { CPERF_EXTERNAL_MBUFS, 0, 0, 0 },
+ { CPERF_CYCLECOUNT_DELAY_US, required_argument, 0, 0 },
+ { NULL, 0, 0, 0 }
+};
+
+static int
+comp_perf_opts_parse_long(int opt_idx, struct comp_test_data *test_data)
+{
+ struct long_opt_parser parsermap[] = {
+ { CPERF_PTEST_TYPE, parse_cperf_test_type },
+ { CPERF_DRIVER_NAME, parse_driver_name },
+ { CPERF_TEST_FILE, parse_test_file },
+ { CPERF_SEG_SIZE, parse_seg_sz },
+ { CPERF_BURST_SIZE, parse_burst_sz },
+ { CPERF_EXTENDED_SIZE, parse_extended_input_sz },
+ { CPERF_POOL_SIZE, parse_pool_sz },
+ { CPERF_MAX_SGL_SEGS, parse_max_num_sgl_segs },
+ { CPERF_NUM_ITER, parse_num_iter },
+ { CPERF_OPTYPE, parse_op_type },
+ { CPERF_HUFFMAN_ENC, parse_huffman_enc },
+ { CPERF_LEVEL, parse_level },
+ { CPERF_WINDOW_SIZE, parse_window_sz },
+ { CPERF_EXTERNAL_MBUFS, parse_external_mbufs },
+ { CPERF_CYCLECOUNT_DELAY_US, parse_cyclecount_delay_us },
+ };
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(parsermap); i++) {
+ if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+ strlen(lgopts[opt_idx].name)) == 0)
+ return parsermap[i].parser_fn(test_data, optarg);
+ }
+
+ return -EINVAL;
+}
+
+int
+comp_perf_options_parse(struct comp_test_data *test_data, int argc, char **argv)
+{
+ int opt, retval, opt_idx;
+
+ while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ break;
+ /* long options */
+ case 0:
+ retval = comp_perf_opts_parse_long(opt_idx, test_data);
+ if (retval != 0)
+ return retval;
+
+ break;
+
+ default:
+ usage(argv[0]);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+void
+comp_perf_options_default(struct comp_test_data *test_data)
+{
+ test_data->seg_sz = 2048;
+ test_data->burst_sz = 32;
+ test_data->pool_sz = 8192;
+ test_data->max_sgl_segs = 16;
+ test_data->num_iter = 10000;
+ test_data->huffman_enc = RTE_COMP_HUFFMAN_DYNAMIC;
+ test_data->test_op = COMPRESS_DECOMPRESS;
+ test_data->window_sz = -1;
+ test_data->level_lst.min = RTE_COMP_LEVEL_MIN;
+ test_data->level_lst.max = RTE_COMP_LEVEL_MAX;
+ test_data->level_lst.inc = 1;
+ test_data->test = CPERF_TEST_TYPE_THROUGHPUT;
+ test_data->use_external_mbufs = 0;
+ test_data->cyclecount_delay = 500;
+}
+
+int
+comp_perf_options_check(struct comp_test_data *test_data)
+{
+ if (test_data->driver_name[0] == '\0') {
+ RTE_LOG(ERR, USER1, "Driver name has to be set\n");
+ return -1;
+ }
+
+ if (test_data->input_file[0] == '\0') {
+ RTE_LOG(ERR, USER1, "Input file name has to be set\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.c b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.c
new file mode 100644
index 000000000..b402a0d83
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.c
@@ -0,0 +1,569 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_compressdev.h>
+
+#include "comp_perf.h"
+#include "comp_perf_options.h"
+#include "comp_perf_test_throughput.h"
+#include "comp_perf_test_cyclecount.h"
+#include "comp_perf_test_common.h"
+#include "comp_perf_test_verify.h"
+
+
+#define DIV_CEIL(a, b) ((a) / (b) + ((a) % (b) != 0))
+
+struct cperf_buffer_info {
+ uint16_t total_segments;
+ uint16_t segment_sz;
+ uint16_t last_segment_sz;
+ uint32_t total_buffs; /*number of buffers = number of ops*/
+ uint16_t segments_per_buff;
+ uint16_t segments_per_last_buff;
+ size_t input_data_sz;
+};
+
+static struct cperf_buffer_info buffer_info;
+
+int
+param_range_check(uint16_t size, const struct rte_param_log2_range *range)
+{
+ unsigned int next_size;
+
+ /* Check lower/upper bounds */
+ if (size < range->min)
+ return -1;
+
+ if (size > range->max)
+ return -1;
+
+ /* If range is actually only one value, size is correct */
+ if (range->increment == 0)
+ return 0;
+
+ /* Check if value is one of the supported sizes */
+ for (next_size = range->min; next_size <= range->max;
+ next_size += range->increment)
+ if (size == next_size)
+ return 0;
+
+ return -1;
+}
+
+static uint32_t
+find_buf_size(uint32_t input_size)
+{
+ uint32_t i;
+
+ /* From performance point of view the buffer size should be a
+ * power of 2 but also should be enough to store incompressible data
+ */
+
+ /* We're looking for nearest power of 2 buffer size, which is greater
+ * than input_size
+ */
+ uint32_t size =
+ !input_size ? MIN_COMPRESSED_BUF_SIZE : (input_size << 1);
+
+ for (i = UINT16_MAX + 1; !(i & size); i >>= 1)
+ ;
+
+ return i > ((UINT16_MAX + 1) >> 1)
+ ? (uint32_t)((float)input_size * EXPANSE_RATIO)
+ : i;
+}
+
+void
+comp_perf_free_memory(struct comp_test_data *test_data,
+ struct cperf_mem_resources *mem)
+{
+ uint32_t i;
+
+ if (mem->decomp_bufs != NULL)
+ for (i = 0; i < mem->total_bufs; i++)
+ rte_pktmbuf_free(mem->decomp_bufs[i]);
+
+ if (mem->comp_bufs != NULL)
+ for (i = 0; i < mem->total_bufs; i++)
+ rte_pktmbuf_free(mem->comp_bufs[i]);
+
+ rte_free(mem->decomp_bufs);
+ rte_free(mem->comp_bufs);
+ rte_free(mem->decompressed_data);
+ rte_free(mem->compressed_data);
+ rte_mempool_free(mem->op_pool);
+ rte_mempool_free(mem->decomp_buf_pool);
+ rte_mempool_free(mem->comp_buf_pool);
+
+ /* external mbuf support */
+ if (mem->decomp_memzones != NULL) {
+ for (i = 0; i < test_data->total_segs; i++)
+ rte_memzone_free(mem->decomp_memzones[i]);
+ rte_free(mem->decomp_memzones);
+ }
+ if (mem->comp_memzones != NULL) {
+ for (i = 0; i < test_data->total_segs; i++)
+ rte_memzone_free(mem->comp_memzones[i]);
+ rte_free(mem->comp_memzones);
+ }
+ rte_free(mem->decomp_buf_infos);
+ rte_free(mem->comp_buf_infos);
+}
+
+static void
+comp_perf_extbuf_free_cb(void *addr __rte_unused, void *opaque __rte_unused)
+{
+}
+
+static const struct rte_memzone *
+comp_perf_make_memzone(const char *name, struct cperf_mem_resources *mem,
+ unsigned int number, size_t size)
+{
+ unsigned int socket_id = rte_socket_id();
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+ const struct rte_memzone *memzone;
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "%s_s%u_d%u_q%u_%d", name,
+ socket_id, mem->dev_id, mem->qp_id, number);
+ memzone = rte_memzone_lookup(mz_name);
+ if (memzone != NULL && memzone->len != size) {
+ rte_memzone_free(memzone);
+ memzone = NULL;
+ }
+ if (memzone == NULL) {
+ memzone = rte_memzone_reserve_aligned(mz_name, size, socket_id,
+ RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE);
+ if (memzone == NULL)
+ RTE_LOG(ERR, USER1, "Can't allocate memory zone %s\n",
+ mz_name);
+ }
+ return memzone;
+}
+
+static int
+comp_perf_allocate_external_mbufs(struct comp_test_data *test_data,
+ struct cperf_mem_resources *mem)
+{
+ uint32_t i;
+
+ mem->comp_memzones = rte_zmalloc_socket(NULL,
+ test_data->total_segs * sizeof(struct rte_memzone *),
+ 0, rte_socket_id());
+
+ if (mem->comp_memzones == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the compression memzones could not be allocated\n");
+ return -1;
+ }
+
+ mem->decomp_memzones = rte_zmalloc_socket(NULL,
+ test_data->total_segs * sizeof(struct rte_memzone *),
+ 0, rte_socket_id());
+
+ if (mem->decomp_memzones == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the decompression memzones could not be allocated\n");
+ return -1;
+ }
+
+ mem->comp_buf_infos = rte_zmalloc_socket(NULL,
+ test_data->total_segs * sizeof(struct rte_mbuf_ext_shared_info),
+ 0, rte_socket_id());
+
+ if (mem->comp_buf_infos == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the compression buf infos could not be allocated\n");
+ return -1;
+ }
+
+ mem->decomp_buf_infos = rte_zmalloc_socket(NULL,
+ test_data->total_segs * sizeof(struct rte_mbuf_ext_shared_info),
+ 0, rte_socket_id());
+
+ if (mem->decomp_buf_infos == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the decompression buf infos could not be allocated\n");
+ return -1;
+ }
+
+ for (i = 0; i < test_data->total_segs; i++) {
+ mem->comp_memzones[i] = comp_perf_make_memzone("comp", mem,
+ i, test_data->out_seg_sz);
+ if (mem->comp_memzones[i] == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the compression memzone could not be allocated\n");
+ return -1;
+ }
+
+ mem->decomp_memzones[i] = comp_perf_make_memzone("decomp", mem,
+ i, test_data->seg_sz);
+ if (mem->decomp_memzones[i] == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Memory to hold the decompression memzone could not be allocated\n");
+ return -1;
+ }
+
+ mem->comp_buf_infos[i].free_cb =
+ comp_perf_extbuf_free_cb;
+ mem->comp_buf_infos[i].fcb_opaque = NULL;
+ rte_mbuf_ext_refcnt_set(&mem->comp_buf_infos[i], 1);
+
+ mem->decomp_buf_infos[i].free_cb =
+ comp_perf_extbuf_free_cb;
+ mem->decomp_buf_infos[i].fcb_opaque = NULL;
+ rte_mbuf_ext_refcnt_set(&mem->decomp_buf_infos[i], 1);
+ }
+
+ return 0;
+}
+
+int
+comp_perf_allocate_memory(struct comp_test_data *test_data,
+ struct cperf_mem_resources *mem)
+{
+ uint16_t comp_mbuf_size;
+ uint16_t decomp_mbuf_size;
+
+ test_data->out_seg_sz = find_buf_size(test_data->seg_sz);
+
+ /* Number of segments for input and output
+ * (compression and decompression)
+ */
+ test_data->total_segs = DIV_CEIL(test_data->input_data_sz,
+ test_data->seg_sz);
+
+ if (test_data->use_external_mbufs != 0) {
+ if (comp_perf_allocate_external_mbufs(test_data, mem) < 0)
+ return -1;
+ comp_mbuf_size = 0;
+ decomp_mbuf_size = 0;
+ } else {
+ comp_mbuf_size = test_data->out_seg_sz + RTE_PKTMBUF_HEADROOM;
+ decomp_mbuf_size = test_data->seg_sz + RTE_PKTMBUF_HEADROOM;
+ }
+
+ char pool_name[32] = "";
+
+ snprintf(pool_name, sizeof(pool_name), "comp_buf_pool_%u_qp_%u",
+ mem->dev_id, mem->qp_id);
+ mem->comp_buf_pool = rte_pktmbuf_pool_create(pool_name,
+ test_data->total_segs,
+ 0, 0,
+ comp_mbuf_size,
+ rte_socket_id());
+ if (mem->comp_buf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Mbuf mempool could not be created\n");
+ return -1;
+ }
+
+ snprintf(pool_name, sizeof(pool_name), "decomp_buf_pool_%u_qp_%u",
+ mem->dev_id, mem->qp_id);
+ mem->decomp_buf_pool = rte_pktmbuf_pool_create(pool_name,
+ test_data->total_segs,
+ 0, 0,
+ decomp_mbuf_size,
+ rte_socket_id());
+ if (mem->decomp_buf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Mbuf mempool could not be created\n");
+ return -1;
+ }
+
+ mem->total_bufs = DIV_CEIL(test_data->total_segs,
+ test_data->max_sgl_segs);
+
+ snprintf(pool_name, sizeof(pool_name), "op_pool_%u_qp_%u",
+ mem->dev_id, mem->qp_id);
+
+ /* one mempool for both src and dst mbufs */
+ mem->op_pool = rte_comp_op_pool_create(pool_name,
+ mem->total_bufs * 2,
+ 0, 0, rte_socket_id());
+ if (mem->op_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Comp op mempool could not be created\n");
+ return -1;
+ }
+
+ /*
+ * Compressed data might be a bit larger than input data,
+ * if data cannot be compressed
+ */
+ mem->compressed_data = rte_zmalloc_socket(NULL,
+ RTE_MAX(
+ (size_t) test_data->out_seg_sz *
+ test_data->total_segs,
+ (size_t) MIN_COMPRESSED_BUF_SIZE),
+ 0,
+ rte_socket_id());
+ if (mem->compressed_data == NULL) {
+ RTE_LOG(ERR, USER1, "Memory to hold the data from the input "
+ "file could not be allocated\n");
+ return -1;
+ }
+
+ mem->decompressed_data = rte_zmalloc_socket(NULL,
+ test_data->input_data_sz, 0,
+ rte_socket_id());
+ if (mem->decompressed_data == NULL) {
+ RTE_LOG(ERR, USER1, "Memory to hold the data from the input "
+ "file could not be allocated\n");
+ return -1;
+ }
+
+ mem->comp_bufs = rte_zmalloc_socket(NULL,
+ mem->total_bufs * sizeof(struct rte_mbuf *),
+ 0, rte_socket_id());
+ if (mem->comp_bufs == NULL) {
+ RTE_LOG(ERR, USER1, "Memory to hold the compression mbufs"
+ " could not be allocated\n");
+ return -1;
+ }
+
+ mem->decomp_bufs = rte_zmalloc_socket(NULL,
+ mem->total_bufs * sizeof(struct rte_mbuf *),
+ 0, rte_socket_id());
+ if (mem->decomp_bufs == NULL) {
+ RTE_LOG(ERR, USER1, "Memory to hold the decompression mbufs"
+ " could not be allocated\n");
+ return -1;
+ }
+
+ buffer_info.total_segments = test_data->total_segs;
+ buffer_info.segment_sz = test_data->seg_sz;
+ buffer_info.total_buffs = mem->total_bufs;
+ buffer_info.segments_per_buff = test_data->max_sgl_segs;
+ buffer_info.input_data_sz = test_data->input_data_sz;
+
+ return 0;
+}
+
+int
+prepare_bufs(struct comp_test_data *test_data, struct cperf_mem_resources *mem)
+{
+ uint32_t remaining_data = test_data->input_data_sz;
+ uint8_t *input_data_ptr = test_data->input_data;
+ size_t data_sz = 0;
+ uint8_t *data_addr;
+ uint32_t i, j;
+ uint16_t segs_per_mbuf = 0;
+ uint32_t cmz = 0;
+ uint32_t dmz = 0;
+
+ for (i = 0; i < mem->total_bufs; i++) {
+ /* Allocate data in input mbuf and copy data from input file */
+ mem->decomp_bufs[i] =
+ rte_pktmbuf_alloc(mem->decomp_buf_pool);
+ if (mem->decomp_bufs[i] == NULL) {
+ RTE_LOG(ERR, USER1, "Could not allocate mbuf\n");
+ return -1;
+ }
+
+ data_sz = RTE_MIN(remaining_data, test_data->seg_sz);
+
+ if (test_data->use_external_mbufs != 0) {
+ rte_pktmbuf_attach_extbuf(mem->decomp_bufs[i],
+ mem->decomp_memzones[dmz]->addr,
+ mem->decomp_memzones[dmz]->iova,
+ test_data->seg_sz,
+ &mem->decomp_buf_infos[dmz]);
+ dmz++;
+ }
+
+ data_addr = (uint8_t *) rte_pktmbuf_append(
+ mem->decomp_bufs[i], data_sz);
+ if (data_addr == NULL) {
+ RTE_LOG(ERR, USER1, "Could not append data\n");
+ return -1;
+ }
+ rte_memcpy(data_addr, input_data_ptr, data_sz);
+
+ input_data_ptr += data_sz;
+ remaining_data -= data_sz;
+
+ /* Already one segment in the mbuf */
+ segs_per_mbuf = 1;
+
+ /* Chain mbufs if needed for input mbufs */
+ while (segs_per_mbuf < test_data->max_sgl_segs
+ && remaining_data > 0) {
+ struct rte_mbuf *next_seg =
+ rte_pktmbuf_alloc(mem->decomp_buf_pool);
+
+ if (next_seg == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Could not allocate mbuf\n");
+ return -1;
+ }
+
+ data_sz = RTE_MIN(remaining_data, test_data->seg_sz);
+
+ if (test_data->use_external_mbufs != 0) {
+ rte_pktmbuf_attach_extbuf(
+ next_seg,
+ mem->decomp_memzones[dmz]->addr,
+ mem->decomp_memzones[dmz]->iova,
+ test_data->seg_sz,
+ &mem->decomp_buf_infos[dmz]);
+ dmz++;
+ }
+
+ data_addr = (uint8_t *)rte_pktmbuf_append(next_seg,
+ data_sz);
+
+ if (data_addr == NULL) {
+ RTE_LOG(ERR, USER1, "Could not append data\n");
+ return -1;
+ }
+
+ rte_memcpy(data_addr, input_data_ptr, data_sz);
+ input_data_ptr += data_sz;
+ remaining_data -= data_sz;
+
+ if (rte_pktmbuf_chain(mem->decomp_bufs[i],
+ next_seg) < 0) {
+ RTE_LOG(ERR, USER1, "Could not chain mbufs\n");
+ return -1;
+ }
+ segs_per_mbuf++;
+ }
+
+ /* Allocate data in output mbuf */
+ mem->comp_bufs[i] =
+ rte_pktmbuf_alloc(mem->comp_buf_pool);
+ if (mem->comp_bufs[i] == NULL) {
+ RTE_LOG(ERR, USER1, "Could not allocate mbuf\n");
+ return -1;
+ }
+
+ if (test_data->use_external_mbufs != 0) {
+ rte_pktmbuf_attach_extbuf(mem->comp_bufs[i],
+ mem->comp_memzones[cmz]->addr,
+ mem->comp_memzones[cmz]->iova,
+ test_data->out_seg_sz,
+ &mem->comp_buf_infos[cmz]);
+ cmz++;
+ }
+
+ data_addr = (uint8_t *) rte_pktmbuf_append(
+ mem->comp_bufs[i],
+ test_data->out_seg_sz);
+ if (data_addr == NULL) {
+ RTE_LOG(ERR, USER1, "Could not append data\n");
+ return -1;
+ }
+
+ /* Chain mbufs if needed for output mbufs */
+ for (j = 1; j < segs_per_mbuf; j++) {
+ struct rte_mbuf *next_seg =
+ rte_pktmbuf_alloc(mem->comp_buf_pool);
+
+ if (next_seg == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Could not allocate mbuf\n");
+ return -1;
+ }
+
+ if (test_data->use_external_mbufs != 0) {
+ rte_pktmbuf_attach_extbuf(
+ next_seg,
+ mem->comp_memzones[cmz]->addr,
+ mem->comp_memzones[cmz]->iova,
+ test_data->out_seg_sz,
+ &mem->comp_buf_infos[cmz]);
+ cmz++;
+ }
+
+ data_addr = (uint8_t *)rte_pktmbuf_append(next_seg,
+ test_data->out_seg_sz);
+ if (data_addr == NULL) {
+ RTE_LOG(ERR, USER1, "Could not append data\n");
+ return -1;
+ }
+
+ if (rte_pktmbuf_chain(mem->comp_bufs[i],
+ next_seg) < 0) {
+ RTE_LOG(ERR, USER1, "Could not chain mbufs\n");
+ return -1;
+ }
+ }
+ }
+
+ buffer_info.segments_per_last_buff = segs_per_mbuf;
+ buffer_info.last_segment_sz = data_sz;
+
+ return 0;
+}
+
+void
+print_test_dynamics(const struct comp_test_data *test_data)
+{
+ uint32_t opt_total_segs = DIV_CEIL(buffer_info.input_data_sz,
+ MAX_SEG_SIZE);
+
+ if (buffer_info.total_buffs > 1) {
+ if (test_data->test == CPERF_TEST_TYPE_THROUGHPUT) {
+ printf("\nWarning: for the current input parameters, number"
+ " of ops is higher than one, which may result"
+ " in sub-optimal performance.\n");
+ printf("To improve the performance (for the current"
+ " input data) following parameters are"
+ " suggested:\n");
+ printf(" * Segment size: %d\n",
+ MAX_SEG_SIZE);
+ printf(" * Number of segments: %u\n",
+ opt_total_segs);
+ }
+ } else if (buffer_info.total_buffs == 1) {
+ printf("\nInfo: there is only one op with %u segments -"
+ " the compression ratio is the best.\n",
+ buffer_info.segments_per_last_buff);
+ if (buffer_info.segment_sz < MAX_SEG_SIZE)
+ printf("To reduce compression time, please use"
+ " bigger segment size: %d.\n",
+ MAX_SEG_SIZE);
+ else if (buffer_info.segment_sz == MAX_SEG_SIZE)
+ printf("Segment size is optimal for the best"
+ " performance.\n");
+ } else
+ printf("Warning: something wrong happened!!\n");
+
+ printf("\nFor the current input parameters (segment size = %u,"
+ " maximum segments per SGL = %u):\n",
+ buffer_info.segment_sz,
+ buffer_info.segments_per_buff);
+ printf(" * Total number of buffers: %d\n",
+ buffer_info.total_segments);
+ printf(" * %u buffer(s) %u bytes long, last buffer %u"
+ " byte(s) long\n",
+ buffer_info.total_segments - 1,
+ buffer_info.segment_sz,
+ buffer_info.last_segment_sz);
+ printf(" * Number of ops: %u\n", buffer_info.total_buffs);
+ printf(" * Total memory allocation: %u\n",
+ (buffer_info.total_segments - 1) * buffer_info.segment_sz
+ + buffer_info.last_segment_sz);
+ if (buffer_info.total_buffs > 1)
+ printf(" * %u ops: %u segment(s) in each,"
+ " segment size %u\n",
+ buffer_info.total_buffs - 1,
+ buffer_info.segments_per_buff,
+ buffer_info.segment_sz);
+ if (buffer_info.segments_per_last_buff > 1) {
+ printf(" * 1 op %u segments:\n",
+ buffer_info.segments_per_last_buff);
+ printf(" o %u segment size %u\n",
+ buffer_info.segments_per_last_buff - 1,
+ buffer_info.segment_sz);
+ printf(" o last segment size %u\n",
+ buffer_info.last_segment_sz);
+ } else if (buffer_info.segments_per_last_buff == 1) {
+ printf(" * 1 op (the last one): %u segment %u"
+ " byte(s) long\n\n",
+ buffer_info.segments_per_last_buff,
+ buffer_info.last_segment_sz);
+ }
+ printf("\n");
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.h
new file mode 100644
index 000000000..72705c6a2
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_common.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_TEST_COMMON_H_
+#define _COMP_PERF_TEST_COMMON_H_
+
+#include <stdint.h>
+
+#include <rte_mempool.h>
+
+struct cperf_mem_resources {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ rte_atomic16_t print_info_once;
+
+ uint32_t total_bufs;
+ uint8_t *compressed_data;
+ uint8_t *decompressed_data;
+
+ struct rte_mbuf **comp_bufs;
+ struct rte_mbuf **decomp_bufs;
+
+ struct rte_mempool *comp_buf_pool;
+ struct rte_mempool *decomp_buf_pool;
+ struct rte_mempool *op_pool;
+
+ /* external mbuf support */
+ const struct rte_memzone **comp_memzones;
+ const struct rte_memzone **decomp_memzones;
+ struct rte_mbuf_ext_shared_info *comp_buf_infos;
+ struct rte_mbuf_ext_shared_info *decomp_buf_infos;
+};
+
+int
+param_range_check(uint16_t size, const struct rte_param_log2_range *range);
+
+void
+comp_perf_free_memory(struct comp_test_data *test_data,
+ struct cperf_mem_resources *mem);
+
+int
+comp_perf_allocate_memory(struct comp_test_data *test_data,
+ struct cperf_mem_resources *mem);
+
+int
+prepare_bufs(struct comp_test_data *test_data, struct cperf_mem_resources *mem);
+
+void
+print_test_dynamics(const struct comp_test_data *test_data);
+
+#endif /* _COMP_PERF_TEST_COMMON_H_ */
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.c b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.c
new file mode 100644
index 000000000..55559a7d5
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.c
@@ -0,0 +1,614 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include "rte_spinlock.h"
+#include <rte_compressdev.h>
+
+#include "comp_perf_test_cyclecount.h"
+
+struct cperf_cyclecount_ctx {
+ struct cperf_verify_ctx ver;
+
+ uint32_t ops_enq_retries;
+ uint32_t ops_deq_retries;
+
+ uint64_t duration_op;
+ uint64_t duration_enq;
+ uint64_t duration_deq;
+};
+
+void
+cperf_cyclecount_test_destructor(void *arg)
+{
+ struct cperf_cyclecount_ctx *ctx = arg;
+
+ if (arg) {
+ comp_perf_free_memory(ctx->ver.options, &ctx->ver.mem);
+ rte_free(arg);
+ }
+}
+
+void *
+cperf_cyclecount_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options)
+{
+ struct cperf_cyclecount_ctx *ctx = NULL;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_cyclecount_ctx), 0);
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->ver.mem.dev_id = dev_id;
+ ctx->ver.mem.qp_id = qp_id;
+ ctx->ver.options = options;
+ ctx->ver.silent = 1; /* ver. part will be silent */
+
+ if (!comp_perf_allocate_memory(ctx->ver.options, &ctx->ver.mem)
+ && !prepare_bufs(ctx->ver.options, &ctx->ver.mem))
+ return ctx;
+
+ cperf_cyclecount_test_destructor(ctx);
+ return NULL;
+}
+
+static int
+cperf_cyclecount_op_setup(struct rte_comp_op **ops,
+ struct cperf_cyclecount_ctx *ctx,
+ struct rte_mbuf **input_bufs,
+ struct rte_mbuf **output_bufs,
+ void *priv_xform,
+ uint32_t out_seg_sz)
+{
+ struct comp_test_data *test_data = ctx->ver.options;
+ struct cperf_mem_resources *mem = &ctx->ver.mem;
+
+ uint32_t i, iter, num_iter;
+ int res = 0;
+ uint16_t ops_needed;
+
+ num_iter = test_data->num_iter;
+
+ for (iter = 0; iter < num_iter; iter++) {
+ uint32_t remaining_ops = mem->total_bufs;
+ uint32_t total_deq_ops = 0;
+ uint32_t total_enq_ops = 0;
+ uint16_t num_enq = 0;
+ uint16_t num_deq = 0;
+
+ while (remaining_ops > 0) {
+ uint16_t num_ops = RTE_MIN(remaining_ops,
+ test_data->burst_sz);
+ ops_needed = num_ops;
+
+ /* Allocate compression operations */
+ if (ops_needed && rte_mempool_get_bulk(
+ mem->op_pool,
+ (void **)ops,
+ ops_needed) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Cyclecount: could not allocate enough operations\n");
+ res = -1;
+ goto end;
+ }
+
+ for (i = 0; i < ops_needed; i++) {
+
+ /* Calculate next buffer to attach */
+ /* to operation */
+ uint32_t buf_id = total_enq_ops + i;
+ uint16_t op_id = i;
+
+ /* Reset all data in output buffers */
+ struct rte_mbuf *m = output_bufs[buf_id];
+
+ m->pkt_len = out_seg_sz * m->nb_segs;
+ while (m) {
+ m->data_len = m->buf_len - m->data_off;
+ m = m->next;
+ }
+ ops[op_id]->m_src = input_bufs[buf_id];
+ ops[op_id]->m_dst = output_bufs[buf_id];
+ ops[op_id]->src.offset = 0;
+ ops[op_id]->src.length =
+ rte_pktmbuf_pkt_len(input_bufs[buf_id]);
+ ops[op_id]->dst.offset = 0;
+ ops[op_id]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ ops[op_id]->input_chksum = buf_id;
+ ops[op_id]->private_xform = priv_xform;
+ }
+
+ /* E N Q U E U I N G */
+ /* assuming that all ops are enqueued */
+ /* instead of the real enqueue operation */
+ num_enq = num_ops;
+
+ remaining_ops -= num_enq;
+ total_enq_ops += num_enq;
+
+ /* D E Q U E U I N G */
+ /* assuming that all ops dequeued */
+ /* instead of the real dequeue operation */
+ num_deq = num_ops;
+
+ total_deq_ops += num_deq;
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)ops, num_deq);
+ }
+ }
+ return res;
+end:
+ rte_mempool_put_bulk(mem->op_pool, (void **)ops, ops_needed);
+ rte_free(ops);
+
+ return res;
+}
+
+static int
+main_loop(struct cperf_cyclecount_ctx *ctx, enum rte_comp_xform_type type)
+{
+ struct comp_test_data *test_data = ctx->ver.options;
+ struct cperf_mem_resources *mem = &ctx->ver.mem;
+ uint8_t dev_id = mem->dev_id;
+ uint32_t i, iter, num_iter;
+ struct rte_comp_op **ops, **deq_ops;
+ void *priv_xform = NULL;
+ struct rte_comp_xform xform;
+ struct rte_mbuf **input_bufs, **output_bufs;
+ int ret, res = 0;
+ int allocated = 0;
+ uint32_t out_seg_sz;
+
+ uint64_t tsc_start, tsc_end, tsc_duration;
+
+ if (test_data == NULL || !test_data->burst_sz) {
+ RTE_LOG(ERR, USER1, "Unknown burst size\n");
+ return -1;
+ }
+ ctx->duration_enq = 0;
+ ctx->duration_deq = 0;
+ ctx->ops_enq_retries = 0;
+ ctx->ops_deq_retries = 0;
+
+ /* one array for both enqueue and dequeue */
+ ops = rte_zmalloc_socket(NULL,
+ 2 * mem->total_bufs * sizeof(struct rte_comp_op *),
+ 0, rte_socket_id());
+
+ if (ops == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate memory for ops strucures\n");
+ return -1;
+ }
+
+ deq_ops = &ops[mem->total_bufs];
+
+ if (type == RTE_COMP_COMPRESS) {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_COMPRESS,
+ .compress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .deflate.huffman = test_data->huffman_enc,
+ .level = test_data->level,
+ .window_size = test_data->window_sz,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ input_bufs = mem->decomp_bufs;
+ output_bufs = mem->comp_bufs;
+ out_seg_sz = test_data->out_seg_sz;
+ } else {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_DECOMPRESS,
+ .decompress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .window_size = test_data->window_sz,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ input_bufs = mem->comp_bufs;
+ output_bufs = mem->decomp_bufs;
+ out_seg_sz = test_data->seg_sz;
+ }
+
+ /* Create private xform */
+ if (rte_compressdev_private_xform_create(dev_id, &xform,
+ &priv_xform) < 0) {
+ RTE_LOG(ERR, USER1, "Private xform could not be created\n");
+ res = -1;
+ goto end;
+ }
+
+ tsc_start = rte_rdtsc_precise();
+ ret = cperf_cyclecount_op_setup(ops,
+ ctx,
+ input_bufs,
+ output_bufs,
+ priv_xform,
+ out_seg_sz);
+
+ tsc_end = rte_rdtsc_precise();
+
+ /* ret value check postponed a bit to cancel extra 'if' bias */
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "Setup function failed\n");
+ res = -1;
+ goto end;
+ }
+
+ tsc_duration = tsc_end - tsc_start;
+ ctx->duration_op = tsc_duration;
+
+ num_iter = test_data->num_iter;
+ for (iter = 0; iter < num_iter; iter++) {
+ uint32_t total_ops = mem->total_bufs;
+ uint32_t remaining_ops = mem->total_bufs;
+ uint32_t total_deq_ops = 0;
+ uint32_t total_enq_ops = 0;
+ uint16_t ops_unused = 0;
+ uint16_t num_enq = 0;
+ uint16_t num_deq = 0;
+
+ while (remaining_ops > 0) {
+ uint16_t num_ops = RTE_MIN(remaining_ops,
+ test_data->burst_sz);
+ uint16_t ops_needed = num_ops - ops_unused;
+
+ /*
+ * Move the unused operations from the previous
+ * enqueue_burst call to the front, to maintain order
+ */
+ if ((ops_unused > 0) && (num_enq > 0)) {
+ size_t nb_b_to_mov =
+ ops_unused * sizeof(struct rte_comp_op *);
+
+ memmove(ops, &ops[num_enq], nb_b_to_mov);
+ }
+
+ /* Allocate compression operations */
+ if (ops_needed && rte_mempool_get_bulk(
+ mem->op_pool,
+ (void **)ops,
+ ops_needed) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Could not allocate enough operations\n");
+ res = -1;
+ goto end;
+ }
+ allocated += ops_needed;
+
+ for (i = 0; i < ops_needed; i++) {
+ /*
+ * Calculate next buffer to attach to operation
+ */
+ uint32_t buf_id = total_enq_ops + i +
+ ops_unused;
+ uint16_t op_id = ops_unused + i;
+ /* Reset all data in output buffers */
+ struct rte_mbuf *m = output_bufs[buf_id];
+
+ m->pkt_len = out_seg_sz * m->nb_segs;
+ while (m) {
+ m->data_len = m->buf_len - m->data_off;
+ m = m->next;
+ }
+ ops[op_id]->m_src = input_bufs[buf_id];
+ ops[op_id]->m_dst = output_bufs[buf_id];
+ ops[op_id]->src.offset = 0;
+ ops[op_id]->src.length =
+ rte_pktmbuf_pkt_len(input_bufs[buf_id]);
+ ops[op_id]->dst.offset = 0;
+ ops[op_id]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ ops[op_id]->input_chksum = buf_id;
+ ops[op_id]->private_xform = priv_xform;
+ }
+
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ tsc_start = rte_rdtsc_precise();
+ num_enq = rte_compressdev_enqueue_burst(dev_id,
+ mem->qp_id, ops,
+ num_ops);
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = tsc_end - tsc_start;
+ ctx->duration_enq += tsc_duration;
+
+ if (num_enq < num_ops)
+ ctx->ops_enq_retries++;
+
+ if (test_data->cyclecount_delay)
+ rte_delay_us_block(test_data->cyclecount_delay);
+
+ if (num_enq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.enqueue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+
+ ops_unused = num_ops - num_enq;
+ remaining_ops -= num_enq;
+ total_enq_ops += num_enq;
+
+ tsc_start = rte_rdtsc_precise();
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ allocated);
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = tsc_end - tsc_start;
+ ctx->duration_deq += tsc_duration;
+
+ if (num_deq < allocated)
+ ctx->ops_deq_retries++;
+
+ total_deq_ops += num_deq;
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1, "Some operations were not successful\n");
+ goto end;
+ }
+
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+
+ /* Dequeue the last operations */
+ while (total_deq_ops < total_ops) {
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ tsc_start = rte_rdtsc_precise();
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ test_data->burst_sz);
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = tsc_end - tsc_start;
+ ctx->duration_deq += tsc_duration;
+ ctx->ops_deq_retries++;
+
+ if (num_deq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.dequeue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+ total_deq_ops += num_deq;
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1, "Some operations were not successful\n");
+ goto end;
+ }
+
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+ }
+ allocated = 0;
+
+end:
+ if (allocated)
+ rte_mempool_put_bulk(mem->op_pool, (void **)ops, allocated);
+ rte_compressdev_private_xform_free(dev_id, priv_xform);
+ rte_free(ops);
+
+ if (test_data->perf_comp_force_stop) {
+ RTE_LOG(ERR, USER1,
+ "lcore: %d Perf. test has been aborted by user\n",
+ mem->lcore_id);
+ res = -1;
+ }
+ return res;
+}
+
+int
+cperf_cyclecount_test_runner(void *test_ctx)
+{
+ struct cperf_cyclecount_ctx *ctx = test_ctx;
+ struct comp_test_data *test_data = ctx->ver.options;
+ uint32_t lcore = rte_lcore_id();
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+ static rte_spinlock_t print_spinlock;
+ int i;
+
+ uint32_t ops_enq_retries_comp;
+ uint32_t ops_deq_retries_comp;
+
+ uint32_t ops_enq_retries_decomp;
+ uint32_t ops_deq_retries_decomp;
+
+ uint32_t duration_setup_per_op;
+
+ uint32_t duration_enq_per_op_comp;
+ uint32_t duration_deq_per_op_comp;
+
+ uint32_t duration_enq_per_op_decomp;
+ uint32_t duration_deq_per_op_decomp;
+
+ ctx->ver.mem.lcore_id = lcore;
+
+ /*
+ * printing information about current compression thread
+ */
+ if (rte_atomic16_test_and_set(&ctx->ver.mem.print_info_once))
+ printf(" lcore: %u,"
+ " driver name: %s,"
+ " device name: %s,"
+ " device id: %u,"
+ " socket id: %u,"
+ " queue pair id: %u\n",
+ lcore,
+ ctx->ver.options->driver_name,
+ rte_compressdev_name_get(ctx->ver.mem.dev_id),
+ ctx->ver.mem.dev_id,
+ rte_compressdev_socket_id(ctx->ver.mem.dev_id),
+ ctx->ver.mem.qp_id);
+
+ /*
+ * First the verification part is needed
+ */
+ if (cperf_verify_test_runner(&ctx->ver))
+ return EXIT_FAILURE;
+
+ /*
+ * Run the tests twice, discarding the first performance
+ * results, before the cache is warmed up
+ */
+
+ /* C O M P R E S S */
+ for (i = 0; i < 2; i++) {
+ if (main_loop(ctx, RTE_COMP_COMPRESS) < 0)
+ return EXIT_FAILURE;
+ }
+
+ ops_enq_retries_comp = ctx->ops_enq_retries;
+ ops_deq_retries_comp = ctx->ops_deq_retries;
+
+ duration_enq_per_op_comp = ctx->duration_enq /
+ (ctx->ver.mem.total_bufs * test_data->num_iter);
+ duration_deq_per_op_comp = ctx->duration_deq /
+ (ctx->ver.mem.total_bufs * test_data->num_iter);
+
+ /* D E C O M P R E S S */
+ for (i = 0; i < 2; i++) {
+ if (main_loop(ctx, RTE_COMP_DECOMPRESS) < 0)
+ return EXIT_FAILURE;
+ }
+
+ ops_enq_retries_decomp = ctx->ops_enq_retries;
+ ops_deq_retries_decomp = ctx->ops_deq_retries;
+
+ duration_enq_per_op_decomp = ctx->duration_enq /
+ (ctx->ver.mem.total_bufs * test_data->num_iter);
+ duration_deq_per_op_decomp = ctx->duration_deq /
+ (ctx->ver.mem.total_bufs * test_data->num_iter);
+
+ duration_setup_per_op = ctx->duration_op /
+ (ctx->ver.mem.total_bufs * test_data->num_iter);
+
+ /* R E P O R T processing */
+ if (rte_atomic16_test_and_set(&display_once)) {
+
+ rte_spinlock_lock(&print_spinlock);
+
+ printf("\nLegend for the table\n"
+ " - Retries section: number of retries for the following operations:\n"
+ " [C-e] - compression enqueue\n"
+ " [C-d] - compression dequeue\n"
+ " [D-e] - decompression enqueue\n"
+ " [D-d] - decompression dequeue\n"
+ " - Cycles section: number of cycles per 'op' for the following operations:\n"
+ " setup/op - memory allocation, op configuration and memory dealocation\n"
+ " [C-e] - compression enqueue\n"
+ " [C-d] - compression dequeue\n"
+ " [D-e] - decompression enqueue\n"
+ " [D-d] - decompression dequeue\n\n");
+
+ printf("\n%12s%6s%12s%17s",
+ "lcore id", "Level", "Comp size", "Comp ratio [%]");
+
+ printf(" |%10s %6s %8s %6s %8s",
+ " Retries:",
+ "[C-e]", "[C-d]",
+ "[D-e]", "[D-d]");
+
+ printf(" |%9s %9s %9s %9s %9s %9s\n",
+ " Cycles:",
+ "setup/op",
+ "[C-e]", "[C-d]",
+ "[D-e]", "[D-d]");
+
+ rte_spinlock_unlock(&print_spinlock);
+ }
+
+ rte_spinlock_lock(&print_spinlock);
+
+ printf("%12u"
+ "%6u"
+ "%12zu"
+ "%17.2f",
+ ctx->ver.mem.lcore_id,
+ test_data->level,
+ ctx->ver.comp_data_sz,
+ ctx->ver.ratio);
+
+ printf(" |%10s %6u %8u %6u %8u",
+ " ",
+ ops_enq_retries_comp,
+ ops_deq_retries_comp,
+ ops_enq_retries_decomp,
+ ops_deq_retries_decomp);
+
+ printf(" |%9s %9u %9u %9u %9u %9u\n",
+ " ",
+ duration_setup_per_op,
+ duration_enq_per_op_comp,
+ duration_deq_per_op_comp,
+ duration_enq_per_op_decomp,
+ duration_deq_per_op_decomp);
+
+ rte_spinlock_unlock(&print_spinlock);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.h
new file mode 100644
index 000000000..8e1b4d9e9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_cyclecount.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_TEST_CYCLECOUNT_
+#define _COMP_PERF_TEST_CYCLECOUNT_
+
+#include <stdint.h>
+
+#include "comp_perf_options.h"
+#include "comp_perf_test_common.h"
+#include "comp_perf_test_verify.h"
+
+void
+cperf_cyclecount_test_destructor(void *arg);
+
+int
+cperf_cyclecount_test_runner(void *test_ctx);
+
+void *
+cperf_cyclecount_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.c b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.c
new file mode 100644
index 000000000..13922b658
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.c
@@ -0,0 +1,408 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_cycles.h>
+#include <rte_compressdev.h>
+
+#include "comp_perf_test_throughput.h"
+
+void
+cperf_throughput_test_destructor(void *arg)
+{
+ if (arg) {
+ comp_perf_free_memory(
+ ((struct cperf_benchmark_ctx *)arg)->ver.options,
+ &((struct cperf_benchmark_ctx *)arg)->ver.mem);
+ rte_free(arg);
+ }
+}
+
+void *
+cperf_throughput_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options)
+{
+ struct cperf_benchmark_ctx *ctx = NULL;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_benchmark_ctx), 0);
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->ver.mem.dev_id = dev_id;
+ ctx->ver.mem.qp_id = qp_id;
+ ctx->ver.options = options;
+ ctx->ver.silent = 1; /* ver. part will be silent */
+
+ if (!comp_perf_allocate_memory(ctx->ver.options, &ctx->ver.mem)
+ && !prepare_bufs(ctx->ver.options, &ctx->ver.mem))
+ return ctx;
+
+ cperf_throughput_test_destructor(ctx);
+ return NULL;
+}
+
+static int
+main_loop(struct cperf_benchmark_ctx *ctx, enum rte_comp_xform_type type)
+{
+ struct comp_test_data *test_data = ctx->ver.options;
+ struct cperf_mem_resources *mem = &ctx->ver.mem;
+ uint8_t dev_id = mem->dev_id;
+ uint32_t i, iter, num_iter;
+ struct rte_comp_op **ops, **deq_ops;
+ void *priv_xform = NULL;
+ struct rte_comp_xform xform;
+ struct rte_mbuf **input_bufs, **output_bufs;
+ int res = 0;
+ int allocated = 0;
+ uint32_t out_seg_sz;
+
+ if (test_data == NULL || !test_data->burst_sz) {
+ RTE_LOG(ERR, USER1,
+ "Unknown burst size\n");
+ return -1;
+ }
+
+ ops = rte_zmalloc_socket(NULL,
+ 2 * mem->total_bufs * sizeof(struct rte_comp_op *),
+ 0, rte_socket_id());
+
+ if (ops == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate memory for ops strucures\n");
+ return -1;
+ }
+
+ deq_ops = &ops[mem->total_bufs];
+
+ if (type == RTE_COMP_COMPRESS) {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_COMPRESS,
+ .compress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .deflate.huffman = test_data->huffman_enc,
+ .level = test_data->level,
+ .window_size = test_data->window_sz,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ input_bufs = mem->decomp_bufs;
+ output_bufs = mem->comp_bufs;
+ out_seg_sz = test_data->out_seg_sz;
+ } else {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_DECOMPRESS,
+ .decompress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .window_size = test_data->window_sz,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ input_bufs = mem->comp_bufs;
+ output_bufs = mem->decomp_bufs;
+ out_seg_sz = test_data->seg_sz;
+ }
+
+ /* Create private xform */
+ if (rte_compressdev_private_xform_create(dev_id, &xform,
+ &priv_xform) < 0) {
+ RTE_LOG(ERR, USER1, "Private xform could not be created\n");
+ res = -1;
+ goto end;
+ }
+
+ uint64_t tsc_start, tsc_end, tsc_duration;
+
+ num_iter = test_data->num_iter;
+ tsc_start = tsc_end = tsc_duration = 0;
+ tsc_start = rte_rdtsc_precise();
+
+ for (iter = 0; iter < num_iter; iter++) {
+ uint32_t total_ops = mem->total_bufs;
+ uint32_t remaining_ops = mem->total_bufs;
+ uint32_t total_deq_ops = 0;
+ uint32_t total_enq_ops = 0;
+ uint16_t ops_unused = 0;
+ uint16_t num_enq = 0;
+ uint16_t num_deq = 0;
+
+ while (remaining_ops > 0) {
+ uint16_t num_ops = RTE_MIN(remaining_ops,
+ test_data->burst_sz);
+ uint16_t ops_needed = num_ops - ops_unused;
+
+ /*
+ * Move the unused operations from the previous
+ * enqueue_burst call to the front, to maintain order
+ */
+ if ((ops_unused > 0) && (num_enq > 0)) {
+ size_t nb_b_to_mov =
+ ops_unused * sizeof(struct rte_comp_op *);
+
+ memmove(ops, &ops[num_enq], nb_b_to_mov);
+ }
+
+ /* Allocate compression operations */
+ if (ops_needed && !rte_comp_op_bulk_alloc(
+ mem->op_pool,
+ &ops[ops_unused],
+ ops_needed)) {
+ RTE_LOG(ERR, USER1,
+ "Could not allocate enough operations\n");
+ res = -1;
+ goto end;
+ }
+ allocated += ops_needed;
+
+ for (i = 0; i < ops_needed; i++) {
+ /*
+ * Calculate next buffer to attach to operation
+ */
+ uint32_t buf_id = total_enq_ops + i +
+ ops_unused;
+ uint16_t op_id = ops_unused + i;
+ /* Reset all data in output buffers */
+ struct rte_mbuf *m = output_bufs[buf_id];
+
+ m->pkt_len = out_seg_sz * m->nb_segs;
+ while (m) {
+ m->data_len = m->buf_len - m->data_off;
+ m = m->next;
+ }
+ ops[op_id]->m_src = input_bufs[buf_id];
+ ops[op_id]->m_dst = output_bufs[buf_id];
+ ops[op_id]->src.offset = 0;
+ ops[op_id]->src.length =
+ rte_pktmbuf_pkt_len(input_bufs[buf_id]);
+ ops[op_id]->dst.offset = 0;
+ ops[op_id]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ ops[op_id]->input_chksum = buf_id;
+ ops[op_id]->private_xform = priv_xform;
+ }
+
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ num_enq = rte_compressdev_enqueue_burst(dev_id,
+ mem->qp_id, ops,
+ num_ops);
+ if (num_enq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.enqueue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+
+ ops_unused = num_ops - num_enq;
+ remaining_ops -= num_enq;
+ total_enq_ops += num_enq;
+
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ test_data->burst_sz);
+ total_deq_ops += num_deq;
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Some operations were not successful\n");
+ goto end;
+ }
+
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+
+ /* Dequeue the last operations */
+ while (total_deq_ops < total_ops) {
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ test_data->burst_sz);
+ if (num_deq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.dequeue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+
+ total_deq_ops += num_deq;
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Some operations were not successful\n");
+ goto end;
+ }
+
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+ }
+
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = tsc_end - tsc_start;
+
+ if (type == RTE_COMP_COMPRESS)
+ ctx->comp_tsc_duration[test_data->level] =
+ tsc_duration / num_iter;
+ else
+ ctx->decomp_tsc_duration[test_data->level] =
+ tsc_duration / num_iter;
+
+end:
+ rte_mempool_put_bulk(mem->op_pool, (void **)ops, allocated);
+ rte_compressdev_private_xform_free(dev_id, priv_xform);
+ rte_free(ops);
+
+ if (test_data->perf_comp_force_stop) {
+ RTE_LOG(ERR, USER1,
+ "lcore: %d Perf. test has been aborted by user\n",
+ mem->lcore_id);
+ res = -1;
+ }
+ return res;
+}
+
+int
+cperf_throughput_test_runner(void *test_ctx)
+{
+ struct cperf_benchmark_ctx *ctx = test_ctx;
+ struct comp_test_data *test_data = ctx->ver.options;
+ uint32_t lcore = rte_lcore_id();
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+ int i, ret = EXIT_SUCCESS;
+
+ ctx->ver.mem.lcore_id = lcore;
+
+ /*
+ * printing information about current compression thread
+ */
+ if (rte_atomic16_test_and_set(&ctx->ver.mem.print_info_once))
+ printf(" lcore: %u,"
+ " driver name: %s,"
+ " device name: %s,"
+ " device id: %u,"
+ " socket id: %u,"
+ " queue pair id: %u\n",
+ lcore,
+ ctx->ver.options->driver_name,
+ rte_compressdev_name_get(ctx->ver.mem.dev_id),
+ ctx->ver.mem.dev_id,
+ rte_compressdev_socket_id(ctx->ver.mem.dev_id),
+ ctx->ver.mem.qp_id);
+
+ /*
+ * First the verification part is needed
+ */
+ if (cperf_verify_test_runner(&ctx->ver)) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ /*
+ * Run the tests twice, discarding the first performance
+ * results, before the cache is warmed up
+ */
+ for (i = 0; i < 2; i++) {
+ if (main_loop(ctx, RTE_COMP_COMPRESS) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (main_loop(ctx, RTE_COMP_DECOMPRESS) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+ }
+
+ ctx->comp_tsc_byte =
+ (double)(ctx->comp_tsc_duration[test_data->level]) /
+ test_data->input_data_sz;
+
+ ctx->decomp_tsc_byte =
+ (double)(ctx->decomp_tsc_duration[test_data->level]) /
+ test_data->input_data_sz;
+
+ ctx->comp_gbps = rte_get_tsc_hz() / ctx->comp_tsc_byte * 8 /
+ 1000000000;
+
+ ctx->decomp_gbps = rte_get_tsc_hz() / ctx->decomp_tsc_byte * 8 /
+ 1000000000;
+
+ if (rte_atomic16_test_and_set(&display_once)) {
+ printf("\n%12s%6s%12s%17s%15s%16s\n",
+ "lcore id", "Level", "Comp size", "Comp ratio [%]",
+ "Comp [Gbps]", "Decomp [Gbps]");
+ }
+
+ printf("%12u%6u%12zu%17.2f%15.2f%16.2f\n",
+ ctx->ver.mem.lcore_id,
+ test_data->level, ctx->ver.comp_data_sz, ctx->ver.ratio,
+ ctx->comp_gbps,
+ ctx->decomp_gbps);
+
+end:
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.h
new file mode 100644
index 000000000..467e3aa78
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_throughput.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_TEST_BENCHMARK_
+#define _COMP_PERF_TEST_BENCHMARK_
+
+#include <stdint.h>
+
+#include "comp_perf_options.h"
+#include "comp_perf_test_common.h"
+#include "comp_perf_test_verify.h"
+
+struct cperf_benchmark_ctx {
+ struct cperf_verify_ctx ver;
+
+ /* Store TSC duration for all levels (including level 0) */
+ uint64_t comp_tsc_duration[RTE_COMP_LEVEL_MAX + 1];
+ uint64_t decomp_tsc_duration[RTE_COMP_LEVEL_MAX + 1];
+ double comp_gbps;
+ double decomp_gbps;
+ double comp_tsc_byte;
+ double decomp_tsc_byte;
+};
+
+void
+cperf_throughput_test_destructor(void *arg);
+
+int
+cperf_throughput_test_runner(void *test_ctx);
+
+void *
+cperf_throughput_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.c b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.c
new file mode 100644
index 000000000..5e13257b7
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.c
@@ -0,0 +1,442 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_compressdev.h>
+
+#include "comp_perf_test_verify.h"
+#include "comp_perf_test_common.h"
+
+void
+cperf_verify_test_destructor(void *arg)
+{
+ if (arg) {
+ comp_perf_free_memory(
+ ((struct cperf_verify_ctx *)arg)->options,
+ &((struct cperf_verify_ctx *)arg)->mem);
+ rte_free(arg);
+ }
+}
+
+void *
+cperf_verify_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options)
+{
+ struct cperf_verify_ctx *ctx = NULL;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_verify_ctx), 0);
+
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->mem.dev_id = dev_id;
+ ctx->mem.qp_id = qp_id;
+ ctx->options = options;
+
+ if (!comp_perf_allocate_memory(ctx->options, &ctx->mem) &&
+ !prepare_bufs(ctx->options, &ctx->mem))
+ return ctx;
+
+ cperf_verify_test_destructor(ctx);
+ return NULL;
+}
+
+static int
+main_loop(struct cperf_verify_ctx *ctx, enum rte_comp_xform_type type)
+{
+ struct comp_test_data *test_data = ctx->options;
+ uint8_t *output_data_ptr = NULL;
+ size_t *output_data_sz = NULL;
+ struct cperf_mem_resources *mem = &ctx->mem;
+
+ uint8_t dev_id = mem->dev_id;
+ uint32_t i, iter, num_iter;
+ struct rte_comp_op **ops, **deq_ops;
+ void *priv_xform = NULL;
+ struct rte_comp_xform xform;
+ size_t output_size = 0;
+ struct rte_mbuf **input_bufs, **output_bufs;
+ int res = 0;
+ int allocated = 0;
+ uint32_t out_seg_sz;
+
+ if (test_data == NULL || !test_data->burst_sz) {
+ RTE_LOG(ERR, USER1,
+ "Unknown burst size\n");
+ return -1;
+ }
+
+ ops = rte_zmalloc_socket(NULL,
+ 2 * mem->total_bufs * sizeof(struct rte_comp_op *),
+ 0, rte_socket_id());
+
+ if (ops == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate memory for ops strucures\n");
+ return -1;
+ }
+
+ deq_ops = &ops[mem->total_bufs];
+
+ if (type == RTE_COMP_COMPRESS) {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_COMPRESS,
+ .compress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .deflate.huffman = test_data->huffman_enc,
+ .level = test_data->level,
+ .window_size = test_data->window_sz,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ output_data_ptr = ctx->mem.compressed_data;
+ output_data_sz = &ctx->comp_data_sz;
+ input_bufs = mem->decomp_bufs;
+ output_bufs = mem->comp_bufs;
+ out_seg_sz = test_data->out_seg_sz;
+ } else {
+ xform = (struct rte_comp_xform) {
+ .type = RTE_COMP_DECOMPRESS,
+ .decompress = {
+ .algo = RTE_COMP_ALGO_DEFLATE,
+ .chksum = RTE_COMP_CHECKSUM_NONE,
+ .window_size = test_data->window_sz,
+ .hash_algo = RTE_COMP_HASH_ALGO_NONE
+ }
+ };
+ output_data_ptr = ctx->mem.decompressed_data;
+ output_data_sz = &ctx->decomp_data_sz;
+ input_bufs = mem->comp_bufs;
+ output_bufs = mem->decomp_bufs;
+ out_seg_sz = test_data->seg_sz;
+ }
+
+ /* Create private xform */
+ if (rte_compressdev_private_xform_create(dev_id, &xform,
+ &priv_xform) < 0) {
+ RTE_LOG(ERR, USER1, "Private xform could not be created\n");
+ res = -1;
+ goto end;
+ }
+
+ num_iter = 1;
+
+ for (iter = 0; iter < num_iter; iter++) {
+ uint32_t total_ops = mem->total_bufs;
+ uint32_t remaining_ops = mem->total_bufs;
+ uint32_t total_deq_ops = 0;
+ uint32_t total_enq_ops = 0;
+ uint16_t ops_unused = 0;
+ uint16_t num_enq = 0;
+ uint16_t num_deq = 0;
+
+ output_size = 0;
+
+ while (remaining_ops > 0) {
+ uint16_t num_ops = RTE_MIN(remaining_ops,
+ test_data->burst_sz);
+ uint16_t ops_needed = num_ops - ops_unused;
+
+ /*
+ * Move the unused operations from the previous
+ * enqueue_burst call to the front, to maintain order
+ */
+ if ((ops_unused > 0) && (num_enq > 0)) {
+ size_t nb_b_to_mov =
+ ops_unused * sizeof(struct rte_comp_op *);
+
+ memmove(ops, &ops[num_enq], nb_b_to_mov);
+ }
+
+ /* Allocate compression operations */
+ if (ops_needed && !rte_comp_op_bulk_alloc(
+ mem->op_pool,
+ &ops[ops_unused],
+ ops_needed)) {
+ RTE_LOG(ERR, USER1,
+ "Could not allocate enough operations\n");
+ res = -1;
+ goto end;
+ }
+ allocated += ops_needed;
+
+ for (i = 0; i < ops_needed; i++) {
+ /*
+ * Calculate next buffer to attach to operation
+ */
+ uint32_t buf_id = total_enq_ops + i +
+ ops_unused;
+ uint16_t op_id = ops_unused + i;
+ /* Reset all data in output buffers */
+ struct rte_mbuf *m = output_bufs[buf_id];
+
+ m->pkt_len = out_seg_sz * m->nb_segs;
+ while (m) {
+ m->data_len = m->buf_len - m->data_off;
+ m = m->next;
+ }
+ ops[op_id]->m_src = input_bufs[buf_id];
+ ops[op_id]->m_dst = output_bufs[buf_id];
+ ops[op_id]->src.offset = 0;
+ ops[op_id]->src.length =
+ rte_pktmbuf_pkt_len(input_bufs[buf_id]);
+ ops[op_id]->dst.offset = 0;
+ ops[op_id]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ ops[op_id]->input_chksum = buf_id;
+ ops[op_id]->private_xform = priv_xform;
+ }
+
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ num_enq = rte_compressdev_enqueue_burst(dev_id,
+ mem->qp_id, ops,
+ num_ops);
+ if (num_enq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.enqueue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+
+ ops_unused = num_ops - num_enq;
+ remaining_ops -= num_enq;
+ total_enq_ops += num_enq;
+
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ test_data->burst_sz);
+ total_deq_ops += num_deq;
+
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED ||
+ op->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
+ RTE_LOG(ERR, USER1,
+"Out of space error occurred due to uncompressible input data expanding to larger than destination buffer. Increase the EXPANSE_RATIO constant to use this data.\n");
+ res = -1;
+ goto end;
+ } else if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Some operations were not successful\n");
+ goto end;
+ }
+
+ const void *read_data_addr =
+ rte_pktmbuf_read(op->m_dst, 0,
+ op->produced, output_data_ptr);
+ if (read_data_addr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Could not copy buffer in destination\n");
+ res = -1;
+ goto end;
+ }
+
+ if (read_data_addr != output_data_ptr)
+ rte_memcpy(output_data_ptr,
+ rte_pktmbuf_mtod(op->m_dst,
+ uint8_t *),
+ op->produced);
+ output_data_ptr += op->produced;
+ output_size += op->produced;
+
+ }
+
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+
+ /* Dequeue the last operations */
+ while (total_deq_ops < total_ops) {
+ if (unlikely(test_data->perf_comp_force_stop))
+ goto end;
+
+ num_deq = rte_compressdev_dequeue_burst(dev_id,
+ mem->qp_id,
+ deq_ops,
+ test_data->burst_sz);
+ if (num_deq == 0) {
+ struct rte_compressdev_stats stats;
+
+ rte_compressdev_stats_get(dev_id, &stats);
+ if (stats.dequeue_err_count) {
+ res = -1;
+ goto end;
+ }
+ }
+
+ total_deq_ops += num_deq;
+
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+
+ if (op->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED ||
+ op->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
+ RTE_LOG(ERR, USER1,
+"Out of space error occurred due to uncompressible input data expanding to larger than destination buffer. Increase the EXPANSE_RATIO constant to use this data.\n");
+ res = -1;
+ goto end;
+ } else if (op->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Some operations were not successful\n");
+ goto end;
+ }
+ const void *read_data_addr =
+ rte_pktmbuf_read(op->m_dst,
+ op->dst.offset,
+ op->produced, output_data_ptr);
+ if (read_data_addr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Could not copy buffer in destination\n");
+ res = -1;
+ goto end;
+ }
+
+ if (read_data_addr != output_data_ptr)
+ rte_memcpy(output_data_ptr,
+ rte_pktmbuf_mtod(
+ op->m_dst, uint8_t *),
+ op->produced);
+ output_data_ptr += op->produced;
+ output_size += op->produced;
+
+ }
+
+ if (iter == num_iter - 1) {
+ for (i = 0; i < num_deq; i++) {
+ struct rte_comp_op *op = deq_ops[i];
+ struct rte_mbuf *m = op->m_dst;
+
+ m->pkt_len = op->produced;
+ uint32_t remaining_data = op->produced;
+ uint16_t data_to_append;
+
+ while (remaining_data > 0) {
+ data_to_append =
+ RTE_MIN(remaining_data,
+ out_seg_sz);
+ m->data_len = data_to_append;
+ remaining_data -=
+ data_to_append;
+ m = m->next;
+ }
+ }
+ }
+ rte_mempool_put_bulk(mem->op_pool,
+ (void **)deq_ops, num_deq);
+ allocated -= num_deq;
+ }
+ }
+
+ if (output_data_sz)
+ *output_data_sz = output_size;
+end:
+ rte_mempool_put_bulk(mem->op_pool, (void **)ops, allocated);
+ rte_compressdev_private_xform_free(dev_id, priv_xform);
+ rte_free(ops);
+
+ if (test_data->perf_comp_force_stop) {
+ RTE_LOG(ERR, USER1,
+ "lcore: %d Perf. test has been aborted by user\n",
+ mem->lcore_id);
+ res = -1;
+ }
+
+ return res;
+}
+
+int
+cperf_verify_test_runner(void *test_ctx)
+{
+ struct cperf_verify_ctx *ctx = test_ctx;
+ struct comp_test_data *test_data = ctx->options;
+ int ret = EXIT_SUCCESS;
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+ uint32_t lcore = rte_lcore_id();
+
+ ctx->mem.lcore_id = lcore;
+
+ test_data->ratio = 0;
+
+ if (main_loop(ctx, RTE_COMP_COMPRESS) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ if (main_loop(ctx, RTE_COMP_DECOMPRESS) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ if (ctx->decomp_data_sz != test_data->input_data_sz) {
+ RTE_LOG(ERR, USER1,
+ "Decompressed data length not equal to input data length\n");
+ RTE_LOG(ERR, USER1,
+ "Decompressed size = %zu, expected = %zu\n",
+ ctx->decomp_data_sz, test_data->input_data_sz);
+ ret = EXIT_FAILURE;
+ goto end;
+ } else {
+ if (memcmp(ctx->mem.decompressed_data,
+ test_data->input_data,
+ test_data->input_data_sz) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Decompressed data is not the same as file data\n");
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+ }
+
+ ctx->ratio = (double) ctx->comp_data_sz /
+ test_data->input_data_sz * 100;
+
+ if (!ctx->silent) {
+ if (rte_atomic16_test_and_set(&display_once)) {
+ printf("%12s%6s%12s%17s\n",
+ "lcore id", "Level", "Comp size", "Comp ratio [%]");
+ }
+ printf("%12u%6u%12zu%17.2f\n",
+ ctx->mem.lcore_id,
+ test_data->level, ctx->comp_data_sz, ctx->ratio);
+ }
+
+end:
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.h b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.h
new file mode 100644
index 000000000..ae8b7429c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/comp_perf_test_verify.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2019 Intel Corporation
+ */
+
+#ifndef _COMP_PERF_TEST_VERIFY_
+#define _COMP_PERF_TEST_VERIFY_
+
+#include <stdint.h>
+
+#include "comp_perf_options.h"
+#include "comp_perf_test_common.h"
+
+struct cperf_verify_ctx {
+ struct cperf_mem_resources mem;
+ struct comp_test_data *options;
+
+ int silent;
+ size_t comp_data_sz;
+ size_t decomp_data_sz;
+ double ratio;
+};
+
+void
+cperf_verify_test_destructor(void *arg);
+
+int
+cperf_verify_test_runner(void *test_ctx);
+
+void *
+cperf_verify_test_constructor(uint8_t dev_id, uint16_t qp_id,
+ struct comp_test_data *options);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-compress-perf/main.c b/src/spdk/dpdk/app/test-compress-perf/main.c
new file mode 100644
index 000000000..ed21605d8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/main.c
@@ -0,0 +1,548 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_log.h>
+#include <rte_compressdev.h>
+
+#include "comp_perf.h"
+#include "comp_perf_options.h"
+#include "comp_perf_test_common.h"
+#include "comp_perf_test_cyclecount.h"
+#include "comp_perf_test_throughput.h"
+#include "comp_perf_test_verify.h"
+
+#define NUM_MAX_XFORMS 16
+#define NUM_MAX_INFLIGHT_OPS 512
+
+__extension__
+const char *comp_perf_test_type_strs[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
+ [CPERF_TEST_TYPE_VERIFY] = "verify",
+ [CPERF_TEST_TYPE_PMDCC] = "pmd-cyclecount"
+};
+
+__extension__
+static const struct cperf_test cperf_testmap[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = {
+ cperf_throughput_test_constructor,
+ cperf_throughput_test_runner,
+ cperf_throughput_test_destructor
+
+ },
+ [CPERF_TEST_TYPE_VERIFY] = {
+ cperf_verify_test_constructor,
+ cperf_verify_test_runner,
+ cperf_verify_test_destructor
+ },
+
+ [CPERF_TEST_TYPE_PMDCC] = {
+ cperf_cyclecount_test_constructor,
+ cperf_cyclecount_test_runner,
+ cperf_cyclecount_test_destructor
+ }
+};
+
+static struct comp_test_data *test_data;
+
+static int
+comp_perf_check_capabilities(struct comp_test_data *test_data, uint8_t cdev_id)
+{
+ const struct rte_compressdev_capabilities *cap;
+
+ cap = rte_compressdev_capability_get(cdev_id,
+ RTE_COMP_ALGO_DEFLATE);
+
+ if (cap == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress device does not support DEFLATE\n");
+ return -1;
+ }
+
+ uint64_t comp_flags = cap->comp_feature_flags;
+
+ /* Huffman enconding */
+ if (test_data->huffman_enc == RTE_COMP_HUFFMAN_FIXED &&
+ (comp_flags & RTE_COMP_FF_HUFFMAN_FIXED) == 0) {
+ RTE_LOG(ERR, USER1,
+ "Compress device does not supported Fixed Huffman\n");
+ return -1;
+ }
+
+ if (test_data->huffman_enc == RTE_COMP_HUFFMAN_DYNAMIC &&
+ (comp_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0) {
+ RTE_LOG(ERR, USER1,
+ "Compress device does not supported Dynamic Huffman\n");
+ return -1;
+ }
+
+ /* Window size */
+ if (test_data->window_sz != -1) {
+ if (param_range_check(test_data->window_sz, &cap->window_size)
+ < 0) {
+ RTE_LOG(ERR, USER1,
+ "Compress device does not support "
+ "this window size\n");
+ return -1;
+ }
+ } else
+ /* Set window size to PMD maximum if none was specified */
+ test_data->window_sz = cap->window_size.max;
+
+ /* Check if chained mbufs is supported */
+ if (test_data->max_sgl_segs > 1 &&
+ (comp_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0) {
+ RTE_LOG(INFO, USER1, "Compress device does not support "
+ "chained mbufs. Max SGL segments set to 1\n");
+ test_data->max_sgl_segs = 1;
+ }
+
+ /* Level 0 support */
+ if (test_data->level_lst.min == 0 &&
+ (comp_flags & RTE_COMP_FF_NONCOMPRESSED_BLOCKS) == 0) {
+ RTE_LOG(ERR, USER1, "Compress device does not support "
+ "level 0 (no compression)\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+comp_perf_initialize_compressdev(struct comp_test_data *test_data,
+ uint8_t *enabled_cdevs)
+{
+ uint8_t enabled_cdev_count, nb_lcores, cdev_id;
+ unsigned int i, j;
+ int ret;
+
+ enabled_cdev_count = rte_compressdev_devices_get(test_data->driver_name,
+ enabled_cdevs, RTE_COMPRESS_MAX_DEVS);
+ if (enabled_cdev_count == 0) {
+ RTE_LOG(ERR, USER1, "No compress devices type %s available,"
+ " please check the list of specified devices in EAL section\n",
+ test_data->driver_name);
+ return -EINVAL;
+ }
+
+ nb_lcores = rte_lcore_count() - 1;
+ /*
+ * Use fewer devices,
+ * if there are more available than cores.
+ */
+ if (enabled_cdev_count > nb_lcores) {
+ if (nb_lcores == 0) {
+ RTE_LOG(ERR, USER1, "Cannot run with 0 cores! Increase the number of cores\n");
+ return -EINVAL;
+ }
+ enabled_cdev_count = nb_lcores;
+ RTE_LOG(INFO, USER1,
+ "There's more available devices than cores!"
+ " The number of devices has been aligned to %d cores\n",
+ nb_lcores);
+ }
+
+ /*
+ * Calculate number of needed queue pairs, based on the amount
+ * of available number of logical cores and compression devices.
+ * For instance, if there are 4 cores and 2 compression devices,
+ * 2 queue pairs will be set up per device.
+ * One queue pair per one core.
+ * if e.g.: there're 3 cores and 2 compression devices,
+ * 2 queue pairs will be set up per device but one queue pair
+ * will left unused in the last one device
+ */
+ test_data->nb_qps = (nb_lcores % enabled_cdev_count) ?
+ (nb_lcores / enabled_cdev_count) + 1 :
+ nb_lcores / enabled_cdev_count;
+
+ for (i = 0; i < enabled_cdev_count &&
+ i < RTE_COMPRESS_MAX_DEVS; i++,
+ nb_lcores -= test_data->nb_qps) {
+ cdev_id = enabled_cdevs[i];
+
+ struct rte_compressdev_info cdev_info;
+ uint8_t socket_id = rte_compressdev_socket_id(cdev_id);
+
+ rte_compressdev_info_get(cdev_id, &cdev_info);
+ if (cdev_info.max_nb_queue_pairs &&
+ test_data->nb_qps > cdev_info.max_nb_queue_pairs) {
+ RTE_LOG(ERR, USER1,
+ "Number of needed queue pairs is higher "
+ "than the maximum number of queue pairs "
+ "per device.\n");
+ RTE_LOG(ERR, USER1,
+ "Lower the number of cores or increase "
+ "the number of crypto devices\n");
+ return -EINVAL;
+ }
+
+ if (comp_perf_check_capabilities(test_data, cdev_id) < 0)
+ return -EINVAL;
+
+ /* Configure compressdev */
+ struct rte_compressdev_config config = {
+ .socket_id = socket_id,
+ .nb_queue_pairs = nb_lcores > test_data->nb_qps
+ ? test_data->nb_qps : nb_lcores,
+ .max_nb_priv_xforms = NUM_MAX_XFORMS,
+ .max_nb_streams = 0
+ };
+
+ if (rte_compressdev_configure(cdev_id, &config) < 0) {
+ RTE_LOG(ERR, USER1, "Device configuration failed\n");
+ return -EINVAL;
+ }
+
+ for (j = 0; j < test_data->nb_qps; j++) {
+ ret = rte_compressdev_queue_pair_setup(cdev_id, j,
+ NUM_MAX_INFLIGHT_OPS, socket_id);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to setup queue pair %u on compressdev %u",
+ j, cdev_id);
+ return -EINVAL;
+ }
+ }
+
+ ret = rte_compressdev_start(cdev_id);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to start device %u: error %d\n",
+ cdev_id, ret);
+ return -EPERM;
+ }
+ }
+
+ return enabled_cdev_count;
+}
+
+static int
+comp_perf_dump_input_data(struct comp_test_data *test_data)
+{
+ FILE *f = fopen(test_data->input_file, "r");
+ int ret = -1;
+
+ if (f == NULL) {
+ RTE_LOG(ERR, USER1, "Input file could not be opened\n");
+ return -1;
+ }
+
+ if (fseek(f, 0, SEEK_END) != 0) {
+ RTE_LOG(ERR, USER1, "Size of input could not be calculated\n");
+ goto end;
+ }
+ size_t actual_file_sz = ftell(f);
+ /* If extended input data size has not been set,
+ * input data size = file size
+ */
+
+ if (test_data->input_data_sz == 0)
+ test_data->input_data_sz = actual_file_sz;
+
+ if (test_data->input_data_sz <= 0 || actual_file_sz <= 0 ||
+ fseek(f, 0, SEEK_SET) != 0) {
+ RTE_LOG(ERR, USER1, "Size of input could not be calculated\n");
+ goto end;
+ }
+
+ test_data->input_data = rte_zmalloc_socket(NULL,
+ test_data->input_data_sz, 0, rte_socket_id());
+
+ if (test_data->input_data == NULL) {
+ RTE_LOG(ERR, USER1, "Memory to hold the data from the input "
+ "file could not be allocated\n");
+ goto end;
+ }
+
+ size_t remaining_data = test_data->input_data_sz;
+ uint8_t *data = test_data->input_data;
+
+ while (remaining_data > 0) {
+ size_t data_to_read = RTE_MIN(remaining_data, actual_file_sz);
+
+ if (fread(data, data_to_read, 1, f) != 1) {
+ RTE_LOG(ERR, USER1, "Input file could not be read\n");
+ goto end;
+ }
+ if (fseek(f, 0, SEEK_SET) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Size of input could not be calculated\n");
+ goto end;
+ }
+ remaining_data -= data_to_read;
+ data += data_to_read;
+ }
+
+ printf("\n");
+ if (test_data->input_data_sz > actual_file_sz)
+ RTE_LOG(INFO, USER1,
+ "%zu bytes read from file %s, extending the file %.2f times\n",
+ test_data->input_data_sz, test_data->input_file,
+ (double)test_data->input_data_sz/actual_file_sz);
+ else
+ RTE_LOG(INFO, USER1,
+ "%zu bytes read from file %s\n",
+ test_data->input_data_sz, test_data->input_file);
+
+ ret = 0;
+
+end:
+ fclose(f);
+ return ret;
+}
+
+static void
+comp_perf_cleanup_on_signal(int signalNumber __rte_unused)
+{
+ test_data->perf_comp_force_stop = 1;
+}
+
+static void
+comp_perf_register_cleanup_on_signal(void)
+{
+ signal(SIGTERM, comp_perf_cleanup_on_signal);
+ signal(SIGINT, comp_perf_cleanup_on_signal);
+}
+
+int
+main(int argc, char **argv)
+{
+ uint8_t level_idx = 0;
+ int ret, i;
+ void *ctx[RTE_MAX_LCORE] = {};
+ uint8_t enabled_cdevs[RTE_COMPRESS_MAX_DEVS];
+ int nb_compressdevs = 0;
+ uint16_t total_nb_qps = 0;
+ uint8_t cdev_id;
+ uint32_t lcore_id;
+
+ /* Initialise DPDK EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+ argc -= ret;
+ argv += ret;
+
+ test_data = rte_zmalloc_socket(NULL, sizeof(struct comp_test_data),
+ 0, rte_socket_id());
+
+ if (test_data == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot reserve memory in socket %d\n",
+ rte_socket_id());
+
+ comp_perf_register_cleanup_on_signal();
+
+ ret = EXIT_SUCCESS;
+ test_data->cleanup = ST_TEST_DATA;
+ comp_perf_options_default(test_data);
+
+ if (comp_perf_options_parse(test_data, argc, argv) < 0) {
+ RTE_LOG(ERR, USER1,
+ "Parsing one or more user options failed\n");
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ if (comp_perf_options_check(test_data) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ nb_compressdevs =
+ comp_perf_initialize_compressdev(test_data, enabled_cdevs);
+
+ if (nb_compressdevs < 1) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ test_data->cleanup = ST_COMPDEV;
+ if (comp_perf_dump_input_data(test_data) < 0) {
+ ret = EXIT_FAILURE;
+ goto end;
+ }
+
+ test_data->cleanup = ST_INPUT_DATA;
+
+ if (test_data->level_lst.inc != 0)
+ test_data->level = test_data->level_lst.min;
+ else
+ test_data->level = test_data->level_lst.list[0];
+
+ printf("\nApp uses socket: %u\n", rte_socket_id());
+ printf("Burst size = %u\n", test_data->burst_sz);
+ printf("Input data size = %zu\n", test_data->input_data_sz);
+ if (test_data->test == CPERF_TEST_TYPE_PMDCC)
+ printf("Cycle-count delay = %u [us]\n",
+ test_data->cyclecount_delay);
+
+ test_data->cleanup = ST_DURING_TEST;
+ total_nb_qps = nb_compressdevs * test_data->nb_qps;
+
+ i = 0;
+ uint8_t qp_id = 0, cdev_index = 0;
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ cdev_id = enabled_cdevs[cdev_index];
+ ctx[i] = cperf_testmap[test_data->test].constructor(
+ cdev_id, qp_id,
+ test_data);
+ if (ctx[i] == NULL) {
+ RTE_LOG(ERR, USER1, "Test run constructor failed\n");
+ goto end;
+ }
+ qp_id = (qp_id + 1) % test_data->nb_qps;
+ if (qp_id == 0)
+ cdev_index++;
+ i++;
+ }
+
+ print_test_dynamics(test_data);
+
+ while (test_data->level <= test_data->level_lst.max) {
+
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ rte_eal_remote_launch(
+ cperf_testmap[test_data->test].runner,
+ ctx[i], lcore_id);
+ i++;
+ }
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+ ret |= rte_eal_wait_lcore(lcore_id);
+ i++;
+ }
+
+ if (ret != EXIT_SUCCESS)
+ break;
+
+ if (test_data->level_lst.inc != 0)
+ test_data->level += test_data->level_lst.inc;
+ else {
+ if (++level_idx == test_data->level_lst.count)
+ break;
+ test_data->level = test_data->level_lst.list[level_idx];
+ }
+ }
+
+end:
+ switch (test_data->cleanup) {
+
+ case ST_DURING_TEST:
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (i == total_nb_qps)
+ break;
+
+ if (ctx[i] && cperf_testmap[test_data->test].destructor)
+ cperf_testmap[test_data->test].destructor(
+ ctx[i]);
+ i++;
+ }
+ /* fallthrough */
+ case ST_INPUT_DATA:
+ rte_free(test_data->input_data);
+ /* fallthrough */
+ case ST_COMPDEV:
+ for (i = 0; i < nb_compressdevs &&
+ i < RTE_COMPRESS_MAX_DEVS; i++) {
+ rte_compressdev_stop(enabled_cdevs[i]);
+ rte_compressdev_close(enabled_cdevs[i]);
+ }
+ /* fallthrough */
+ case ST_TEST_DATA:
+ rte_free(test_data);
+ /* fallthrough */
+ case ST_CLEAR:
+ default:
+ i = rte_eal_cleanup();
+ if (i) {
+ RTE_LOG(ERR, USER1,
+ "Error from rte_eal_cleanup(), %d\n", i);
+ ret = i;
+ }
+ break;
+ }
+ return ret;
+}
+
+__rte_weak void *
+cperf_cyclecount_test_constructor(uint8_t dev_id __rte_unused,
+ uint16_t qp_id __rte_unused,
+ struct comp_test_data *options __rte_unused)
+{
+ RTE_LOG(INFO, USER1, "Cycle count test is not supported yet\n");
+ return NULL;
+}
+
+__rte_weak void
+cperf_cyclecount_test_destructor(void *arg __rte_unused)
+{
+ RTE_LOG(INFO, USER1, "Something wrong happened!!!\n");
+}
+
+__rte_weak int
+cperf_cyclecount_test_runner(void *test_ctx __rte_unused)
+{
+ return 0;
+}
+
+__rte_weak void *
+cperf_throughput_test_constructor(uint8_t dev_id __rte_unused,
+ uint16_t qp_id __rte_unused,
+ struct comp_test_data *options __rte_unused)
+{
+ RTE_LOG(INFO, USER1, "Benchmark test is not supported yet\n");
+ return NULL;
+}
+
+__rte_weak void
+cperf_throughput_test_destructor(void *arg __rte_unused)
+{
+
+}
+
+__rte_weak int
+cperf_throughput_test_runner(void *test_ctx __rte_unused)
+{
+ return 0;
+}
+__rte_weak void *
+cperf_verify_test_constructor(uint8_t dev_id __rte_unused,
+ uint16_t qp_id __rte_unused,
+ struct comp_test_data *options __rte_unused)
+{
+ RTE_LOG(INFO, USER1, "Verify test is not supported yet\n");
+ return NULL;
+}
+
+__rte_weak void
+cperf_verify_test_destructor(void *arg __rte_unused)
+{
+
+}
+
+__rte_weak int
+cperf_verify_test_runner(void *test_ctx __rte_unused)
+{
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-compress-perf/meson.build b/src/spdk/dpdk/app/test-compress-perf/meson.build
new file mode 100644
index 000000000..a1a484da9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-compress-perf/meson.build
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+sources = files('comp_perf_options_parse.c',
+ 'main.c',
+ 'comp_perf_test_verify.c',
+ 'comp_perf_test_throughput.c',
+ 'comp_perf_test_cyclecount.c',
+ 'comp_perf_test_common.c')
+deps = ['compressdev']
diff --git a/src/spdk/dpdk/app/test-crypto-perf/Makefile b/src/spdk/dpdk/app/test-crypto-perf/Makefile
new file mode 100644
index 000000000..0dced790f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/Makefile
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2016-2017 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+
+APP = dpdk-test-crypto-perf
+
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -O3
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+SRCS-y += cperf_ops.c
+SRCS-y += cperf_options_parsing.c
+SRCS-y += cperf_test_vectors.c
+SRCS-y += cperf_test_throughput.c
+SRCS-y += cperf_test_latency.c
+SRCS-y += cperf_test_pmd_cyclecount.c
+SRCS-y += cperf_test_verify.c
+SRCS-y += cperf_test_vector_parsing.c
+SRCS-y += cperf_test_common.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER),y)
+LDLIBS += -lrte_pmd_crypto_scheduler
+endif
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf.h b/src/spdk/dpdk/app/test-crypto-perf/cperf.h
new file mode 100644
index 000000000..2b0aad095
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_
+#define _CPERF_
+
+#include <rte_crypto.h>
+
+#include "cperf_ops.h"
+
+struct cperf_options;
+struct cperf_test_vector;
+struct cperf_op_fns;
+
+typedef void *(*cperf_constructor_t)(
+ struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id,
+ uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *t_vec,
+ const struct cperf_op_fns *op_fns);
+
+typedef int (*cperf_runner_t)(void *test_ctx);
+typedef void (*cperf_destructor_t)(void *test_ctx);
+
+struct cperf_test {
+ cperf_constructor_t constructor;
+ cperf_runner_t runner;
+ cperf_destructor_t destructor;
+};
+
+#endif /* _CPERF_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.c
new file mode 100644
index 000000000..97584ceed
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.c
@@ -0,0 +1,777 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_cryptodev.h>
+
+#include "cperf_ops.h"
+#include "cperf_test_vectors.h"
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+cperf_set_ops_security(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset __rte_unused,
+ uint32_t dst_buf_offset __rte_unused,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options __rte_unused,
+ const struct cperf_test_vector *test_vector __rte_unused,
+ uint16_t iv_offset __rte_unused,
+ uint32_t *imix_idx __rte_unused)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+ struct rte_security_session *sec_sess =
+ (struct rte_security_session *)sess;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_security_attach_session(ops[i], sec_sess);
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+ sym_op->m_src->buf_len = options->segment_sz;
+ sym_op->m_src->data_len = options->test_buffer_size;
+ sym_op->m_src->pkt_len = sym_op->m_src->data_len;
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+ }
+
+ return 0;
+}
+#endif
+
+static int
+cperf_set_ops_null_cipher(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector __rte_unused,
+ uint16_t iv_offset __rte_unused, uint32_t *imix_idx)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ /* cipher parameters */
+ if (options->imix_distribution_count) {
+ sym_op->cipher.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->cipher.data.length = options->test_buffer_size;
+ sym_op->cipher.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_null_auth(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector __rte_unused,
+ uint16_t iv_offset __rte_unused, uint32_t *imix_idx)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ /* auth parameters */
+ if (options->imix_distribution_count) {
+ sym_op->auth.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->auth.data.length = options->test_buffer_size;
+ sym_op->auth.data.offset = 0;
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_cipher(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset, uint32_t *imix_idx)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ /* cipher parameters */
+ if (options->imix_distribution_count) {
+ sym_op->cipher.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->cipher.data.length = options->test_buffer_size;
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3)
+ sym_op->cipher.data.length <<= 3;
+
+ sym_op->cipher.data.offset = 0;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY) {
+ for (i = 0; i < nb_ops; i++) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *, iv_offset);
+
+ memcpy(iv_ptr, test_vector->cipher_iv.data,
+ test_vector->cipher_iv.length);
+
+ }
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_auth(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset, uint32_t *imix_idx)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ if (test_vector->auth_iv.length) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *,
+ iv_offset);
+ memcpy(iv_ptr, test_vector->auth_iv.data,
+ test_vector->auth_iv.length);
+ }
+
+ /* authentication parameters */
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ sym_op->auth.digest.data = test_vector->digest.data;
+ sym_op->auth.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ } else {
+
+ uint32_t offset = options->test_buffer_size;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = sym_op->m_dst;
+ } else {
+ tbuf = sym_op->m_src;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ /*
+ * If there is not enough room in segment,
+ * place the digest in the next segment
+ */
+ if ((tbuf->data_len - offset) < options->digest_sz) {
+ tbuf = tbuf->next;
+ offset = 0;
+ }
+ buf = tbuf;
+ }
+
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->auth.digest.phys_addr =
+ rte_pktmbuf_iova_offset(buf, offset);
+
+ }
+
+ if (options->imix_distribution_count) {
+ sym_op->auth.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->auth.data.length = options->test_buffer_size;
+
+ if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3)
+ sym_op->auth.data.length <<= 3;
+
+ sym_op->auth.data.offset = 0;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY) {
+ if (test_vector->auth_iv.length) {
+ for (i = 0; i < nb_ops; i++) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *, iv_offset);
+
+ memcpy(iv_ptr, test_vector->auth_iv.data,
+ test_vector->auth_iv.length);
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+cperf_set_ops_cipher_auth(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset, uint32_t *imix_idx)
+{
+ uint16_t i;
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ /* cipher parameters */
+ if (options->imix_distribution_count) {
+ sym_op->cipher.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->cipher.data.length = options->test_buffer_size;
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3)
+ sym_op->cipher.data.length <<= 3;
+
+ sym_op->cipher.data.offset = 0;
+
+ /* authentication parameters */
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ sym_op->auth.digest.data = test_vector->digest.data;
+ sym_op->auth.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ } else {
+
+ uint32_t offset = options->test_buffer_size;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = sym_op->m_dst;
+ } else {
+ tbuf = sym_op->m_src;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ /*
+ * If there is not enough room in segment,
+ * place the digest in the next segment
+ */
+ if ((tbuf->data_len - offset) < options->digest_sz) {
+ tbuf = tbuf->next;
+ offset = 0;
+ }
+ buf = tbuf;
+ }
+
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->auth.digest.phys_addr =
+ rte_pktmbuf_iova_offset(buf, offset);
+ }
+
+ if (options->imix_distribution_count) {
+ sym_op->auth.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->auth.data.length = options->test_buffer_size;
+
+ if (options->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ options->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3)
+ sym_op->auth.data.length <<= 3;
+
+ sym_op->auth.data.offset = 0;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY) {
+ for (i = 0; i < nb_ops; i++) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *, iv_offset);
+
+ memcpy(iv_ptr, test_vector->cipher_iv.data,
+ test_vector->cipher_iv.length);
+ if (test_vector->auth_iv.length) {
+ /*
+ * Copy IV after the crypto operation and
+ * the cipher IV
+ */
+ iv_ptr += test_vector->cipher_iv.length;
+ memcpy(iv_ptr, test_vector->auth_iv.data,
+ test_vector->auth_iv.length);
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+static int
+cperf_set_ops_aead(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset, uint32_t *imix_idx)
+{
+ uint16_t i;
+ /* AAD is placed after the IV */
+ uint16_t aad_offset = iv_offset +
+ RTE_ALIGN_CEIL(test_vector->aead_iv.length, 16);
+
+ for (i = 0; i < nb_ops; i++) {
+ struct rte_crypto_sym_op *sym_op = ops[i]->sym;
+
+ ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ rte_crypto_op_attach_sym_session(ops[i], sess);
+
+ sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ src_buf_offset);
+
+ /* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
+ if (dst_buf_offset == 0)
+ sym_op->m_dst = NULL;
+ else
+ sym_op->m_dst = (struct rte_mbuf *)((uint8_t *)ops[i] +
+ dst_buf_offset);
+
+ /* AEAD parameters */
+ if (options->imix_distribution_count) {
+ sym_op->aead.data.length =
+ options->imix_buffer_sizes[*imix_idx];
+ *imix_idx = (*imix_idx + 1) % options->pool_sz;
+ } else
+ sym_op->aead.data.length = options->test_buffer_size;
+ sym_op->aead.data.offset = 0;
+
+ sym_op->aead.aad.data = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *, aad_offset);
+ sym_op->aead.aad.phys_addr = rte_crypto_op_ctophys_offset(ops[i],
+ aad_offset);
+
+ if (options->aead_op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
+ sym_op->aead.digest.data = test_vector->digest.data;
+ sym_op->aead.digest.phys_addr =
+ test_vector->digest.phys_addr;
+ } else {
+
+ uint32_t offset = sym_op->aead.data.length +
+ sym_op->aead.data.offset;
+ struct rte_mbuf *buf, *tbuf;
+
+ if (options->out_of_place) {
+ buf = sym_op->m_dst;
+ } else {
+ tbuf = sym_op->m_src;
+ while ((tbuf->next != NULL) &&
+ (offset >= tbuf->data_len)) {
+ offset -= tbuf->data_len;
+ tbuf = tbuf->next;
+ }
+ /*
+ * If there is not enough room in segment,
+ * place the digest in the next segment
+ */
+ if ((tbuf->data_len - offset) < options->digest_sz) {
+ tbuf = tbuf->next;
+ offset = 0;
+ }
+ buf = tbuf;
+ }
+
+ sym_op->aead.digest.data = rte_pktmbuf_mtod_offset(buf,
+ uint8_t *, offset);
+ sym_op->aead.digest.phys_addr =
+ rte_pktmbuf_iova_offset(buf, offset);
+ }
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY) {
+ for (i = 0; i < nb_ops; i++) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ops[i],
+ uint8_t *, iv_offset);
+
+ /*
+ * If doing AES-CCM, nonce is copied one byte
+ * after the start of IV field, and AAD is copied
+ * 18 bytes after the start of the AAD field.
+ */
+ if (options->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) {
+ memcpy(iv_ptr + 1, test_vector->aead_iv.data,
+ test_vector->aead_iv.length);
+
+ memcpy(ops[i]->sym->aead.aad.data + 18,
+ test_vector->aad.data,
+ test_vector->aad.length);
+ } else {
+ memcpy(iv_ptr, test_vector->aead_iv.data,
+ test_vector->aead_iv.length);
+
+ memcpy(ops[i]->sym->aead.aad.data,
+ test_vector->aad.data,
+ test_vector->aad.length);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct rte_cryptodev_sym_session *
+cperf_create_session(struct rte_mempool *sess_mp,
+ struct rte_mempool *priv_mp,
+ uint8_t dev_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset)
+{
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_crypto_sym_xform aead_xform;
+ struct rte_cryptodev_sym_session *sess = NULL;
+
+#ifdef RTE_LIBRTE_SECURITY
+ /*
+ * security only
+ */
+ if (options->op_type == CPERF_PDCP) {
+ /* Setup Cipher Parameters */
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+ cipher_xform.cipher.algo = options->cipher_algo;
+ cipher_xform.cipher.op = options->cipher_op;
+ cipher_xform.cipher.iv.offset = iv_offset;
+
+ /* cipher different than null */
+ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ cipher_xform.cipher.key.data = test_vector->cipher_key.data;
+ cipher_xform.cipher.key.length = test_vector->cipher_key.length;
+ cipher_xform.cipher.iv.length = test_vector->cipher_iv.length;
+ } else {
+ cipher_xform.cipher.key.data = NULL;
+ cipher_xform.cipher.key.length = 0;
+ cipher_xform.cipher.iv.length = 0;
+ }
+
+ /* Setup Auth Parameters */
+ if (options->auth_algo != 0) {
+ auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform.next = NULL;
+ auth_xform.auth.algo = options->auth_algo;
+ auth_xform.auth.op = options->auth_op;
+ auth_xform.auth.iv.offset = iv_offset +
+ cipher_xform.cipher.iv.length;
+
+ /* auth different than null */
+ if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ auth_xform.auth.digest_length = options->digest_sz;
+ auth_xform.auth.key.length = test_vector->auth_key.length;
+ auth_xform.auth.key.data = test_vector->auth_key.data;
+ auth_xform.auth.iv.length = test_vector->auth_iv.length;
+ } else {
+ auth_xform.auth.digest_length = 0;
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ auth_xform.auth.iv.length = 0;
+ }
+
+ cipher_xform.next = &auth_xform;
+ } else {
+ cipher_xform.next = NULL;
+ }
+
+ struct rte_security_session_conf sess_conf = {
+ .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ {.pdcp = {
+ .bearer = 0x16,
+ .domain = options->pdcp_domain,
+ .pkt_dir = 0,
+ .sn_size = options->pdcp_sn_sz,
+ .hfn = 0x1,
+ .hfn_threshold = 0x70C0A,
+ } },
+ .crypto_xform = &cipher_xform
+ };
+
+ struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+ rte_cryptodev_get_sec_ctx(dev_id);
+
+ /* Create security session */
+ return (void *)rte_security_session_create(ctx,
+ &sess_conf, sess_mp);
+ }
+#endif
+ sess = rte_cryptodev_sym_session_create(sess_mp);
+ /*
+ * cipher only
+ */
+ if (options->op_type == CPERF_CIPHER_ONLY) {
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+ cipher_xform.cipher.algo = options->cipher_algo;
+ cipher_xform.cipher.op = options->cipher_op;
+ cipher_xform.cipher.iv.offset = iv_offset;
+
+ /* cipher different than null */
+ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ cipher_xform.cipher.key.data =
+ test_vector->cipher_key.data;
+ cipher_xform.cipher.key.length =
+ test_vector->cipher_key.length;
+ cipher_xform.cipher.iv.length =
+ test_vector->cipher_iv.length;
+ } else {
+ cipher_xform.cipher.key.data = NULL;
+ cipher_xform.cipher.key.length = 0;
+ cipher_xform.cipher.iv.length = 0;
+ }
+ /* create crypto session */
+ rte_cryptodev_sym_session_init(dev_id, sess, &cipher_xform,
+ priv_mp);
+ /*
+ * auth only
+ */
+ } else if (options->op_type == CPERF_AUTH_ONLY) {
+ auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform.next = NULL;
+ auth_xform.auth.algo = options->auth_algo;
+ auth_xform.auth.op = options->auth_op;
+ auth_xform.auth.iv.offset = iv_offset;
+
+ /* auth different than null */
+ if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ auth_xform.auth.digest_length =
+ options->digest_sz;
+ auth_xform.auth.key.length =
+ test_vector->auth_key.length;
+ auth_xform.auth.key.data = test_vector->auth_key.data;
+ auth_xform.auth.iv.length =
+ test_vector->auth_iv.length;
+ } else {
+ auth_xform.auth.digest_length = 0;
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ auth_xform.auth.iv.length = 0;
+ }
+ /* create crypto session */
+ rte_cryptodev_sym_session_init(dev_id, sess, &auth_xform,
+ priv_mp);
+ /*
+ * cipher and auth
+ */
+ } else if (options->op_type == CPERF_CIPHER_THEN_AUTH
+ || options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ /*
+ * cipher
+ */
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+ cipher_xform.cipher.algo = options->cipher_algo;
+ cipher_xform.cipher.op = options->cipher_op;
+ cipher_xform.cipher.iv.offset = iv_offset;
+
+ /* cipher different than null */
+ if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ cipher_xform.cipher.key.data =
+ test_vector->cipher_key.data;
+ cipher_xform.cipher.key.length =
+ test_vector->cipher_key.length;
+ cipher_xform.cipher.iv.length =
+ test_vector->cipher_iv.length;
+ } else {
+ cipher_xform.cipher.key.data = NULL;
+ cipher_xform.cipher.key.length = 0;
+ cipher_xform.cipher.iv.length = 0;
+ }
+
+ /*
+ * auth
+ */
+ auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform.next = NULL;
+ auth_xform.auth.algo = options->auth_algo;
+ auth_xform.auth.op = options->auth_op;
+ auth_xform.auth.iv.offset = iv_offset +
+ cipher_xform.cipher.iv.length;
+
+ /* auth different than null */
+ if (options->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ auth_xform.auth.digest_length = options->digest_sz;
+ auth_xform.auth.iv.length = test_vector->auth_iv.length;
+ auth_xform.auth.key.length =
+ test_vector->auth_key.length;
+ auth_xform.auth.key.data =
+ test_vector->auth_key.data;
+ } else {
+ auth_xform.auth.digest_length = 0;
+ auth_xform.auth.key.length = 0;
+ auth_xform.auth.key.data = NULL;
+ auth_xform.auth.iv.length = 0;
+ }
+
+ /* cipher then auth */
+ if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ cipher_xform.next = &auth_xform;
+ /* create crypto session */
+ rte_cryptodev_sym_session_init(dev_id,
+ sess, &cipher_xform, priv_mp);
+ } else { /* auth then cipher */
+ auth_xform.next = &cipher_xform;
+ /* create crypto session */
+ rte_cryptodev_sym_session_init(dev_id,
+ sess, &auth_xform, priv_mp);
+ }
+ } else { /* options->op_type == CPERF_AEAD */
+ aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ aead_xform.next = NULL;
+ aead_xform.aead.algo = options->aead_algo;
+ aead_xform.aead.op = options->aead_op;
+ aead_xform.aead.iv.offset = iv_offset;
+
+ aead_xform.aead.key.data =
+ test_vector->aead_key.data;
+ aead_xform.aead.key.length =
+ test_vector->aead_key.length;
+ aead_xform.aead.iv.length = test_vector->aead_iv.length;
+
+ aead_xform.aead.digest_length = options->digest_sz;
+ aead_xform.aead.aad_length =
+ options->aead_aad_sz;
+
+ /* Create crypto session */
+ rte_cryptodev_sym_session_init(dev_id,
+ sess, &aead_xform, priv_mp);
+ }
+
+ return sess;
+}
+
+int
+cperf_get_op_functions(const struct cperf_options *options,
+ struct cperf_op_fns *op_fns)
+{
+ memset(op_fns, 0, sizeof(struct cperf_op_fns));
+
+ op_fns->sess_create = cperf_create_session;
+
+ if (options->op_type == CPERF_AEAD) {
+ op_fns->populate_ops = cperf_set_ops_aead;
+ return 0;
+ }
+
+ if (options->op_type == CPERF_AUTH_THEN_CIPHER
+ || options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ op_fns->populate_ops = cperf_set_ops_cipher_auth;
+ return 0;
+ }
+ if (options->op_type == CPERF_AUTH_ONLY) {
+ if (options->auth_algo == RTE_CRYPTO_AUTH_NULL)
+ op_fns->populate_ops = cperf_set_ops_null_auth;
+ else
+ op_fns->populate_ops = cperf_set_ops_auth;
+ return 0;
+ }
+ if (options->op_type == CPERF_CIPHER_ONLY) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL)
+ op_fns->populate_ops = cperf_set_ops_null_cipher;
+ else
+ op_fns->populate_ops = cperf_set_ops_cipher;
+ return 0;
+ }
+#ifdef RTE_LIBRTE_SECURITY
+ if (options->op_type == CPERF_PDCP) {
+ op_fns->populate_ops = cperf_set_ops_security;
+ return 0;
+ }
+#endif
+ return -1;
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.h
new file mode 100644
index 000000000..ff125d12c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_ops.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_OPS_
+#define _CPERF_OPS_
+
+#include <rte_crypto.h>
+
+#include "cperf.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+typedef struct rte_cryptodev_sym_session *(*cperf_sessions_create_t)(
+ struct rte_mempool *sess_mp, struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id, const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset);
+
+typedef int (*cperf_populate_ops_t)(struct rte_crypto_op **ops,
+ uint32_t src_buf_offset, uint32_t dst_buf_offset,
+ uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint16_t iv_offset, uint32_t *imix_idx);
+
+struct cperf_op_fns {
+ cperf_sessions_create_t sess_create;
+ cperf_populate_ops_t populate_ops;
+};
+
+int
+cperf_get_op_functions(const struct cperf_options *options,
+ struct cperf_op_fns *op_fns);
+
+#endif /* _CPERF_OPS_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_options.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_options.h
new file mode 100644
index 000000000..1ed0a77e5
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_options.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _CPERF_OPTIONS_
+#define _CPERF_OPTIONS_
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
+
+#define CPERF_PTEST_TYPE ("ptest")
+#define CPERF_SILENT ("silent")
+
+#define CPERF_POOL_SIZE ("pool-sz")
+#define CPERF_TOTAL_OPS ("total-ops")
+#define CPERF_BURST_SIZE ("burst-sz")
+#define CPERF_BUFFER_SIZE ("buffer-sz")
+#define CPERF_SEGMENT_SIZE ("segment-sz")
+#define CPERF_DESC_NB ("desc-nb")
+#define CPERF_IMIX ("imix")
+
+#define CPERF_DEVTYPE ("devtype")
+#define CPERF_OPTYPE ("optype")
+#define CPERF_SESSIONLESS ("sessionless")
+#define CPERF_OUT_OF_PLACE ("out-of-place")
+#define CPERF_TEST_FILE ("test-file")
+#define CPERF_TEST_NAME ("test-name")
+
+#define CPERF_CIPHER_ALGO ("cipher-algo")
+#define CPERF_CIPHER_OP ("cipher-op")
+#define CPERF_CIPHER_KEY_SZ ("cipher-key-sz")
+#define CPERF_CIPHER_IV_SZ ("cipher-iv-sz")
+
+#define CPERF_AUTH_ALGO ("auth-algo")
+#define CPERF_AUTH_OP ("auth-op")
+#define CPERF_AUTH_KEY_SZ ("auth-key-sz")
+#define CPERF_AUTH_IV_SZ ("auth-iv-sz")
+
+#define CPERF_AEAD_ALGO ("aead-algo")
+#define CPERF_AEAD_OP ("aead-op")
+#define CPERF_AEAD_KEY_SZ ("aead-key-sz")
+#define CPERF_AEAD_IV_SZ ("aead-iv-sz")
+#define CPERF_AEAD_AAD_SZ ("aead-aad-sz")
+
+#define CPERF_DIGEST_SZ ("digest-sz")
+
+#ifdef RTE_LIBRTE_SECURITY
+#define CPERF_PDCP_SN_SZ ("pdcp-sn-sz")
+#define CPERF_PDCP_DOMAIN ("pdcp-domain")
+#endif
+
+#define CPERF_CSV ("csv-friendly")
+
+/* benchmark-specific options */
+#define CPERF_PMDCC_DELAY_MS ("pmd-cyclecount-delay-ms")
+
+#define MAX_LIST 32
+
+enum cperf_perf_test_type {
+ CPERF_TEST_TYPE_THROUGHPUT,
+ CPERF_TEST_TYPE_LATENCY,
+ CPERF_TEST_TYPE_VERIFY,
+ CPERF_TEST_TYPE_PMDCC
+};
+
+
+extern const char *cperf_test_type_strs[];
+
+enum cperf_op_type {
+ CPERF_CIPHER_ONLY = 1,
+ CPERF_AUTH_ONLY,
+ CPERF_CIPHER_THEN_AUTH,
+ CPERF_AUTH_THEN_CIPHER,
+ CPERF_AEAD,
+ CPERF_PDCP
+};
+
+extern const char *cperf_op_type_strs[];
+
+struct cperf_options {
+ enum cperf_perf_test_type test;
+
+ uint32_t pool_sz;
+ uint32_t total_ops;
+ uint32_t headroom_sz;
+ uint32_t tailroom_sz;
+ uint32_t segment_sz;
+ uint32_t test_buffer_size;
+ uint32_t *imix_buffer_sizes;
+ uint32_t nb_descriptors;
+ uint16_t nb_qps;
+
+ uint32_t sessionless:1;
+ uint32_t out_of_place:1;
+ uint32_t silent:1;
+ uint32_t csv:1;
+
+ enum rte_crypto_cipher_algorithm cipher_algo;
+ enum rte_crypto_cipher_operation cipher_op;
+
+ uint16_t cipher_key_sz;
+ uint16_t cipher_iv_sz;
+
+ enum rte_crypto_auth_algorithm auth_algo;
+ enum rte_crypto_auth_operation auth_op;
+
+ uint16_t auth_key_sz;
+ uint16_t auth_iv_sz;
+
+ enum rte_crypto_aead_algorithm aead_algo;
+ enum rte_crypto_aead_operation aead_op;
+
+ uint16_t aead_key_sz;
+ uint16_t aead_iv_sz;
+ uint16_t aead_aad_sz;
+
+ uint16_t digest_sz;
+
+#ifdef RTE_LIBRTE_SECURITY
+ uint16_t pdcp_sn_sz;
+ enum rte_security_pdcp_domain pdcp_domain;
+#endif
+ char device_type[RTE_CRYPTODEV_NAME_MAX_LEN];
+ enum cperf_op_type op_type;
+
+ char *test_file;
+ char *test_name;
+
+ uint32_t buffer_size_list[MAX_LIST];
+ uint8_t buffer_size_count;
+ uint32_t max_buffer_size;
+ uint32_t min_buffer_size;
+ uint32_t inc_buffer_size;
+
+ uint32_t burst_size_list[MAX_LIST];
+ uint8_t burst_size_count;
+ uint32_t max_burst_size;
+ uint32_t min_burst_size;
+ uint32_t inc_burst_size;
+
+ /* pmd-cyclecount specific options */
+ uint32_t pmdcc_delay;
+ uint32_t imix_distribution_list[MAX_LIST];
+ uint8_t imix_distribution_count;
+};
+
+void
+cperf_options_default(struct cperf_options *options);
+
+int
+cperf_options_parse(struct cperf_options *options,
+ int argc, char **argv);
+
+int
+cperf_options_check(struct cperf_options *options);
+
+void
+cperf_options_dump(struct cperf_options *options);
+
+#endif
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_options_parsing.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_options_parsing.c
new file mode 100644
index 000000000..f43c5bede
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_options_parsing.c
@@ -0,0 +1,1239 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "cperf_options.h"
+
+#define AES_BLOCK_SIZE 16
+#define DES_BLOCK_SIZE 8
+
+struct name_id_map {
+ const char *name;
+ uint32_t id;
+};
+
+static void
+usage(char *progname)
+{
+ printf("%s [EAL options] --\n"
+ " --silent: disable options dump\n"
+ " --ptest throughput / latency / verify / pmd-cycleount :"
+ " set test type\n"
+ " --pool_sz N: set the number of crypto ops/mbufs allocated\n"
+ " --total-ops N: set the number of total operations performed\n"
+ " --burst-sz N: set the number of packets per burst\n"
+ " --buffer-sz N: set the size of a single packet\n"
+ " --imix N: set the distribution of packet sizes\n"
+ " --segment-sz N: set the size of the segment to use\n"
+ " --desc-nb N: set number of descriptors for each crypto device\n"
+ " --devtype TYPE: set crypto device type to use\n"
+ " --optype cipher-only / auth-only / cipher-then-auth /\n"
+ " auth-then-cipher / aead : set operation type\n"
+ " --sessionless: enable session-less crypto operations\n"
+ " --out-of-place: enable out-of-place crypto operations\n"
+ " --test-file NAME: set the test vector file path\n"
+ " --test-name NAME: set specific test name section in test file\n"
+ " --cipher-algo ALGO: set cipher algorithm\n"
+ " --cipher-op encrypt / decrypt: set the cipher operation\n"
+ " --cipher-key-sz N: set the cipher key size\n"
+ " --cipher-iv-sz N: set the cipher IV size\n"
+ " --auth-algo ALGO: set auth algorithm\n"
+ " --auth-op generate / verify: set the auth operation\n"
+ " --auth-key-sz N: set the auth key size\n"
+ " --auth-iv-sz N: set the auth IV size\n"
+ " --aead-algo ALGO: set AEAD algorithm\n"
+ " --aead-op encrypt / decrypt: set the AEAD operation\n"
+ " --aead-key-sz N: set the AEAD key size\n"
+ " --aead-iv-sz N: set the AEAD IV size\n"
+ " --aead-aad-sz N: set the AEAD AAD size\n"
+ " --digest-sz N: set the digest size\n"
+ " --pmd-cyclecount-delay-ms N: set delay between enqueue\n"
+ " and dequeue in pmd-cyclecount benchmarking mode\n"
+ " --csv-friendly: enable test result output CSV friendly\n"
+ " -h: prints this help\n",
+ progname);
+}
+
+static int
+get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
+ const char *str_key)
+{
+ unsigned int i;
+
+ for (i = 0; i < map_len; i++) {
+
+ if (strcmp(str_key, map[i].name) == 0)
+ return map[i].id;
+ }
+
+ return -1;
+}
+
+static int
+parse_cperf_test_type(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map cperftest_namemap[] = {
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
+ CPERF_TEST_TYPE_THROUGHPUT
+ },
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
+ CPERF_TEST_TYPE_VERIFY
+ },
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_LATENCY],
+ CPERF_TEST_TYPE_LATENCY
+ },
+ {
+ cperf_test_type_strs[CPERF_TEST_TYPE_PMDCC],
+ CPERF_TEST_TYPE_PMDCC
+ }
+ };
+
+ int id = get_str_key_id_mapping(
+ (struct name_id_map *)cperftest_namemap,
+ RTE_DIM(cperftest_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse test type");
+ return -1;
+ }
+
+ opts->test = (enum cperf_perf_test_type)id;
+
+ return 0;
+}
+
+static int
+parse_uint32_t(uint32_t *value, const char *arg)
+{
+ char *end = NULL;
+ unsigned long n = strtoul(arg, &end, 10);
+
+ if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (n > UINT32_MAX)
+ return -ERANGE;
+
+ *value = (uint32_t) n;
+
+ return 0;
+}
+
+static int
+parse_uint16_t(uint16_t *value, const char *arg)
+{
+ uint32_t val = 0;
+ int ret = parse_uint32_t(&val, arg);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = (uint16_t) val;
+
+ return 0;
+}
+
+static int
+parse_range(const char *arg, uint32_t *min, uint32_t *max, uint32_t *inc)
+{
+ char *token;
+ uint32_t number;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ errno = 0;
+ token = strtok(copy_arg, ":");
+
+ /* Parse minimum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_range;
+
+ *min = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse increment value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_range;
+
+ *inc = number;
+ } else
+ goto err_range;
+
+ token = strtok(NULL, ":");
+
+ /* Parse maximum value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0 ||
+ number < *min)
+ goto err_range;
+
+ *max = number;
+ } else
+ goto err_range;
+
+ if (strtok(NULL, ":") != NULL)
+ goto err_range;
+
+ free(copy_arg);
+ return 0;
+
+err_range:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_list(const char *arg, uint32_t *list, uint32_t *min, uint32_t *max)
+{
+ char *token;
+ uint32_t number;
+ uint8_t count = 0;
+ uint32_t temp_min;
+ uint32_t temp_max;
+
+ char *copy_arg = strdup(arg);
+
+ if (copy_arg == NULL)
+ return -1;
+
+ errno = 0;
+ token = strtok(copy_arg, ",");
+
+ /* Parse first value */
+ if (token != NULL) {
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_list;
+
+ list[count++] = number;
+ temp_min = number;
+ temp_max = number;
+ } else
+ goto err_list;
+
+ token = strtok(NULL, ",");
+
+ while (token != NULL) {
+ if (count == MAX_LIST) {
+ RTE_LOG(WARNING, USER1, "Using only the first %u sizes\n",
+ MAX_LIST);
+ break;
+ }
+
+ number = strtoul(token, NULL, 10);
+
+ if (errno == EINVAL || errno == ERANGE ||
+ number == 0)
+ goto err_list;
+
+ list[count++] = number;
+
+ if (number < temp_min)
+ temp_min = number;
+ if (number > temp_max)
+ temp_max = number;
+
+ token = strtok(NULL, ",");
+ }
+
+ if (min)
+ *min = temp_min;
+ if (max)
+ *max = temp_max;
+
+ free(copy_arg);
+ return count;
+
+err_list:
+ free(copy_arg);
+ return -1;
+}
+
+static int
+parse_total_ops(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->total_ops, arg);
+
+ if (ret)
+ RTE_LOG(ERR, USER1, "failed to parse total operations count\n");
+
+ if (opts->total_ops == 0) {
+ RTE_LOG(ERR, USER1,
+ "invalid total operations count number specified\n");
+ return -1;
+ }
+
+ return ret;
+}
+
+static int
+parse_pool_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->pool_sz, arg);
+
+ if (ret)
+ RTE_LOG(ERR, USER1, "failed to parse pool size");
+ return ret;
+}
+
+static int
+parse_burst_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret;
+
+ /* Try parsing the argument as a range, if it fails, parse it as a list */
+ if (parse_range(arg, &opts->min_burst_size, &opts->max_burst_size,
+ &opts->inc_burst_size) < 0) {
+ ret = parse_list(arg, opts->burst_size_list,
+ &opts->min_burst_size,
+ &opts->max_burst_size);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse burst size/s\n");
+ return -1;
+ }
+ opts->burst_size_count = ret;
+ }
+
+ return 0;
+}
+
+static int
+parse_buffer_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret;
+
+ /* Try parsing the argument as a range, if it fails, parse it as a list */
+ if (parse_range(arg, &opts->min_buffer_size, &opts->max_buffer_size,
+ &opts->inc_buffer_size) < 0) {
+ ret = parse_list(arg, opts->buffer_size_list,
+ &opts->min_buffer_size,
+ &opts->max_buffer_size);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse buffer size/s\n");
+ return -1;
+ }
+ opts->buffer_size_count = ret;
+ }
+
+ return 0;
+}
+
+static int
+parse_segment_sz(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->segment_sz, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "failed to parse segment size\n");
+ return -1;
+ }
+
+ if (opts->segment_sz == 0) {
+ RTE_LOG(ERR, USER1, "Segment size has to be bigger than 0\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_imix(struct cperf_options *opts, const char *arg)
+{
+ int ret;
+
+ ret = parse_list(arg, opts->imix_distribution_list,
+ NULL, NULL);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1, "failed to parse imix distribution\n");
+ return -1;
+ }
+
+ opts->imix_distribution_count = ret;
+
+ if (opts->imix_distribution_count <= 1) {
+ RTE_LOG(ERR, USER1, "imix distribution should have "
+ "at least two entries\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_desc_nb(struct cperf_options *opts, const char *arg)
+{
+ int ret = parse_uint32_t(&opts->nb_descriptors, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "failed to parse descriptors number\n");
+ return -1;
+ }
+
+ if (opts->nb_descriptors == 0) {
+ RTE_LOG(ERR, USER1, "invalid descriptors number specified\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+parse_device_type(struct cperf_options *opts, const char *arg)
+{
+ if (strlen(arg) > (sizeof(opts->device_type) - 1))
+ return -1;
+
+ strncpy(opts->device_type, arg, sizeof(opts->device_type) - 1);
+ *(opts->device_type + sizeof(opts->device_type) - 1) = '\0';
+
+ return 0;
+}
+
+static int
+parse_op_type(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map optype_namemap[] = {
+ {
+ cperf_op_type_strs[CPERF_CIPHER_ONLY],
+ CPERF_CIPHER_ONLY
+ },
+ {
+ cperf_op_type_strs[CPERF_AUTH_ONLY],
+ CPERF_AUTH_ONLY
+ },
+ {
+ cperf_op_type_strs[CPERF_CIPHER_THEN_AUTH],
+ CPERF_CIPHER_THEN_AUTH
+ },
+ {
+ cperf_op_type_strs[CPERF_AUTH_THEN_CIPHER],
+ CPERF_AUTH_THEN_CIPHER
+ },
+ {
+ cperf_op_type_strs[CPERF_AEAD],
+ CPERF_AEAD
+ },
+ {
+ cperf_op_type_strs[CPERF_PDCP],
+ CPERF_PDCP
+ }
+ };
+
+ int id = get_str_key_id_mapping(optype_namemap,
+ RTE_DIM(optype_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid opt type specified\n");
+ return -1;
+ }
+
+ opts->op_type = (enum cperf_op_type)id;
+
+ return 0;
+}
+
+static int
+parse_sessionless(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->sessionless = 1;
+ return 0;
+}
+
+static int
+parse_out_of_place(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->out_of_place = 1;
+ return 0;
+}
+
+static int
+parse_test_file(struct cperf_options *opts,
+ const char *arg)
+{
+ opts->test_file = strdup(arg);
+ if (access(opts->test_file, F_OK) != -1)
+ return 0;
+ RTE_LOG(ERR, USER1, "Test vector file doesn't exist\n");
+
+ return -1;
+}
+
+static int
+parse_test_name(struct cperf_options *opts,
+ const char *arg)
+{
+ char *test_name = (char *) rte_zmalloc(NULL,
+ sizeof(char) * (strlen(arg) + 3), 0);
+ snprintf(test_name, strlen(arg) + 3, "[%s]", arg);
+ opts->test_name = test_name;
+
+ return 0;
+}
+
+static int
+parse_silent(struct cperf_options *opts,
+ const char *arg __rte_unused)
+{
+ opts->silent = 1;
+
+ return 0;
+}
+
+static int
+parse_cipher_algo(struct cperf_options *opts, const char *arg)
+{
+
+ enum rte_crypto_cipher_algorithm cipher_algo;
+
+ if (rte_cryptodev_get_cipher_algo_enum(&cipher_algo, arg) < 0) {
+ RTE_LOG(ERR, USER1, "Invalid cipher algorithm specified\n");
+ return -1;
+ }
+
+ opts->cipher_algo = cipher_algo;
+
+ return 0;
+}
+
+static int
+parse_cipher_op(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map cipher_op_namemap[] = {
+ {
+ rte_crypto_cipher_operation_strings
+ [RTE_CRYPTO_CIPHER_OP_ENCRYPT],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT },
+ {
+ rte_crypto_cipher_operation_strings
+ [RTE_CRYPTO_CIPHER_OP_DECRYPT],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT
+ }
+ };
+
+ int id = get_str_key_id_mapping(cipher_op_namemap,
+ RTE_DIM(cipher_op_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "Invalid cipher operation specified\n");
+ return -1;
+ }
+
+ opts->cipher_op = (enum rte_crypto_cipher_operation)id;
+
+ return 0;
+}
+
+static int
+parse_cipher_key_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->cipher_key_sz, arg);
+}
+
+static int
+parse_cipher_iv_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->cipher_iv_sz, arg);
+}
+
+static int
+parse_auth_algo(struct cperf_options *opts, const char *arg)
+{
+ enum rte_crypto_auth_algorithm auth_algo;
+
+ if (rte_cryptodev_get_auth_algo_enum(&auth_algo, arg) < 0) {
+ RTE_LOG(ERR, USER1, "Invalid authentication algorithm specified\n");
+ return -1;
+ }
+
+ opts->auth_algo = auth_algo;
+
+ return 0;
+}
+
+static int
+parse_auth_op(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map auth_op_namemap[] = {
+ {
+ rte_crypto_auth_operation_strings
+ [RTE_CRYPTO_AUTH_OP_GENERATE],
+ RTE_CRYPTO_AUTH_OP_GENERATE },
+ {
+ rte_crypto_auth_operation_strings
+ [RTE_CRYPTO_AUTH_OP_VERIFY],
+ RTE_CRYPTO_AUTH_OP_VERIFY
+ }
+ };
+
+ int id = get_str_key_id_mapping(auth_op_namemap,
+ RTE_DIM(auth_op_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid authentication operation specified"
+ "\n");
+ return -1;
+ }
+
+ opts->auth_op = (enum rte_crypto_auth_operation)id;
+
+ return 0;
+}
+
+static int
+parse_auth_key_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->auth_key_sz, arg);
+}
+
+static int
+parse_digest_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->digest_sz, arg);
+}
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+parse_pdcp_sn_sz(struct cperf_options *opts, const char *arg)
+{
+ uint32_t val = 0;
+ int ret = parse_uint32_t(&val, arg);
+
+ if (ret < 0)
+ return ret;
+
+ if (val != RTE_SECURITY_PDCP_SN_SIZE_5 &&
+ val != RTE_SECURITY_PDCP_SN_SIZE_7 &&
+ val != RTE_SECURITY_PDCP_SN_SIZE_12 &&
+ val != RTE_SECURITY_PDCP_SN_SIZE_15 &&
+ val != RTE_SECURITY_PDCP_SN_SIZE_18) {
+ printf("\nInvalid pdcp SN size: %u\n", val);
+ return -ERANGE;
+ }
+ opts->pdcp_sn_sz = val;
+
+ return 0;
+}
+
+const char *cperf_pdcp_domain_strs[] = {
+ [RTE_SECURITY_PDCP_MODE_CONTROL] = "control",
+ [RTE_SECURITY_PDCP_MODE_DATA] = "data"
+};
+
+static int
+parse_pdcp_domain(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map pdcp_domain_namemap[] = {
+ {
+ cperf_pdcp_domain_strs
+ [RTE_SECURITY_PDCP_MODE_CONTROL],
+ RTE_SECURITY_PDCP_MODE_CONTROL },
+ {
+ cperf_pdcp_domain_strs
+ [RTE_SECURITY_PDCP_MODE_DATA],
+ RTE_SECURITY_PDCP_MODE_DATA
+ }
+ };
+
+ int id = get_str_key_id_mapping(pdcp_domain_namemap,
+ RTE_DIM(pdcp_domain_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid pdcp domain specified"
+ "\n");
+ return -1;
+ }
+
+ opts->pdcp_domain = (enum rte_security_pdcp_domain)id;
+
+ return 0;
+}
+#endif
+
+static int
+parse_auth_iv_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->auth_iv_sz, arg);
+}
+
+static int
+parse_aead_algo(struct cperf_options *opts, const char *arg)
+{
+ enum rte_crypto_aead_algorithm aead_algo;
+
+ if (rte_cryptodev_get_aead_algo_enum(&aead_algo, arg) < 0) {
+ RTE_LOG(ERR, USER1, "Invalid AEAD algorithm specified\n");
+ return -1;
+ }
+
+ opts->aead_algo = aead_algo;
+
+ return 0;
+}
+
+static int
+parse_aead_op(struct cperf_options *opts, const char *arg)
+{
+ struct name_id_map aead_op_namemap[] = {
+ {
+ rte_crypto_aead_operation_strings
+ [RTE_CRYPTO_AEAD_OP_ENCRYPT],
+ RTE_CRYPTO_AEAD_OP_ENCRYPT },
+ {
+ rte_crypto_aead_operation_strings
+ [RTE_CRYPTO_AEAD_OP_DECRYPT],
+ RTE_CRYPTO_AEAD_OP_DECRYPT
+ }
+ };
+
+ int id = get_str_key_id_mapping(aead_op_namemap,
+ RTE_DIM(aead_op_namemap), arg);
+ if (id < 0) {
+ RTE_LOG(ERR, USER1, "invalid AEAD operation specified"
+ "\n");
+ return -1;
+ }
+
+ opts->aead_op = (enum rte_crypto_aead_operation)id;
+
+ return 0;
+}
+
+static int
+parse_aead_key_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->aead_key_sz, arg);
+}
+
+static int
+parse_aead_iv_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->aead_iv_sz, arg);
+}
+
+static int
+parse_aead_aad_sz(struct cperf_options *opts, const char *arg)
+{
+ return parse_uint16_t(&opts->aead_aad_sz, arg);
+}
+
+static int
+parse_csv_friendly(struct cperf_options *opts, const char *arg __rte_unused)
+{
+ opts->csv = 1;
+ opts->silent = 1;
+ return 0;
+}
+
+static int
+parse_pmd_cyclecount_delay_ms(struct cperf_options *opts,
+ const char *arg)
+{
+ int ret = parse_uint32_t(&opts->pmdcc_delay, arg);
+
+ if (ret) {
+ RTE_LOG(ERR, USER1, "failed to parse pmd-cyclecount delay\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+typedef int (*option_parser_t)(struct cperf_options *opts,
+ const char *arg);
+
+struct long_opt_parser {
+ const char *lgopt_name;
+ option_parser_t parser_fn;
+
+};
+
+static struct option lgopts[] = {
+
+ { CPERF_PTEST_TYPE, required_argument, 0, 0 },
+
+ { CPERF_POOL_SIZE, required_argument, 0, 0 },
+ { CPERF_TOTAL_OPS, required_argument, 0, 0 },
+ { CPERF_BURST_SIZE, required_argument, 0, 0 },
+ { CPERF_BUFFER_SIZE, required_argument, 0, 0 },
+ { CPERF_SEGMENT_SIZE, required_argument, 0, 0 },
+ { CPERF_DESC_NB, required_argument, 0, 0 },
+
+ { CPERF_IMIX, required_argument, 0, 0 },
+ { CPERF_DEVTYPE, required_argument, 0, 0 },
+ { CPERF_OPTYPE, required_argument, 0, 0 },
+
+ { CPERF_SILENT, no_argument, 0, 0 },
+ { CPERF_SESSIONLESS, no_argument, 0, 0 },
+ { CPERF_OUT_OF_PLACE, no_argument, 0, 0 },
+ { CPERF_TEST_FILE, required_argument, 0, 0 },
+ { CPERF_TEST_NAME, required_argument, 0, 0 },
+
+ { CPERF_CIPHER_ALGO, required_argument, 0, 0 },
+ { CPERF_CIPHER_OP, required_argument, 0, 0 },
+
+ { CPERF_CIPHER_KEY_SZ, required_argument, 0, 0 },
+ { CPERF_CIPHER_IV_SZ, required_argument, 0, 0 },
+
+ { CPERF_AUTH_ALGO, required_argument, 0, 0 },
+ { CPERF_AUTH_OP, required_argument, 0, 0 },
+
+ { CPERF_AUTH_KEY_SZ, required_argument, 0, 0 },
+ { CPERF_AUTH_IV_SZ, required_argument, 0, 0 },
+
+ { CPERF_AEAD_ALGO, required_argument, 0, 0 },
+ { CPERF_AEAD_OP, required_argument, 0, 0 },
+
+ { CPERF_AEAD_KEY_SZ, required_argument, 0, 0 },
+ { CPERF_AEAD_AAD_SZ, required_argument, 0, 0 },
+ { CPERF_AEAD_IV_SZ, required_argument, 0, 0 },
+
+ { CPERF_DIGEST_SZ, required_argument, 0, 0 },
+
+#ifdef RTE_LIBRTE_SECURITY
+ { CPERF_PDCP_SN_SZ, required_argument, 0, 0 },
+ { CPERF_PDCP_DOMAIN, required_argument, 0, 0 },
+#endif
+ { CPERF_CSV, no_argument, 0, 0},
+
+ { CPERF_PMDCC_DELAY_MS, required_argument, 0, 0 },
+
+ { NULL, 0, 0, 0 }
+};
+
+void
+cperf_options_default(struct cperf_options *opts)
+{
+ opts->test = CPERF_TEST_TYPE_THROUGHPUT;
+
+ opts->pool_sz = 8192;
+ opts->total_ops = 10000000;
+ opts->nb_descriptors = 2048;
+
+ opts->buffer_size_list[0] = 64;
+ opts->buffer_size_count = 1;
+ opts->max_buffer_size = 64;
+ opts->min_buffer_size = 64;
+ opts->inc_buffer_size = 0;
+
+ opts->burst_size_list[0] = 32;
+ opts->burst_size_count = 1;
+ opts->max_burst_size = 32;
+ opts->min_burst_size = 32;
+ opts->inc_burst_size = 0;
+
+ /*
+ * Will be parsed from command line or set to
+ * maximum buffer size + digest, later
+ */
+ opts->segment_sz = 0;
+
+ opts->imix_distribution_count = 0;
+ strncpy(opts->device_type, "crypto_aesni_mb",
+ sizeof(opts->device_type));
+ opts->nb_qps = 1;
+
+ opts->op_type = CPERF_CIPHER_THEN_AUTH;
+
+ opts->silent = 0;
+ opts->test_file = NULL;
+ opts->test_name = NULL;
+ opts->sessionless = 0;
+ opts->out_of_place = 0;
+ opts->csv = 0;
+
+ opts->cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ opts->cipher_op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ opts->cipher_key_sz = 16;
+ opts->cipher_iv_sz = 16;
+
+ opts->auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ opts->auth_op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ opts->auth_key_sz = 64;
+ opts->auth_iv_sz = 0;
+
+ opts->aead_key_sz = 0;
+ opts->aead_iv_sz = 0;
+ opts->aead_aad_sz = 0;
+
+ opts->digest_sz = 12;
+
+ opts->pmdcc_delay = 0;
+#ifdef RTE_LIBRTE_SECURITY
+ opts->pdcp_sn_sz = 12;
+ opts->pdcp_domain = RTE_SECURITY_PDCP_MODE_CONTROL;
+#endif
+}
+
+static int
+cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
+{
+ struct long_opt_parser parsermap[] = {
+ { CPERF_PTEST_TYPE, parse_cperf_test_type },
+ { CPERF_SILENT, parse_silent },
+ { CPERF_POOL_SIZE, parse_pool_sz },
+ { CPERF_TOTAL_OPS, parse_total_ops },
+ { CPERF_BURST_SIZE, parse_burst_sz },
+ { CPERF_BUFFER_SIZE, parse_buffer_sz },
+ { CPERF_SEGMENT_SIZE, parse_segment_sz },
+ { CPERF_DESC_NB, parse_desc_nb },
+ { CPERF_DEVTYPE, parse_device_type },
+ { CPERF_OPTYPE, parse_op_type },
+ { CPERF_SESSIONLESS, parse_sessionless },
+ { CPERF_OUT_OF_PLACE, parse_out_of_place },
+ { CPERF_IMIX, parse_imix },
+ { CPERF_TEST_FILE, parse_test_file },
+ { CPERF_TEST_NAME, parse_test_name },
+ { CPERF_CIPHER_ALGO, parse_cipher_algo },
+ { CPERF_CIPHER_OP, parse_cipher_op },
+ { CPERF_CIPHER_KEY_SZ, parse_cipher_key_sz },
+ { CPERF_CIPHER_IV_SZ, parse_cipher_iv_sz },
+ { CPERF_AUTH_ALGO, parse_auth_algo },
+ { CPERF_AUTH_OP, parse_auth_op },
+ { CPERF_AUTH_KEY_SZ, parse_auth_key_sz },
+ { CPERF_AUTH_IV_SZ, parse_auth_iv_sz },
+ { CPERF_AEAD_ALGO, parse_aead_algo },
+ { CPERF_AEAD_OP, parse_aead_op },
+ { CPERF_AEAD_KEY_SZ, parse_aead_key_sz },
+ { CPERF_AEAD_IV_SZ, parse_aead_iv_sz },
+ { CPERF_AEAD_AAD_SZ, parse_aead_aad_sz },
+ { CPERF_DIGEST_SZ, parse_digest_sz },
+#ifdef RTE_LIBRTE_SECURITY
+ { CPERF_PDCP_SN_SZ, parse_pdcp_sn_sz },
+ { CPERF_PDCP_DOMAIN, parse_pdcp_domain },
+#endif
+ { CPERF_CSV, parse_csv_friendly},
+ { CPERF_PMDCC_DELAY_MS, parse_pmd_cyclecount_delay_ms},
+ };
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(parsermap); i++) {
+ if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+ strlen(lgopts[opt_idx].name)) == 0)
+ return parsermap[i].parser_fn(opts, optarg);
+ }
+
+ return -EINVAL;
+}
+
+int
+cperf_options_parse(struct cperf_options *options, int argc, char **argv)
+{
+ int opt, retval, opt_idx;
+
+ while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ break;
+ /* long options */
+ case 0:
+ retval = cperf_opts_parse_long(opt_idx, options);
+ if (retval != 0)
+ return retval;
+
+ break;
+
+ default:
+ usage(argv[0]);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int
+check_cipher_buffer_length(struct cperf_options *options)
+{
+ uint32_t buffer_size, buffer_size_idx = 0;
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_AES_ECB) {
+ if (options->inc_buffer_size != 0)
+ buffer_size = options->min_buffer_size;
+ else
+ buffer_size = options->buffer_size_list[0];
+
+ while (buffer_size <= options->max_buffer_size) {
+ if ((buffer_size % AES_BLOCK_SIZE) != 0) {
+ RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
+ "not suitable for the algorithm selected\n");
+ return -EINVAL;
+ }
+
+ if (options->inc_buffer_size != 0)
+ buffer_size += options->inc_buffer_size;
+ else {
+ if (++buffer_size_idx == options->buffer_size_count)
+ break;
+ buffer_size = options->buffer_size_list[buffer_size_idx];
+ }
+
+ }
+ }
+
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_DES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_CBC ||
+ options->cipher_algo == RTE_CRYPTO_CIPHER_3DES_ECB) {
+ if (options->inc_buffer_size != 0)
+ buffer_size = options->min_buffer_size;
+ else
+ buffer_size = options->buffer_size_list[0];
+
+ while (buffer_size <= options->max_buffer_size) {
+ if ((buffer_size % DES_BLOCK_SIZE) != 0) {
+ RTE_LOG(ERR, USER1, "Some of the buffer sizes are "
+ "not suitable for the algorithm selected\n");
+ return -EINVAL;
+ }
+
+ if (options->inc_buffer_size != 0)
+ buffer_size += options->inc_buffer_size;
+ else {
+ if (++buffer_size_idx == options->buffer_size_count)
+ break;
+ buffer_size = options->buffer_size_list[buffer_size_idx];
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+int
+cperf_options_check(struct cperf_options *options)
+{
+ if (options->op_type == CPERF_CIPHER_ONLY)
+ options->digest_sz = 0;
+
+ if (options->out_of_place &&
+ options->segment_sz <= options->max_buffer_size) {
+ RTE_LOG(ERR, USER1, "Out of place mode can only work "
+ "with non segmented buffers\n");
+ return -EINVAL;
+ }
+
+ /*
+ * If segment size is not set, assume only one segment,
+ * big enough to contain the largest buffer and the digest
+ */
+ if (options->segment_sz == 0)
+ options->segment_sz = options->max_buffer_size +
+ options->digest_sz;
+
+ if (options->segment_sz < options->digest_sz) {
+ RTE_LOG(ERR, USER1,
+ "Segment size should be at least "
+ "the size of the digest\n");
+ return -EINVAL;
+ }
+
+ if ((options->imix_distribution_count != 0) &&
+ (options->imix_distribution_count !=
+ options->buffer_size_count)) {
+ RTE_LOG(ERR, USER1, "IMIX distribution must have the same "
+ "number of buffer sizes\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->op_type != CPERF_CIPHER_ONLY &&
+ options->test_name == NULL) {
+ RTE_LOG(ERR, USER1, "Define test name to get the correct digest"
+ " from the test vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test_name != NULL && options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY &&
+ options->test_file == NULL) {
+ RTE_LOG(ERR, USER1, "Define path to the file with test"
+ " vectors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ (options->inc_buffer_size != 0 ||
+ options->buffer_size_count > 1)) {
+ RTE_LOG(ERR, USER1, "Only one buffer size is allowed when "
+ "using the verify test.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ (options->inc_burst_size != 0 ||
+ options->burst_size_count > 1)) {
+ RTE_LOG(ERR, USER1, "Only one burst size is allowed when "
+ "using the verify test.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_PMDCC &&
+ options->pool_sz < options->nb_descriptors) {
+ RTE_LOG(ERR, USER1, "For pmd cyclecount benchmarks, pool size "
+ "must be equal or greater than the number of "
+ "cryptodev descriptors.\n");
+ return -EINVAL;
+ }
+
+ if (options->test == CPERF_TEST_TYPE_VERIFY &&
+ options->imix_distribution_count > 0) {
+ RTE_LOG(ERR, USER1, "IMIX is not allowed when "
+ "using the verify test.\n");
+ return -EINVAL;
+ }
+
+ if (options->op_type == CPERF_CIPHER_THEN_AUTH) {
+ if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+ options->auth_op !=
+ RTE_CRYPTO_AUTH_OP_GENERATE) {
+ RTE_LOG(ERR, USER1, "Option cipher then auth must use"
+ " options: encrypt and generate.\n");
+ return -EINVAL;
+ }
+ } else if (options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (options->cipher_op != RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+ options->auth_op !=
+ RTE_CRYPTO_AUTH_OP_VERIFY) {
+ RTE_LOG(ERR, USER1, "Option auth then cipher must use"
+ " options: decrypt and verify.\n");
+ return -EINVAL;
+ }
+ }
+
+ if (options->op_type == CPERF_CIPHER_ONLY ||
+ options->op_type == CPERF_CIPHER_THEN_AUTH ||
+ options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (check_cipher_buffer_length(options) < 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void
+cperf_options_dump(struct cperf_options *opts)
+{
+ uint8_t size_idx;
+
+ printf("# Crypto Performance Application Options:\n");
+ printf("#\n");
+ printf("# cperf test: %s\n", cperf_test_type_strs[opts->test]);
+ printf("#\n");
+ printf("# size of crypto op / mbuf pool: %u\n", opts->pool_sz);
+ printf("# total number of ops: %u\n", opts->total_ops);
+ if (opts->inc_buffer_size != 0) {
+ printf("# buffer size:\n");
+ printf("#\t min: %u\n", opts->min_buffer_size);
+ printf("#\t max: %u\n", opts->max_buffer_size);
+ printf("#\t inc: %u\n", opts->inc_buffer_size);
+ } else {
+ printf("# buffer sizes: ");
+ for (size_idx = 0; size_idx < opts->buffer_size_count; size_idx++)
+ printf("%u ", opts->buffer_size_list[size_idx]);
+ printf("\n");
+ }
+ if (opts->inc_burst_size != 0) {
+ printf("# burst size:\n");
+ printf("#\t min: %u\n", opts->min_burst_size);
+ printf("#\t max: %u\n", opts->max_burst_size);
+ printf("#\t inc: %u\n", opts->inc_burst_size);
+ } else {
+ printf("# burst sizes: ");
+ for (size_idx = 0; size_idx < opts->burst_size_count; size_idx++)
+ printf("%u ", opts->burst_size_list[size_idx]);
+ printf("\n");
+ }
+ printf("\n# segment size: %u\n", opts->segment_sz);
+ printf("#\n");
+ printf("# cryptodev type: %s\n", opts->device_type);
+ printf("#\n");
+ printf("# number of queue pairs per device: %u\n", opts->nb_qps);
+ printf("# crypto operation: %s\n", cperf_op_type_strs[opts->op_type]);
+ printf("# sessionless: %s\n", opts->sessionless ? "yes" : "no");
+ printf("# out of place: %s\n", opts->out_of_place ? "yes" : "no");
+ if (opts->test == CPERF_TEST_TYPE_PMDCC)
+ printf("# inter-burst delay: %u ms\n", opts->pmdcc_delay);
+
+ printf("#\n");
+
+ if (opts->op_type == CPERF_AUTH_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+ printf("# auth algorithm: %s\n",
+ rte_crypto_auth_algorithm_strings[opts->auth_algo]);
+ printf("# auth operation: %s\n",
+ rte_crypto_auth_operation_strings[opts->auth_op]);
+ printf("# auth key size: %u\n", opts->auth_key_sz);
+ printf("# auth iv size: %u\n", opts->auth_iv_sz);
+ printf("# auth digest size: %u\n", opts->digest_sz);
+ printf("#\n");
+ }
+
+ if (opts->op_type == CPERF_CIPHER_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+ printf("# cipher algorithm: %s\n",
+ rte_crypto_cipher_algorithm_strings[opts->cipher_algo]);
+ printf("# cipher operation: %s\n",
+ rte_crypto_cipher_operation_strings[opts->cipher_op]);
+ printf("# cipher key size: %u\n", opts->cipher_key_sz);
+ printf("# cipher iv size: %u\n", opts->cipher_iv_sz);
+ printf("#\n");
+ }
+
+ if (opts->op_type == CPERF_AEAD) {
+ printf("# aead algorithm: %s\n",
+ rte_crypto_aead_algorithm_strings[opts->aead_algo]);
+ printf("# aead operation: %s\n",
+ rte_crypto_aead_operation_strings[opts->aead_op]);
+ printf("# aead key size: %u\n", opts->aead_key_sz);
+ printf("# aead iv size: %u\n", opts->aead_iv_sz);
+ printf("# aead digest size: %u\n", opts->digest_sz);
+ printf("# aead aad size: %u\n", opts->aead_aad_sz);
+ printf("#\n");
+ }
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.c
new file mode 100644
index 000000000..058e0ba56
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.c
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_mbuf_pool_ops.h>
+
+#include "cperf_test_common.h"
+
+struct obj_params {
+ uint32_t src_buf_offset;
+ uint32_t dst_buf_offset;
+ uint16_t segment_sz;
+ uint16_t headroom_sz;
+ uint16_t data_len;
+ uint16_t segments_nb;
+};
+
+static void
+fill_single_seg_mbuf(struct rte_mbuf *m, struct rte_mempool *mp,
+ void *obj, uint32_t mbuf_offset, uint16_t segment_sz,
+ uint16_t headroom, uint16_t data_len)
+{
+ uint32_t mbuf_hdr_size = sizeof(struct rte_mbuf);
+
+ /* start of buffer is after mbuf structure and priv data */
+ m->priv_size = 0;
+ m->buf_addr = (char *)m + mbuf_hdr_size;
+ m->buf_iova = rte_mempool_virt2iova(obj) +
+ mbuf_offset + mbuf_hdr_size;
+ m->buf_len = segment_sz;
+ m->data_len = data_len;
+ m->pkt_len = data_len;
+
+ /* Use headroom specified for the buffer */
+ m->data_off = headroom;
+
+ /* init some constant fields */
+ m->pool = mp;
+ m->nb_segs = 1;
+ m->port = 0xff;
+ rte_mbuf_refcnt_set(m, 1);
+ m->next = NULL;
+}
+
+static void
+fill_multi_seg_mbuf(struct rte_mbuf *m, struct rte_mempool *mp,
+ void *obj, uint32_t mbuf_offset, uint16_t segment_sz,
+ uint16_t headroom, uint16_t data_len, uint16_t segments_nb)
+{
+ uint16_t mbuf_hdr_size = sizeof(struct rte_mbuf);
+ uint16_t remaining_segments = segments_nb;
+ struct rte_mbuf *next_mbuf;
+ rte_iova_t next_seg_phys_addr = rte_mempool_virt2iova(obj) +
+ mbuf_offset + mbuf_hdr_size;
+
+ do {
+ /* start of buffer is after mbuf structure and priv data */
+ m->priv_size = 0;
+ m->buf_addr = (char *)m + mbuf_hdr_size;
+ m->buf_iova = next_seg_phys_addr;
+ next_seg_phys_addr += mbuf_hdr_size + segment_sz;
+ m->buf_len = segment_sz;
+ m->data_len = data_len;
+
+ /* Use headroom specified for the buffer */
+ m->data_off = headroom;
+
+ /* init some constant fields */
+ m->pool = mp;
+ m->nb_segs = segments_nb;
+ m->port = 0xff;
+ rte_mbuf_refcnt_set(m, 1);
+ next_mbuf = (struct rte_mbuf *) ((uint8_t *) m +
+ mbuf_hdr_size + segment_sz);
+ m->next = next_mbuf;
+ m = next_mbuf;
+ remaining_segments--;
+
+ } while (remaining_segments > 0);
+
+ m->next = NULL;
+}
+
+static void
+mempool_obj_init(struct rte_mempool *mp,
+ void *opaque_arg,
+ void *obj,
+ __rte_unused unsigned int i)
+{
+ struct obj_params *params = opaque_arg;
+ struct rte_crypto_op *op = obj;
+ struct rte_mbuf *m = (struct rte_mbuf *) ((uint8_t *) obj +
+ params->src_buf_offset);
+ /* Set crypto operation */
+ op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
+ op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
+ op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
+ op->phys_addr = rte_mem_virt2iova(obj);
+ op->mempool = mp;
+
+ /* Set source buffer */
+ op->sym->m_src = m;
+ if (params->segments_nb == 1)
+ fill_single_seg_mbuf(m, mp, obj, params->src_buf_offset,
+ params->segment_sz, params->headroom_sz,
+ params->data_len);
+ else
+ fill_multi_seg_mbuf(m, mp, obj, params->src_buf_offset,
+ params->segment_sz, params->headroom_sz,
+ params->data_len, params->segments_nb);
+
+
+ /* Set destination buffer */
+ if (params->dst_buf_offset) {
+ m = (struct rte_mbuf *) ((uint8_t *) obj +
+ params->dst_buf_offset);
+ fill_single_seg_mbuf(m, mp, obj, params->dst_buf_offset,
+ params->segment_sz, params->headroom_sz,
+ params->data_len);
+ op->sym->m_dst = m;
+ } else
+ op->sym->m_dst = NULL;
+}
+
+int
+cperf_alloc_common_memory(const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint8_t dev_id, uint16_t qp_id,
+ size_t extra_op_priv_size,
+ uint32_t *src_buf_offset,
+ uint32_t *dst_buf_offset,
+ struct rte_mempool **pool)
+{
+ const char *mp_ops_name;
+ char pool_name[32] = "";
+ int ret;
+
+ /* Calculate the object size */
+ uint16_t crypto_op_size = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+ uint16_t crypto_op_private_size;
+ /*
+ * If doing AES-CCM, IV field needs to be 16 bytes long,
+ * and AAD field needs to be long enough to have 18 bytes,
+ * plus the length of the AAD, and all rounded to a
+ * multiple of 16 bytes.
+ */
+ if (options->aead_algo == RTE_CRYPTO_AEAD_AES_CCM) {
+ crypto_op_private_size = extra_op_priv_size +
+ test_vector->cipher_iv.length +
+ test_vector->auth_iv.length +
+ RTE_ALIGN_CEIL(test_vector->aead_iv.length, 16) +
+ RTE_ALIGN_CEIL(options->aead_aad_sz + 18, 16);
+ } else {
+ crypto_op_private_size = extra_op_priv_size +
+ test_vector->cipher_iv.length +
+ test_vector->auth_iv.length +
+ test_vector->aead_iv.length +
+ options->aead_aad_sz;
+ }
+
+ uint16_t crypto_op_total_size = crypto_op_size +
+ crypto_op_private_size;
+ uint16_t crypto_op_total_size_padded =
+ RTE_CACHE_LINE_ROUNDUP(crypto_op_total_size);
+ uint32_t mbuf_size = sizeof(struct rte_mbuf) + options->segment_sz;
+ uint32_t max_size = options->max_buffer_size + options->digest_sz;
+ uint16_t segments_nb = (max_size % options->segment_sz) ?
+ (max_size / options->segment_sz) + 1 :
+ max_size / options->segment_sz;
+ uint32_t obj_size = crypto_op_total_size_padded +
+ (mbuf_size * segments_nb);
+
+ snprintf(pool_name, sizeof(pool_name), "pool_cdev_%u_qp_%u",
+ dev_id, qp_id);
+
+ *src_buf_offset = crypto_op_total_size_padded;
+
+ struct obj_params params = {
+ .segment_sz = options->segment_sz,
+ .headroom_sz = options->headroom_sz,
+ /* Data len = segment size - (headroom + tailroom) */
+ .data_len = options->segment_sz -
+ options->headroom_sz -
+ options->tailroom_sz,
+ .segments_nb = segments_nb,
+ .src_buf_offset = crypto_op_total_size_padded,
+ .dst_buf_offset = 0
+ };
+
+ if (options->out_of_place) {
+ *dst_buf_offset = *src_buf_offset +
+ (mbuf_size * segments_nb);
+ params.dst_buf_offset = *dst_buf_offset;
+ /* Destination buffer will be one segment only */
+ obj_size += max_size;
+ }
+
+ *pool = rte_mempool_create_empty(pool_name,
+ options->pool_sz, obj_size, 512, 0,
+ rte_socket_id(), 0);
+ if (*pool == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Cannot allocate mempool for device %u\n",
+ dev_id);
+ return -1;
+ }
+
+ mp_ops_name = rte_mbuf_best_mempool_ops();
+
+ ret = rte_mempool_set_ops_byname(*pool,
+ mp_ops_name, NULL);
+ if (ret != 0) {
+ RTE_LOG(ERR, USER1,
+ "Error setting mempool handler for device %u\n",
+ dev_id);
+ return -1;
+ }
+
+ ret = rte_mempool_populate_default(*pool);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Error populating mempool for device %u\n",
+ dev_id);
+ return -1;
+ }
+
+ rte_mempool_obj_iter(*pool, mempool_obj_init, (void *)&params);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.h
new file mode 100644
index 000000000..3ace0d2e5
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_common.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _CPERF_TEST_COMMON_H_
+#define _CPERF_TEST_COMMON_H_
+
+#include <stdint.h>
+
+#include <rte_mempool.h>
+
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+int
+cperf_alloc_common_memory(const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ uint8_t dev_id, uint16_t qp_id,
+ size_t extra_op_priv_size,
+ uint32_t *src_buf_offset,
+ uint32_t *dst_buf_offset,
+ struct rte_mempool **pool);
+
+#endif /* _CPERF_TEST_COMMON_H_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.c
new file mode 100644
index 000000000..0e4d0e153
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.c
@@ -0,0 +1,376 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_latency.h"
+#include "cperf_ops.h"
+#include "cperf_test_common.h"
+
+struct cperf_op_result {
+ uint64_t tsc_start;
+ uint64_t tsc_end;
+ enum rte_crypto_op_status status;
+};
+
+struct cperf_latency_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ uint32_t src_buf_offset;
+ uint32_t dst_buf_offset;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+ struct cperf_op_result *res;
+};
+
+struct priv_op_data {
+ struct cperf_op_result *result;
+};
+
+static void
+cperf_latency_test_free(struct cperf_latency_ctx *ctx)
+{
+ if (ctx) {
+ if (ctx->sess) {
+ rte_cryptodev_sym_session_clear(ctx->dev_id, ctx->sess);
+ rte_cryptodev_sym_session_free(ctx->sess);
+ }
+
+ if (ctx->pool)
+ rte_mempool_free(ctx->pool);
+
+ rte_free(ctx->res);
+ rte_free(ctx);
+ }
+}
+
+void *
+cperf_latency_test_constructor(struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_latency_ctx *ctx = NULL;
+ size_t extra_op_priv_size = sizeof(struct priv_op_data);
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_latency_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ /* IV goes at the end of the crypto operation */
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op) +
+ sizeof(struct cperf_op_result *);
+
+ ctx->sess = op_fns->sess_create(sess_mp, sess_priv_mp, dev_id, options,
+ test_vector, iv_offset);
+ if (ctx->sess == NULL)
+ goto err;
+
+ if (cperf_alloc_common_memory(options, test_vector, dev_id, qp_id,
+ extra_op_priv_size,
+ &ctx->src_buf_offset, &ctx->dst_buf_offset,
+ &ctx->pool) < 0)
+ goto err;
+
+ ctx->res = rte_malloc(NULL, sizeof(struct cperf_op_result) *
+ ctx->options->total_ops, 0);
+
+ if (ctx->res == NULL)
+ goto err;
+
+ return ctx;
+err:
+ cperf_latency_test_free(ctx);
+
+ return NULL;
+}
+
+static inline void
+store_timestamp(struct rte_crypto_op *op, uint64_t timestamp)
+{
+ struct priv_op_data *priv_data;
+
+ priv_data = (struct priv_op_data *) (op->sym + 1);
+ priv_data->result->status = op->status;
+ priv_data->result->tsc_end = timestamp;
+}
+
+int
+cperf_latency_test_runner(void *arg)
+{
+ struct cperf_latency_ctx *ctx = arg;
+ uint16_t test_burst_size;
+ uint8_t burst_size_idx = 0;
+ uint32_t imix_idx = 0;
+
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+
+ if (ctx == NULL)
+ return 0;
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+ uint64_t i;
+ struct priv_op_data *priv_data;
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ /* Warm up the host CPU before starting the test */
+ for (i = 0; i < ctx->options->total_ops; i++)
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* Get first size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size = ctx->options->min_burst_size;
+ else
+ test_burst_size = ctx->options->burst_size_list[0];
+
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op) +
+ sizeof(struct cperf_op_result *);
+
+ while (test_burst_size <= ctx->options->max_burst_size) {
+ uint64_t ops_enqd = 0, ops_deqd = 0;
+ uint64_t b_idx = 0;
+
+ uint64_t tsc_val, tsc_end, tsc_start;
+ uint64_t tsc_max = 0, tsc_min = ~0UL, tsc_tot = 0, tsc_idx = 0;
+ uint64_t enqd_max = 0, enqd_min = ~0UL, enqd_tot = 0;
+ uint64_t deqd_max = 0, deqd_min = ~0UL, deqd_tot = 0;
+
+ while (enqd_tot < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((enqd_tot + test_burst_size)
+ <= ctx->options->total_ops) ?
+ test_burst_size :
+ ctx->options->total_ops -
+ enqd_tot;
+
+ /* Allocate objects containing crypto operations and mbufs */
+ if (rte_mempool_get_bulk(ctx->pool, (void **)ops,
+ burst_size) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate more crypto operations "
+ "from the crypto operation pool.\n"
+ "Consider increasing the pool size "
+ "with --pool-sz\n");
+ return -1;
+ }
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, ctx->src_buf_offset,
+ ctx->dst_buf_offset,
+ burst_size, ctx->sess, ctx->options,
+ ctx->test_vector, iv_offset,
+ &imix_idx);
+
+ tsc_start = rte_rdtsc_precise();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ /* Free memory for not enqueued operations */
+ if (ops_enqd != burst_size)
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)&ops[ops_enqd],
+ burst_size - ops_enqd);
+
+ for (i = 0; i < ops_enqd; i++) {
+ ctx->res[tsc_idx].tsc_start = tsc_start;
+ /*
+ * Private data structure starts after the end of the
+ * rte_crypto_sym_op structure.
+ */
+ priv_data = (struct priv_op_data *) (ops[i]->sym + 1);
+ priv_data->result = (void *)&ctx->res[tsc_idx];
+ tsc_idx++;
+ }
+
+ if (likely(ops_deqd)) {
+ /* Free crypto ops so they can be reused. */
+ for (i = 0; i < ops_deqd; i++)
+ store_timestamp(ops_processed[i], tsc_end);
+
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+
+ deqd_tot += ops_deqd;
+ deqd_max = RTE_MAX(ops_deqd, deqd_max);
+ deqd_min = RTE_MIN(ops_deqd, deqd_min);
+ }
+
+ enqd_tot += ops_enqd;
+ enqd_max = RTE_MAX(ops_enqd, enqd_max);
+ enqd_min = RTE_MIN(ops_enqd, enqd_min);
+
+ b_idx++;
+ }
+
+ /* Dequeue any operations still in the crypto device */
+ while (deqd_tot < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ if (ops_deqd != 0) {
+ for (i = 0; i < ops_deqd; i++)
+ store_timestamp(ops_processed[i], tsc_end);
+
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+
+ deqd_tot += ops_deqd;
+ deqd_max = RTE_MAX(ops_deqd, deqd_max);
+ deqd_min = RTE_MIN(ops_deqd, deqd_min);
+ }
+ }
+
+ for (i = 0; i < tsc_idx; i++) {
+ tsc_val = ctx->res[i].tsc_end - ctx->res[i].tsc_start;
+ tsc_max = RTE_MAX(tsc_val, tsc_max);
+ tsc_min = RTE_MIN(tsc_val, tsc_min);
+ tsc_tot += tsc_val;
+ }
+
+ double time_tot, time_avg, time_max, time_min;
+
+ const uint64_t tunit = 1000000; /* us */
+ const uint64_t tsc_hz = rte_get_tsc_hz();
+
+ uint64_t enqd_avg = enqd_tot / b_idx;
+ uint64_t deqd_avg = deqd_tot / b_idx;
+ uint64_t tsc_avg = tsc_tot / tsc_idx;
+
+ time_tot = tunit*(double)(tsc_tot) / tsc_hz;
+ time_avg = tunit*(double)(tsc_avg) / tsc_hz;
+ time_max = tunit*(double)(tsc_max) / tsc_hz;
+ time_min = tunit*(double)(tsc_min) / tsc_hz;
+
+ if (ctx->options->csv) {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf("\n# lcore, Buffer Size, Burst Size, Pakt Seq #, "
+ "Packet Size, cycles, time (us)");
+
+ for (i = 0; i < ctx->options->total_ops; i++) {
+
+ printf("\n%u;%u;%u;%"PRIu64";%"PRIu64";%.3f",
+ ctx->lcore_id, ctx->options->test_buffer_size,
+ test_burst_size, i + 1,
+ ctx->res[i].tsc_end - ctx->res[i].tsc_start,
+ tunit * (double) (ctx->res[i].tsc_end
+ - ctx->res[i].tsc_start)
+ / tsc_hz);
+
+ }
+ } else {
+ printf("\n# Device %d on lcore %u\n", ctx->dev_id,
+ ctx->lcore_id);
+ printf("\n# total operations: %u", ctx->options->total_ops);
+ printf("\n# Buffer size: %u", ctx->options->test_buffer_size);
+ printf("\n# Burst size: %u", test_burst_size);
+ printf("\n# Number of bursts: %"PRIu64,
+ b_idx);
+
+ printf("\n#");
+ printf("\n# \t Total\t Average\t "
+ "Maximum\t Minimum");
+ printf("\n# enqueued\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, enqd_tot,
+ enqd_avg, enqd_max, enqd_min);
+ printf("\n# dequeued\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, deqd_tot,
+ deqd_avg, deqd_max, deqd_min);
+ printf("\n# cycles\t%12"PRIu64"\t%10"PRIu64"\t"
+ "%10"PRIu64"\t%10"PRIu64, tsc_tot,
+ tsc_avg, tsc_max, tsc_min);
+ printf("\n# time [us]\t%12.0f\t%10.3f\t%10.3f\t%10.3f",
+ time_tot, time_avg, time_max, time_min);
+ printf("\n\n");
+
+ }
+
+ /* Get next size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size += ctx->options->inc_burst_size;
+ else {
+ if (++burst_size_idx == ctx->options->burst_size_count)
+ break;
+ test_burst_size =
+ ctx->options->burst_size_list[burst_size_idx];
+ }
+ }
+
+ return 0;
+}
+
+void
+cperf_latency_test_destructor(void *arg)
+{
+ struct cperf_latency_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_latency_test_free(ctx);
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.h
new file mode 100644
index 000000000..ed5b0a07b
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_latency.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_LATENCY_
+#define _CPERF_LATENCY_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+void *
+cperf_latency_test_constructor(
+ struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id,
+ uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_latency_test_runner(void *test_ctx);
+
+void
+cperf_latency_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_LATENCY_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
new file mode 100644
index 000000000..74371faa8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <stdbool.h>
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+
+#include "cperf_ops.h"
+#include "cperf_test_pmd_cyclecount.h"
+#include "cperf_test_common.h"
+
+#define PRETTY_HDR_FMT "%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s\n\n"
+#define PRETTY_LINE_FMT "%12u%12u%12u%12u%12u%12u%12u%12.0f%12.0f%12.0f\n"
+#define CSV_HDR_FMT "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"
+#define CSV_LINE_FMT "%10u;%10u;%u;%u;%u;%u;%u;%.3f;%.3f;%.3f\n"
+
+struct cperf_pmd_cyclecount_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pool;
+ struct rte_crypto_op **ops;
+ struct rte_crypto_op **ops_processed;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ uint32_t src_buf_offset;
+ uint32_t dst_buf_offset;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+};
+
+struct pmd_cyclecount_state {
+ struct cperf_pmd_cyclecount_ctx *ctx;
+ const struct cperf_options *opts;
+ uint32_t lcore;
+ uint64_t delay;
+ int linearize;
+ uint32_t ops_enqd;
+ uint32_t ops_deqd;
+ uint32_t ops_enq_retries;
+ uint32_t ops_deq_retries;
+ double cycles_per_build;
+ double cycles_per_enq;
+ double cycles_per_deq;
+};
+
+static const uint16_t iv_offset =
+ sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op);
+
+static void
+cperf_pmd_cyclecount_test_free(struct cperf_pmd_cyclecount_ctx *ctx)
+{
+ if (ctx) {
+ if (ctx->sess) {
+ rte_cryptodev_sym_session_clear(ctx->dev_id, ctx->sess);
+ rte_cryptodev_sym_session_free(ctx->sess);
+ }
+
+ if (ctx->pool)
+ rte_mempool_free(ctx->pool);
+
+ if (ctx->ops)
+ rte_free(ctx->ops);
+
+ if (ctx->ops_processed)
+ rte_free(ctx->ops_processed);
+
+ rte_free(ctx);
+ }
+}
+
+void *
+cperf_pmd_cyclecount_test_constructor(struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_pmd_cyclecount_ctx *ctx = NULL;
+
+ /* preallocate buffers for crypto ops as they can get quite big */
+ size_t alloc_sz = sizeof(struct rte_crypto_op *) *
+ options->nb_descriptors;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_pmd_cyclecount_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ /* IV goes at the end of the crypto operation */
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+
+ ctx->sess = op_fns->sess_create(sess_mp, sess_priv_mp, dev_id, options,
+ test_vector, iv_offset);
+ if (ctx->sess == NULL)
+ goto err;
+
+ if (cperf_alloc_common_memory(options, test_vector, dev_id, qp_id, 0,
+ &ctx->src_buf_offset, &ctx->dst_buf_offset,
+ &ctx->pool) < 0)
+ goto err;
+
+ ctx->ops = rte_malloc("ops", alloc_sz, 0);
+ if (!ctx->ops)
+ goto err;
+
+ ctx->ops_processed = rte_malloc("ops_processed", alloc_sz, 0);
+ if (!ctx->ops_processed)
+ goto err;
+
+ return ctx;
+
+err:
+ cperf_pmd_cyclecount_test_free(ctx);
+
+ return NULL;
+}
+
+/* benchmark alloc-build-free of ops */
+static inline int
+pmd_cyclecount_bench_ops(struct pmd_cyclecount_state *state, uint32_t cur_op,
+ uint16_t test_burst_size)
+{
+ uint32_t iter_ops_left = state->opts->total_ops - cur_op;
+ uint32_t iter_ops_needed =
+ RTE_MIN(state->opts->nb_descriptors, iter_ops_left);
+ uint32_t cur_iter_op;
+ uint32_t imix_idx = 0;
+
+ for (cur_iter_op = 0; cur_iter_op < iter_ops_needed;
+ cur_iter_op += test_burst_size) {
+ uint32_t burst_size = RTE_MIN(iter_ops_needed - cur_iter_op,
+ test_burst_size);
+ struct rte_crypto_op **ops = &state->ctx->ops[cur_iter_op];
+
+ /* Allocate objects containing crypto operations and mbufs */
+ if (rte_mempool_get_bulk(state->ctx->pool, (void **)ops,
+ burst_size) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate more crypto operations "
+ "from the crypto operation pool.\n"
+ "Consider increasing the pool size "
+ "with --pool-sz\n");
+ return -1;
+ }
+
+ /* Setup crypto op, attach mbuf etc */
+ (state->ctx->populate_ops)(ops,
+ state->ctx->src_buf_offset,
+ state->ctx->dst_buf_offset,
+ burst_size,
+ state->ctx->sess, state->opts,
+ state->ctx->test_vector, iv_offset,
+ &imix_idx);
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ /* Check if source mbufs require coalescing */
+ if (state->linearize) {
+ uint8_t i;
+ for (i = 0; i < burst_size; i++) {
+ struct rte_mbuf *src = ops[i]->sym->m_src;
+ rte_pktmbuf_linearize(src);
+ }
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+ rte_mempool_put_bulk(state->ctx->pool, (void **)ops,
+ burst_size);
+ }
+
+ return 0;
+}
+
+/* allocate and build ops (no free) */
+static int
+pmd_cyclecount_build_ops(struct pmd_cyclecount_state *state,
+ uint32_t iter_ops_needed, uint16_t test_burst_size)
+{
+ uint32_t cur_iter_op;
+ uint32_t imix_idx = 0;
+
+ for (cur_iter_op = 0; cur_iter_op < iter_ops_needed;
+ cur_iter_op += test_burst_size) {
+ uint32_t burst_size = RTE_MIN(
+ iter_ops_needed - cur_iter_op, test_burst_size);
+ struct rte_crypto_op **ops = &state->ctx->ops[cur_iter_op];
+
+ /* Allocate objects containing crypto operations and mbufs */
+ if (rte_mempool_get_bulk(state->ctx->pool, (void **)ops,
+ burst_size) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate more crypto operations "
+ "from the crypto operation pool.\n"
+ "Consider increasing the pool size "
+ "with --pool-sz\n");
+ return -1;
+ }
+
+ /* Setup crypto op, attach mbuf etc */
+ (state->ctx->populate_ops)(ops,
+ state->ctx->src_buf_offset,
+ state->ctx->dst_buf_offset,
+ burst_size,
+ state->ctx->sess, state->opts,
+ state->ctx->test_vector, iv_offset,
+ &imix_idx);
+ }
+ return 0;
+}
+
+/* benchmark enqueue, returns number of ops enqueued */
+static uint32_t
+pmd_cyclecount_bench_enq(struct pmd_cyclecount_state *state,
+ uint32_t iter_ops_needed, uint16_t test_burst_size)
+{
+ /* Enqueue full descriptor ring of ops on crypto device */
+ uint32_t cur_iter_op = 0;
+ while (cur_iter_op < iter_ops_needed) {
+ uint32_t burst_size = RTE_MIN(iter_ops_needed - cur_iter_op,
+ test_burst_size);
+ struct rte_crypto_op **ops = &state->ctx->ops[cur_iter_op];
+ uint32_t burst_enqd;
+
+ burst_enqd = rte_cryptodev_enqueue_burst(state->ctx->dev_id,
+ state->ctx->qp_id, ops, burst_size);
+
+ /* if we couldn't enqueue anything, the queue is full */
+ if (!burst_enqd) {
+ /* don't try to dequeue anything we didn't enqueue */
+ return cur_iter_op;
+ }
+
+ if (burst_enqd < burst_size)
+ state->ops_enq_retries++;
+ state->ops_enqd += burst_enqd;
+ cur_iter_op += burst_enqd;
+ }
+ return iter_ops_needed;
+}
+
+/* benchmark dequeue */
+static void
+pmd_cyclecount_bench_deq(struct pmd_cyclecount_state *state,
+ uint32_t iter_ops_needed, uint16_t test_burst_size)
+{
+ /* Dequeue full descriptor ring of ops on crypto device */
+ uint32_t cur_iter_op = 0;
+ while (cur_iter_op < iter_ops_needed) {
+ uint32_t burst_size = RTE_MIN(iter_ops_needed - cur_iter_op,
+ test_burst_size);
+ struct rte_crypto_op **ops_processed =
+ &state->ctx->ops[cur_iter_op];
+ uint32_t burst_deqd;
+
+ burst_deqd = rte_cryptodev_dequeue_burst(state->ctx->dev_id,
+ state->ctx->qp_id, ops_processed, burst_size);
+
+ if (burst_deqd < burst_size)
+ state->ops_deq_retries++;
+ state->ops_deqd += burst_deqd;
+ cur_iter_op += burst_deqd;
+ }
+}
+
+/* run benchmark per burst size */
+static inline int
+pmd_cyclecount_bench_burst_sz(
+ struct pmd_cyclecount_state *state, uint16_t test_burst_size)
+{
+ uint64_t tsc_start;
+ uint64_t tsc_end;
+ uint64_t tsc_op;
+ uint64_t tsc_enq;
+ uint64_t tsc_deq;
+ uint32_t cur_op;
+
+ /* reset all counters */
+ tsc_enq = 0;
+ tsc_deq = 0;
+ state->ops_enqd = 0;
+ state->ops_enq_retries = 0;
+ state->ops_deqd = 0;
+ state->ops_deq_retries = 0;
+
+ /*
+ * Benchmark crypto op alloc-build-free separately.
+ */
+ tsc_start = rte_rdtsc_precise();
+
+ for (cur_op = 0; cur_op < state->opts->total_ops;
+ cur_op += state->opts->nb_descriptors) {
+ if (unlikely(pmd_cyclecount_bench_ops(
+ state, cur_op, test_burst_size)))
+ return -1;
+ }
+
+ tsc_end = rte_rdtsc_precise();
+ tsc_op = tsc_end - tsc_start;
+
+
+ /*
+ * Hardware acceleration cyclecount benchmarking loop.
+ *
+ * We're benchmarking raw enq/deq performance by filling up the device
+ * queue, so we never get any failed enqs unless the driver won't accept
+ * the exact number of descriptors we requested, or the driver won't
+ * wrap around the end of the TX ring. However, since we're only
+ * dequeueing once we've filled up the queue, we have to benchmark it
+ * piecemeal and then average out the results.
+ */
+ cur_op = 0;
+ while (cur_op < state->opts->total_ops) {
+ uint32_t iter_ops_left = state->opts->total_ops - cur_op;
+ uint32_t iter_ops_needed = RTE_MIN(
+ state->opts->nb_descriptors, iter_ops_left);
+ uint32_t iter_ops_allocd = iter_ops_needed;
+
+ /* allocate and build ops */
+ if (unlikely(pmd_cyclecount_build_ops(state, iter_ops_needed,
+ test_burst_size)))
+ return -1;
+
+ tsc_start = rte_rdtsc_precise();
+
+ /* fill up TX ring */
+ iter_ops_needed = pmd_cyclecount_bench_enq(state,
+ iter_ops_needed, test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ tsc_enq += tsc_end - tsc_start;
+
+ /* allow for HW to catch up */
+ if (state->delay)
+ rte_delay_us_block(state->delay);
+
+ tsc_start = rte_rdtsc_precise();
+
+ /* drain RX ring */
+ pmd_cyclecount_bench_deq(state, iter_ops_needed,
+ test_burst_size);
+
+ tsc_end = rte_rdtsc_precise();
+
+ tsc_deq += tsc_end - tsc_start;
+
+ cur_op += iter_ops_needed;
+
+ /*
+ * we may not have processed all ops that we allocated, so
+ * free everything we've allocated.
+ */
+ rte_mempool_put_bulk(state->ctx->pool,
+ (void **)state->ctx->ops, iter_ops_allocd);
+ }
+
+ state->cycles_per_build = (double)tsc_op / state->opts->total_ops;
+ state->cycles_per_enq = (double)tsc_enq / state->ops_enqd;
+ state->cycles_per_deq = (double)tsc_deq / state->ops_deqd;
+
+ return 0;
+}
+
+int
+cperf_pmd_cyclecount_test_runner(void *test_ctx)
+{
+ struct pmd_cyclecount_state state = {0};
+ const struct cperf_options *opts;
+ uint16_t test_burst_size;
+ uint8_t burst_size_idx = 0;
+
+ state.ctx = test_ctx;
+ opts = state.ctx->options;
+ state.opts = opts;
+ state.lcore = rte_lcore_id();
+ state.linearize = 0;
+
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+ static bool warmup = true;
+
+ /*
+ * We need a small delay to allow for hardware to process all the crypto
+ * operations. We can't automatically figure out what the delay should
+ * be, so we leave it up to the user (by default it's 0).
+ */
+ state.delay = 1000 * opts->pmdcc_delay;
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+
+ /* Check if source mbufs require coalescing */
+ if (opts->segments_sz < ctx->options->max_buffer_size) {
+ rte_cryptodev_info_get(state.ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) ==
+ 0) {
+ state.linearize = 1;
+ }
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ state.ctx->lcore_id = state.lcore;
+
+ /* Get first size from range or list */
+ if (opts->inc_burst_size != 0)
+ test_burst_size = opts->min_burst_size;
+ else
+ test_burst_size = opts->burst_size_list[0];
+
+ while (test_burst_size <= opts->max_burst_size) {
+ /* do a benchmark run */
+ if (pmd_cyclecount_bench_burst_sz(&state, test_burst_size))
+ return -1;
+
+ /*
+ * First run is always a warm up run.
+ */
+ if (warmup) {
+ warmup = false;
+ continue;
+ }
+
+ if (!opts->csv) {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf(PRETTY_HDR_FMT, "lcore id", "Buf Size",
+ "Burst Size", "Enqueued",
+ "Dequeued", "Enq Retries",
+ "Deq Retries", "Cycles/Op",
+ "Cycles/Enq", "Cycles/Deq");
+
+ printf(PRETTY_LINE_FMT, state.ctx->lcore_id,
+ opts->test_buffer_size, test_burst_size,
+ state.ops_enqd, state.ops_deqd,
+ state.ops_enq_retries,
+ state.ops_deq_retries,
+ state.cycles_per_build,
+ state.cycles_per_enq,
+ state.cycles_per_deq);
+ } else {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf(CSV_HDR_FMT, "# lcore id", "Buf Size",
+ "Burst Size", "Enqueued",
+ "Dequeued", "Enq Retries",
+ "Deq Retries", "Cycles/Op",
+ "Cycles/Enq", "Cycles/Deq");
+
+ printf(CSV_LINE_FMT, state.ctx->lcore_id,
+ opts->test_buffer_size, test_burst_size,
+ state.ops_enqd, state.ops_deqd,
+ state.ops_enq_retries,
+ state.ops_deq_retries,
+ state.cycles_per_build,
+ state.cycles_per_enq,
+ state.cycles_per_deq);
+ }
+
+ /* Get next size from range or list */
+ if (opts->inc_burst_size != 0)
+ test_burst_size += opts->inc_burst_size;
+ else {
+ if (++burst_size_idx == opts->burst_size_count)
+ break;
+ test_burst_size = opts->burst_size_list[burst_size_idx];
+ }
+ }
+
+ return 0;
+}
+
+void
+cperf_pmd_cyclecount_test_destructor(void *arg)
+{
+ struct cperf_pmd_cyclecount_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_pmd_cyclecount_test_free(ctx);
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.h
new file mode 100644
index 000000000..3084038a1
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _CPERF_TEST_PMD_CYCLECOUNT_H_
+#define _CPERF_TEST_PMD_CYCLECOUNT_H_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+void *
+cperf_pmd_cyclecount_test_constructor(
+ struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id,
+ uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_pmd_cyclecount_test_runner(void *test_ctx);
+
+void
+cperf_pmd_cyclecount_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_TEST_PMD_CYCLECOUNT_H_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.c
new file mode 100644
index 000000000..35c51026f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.c
@@ -0,0 +1,339 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_throughput.h"
+#include "cperf_ops.h"
+#include "cperf_test_common.h"
+
+struct cperf_throughput_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ uint32_t src_buf_offset;
+ uint32_t dst_buf_offset;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+};
+
+static void
+cperf_throughput_test_free(struct cperf_throughput_ctx *ctx)
+{
+ if (!ctx)
+ return;
+ if (ctx->sess) {
+#ifdef RTE_LIBRTE_SECURITY
+ if (ctx->options->op_type == CPERF_PDCP) {
+ struct rte_security_ctx *sec_ctx =
+ (struct rte_security_ctx *)
+ rte_cryptodev_get_sec_ctx(ctx->dev_id);
+ rte_security_session_destroy(sec_ctx,
+ (struct rte_security_session *)ctx->sess);
+ } else
+#endif
+ {
+ rte_cryptodev_sym_session_clear(ctx->dev_id, ctx->sess);
+ rte_cryptodev_sym_session_free(ctx->sess);
+ }
+ }
+ if (ctx->pool)
+ rte_mempool_free(ctx->pool);
+
+ rte_free(ctx);
+}
+
+void *
+cperf_throughput_test_constructor(struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_throughput_ctx *ctx = NULL;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_throughput_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ /* IV goes at the end of the crypto operation */
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+
+ ctx->sess = op_fns->sess_create(sess_mp, sess_priv_mp, dev_id, options,
+ test_vector, iv_offset);
+ if (ctx->sess == NULL)
+ goto err;
+
+ if (cperf_alloc_common_memory(options, test_vector, dev_id, qp_id, 0,
+ &ctx->src_buf_offset, &ctx->dst_buf_offset,
+ &ctx->pool) < 0)
+ goto err;
+
+ return ctx;
+err:
+ cperf_throughput_test_free(ctx);
+
+ return NULL;
+}
+
+int
+cperf_throughput_test_runner(void *test_ctx)
+{
+ struct cperf_throughput_ctx *ctx = test_ctx;
+ uint16_t test_burst_size;
+ uint8_t burst_size_idx = 0;
+ uint32_t imix_idx = 0;
+
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+ uint64_t i;
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ /* Warm up the host CPU before starting the test */
+ for (i = 0; i < ctx->options->total_ops; i++)
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* Get first size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size = ctx->options->min_burst_size;
+ else
+ test_burst_size = ctx->options->burst_size_list[0];
+
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+
+ while (test_burst_size <= ctx->options->max_burst_size) {
+ uint64_t ops_enqd = 0, ops_enqd_total = 0, ops_enqd_failed = 0;
+ uint64_t ops_deqd = 0, ops_deqd_total = 0, ops_deqd_failed = 0;
+
+ uint64_t tsc_start, tsc_end, tsc_duration;
+
+ uint16_t ops_unused = 0;
+
+ tsc_start = rte_rdtsc_precise();
+
+ while (ops_enqd_total < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((ops_enqd_total + test_burst_size)
+ <= ctx->options->total_ops) ?
+ test_burst_size :
+ ctx->options->total_ops -
+ ops_enqd_total;
+
+ uint16_t ops_needed = burst_size - ops_unused;
+
+ /* Allocate objects containing crypto operations and mbufs */
+ if (rte_mempool_get_bulk(ctx->pool, (void **)ops,
+ ops_needed) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate more crypto operations "
+ "from the crypto operation pool.\n"
+ "Consider increasing the pool size "
+ "with --pool-sz\n");
+ return -1;
+ }
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, ctx->src_buf_offset,
+ ctx->dst_buf_offset,
+ ops_needed, ctx->sess,
+ ctx->options, ctx->test_vector,
+ iv_offset, &imix_idx);
+
+ /**
+ * When ops_needed is smaller than ops_enqd, the
+ * unused ops need to be moved to the front for
+ * next round use.
+ */
+ if (unlikely(ops_enqd > ops_needed)) {
+ size_t nb_b_to_mov = ops_unused * sizeof(
+ struct rte_crypto_op *);
+
+ memmove(&ops[ops_needed], &ops[ops_enqd],
+ nb_b_to_mov);
+ }
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+ if (ops_enqd < burst_size)
+ ops_enqd_failed++;
+
+ /**
+ * Calculate number of ops not enqueued (mainly for hw
+ * accelerators whose ingress queue can fill up).
+ */
+ ops_unused = burst_size - ops_enqd;
+ ops_enqd_total += ops_enqd;
+
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+
+ if (likely(ops_deqd)) {
+ /* Free crypto ops so they can be reused. */
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+
+ ops_deqd_total += ops_deqd;
+ } else {
+ /**
+ * Count dequeue polls which didn't return any
+ * processed operations. This statistic is mainly
+ * relevant to hw accelerators.
+ */
+ ops_deqd_failed++;
+ }
+
+ }
+
+ /* Dequeue any operations still in the crypto device */
+
+ while (ops_deqd_total < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, test_burst_size);
+ if (ops_deqd == 0)
+ ops_deqd_failed++;
+ else {
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+ ops_deqd_total += ops_deqd;
+ }
+ }
+
+ tsc_end = rte_rdtsc_precise();
+ tsc_duration = (tsc_end - tsc_start);
+
+ /* Calculate average operations processed per second */
+ double ops_per_second = ((double)ctx->options->total_ops /
+ tsc_duration) * rte_get_tsc_hz();
+
+ /* Calculate average throughput (Gbps) in bits per second */
+ double throughput_gbps = ((ops_per_second *
+ ctx->options->test_buffer_size * 8) / 1000000000);
+
+ /* Calculate average cycles per packet */
+ double cycles_per_packet = ((double)tsc_duration /
+ ctx->options->total_ops);
+
+ if (!ctx->options->csv) {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf("%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s\n\n",
+ "lcore id", "Buf Size", "Burst Size",
+ "Enqueued", "Dequeued", "Failed Enq",
+ "Failed Deq", "MOps", "Gbps",
+ "Cycles/Buf");
+
+ printf("%12u%12u%12u%12"PRIu64"%12"PRIu64"%12"PRIu64
+ "%12"PRIu64"%12.4f%12.4f%12.2f\n",
+ ctx->lcore_id,
+ ctx->options->test_buffer_size,
+ test_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_per_second/1000000,
+ throughput_gbps,
+ cycles_per_packet);
+ } else {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf("#lcore id,Buffer Size(B),"
+ "Burst Size,Enqueued,Dequeued,Failed Enq,"
+ "Failed Deq,Ops(Millions),Throughput(Gbps),"
+ "Cycles/Buf\n\n");
+
+ printf("%u;%u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
+ "%.3f;%.3f;%.3f\n",
+ ctx->lcore_id,
+ ctx->options->test_buffer_size,
+ test_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_per_second/1000000,
+ throughput_gbps,
+ cycles_per_packet);
+ }
+
+ /* Get next size from range or list */
+ if (ctx->options->inc_burst_size != 0)
+ test_burst_size += ctx->options->inc_burst_size;
+ else {
+ if (++burst_size_idx == ctx->options->burst_size_count)
+ break;
+ test_burst_size = ctx->options->burst_size_list[burst_size_idx];
+ }
+
+ }
+
+ return 0;
+}
+
+
+void
+cperf_throughput_test_destructor(void *arg)
+{
+ struct cperf_throughput_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_throughput_test_free(ctx);
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.h
new file mode 100644
index 000000000..91e1a4b70
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_throughput.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_THROUGHPUT_
+#define _CPERF_THROUGHPUT_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+void *
+cperf_throughput_test_constructor(
+ struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id,
+ uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_throughput_test_runner(void *test_ctx);
+
+void
+cperf_throughput_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_THROUGHPUT_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c
new file mode 100644
index 000000000..1e9dfcfff
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.c
@@ -0,0 +1,591 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+#ifdef RTE_EXEC_ENV_FREEBSD
+ #define _WITH_GETLINE
+#endif
+#include <stdio.h>
+
+#include <rte_malloc.h>
+
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+#include "cperf_test_vector_parsing.h"
+
+int
+free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
+{
+ if (vector == NULL || opts == NULL)
+ return -1;
+
+ rte_free(vector->cipher_iv.data);
+ rte_free(vector->auth_iv.data);
+ rte_free(vector->aad.data);
+ rte_free(vector->digest.data);
+
+ if (opts->test_file != NULL) {
+ rte_free(vector->plaintext.data);
+ rte_free(vector->cipher_key.data);
+ rte_free(vector->auth_key.data);
+ rte_free(vector->ciphertext.data);
+ }
+
+ rte_free(vector);
+
+ return 0;
+}
+
+void
+show_test_vector(struct cperf_test_vector *test_vector)
+{
+ const uint8_t wrap = 32;
+ uint32_t i;
+
+ if (test_vector == NULL)
+ return;
+
+ if (test_vector->plaintext.data) {
+ printf("\nplaintext =\n");
+ for (i = 0; i < test_vector->plaintext.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == test_vector->plaintext.length - 1)
+ printf("0x%02x",
+ test_vector->plaintext.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->plaintext.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->cipher_key.data) {
+ printf("\ncipher_key =\n");
+ for (i = 0; i < test_vector->cipher_key.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->cipher_key.length - 1))
+ printf("0x%02x",
+ test_vector->cipher_key.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->cipher_key.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->auth_key.data) {
+ printf("\nauth_key =\n");
+ for (i = 0; i < test_vector->auth_key.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->auth_key.length - 1))
+ printf("0x%02x", test_vector->auth_key.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->auth_key.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->aead_key.data) {
+ printf("\naead_key =\n");
+ for (i = 0; i < test_vector->aead_key.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->aead_key.length - 1))
+ printf("0x%02x", test_vector->aead_key.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->aead_key.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->cipher_iv.data) {
+ printf("\ncipher_iv =\n");
+ for (i = 0; i < test_vector->cipher_iv.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->cipher_iv.length - 1))
+ printf("0x%02x", test_vector->cipher_iv.data[i]);
+ else
+ printf("0x%02x, ", test_vector->cipher_iv.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->auth_iv.data) {
+ printf("\nauth_iv =\n");
+ for (i = 0; i < test_vector->auth_iv.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->auth_iv.length - 1))
+ printf("0x%02x", test_vector->auth_iv.data[i]);
+ else
+ printf("0x%02x, ", test_vector->auth_iv.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->aead_iv.data) {
+ printf("\naead_iv =\n");
+ for (i = 0; i < test_vector->aead_iv.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->aead_iv.length - 1))
+ printf("0x%02x", test_vector->aead_iv.data[i]);
+ else
+ printf("0x%02x, ", test_vector->aead_iv.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->ciphertext.data) {
+ printf("\nciphertext =\n");
+ for (i = 0; i < test_vector->ciphertext.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == test_vector->ciphertext.length - 1)
+ printf("0x%02x",
+ test_vector->ciphertext.data[i]);
+ else
+ printf("0x%02x, ",
+ test_vector->ciphertext.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->aad.data) {
+ printf("\naad =\n");
+ for (i = 0; i < test_vector->aad.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->aad.length - 1))
+ printf("0x%02x", test_vector->aad.data[i]);
+ else
+ printf("0x%02x, ", test_vector->aad.data[i]);
+ }
+ printf("\n");
+ }
+
+ if (test_vector->digest.data) {
+ printf("\ndigest =\n");
+ for (i = 0; i < test_vector->digest.length; ++i) {
+ if ((i % wrap == 0) && (i != 0))
+ printf("\n");
+ if (i == (uint32_t)(test_vector->digest.length - 1))
+ printf("0x%02x", test_vector->digest.data[i]);
+ else
+ printf("0x%02x, ", test_vector->digest.data[i]);
+ }
+ printf("\n");
+ }
+}
+
+/* trim leading and trailing spaces */
+static char *
+trim_space(char *str)
+{
+ char *start, *end;
+
+ for (start = str; *start; start++) {
+ if (!isspace((unsigned char) start[0]))
+ break;
+ }
+
+ for (end = start + strlen(start); end > start + 1; end--) {
+ if (!isspace((unsigned char) end[-1]))
+ break;
+ }
+
+ *end = 0;
+
+ /* Shift from "start" to the beginning of the string */
+ if (start > str)
+ memmove(str, start, (end - start) + 1);
+
+ return str;
+}
+
+/* tokenization test values separated by a comma */
+static int
+parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
+{
+ uint32_t n_tokens;
+ uint32_t data_size = 32;
+
+ uint8_t *values, *values_resized;
+ char *tok, *error = NULL;
+
+ tok = strtok(tokens, CPERF_VALUE_DELIMITER);
+ if (tok == NULL)
+ return -1;
+
+ values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
+ if (values == NULL)
+ return -1;
+
+ n_tokens = 0;
+ while (tok != NULL) {
+ values_resized = NULL;
+
+ if (n_tokens >= data_size) {
+ data_size *= 2;
+
+ values_resized = (uint8_t *) rte_realloc(values,
+ sizeof(uint8_t) * data_size, 0);
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+ values = values_resized;
+ }
+
+ values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
+ if ((error == NULL) || (*error != '\0')) {
+ printf("Failed with convert '%s'\n", tok);
+ rte_free(values);
+ return -1;
+ }
+
+ tok = strtok(NULL, CPERF_VALUE_DELIMITER);
+ if (tok == NULL)
+ break;
+
+ n_tokens++;
+ }
+
+ values_resized = (uint8_t *) rte_realloc(values,
+ sizeof(uint8_t) * (n_tokens + 1), 0);
+
+ if (values_resized == NULL) {
+ rte_free(values);
+ return -1;
+ }
+
+ *data = values_resized;
+ *data_length = n_tokens + 1;
+
+ return 0;
+}
+
+/* checks the type of key and assigns data */
+static int
+parse_entry(char *entry, struct cperf_test_vector *vector,
+ struct cperf_options *opts, uint8_t tc_found)
+{
+ int status;
+ uint32_t data_length;
+
+ uint8_t *data = NULL;
+ char *token, *key_token;
+
+ if (entry == NULL) {
+ printf("Expected entry value\n");
+ return -1;
+ }
+
+ /* get key */
+ token = strtok(entry, CPERF_ENTRY_DELIMITER);
+ key_token = token;
+ /* get values for key */
+ token = strtok(NULL, CPERF_ENTRY_DELIMITER);
+
+ if (key_token == NULL || token == NULL) {
+ printf("Expected 'key = values' but was '%.40s'..\n", entry);
+ return -1;
+ }
+
+ status = parse_values(token, &data, &data_length);
+ if (status)
+ return -1;
+
+ /* compare keys */
+ if (strstr(key_token, "plaintext")) {
+ rte_free(vector->plaintext.data);
+ vector->plaintext.data = data;
+ if (tc_found)
+ vector->plaintext.length = data_length;
+ else {
+ if (opts->max_buffer_size > data_length) {
+ printf("Global plaintext shorter than "
+ "buffer_sz\n");
+ return -1;
+ }
+ vector->plaintext.length = opts->max_buffer_size;
+ }
+
+ } else if (strstr(key_token, "cipher_key")) {
+ rte_free(vector->cipher_key.data);
+ vector->cipher_key.data = data;
+ if (tc_found)
+ vector->cipher_key.length = data_length;
+ else {
+ if (opts->cipher_key_sz > data_length) {
+ printf("Global cipher_key shorter than "
+ "cipher_key_sz\n");
+ return -1;
+ }
+ vector->cipher_key.length = opts->cipher_key_sz;
+ }
+
+ } else if (strstr(key_token, "auth_key")) {
+ rte_free(vector->auth_key.data);
+ vector->auth_key.data = data;
+ if (tc_found)
+ vector->auth_key.length = data_length;
+ else {
+ if (opts->auth_key_sz > data_length) {
+ printf("Global auth_key shorter than "
+ "auth_key_sz\n");
+ return -1;
+ }
+ vector->auth_key.length = opts->auth_key_sz;
+ }
+
+ } else if (strstr(key_token, "aead_key")) {
+ rte_free(vector->aead_key.data);
+ vector->aead_key.data = data;
+ if (tc_found)
+ vector->aead_key.length = data_length;
+ else {
+ if (opts->aead_key_sz > data_length) {
+ printf("Global aead_key shorter than "
+ "aead_key_sz\n");
+ return -1;
+ }
+ vector->aead_key.length = opts->aead_key_sz;
+ }
+
+ } else if (strstr(key_token, "cipher_iv")) {
+ rte_free(vector->cipher_iv.data);
+ vector->cipher_iv.data = data;
+ if (tc_found)
+ vector->cipher_iv.length = data_length;
+ else {
+ if (opts->cipher_iv_sz > data_length) {
+ printf("Global cipher iv shorter than "
+ "cipher_iv_sz\n");
+ return -1;
+ }
+ vector->cipher_iv.length = opts->cipher_iv_sz;
+ }
+
+ } else if (strstr(key_token, "auth_iv")) {
+ rte_free(vector->auth_iv.data);
+ vector->auth_iv.data = data;
+ if (tc_found)
+ vector->auth_iv.length = data_length;
+ else {
+ if (opts->auth_iv_sz > data_length) {
+ printf("Global auth iv shorter than "
+ "auth_iv_sz\n");
+ return -1;
+ }
+ vector->auth_iv.length = opts->auth_iv_sz;
+ }
+
+ } else if (strstr(key_token, "aead_iv")) {
+ rte_free(vector->aead_iv.data);
+ vector->aead_iv.data = data;
+ if (tc_found)
+ vector->aead_iv.length = data_length;
+ else {
+ if (opts->aead_iv_sz > data_length) {
+ printf("Global aead iv shorter than "
+ "aead_iv_sz\n");
+ return -1;
+ }
+ vector->aead_iv.length = opts->aead_iv_sz;
+ }
+
+ } else if (strstr(key_token, "ciphertext")) {
+ rte_free(vector->ciphertext.data);
+ vector->ciphertext.data = data;
+ if (tc_found)
+ vector->ciphertext.length = data_length;
+ else {
+ if (opts->max_buffer_size > data_length) {
+ printf("Global ciphertext shorter than "
+ "buffer_sz\n");
+ return -1;
+ }
+ vector->ciphertext.length = opts->max_buffer_size;
+ }
+
+ } else if (strstr(key_token, "aad")) {
+ rte_free(vector->aad.data);
+ vector->aad.data = data;
+ vector->aad.phys_addr = rte_malloc_virt2iova(vector->aad.data);
+ if (tc_found)
+ vector->aad.length = data_length;
+ else {
+ if (opts->aead_aad_sz > data_length) {
+ printf("Global aad shorter than "
+ "aead_aad_sz\n");
+ return -1;
+ }
+ vector->aad.length = opts->aead_aad_sz;
+ }
+
+ } else if (strstr(key_token, "digest")) {
+ rte_free(vector->digest.data);
+ vector->digest.data = data;
+ vector->digest.phys_addr = rte_malloc_virt2iova(
+ vector->digest.data);
+ if (tc_found)
+ vector->digest.length = data_length;
+ else {
+ if (opts->digest_sz > data_length) {
+ printf("Global digest shorter than "
+ "digest_sz\n");
+ return -1;
+ }
+ vector->digest.length = opts->digest_sz;
+ }
+ } else {
+ printf("Not valid key: '%s'\n", trim_space(key_token));
+ return -1;
+ }
+
+ return 0;
+}
+
+/* searches in the file for test keys and values */
+static int
+parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
+{
+ uint8_t tc_found = 0;
+ uint8_t tc_data_start = 0;
+ ssize_t read;
+ size_t len = 0;
+ int status = 0;
+
+ FILE *fp;
+ char *line = NULL;
+ char *entry = NULL;
+
+ fp = fopen(opts->test_file, "r");
+ if (fp == NULL) {
+ printf("File %s does not exists\n", opts->test_file);
+ return -1;
+ }
+
+ while ((read = getline(&line, &len, fp)) != -1) {
+
+ /* ignore comments and new lines */
+ if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
+ || line[0] == '\r' || line[0] == ' ')
+ continue;
+
+ trim_space(line);
+
+ /* next test case is started */
+ if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
+ break;
+ /* test case section started, end of global data */
+ else if (line[0] == '[' && line[strlen(line) - 1] == ']')
+ tc_data_start = 1;
+
+ /* test name unspecified, end after global data */
+ if (tc_data_start && opts->test_name == NULL)
+ break;
+ /* searching for a suitable test */
+ else if (tc_data_start && tc_found == 0) {
+ if (!strcmp(line, opts->test_name)) {
+ tc_found = 1;
+ continue;
+ } else
+ continue;
+ }
+
+ /* buffer for multiline */
+ entry = (char *) rte_realloc(entry,
+ sizeof(char) * strlen(line) + 1, 0);
+ if (entry == NULL)
+ return -1;
+
+ strcpy(entry, line);
+
+ /* check if entry ends with , or = */
+ if (entry[strlen(entry) - 1] == ','
+ || entry[strlen(entry) - 1] == '=') {
+ while ((read = getline(&line, &len, fp)) != -1) {
+ trim_space(line);
+
+ /* extend entry about length of new line */
+ char *entry_extended = (char *) rte_realloc(
+ entry, sizeof(char)
+ * (strlen(line) + strlen(entry))
+ + 1, 0);
+
+ if (entry_extended == NULL)
+ goto err;
+ entry = entry_extended;
+ /* entry has been allocated accordingly */
+ strcpy(&entry[strlen(entry)], line);
+
+ if (entry[strlen(entry) - 1] != ',')
+ break;
+ }
+ }
+ status = parse_entry(entry, vector, opts, tc_found);
+ if (status) {
+ printf("An error occurred while parsing!\n");
+ goto err;
+ }
+ }
+
+ if (tc_found == 0 && opts->test_name != NULL) {
+ printf("Not found '%s' case in test file\n", opts->test_name);
+ goto err;
+ }
+
+ fclose(fp);
+ free(line);
+ rte_free(entry);
+
+ return 0;
+
+err:
+ if (fp)
+ fclose(fp);
+ if (line)
+ free(line);
+ if (entry)
+ rte_free(entry);
+
+ return -1;
+}
+
+struct cperf_test_vector*
+cperf_test_vector_get_from_file(struct cperf_options *opts)
+{
+ int status;
+ struct cperf_test_vector *test_vector = NULL;
+
+ if (opts == NULL || opts->test_file == NULL)
+ return test_vector;
+
+ test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
+ sizeof(struct cperf_test_vector), 0);
+ if (test_vector == NULL)
+ return test_vector;
+
+ /* filling the vector with data from a file */
+ status = parse_file(test_vector, opts);
+ if (status) {
+ free_test_vector(test_vector, opts);
+ return NULL;
+ }
+
+ /* other values not included in the file */
+ test_vector->data.cipher_offset = 0;
+ test_vector->data.cipher_length = opts->max_buffer_size;
+
+ test_vector->data.auth_offset = 0;
+ test_vector->data.auth_length = opts->max_buffer_size;
+
+ return test_vector;
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h
new file mode 100644
index 000000000..247b14221
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vector_parsing.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_
+#define APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_
+
+#define CPERF_VALUE_DELIMITER ","
+#define CPERF_ENTRY_DELIMITER "="
+
+/**
+ * Frees the allocated memory for test vector
+ *
+ * @param vector
+ * Destination vector test to release
+ * @param opts
+ * Test options
+ * @return
+ * 0 on success, (-1) on error.
+ */
+int
+free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts);
+
+/**
+ * Displays data in test vector
+ *
+ * @param vector
+ * Vector to display
+ */
+void
+show_test_vector(struct cperf_test_vector *test_vector);
+
+/**
+ * Completes test vector with data from file
+ *
+ * @param opts
+ * Test options
+ * @return
+ * NULL on error.
+ * Test vector pointer on successful.
+ */
+struct cperf_test_vector*
+cperf_test_vector_get_from_file(struct cperf_options *opts);
+
+#endif /* APP_CRYPTO_PERF_CPERF_TEST_VECTOR_PARSING_H_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.c
new file mode 100644
index 000000000..41641650c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.c
@@ -0,0 +1,591 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_crypto.h>
+#include <rte_malloc.h>
+
+#include "cperf_test_vectors.h"
+
+uint8_t plaintext[2048] = {
+ 0x71, 0x75, 0x83, 0x98, 0x75, 0x42, 0x51, 0x09, 0x94, 0x02, 0x13, 0x20,
+ 0x15, 0x64, 0x46, 0x32, 0x08, 0x18, 0x91, 0x82, 0x86, 0x52, 0x23, 0x93,
+ 0x44, 0x54, 0x28, 0x68, 0x78, 0x78, 0x70, 0x06, 0x42, 0x74, 0x41, 0x27,
+ 0x73, 0x38, 0x53, 0x77, 0x51, 0x96, 0x53, 0x24, 0x03, 0x88, 0x74, 0x14,
+ 0x70, 0x23, 0x88, 0x30, 0x85, 0x18, 0x89, 0x27, 0x41, 0x71, 0x61, 0x23,
+ 0x04, 0x83, 0x30, 0x57, 0x26, 0x47, 0x23, 0x75, 0x25, 0x62, 0x53, 0x80,
+ 0x38, 0x34, 0x21, 0x33, 0x34, 0x51, 0x46, 0x29, 0x94, 0x64, 0x22, 0x67,
+ 0x25, 0x45, 0x70, 0x26, 0x74, 0x39, 0x46, 0x71, 0x08, 0x85, 0x27, 0x18,
+ 0x93, 0x39, 0x72, 0x11, 0x57, 0x26, 0x88, 0x46, 0x47, 0x49, 0x86, 0x92,
+ 0x03, 0x37, 0x96, 0x40, 0x84, 0x53, 0x67, 0x47, 0x60, 0x60, 0x37, 0x67,
+ 0x02, 0x68, 0x76, 0x62, 0x42, 0x01, 0x59, 0x11, 0x01, 0x89, 0x40, 0x87,
+ 0x58, 0x20, 0x51, 0x21, 0x66, 0x26, 0x26, 0x73, 0x03, 0x06, 0x14, 0x25,
+ 0x98, 0x42, 0x44, 0x67, 0x24, 0x78, 0x71, 0x45, 0x32, 0x61, 0x20, 0x26,
+ 0x08, 0x88, 0x44, 0x26, 0x40, 0x63, 0x76, 0x23, 0x78, 0x55, 0x81, 0x97,
+ 0x95, 0x89, 0x39, 0x07, 0x14, 0x50, 0x50, 0x73, 0x07, 0x20, 0x86, 0x83,
+ 0x74, 0x57, 0x72, 0x36, 0x68, 0x61, 0x14, 0x41, 0x56, 0x49, 0x64, 0x72,
+ 0x75, 0x81, 0x47, 0x91, 0x08, 0x76, 0x47, 0x06, 0x55, 0x77, 0x61, 0x45,
+ 0x50, 0x10, 0x07, 0x46, 0x46, 0x89, 0x80, 0x07, 0x24, 0x95, 0x39, 0x43,
+ 0x03, 0x75, 0x24, 0x35, 0x57, 0x82, 0x09, 0x64, 0x29, 0x24, 0x26, 0x66,
+ 0x67, 0x29, 0x05, 0x90, 0x82, 0x02, 0x45, 0x71, 0x21, 0x34, 0x25, 0x48,
+ 0x68, 0x26, 0x01, 0x18, 0x73, 0x18, 0x46, 0x15, 0x14, 0x33, 0x28, 0x44,
+ 0x24, 0x82, 0x20, 0x12, 0x99, 0x43, 0x68, 0x43, 0x25, 0x14, 0x34, 0x33,
+ 0x31, 0x13, 0x77, 0x44, 0x95, 0x22, 0x99, 0x02, 0x30, 0x50, 0x74, 0x43,
+ 0x81, 0x78, 0x32, 0x17, 0x09, 0x85, 0x04, 0x37, 0x31, 0x98, 0x76, 0x79,
+ 0x64, 0x10, 0x39, 0x89, 0x59, 0x90, 0x50, 0x15, 0x77, 0x39, 0x28, 0x14,
+ 0x30, 0x19, 0x68, 0x77, 0x89, 0x48, 0x86, 0x16, 0x11, 0x33, 0x84, 0x56,
+ 0x10, 0x20, 0x94, 0x72, 0x41, 0x69, 0x13, 0x00, 0x56, 0x27, 0x01, 0x57,
+ 0x46, 0x65, 0x65, 0x19, 0x33, 0x07, 0x62, 0x19, 0x91, 0x60, 0x29, 0x11,
+ 0x41, 0x25, 0x88, 0x21, 0x93, 0x85, 0x87, 0x40, 0x91, 0x25, 0x32, 0x86,
+ 0x76, 0x54, 0x92, 0x52, 0x72, 0x46, 0x61, 0x84, 0x20, 0x14, 0x65, 0x83,
+ 0x69, 0x90, 0x80, 0x11, 0x35, 0x70, 0x42, 0x64, 0x74, 0x85, 0x15, 0x23,
+ 0x06, 0x55, 0x67, 0x49, 0x76, 0x47, 0x11, 0x95, 0x00, 0x85, 0x05, 0x12,
+ 0x58, 0x53, 0x25, 0x73, 0x62, 0x81, 0x63, 0x82, 0x32, 0x75, 0x16, 0x48,
+ 0x04, 0x96, 0x75, 0x16, 0x43, 0x83, 0x41, 0x85, 0x95, 0x67, 0x27, 0x83,
+ 0x22, 0x43, 0x02, 0x27, 0x69, 0x62, 0x78, 0x50, 0x57, 0x66, 0x99, 0x89,
+ 0x05, 0x06, 0x35, 0x86, 0x37, 0x27, 0x48, 0x46, 0x50, 0x80, 0x96, 0x40,
+ 0x42, 0x36, 0x21, 0x54, 0x49, 0x18, 0x63, 0x38, 0x45, 0x76, 0x23, 0x20,
+ 0x28, 0x06, 0x17, 0x32, 0x58, 0x50, 0x49, 0x54, 0x29, 0x46, 0x18, 0x12,
+ 0x17, 0x50, 0x02, 0x80, 0x99, 0x53, 0x15, 0x02, 0x07, 0x14, 0x19, 0x60,
+ 0x56, 0x43, 0x76, 0x71, 0x49, 0x99, 0x54, 0x83, 0x28, 0x94, 0x30, 0x30,
+ 0x57, 0x05, 0x89, 0x80, 0x11, 0x03, 0x78, 0x35, 0x73, 0x52, 0x67, 0x39,
+ 0x67, 0x07, 0x04, 0x49, 0x23, 0x83, 0x86, 0x89, 0x57, 0x71, 0x08, 0x41,
+ 0x15, 0x97, 0x19, 0x72, 0x03, 0x27, 0x72, 0x52, 0x66, 0x67, 0x99, 0x15,
+ 0x33, 0x64, 0x69, 0x78, 0x07, 0x83, 0x53, 0x71, 0x21, 0x50, 0x05, 0x48,
+ 0x59, 0x85, 0x01, 0x36, 0x65, 0x02, 0x52, 0x01, 0x09, 0x49, 0x28, 0x77,
+ 0x25, 0x35, 0x67, 0x77, 0x81, 0x64, 0x24, 0x29, 0x42, 0x32, 0x59, 0x22,
+ 0x93, 0x48, 0x59, 0x03, 0x85, 0x87, 0x15, 0x55, 0x23, 0x42, 0x58, 0x17,
+ 0x18, 0x37, 0x70, 0x83, 0x80, 0x12, 0x44, 0x83, 0x45, 0x70, 0x55, 0x86,
+ 0x03, 0x23, 0x01, 0x56, 0x94, 0x12, 0x41, 0x34, 0x82, 0x90, 0x83, 0x46,
+ 0x17, 0x56, 0x66, 0x96, 0x75, 0x80, 0x59, 0x07, 0x15, 0x84, 0x19, 0x52,
+ 0x37, 0x44, 0x44, 0x83, 0x72, 0x43, 0x25, 0x42, 0x26, 0x86, 0x87, 0x86,
+ 0x91, 0x62, 0x14, 0x90, 0x34, 0x26, 0x14, 0x33, 0x59, 0x70, 0x73, 0x15,
+ 0x49, 0x40, 0x66, 0x88, 0x42, 0x66, 0x16, 0x42, 0x55, 0x92, 0x82, 0x06,
+ 0x20, 0x96, 0x36, 0x96, 0x13, 0x07, 0x84, 0x94, 0x37, 0x66, 0x62, 0x78,
+ 0x60, 0x58, 0x80, 0x50, 0x69, 0x03, 0x97, 0x16, 0x64, 0x45, 0x21, 0x39,
+ 0x79, 0x28, 0x52, 0x17, 0x14, 0x77, 0x31, 0x60, 0x86, 0x70, 0x09, 0x53,
+ 0x39, 0x32, 0x52, 0x31, 0x35, 0x79, 0x24, 0x70, 0x25, 0x48, 0x23, 0x49,
+ 0x10, 0x64, 0x54, 0x30, 0x82, 0x34, 0x51, 0x20, 0x46, 0x04, 0x29, 0x25,
+ 0x65, 0x09, 0x55, 0x30, 0x30, 0x52, 0x85, 0x32, 0x79, 0x19, 0x59, 0x07,
+ 0x05, 0x12, 0x11, 0x03, 0x21, 0x90, 0x36, 0x62, 0x23, 0x67, 0x36, 0x67,
+ 0x47, 0x39, 0x92, 0x88, 0x45, 0x43, 0x71, 0x16, 0x48, 0x27, 0x68, 0x39,
+ 0x98, 0x38, 0x03, 0x31, 0x85, 0x10, 0x06, 0x95, 0x54, 0x79, 0x28, 0x79,
+ 0x56, 0x16, 0x65, 0x69, 0x00, 0x54, 0x09, 0x91, 0x06, 0x10, 0x10, 0x86,
+ 0x75, 0x01, 0x02, 0x71, 0x01, 0x09, 0x32, 0x94, 0x66, 0x43, 0x68, 0x36,
+ 0x19, 0x52, 0x02, 0x04, 0x45, 0x49, 0x40, 0x94, 0x07, 0x87, 0x86, 0x79,
+ 0x84, 0x07, 0x75, 0x30, 0x73, 0x02, 0x57, 0x81, 0x65, 0x02, 0x28, 0x96,
+ 0x57, 0x07, 0x70, 0x34, 0x39, 0x35, 0x75, 0x19, 0x47, 0x57, 0x08, 0x75,
+ 0x86, 0x57, 0x11, 0x32, 0x09, 0x47, 0x83, 0x93, 0x20, 0x94, 0x90, 0x88,
+ 0x39, 0x63, 0x22, 0x88, 0x54, 0x54, 0x95, 0x75, 0x67, 0x26, 0x02, 0x49,
+ 0x26, 0x17, 0x35, 0x16, 0x27, 0x65, 0x64, 0x26, 0x93, 0x92, 0x77, 0x85,
+ 0x84, 0x40, 0x59, 0x29, 0x49, 0x69, 0x94, 0x71, 0x72, 0x21, 0x55, 0x03,
+ 0x19, 0x74, 0x09, 0x40, 0x57, 0x68, 0x41, 0x19, 0x11, 0x21, 0x63, 0x56,
+ 0x29, 0x77, 0x57, 0x81, 0x44, 0x40, 0x76, 0x77, 0x02, 0x71, 0x66, 0x35,
+ 0x89, 0x02, 0x64, 0x51, 0x61, 0x02, 0x46, 0x91, 0x38, 0x93, 0x62, 0x57,
+ 0x18, 0x98, 0x12, 0x87, 0x29, 0x48, 0x65, 0x39, 0x99, 0x45, 0x54, 0x69,
+ 0x51, 0x16, 0x25, 0x75, 0x60, 0x70, 0x33, 0x72, 0x01, 0x60, 0x26, 0x51,
+ 0x44, 0x14, 0x39, 0x12, 0x95, 0x48, 0x87, 0x33, 0x90, 0x16, 0x42, 0x78,
+ 0x48, 0x58, 0x96, 0x93, 0x75, 0x23, 0x07, 0x13, 0x86, 0x07, 0x96, 0x30,
+ 0x22, 0x82, 0x91, 0x36, 0x72, 0x16, 0x48, 0x77, 0x64, 0x99, 0x07, 0x34,
+ 0x78, 0x60, 0x61, 0x13, 0x48, 0x93, 0x46, 0x62, 0x48, 0x38, 0x37, 0x96,
+ 0x58, 0x64, 0x39, 0x90, 0x69, 0x46, 0x81, 0x98, 0x61, 0x89, 0x15, 0x59,
+ 0x78, 0x98, 0x21, 0x34, 0x00, 0x69, 0x97, 0x80, 0x28, 0x81, 0x53, 0x49,
+ 0x79, 0x53, 0x92, 0x20, 0x29, 0x40, 0x70, 0x06, 0x09, 0x55, 0x99, 0x41,
+ 0x51, 0x35, 0x55, 0x27, 0x39, 0x06, 0x29, 0x83, 0x66, 0x03, 0x68, 0x14,
+ 0x11, 0x69, 0x95, 0x51, 0x71, 0x55, 0x24, 0x60, 0x52, 0x58, 0x88, 0x11,
+ 0x88, 0x25, 0x37, 0x86, 0x01, 0x52, 0x93, 0x52, 0x02, 0x24, 0x91, 0x58,
+ 0x56, 0x37, 0x50, 0x88, 0x39, 0x09, 0x61, 0x19, 0x08, 0x86, 0x29, 0x51,
+ 0x63, 0x38, 0x81, 0x14, 0x75, 0x75, 0x39, 0x99, 0x22, 0x04, 0x32, 0x63,
+ 0x14, 0x68, 0x41, 0x79, 0x09, 0x57, 0x87, 0x29, 0x26, 0x94, 0x05, 0x71,
+ 0x82, 0x41, 0x26, 0x98, 0x68, 0x18, 0x55, 0x42, 0x78, 0x05, 0x74, 0x17,
+ 0x34, 0x34, 0x07, 0x62, 0x94, 0x72, 0x21, 0x08, 0x54, 0x72, 0x21, 0x08,
+ 0x31, 0x53, 0x82, 0x35, 0x27, 0x40, 0x85, 0x77, 0x08, 0x52, 0x58, 0x48,
+ 0x03, 0x86, 0x65, 0x51, 0x96, 0x43, 0x89, 0x19, 0x15, 0x08, 0x49, 0x62,
+ 0x57, 0x46, 0x17, 0x68, 0x56, 0x04, 0x70, 0x63, 0x75, 0x88, 0x13, 0x27,
+ 0x87, 0x44, 0x46, 0x27, 0x02, 0x97, 0x71, 0x07, 0x40, 0x17, 0x24, 0x61,
+ 0x16, 0x94, 0x86, 0x85, 0x67, 0x58, 0x87, 0x92, 0x02, 0x84, 0x75, 0x19,
+ 0x43, 0x60, 0x68, 0x03, 0x54, 0x75, 0x33, 0x17, 0x97, 0x75, 0x12, 0x62,
+ 0x43, 0x08, 0x35, 0x75, 0x32, 0x21, 0x08, 0x82, 0x78, 0x04, 0x74, 0x09,
+ 0x13, 0x48, 0x63, 0x68, 0x67, 0x09, 0x08, 0x50, 0x11, 0x71, 0x64, 0x72,
+ 0x63, 0x76, 0x21, 0x62, 0x80, 0x57, 0x19, 0x15, 0x26, 0x88, 0x02, 0x26,
+ 0x83, 0x17, 0x61, 0x76, 0x28, 0x10, 0x22, 0x37, 0x56, 0x71, 0x51, 0x60,
+ 0x12, 0x79, 0x24, 0x83, 0x78, 0x47, 0x78, 0x20, 0x52, 0x27, 0x19, 0x88,
+ 0x81, 0x04, 0x70, 0x20, 0x25, 0x10, 0x04, 0x01, 0x72, 0x57, 0x30, 0x93,
+ 0x96, 0x23, 0x02, 0x94, 0x61, 0x44, 0x17, 0x65, 0x77, 0x60, 0x27, 0x43,
+ 0x24, 0x59, 0x46, 0x76, 0x00, 0x11, 0x31, 0x99, 0x41, 0x48, 0x75, 0x32,
+ 0x05, 0x15, 0x45, 0x31, 0x57, 0x89, 0x10, 0x47, 0x53, 0x14, 0x66, 0x54,
+ 0x60, 0x55, 0x36, 0x93, 0x30, 0x03, 0x63, 0x80, 0x65, 0x43, 0x17, 0x36,
+ 0x18, 0x64, 0x21, 0x38, 0x16, 0x19, 0x19, 0x51, 0x73, 0x80, 0x38, 0x27,
+ 0x30, 0x89, 0x13, 0x43, 0x54, 0x11, 0x78, 0x05, 0x24, 0x38, 0x83, 0x56,
+ 0x50, 0x59, 0x12, 0x47, 0x69, 0x70, 0x70, 0x91, 0x28, 0x02, 0x08, 0x91,
+ 0x66, 0x09, 0x31, 0x65, 0x46, 0x20, 0x04, 0x85, 0x89, 0x53, 0x91, 0x42,
+ 0x34, 0x09, 0x36, 0x92, 0x42, 0x06, 0x87, 0x88, 0x23, 0x54, 0x87, 0x85,
+ 0x52, 0x98, 0x95, 0x76, 0x13, 0x50, 0x59, 0x89, 0x18, 0x14, 0x17, 0x47,
+ 0x10, 0x97, 0x39, 0x14, 0x33, 0x79, 0x83, 0x62, 0x55, 0x18, 0x30, 0x83,
+ 0x03, 0x45, 0x38, 0x37, 0x35, 0x20, 0x94, 0x84, 0x89, 0x80, 0x89, 0x10,
+ 0x48, 0x77, 0x33, 0x36, 0x50, 0x07, 0x93, 0x02, 0x45, 0x42, 0x91, 0x12,
+ 0x98, 0x09, 0x77, 0x20, 0x31, 0x95, 0x10, 0x29, 0x89, 0x02, 0x38, 0x92,
+ 0x90, 0x19, 0x51, 0x10, 0x19, 0x82, 0x23, 0x68, 0x06, 0x00, 0x67, 0x50,
+ 0x25, 0x03, 0x41, 0x69, 0x53, 0x42, 0x23, 0x99, 0x29, 0x21, 0x63, 0x22,
+ 0x72, 0x54, 0x72, 0x40, 0x23, 0x39, 0x74, 0x92, 0x53, 0x28, 0x67, 0x56,
+ 0x46, 0x84, 0x59, 0x85, 0x10, 0x92, 0x31, 0x20, 0x39, 0x95, 0x65, 0x15,
+ 0x76, 0x35, 0x37, 0x21, 0x98, 0x41, 0x68, 0x74, 0x94, 0x94, 0x86, 0x90,
+ 0x35, 0x07, 0x06, 0x38, 0x78, 0x32, 0x00, 0x60, 0x86, 0x12, 0x34, 0x65,
+ 0x67, 0x35, 0x76, 0x94, 0x78, 0x22, 0x99, 0x42, 0x82, 0x40, 0x05, 0x74,
+ 0x18, 0x59, 0x03, 0x83, 0x89, 0x05, 0x19, 0x28, 0x88, 0x35, 0x59, 0x10,
+ 0x12, 0x96, 0x48, 0x67, 0x59, 0x87, 0x26, 0x85, 0x74, 0x64, 0x78, 0x56,
+ 0x91, 0x81, 0x45, 0x90, 0x21, 0x80, 0x32, 0x19, 0x61, 0x38, 0x61, 0x70,
+ 0x35, 0x08, 0x93, 0x53, 0x21, 0x95, 0x08, 0x27, 0x90, 0x28, 0x94, 0x27,
+ 0x35, 0x78, 0x03, 0x57, 0x74, 0x84, 0x73, 0x63, 0x27, 0x98, 0x14, 0x21,
+ 0x22, 0x36, 0x75, 0x31, 0x81, 0x65, 0x85, 0x51, 0x02, 0x45, 0x18, 0x06,
+ 0x39, 0x13, 0x29, 0x29, 0x73, 0x26, 0x99, 0x51, 0x38, 0x43, 0x35, 0x58,
+ 0x70, 0x92, 0x32, 0x13, 0x80, 0x16, 0x26, 0x44, 0x22, 0x28, 0x05, 0x45,
+ 0x86, 0x90, 0x38, 0x19, 0x40, 0x06, 0x30, 0x56, 0x94, 0x09, 0x02, 0x02,
+ 0x96, 0x29, 0x22, 0x44, 0x87, 0x38, 0x09, 0x95, 0x58, 0x46, 0x42, 0x78,
+ 0x72, 0x77, 0x86, 0x31, 0x97, 0x19, 0x86, 0x51, 0x73, 0x76, 0x63, 0x98,
+ 0x39, 0x40, 0x20, 0x20, 0x67, 0x42, 0x55, 0x50, 0x63, 0x76, 0x81, 0x87,
+ 0x13, 0x81, 0x19, 0x54, 0x11, 0x77, 0x90, 0x26, 0x47, 0x25, 0x92, 0x88,
+ 0x18, 0x56, 0x23, 0x73, 0x91, 0x52, 0x39, 0x08, 0x59, 0x51, 0x81, 0x57,
+ 0x78, 0x17, 0x13, 0x90, 0x90, 0x50, 0x65, 0x59, 0x99, 0x77, 0x42, 0x28,
+ 0x21, 0x59, 0x97, 0x64, 0x25, 0x17, 0x92, 0x24, 0x50, 0x00, 0x28, 0x40,
+ 0x85, 0x33, 0x78, 0x86, 0x79, 0x40, 0x28, 0x30, 0x14, 0x12, 0x01, 0x72,
+ 0x41, 0x43, 0x06, 0x87, 0x67, 0x31, 0x66, 0x77, 0x07, 0x50, 0x55, 0x50,
+ 0x22, 0x80, 0x42, 0x06, 0x38, 0x01, 0x63, 0x66, 0x70, 0x12, 0x52, 0x91,
+ 0x90, 0x97, 0x21, 0x28, 0x22, 0x65, 0x02, 0x80, 0x72, 0x31, 0x17, 0x76,
+ 0x35, 0x16, 0x03, 0x56, 0x59, 0x93, 0x36, 0x37, 0x67, 0x54, 0x46, 0x87,
+ 0x29, 0x01, 0x30, 0x80, 0x47, 0x47, 0x31, 0x98, 0x34, 0x30, 0x23, 0x86,
+ 0x86, 0x14, 0x05, 0x75, 0x09, 0x88, 0x77, 0x92, 0x59, 0x43, 0x98, 0x72,
+ 0x55, 0x54, 0x25, 0x59, 0x22, 0x27, 0x21, 0x62, 0x97, 0x10, 0x61, 0x73,
+ 0x86, 0x95, 0x99, 0x10, 0x62, 0x35, 0x25, 0x16, 0x62, 0x60, 0x51, 0x48,
+ 0x69, 0x69, 0x92, 0x27, 0x19, 0x43, 0x40, 0x52, 0x70, 0x23, 0x37, 0x28,
+ 0x73, 0x10, 0x32, 0x55, 0x85, 0x46, 0x97, 0x59, 0x88, 0x48, 0x54, 0x06,
+ 0x58, 0x04, 0x82, 0x98, 0x88, 0x34, 0x05, 0x41, 0x94, 0x44, 0x35, 0x10,
+ 0x96, 0x48, 0x21, 0x17, 0x24, 0x40, 0x26, 0x15, 0x49, 0x28, 0x12, 0x17,
+ 0x10, 0x17, 0x91, 0x42, 0x84, 0x15, 0x83, 0x36, 0x29, 0x49, 0x92, 0x77,
+ 0x74, 0x11, 0x72, 0x97, 0x64, 0x53, 0x23, 0x29, 0x16, 0x35, 0x22, 0x10,
+ 0x87, 0x07, 0x44, 0x78, 0x18, 0x19, 0x79, 0x03, 0x58, 0x24, 0x15, 0x63,
+ 0x55, 0x75, 0x56, 0x14, 0x63, 0x65, 0x86, 0x61, 0x92, 0x94, 0x30, 0x92,
+ 0x69, 0x78, 0x40, 0x95, 0x19, 0x81, 0x41, 0x66, 0x97, 0x00, 0x17, 0x37,
+ 0x20, 0x82, 0x14, 0x26, 0x42, 0x63, 0x84, 0x20, 0x96, 0x11, 0x68, 0x37,
+ 0x60, 0x28, 0x69, 0x85, 0x45, 0x04, 0x62, 0x20, 0x49, 0x39, 0x74, 0x84,
+ 0x60, 0x23, 0x38, 0x33, 0x42, 0x49, 0x38, 0x82, 0x30, 0x63, 0x21, 0x51,
+ 0x69, 0x09, 0x05, 0x55, 0x78, 0x90, 0x68, 0x69, 0x22, 0x20, 0x17, 0x26,
+ 0x54, 0x01, 0x10, 0x04, 0x68, 0x19, 0x88, 0x40, 0x91, 0x74, 0x81, 0x29,
+ 0x07, 0x45, 0x33, 0x77, 0x12, 0x47, 0x08, 0x60, 0x09, 0x42, 0x84, 0x15,
+ 0x63, 0x92, 0x64, 0x77, 0x07, 0x44, 0x11, 0x07, 0x79, 0x81, 0x24, 0x05,
+ 0x21, 0x60, 0x81, 0x70, 0x66, 0x36, 0x69, 0x68, 0x45, 0x01, 0x11, 0x95,
+ 0x67, 0x95, 0x55, 0x07, 0x96, 0x63, 0x84, 0x04, 0x74, 0x72, 0x61, 0x91,
+ 0x60, 0x09, 0x90, 0x14, 0x34, 0x94, 0x06, 0x12, 0x01, 0x94, 0x40, 0x14,
+ 0x12, 0x53, 0x64, 0x81, 0x75, 0x99, 0x36, 0x99, 0x11, 0x69, 0x95, 0x51,
+ 0x71, 0x55, 0x24, 0x60, 0x52, 0x58, 0x88, 0x11, 0x88, 0x25, 0x37, 0x86,
+ 0x66, 0x36, 0x69, 0x68, 0x45, 0x01, 0x11, 0x95
+};
+
+/* cipher text */
+uint8_t ciphertext[2048] = {
+ 0xE2, 0x19, 0x24, 0x56, 0x13, 0x59, 0xA6, 0x5D, 0xDF, 0xD0, 0x72, 0xAA,
+ 0x23, 0xC7, 0x36, 0x3A, 0xBB, 0x3E, 0x8B, 0x64, 0xD5, 0xBF, 0xDE, 0x65,
+ 0xA2, 0x75, 0xD9, 0x45, 0x6C, 0x3C, 0xD2, 0x6A, 0xC7, 0xD0, 0x9A, 0xD0,
+ 0x87, 0xB8, 0xE4, 0x94, 0x11, 0x62, 0x5A, 0xC3, 0xC3, 0x01, 0xA3, 0x86,
+ 0xBC, 0xBC, 0x9C, 0xC0, 0x81, 0x9F, 0xBF, 0x5C, 0x6F, 0x3F, 0x13, 0xF1,
+ 0xAE, 0xCF, 0x26, 0xB3, 0xBC, 0x49, 0xD6, 0x3B, 0x7A, 0x2E, 0x99, 0x9E,
+ 0x1B, 0x04, 0x50, 0x6C, 0x48, 0x6B, 0x4E, 0x72, 0xFC, 0xC8, 0xA7, 0x0C,
+ 0x2C, 0xD9, 0xED, 0xE4, 0x82, 0xC4, 0x81, 0xA6, 0xB4, 0xCC, 0xAD, 0x10,
+ 0xF3, 0x1C, 0x39, 0x05, 0x41, 0x2D, 0x57, 0x32, 0xE7, 0x16, 0xF8, 0x4D,
+ 0xF0, 0xDE, 0x40, 0x5B, 0x5F, 0x80, 0xDC, 0xA7, 0xC3, 0x2D, 0x3D, 0x9E,
+ 0x27, 0xD4, 0xE8, 0x10, 0x8E, 0xEB, 0xA5, 0x68, 0x6F, 0x3D, 0xC0, 0x44,
+ 0xE7, 0x77, 0x73, 0xB9, 0x92, 0x8E, 0xA2, 0x26, 0x5C, 0x6F, 0x33, 0x4B,
+ 0x0B, 0xEF, 0x37, 0x55, 0xBE, 0xEC, 0x98, 0x83, 0x1E, 0xDF, 0xB2, 0x9E,
+ 0x5D, 0x1D, 0x78, 0x14, 0xD7, 0x85, 0x0E, 0xF8, 0x12, 0x30, 0x8E, 0x5D,
+ 0x08, 0x77, 0x0B, 0x2E, 0x9B, 0xF9, 0xA6, 0x72, 0xD2, 0x41, 0xC1, 0x8E,
+ 0x6B, 0x5E, 0x11, 0x85, 0x22, 0x6E, 0xE4, 0xA3, 0xEA, 0x4C, 0x91, 0xE1,
+ 0x7D, 0xD0, 0xEB, 0x9F, 0xD9, 0xD7, 0x05, 0x77, 0xD9, 0xA1, 0xC2, 0xFD,
+ 0x41, 0x63, 0x51, 0xB4, 0x7A, 0x1F, 0x21, 0xF0, 0xBF, 0x11, 0x4D, 0x9B,
+ 0x97, 0xAB, 0xB4, 0x94, 0x36, 0x34, 0xC9, 0x2D, 0x8B, 0xE2, 0x61, 0xCF,
+ 0xAF, 0x69, 0xD5, 0x5C, 0xE9, 0xED, 0xE3, 0xA0, 0x69, 0xD3, 0xE5, 0xAE,
+ 0x67, 0x6C, 0xC7, 0x11, 0xB1, 0x21, 0x96, 0xD6, 0xDB, 0xA8, 0x1D, 0xC9,
+ 0x83, 0x0B, 0xE2, 0xC6, 0x6E, 0x94, 0xE9, 0x50, 0x12, 0x9B, 0x01, 0x72,
+ 0xAA, 0xFD, 0x8B, 0x7C, 0xEC, 0x0D, 0x01, 0xA4, 0x5D, 0x00, 0xE9, 0x79,
+ 0x58, 0xF5, 0x67, 0xF9, 0x61, 0xC3, 0x11, 0xB4, 0x7E, 0x76, 0x0A, 0x4C,
+ 0x60, 0xD6, 0xBD, 0xC8, 0x31, 0xD3, 0x0C, 0xD0, 0x5B, 0xDF, 0x7B, 0x05,
+ 0x9A, 0xBB, 0xC6, 0x2E, 0x9F, 0xF8, 0x18, 0x80, 0x6D, 0x1B, 0x21, 0xE5,
+ 0xAC, 0x75, 0xBC, 0x0D, 0x72, 0x51, 0x61, 0xD7, 0xEA, 0xA2, 0xAC, 0x0E,
+ 0xC1, 0xE7, 0x49, 0x37, 0xE7, 0x7C, 0xDE, 0xBD, 0x56, 0x00, 0x44, 0x6D,
+ 0xAB, 0x81, 0x2B, 0x26, 0x4A, 0xAA, 0x60, 0xE6, 0x43, 0x8D, 0x88, 0x1C,
+ 0x48, 0x55, 0x53, 0x25, 0xE8, 0x3C, 0x46, 0xF0, 0xA6, 0x33, 0x2D, 0xA2,
+ 0xDC, 0x99, 0x57, 0x38, 0x59, 0xCF, 0x53, 0xFA, 0x3E, 0x78, 0x46, 0xA0,
+ 0xA9, 0x50, 0x12, 0x72, 0xAC, 0x15, 0xC6, 0xA7, 0x42, 0x0F, 0x59, 0x6E,
+ 0xEA, 0xB0, 0x3D, 0xB8, 0x94, 0x32, 0xD1, 0xB6, 0xE8, 0x90, 0x06, 0x66,
+ 0x0C, 0xDE, 0xA9, 0x35, 0xC7, 0xDD, 0x72, 0x42, 0x38, 0x33, 0x32, 0x2F,
+ 0x2C, 0x3F, 0xBD, 0x01, 0xD6, 0x47, 0xFC, 0x89, 0x31, 0x38, 0x2E, 0xB9,
+ 0x6B, 0xED, 0xDB, 0x85, 0x38, 0xB1, 0xA5, 0x50, 0xFA, 0xFB, 0xA7, 0x31,
+ 0xEC, 0xB6, 0xBB, 0x82, 0x50, 0xB4, 0x88, 0x5C, 0xED, 0xE5, 0x4B, 0x5B,
+ 0xBF, 0xB3, 0x18, 0xFB, 0xAD, 0x24, 0x41, 0x55, 0x80, 0xCD, 0xA3, 0xA1,
+ 0xD6, 0xD5, 0xB6, 0x06, 0xE9, 0x85, 0x12, 0x33, 0x52, 0x56, 0xF1, 0xB7,
+ 0xDC, 0x57, 0x9E, 0xB4, 0x00, 0x1E, 0xCB, 0x62, 0x13, 0x4C, 0x90, 0x9A,
+ 0x9D, 0x64, 0x80, 0xD1, 0x5E, 0xB3, 0xCB, 0x8A, 0x73, 0x4E, 0x7B, 0xBE,
+ 0x4D, 0xA7, 0xF7, 0xB7, 0x9C, 0x1C, 0x7F, 0x27, 0x1E, 0x7F, 0x58, 0xB2,
+ 0x74, 0xAF, 0x94, 0x0E, 0x19, 0x23, 0xE1, 0x6B, 0xD8, 0x20, 0x4F, 0x2C,
+ 0x13, 0xE8, 0x8C, 0x37, 0x46, 0x27, 0x55, 0x68, 0xDA, 0x3F, 0x7A, 0xC6,
+ 0xEF, 0x87, 0x1D, 0x3B, 0x95, 0x43, 0x5E, 0x75, 0xE0, 0x02, 0x22, 0x0E,
+ 0x11, 0x60, 0xAB, 0x1A, 0x91, 0x94, 0xC4, 0xFA, 0xD9, 0x92, 0x2B, 0xE5,
+ 0x03, 0xE0, 0x7A, 0x17, 0x5C, 0x67, 0x22, 0xB3, 0xCB, 0x77, 0x9E, 0x22,
+ 0x01, 0x5F, 0x5D, 0x64, 0xE4, 0x2F, 0xC4, 0x61, 0xCA, 0xC7, 0xFD, 0x20,
+ 0x24, 0x30, 0xAB, 0x3F, 0x1A, 0x08, 0x85, 0x08, 0x39, 0xDE, 0x19, 0x1C,
+ 0x1A, 0xEA, 0xB8, 0x7E, 0xE5, 0xBC, 0xD9, 0xB2, 0x59, 0xC8, 0x81, 0x02,
+ 0x1D, 0x5C, 0xC0, 0xDD, 0x8D, 0x56, 0xB6, 0x2E, 0x85, 0x26, 0xA8, 0x34,
+ 0x92, 0x36, 0x9A, 0x84, 0xBD, 0x27, 0xC1, 0x9D, 0x5E, 0x14, 0xC4, 0xB7,
+ 0x02, 0xA8, 0xC9, 0xC2, 0xAD, 0xDC, 0x98, 0x42, 0x51, 0xDE, 0x94, 0x28,
+ 0x39, 0xEF, 0xE9, 0x7F, 0x05, 0x3F, 0x1D, 0x67, 0x72, 0x04, 0xCF, 0x7D,
+ 0x38, 0x49, 0xC4, 0x59, 0xA5, 0xF6, 0xB6, 0x02, 0x31, 0xD0, 0x05, 0x74,
+ 0x4B, 0xD0, 0x89, 0xD1, 0x7F, 0xC6, 0xDB, 0x7E, 0x75, 0x62, 0xA3, 0xC2,
+ 0x2E, 0xB0, 0xCC, 0x9A, 0xD3, 0xA4, 0x14, 0xB6, 0xF2, 0x91, 0x44, 0x3F,
+ 0x84, 0xE0, 0x90, 0x4A, 0x6A, 0x34, 0x8C, 0x35, 0x3C, 0xB2, 0xA9, 0x35,
+ 0x88, 0xB0, 0x88, 0xF8, 0x7E, 0x5C, 0xD2, 0x08, 0x5E, 0x08, 0x15, 0x03,
+ 0xBC, 0xF5, 0x42, 0x6B, 0x28, 0xED, 0xDD, 0xAA, 0x4D, 0x78, 0x10, 0x31,
+ 0x32, 0xA2, 0xC5, 0xCA, 0xEE, 0x9A, 0x62, 0x52, 0x3E, 0x48, 0x83, 0xA4,
+ 0xCA, 0xD4, 0xC7, 0xA7, 0xA5, 0x3F, 0x44, 0x1C, 0x86, 0xAD, 0x52, 0x7D,
+ 0x80, 0x1D, 0x9E, 0x32, 0x3F, 0x2A, 0x2E, 0xD8, 0x89, 0xC1, 0xA4, 0xD6,
+ 0xC1, 0x90, 0x2E, 0x1A, 0x20, 0x4B, 0x87, 0x32, 0x35, 0x25, 0xD8, 0xB8,
+ 0x57, 0x15, 0x85, 0x1E, 0x3C, 0x8A, 0xDC, 0x1A, 0x49, 0x3D, 0x70, 0x35,
+ 0x99, 0xAA, 0xDE, 0x2C, 0xD4, 0xAF, 0x79, 0x72, 0xAB, 0x97, 0x84, 0x20,
+ 0xB6, 0x4F, 0x34, 0x3F, 0xEA, 0xAE, 0x5F, 0x8F, 0x3A, 0x42, 0xDB, 0x68,
+ 0xE5, 0x84, 0x63, 0x2E, 0x7A, 0x0E, 0xBD, 0x28, 0x6A, 0x24, 0xB6, 0xAB,
+ 0xE4, 0xAC, 0x20, 0x7C, 0x81, 0xD0, 0x69, 0x89, 0xF8, 0xDE, 0xA9, 0x02,
+ 0xFD, 0x1F, 0x08, 0xDA, 0x26, 0xC2, 0x24, 0xCA, 0xEB, 0x44, 0x16, 0x8D,
+ 0x55, 0x5F, 0xB9, 0xA9, 0x5A, 0x18, 0x50, 0xB1, 0x54, 0xF1, 0xBF, 0x06,
+ 0xC2, 0xB0, 0x95, 0xC2, 0xAE, 0xE5, 0xBF, 0xB3, 0xFD, 0xC9, 0xBF, 0x75,
+ 0x42, 0x7D, 0xA0, 0xA8, 0x95, 0xF9, 0x62, 0x3B, 0x9C, 0x0D, 0x81, 0xF3,
+ 0x9C, 0xFC, 0x19, 0x5B, 0xF7, 0xD1, 0x9C, 0xF0, 0xAA, 0xFE, 0xEF, 0x35,
+ 0x1E, 0x81, 0x9E, 0x02, 0x46, 0x52, 0x9B, 0x99, 0x0D, 0x12, 0x8B, 0x71,
+ 0x6C, 0x32, 0xB5, 0x23, 0x17, 0x03, 0xC5, 0xB0, 0xA1, 0xC3, 0x4B, 0x10,
+ 0x01, 0x4D, 0x4C, 0x4A, 0x46, 0x8F, 0xD9, 0x79, 0xBB, 0x10, 0x44, 0xB0,
+ 0x3C, 0x7D, 0x46, 0xFD, 0x38, 0xDF, 0xAF, 0x6E, 0x58, 0x7D, 0xE1, 0xEB,
+ 0xBB, 0x8C, 0xDC, 0x79, 0xDA, 0x41, 0xD1, 0x8B, 0x0B, 0x11, 0x4F, 0xE5,
+ 0x1C, 0xC1, 0x59, 0xA7, 0x1E, 0x5A, 0xC1, 0xEE, 0x27, 0x33, 0xC8, 0x55,
+ 0xA9, 0x32, 0xEA, 0xF7, 0x45, 0xB0, 0x08, 0xE9, 0x32, 0xDF, 0x70, 0x24,
+ 0x82, 0xD3, 0x2A, 0x3E, 0x4F, 0x42, 0xB9, 0x25, 0x10, 0xD1, 0x73, 0xFA,
+ 0xFD, 0xC1, 0x84, 0xF2, 0xF7, 0x0E, 0xBC, 0x9D, 0x90, 0x39, 0xD7, 0xFD,
+ 0x45, 0x77, 0xBA, 0x29, 0xF9, 0x87, 0x45, 0xC1, 0x32, 0x44, 0xB0, 0x27,
+ 0x6B, 0xFC, 0x8A, 0xFE, 0x00, 0x6F, 0x61, 0x98, 0xD0, 0x60, 0xC8, 0x10,
+ 0xE5, 0xBC, 0x88, 0x13, 0x45, 0x44, 0xA5, 0xEB, 0x6E, 0xCB, 0x11, 0xAF,
+ 0x30, 0xDC, 0x8B, 0xF8, 0x30, 0x46, 0xDA, 0x76, 0xF1, 0xE5, 0x14, 0x51,
+ 0x8A, 0x02, 0x5A, 0x5A, 0xAA, 0x7B, 0x2D, 0x57, 0x0A, 0x5C, 0x73, 0xD1,
+ 0x88, 0xCE, 0xBE, 0x3D, 0x06, 0x3F, 0x48, 0x1D, 0x44, 0x24, 0x6F, 0x4F,
+ 0x7F, 0x6A, 0xF2, 0x16, 0x34, 0x35, 0x38, 0x73, 0x8A, 0xE5, 0x25, 0xF4,
+ 0x34, 0x9E, 0x5B, 0x40, 0x90, 0x04, 0x57, 0x1B, 0x57, 0x75, 0x8F, 0xEA,
+ 0x1C, 0xF8, 0x7A, 0x68, 0x01, 0x1C, 0x8D, 0xBA, 0xF4, 0xE3, 0xD3, 0x8F,
+ 0x7F, 0xE4, 0x50, 0x35, 0x6B, 0x6B, 0xF6, 0xFC, 0x5F, 0x9B, 0x98, 0x78,
+ 0x16, 0x68, 0x72, 0x74, 0x71, 0x78, 0x25, 0x68, 0xE5, 0x1E, 0x66, 0xE2,
+ 0x4E, 0xC8, 0xDB, 0x92, 0x8E, 0x88, 0x64, 0x74, 0xDE, 0xDB, 0x85, 0x56,
+ 0x9F, 0xF9, 0xC4, 0x29, 0x54, 0xA8, 0xFB, 0xBA, 0xEA, 0xAB, 0xC7, 0x49,
+ 0x5C, 0x6C, 0xD7, 0x61, 0x8C, 0xE2, 0x2B, 0xF5, 0xA0, 0xA8, 0xD2, 0x41,
+ 0xC0, 0x54, 0xAB, 0xA7, 0x56, 0x5C, 0xE7, 0xA5, 0xEA, 0xBC, 0x47, 0xD1,
+ 0x0D, 0xD9, 0xC0, 0xA9, 0xC4, 0xA7, 0x3E, 0xD1, 0x2B, 0x1E, 0x34, 0x31,
+ 0x36, 0x9D, 0xB9, 0x51, 0xD3, 0xAD, 0x29, 0xE6, 0x9B, 0xD8, 0x4B, 0x93,
+ 0x33, 0x2F, 0x30, 0xEF, 0x18, 0x90, 0x69, 0x11, 0x09, 0xEA, 0xBA, 0xE0,
+ 0x10, 0x93, 0x63, 0x71, 0xA8, 0x83, 0x59, 0xDB, 0xFC, 0x12, 0x22, 0x84,
+ 0xC7, 0x01, 0x20, 0x99, 0xEC, 0x59, 0xA9, 0xE6, 0x9B, 0x5B, 0x8B, 0xB8,
+ 0x68, 0x52, 0x61, 0x8B, 0x4E, 0xF3, 0x50, 0x69, 0xF1, 0x49, 0x9B, 0xAF,
+ 0x53, 0xAD, 0xA0, 0x9D, 0x23, 0xE0, 0xE0, 0xC4, 0x31, 0xE4, 0x8E, 0x1C,
+ 0x51, 0x14, 0xFC, 0x95, 0x9C, 0xA6, 0x34, 0x85, 0xB0, 0x36, 0xFC, 0x7A,
+ 0x53, 0x03, 0x31, 0x0E, 0xCB, 0x34, 0x3E, 0xDF, 0xD1, 0x71, 0xBC, 0xDB,
+ 0xA1, 0xAF, 0x59, 0x4A, 0x03, 0x19, 0xA7, 0x8E, 0xB5, 0x82, 0x15, 0x24,
+ 0x69, 0x68, 0xBD, 0x9C, 0x2E, 0xFA, 0x06, 0xB5, 0x70, 0xC5, 0x70, 0xC4,
+ 0x14, 0x99, 0x01, 0x49, 0xBD, 0x6E, 0xAE, 0x10, 0xA1, 0xE4, 0xEF, 0xDD,
+ 0xE5, 0x51, 0x22, 0x9D, 0xF7, 0x93, 0xAB, 0x41, 0xBD, 0x86, 0x7A, 0xCC,
+ 0x51, 0x94, 0xEC, 0x22, 0xBE, 0x0D, 0x67, 0xFD, 0xA3, 0xFD, 0xCF, 0xF8,
+ 0x74, 0x0A, 0x5E, 0x1C, 0x71, 0xAD, 0xB6, 0xD0, 0xD7, 0xF8, 0x71, 0x34,
+ 0xAB, 0x62, 0xE7, 0xA8, 0x6B, 0x8F, 0x1E, 0x43, 0x46, 0xA5, 0xE4, 0xB4,
+ 0x52, 0x81, 0x66, 0xB3, 0xE5, 0x10, 0x23, 0x21, 0x2B, 0x31, 0x0F, 0xB8,
+ 0xB6, 0xC5, 0xA5, 0xC9, 0x90, 0x07, 0x83, 0xD0, 0xC3, 0x10, 0x7A, 0x04,
+ 0xBD, 0x8A, 0x3C, 0x7B, 0xF9, 0x0E, 0x51, 0x81, 0x96, 0xC8, 0xAE, 0xF9,
+ 0x27, 0xDE, 0x62, 0x7A, 0x41, 0x60, 0x35, 0x8F, 0x77, 0xBC, 0x95, 0x11,
+ 0x2C, 0xC4, 0x6C, 0x47, 0x7A, 0xEB, 0x29, 0xE5, 0x8E, 0xB5, 0xD6, 0xA5,
+ 0x54, 0x1B, 0xD0, 0xE0, 0x0F, 0x7D, 0x5C, 0x51, 0xD8, 0x6C, 0x92, 0x2F,
+ 0x13, 0x4E, 0x90, 0x77, 0xF8, 0x8D, 0x69, 0x78, 0x96, 0x96, 0x49, 0x9F,
+ 0x3C, 0x2E, 0x5C, 0xA6, 0x73, 0x27, 0x7D, 0xAD, 0x8D, 0xE3, 0x9B, 0x4A,
+ 0x2F, 0x50, 0x0A, 0x42, 0x7E, 0xF2, 0x3B, 0x50, 0x5C, 0x81, 0xC9, 0x49,
+ 0x01, 0x96, 0x83, 0x0A, 0xEC, 0x7F, 0xED, 0x1C, 0xA5, 0x7D, 0xF1, 0xE6,
+ 0xC4, 0xB3, 0x8F, 0xF9, 0x0F, 0xDB, 0x7B, 0xC1, 0x35, 0xF7, 0x63, 0x4A,
+ 0x39, 0xD4, 0x0E, 0x9E, 0x05, 0xD9, 0x42, 0xAA, 0xAB, 0x52, 0xCA, 0x4E,
+ 0x98, 0x3B, 0x43, 0x1A, 0x91, 0x25, 0xA9, 0x34, 0xD5, 0x66, 0xB2, 0xF4,
+ 0xFF, 0xDE, 0x64, 0x91, 0x90, 0xB9, 0x17, 0x70, 0xA0, 0xD6, 0xEA, 0xB6,
+ 0x36, 0xF4, 0x44, 0xCE, 0x86, 0x7B, 0x18, 0x74, 0x9C, 0x18, 0xAD, 0xB6,
+ 0xE0, 0x74, 0xC1, 0x0E, 0x29, 0x5D, 0x6A, 0x36, 0xD1, 0x3E, 0xB8, 0x2A,
+ 0xE4, 0x23, 0x1D, 0xB2, 0xAE, 0xF5, 0x5B, 0x8E, 0x2C, 0xD9, 0xD1, 0xE1,
+ 0x4F, 0x58, 0xA6, 0xE3, 0x88, 0x2E, 0xF9, 0xCF, 0x32, 0x3E, 0x8E, 0x37,
+ 0x95, 0xFF, 0xAD, 0x68, 0x11, 0x5E, 0x7F, 0x3D, 0x38, 0x06, 0x7C, 0x33,
+ 0x32, 0x78, 0x09, 0xEC, 0xCA, 0x3E, 0x08, 0xF1, 0xD0, 0x95, 0x19, 0xC9,
+ 0x7E, 0x62, 0xB2, 0x02, 0xA3, 0x5D, 0xF8, 0x3F, 0xA2, 0xB0, 0x8B, 0x38,
+ 0xB1, 0x8C, 0xEA, 0xB3, 0xE4, 0xBF, 0xD3, 0x6C, 0x6D, 0x3D, 0xD1, 0xC6,
+ 0xDA, 0x6B, 0x7A, 0xBA, 0x05, 0xEA, 0x9E, 0xA5, 0xE9, 0x00, 0xCC, 0x80,
+ 0x57, 0xAB, 0xD9, 0x0A, 0xD1, 0x00, 0x82, 0x2A, 0x51, 0x4B, 0xA2, 0x96,
+ 0xEB, 0x96, 0x14, 0xA8, 0x46, 0xDF, 0x1D, 0x48, 0xAE, 0xFA, 0x12, 0xA8,
+ 0x89, 0x8E, 0xEF, 0xBC, 0x3C, 0xA1, 0x6E, 0xDD, 0x90, 0x66, 0x2E, 0x56,
+ 0x6B, 0xF7, 0x1D, 0xF0, 0x46, 0x11, 0x4A, 0xA6, 0x07, 0x73, 0xC4, 0xE3,
+ 0x97, 0xFE, 0x7E, 0x22, 0x6F, 0x22, 0xB4, 0x6F, 0xB0, 0x32, 0x0A, 0x5E,
+ 0x85, 0x7E, 0x54, 0xB4, 0x24, 0xBD, 0x36, 0xA7, 0x94, 0xE7, 0x37, 0xFD,
+ 0x1A, 0xAF, 0xF4, 0x44, 0xB4, 0x35, 0x4F, 0xE0, 0x41, 0x0E, 0x7D, 0x73,
+ 0x29, 0x28, 0xDA, 0xAF, 0x69, 0xB2, 0xC5, 0xA7, 0x2A, 0x0A, 0xB5, 0x9C,
+ 0xC2, 0xAC, 0x5F, 0x59, 0x5C, 0xEE, 0x44, 0x49, 0x6F, 0x4F, 0x64, 0x43,
+ 0x6F, 0x43, 0x44, 0xAA, 0xA0, 0x4E, 0x94, 0x7C, 0x26, 0x5A, 0xF1, 0xD9,
+ 0xE6, 0x09, 0x80, 0x7A, 0x7D, 0x2E, 0xA2, 0xB9, 0x1A, 0x7A, 0x8F, 0x2A,
+ 0x97, 0x77, 0x23, 0xB4, 0x10, 0xAD, 0x20, 0x7B, 0xA3, 0x0F, 0xFD, 0x44,
+ 0x38, 0xAD, 0x94, 0x39, 0x88, 0x1C, 0xC4, 0xC8, 0xDF, 0xF1, 0x04, 0xA6,
+ 0x51, 0x5D, 0x54, 0x53, 0x60, 0xE4, 0x8A, 0x89, 0x4A, 0x9C, 0xE1, 0x68,
+ 0x4D, 0xFE, 0x69, 0x94, 0x0B, 0x8E, 0xED, 0x6C, 0xFE, 0x11, 0xA7, 0x77,
+ 0xBF, 0x08, 0x41, 0x67, 0x22, 0x59, 0x51, 0x48, 0xEE, 0x59, 0x02, 0x0E,
+ 0x60, 0x6D, 0xAE, 0x8C, 0xC6, 0x39, 0xB7, 0x55, 0xC5, 0x3B, 0x87, 0xA9,
+ 0xBD, 0xD8, 0xEA, 0x48, 0x21, 0xE4, 0x57, 0x51, 0x56, 0x03, 0xF4, 0xBE,
+ 0xBD, 0xBD, 0xC5, 0x26, 0x9B, 0x27, 0xE3, 0xAE, 0xD5, 0x1E, 0x30, 0xE9,
+ 0x7C, 0x9D, 0xDB, 0xE1, 0x09, 0x9D, 0x82, 0x49, 0x15, 0x38, 0x69, 0xFC,
+ 0x1D, 0x52, 0x1A, 0x75, 0xE6, 0xDD, 0x1D, 0xBE, 0x06, 0xC4, 0x9F, 0x14,
+ 0x4C, 0x12, 0xDE, 0xDF, 0x4A, 0xE1, 0x3B, 0xE7, 0xD1, 0xE3, 0x71, 0xD1,
+ 0xFA, 0xD8, 0x0E, 0x63, 0x27, 0xA9, 0xC7, 0x9D, 0xC0, 0x01, 0xC2, 0xDD,
+ 0xFC, 0xA6, 0x1F, 0x59, 0x87, 0xC5, 0x56, 0x99, 0x80, 0xEB, 0xF0, 0xB8,
+ 0xB3, 0x00, 0x9A, 0x61, 0xDB, 0x50, 0x79, 0x48, 0x37, 0x35, 0xDA, 0xD8,
+ 0xF2, 0x37, 0xA7, 0x43, 0xA7, 0xEB, 0x88, 0x2C, 0x68, 0xB4, 0xBB, 0x14,
+ 0x45, 0x31, 0x6B, 0x87, 0x65, 0xE7, 0x82, 0xB4, 0x74, 0xD2, 0xFF, 0x7F,
+ 0x60, 0x15, 0x94, 0x75, 0xEE, 0x30, 0x3C, 0x4E, 0xFC, 0x41, 0xD1, 0x5B,
+ 0xDD, 0x84, 0x6E, 0x13, 0x6C, 0xF8, 0x12, 0xE6, 0xB7, 0xA4, 0xB9, 0xC8,
+ 0x13, 0x89, 0x0C, 0x34, 0xA6, 0xAF, 0x09, 0xEB, 0xF2, 0xB3, 0x79, 0x77,
+ 0x80, 0xD8, 0x77, 0x64, 0xAD, 0x32, 0x3D, 0xD2, 0x06, 0xDF, 0x72, 0x11,
+ 0x4A, 0xA7, 0x70, 0xCE, 0xF9, 0xE6, 0x81, 0x35, 0xA4, 0xA7, 0x52, 0xB5,
+ 0x13, 0x68, 0x5C, 0x69, 0x45, 0xE2, 0x77, 0x2D, 0xBE, 0x2C, 0xE9, 0x38,
+ 0x25, 0x28, 0x7B, 0x63, 0x2C, 0x19, 0x8F, 0x59
+};
+
+/* aad */
+uint8_t aad[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
+};
+
+/* iv */
+uint8_t iv[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+/* cipher key */
+uint8_t cipher_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+};
+
+/* auth key */
+uint8_t auth_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+ 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
+};
+
+/* AEAD key */
+uint8_t aead_key[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+};
+
+/* Digests */
+uint8_t digest[2048] = { 0x00 };
+
+struct cperf_test_vector*
+cperf_test_vector_get_dummy(struct cperf_options *options)
+{
+ struct cperf_test_vector *t_vec;
+
+ t_vec = (struct cperf_test_vector *)rte_malloc(NULL,
+ sizeof(struct cperf_test_vector), 0);
+ if (t_vec == NULL)
+ return t_vec;
+
+ t_vec->plaintext.data = plaintext;
+ t_vec->plaintext.length = options->max_buffer_size;
+
+ if (options->op_type == CPERF_PDCP) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ t_vec->cipher_key.length = 0;
+ t_vec->ciphertext.data = plaintext;
+ t_vec->cipher_key.data = NULL;
+ } else {
+ t_vec->cipher_key.length = options->cipher_key_sz;
+ t_vec->ciphertext.data = ciphertext;
+ t_vec->cipher_key.data = cipher_key;
+ }
+
+ /* Init IV data ptr */
+ t_vec->cipher_iv.data = NULL;
+
+ if (options->cipher_iv_sz != 0) {
+ /* Set IV parameters */
+ t_vec->cipher_iv.data = rte_malloc(NULL,
+ options->cipher_iv_sz, 16);
+ if (t_vec->cipher_iv.data == NULL) {
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->cipher_iv.data, iv, options->cipher_iv_sz);
+ }
+ t_vec->ciphertext.length = options->max_buffer_size;
+ t_vec->cipher_iv.length = options->cipher_iv_sz;
+ t_vec->data.cipher_offset = 0;
+ t_vec->data.cipher_length = options->max_buffer_size;
+ if (options->auth_algo == RTE_CRYPTO_AUTH_NULL) {
+ t_vec->auth_key.length = 0;
+ t_vec->auth_key.data = NULL;
+ t_vec->digest.data = NULL;
+ t_vec->digest.length = 0;
+ } else {
+ t_vec->auth_key.length = options->auth_key_sz;
+ t_vec->auth_key.data = auth_key;
+
+ t_vec->digest.data = rte_malloc(NULL,
+ options->digest_sz,
+ 16);
+ if (t_vec->digest.data == NULL) {
+ rte_free(t_vec->cipher_iv.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ t_vec->digest.phys_addr =
+ rte_malloc_virt2iova(t_vec->digest.data);
+ t_vec->digest.length = options->digest_sz;
+ memcpy(t_vec->digest.data, digest,
+ options->digest_sz);
+ }
+ t_vec->data.auth_offset = 0;
+ t_vec->data.auth_length = options->max_buffer_size;
+ }
+
+ if (options->op_type == CPERF_CIPHER_ONLY ||
+ options->op_type == CPERF_CIPHER_THEN_AUTH ||
+ options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ t_vec->cipher_key.length = 0;
+ t_vec->ciphertext.data = plaintext;
+ t_vec->cipher_key.data = NULL;
+ } else {
+ t_vec->cipher_key.length = options->cipher_key_sz;
+ t_vec->ciphertext.data = ciphertext;
+ t_vec->cipher_key.data = cipher_key;
+ }
+
+ /* Init IV data ptr */
+ t_vec->cipher_iv.data = NULL;
+
+ if (options->cipher_iv_sz != 0) {
+ /* Set IV parameters */
+ t_vec->cipher_iv.data = rte_malloc(NULL,
+ options->cipher_iv_sz, 16);
+ if (t_vec->cipher_iv.data == NULL) {
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->cipher_iv.data, iv, options->cipher_iv_sz);
+ }
+ t_vec->ciphertext.length = options->max_buffer_size;
+ t_vec->cipher_iv.length = options->cipher_iv_sz;
+ t_vec->data.cipher_offset = 0;
+ t_vec->data.cipher_length = options->max_buffer_size;
+
+ }
+
+ if (options->op_type == CPERF_AUTH_ONLY ||
+ options->op_type == CPERF_CIPHER_THEN_AUTH ||
+ options->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (options->auth_algo == RTE_CRYPTO_AUTH_NULL) {
+ t_vec->auth_key.length = 0;
+ t_vec->auth_key.data = NULL;
+ t_vec->digest.data = NULL;
+ t_vec->digest.length = 0;
+ } else {
+ t_vec->auth_key.length = options->auth_key_sz;
+ t_vec->auth_key.data = auth_key;
+
+ t_vec->digest.data = rte_malloc(NULL,
+ options->digest_sz,
+ 16);
+ if (t_vec->digest.data == NULL) {
+ rte_free(t_vec->cipher_iv.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ t_vec->digest.phys_addr =
+ rte_malloc_virt2iova(t_vec->digest.data);
+ t_vec->digest.length = options->digest_sz;
+ memcpy(t_vec->digest.data, digest,
+ options->digest_sz);
+ }
+ t_vec->data.auth_offset = 0;
+ t_vec->data.auth_length = options->max_buffer_size;
+
+ /* Set IV parameters */
+ t_vec->auth_iv.data = rte_malloc(NULL, options->auth_iv_sz,
+ 16);
+ if (options->auth_iv_sz && t_vec->auth_iv.data == NULL) {
+ if (options->op_type != CPERF_AUTH_ONLY)
+ rte_free(t_vec->cipher_iv.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->auth_iv.data, iv, options->auth_iv_sz);
+ t_vec->auth_iv.length = options->auth_iv_sz;
+ }
+
+ if (options->op_type == CPERF_AEAD) {
+ t_vec->aead_key.length = options->aead_key_sz;
+ t_vec->aead_key.data = aead_key;
+
+ if (options->aead_aad_sz) {
+ t_vec->aad.data = rte_malloc(NULL,
+ options->aead_aad_sz, 16);
+ if (t_vec->aad.data == NULL) {
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->aad.data, aad, options->aead_aad_sz);
+ t_vec->aad.phys_addr = rte_malloc_virt2iova(t_vec->aad.data);
+ t_vec->aad.length = options->aead_aad_sz;
+ } else {
+ t_vec->aad.data = NULL;
+ t_vec->aad.length = 0;
+ }
+
+ t_vec->digest.data = rte_malloc(NULL, options->digest_sz,
+ 16);
+ if (t_vec->digest.data == NULL) {
+ rte_free(t_vec->aad.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ t_vec->digest.phys_addr =
+ rte_malloc_virt2iova(t_vec->digest.data);
+ t_vec->digest.length = options->digest_sz;
+ memcpy(t_vec->digest.data, digest, options->digest_sz);
+ t_vec->data.aead_offset = 0;
+ t_vec->data.aead_length = options->max_buffer_size;
+
+ /* Set IV parameters */
+ t_vec->aead_iv.data = rte_malloc(NULL, options->aead_iv_sz,
+ 16);
+ if (options->aead_iv_sz && t_vec->aead_iv.data == NULL) {
+ rte_free(t_vec->aad.data);
+ rte_free(t_vec->digest.data);
+ rte_free(t_vec);
+ return NULL;
+ }
+ memcpy(t_vec->aead_iv.data, iv, options->aead_iv_sz);
+ t_vec->aead_iv.length = options->aead_iv_sz;
+ }
+ return t_vec;
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.h
new file mode 100644
index 000000000..6f10823ef
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_vectors.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_TEST_VECTRORS_
+#define _CPERF_TEST_VECTRORS_
+
+#include "cperf_options.h"
+
+struct cperf_test_vector {
+ struct {
+ uint8_t *data;
+ uint32_t length;
+ } plaintext;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } cipher_key;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } auth_key;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } aead_key;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } cipher_iv;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } auth_iv;
+
+ struct {
+ uint8_t *data;
+ uint16_t length;
+ } aead_iv;
+
+ struct {
+ uint8_t *data;
+ uint32_t length;
+ } ciphertext;
+
+ struct {
+ uint8_t *data;
+ rte_iova_t phys_addr;
+ uint16_t length;
+ } aad;
+
+ struct {
+ uint8_t *data;
+ rte_iova_t phys_addr;
+ uint16_t length;
+ } digest;
+
+ struct {
+ uint32_t auth_offset;
+ uint32_t auth_length;
+ uint32_t cipher_offset;
+ uint32_t cipher_length;
+ uint32_t aead_offset;
+ uint32_t aead_length;
+ } data;
+};
+
+struct cperf_test_vector*
+cperf_test_vector_get_dummy(struct cperf_options *options);
+
+extern uint8_t ciphertext[2048];
+
+extern uint8_t cipher_key[];
+extern uint8_t auth_key[];
+
+extern uint8_t iv[];
+extern uint8_t aad[];
+
+extern uint8_t digest[2048];
+
+#endif
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.c b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.c
new file mode 100644
index 000000000..833bc9a55
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.c
@@ -0,0 +1,435 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+
+#include "cperf_test_verify.h"
+#include "cperf_ops.h"
+#include "cperf_test_common.h"
+
+struct cperf_verify_ctx {
+ uint8_t dev_id;
+ uint16_t qp_id;
+ uint8_t lcore_id;
+
+ struct rte_mempool *pool;
+
+ struct rte_cryptodev_sym_session *sess;
+
+ cperf_populate_ops_t populate_ops;
+
+ uint32_t src_buf_offset;
+ uint32_t dst_buf_offset;
+
+ const struct cperf_options *options;
+ const struct cperf_test_vector *test_vector;
+};
+
+struct cperf_op_result {
+ enum rte_crypto_op_status status;
+};
+
+static void
+cperf_verify_test_free(struct cperf_verify_ctx *ctx)
+{
+ if (ctx) {
+ if (ctx->sess) {
+ rte_cryptodev_sym_session_clear(ctx->dev_id, ctx->sess);
+ rte_cryptodev_sym_session_free(ctx->sess);
+ }
+
+ if (ctx->pool)
+ rte_mempool_free(ctx->pool);
+
+ rte_free(ctx);
+ }
+}
+
+void *
+cperf_verify_test_constructor(struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id, uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *op_fns)
+{
+ struct cperf_verify_ctx *ctx = NULL;
+
+ ctx = rte_malloc(NULL, sizeof(struct cperf_verify_ctx), 0);
+ if (ctx == NULL)
+ goto err;
+
+ ctx->dev_id = dev_id;
+ ctx->qp_id = qp_id;
+
+ ctx->populate_ops = op_fns->populate_ops;
+ ctx->options = options;
+ ctx->test_vector = test_vector;
+
+ /* IV goes at the end of the crypto operation */
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+
+ ctx->sess = op_fns->sess_create(sess_mp, sess_priv_mp, dev_id, options,
+ test_vector, iv_offset);
+ if (ctx->sess == NULL)
+ goto err;
+
+ if (cperf_alloc_common_memory(options, test_vector, dev_id, qp_id, 0,
+ &ctx->src_buf_offset, &ctx->dst_buf_offset,
+ &ctx->pool) < 0)
+ goto err;
+
+ return ctx;
+err:
+ cperf_verify_test_free(ctx);
+
+ return NULL;
+}
+
+static int
+cperf_verify_op(struct rte_crypto_op *op,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *vector)
+{
+ const struct rte_mbuf *m;
+ uint32_t len;
+ uint16_t nb_segs;
+ uint8_t *data;
+ uint32_t cipher_offset, auth_offset;
+ uint8_t cipher, auth;
+ int res = 0;
+
+ if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
+ return 1;
+
+ if (op->sym->m_dst)
+ m = op->sym->m_dst;
+ else
+ m = op->sym->m_src;
+ nb_segs = m->nb_segs;
+ len = 0;
+ while (m && nb_segs != 0) {
+ len += m->data_len;
+ m = m->next;
+ nb_segs--;
+ }
+
+ data = rte_malloc(NULL, len, 0);
+ if (data == NULL)
+ return 1;
+
+ if (op->sym->m_dst)
+ m = op->sym->m_dst;
+ else
+ m = op->sym->m_src;
+ nb_segs = m->nb_segs;
+ len = 0;
+ while (m && nb_segs != 0) {
+ memcpy(data + len, rte_pktmbuf_mtod(m, uint8_t *),
+ m->data_len);
+ len += m->data_len;
+ m = m->next;
+ nb_segs--;
+ }
+
+ switch (options->op_type) {
+ case CPERF_CIPHER_ONLY:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 0;
+ auth_offset = 0;
+ break;
+ case CPERF_CIPHER_THEN_AUTH:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AUTH_ONLY:
+ cipher = 0;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AUTH_THEN_CIPHER:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ case CPERF_AEAD:
+ cipher = 1;
+ cipher_offset = 0;
+ auth = 1;
+ auth_offset = options->test_buffer_size;
+ break;
+ default:
+ res = 1;
+ goto out;
+ }
+
+ if (cipher == 1) {
+ if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+ res += memcmp(data + cipher_offset,
+ vector->ciphertext.data,
+ options->test_buffer_size);
+ else
+ res += memcmp(data + cipher_offset,
+ vector->plaintext.data,
+ options->test_buffer_size);
+ }
+
+ if (auth == 1) {
+ if (options->auth_op == RTE_CRYPTO_AUTH_OP_GENERATE)
+ res += memcmp(data + auth_offset,
+ vector->digest.data,
+ options->digest_sz);
+ }
+
+out:
+ rte_free(data);
+ return !!res;
+}
+
+static void
+cperf_mbuf_set(struct rte_mbuf *mbuf,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector)
+{
+ uint32_t segment_sz = options->segment_sz;
+ uint8_t *mbuf_data;
+ uint8_t *test_data;
+ uint32_t remaining_bytes = options->max_buffer_size;
+
+ if (options->op_type == CPERF_AEAD) {
+ test_data = (options->aead_op == RTE_CRYPTO_AEAD_OP_ENCRYPT) ?
+ test_vector->plaintext.data :
+ test_vector->ciphertext.data;
+ } else {
+ test_data =
+ (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) ?
+ test_vector->plaintext.data :
+ test_vector->ciphertext.data;
+ }
+
+ while (remaining_bytes) {
+ mbuf_data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+
+ if (remaining_bytes <= segment_sz) {
+ memcpy(mbuf_data, test_data, remaining_bytes);
+ return;
+ }
+
+ memcpy(mbuf_data, test_data, segment_sz);
+ remaining_bytes -= segment_sz;
+ test_data += segment_sz;
+ mbuf = mbuf->next;
+ }
+}
+
+int
+cperf_verify_test_runner(void *test_ctx)
+{
+ struct cperf_verify_ctx *ctx = test_ctx;
+
+ uint64_t ops_enqd = 0, ops_enqd_total = 0, ops_enqd_failed = 0;
+ uint64_t ops_deqd = 0, ops_deqd_total = 0, ops_deqd_failed = 0;
+ uint64_t ops_failed = 0;
+
+ static rte_atomic16_t display_once = RTE_ATOMIC16_INIT(0);
+
+ uint64_t i;
+ uint16_t ops_unused = 0;
+ uint32_t imix_idx = 0;
+
+ struct rte_crypto_op *ops[ctx->options->max_burst_size];
+ struct rte_crypto_op *ops_processed[ctx->options->max_burst_size];
+
+ uint32_t lcore = rte_lcore_id();
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ struct rte_cryptodev_info dev_info;
+ int linearize = 0;
+
+ /* Check if source mbufs require coalescing */
+ if (ctx->options->segment_sz < ctx->options->max_buffer_size) {
+ rte_cryptodev_info_get(ctx->dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER) == 0)
+ linearize = 1;
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ ctx->lcore_id = lcore;
+
+ if (!ctx->options->csv)
+ printf("\n# Running verify test on device: %u, lcore: %u\n",
+ ctx->dev_id, lcore);
+
+ uint16_t iv_offset = sizeof(struct rte_crypto_op) +
+ sizeof(struct rte_crypto_sym_op);
+
+ while (ops_enqd_total < ctx->options->total_ops) {
+
+ uint16_t burst_size = ((ops_enqd_total + ctx->options->max_burst_size)
+ <= ctx->options->total_ops) ?
+ ctx->options->max_burst_size :
+ ctx->options->total_ops -
+ ops_enqd_total;
+
+ uint16_t ops_needed = burst_size - ops_unused;
+
+ /* Allocate objects containing crypto operations and mbufs */
+ if (rte_mempool_get_bulk(ctx->pool, (void **)ops,
+ ops_needed) != 0) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate more crypto operations "
+ "from the crypto operation pool.\n"
+ "Consider increasing the pool size "
+ "with --pool-sz\n");
+ return -1;
+ }
+
+ /* Setup crypto op, attach mbuf etc */
+ (ctx->populate_ops)(ops, ctx->src_buf_offset,
+ ctx->dst_buf_offset,
+ ops_needed, ctx->sess, ctx->options,
+ ctx->test_vector, iv_offset, &imix_idx);
+
+
+ /* Populate the mbuf with the test vector, for verification */
+ for (i = 0; i < ops_needed; i++)
+ cperf_mbuf_set(ops[i]->sym->m_src,
+ ctx->options,
+ ctx->test_vector);
+
+#ifdef CPERF_LINEARIZATION_ENABLE
+ if (linearize) {
+ /* PMD doesn't support scatter-gather and source buffer
+ * is segmented.
+ * We need to linearize it before enqueuing.
+ */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_linearize(ops[i]->sym->m_src);
+ }
+#endif /* CPERF_LINEARIZATION_ENABLE */
+
+ /* Enqueue burst of ops on crypto device */
+ ops_enqd = rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id,
+ ops, burst_size);
+ if (ops_enqd < burst_size)
+ ops_enqd_failed++;
+
+ /**
+ * Calculate number of ops not enqueued (mainly for hw
+ * accelerators whose ingress queue can fill up).
+ */
+ ops_unused = burst_size - ops_enqd;
+ ops_enqd_total += ops_enqd;
+
+
+ /* Dequeue processed burst of ops from crypto device */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, ctx->options->max_burst_size);
+
+ if (ops_deqd == 0) {
+ /**
+ * Count dequeue polls which didn't return any
+ * processed operations. This statistic is mainly
+ * relevant to hw accelerators.
+ */
+ ops_deqd_failed++;
+ continue;
+ }
+
+ for (i = 0; i < ops_deqd; i++) {
+ if (cperf_verify_op(ops_processed[i], ctx->options,
+ ctx->test_vector))
+ ops_failed++;
+ }
+ /* Free crypto ops so they can be reused. */
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+ ops_deqd_total += ops_deqd;
+ }
+
+ /* Dequeue any operations still in the crypto device */
+
+ while (ops_deqd_total < ctx->options->total_ops) {
+ /* Sending 0 length burst to flush sw crypto device */
+ rte_cryptodev_enqueue_burst(ctx->dev_id, ctx->qp_id, NULL, 0);
+
+ /* dequeue burst */
+ ops_deqd = rte_cryptodev_dequeue_burst(ctx->dev_id, ctx->qp_id,
+ ops_processed, ctx->options->max_burst_size);
+ if (ops_deqd == 0) {
+ ops_deqd_failed++;
+ continue;
+ }
+
+ for (i = 0; i < ops_deqd; i++) {
+ if (cperf_verify_op(ops_processed[i], ctx->options,
+ ctx->test_vector))
+ ops_failed++;
+ }
+ /* Free crypto ops so they can be reused. */
+ rte_mempool_put_bulk(ctx->pool,
+ (void **)ops_processed, ops_deqd);
+ ops_deqd_total += ops_deqd;
+ }
+
+ if (!ctx->options->csv) {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf("%12s%12s%12s%12s%12s%12s%12s%12s\n\n",
+ "lcore id", "Buf Size", "Burst size",
+ "Enqueued", "Dequeued", "Failed Enq",
+ "Failed Deq", "Failed Ops");
+
+ printf("%12u%12u%12u%12"PRIu64"%12"PRIu64"%12"PRIu64
+ "%12"PRIu64"%12"PRIu64"\n",
+ ctx->lcore_id,
+ ctx->options->max_buffer_size,
+ ctx->options->max_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_failed);
+ } else {
+ if (rte_atomic16_test_and_set(&display_once))
+ printf("\n# lcore id, Buffer Size(B), "
+ "Burst Size,Enqueued,Dequeued,Failed Enq,"
+ "Failed Deq,Failed Ops\n");
+
+ printf("%10u;%10u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
+ "%"PRIu64"\n",
+ ctx->lcore_id,
+ ctx->options->max_buffer_size,
+ ctx->options->max_burst_size,
+ ops_enqd_total,
+ ops_deqd_total,
+ ops_enqd_failed,
+ ops_deqd_failed,
+ ops_failed);
+ }
+
+ return 0;
+}
+
+
+
+void
+cperf_verify_test_destructor(void *arg)
+{
+ struct cperf_verify_ctx *ctx = arg;
+
+ if (ctx == NULL)
+ return;
+
+ cperf_verify_test_free(ctx);
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.h b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.h
new file mode 100644
index 000000000..ac2192ba9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/cperf_test_verify.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef _CPERF_VERIFY_
+#define _CPERF_VERIFY_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "cperf.h"
+#include "cperf_ops.h"
+#include "cperf_options.h"
+#include "cperf_test_vectors.h"
+
+
+void *
+cperf_verify_test_constructor(
+ struct rte_mempool *sess_mp,
+ struct rte_mempool *sess_priv_mp,
+ uint8_t dev_id,
+ uint16_t qp_id,
+ const struct cperf_options *options,
+ const struct cperf_test_vector *test_vector,
+ const struct cperf_op_fns *ops_fn);
+
+int
+cperf_verify_test_runner(void *test_ctx);
+
+void
+cperf_verify_test_destructor(void *test_ctx);
+
+#endif /* _CPERF_VERIFY_ */
diff --git a/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data
new file mode 100644
index 000000000..ff555903b
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_128_sha.data
@@ -0,0 +1,502 @@
+# List of tests for AES-128 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x75, 0x95, 0xb3, 0x48, 0x38, 0xf9, 0xe4, 0x88, 0xec, 0xf8, 0x3b, 0x09, 0x40, 0xd4, 0xd6, 0xea,
+0xf1, 0x80, 0x6d, 0xfb, 0xba, 0x9e, 0xee, 0xac, 0x6a, 0xf9, 0x8f, 0xb6, 0xe1, 0xff, 0xea, 0x19,
+0x17, 0xc2, 0x77, 0x8d, 0xc2, 0x8d, 0x6c, 0x89, 0xd1, 0x5f, 0xa6, 0xf3, 0x2c, 0xa7, 0x6a, 0x7f,
+0x50, 0x1b, 0xc9, 0x4d, 0xb4, 0x36, 0x64, 0x6e, 0xa6, 0xd9, 0x39, 0x8b, 0xcf, 0x8e, 0x0c, 0x55,
+0x4d, 0xb8, 0xe8, 0xf5, 0xb6, 0x5a, 0xd4, 0x49, 0x63, 0x24, 0xa2, 0xdf, 0xf0, 0x7a, 0x1c, 0x3b,
+0x74, 0x0c, 0x1d, 0x9b, 0xe2, 0x2b, 0x31, 0xb5, 0xe3, 0xca, 0x9f, 0xe4, 0x23, 0xe8, 0x64, 0x83,
+0x1a, 0xf1, 0xaa, 0xbf, 0xd0, 0x6a, 0xd6, 0x43, 0xd1, 0x2d, 0x2b, 0x7f, 0x38, 0x8d, 0x55, 0xd8,
+0xb2, 0xa9, 0x96, 0xec, 0xf5, 0xf9, 0x56, 0x50, 0x65, 0xc8, 0x63, 0x35, 0x22, 0xb0, 0xf4, 0x11,
+0xf3, 0x96, 0x16, 0xc3, 0x55, 0x90, 0xd0, 0x42, 0x3a, 0x5b, 0xc7, 0xfa, 0x67, 0x9b, 0x9f, 0xbd,
+0xca, 0xa5, 0x89, 0xd1, 0xe6, 0xfb, 0xbe, 0x3c, 0x7a, 0x29, 0xcb, 0xd7, 0xd2, 0xaf, 0xfc, 0x2d,
+0x1e, 0xb2, 0x6c, 0x4f, 0x5e, 0x31, 0x67, 0x6f, 0xa9, 0x8e, 0x54, 0x1f, 0xdb, 0x87, 0xd4, 0x11,
+0xa4, 0x99, 0x50, 0xcc, 0x52, 0xd0, 0xfa, 0x43, 0x70, 0x03, 0xa6, 0xff, 0xe0, 0xcb, 0x22, 0xbd,
+0xf3, 0x66, 0xf2, 0x4d, 0x82, 0x13, 0x94, 0x28, 0x89, 0xae, 0x82, 0xdc, 0xa5, 0x3e, 0xf2, 0xd2,
+0x01, 0xda, 0xef, 0xb4, 0x81, 0x77, 0x86, 0x29, 0x35, 0xad, 0xca, 0x14, 0x84, 0xdb, 0x86, 0xbd,
+0x8c, 0xf0, 0x8b, 0xc4, 0x2a, 0xb0, 0x87, 0xd8, 0x0b, 0xcd, 0x2c, 0x32, 0xe1, 0xce, 0xca, 0x15,
+0x82, 0x6e, 0xf5, 0xc8, 0x20, 0x38, 0xa2, 0x60, 0xaf, 0xe1, 0xdc, 0xe7, 0x7b, 0xa4, 0x75, 0x4b,
+0xf2, 0xd1, 0xfb, 0x25, 0x36, 0xbe, 0x84, 0x67, 0x94, 0x06, 0x20, 0xc0, 0x21, 0x30, 0x29, 0xdf,
+0x63, 0xf5, 0x56, 0x3a, 0x07, 0xef, 0x8d, 0xad, 0x62, 0x0f, 0x60, 0xbe, 0xb0, 0x8e, 0x10, 0x27,
+0xc6, 0x46, 0x90, 0xe5, 0x59, 0xaa, 0x16, 0x55, 0xca, 0x68, 0x6c, 0xbf, 0x19, 0x4e, 0xcd, 0xe8,
+0xb4, 0xf8, 0x94, 0xc4, 0x55, 0x9d, 0x7c, 0x3c, 0x06, 0x4e, 0x1a, 0x34, 0x1b, 0x16, 0x80, 0xe4,
+0x56, 0x98, 0xd4, 0xaa, 0xee, 0x66, 0xea, 0x91, 0x71, 0x44, 0xbd, 0xcb, 0xb1, 0xc5, 0x57, 0x49,
+0xa8, 0x4e, 0xe2, 0x03, 0xc6, 0xd5, 0x39, 0xd8, 0x69, 0xa8, 0xa0, 0xad, 0xad, 0x0d, 0x8d, 0xa7,
+0x80, 0xd3, 0xba, 0xc1, 0xae, 0xfe, 0xf5, 0xa2, 0x55, 0x8d, 0xa6, 0x2f, 0xb1, 0x4c, 0x67, 0x3e,
+0xb4, 0xaa, 0xed, 0xab, 0x89, 0xbc, 0xa5, 0x6c, 0x96, 0xe1, 0xc2, 0x27, 0x80, 0x55, 0xe3, 0x1b,
+0x5c, 0x20, 0xad, 0x02, 0x83, 0xa1, 0xc9, 0x51, 0xbd, 0x63, 0xf6, 0x08, 0x64, 0x38, 0x75, 0x7c,
+0x50, 0xd9, 0xae, 0xbb, 0x1b, 0xab, 0x33, 0xd5, 0x61, 0xf1, 0xda, 0xe4, 0x52, 0x6d, 0x97, 0x3c,
+0xdb, 0xec, 0x62, 0x37, 0x5b, 0xe9, 0x84, 0xda, 0x26, 0x26, 0xa2, 0xc2, 0x00, 0x67, 0x50, 0x82,
+0x0c, 0xa2, 0xd4, 0xb0, 0xc9, 0xe7, 0x6e, 0x2a, 0x2a, 0xaa, 0x5a, 0x8a, 0x3c, 0xfa, 0xb8, 0xd6,
+0x95, 0xdf, 0xb5, 0x20, 0x08, 0x65, 0xf4, 0x2f, 0x49, 0x2a, 0xeb, 0x06, 0xd4, 0x1a, 0x3a, 0x3d,
+0xc7, 0xfe, 0xd2, 0x5c, 0xb5, 0x00, 0x14, 0x67, 0x32, 0xb2, 0x17, 0xe2, 0x17, 0x50, 0x97, 0xf0,
+0x11, 0xb5, 0x1a, 0xe4, 0xa9, 0xe1, 0x40, 0x21, 0xbb, 0x75, 0x96, 0xb2, 0xc1, 0x90, 0x8a, 0x66,
+0xfd, 0x2c, 0x1a, 0xa6, 0xc0, 0x4a, 0x53, 0xcb, 0x3e, 0x10, 0x0f, 0x0a, 0x73, 0x3c, 0x6b, 0x4f,
+0xba, 0x14, 0x57, 0xce, 0xc8, 0xb7, 0xd8, 0x33, 0xf1, 0xc4, 0xba, 0x02, 0x13, 0xaa, 0xc6, 0x15,
+0x9e, 0xd6, 0xfd, 0x77, 0x05, 0x81, 0x92, 0x61, 0x3b, 0x35, 0x3f, 0xbd, 0x38, 0x22, 0x2a, 0x5f,
+0xc3, 0x09, 0xc5, 0x73, 0x22, 0x2d, 0x27, 0x8a, 0x42, 0xac, 0x06, 0xe2, 0x8b, 0x9e, 0x3d, 0x73,
+0xfb, 0xf2, 0x71, 0x06, 0x07, 0x26, 0xc7, 0x25, 0xdd, 0x19, 0x7a, 0x54, 0xd8, 0xb8, 0x66, 0x6b,
+0x73, 0xad, 0xc8, 0xa2, 0x24, 0x39, 0x4a, 0xab, 0xdc, 0x5a, 0x6e, 0x32, 0xd9, 0x4a, 0x12, 0xe4,
+0xbd, 0x39, 0xf8, 0x72, 0x6a, 0xdc, 0x46, 0xfb, 0x18, 0x08, 0x01, 0xc5, 0xd3, 0xe7, 0xa2, 0xe9,
+0xf4, 0xe4, 0xcc, 0xaf, 0x91, 0x1c, 0xc7, 0x57, 0xdc, 0x18, 0x53, 0x2a, 0x66, 0xeb, 0x29, 0xf9,
+0xc5, 0x0e, 0x5a, 0x1c, 0x0d, 0xcc, 0xca, 0xb1, 0x67, 0x75, 0xff, 0x91, 0x58, 0x71, 0xff, 0x01,
+0x56, 0xaa, 0x51, 0x75, 0xfc, 0x61, 0x8a, 0x2a, 0x1c, 0xb3, 0x0a, 0x4b, 0x9a, 0xea, 0xe3, 0xc4,
+0x2a, 0x07, 0xd2, 0xce, 0x6d, 0xfc, 0x34, 0xf8, 0xb0, 0xe9, 0xe3, 0x4b, 0x71, 0x1f, 0x5f, 0x0e,
+0xb9, 0x87, 0x25, 0x1c, 0xad, 0x7b, 0x52, 0xa0, 0x56, 0xcf, 0x90, 0xbe, 0x7d, 0xc0, 0x6c, 0x34,
+0x28, 0x49, 0x77, 0xd4, 0x66, 0x12, 0x40, 0xa9, 0xd4, 0x32, 0xbe, 0x10, 0xad, 0x11, 0x73, 0xed,
+0x10, 0x60, 0xc5, 0x76, 0x63, 0xe8, 0x1a, 0x12, 0x26, 0x94, 0xa4, 0xa7, 0xee, 0xc3, 0xd3, 0x47,
+0xb6, 0x2f, 0xa1, 0x18, 0xe5, 0x7a, 0xf4, 0x85, 0x97, 0x1e, 0x09, 0xdf, 0xd6, 0x92, 0xc5, 0x2e,
+0x3e, 0xe5, 0xa9, 0x70, 0x7b, 0x89, 0x91, 0x5b, 0x72, 0x9a, 0x53, 0x5c, 0xdd, 0xb9, 0xd5, 0xe0,
+0xab, 0xb3, 0xc5, 0x14, 0x74, 0xcb, 0x67, 0xdc, 0xbb, 0x7c, 0x98, 0x31, 0xde, 0x2a, 0x61, 0x79,
+0x48, 0xdf, 0xb5, 0x1f, 0xb6, 0x3f, 0xbd, 0x15, 0xc8, 0xdf, 0x69, 0xc1, 0x11, 0xfc, 0xd2, 0xcf,
+0x33, 0xac, 0xe3, 0xdf, 0xc9, 0x26, 0xc7, 0x3c, 0x3d, 0xa8, 0x2b, 0xf1, 0xb7, 0x34, 0x01, 0x9e,
+0x53, 0x5a, 0x98, 0xe7, 0x45, 0x3a, 0x46, 0x90, 0xe1, 0xa3, 0x5f, 0xd3, 0xc4, 0xbc, 0x64, 0xea,
+0x9d, 0x90, 0xcc, 0xfc, 0x35, 0xa3, 0xd1, 0x8b, 0xc1, 0x9b, 0x6f, 0xce, 0xdb, 0xe7, 0x43, 0x3b,
+0x3d, 0x2e, 0xff, 0xc5, 0x81, 0x27, 0x2f, 0xd2, 0x66, 0x85, 0x7c, 0x8c, 0x3d, 0x4f, 0x3d, 0xca,
+0xce, 0x3a, 0xdf, 0xbc, 0xa2, 0x76, 0x3b, 0xe9, 0xc0, 0xf0, 0x22, 0xd8, 0x3c, 0xb8, 0x67, 0x7b,
+0x9b, 0xf1, 0x8d, 0x30, 0x0c, 0x1a, 0xd9, 0xe1, 0xff, 0x85, 0x26, 0xf1, 0xe8, 0x99, 0x92, 0x24,
+0xec, 0xb0, 0x7a, 0x20, 0xe3, 0x36, 0xe0, 0xe7, 0xc6, 0x9d, 0xfe, 0x7e, 0x52, 0x08, 0x00, 0x8c,
+0xc3, 0x8b, 0x8d, 0x3b, 0xf8, 0x07, 0x8c, 0x1e, 0x26, 0xbd, 0x1b, 0x82, 0x80, 0xe4, 0xec, 0x7a,
+0xf5, 0x3b, 0xb6, 0x2a, 0x59, 0xf0, 0x0c, 0x3d, 0x36, 0xaf, 0x8a, 0x59, 0xc1, 0x57, 0xc1, 0x9c,
+0xf1, 0x6e, 0x81, 0x98, 0xc2, 0x18, 0x0a, 0xb8, 0xe3, 0xe8, 0xa6, 0xd6, 0x54, 0x3a, 0xfd, 0xb2,
+0x3e, 0x13, 0x3e, 0xfb, 0xf9, 0x34, 0xc4, 0x8c, 0x6f, 0xbe, 0x11, 0x5b, 0x2d, 0x81, 0x7b, 0x20,
+0xc9, 0xd3, 0xe6, 0x71, 0x3e, 0xae, 0xbf, 0x23, 0x09, 0xa0, 0x87, 0xe7, 0x49, 0x2d, 0xc9, 0x6a,
+0x8d, 0xa3, 0x5e, 0x8e, 0xeb, 0x18, 0x33, 0x3a, 0xf8, 0x00, 0x3d, 0x91, 0xf0, 0x6c, 0x80, 0x38,
+0x3b, 0x0c, 0xa1, 0xb1, 0x17, 0xb1, 0xe0, 0x6d, 0x63, 0x7c, 0xa4, 0xf5, 0x9a, 0x65, 0xc8, 0x3e,
+0x09, 0xc5, 0x57, 0x79, 0x7a, 0x2a, 0x17, 0x8b, 0xbb, 0xe2, 0x75, 0xb8, 0x87, 0x14, 0x7b, 0xc6,
+0x21, 0xa8, 0x9e, 0x31, 0xdc, 0x15, 0xee, 0x43, 0xf6, 0xc0, 0x11, 0x30, 0xa8, 0x45, 0xd3, 0x4b,
+0x61, 0xfe, 0x9a, 0x19, 0xae, 0x01, 0x40, 0xf7, 0x56, 0xcc, 0xc6, 0xa9, 0x35, 0x10, 0xe7, 0x58,
+0xbb, 0x13, 0x79, 0x19, 0x11, 0x47, 0x90, 0xf4, 0xa3, 0x40, 0xf2, 0xa1, 0xe0, 0xd0, 0xb0, 0xe4,
+0xca, 0xf3, 0x03, 0x3a, 0xd5, 0xd9, 0x67, 0xbc, 0x35, 0x6d, 0x74, 0xa0, 0xd2, 0x10, 0x9a, 0x5e,
+0x14, 0x7e, 0xb9, 0x10, 0x17, 0x1c, 0x1d, 0x44, 0x31, 0xe4, 0xcc, 0xa6, 0x95, 0xd2, 0x45, 0x1a,
+0xfc, 0x9a, 0x7c, 0x62, 0xf2, 0xd8, 0xc4, 0x4b, 0x4c, 0x87, 0x13, 0xb7, 0x61, 0xe5, 0x7e, 0xa7,
+0x47, 0xac, 0x97, 0xf0, 0x86, 0x2b, 0xe6, 0x1e, 0x8c, 0xd0, 0x66, 0x86, 0xfa, 0x18, 0x1f, 0x12,
+0xa7, 0x84, 0x6f, 0x0d, 0x66, 0x1e, 0xe5, 0xf3, 0xb8, 0x1b, 0x37, 0xe4, 0x9a, 0x12, 0x81, 0x10,
+0x18, 0xad, 0xdd, 0x9d, 0x5a, 0x4b, 0xce, 0xf5, 0xcb, 0x31, 0x6d, 0x2e, 0xa5, 0x82, 0x40, 0x87,
+0x5c, 0x08, 0x62, 0xc2, 0xc2, 0x5d, 0xea, 0x78, 0x0a, 0xc1, 0x96, 0x99, 0xe5, 0xf4, 0x12, 0x5c,
+0xf1, 0xee, 0x70, 0x59, 0xc6, 0x5e, 0xc5, 0xfa, 0xb3, 0xa3, 0x62, 0x71, 0xd8, 0x22, 0x6a, 0x99,
+0xf9, 0xb7, 0xbe, 0x58, 0x45, 0x9a, 0x5a, 0xc1, 0xa9, 0x3f, 0x99, 0x7a, 0x16, 0x46, 0x52, 0x21,
+0x4b, 0x0c, 0x52, 0xce, 0xa6, 0x6c, 0x44, 0xf7, 0x77, 0xc2, 0x10, 0x11, 0x13, 0xe2, 0x19, 0x2e,
+0x5e, 0xb5, 0x4a, 0x5b, 0xfc, 0x66, 0x9d, 0xe1, 0xd0, 0x9d, 0xde, 0x46, 0xf2, 0xad, 0x35, 0x97,
+0x64, 0xa9, 0x05, 0x0e, 0x3b, 0x0f, 0xf9, 0xc7, 0xe0, 0xcd, 0x3b, 0x8c, 0xff, 0x6b, 0xde, 0xb0,
+0x7f, 0x3e, 0x1f, 0x3f, 0x7b, 0x66, 0xbd, 0x52, 0x40, 0x18, 0xde, 0x91, 0x61, 0xca, 0xae, 0x40,
+0x56, 0x9b, 0x46, 0x5f, 0xd9, 0x2f, 0x13, 0x62, 0x7e, 0x22, 0xec, 0x4b, 0x64, 0x8d, 0x21, 0xa2,
+0xe9, 0x83, 0xbb, 0xec, 0x7f, 0xd9, 0xb4, 0xfb, 0x4f, 0x21, 0x9e, 0xb4, 0x66, 0x15, 0x13, 0x95,
+0x0f, 0x50, 0xb4, 0x9f, 0x77, 0xe8, 0xad, 0x24, 0x0e, 0x00, 0xb3, 0x73, 0x29, 0xd0, 0xc4, 0x25,
+0xf7, 0x91, 0xe6, 0xac, 0xf4, 0x5f, 0x7f, 0xac, 0xd7, 0x68, 0x6b, 0x94, 0xd8, 0x7a, 0xcb, 0xb8,
+0xd8, 0xcb, 0x24, 0x06, 0x88, 0x2e, 0x8e, 0x91, 0xaf, 0xce, 0x6f, 0x36, 0x2f, 0x2d, 0x1a, 0xac,
+0xcc, 0x06, 0xb4, 0x0e, 0x66, 0x6e, 0x79, 0x15, 0xe5, 0xaa, 0x33, 0xeb, 0xb1, 0xe5, 0xa3, 0x62,
+0x7a, 0x76, 0xfc, 0x4a, 0xbd, 0xa2, 0xbe, 0x85, 0x44, 0x6c, 0x31, 0xae, 0x5b, 0xd9, 0x85, 0x5e,
+0xb7, 0x88, 0xdb, 0x29, 0xa1, 0x1e, 0x78, 0x98, 0x56, 0xbf, 0xfb, 0x4c, 0x63, 0xac, 0x96, 0xfb,
+0xa1, 0x18, 0x91, 0xc2, 0x21, 0x90, 0x7c, 0xfa, 0x9d, 0x6d, 0x09, 0xb9, 0xae, 0x9e, 0x90, 0xf3,
+0x33, 0x31, 0x95, 0xa3, 0xf4, 0xc1, 0xfa, 0x89, 0xad, 0x6d, 0x30, 0x1c, 0x42, 0x5b, 0x56, 0x6f,
+0x85, 0x26, 0x6a, 0xf6, 0x95, 0xf6, 0x3c, 0xbc, 0x9b, 0xb1, 0x70, 0x50, 0xeb, 0x9e, 0x40, 0xa2,
+0x97, 0x50, 0x2b, 0x90, 0x7b, 0x38, 0x64, 0xf1, 0xae, 0xa1, 0x23, 0xeb, 0x34, 0x22, 0x1a, 0x97,
+0x9d, 0xdb, 0x48, 0x44, 0x7d, 0x1a, 0x56, 0xfa, 0xdd, 0x18, 0xc9, 0xac, 0xe9, 0x2a, 0x98, 0x97,
+0x48, 0xff, 0x79, 0x66, 0x44, 0xfd, 0x2e, 0xa6, 0x15, 0x0b, 0x51, 0x3e, 0x0a, 0xaf, 0x62, 0x16,
+0x1a, 0x37, 0xab, 0x72, 0xa5, 0xf1, 0x0b, 0xa7, 0x8c, 0x00, 0xf2, 0xaa, 0xd3, 0x34, 0x01, 0xb1,
+0xd0, 0x2c, 0x88, 0xb8, 0x25, 0xd6, 0x62, 0x02, 0x52, 0xa4, 0x4a, 0xa2, 0xb1, 0xe3, 0x07, 0x91,
+0x41, 0x30, 0x55, 0x2f, 0x14, 0x61, 0x29, 0xd0, 0x94, 0x1e, 0x4e, 0xe3, 0x02, 0x39, 0xc9, 0xb1,
+0xfc, 0x43, 0xec, 0x83, 0x28, 0xf1, 0x98, 0x0e, 0xe9, 0x26, 0x79, 0x1c, 0x48, 0xa9, 0x22, 0x21,
+0x4a, 0x82, 0xaf, 0x43, 0x35, 0xf4, 0x9c, 0x39, 0x08, 0x8b, 0x93, 0xb8, 0x42, 0x40, 0x7b, 0x99,
+0x4c, 0xfa, 0x63, 0x90, 0x4e, 0x31, 0x5f, 0x9f, 0x60, 0x60, 0xa7, 0x1b, 0xb8, 0x38, 0x83, 0x63,
+0xb3, 0xe7, 0x2e, 0xcc, 0x1a, 0x21, 0xdd, 0x4b, 0xfb, 0x62, 0x2c, 0x30, 0xae, 0x15, 0x6b, 0xe2,
+0x37, 0x63, 0xc8, 0xa1, 0x16, 0x57, 0x83, 0x14, 0xcc, 0xae, 0xe4, 0x31, 0x1b, 0x06, 0xf7, 0xbe,
+0xf8, 0x56, 0xef, 0xd4, 0x60, 0x9e, 0x68, 0x0c, 0xa0, 0x82, 0x7e, 0x71, 0x87, 0x9e, 0xd2, 0xa7,
+0x5d, 0x86, 0xc6, 0x3d, 0x88, 0x4a, 0xd9, 0x01, 0x1e, 0x44, 0xa1, 0xc0, 0x91, 0x42, 0xd2, 0xfc,
+0xab, 0xf2, 0x7a, 0x94, 0x16, 0xf1, 0x39, 0x50, 0x83, 0x1c, 0x65, 0x9d, 0xc3, 0x26, 0x93, 0xdf,
+0x65, 0x0c, 0xe3, 0x83, 0xb5, 0x7f, 0x72, 0x73, 0xef, 0xd7, 0x62, 0xe9, 0x7f, 0xe2, 0xd1, 0xcc,
+0x9e, 0x77, 0x9f, 0xab, 0x30, 0x26, 0x2a, 0x2c, 0x18, 0xb1, 0x3c, 0x64, 0xcf, 0x54, 0x49, 0x75,
+0xe1, 0xbe, 0x51, 0xdc, 0xaa, 0xdf, 0xeb, 0xc0, 0x41, 0xc7, 0x24, 0x4b, 0xe3, 0xe0, 0xe7, 0xbc,
+0xed, 0x32, 0x15, 0x9f, 0x4b, 0x2f, 0x17, 0xc1, 0xce, 0x39, 0x38, 0x83, 0xcb, 0x97, 0x30, 0x7b,
+0x82, 0x46, 0x65, 0x55, 0x2d, 0xd8, 0x16, 0xa7, 0xd3, 0x33, 0x73, 0x5a, 0xb2, 0xe0, 0xae, 0xfc,
+0x12, 0x8a, 0xf4, 0x56, 0xd9, 0x7b, 0xd2, 0x02, 0xcf, 0x99, 0x37, 0x04, 0x56, 0x90, 0xab, 0x10,
+0x82, 0x3e, 0xcc, 0x2c, 0x8d, 0x53, 0x67, 0x9b, 0x43, 0x59, 0xc0, 0x80, 0xec, 0x18, 0x5e, 0x03,
+0x04, 0x5d, 0x1d, 0x5f, 0xb4, 0x03, 0x8f, 0xc7, 0x38, 0x10, 0x6c, 0xd7, 0xfe, 0x8f, 0x2c, 0xd4,
+0x0a, 0x1e, 0x47, 0x5f, 0x2a, 0x26, 0xd3, 0x4b, 0x3e, 0x46, 0x87, 0xd4, 0x94, 0xba, 0xe8, 0x19,
+0x89, 0x90, 0x70, 0x90, 0xa0, 0xee, 0x8d, 0x74, 0x87, 0x1c, 0x35, 0x6b, 0x48, 0x94, 0x3d, 0x80,
+0x4c, 0x8c, 0x84, 0x35, 0x86, 0x97, 0xb4, 0xe2, 0xae, 0x4c, 0xae, 0x30, 0xcf, 0x6e, 0x34, 0xa5,
+0xbb, 0xa5, 0xf5, 0xdd, 0x7e, 0xe8, 0xea, 0x37, 0x54, 0xe2, 0xc3, 0x91, 0x03, 0xcb, 0x8c, 0x4b,
+0x23, 0x73, 0x63, 0x5b, 0x35, 0x63, 0x5b, 0x89, 0xbb, 0x01, 0xce, 0x8d, 0x73, 0xa3, 0x4f, 0x89,
+0x76, 0x15, 0x5d, 0x50, 0x26, 0x01, 0x8c, 0x7b, 0x23, 0x6b, 0x84, 0xa6, 0x60, 0x44, 0x2a, 0x0b,
+0x33, 0x8f, 0x00, 0xad, 0x0e, 0x05, 0x75, 0x41, 0xae, 0x96, 0x1b, 0x2d, 0x0b, 0xe9, 0xdb, 0xba,
+0xbe, 0xe0, 0xc5, 0x65, 0x35, 0x02, 0xf2, 0x04, 0x6c, 0x3f, 0x81, 0xe0, 0x0c, 0x2c, 0xd7, 0xde,
+0xc8, 0xb2, 0x6c, 0x5d, 0x1e, 0x9b, 0xe0, 0x65, 0x1e, 0x13, 0xd8, 0x6a, 0x92, 0xa7, 0x59, 0x14,
+0x78, 0x92, 0xb7, 0x11, 0x06, 0xea, 0xc2, 0x8d, 0x61, 0x82, 0x5d, 0xfe, 0x18, 0x66, 0x02, 0x8e,
+0x7a, 0x09, 0x7f, 0xdc, 0x7e, 0xca, 0xa7, 0x76, 0x99, 0x50, 0x25, 0xf6, 0x7e, 0x30, 0xaa, 0xf7,
+0x82, 0xae, 0xfa, 0xe3, 0xdf, 0x56, 0xa9, 0xab, 0xa4, 0xa3, 0x2c, 0x4d, 0x02, 0x4c, 0x38, 0x02,
+0x2d, 0x7f, 0x37, 0x54, 0xca, 0x3f, 0x6e, 0x7b, 0x0e, 0xb2, 0xa5, 0x68, 0x76, 0x98, 0x85, 0xd4,
+0x83, 0x5b, 0x26, 0xb3, 0xcd, 0xe9, 0x0c, 0xdf, 0xa5, 0x35, 0x4d, 0xd8, 0x5c, 0x59, 0x53, 0xe8,
+0x81, 0xf0, 0x33, 0xc9, 0xc9, 0xef, 0x84, 0xf6, 0x5c, 0xf8, 0x6e, 0x32, 0xe7, 0x20, 0x94, 0x79
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+cipher_iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0xAD, 0x0F, 0xE8, 0xAD, 0x30, 0xD6, 0x0A, 0x2B, 0x6B, 0x3D, 0x24, 0x79, 0x6D, 0xB6, 0x80, 0x43,
+0x1D, 0xD1, 0x8A, 0xA8
+
+[sha224_hmac_buff_32]
+digest =
+0xB4, 0x1C, 0xF4, 0x73, 0x04, 0x62, 0x2D, 0xAF, 0x59, 0x05, 0xE8, 0x55, 0xE4, 0x8B, 0x24, 0xB4,
+0x0F, 0x4C, 0x3D, 0xBE, 0xFF, 0xFF, 0x8D, 0x19, 0x0D, 0x38, 0xA1, 0xFC
+
+[sha256_hmac_buff_32]
+digest =
+0x77, 0x54, 0x8D, 0x73, 0x7D, 0xB9, 0x78, 0x2F, 0x3D, 0xEE, 0xA2, 0xE7, 0xC9, 0x03, 0xF3, 0xB0,
+0x17, 0x8E, 0x71, 0x81, 0xB7, 0xA7, 0x5F, 0x9F, 0xF3, 0xED, 0x55, 0x1A, 0x69, 0x68, 0x52, 0xE5
+
+[sha384_hmac_buff_32]
+digest =
+0x1A, 0x3D, 0x1A, 0xD8, 0x0C, 0x04, 0x4B, 0x14, 0x9F, 0xF6, 0x9B, 0x80, 0x5C, 0xA2, 0x78, 0xFC,
+0xE6, 0xA3, 0xBA, 0x32, 0x09, 0x04, 0x52, 0x24, 0x76, 0xC9, 0xFC, 0x70, 0xA6, 0x00, 0xB4, 0x41,
+0xA1, 0x48, 0x1D, 0xCC, 0x54, 0x59, 0xE6, 0x94, 0x35, 0x36, 0xCC, 0xAB, 0x4B, 0xF5, 0xE4, 0xCA
+
+[sha512_hmac_buff_32]
+digest =
+0xED, 0xD7, 0x96, 0x0B, 0xC4, 0x8F, 0xBF, 0xF3, 0xEA, 0x7D, 0x5D, 0x57, 0x2A, 0x50, 0x50, 0xAC,
+0x33, 0xF2, 0xED, 0x56, 0x0A, 0xF7, 0x97, 0x4A, 0x36, 0x8D, 0x3B, 0xA5, 0x9F, 0x7A, 0x6D, 0x57,
+0xE0, 0x94, 0x10, 0xB9, 0x15, 0xC6, 0x1B, 0x7F, 0x17, 0xB3, 0x48, 0xB5, 0xF9, 0x93, 0xD8, 0xCA,
+0x74, 0x56, 0xED, 0xBD, 0x55, 0x14, 0xD2, 0xB6, 0x36, 0x07, 0x06, 0x73, 0x66, 0x41, 0x50, 0x84
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xC9, 0xC3, 0x65, 0x23, 0xCE, 0x9D, 0x6E, 0x35, 0xDC, 0x65, 0x3B, 0x21, 0x33, 0xFF, 0x1E, 0x74,
+0xAF, 0x48, 0x24, 0xD9
+
+[sha224_hmac_buff_64]
+digest =
+0x9F, 0xC3, 0x34, 0x0F, 0xB0, 0xA5, 0x4D, 0x89, 0xA4, 0x20, 0x01, 0xDF, 0x40, 0xAE, 0xA2, 0x41,
+0x4E, 0x97, 0x38, 0xBA, 0xA7, 0xF9, 0x94, 0x1F, 0x56, 0x4E, 0x00, 0x0A
+
+[sha256_hmac_buff_64]
+digest =
+0x66, 0x52, 0xF3, 0xEB, 0xC7, 0x06, 0xEF, 0x21, 0x82, 0x7C, 0xCF, 0x7F, 0x5B, 0x6B, 0x77, 0x2F,
+0x28, 0x61, 0x06, 0x2B, 0x67, 0x4B, 0x2D, 0x62, 0x71, 0x53, 0xBE, 0x12, 0xF9, 0x5B, 0xD8, 0x64
+
+[sha384_hmac_buff_64]
+digest =
+0x63, 0x50, 0x09, 0x45, 0x87, 0x02, 0x7F, 0x85, 0xD3, 0xC8, 0xF2, 0x26, 0x01, 0xE8, 0x2C, 0x28,
+0xB4, 0x86, 0x5A, 0x8E, 0x8E, 0x95, 0x27, 0x6A, 0x74, 0xF0, 0x29, 0xC2, 0x2D, 0x13, 0x91, 0xD5,
+0x38, 0xDB, 0x06, 0x7E, 0xB4, 0x8C, 0xD6, 0x30, 0x54, 0x86, 0xE7, 0xBB, 0x5C, 0xB6, 0xDD, 0x90
+
+[sha512_hmac_buff_64]
+digest =
+0xBE, 0x52, 0xBF, 0x69, 0x2B, 0x7F, 0xD5, 0x37, 0x48, 0x76, 0xCF, 0xBD, 0x23, 0x18, 0x45, 0x90,
+0x74, 0x25, 0x07, 0x91, 0x13, 0x37, 0xF3, 0x26, 0xEE, 0x68, 0xEC, 0xFC, 0xCB, 0x60, 0x53, 0x96,
+0x54, 0xF6, 0xE8, 0xAC, 0xF7, 0xB1, 0x52, 0x31, 0x7E, 0x5D, 0x99, 0xF3, 0x86, 0xF2, 0x98, 0x7D,
+0xD4, 0x38, 0xD9, 0xF1, 0x4C, 0x08, 0x87, 0x7F, 0xB9, 0x17, 0x97, 0x39, 0xDB, 0x68, 0x39, 0x19
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xB0, 0x6F, 0x7D, 0xB3, 0x29, 0xC3, 0x2B, 0x5D, 0xB7, 0xF1, 0x13, 0xFB, 0x9E, 0x90, 0x5D, 0xF1,
+0x48, 0xBC, 0x71, 0xA4
+
+[sha224_hmac_buff_128]
+digest =
+0xFC, 0x59, 0xAF, 0xF2, 0x83, 0x2E, 0x07, 0x08, 0xBF, 0xB4, 0x3C, 0x24, 0xA8, 0x52, 0x7B, 0x9E,
+0x92, 0x83, 0xCE, 0x96, 0xEE, 0x8B, 0x65, 0x72, 0x00, 0x12, 0xC6, 0x98
+
+[sha256_hmac_buff_128]
+digest =
+0x7E, 0xCA, 0x95, 0xD5, 0x63, 0xA8, 0xCA, 0xA6, 0xC5, 0x41, 0x75, 0x12, 0x60, 0xDF, 0xFE, 0x16,
+0x70, 0xEB, 0xCC, 0x4E, 0xEB, 0x00, 0x86, 0xF0, 0xEC, 0x45, 0x44, 0x76, 0x62, 0x55, 0x48, 0x56
+
+[sha384_hmac_buff_128]
+digest =
+0x1B, 0x2A, 0xAA, 0x7F, 0x2E, 0x58, 0x1F, 0x64, 0xB4, 0xE6, 0x29, 0xE4, 0x74, 0x78, 0x09, 0xD7,
+0xBA, 0xDD, 0x18, 0xB6, 0xE4, 0x21, 0xF5, 0x8F, 0x40, 0x45, 0x65, 0xD1, 0xBE, 0x4F, 0x7B, 0x27,
+0xF4, 0x64, 0x72, 0x55, 0x53, 0xAB, 0x39, 0x05, 0x7A, 0x6D, 0xAA, 0x12, 0x75, 0x03, 0x67, 0x4E
+
+[sha512_hmac_buff_128]
+digest =
+0x5F, 0x8F, 0xA8, 0xFA, 0xEA, 0x05, 0x29, 0xBD, 0x3B, 0xBA, 0xF6, 0xA7, 0x93, 0x9E, 0x16, 0xF1,
+0x8B, 0x10, 0x2F, 0x6D, 0x08, 0x18, 0x54, 0xD2, 0x39, 0xEB, 0xF9, 0x70, 0xCC, 0x55, 0xA0, 0xC3,
+0x08, 0x9B, 0x8E, 0x55, 0x81, 0x1A, 0xCE, 0x0D, 0x09, 0x97, 0x4E, 0x34, 0xD1, 0xE6, 0x25, 0x05,
+0x94, 0xC7, 0x05, 0x30, 0xAF, 0x2F, 0x7F, 0x54, 0xAA, 0xB8, 0xC5, 0x8E, 0x3D, 0xBB, 0xF2, 0x12
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0xF9, 0xCA, 0x12, 0x7D, 0x60, 0x68, 0xB7, 0xAF, 0xDC, 0xAC, 0x41, 0x13, 0x1C, 0xA8, 0xC1, 0x85,
+0x65, 0x11, 0x31, 0x4C
+
+[sha224_hmac_buff_256]
+digest =
+0x49, 0xED, 0xA4, 0x27, 0x51, 0x6A, 0x46, 0xE4, 0x31, 0x12, 0x72, 0x92, 0xB8, 0x81, 0x16, 0x97,
+0x19, 0x4F, 0x3B, 0xAC, 0xD1, 0xCE, 0x06, 0x40, 0xD4, 0xEA, 0x8E, 0xC3
+
+[sha256_hmac_buff_256]
+digest =
+0xB9, 0xFB, 0x21, 0x16, 0x0C, 0x08, 0xD1, 0xE0, 0x49, 0xB8, 0xC8, 0x7E, 0xCC, 0xF0, 0xBA, 0x29,
+0x32, 0xCE, 0x53, 0x03, 0xE8, 0xFB, 0xD2, 0x44, 0xB7, 0xB9, 0xFE, 0xE8, 0x03, 0x86, 0xE2, 0x68
+
+[sha384_hmac_buff_256]
+digest =
+0x47, 0xEA, 0x51, 0xA7, 0xAD, 0xA2, 0x34, 0x3D, 0x4A, 0x3A, 0x86, 0x89, 0x78, 0x56, 0xCF, 0x21,
+0x94, 0xBF, 0x80, 0x33, 0x6B, 0x42, 0x73, 0x01, 0xAD, 0x6B, 0xE0, 0xEC, 0x10, 0xEE, 0x6E, 0xEC,
+0xED, 0x54, 0x50, 0x5E, 0x96, 0x3B, 0xE8, 0x2A, 0x8C, 0x33, 0x67, 0x9B, 0x17, 0x6C, 0xBB, 0xF8
+
+[sha512_hmac_buff_256]
+digest =
+0x01, 0xAE, 0xE7, 0x74, 0xCD, 0x86, 0x43, 0xBC, 0x8A, 0xF6, 0xAF, 0x6C, 0xDE, 0x9E, 0x9A, 0xB7,
+0x6B, 0xCF, 0x98, 0x95, 0x31, 0xE8, 0x37, 0x3B, 0x3F, 0xF3, 0xC1, 0x00, 0xA0, 0xA6, 0xE5, 0x15,
+0x60, 0x36, 0x7E, 0x7C, 0x96, 0xAB, 0x17, 0xB9, 0x79, 0x3D, 0x3E, 0x43, 0xBC, 0xA0, 0xA0, 0x8B,
+0x14, 0x14, 0x22, 0x86, 0xE9, 0xF6, 0x96, 0x38, 0x9F, 0x24, 0x45, 0x9C, 0xE8, 0x63, 0x2A, 0x22
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x45, 0x8D, 0x5B, 0x40, 0x0D, 0x34, 0x3A, 0x7B, 0xB2, 0xB1, 0xE7, 0x62, 0xDE, 0x2B, 0xD0, 0x46,
+0xCD, 0x4B, 0x55, 0x95
+
+[sha224_hmac_buff_512]
+digest =
+0xE1, 0x82, 0x07, 0x4F, 0x6B, 0x24, 0x4A, 0x57, 0xE9, 0x04, 0x14, 0xB1, 0x7F, 0xD2, 0x4C, 0xA0,
+0x89, 0x8B, 0xB2, 0xA2, 0x28, 0x9F, 0xFE, 0x7C, 0xD1, 0x7F, 0x35, 0x07
+
+[sha256_hmac_buff_512]
+digest =
+0xB9, 0x75, 0x4F, 0x70, 0xC7, 0x8C, 0xF2, 0x62, 0x89, 0x3C, 0x41, 0x4D, 0x1D, 0x15, 0x81, 0x2A,
+0x5A, 0xCB, 0x56, 0x62, 0xF8, 0xE9, 0x38, 0x13, 0xC9, 0x4D, 0xC3, 0x9D, 0xF0, 0x82, 0xAC, 0xD2
+
+[sha384_hmac_buff_512]
+digest =
+0x9C, 0xAE, 0x77, 0x8D, 0x7E, 0x26, 0x01, 0xA6, 0x46, 0x47, 0xDF, 0xB7, 0x23, 0x6F, 0x17, 0x6B,
+0x9F, 0x4D, 0x94, 0xBB, 0x78, 0xD8, 0x2D, 0x90, 0xB1, 0xC1, 0x65, 0x6D, 0x92, 0x4E, 0x54, 0x7A,
+0xA5, 0xF6, 0x80, 0x29, 0x82, 0x77, 0xAC, 0xC3, 0x58, 0xE5, 0x14, 0x75, 0x64, 0x9D, 0x02, 0x6E
+
+[sha512_hmac_buff_512]
+digest =
+0x33, 0xB6, 0xD1, 0xC4, 0x5F, 0xDB, 0xEF, 0xF4, 0x14, 0xE8, 0xDA, 0x07, 0x30, 0xB6, 0xC6, 0xC9,
+0x4F, 0xCF, 0x64, 0x48, 0x08, 0xA2, 0xC1, 0x9D, 0x03, 0xAD, 0x93, 0x62, 0x41, 0xB6, 0xB9, 0xEC,
+0x1B, 0xD1, 0xAC, 0xA1, 0xC5, 0x94, 0x67, 0x19, 0xA3, 0x4B, 0x53, 0xCE, 0x0C, 0x8A, 0x27, 0x07,
+0x37, 0x75, 0x93, 0xC3, 0xC6, 0x60, 0x19, 0x39, 0x9E, 0x02, 0x23, 0x9A, 0xE6, 0xA9, 0x34, 0x1A
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0x0B, 0x26, 0x34, 0xAD, 0x56, 0x44, 0x39, 0x4A, 0x0D, 0x2F, 0x14, 0xFB, 0x60, 0x77, 0xDD, 0xFC,
+0x0B, 0x5F, 0x9F, 0x99
+
+[sha224_hmac_buff_1024]
+digest =
+0x56, 0x41, 0xC2, 0xF0, 0x73, 0x5C, 0x21, 0x13, 0x7E, 0x47, 0xCC, 0xAB, 0x21, 0x3D, 0x5E, 0xA7,
+0xC6, 0x1E, 0xFF, 0x26, 0x59, 0x0C, 0x71, 0x95, 0x72, 0x76, 0x0D, 0x00
+
+[sha256_hmac_buff_1024]
+digest =
+0x08, 0x91, 0x23, 0x89, 0x0F, 0xB0, 0xE4, 0x25, 0x9F, 0xC7, 0x46, 0x6B, 0xC3, 0x39, 0xE0, 0x9C,
+0xE2, 0xAE, 0xA3, 0xCF, 0xB8, 0xA0, 0x0A, 0xCF, 0x29, 0xEE, 0x0D, 0x83, 0x8A, 0xE5, 0xE4, 0x85
+
+[sha384_hmac_buff_1024]
+digest =
+0x38, 0xC7, 0x19, 0xA4, 0x46, 0x14, 0x79, 0xA4, 0xAB, 0x40, 0x61, 0xBC, 0xFB, 0x87, 0x16, 0xE2,
+0x08, 0x90, 0xAD, 0x33, 0x5D, 0x37, 0xB6, 0xCA, 0x80, 0xEE, 0x59, 0x9C, 0xBF, 0xA8, 0xEB, 0x78,
+0xC2, 0xE2, 0x2D, 0x6E, 0x2E, 0x98, 0x98, 0x6F, 0x07, 0x6A, 0x39, 0x57, 0x8F, 0xCE, 0xEE, 0x64
+
+[sha512_hmac_buff_1024]
+digest =
+0x17, 0x60, 0x08, 0x57, 0x43, 0x20, 0xF6, 0xB5, 0x6D, 0x0D, 0x7F, 0x7C, 0xB9, 0x09, 0x3F, 0x6D,
+0x3E, 0x75, 0x2F, 0x17, 0xDA, 0x19, 0x58, 0xF0, 0xEC, 0xED, 0x96, 0xA9, 0x57, 0x05, 0xCD, 0x23,
+0x0F, 0x1E, 0x38, 0x55, 0x2D, 0x8E, 0x36, 0x14, 0xF4, 0x99, 0x5E, 0x3C, 0x33, 0xBB, 0x99, 0xC9,
+0xCD, 0x7A, 0xF4, 0x87, 0x10, 0xB8, 0x6C, 0xB1, 0x14, 0x2D, 0xA8, 0xCE, 0xFE, 0xF8, 0x6F, 0xD9
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x58, 0xE4, 0xBB, 0x8D, 0x63, 0x5D, 0x23, 0xF1, 0xAB, 0xB5, 0xBD, 0xD8, 0x71, 0xC9, 0x05, 0x0A,
+0x65, 0x5D, 0x2D, 0x2D
+
+[sha224_hmac_buff_2048]
+digest =
+0xA3, 0x9A, 0x47, 0x68, 0x32, 0x3A, 0xA8, 0xE4, 0xBE, 0x23, 0xEA, 0xEE, 0x2D, 0x5E, 0x3C, 0x2E,
+0xD3, 0x99, 0xBE, 0x87, 0x19, 0x17, 0xC5, 0x13, 0x6D, 0xB7, 0x05, 0x97
+
+[sha256_hmac_buff_2048]
+digest =
+0x5B, 0x36, 0x1A, 0xF0, 0x55, 0xAC, 0xC3, 0xEA, 0x1B, 0x01, 0xCF, 0xCE, 0x89, 0x0D, 0x6A, 0xC3,
+0x5F, 0x9A, 0xD3, 0x49, 0xCC, 0xA4, 0xDF, 0xDD, 0x44, 0x1F, 0x9D, 0x6C, 0xB1, 0x92, 0xDF, 0xB9
+
+[sha384_hmac_buff_2048]
+digest =
+0x24, 0x17, 0xA2, 0x61, 0xFF, 0x46, 0xA2, 0x2E, 0xE5, 0xC3, 0xB4, 0x47, 0x10, 0x8C, 0x54, 0xD2,
+0xC2, 0x4D, 0x15, 0xA2, 0x8D, 0xEF, 0x98, 0x6E, 0xE0, 0xB1, 0x31, 0x3B, 0x7D, 0xDE, 0x41, 0x8E,
+0x98, 0xB9, 0xE9, 0xD2, 0xD8, 0xE5, 0x75, 0x6D, 0xC5, 0xF0, 0x1A, 0xC4, 0x1B, 0x8B, 0xC1, 0xA4
+
+[sha512_hmac_buff_2048]
+digest =
+0xD8, 0x77, 0x7A, 0x0F, 0x63, 0x1E, 0x92, 0x7B, 0x87, 0xCE, 0x07, 0x24, 0x7E, 0xE4, 0x36, 0x30,
+0x16, 0x76, 0x0D, 0xEC, 0xEF, 0x01, 0xF5, 0xD5, 0x44, 0xB7, 0xF3, 0x51, 0x31, 0x6A, 0xC2, 0x80,
+0xCD, 0x4C, 0x7F, 0xD4, 0xA6, 0x90, 0x85, 0xAE, 0x49, 0xB1, 0xF1, 0xB0, 0xC4, 0x16, 0x79, 0xC3,
+0xE3, 0x8B, 0x67, 0xC3, 0xAA, 0xC1, 0x9C, 0x8D, 0xE0, 0x22, 0xB3, 0xFD, 0x09, 0xD5, 0x40, 0xAC
diff --git a/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data
new file mode 100644
index 000000000..3f85a0048
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_192_sha.data
@@ -0,0 +1,504 @@
+# List of tests for AES-192 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x0F, 0x9B, 0xF5, 0x9F, 0xE2, 0xB3, 0xD9, 0x12, 0x27, 0x51, 0x18, 0xD7, 0x4E, 0x1F, 0x40, 0x4C,
+0xC1, 0xDF, 0x66, 0xAB, 0x1A, 0xFA, 0xF8, 0xEE, 0xA4, 0x40, 0x63, 0x72, 0x58, 0xAE, 0x7E, 0x98,
+0x76, 0x63, 0x56, 0x1F, 0x71, 0xDB, 0x80, 0x07, 0xFE, 0x34, 0x23, 0x43, 0x1E, 0x3D, 0xDE, 0x7E,
+0xC0, 0x72, 0xEF, 0xAD, 0xF4, 0x30, 0xDF, 0x4E, 0x3B, 0x9F, 0xCA, 0x90, 0xC3, 0x95, 0x8A, 0x66,
+0x5C, 0xD6, 0xCA, 0xBD, 0x3C, 0xC9, 0xD2, 0xFE, 0x30, 0x02, 0xA9, 0x8E, 0xAA, 0x80, 0xF6, 0xFF,
+0xCD, 0x40, 0xBC, 0x99, 0xD2, 0x25, 0x7F, 0xBF, 0xC5, 0xF3, 0x50, 0x31, 0x69, 0xE1, 0xC8, 0x64,
+0xC5, 0x5F, 0x30, 0x30, 0xD9, 0xD7, 0xF9, 0xF0, 0xD3, 0x77, 0xE0, 0xD0, 0x11, 0xB8, 0xC9, 0x54,
+0xD9, 0x9C, 0x10, 0x74, 0xCA, 0x4A, 0xFE, 0xD2, 0x16, 0xA5, 0xD8, 0x2D, 0xC0, 0xDA, 0x39, 0x24,
+0xAF, 0x5E, 0xF2, 0xEB, 0xC7, 0x9D, 0xBC, 0xEF, 0x94, 0xA0, 0x49, 0x56, 0x39, 0xCE, 0x8A, 0x38,
+0x3B, 0x70, 0xC7, 0xB2, 0xE0, 0xD4, 0x43, 0xD7, 0xAC, 0xB4, 0xB3, 0xDB, 0xA2, 0x2B, 0x75, 0xE2,
+0x0E, 0x38, 0x2B, 0xE6, 0x42, 0x1A, 0x11, 0x08, 0x79, 0x9A, 0x32, 0xD2, 0x41, 0xCC, 0x28, 0xC3,
+0x4B, 0x3E, 0xD4, 0xB0, 0x10, 0x89, 0x7B, 0x0D, 0xB7, 0x95, 0xBE, 0x22, 0x01, 0xD0, 0x86, 0xA8,
+0xC6, 0xD0, 0xDD, 0xDF, 0x18, 0x2C, 0x1B, 0x49, 0xE3, 0x2B, 0x84, 0x53, 0x54, 0x14, 0xE6, 0x04,
+0xE1, 0xD6, 0x98, 0x91, 0x17, 0xE0, 0xD9, 0x39, 0xAF, 0xF9, 0x71, 0x35, 0x90, 0xCE, 0x4B, 0xD2,
+0x45, 0xB2, 0x4B, 0x68, 0x26, 0xBB, 0x8C, 0xBD, 0xA3, 0xF7, 0x60, 0xD4, 0x38, 0xAA, 0xDF, 0x5B,
+0x3B, 0x53, 0xF6, 0xA4, 0x45, 0x49, 0x4A, 0xEF, 0x6F, 0x04, 0x00, 0xFF, 0xE3, 0x3F, 0x7C, 0x7D,
+0xDC, 0xB0, 0x62, 0x9C, 0x6A, 0x99, 0x07, 0x85, 0xB3, 0x13, 0x2B, 0x40, 0x06, 0xAF, 0xE3, 0xA0,
+0x17, 0x97, 0x0D, 0x4E, 0xD7, 0xB0, 0x6B, 0xF8, 0x3C, 0x91, 0x0A, 0xF3, 0x17, 0x51, 0x30, 0xC8,
+0x58, 0x20, 0x20, 0xE2, 0xA3, 0xE6, 0x3B, 0x2F, 0x77, 0x7C, 0x52, 0x31, 0x4F, 0x4C, 0xA8, 0xD8,
+0x84, 0xB1, 0xE9, 0xB4, 0x86, 0xD8, 0x93, 0xBF, 0x2D, 0x6A, 0xDA, 0x5D, 0x39, 0x62, 0x5B, 0x52,
+0xFB, 0xBA, 0x9F, 0x83, 0x82, 0x3C, 0x40, 0x57, 0x02, 0x92, 0x6A, 0x97, 0x06, 0x39, 0x17, 0x0B,
+0xA7, 0xF5, 0x6A, 0x1A, 0x8E, 0x64, 0x74, 0x90, 0x33, 0xA6, 0xA3, 0x1E, 0x30, 0x1E, 0x67, 0x49,
+0x5A, 0x76, 0x43, 0x97, 0x71, 0xE0, 0x4E, 0xCC, 0x5A, 0xFD, 0x44, 0xFD, 0x5C, 0x41, 0x3A, 0x09,
+0x8E, 0x4E, 0xD2, 0xF0, 0x9A, 0x52, 0x39, 0x5B, 0x0E, 0xC4, 0xF2, 0xFE, 0xB4, 0x66, 0x6C, 0x60,
+0x47, 0x96, 0x80, 0x91, 0xBE, 0x6C, 0xA8, 0x33, 0x66, 0x4D, 0x08, 0x70, 0x27, 0x0C, 0x33, 0x50,
+0x8F, 0xEF, 0x05, 0xC9, 0x93, 0x21, 0x8D, 0xA4, 0x94, 0xF3, 0xBC, 0x4D, 0x96, 0x9A, 0x51, 0x29,
+0xDA, 0x8E, 0x32, 0xB4, 0xB3, 0xD8, 0x75, 0x20, 0x37, 0x9F, 0x33, 0xE2, 0xF9, 0xEB, 0xFA, 0xF2,
+0x6E, 0x3F, 0x71, 0x0C, 0x29, 0x8D, 0xFE, 0xE1, 0xF9, 0xC6, 0x49, 0xB6, 0x6E, 0x53, 0xBC, 0x24,
+0x1D, 0x0B, 0x24, 0x75, 0x54, 0x51, 0x0B, 0xEB, 0xDD, 0x67, 0x40, 0x61, 0xCA, 0x3F, 0xD2, 0x85,
+0x71, 0x16, 0xFC, 0x77, 0x9C, 0x56, 0xE5, 0xCA, 0x43, 0xC6, 0xC3, 0x2A, 0x47, 0xA8, 0x98, 0x40,
+0x02, 0x1D, 0x64, 0x47, 0x85, 0x99, 0x2F, 0x8F, 0x2D, 0xC2, 0x29, 0x7B, 0x8D, 0x64, 0xD9, 0x8F,
+0xF4, 0x91, 0x6F, 0x2A, 0xB0, 0x5C, 0xDC, 0xB0, 0xBE, 0xDE, 0x34, 0xA8, 0x99, 0x40, 0x23, 0x9F,
+0x8A, 0xF5, 0x0C, 0x32, 0xDE, 0x53, 0xA5, 0x55, 0xFE, 0x4C, 0xF8, 0x87, 0x83, 0xB6, 0xA1, 0x31,
+0x2C, 0xB4, 0xE9, 0x78, 0xB8, 0x45, 0xAA, 0x33, 0x6E, 0x8A, 0xBE, 0xDB, 0x76, 0x35, 0xDD, 0xDF,
+0xA1, 0x98, 0x21, 0x2B, 0x42, 0xF3, 0xA4, 0x3E, 0x2C, 0x38, 0xA9, 0xB1, 0x07, 0x38, 0xA1, 0x1D,
+0xA5, 0x85, 0x61, 0x87, 0xF1, 0xA1, 0x9D, 0x3D, 0x2C, 0xA6, 0x2F, 0x26, 0xFD, 0xE8, 0x46, 0x0D,
+0xBD, 0xDA, 0x44, 0xC4, 0xB5, 0xFF, 0x6F, 0xDB, 0xF7, 0xF4, 0xDB, 0x0A, 0x80, 0x7C, 0x81, 0x27,
+0xF4, 0x27, 0x41, 0x15, 0x9F, 0xEC, 0xA5, 0xAA, 0x79, 0x30, 0x9B, 0x0D, 0x84, 0xAC, 0x4D, 0x50,
+0x68, 0x56, 0x55, 0x32, 0xF9, 0x28, 0x06, 0xC3, 0x96, 0xD6, 0x57, 0x61, 0x04, 0xCF, 0xD8, 0xB9,
+0x36, 0x0D, 0x33, 0x11, 0xEE, 0x8A, 0x88, 0x5A, 0x11, 0x6C, 0x11, 0x71, 0x41, 0xFC, 0xD5, 0xF1,
+0xB7, 0xC2, 0x94, 0x98, 0x6F, 0xAB, 0x12, 0x5F, 0x34, 0x46, 0xDD, 0xBC, 0x65, 0x5C, 0x76, 0x3A,
+0x81, 0x42, 0xF8, 0x6D, 0xC2, 0x08, 0x93, 0x58, 0x30, 0x1B, 0x82, 0x28, 0xD7, 0xFB, 0x90, 0x61,
+0x24, 0x38, 0x12, 0xDC, 0xFB, 0x88, 0xFB, 0xC8, 0xB9, 0xB8, 0x23, 0xA5, 0xEB, 0x85, 0xB1, 0x92,
+0x55, 0x34, 0xA7, 0x8E, 0x2C, 0x3D, 0xD7, 0x07, 0xF6, 0x2C, 0xF5, 0x5A, 0x72, 0x38, 0x25, 0x5A,
+0x3F, 0x1F, 0xF5, 0x7B, 0x02, 0xFC, 0x70, 0xB1, 0x31, 0x01, 0xCA, 0xD6, 0x18, 0x7C, 0xF4, 0x0A,
+0x3A, 0xAE, 0x7B, 0x89, 0x0B, 0xE8, 0x5E, 0x7D, 0x64, 0x7A, 0x10, 0xE0, 0x8C, 0x8C, 0x02, 0xF7,
+0x2F, 0x52, 0x06, 0xE7, 0xD7, 0xFA, 0x56, 0xBB, 0xC4, 0x5A, 0x82, 0x14, 0x13, 0x7D, 0x41, 0xD0,
+0xCE, 0x57, 0xE6, 0x41, 0x3A, 0x08, 0xAD, 0x7C, 0x20, 0xDC, 0x15, 0xA8, 0xBA, 0xE6, 0xB8, 0x58,
+0xA6, 0xF4, 0x82, 0x70, 0xDE, 0x09, 0xE2, 0x8B, 0xFC, 0xAA, 0x7D, 0xD9, 0xFD, 0xCE, 0xBC, 0xAC,
+0xB8, 0xE8, 0xB2, 0x46, 0xC5, 0xC4, 0xF9, 0xFC, 0xE5, 0xFF, 0xF5, 0xCA, 0xB3, 0x51, 0x3C, 0xB8,
+0x25, 0xD7, 0x83, 0x3C, 0x91, 0xCD, 0xFB, 0x86, 0x94, 0x5E, 0x36, 0xCF, 0xDE, 0x8E, 0x37, 0x4F,
+0x9D, 0x54, 0xBB, 0x8D, 0x52, 0xE6, 0x86, 0x5C, 0x8B, 0x72, 0x23, 0xAF, 0x93, 0xF5, 0xFF, 0xB5,
+0xC5, 0xFE, 0xC1, 0x31, 0xCE, 0x72, 0xD7, 0x3A, 0x2E, 0x25, 0xBF, 0xC1, 0xEE, 0xD5, 0x28, 0xDB,
+0xB7, 0xD2, 0x4E, 0xC6, 0x2B, 0xE3, 0x6F, 0x87, 0x2D, 0xA5, 0xFB, 0xDB, 0x03, 0xB0, 0x13, 0x58,
+0x3F, 0x3B, 0xBD, 0x2E, 0x0B, 0x78, 0xC2, 0xDC, 0xF8, 0x30, 0x2F, 0x08, 0xA6, 0x6A, 0x00, 0x57,
+0x82, 0x79, 0x06, 0x11, 0xC2, 0x20, 0x49, 0xD1, 0xDD, 0x53, 0xF6, 0xA8, 0xB1, 0x0A, 0x1C, 0x97,
+0x11, 0x5C, 0xA4, 0x98, 0xBC, 0xE7, 0x10, 0x27, 0x73, 0x54, 0x3C, 0x91, 0x98, 0x58, 0x2F, 0xA8,
+0x96, 0xB2, 0xE8, 0x54, 0xC0, 0x6B, 0x4B, 0x69, 0x0E, 0x92, 0xFB, 0xF0, 0x5E, 0xDC, 0x45, 0xAE,
+0x6B, 0x12, 0x29, 0xBE, 0x59, 0xA2, 0x0B, 0xD6, 0xD2, 0x09, 0xE0, 0xBA, 0xE2, 0x1D, 0xD9, 0x8A,
+0x6D, 0x70, 0xD0, 0x62, 0x0C, 0x9D, 0xC4, 0x38, 0x3A, 0x11, 0xBA, 0xF8, 0x8B, 0x0A, 0xDF, 0xDF,
+0xD1, 0xBF, 0x87, 0x98, 0xC8, 0xFF, 0x42, 0x85, 0x13, 0xE7, 0x6C, 0xDE, 0xFE, 0x45, 0xFE, 0xF8,
+0x67, 0x28, 0x56, 0xF7, 0x3C, 0x12, 0x4E, 0x88, 0x05, 0x8B, 0x56, 0x53, 0x2E, 0xE8, 0x6F, 0x3B,
+0xEE, 0x40, 0x4D, 0x3C, 0x1B, 0x0C, 0xE7, 0xCA, 0xD1, 0x3A, 0xA3, 0x2A, 0xDB, 0xC0, 0xDB, 0x9D,
+0xA4, 0xC1, 0xDA, 0x50, 0x81, 0x59, 0x52, 0x87, 0x33, 0x10, 0xE6, 0x58, 0xC3, 0x3E, 0x08, 0x69,
+0xFF, 0x3B, 0x4C, 0x82, 0xBA, 0xC3, 0x81, 0x82, 0xB5, 0xF2, 0x9F, 0x0A, 0x20, 0xCF, 0x70, 0xFB,
+0x81, 0x63, 0xB7, 0x04, 0x95, 0xFE, 0x08, 0x33, 0x1A, 0xED, 0xB0, 0x0A, 0x86, 0xA6, 0x42, 0x8F,
+0xEB, 0x48, 0xD8, 0xF4, 0xFE, 0x50, 0xA2, 0xC6, 0x5E, 0xD8, 0x33, 0xAE, 0x44, 0x83, 0xE6, 0x7C,
+0x88, 0xA3, 0xEC, 0x74, 0xA4, 0x26, 0x58, 0xE6, 0x3C, 0xD4, 0x04, 0xAC, 0x71, 0xBD, 0xBE, 0xCC,
+0xC6, 0xE8, 0x55, 0xDE, 0x98, 0x7F, 0x6B, 0x4F, 0x62, 0xF6, 0x4E, 0x1C, 0x95, 0x44, 0xBE, 0xD7,
+0x77, 0x9C, 0xD2, 0x13, 0xD7, 0xF5, 0x2C, 0x8D, 0xC1, 0xC7, 0xCA, 0xF8, 0x68, 0x91, 0x06, 0x24,
+0x01, 0x5D, 0xD0, 0x9E, 0xC9, 0x24, 0x12, 0x83, 0xA1, 0xF4, 0x05, 0xE0, 0xB2, 0xA9, 0xAD, 0xFC,
+0xC3, 0x64, 0x08, 0x17, 0x58, 0xAB, 0xB7, 0x39, 0xA4, 0xB6, 0x77, 0x26, 0x37, 0x13, 0x24, 0x20,
+0xEB, 0xEE, 0x61, 0x28, 0x0E, 0x33, 0x7C, 0x4D, 0xD5, 0xEA, 0x42, 0x39, 0xB7, 0x20, 0xCB, 0x97,
+0x44, 0xBE, 0x6D, 0x67, 0x28, 0xF9, 0x99, 0xE1, 0xE7, 0x3A, 0x5D, 0x7D, 0xAA, 0xBB, 0x1D, 0xEC,
+0xA4, 0xF6, 0xAA, 0xED, 0xC5, 0x1F, 0xAD, 0xDF, 0x0E, 0xD3, 0x94, 0xA9, 0xD9, 0xFF, 0x29, 0x56,
+0x3C, 0x43, 0x5E, 0xC2, 0x3B, 0xB3, 0x2E, 0x4A, 0xB7, 0x9F, 0xF4, 0xA0, 0xF1, 0xD6, 0x93, 0xFF,
+0x4A, 0xC8, 0xF2, 0xDE, 0x1A, 0x96, 0xB1, 0x83, 0x37, 0x45, 0x0C, 0x79, 0x40, 0x51, 0xD1, 0x08,
+0xF2, 0xDC, 0xFA, 0xBF, 0xB4, 0x15, 0x9A, 0x60, 0x37, 0x81, 0x5F, 0x76, 0xB2, 0x87, 0x82, 0x2D,
+0xA8, 0x0A, 0x70, 0x1B, 0xA2, 0xD6, 0x7E, 0x65, 0xAC, 0x02, 0x36, 0xDA, 0x0F, 0xB4, 0xD5, 0x6E,
+0xEE, 0x60, 0x0B, 0xC8, 0xD6, 0x1B, 0x9C, 0xF1, 0xCF, 0x66, 0xCA, 0x1D, 0x9D, 0xE5, 0xC7, 0x0B,
+0x1A, 0xE1, 0x9E, 0x68, 0xFF, 0xCE, 0xCE, 0x1B, 0x0A, 0x1E, 0x8D, 0x25, 0x37, 0x40, 0x05, 0x20,
+0xE4, 0xA1, 0x4F, 0x4C, 0x33, 0x29, 0xB3, 0x7B, 0x47, 0xFA, 0x7E, 0xEF, 0x87, 0x89, 0x13, 0x10,
+0x1C, 0x0F, 0x15, 0x03, 0xFD, 0xD8, 0x81, 0xD7, 0xB9, 0xA7, 0xBA, 0xD0, 0x6F, 0x6F, 0x76, 0xF6,
+0xD1, 0xF3, 0xCE, 0x57, 0x21, 0x02, 0x12, 0xAA, 0x5E, 0x61, 0xD4, 0xCA, 0xF2, 0x84, 0x80, 0xF0,
+0x90, 0x37, 0x0B, 0xE5, 0xC9, 0xE4, 0xAD, 0xD5, 0x8C, 0x47, 0x6D, 0xFA, 0xE1, 0xE5, 0xC6, 0x3A,
+0xE4, 0x0A, 0x82, 0xCE, 0x05, 0xD6, 0x46, 0x39, 0xAE, 0xE9, 0xE4, 0x6A, 0xD7, 0xE5, 0x9E, 0x85,
+0x4A, 0x31, 0xFA, 0xA0, 0x86, 0x01, 0x4B, 0xC8, 0x77, 0xC2, 0x10, 0xED, 0x70, 0xD5, 0x7D, 0x0F,
+0xF4, 0xDC, 0x97, 0x93, 0xB2, 0x7D, 0x45, 0x7A, 0x24, 0x37, 0x2D, 0x39, 0xAC, 0xB6, 0x53, 0x6B,
+0xA5, 0x9B, 0xDC, 0xC1, 0xAC, 0x95, 0x01, 0x3E, 0x52, 0x53, 0x11, 0x0A, 0xB7, 0x1E, 0x1F, 0xCD,
+0x29, 0xC0, 0xE9, 0x0A, 0xDF, 0xE5, 0xF5, 0x54, 0xF7, 0xF7, 0x23, 0x7C, 0xC6, 0xB3, 0x18, 0xEA,
+0x0E, 0x08, 0xE3, 0x76, 0x8D, 0xDC, 0x01, 0x45, 0xB7, 0x45, 0xAF, 0x5C, 0x88, 0xEA, 0x74, 0xFE,
+0xE0, 0xC5, 0xA3, 0x73, 0x2D, 0x2E, 0x47, 0xF1, 0x2E, 0xC0, 0x01, 0x97, 0xE5, 0x64, 0x84, 0x59,
+0xC6, 0x83, 0xF5, 0xFC, 0x0D, 0x2D, 0x70, 0x46, 0x0E, 0x17, 0xE1, 0xC9, 0xE2, 0xBF, 0xF2, 0xF4,
+0x7B, 0x5C, 0xF1, 0xBE, 0xC3, 0xA7, 0x81, 0x96, 0xA1, 0x24, 0x67, 0x85, 0xF5, 0x6C, 0xD4, 0xA3,
+0x2A, 0xBE, 0xF5, 0x05, 0x2A, 0xBB, 0xF2, 0x18, 0xAF, 0xDC, 0x21, 0x8A, 0x76, 0x2E, 0xAC, 0x31,
+0xB7, 0x56, 0x55, 0xFD, 0x09, 0x48, 0x3A, 0xA6, 0x66, 0x1C, 0x2F, 0x92, 0x2C, 0x07, 0xDF, 0x09,
+0x3A, 0xD1, 0xEA, 0x7A, 0xFA, 0x87, 0xE3, 0xF6, 0x5D, 0x03, 0x45, 0xC9, 0x3F, 0x97, 0x60, 0x4F,
+0x9C, 0x6C, 0xCC, 0x55, 0x1F, 0xE1, 0xBD, 0x5E, 0xE5, 0x5D, 0x76, 0x0C, 0x00, 0xE0, 0xDA, 0xB9,
+0x60, 0xFC, 0xF4, 0xC5, 0xFC, 0x14, 0x3E, 0x2C, 0xF2, 0x18, 0xEC, 0x7D, 0x2B, 0x56, 0xFC, 0x6D,
+0xCE, 0x3D, 0x94, 0x5E, 0xA1, 0x00, 0xDC, 0x00, 0xA6, 0x73, 0xCE, 0xDE, 0x57, 0x87, 0xB3, 0x90,
+0xE5, 0x16, 0x82, 0x24, 0x62, 0xAD, 0x27, 0x8B, 0xFF, 0xDD, 0xD6, 0x7C, 0xFB, 0x45, 0x8A, 0x09,
+0xB0, 0x80, 0x15, 0x86, 0x90, 0xB9, 0xE9, 0x0F, 0x59, 0x86, 0x9E, 0xBA, 0xA2, 0x6A, 0xBA, 0x33,
+0xDD, 0xE5, 0xE8, 0x08, 0x6F, 0x3F, 0xF4, 0x2E, 0xF7, 0x25, 0x28, 0x23, 0x60, 0x51, 0x88, 0x50,
+0x66, 0x31, 0xEA, 0xEE, 0x83, 0x98, 0x62, 0x04, 0xBD, 0x48, 0x17, 0x34, 0x15, 0x2E, 0x9F, 0x33,
+0x8C, 0x96, 0x83, 0x71, 0x1C, 0x0F, 0x72, 0xEB, 0x5F, 0x1C, 0x1A, 0x79, 0x7C, 0x22, 0x4C, 0x84,
+0xC6, 0xA6, 0xD6, 0xDD, 0x29, 0x67, 0x78, 0xC5, 0xEC, 0x37, 0x3E, 0x00, 0xCF, 0xEF, 0x7E, 0x4B,
+0x6D, 0xB2, 0xBD, 0xD3, 0x70, 0x41, 0x2A, 0x89, 0x00, 0x0E, 0xCA, 0x89, 0xC6, 0x31, 0x9F, 0xCB,
+0x59, 0x0C, 0x9B, 0x47, 0x6A, 0x0C, 0x56, 0x6D, 0x03, 0xF7, 0xD4, 0x81, 0x15, 0x3E, 0x9F, 0x6F,
+0x15, 0x22, 0x10, 0x52, 0xCC, 0xD9, 0x2C, 0xA3, 0x85, 0xA5, 0x42, 0x04, 0x7E, 0xD2, 0xE2, 0x16,
+0x98, 0xB1, 0x40, 0x57, 0x8A, 0x5A, 0x54, 0xA1, 0xF8, 0x9B, 0x8C, 0x77, 0x7A, 0x5F, 0x26, 0x4B,
+0x85, 0xE0, 0x3C, 0xB2, 0xC2, 0xC2, 0x90, 0xDD, 0x8E, 0xD9, 0xF5, 0x94, 0xAC, 0x3E, 0x56, 0x20,
+0x63, 0x13, 0x08, 0x48, 0x69, 0x9C, 0xD7, 0xD7, 0x05, 0x1B, 0xB0, 0xF3, 0x8A, 0x81, 0x78, 0x43,
+0x62, 0x04, 0xAB, 0x8D, 0xA8, 0xD7, 0x51, 0x2C, 0xFE, 0x66, 0x80, 0x06, 0xC0, 0x10, 0x92, 0xF3,
+0xBA, 0xBF, 0x42, 0x95, 0x96, 0xB7, 0xDB, 0xA5, 0x73, 0x06, 0xB8, 0x0D, 0xAE, 0xDA, 0x00, 0xA7,
+0xD2, 0xF8, 0x63, 0xF0, 0x35, 0x15, 0x7D, 0x9B, 0x1C, 0x3D, 0x3F, 0x83, 0x9C, 0xAE, 0xC1, 0xFA,
+0xE3, 0x62, 0x9A, 0x8A, 0xF3, 0x86, 0x2F, 0xE4, 0xDB, 0x49, 0xDF, 0x2C, 0x17, 0xFE, 0x2C, 0x30,
+0xD1, 0x76, 0x88, 0x92, 0x60, 0x60, 0xB9, 0xF9, 0x35, 0x0F, 0xE2, 0xE8, 0x8E, 0x73, 0x9E, 0x7C,
+0xF6, 0xD0, 0x5F, 0x81, 0x22, 0x2A, 0x5D, 0x5F, 0x10, 0xFE, 0x7B, 0x06, 0xB5, 0x5F, 0xF3, 0x42,
+0x94, 0xC4, 0x3E, 0xE0, 0x0E, 0x11, 0xCC, 0x3B, 0x4F, 0xBD, 0x06, 0xD1, 0x15, 0xF5, 0x32, 0x76,
+0xE4, 0x97, 0xBF, 0xA7, 0xC5, 0xD0, 0x5E, 0x5A, 0x1C, 0x35, 0x18, 0x43, 0x6B, 0x10, 0xD2, 0xAB,
+0x8B, 0xF6, 0xE1, 0xBB, 0x8C, 0xE9, 0x9C, 0x6C, 0x27, 0x96, 0xF8, 0x19, 0x6F, 0x6E, 0x73, 0x28,
+0x8F, 0x51, 0x61, 0x0B, 0x4D, 0x4F, 0x22, 0x15, 0x1A, 0xCD, 0x88, 0x2C, 0x6F, 0x9C, 0xEC, 0x79,
+0x51, 0x70, 0x27, 0x8E, 0x58, 0xEF, 0xDE, 0x0B, 0xAA, 0x4D, 0xD2, 0x8F, 0x96, 0xE0, 0x71, 0x6A,
+0x8C, 0x41, 0xDB, 0x98, 0xF7, 0x2A, 0x09, 0x59, 0xD9, 0x48, 0x7B, 0x14, 0x87, 0x9B, 0x4A, 0xBB,
+0x88, 0xF2, 0x9D, 0x9D, 0x47, 0xF2, 0x80, 0x4B, 0xD9, 0x0E, 0xF3, 0xA9, 0x7E, 0xEF, 0xA1, 0x80,
+0x9D, 0x6F, 0x67, 0x6C, 0x14, 0x09, 0x2C, 0xB9, 0x03, 0xF3, 0x58, 0x37, 0xAE, 0x6B, 0xF7, 0x01,
+0x86, 0xDF, 0x43, 0xD5, 0xE4, 0xE2, 0x28, 0x8E, 0x8D, 0xA4, 0xF2, 0xC5, 0x7A, 0xA7, 0x89, 0x3A,
+0xE2, 0x7E, 0x77, 0xFD, 0x3A, 0x9A, 0x65, 0x5D, 0x87, 0xDC, 0x85, 0x70, 0xAB, 0xF3, 0x18, 0x0A
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+0xd0, 0xe7, 0x4b, 0xfb, 0x5d, 0xe5, 0x0c, 0xe7
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+cipher_iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0x34, 0xCB, 0xFA, 0xE6, 0xBF, 0x60, 0x88, 0x82, 0x2C, 0x9F, 0x96, 0x4A, 0x5A, 0xD8, 0xAE, 0x48,
+0x1D, 0x2B, 0x0A, 0x22
+
+[sha224_hmac_buff_32]
+digest =
+0x17, 0xDD, 0xF3, 0xC0, 0xFC, 0xBC, 0x89, 0xE1, 0x02, 0x94, 0x51, 0x2B, 0xA0, 0x63, 0x4D, 0x1B,
+0x78, 0xCA, 0x0D, 0xD5, 0x99, 0xC0, 0xB8, 0x8E, 0x7F, 0x8A, 0xCB, 0x92
+
+[sha256_hmac_buff_32]
+digest =
+0xF7, 0xC0, 0xFD, 0x09, 0x94, 0x8F, 0x88, 0xF3, 0x26, 0xE1, 0xB1, 0xA6, 0x70, 0xFD, 0x57, 0xA2,
+0xB7, 0x63, 0x9C, 0x35, 0x97, 0x60, 0x27, 0x6A, 0xCC, 0xD8, 0x4A, 0xAE, 0xFD, 0xEC, 0x14, 0x56
+
+[sha384_hmac_buff_32]
+digest =
+0x01, 0x90, 0x96, 0x95, 0x8B, 0xE8, 0xF8, 0x30, 0xE0, 0xFE, 0xD4, 0x83, 0xE4, 0xE1, 0x48, 0xEB,
+0xEB, 0x3E, 0x6D, 0xBC, 0x72, 0xD8, 0xBF, 0x00, 0x86, 0x0B, 0x80, 0xCB, 0xCF, 0x0E, 0x83, 0x7E,
+0x77, 0x29, 0xA0, 0x71, 0xA9, 0x15, 0x8F, 0xE5, 0xC4, 0x32, 0xC8, 0xDB, 0x0A, 0xD1, 0xE3, 0x79
+
+[sha512_hmac_buff_32]
+digest =
+0x45, 0x72, 0x2B, 0xF4, 0x10, 0x82, 0xB6, 0xBC, 0xDB, 0x44, 0x34, 0x47, 0x55, 0xA7, 0x34, 0x4C,
+0x1C, 0x5D, 0x4D, 0x88, 0x58, 0x0B, 0xC2, 0x3E, 0xE7, 0x49, 0xF4, 0x6A, 0x99, 0x35, 0xE5, 0x2B,
+0xF4, 0x18, 0xD7, 0xD1, 0xAF, 0xC9, 0x81, 0xC5, 0x97, 0xE7, 0x94, 0xC4, 0xFD, 0x95, 0x7E, 0x1D,
+0x4E, 0xF4, 0x88, 0xC0, 0x10, 0x31, 0xB5, 0x1E, 0x39, 0x91, 0x1A, 0x48, 0xC2, 0x2F, 0xFE, 0xF6
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xD5, 0x0D, 0x9A, 0x30, 0xED, 0x71, 0x88, 0xF3, 0x72, 0x5D, 0x1C, 0xEF, 0x44, 0x36, 0xC1, 0x0C,
+0x66, 0x32, 0x15, 0xB5
+
+[sha224_hmac_buff_64]
+digest =
+0x59, 0xF0, 0x38, 0xA5, 0x7F, 0xDC, 0x55, 0xAF, 0x0A, 0x18, 0x0B, 0x34, 0xC1, 0x48, 0xFC, 0xB2,
+0xF8, 0x3B, 0xC2, 0x4A, 0x36, 0x0F, 0xEA, 0x4F, 0xD9, 0x46, 0x25, 0x1F
+
+[sha256_hmac_buff_64]
+digest =
+0x00, 0xD2, 0x5F, 0xAC, 0x89, 0x4B, 0x16, 0x08, 0x89, 0x8D, 0x4F, 0x8F, 0x56, 0xF5, 0xA2, 0x9B,
+0xDB, 0x91, 0x2F, 0xCE, 0x90, 0x0E, 0x4B, 0x17, 0x74, 0x8B, 0xC4, 0x8A, 0x47, 0xF0, 0x7C, 0x7A
+
+[sha384_hmac_buff_64]
+digest =
+0xFE, 0x79, 0x5C, 0x3D, 0xEA, 0x2C, 0x04, 0xB9, 0xE9, 0x37, 0x4E, 0x02, 0xE8, 0x56, 0xE8, 0x7E,
+0xB4, 0xA7, 0x3D, 0x37, 0xDD, 0x05, 0x58, 0x6A, 0x3D, 0x44, 0x0E, 0x84, 0xA9, 0xB4, 0x1F, 0x26,
+0xED, 0xAF, 0xA3, 0x4D, 0xA3, 0x6E, 0x30, 0x8F, 0xE3, 0x79, 0xB9, 0x58, 0x4E, 0xB3, 0x36, 0x1D
+
+[sha512_hmac_buff_64]
+digest =
+0x3A, 0xFE, 0x1E, 0xC8, 0x75, 0x0D, 0xF3, 0x15, 0x03, 0xCC, 0x7B, 0x50, 0xD1, 0x3E, 0x35, 0x97,
+0x4D, 0x80, 0xB8, 0x0B, 0x5E, 0x22, 0x4D, 0xB9, 0xD2, 0xC9, 0x0E, 0x24, 0xC4, 0xD9, 0xDD, 0x95,
+0xA1, 0x7D, 0xED, 0xE4, 0x28, 0x17, 0x7C, 0x50, 0x0B, 0x40, 0x81, 0x18, 0xEA, 0xFF, 0xBA, 0x1C,
+0x8C, 0x5D, 0x17, 0xB3, 0x5B, 0x39, 0x70, 0x93, 0x9A, 0xA0, 0x47, 0x59, 0x06, 0x01, 0xE5, 0xD0
+
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xF6, 0x21, 0x56, 0x15, 0xEC, 0xB6, 0xDE, 0x2B, 0x68, 0x79, 0x30, 0x69, 0x69, 0x82, 0x4B, 0x97,
+0x57, 0x61, 0xED, 0x01
+
+[sha224_hmac_buff_128]
+digest =
+0xC4, 0x5A, 0x48, 0x07, 0xCC, 0xFD, 0x68, 0x28, 0xCC, 0xDA, 0x13, 0x9C, 0xFE, 0x02, 0x22, 0x1C,
+0xD5, 0x2E, 0x9F, 0x0D, 0xED, 0x0B, 0x9B, 0x6D, 0xF3, 0x81, 0xD6, 0xDF
+
+[sha256_hmac_buff_128]
+digest =
+0x44, 0xA6, 0x70, 0x6C, 0xD2, 0xA6, 0x3F, 0xFB, 0x98, 0xB9, 0x6A, 0x71, 0x40, 0xCF, 0xD2, 0x40,
+0xA3, 0xC0, 0xC6, 0x4E, 0xF6, 0xD8, 0x4D, 0x87, 0xF5, 0x9B, 0xAC, 0xB0, 0x7B, 0xB7, 0x35, 0x5B
+
+[sha384_hmac_buff_128]
+digest =
+0xD7, 0xFA, 0xF1, 0xC5, 0xD6, 0xCE, 0xB9, 0x77, 0xD5, 0x6B, 0x4D, 0x7F, 0xFE, 0xAF, 0xDF, 0xCE,
+0x68, 0x1A, 0xB7, 0x3E, 0xA5, 0x9A, 0xF5, 0x79, 0x91, 0x96, 0x7C, 0xED, 0xC9, 0x02, 0x31, 0x67,
+0xC4, 0xD9, 0xD7, 0x5A, 0xD7, 0xF0, 0x82, 0x2C, 0xBD, 0x4A, 0xFF, 0x03, 0x25, 0xB6, 0x50, 0x17
+
+[sha512_hmac_buff_128]
+digest =
+0x78, 0xE1, 0x86, 0x74, 0xC1, 0x83, 0xDB, 0x3C, 0xAC, 0x2B, 0x17, 0xAC, 0x12, 0xAA, 0x30, 0xDE,
+0x2C, 0x86, 0xC4, 0x53, 0x4A, 0xC2, 0x78, 0x86, 0x3A, 0x8A, 0x96, 0x36, 0x2B, 0x09, 0xB1, 0x62,
+0xCA, 0xD0, 0x25, 0xB2, 0x5B, 0x3A, 0x76, 0xFA, 0xED, 0x5B, 0xFB, 0xF0, 0x8F, 0xF2, 0x06, 0x76,
+0x9B, 0xE0, 0x82, 0x25, 0x10, 0x5E, 0x8A, 0x13, 0xA1, 0x25, 0x3B, 0xB7, 0xFC, 0xC3, 0x15, 0xED
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0x31, 0x36, 0xC8, 0xC7, 0x95, 0xDB, 0xF7, 0xF3, 0xA0, 0xFF, 0x89, 0x94, 0x8D, 0xB2, 0x3D, 0x5F,
+0x7A, 0xC1, 0x38, 0x97
+
+[sha224_hmac_buff_256]
+digest =
+0xAE, 0x1B, 0xA4, 0x42, 0xE6, 0x3C, 0x3D, 0xEE, 0xEE, 0xD1, 0x24, 0xD2, 0xFF, 0xD2, 0x1A, 0xF3,
+0x28, 0x87, 0x8F, 0x00, 0xE3, 0x74, 0xA1, 0xA2, 0xED, 0x70, 0x2D, 0x9D
+
+[sha256_hmac_buff_256]
+digest =
+0x73, 0x89, 0x54, 0x06, 0x65, 0x71, 0x1D, 0xA1, 0xAB, 0x4A, 0x0A, 0x36, 0x63, 0x92, 0xB8, 0x94,
+0x98, 0x98, 0xB5, 0x27, 0x9D, 0x9C, 0xF2, 0x91, 0x0C, 0x56, 0xC4, 0xEE, 0x99, 0xC6, 0xDE, 0xC7
+
+[sha384_hmac_buff_256]
+digest =
+0xFE, 0x6E, 0xA5, 0xDC, 0x82, 0x57, 0xBB, 0x4D, 0xA8, 0xF1, 0x2F, 0xD1, 0xA2, 0x05, 0x0A, 0xFE,
+0xF2, 0x64, 0x8A, 0xB3, 0x96, 0xBA, 0x06, 0x47, 0xA4, 0x40, 0x76, 0x8E, 0xB8, 0xE3, 0xAD, 0xD1,
+0xB2, 0x90, 0x9A, 0x02, 0xD1, 0x13, 0x4F, 0x74, 0x9B, 0xEB, 0x09, 0xFC, 0x7F, 0x99, 0xAC, 0xCD
+
+[sha512_hmac_buff_256]
+digest =
+0x9F, 0x71, 0xE0, 0x86, 0xF9, 0x76, 0x3F, 0xAB, 0x16, 0x4D, 0x9C, 0x28, 0x72, 0x3A, 0x17, 0x8F,
+0x35, 0xD1, 0x44, 0x18, 0xE0, 0x4A, 0xBD, 0x8B, 0x25, 0x9F, 0x6E, 0x5B, 0xE3, 0xF4, 0x1C, 0x40,
+0x2B, 0xF4, 0x61, 0x59, 0x60, 0x8D, 0x55, 0xD8, 0x18, 0x9B, 0x65, 0x8D, 0x9F, 0xAA, 0xB3, 0x71,
+0x3D, 0xB5, 0x70, 0xD2, 0x26, 0xF1, 0x55, 0xDC, 0xCE, 0x49, 0x40, 0xD7, 0x23, 0x6B, 0x20, 0x4A
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x0F, 0xF6, 0x33, 0x61, 0x16, 0x5C, 0xD1, 0x9E, 0xE0, 0x3D, 0x95, 0x93, 0xD2, 0x82, 0xDE, 0x2E,
+0xFA, 0x25, 0x56, 0xE4
+
+[sha224_hmac_buff_512]
+digest =
+0x85, 0x61, 0x57, 0x9F, 0x3E, 0x6A, 0xE1, 0x5C, 0x1D, 0xA3, 0x98, 0x9C, 0x28, 0x2C, 0x96, 0x8E,
+0xD0, 0x7D, 0x70, 0x7D, 0xF5, 0x98, 0xA4, 0x7C, 0x88, 0x1C, 0xA4, 0x5C
+
+[sha256_hmac_buff_512]
+digest =
+0xF4, 0x77, 0xB2, 0x2E, 0xAD, 0xBC, 0xA2, 0xCD, 0x49, 0xE0, 0xD2, 0xB0, 0xB3, 0xDE, 0x51, 0xD0,
+0xBC, 0xEF, 0x33, 0x50, 0x4F, 0x39, 0xBC, 0x94, 0x18, 0xF3, 0xDD, 0xFC, 0xB5, 0x8E, 0x44, 0x18
+
+[sha384_hmac_buff_512]
+digest =
+0x03, 0x4F, 0x86, 0xA0, 0xBC, 0x00, 0x44, 0xEB, 0x06, 0x75, 0x61, 0x13, 0x92, 0x60, 0x74, 0x44,
+0x1D, 0xCB, 0x2C, 0x8D, 0xEC, 0xE5, 0x5C, 0xBE, 0xA3, 0xAE, 0x5F, 0xE2, 0x71, 0xED, 0xAC, 0x69,
+0x9C, 0x6C, 0xE3, 0x20, 0x5C, 0x90, 0xC3, 0xF4, 0x36, 0x76, 0x70, 0xAE, 0x2A, 0x9C, 0xF5, 0x0B
+
+[sha512_hmac_buff_512]
+digest =
+0x3B, 0x83, 0x4B, 0x7F, 0x2A, 0x62, 0x9A, 0xF6, 0x42, 0x29, 0x7A, 0xF0, 0xCA, 0xE7, 0xBE, 0x1F,
+0x92, 0x5C, 0x66, 0x88, 0x58, 0xFA, 0xA4, 0xC7, 0xE7, 0xF0, 0xEA, 0x83, 0xB2, 0x0A, 0x2C, 0x3B,
+0xA7, 0xD4, 0xA4, 0x3E, 0x87, 0x00, 0x44, 0x2B, 0x3F, 0xB2, 0x4B, 0xFF, 0xAD, 0x9B, 0x07, 0x7D,
+0xA1, 0x09, 0x09, 0x60, 0x68, 0x2F, 0x7B, 0x16, 0x43, 0x0E, 0x22, 0xAF, 0x78, 0x8D, 0xC7, 0x16
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0xCD, 0x04, 0x78, 0x4A, 0xD5, 0xFE, 0x95, 0xFB, 0x04, 0x85, 0xD5, 0x25, 0x58, 0xE6, 0x6C, 0x81,
+0xFA, 0x4B, 0xE7, 0x75
+
+[sha224_hmac_buff_1024]
+digest =
+0x10, 0xA5, 0x18, 0x56, 0x66, 0xDE, 0xE6, 0xF6, 0x71, 0xAF, 0x65, 0xEC, 0xE3, 0x77, 0x08, 0x58,
+0xD5, 0x45, 0xE6, 0x21, 0xF5, 0xCC, 0x2B, 0xE2, 0x76, 0x91, 0x51, 0xD9
+
+[sha256_hmac_buff_1024]
+digest =
+0xB4, 0x09, 0xF9, 0xA0, 0x5B, 0x80, 0xFF, 0xBA, 0x21, 0x5F, 0x57, 0xAB, 0x8B, 0x67, 0x89, 0x6D,
+0xB4, 0xE9, 0xEA, 0x5D, 0x77, 0x57, 0xBD, 0x0A, 0x60, 0xA4, 0x6B, 0xE8, 0xAA, 0x8A, 0x9B, 0xC7
+
+[sha384_hmac_buff_1024]
+digest =
+0x9D, 0xAE, 0x37, 0x87, 0x2C, 0x36, 0xFD, 0x51, 0xF1, 0xF2, 0x4C, 0x82, 0x27, 0xB5, 0x99, 0x63,
+0xAB, 0xD7, 0x62, 0x4A, 0x4E, 0xF1, 0xBF, 0xFB, 0xCA, 0x30, 0x55, 0x3F, 0x43, 0x85, 0xDE, 0x6B,
+0xA2, 0xB2, 0x8B, 0x45, 0x2A, 0x9D, 0x39, 0x29, 0x63, 0x1C, 0x04, 0x47, 0x58, 0x94, 0x5C, 0x91
+
+[sha512_hmac_buff_1024]
+digest =
+0xBF, 0x06, 0x94, 0xBB, 0x2E, 0x9C, 0x0A, 0xA4, 0xF3, 0x5F, 0x52, 0x4B, 0x42, 0x6E, 0xE1, 0x6C,
+0xA8, 0xAB, 0xB7, 0xE9, 0x6F, 0xAB, 0x77, 0xF8, 0x94, 0xD0, 0xA1, 0x81, 0xB8, 0x17, 0x21, 0xAC,
+0xB2, 0x3C, 0x73, 0x71, 0xDD, 0x76, 0xF8, 0x58, 0x84, 0xE7, 0xBB, 0xD4, 0x4A, 0x4F, 0x51, 0xF5,
+0x8C, 0x87, 0xAA, 0xAC, 0xCE, 0x5E, 0xFB, 0xD3, 0x1F, 0xA2, 0x49, 0xF2, 0x40, 0xAB, 0xB8, 0x76
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x56, 0xE7, 0x86, 0x23, 0x2C, 0x77, 0xBE, 0x2B, 0xE6, 0x76, 0xA1, 0xE9, 0xB1, 0x0F, 0x25, 0x15,
+0x1D, 0x59, 0x7F, 0x4A
+
+[sha224_hmac_buff_2048]
+digest =
+0xFD, 0xEB, 0x9E, 0x04, 0x53, 0xC7, 0xEA, 0x56, 0x21, 0x91, 0x6D, 0x8B, 0xDC, 0xA1, 0x0A, 0x2F,
+0x73, 0x4D, 0x05, 0x36, 0x43, 0x58, 0x71, 0xB2, 0x74, 0x6E, 0x7B, 0xAF
+
+[sha256_hmac_buff_2048]
+digest =
+0x25, 0x76, 0xA5, 0x64, 0x00, 0x13, 0xF7, 0xE7, 0x2D, 0x6D, 0x17, 0x36, 0x13, 0xF3, 0xC7, 0x57,
+0x70, 0x30, 0xB2, 0x76, 0x7A, 0xF4, 0x8F, 0xAF, 0x6B, 0x8C, 0x26, 0x88, 0x73, 0x2E, 0x49, 0xC0
+
+[sha384_hmac_buff_2048]
+digest =
+0xF0, 0x69, 0x78, 0x9A, 0x34, 0x88, 0x25, 0x3C, 0x3D, 0xF5, 0x42, 0x65, 0x25, 0x79, 0xB2, 0xFC,
+0x3B, 0x92, 0x46, 0xF9, 0x0D, 0x6D, 0xC1, 0x8E, 0x45, 0xBE, 0x8B, 0x70, 0x7D, 0x1B, 0x7E, 0xDE,
+0x93, 0x04, 0xC8, 0x59, 0x4B, 0x37, 0x2C, 0x20, 0x51, 0xB1, 0x91, 0x4F, 0xA4, 0x30, 0x09, 0xED
+
+[sha512_hmac_buff_2048]
+digest =
+0xAE, 0x8A, 0x42, 0x03, 0x11, 0x25, 0xE8, 0xC3, 0x4B, 0x4B, 0xC0, 0x29, 0x27, 0xE0, 0x0D, 0x27,
+0x13, 0x8F, 0x7D, 0x82, 0x72, 0x94, 0x4B, 0xF8, 0xC3, 0x1A, 0xE1, 0x5A, 0xF3, 0x8E, 0x23, 0x27,
+0x76, 0xE4, 0xF5, 0x3E, 0x24, 0x5B, 0xA3, 0xFA, 0x49, 0x8E, 0x57, 0xE3, 0x88, 0x15, 0x1D, 0xF6,
+0x27, 0xA5, 0xC8, 0xFB, 0x34, 0x44, 0x18, 0x6A, 0x64, 0xBE, 0xFB, 0x1E, 0x87, 0xA8, 0x36, 0x1E
diff --git a/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data
new file mode 100644
index 000000000..8da81611c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/data/aes_cbc_256_sha.data
@@ -0,0 +1,504 @@
+# List of tests for AES-256 CBC:
+# 1) [sha1_hmac_buff_x]
+# 2) [sha224_hmac_buff_x]
+# 3) [sha256_hmac_buff_x]
+# 4) [sha384_hmac_buff_x]
+# 5) [sha512_hmac_buff_x]
+# where x is one of the values: 32, 64, 128, 256, 512, 1024, 2048
+
+##########
+# GLOBAL #
+##########
+plaintext =
+0xff, 0xca, 0xfb, 0xf1, 0x38, 0x20, 0x2f, 0x7b, 0x24, 0x98, 0x26, 0x7d, 0x1d, 0x9f, 0xb3, 0x93,
+0xd9, 0xef, 0xbd, 0xad, 0x4e, 0x40, 0xbd, 0x60, 0xe9, 0x48, 0x59, 0x90, 0x67, 0xd7, 0x2b, 0x7b,
+0x8a, 0xe0, 0x4d, 0xb0, 0x70, 0x38, 0xcc, 0x48, 0x61, 0x7d, 0xee, 0xd6, 0x35, 0x49, 0xae, 0xb4,
+0xaf, 0x6b, 0xdd, 0xe6, 0x21, 0xc0, 0x60, 0xce, 0x0a, 0xf4, 0x1c, 0x2e, 0x1c, 0x8d, 0xe8, 0x7b,
+0x59, 0xda, 0x19, 0x4f, 0xec, 0x07, 0x8e, 0xe2, 0xf0, 0x61, 0xf9, 0x27, 0x61, 0x6f, 0xf8, 0xdf,
+0x62, 0x4d, 0xaf, 0x06, 0xfe, 0x41, 0xa6, 0xa6, 0xf9, 0xa2, 0x06, 0x40, 0xb3, 0x04, 0xbd, 0xe6,
+0xc8, 0x17, 0xfb, 0x56, 0x6f, 0xa9, 0x3b, 0x8e, 0xa6, 0x58, 0xdc, 0x91, 0x17, 0x58, 0x42, 0x95,
+0xa3, 0x7c, 0x81, 0x78, 0xa6, 0x3d, 0x3f, 0x75, 0x74, 0x17, 0x1a, 0xd3, 0x6c, 0x2f, 0x48, 0x39,
+0x20, 0x20, 0xc1, 0x9a, 0x29, 0x84, 0x7d, 0x2d, 0x52, 0xa1, 0xf9, 0x5c, 0xf3, 0x4f, 0x91, 0xfc,
+0x75, 0xcf, 0xd6, 0x2d, 0xe7, 0x9a, 0x59, 0x6e, 0x00, 0x0e, 0x8d, 0x22, 0x17, 0xbd, 0xa0, 0xdd,
+0x79, 0x1f, 0x71, 0xe6, 0xcd, 0x2f, 0xb1, 0xb6, 0xbc, 0xc3, 0xdb, 0x02, 0x91, 0x41, 0x9b, 0x09,
+0xa9, 0xd2, 0x7e, 0xbd, 0x2c, 0x18, 0xae, 0xc0, 0x93, 0x0c, 0x02, 0x9a, 0xdb, 0x4e, 0xaa, 0xeb,
+0x84, 0x4b, 0x43, 0x5e, 0xf0, 0x98, 0xf2, 0x5f, 0x86, 0x70, 0x96, 0x90, 0x15, 0x30, 0xcf, 0x3a,
+0xc9, 0x33, 0x21, 0xec, 0x59, 0x86, 0xfc, 0x65, 0x7d, 0xbe, 0xb9, 0xf8, 0x97, 0xf9, 0x30, 0xa9,
+0x6d, 0xfc, 0x0c, 0x6e, 0x36, 0x67, 0xd5, 0xa6, 0x67, 0xd9, 0xbd, 0x9b, 0x34, 0x5d, 0xa7, 0xdd,
+0xda, 0x46, 0x33, 0x25, 0x60, 0x4a, 0x18, 0xf1, 0x55, 0x07, 0xb2, 0xb7, 0x26, 0x7b, 0xa6, 0x1e,
+0x77, 0xbe, 0x7f, 0x35, 0x46, 0xdf, 0x56, 0x9c, 0x22, 0x19, 0xc8, 0x85, 0xa2, 0x45, 0xb2, 0xad,
+0xf9, 0x26, 0x66, 0xab, 0xfc, 0x97, 0x4b, 0x51, 0x32, 0x36, 0xbc, 0xad, 0xcf, 0x54, 0x3a, 0x4f,
+0x94, 0xdb, 0xd2, 0xf9, 0x67, 0x1b, 0x3b, 0xe5, 0xb2, 0x1d, 0xc5, 0x52, 0x64, 0x2c, 0x06, 0x44,
+0xcf, 0x18, 0x83, 0xe0, 0xd8, 0x04, 0x92, 0xa9, 0xc4, 0x3c, 0x8b, 0xa3, 0x2b, 0xbc, 0x88, 0x7e,
+0xc0, 0x76, 0xa7, 0xe2, 0x7b, 0x47, 0x90, 0xf2, 0xaa, 0x0a, 0x34, 0x1b, 0x91, 0x12, 0xd2, 0xd0,
+0x82, 0x45, 0xf4, 0x57, 0xf1, 0xbd, 0x91, 0x5e, 0xab, 0x41, 0x4c, 0xdf, 0x91, 0x4c, 0xdd, 0x67,
+0x04, 0xa0, 0x98, 0x23, 0x8c, 0x24, 0xbe, 0xd6, 0x80, 0xb3, 0x6d, 0x04, 0xa1, 0x77, 0x43, 0xa5,
+0xee, 0xb7, 0xce, 0xb1, 0x48, 0x43, 0x94, 0x61, 0x15, 0x20, 0x9d, 0xce, 0xd0, 0x14, 0x95, 0x37,
+0xc8, 0x64, 0xa3, 0x2d, 0x3d, 0xe3, 0xff, 0xb4, 0x55, 0x83, 0x84, 0x41, 0x50, 0x57, 0xbd, 0x5a,
+0x0c, 0xe4, 0xda, 0x3b, 0x36, 0x4d, 0x21, 0xb5, 0x6f, 0x73, 0x2a, 0x8c, 0x78, 0x4f, 0x9b, 0x83,
+0xda, 0x11, 0x3c, 0xf0, 0xc9, 0x7e, 0xa6, 0x48, 0x34, 0x53, 0x62, 0xd3, 0x0c, 0xff, 0xb1, 0x74,
+0xd6, 0xea, 0xa5, 0xfc, 0x13, 0x1c, 0x05, 0xa8, 0xc0, 0xbc, 0x95, 0x9c, 0x8c, 0xf6, 0x8c, 0xc3,
+0xf3, 0x69, 0xab, 0x93, 0x65, 0xc0, 0xb7, 0x7e, 0xb0, 0x16, 0x7c, 0xb5, 0x5f, 0x05, 0x28, 0xc9,
+0x09, 0x4e, 0x2a, 0x32, 0x87, 0xb3, 0xab, 0xf8, 0x4c, 0xab, 0xeb, 0x3b, 0x6a, 0xa0, 0x1d, 0x7f,
+0xef, 0xe5, 0x9b, 0xa4, 0xb7, 0xd7, 0xc2, 0x5e, 0x03, 0x0f, 0x99, 0xeb, 0xb1, 0xb1, 0xa6, 0x9d,
+0x1c, 0x7c, 0x5c, 0x94, 0x8b, 0x6e, 0x11, 0x7a, 0xb3, 0x6d, 0x1e, 0x61, 0x64, 0xc3, 0x7d, 0x1c,
+0xb3, 0x54, 0x65, 0x08, 0x3b, 0xda, 0x97, 0xb9, 0x75, 0xc1, 0x2b, 0x3e, 0xa8, 0x5c, 0x3c, 0x2d,
+0x81, 0x5b, 0xbf, 0x5a, 0x13, 0x0e, 0xeb, 0x66, 0xc0, 0x0b, 0x8f, 0x04, 0x68, 0x68, 0x9b, 0xe3,
+0x0d, 0x84, 0xe0, 0xcf, 0x83, 0xd7, 0x62, 0x48, 0xc1, 0x31, 0xa5, 0xd5, 0xbc, 0xe3, 0xa3, 0xa5,
+0xb6, 0xd1, 0xfd, 0x81, 0x91, 0x4d, 0xbd, 0xc4, 0x62, 0x4f, 0xe3, 0xd5, 0x99, 0x14, 0xf1, 0xcd,
+0xf4, 0x7d, 0x13, 0xda, 0x68, 0x0a, 0xca, 0xd6, 0x82, 0x0b, 0xf6, 0xea, 0xad, 0x78, 0xa4, 0xc8,
+0x14, 0x7a, 0xec, 0x11, 0xd3, 0x16, 0x86, 0x9f, 0x17, 0x37, 0x6a, 0x06, 0x56, 0xaa, 0x1b, 0xd1,
+0xaf, 0x85, 0x95, 0x21, 0x36, 0x69, 0xec, 0x1b, 0x56, 0x84, 0x01, 0x3f, 0x4d, 0x34, 0x3d, 0x2d,
+0x38, 0x57, 0x2d, 0x7e, 0xd9, 0x7b, 0x2d, 0x81, 0x86, 0xd4, 0x7c, 0x83, 0x12, 0x1d, 0x9d, 0x27,
+0x72, 0x1b, 0x5e, 0xf4, 0x15, 0xa5, 0xcd, 0xb7, 0x5f, 0xbb, 0x49, 0xa1, 0xd9, 0xdd, 0x8d, 0xad,
+0xa9, 0x2c, 0x65, 0x18, 0x91, 0xfd, 0xd2, 0xd4, 0x09, 0x60, 0x0c, 0xfd, 0xa4, 0xe1, 0x25, 0x87,
+0x32, 0x64, 0x7b, 0x99, 0xd7, 0x61, 0x2f, 0xd4, 0x73, 0xdd, 0x85, 0x26, 0x08, 0x92, 0xc0, 0xe1,
+0x4f, 0x0c, 0x76, 0x5b, 0x26, 0x69, 0xdb, 0x78, 0x35, 0x65, 0xb9, 0x58, 0x1f, 0x9c, 0x0f, 0x18,
+0x95, 0xfe, 0x40, 0xfc, 0xf7, 0x93, 0x71, 0x70, 0x8b, 0x73, 0xdc, 0xb0, 0x88, 0x72, 0x19, 0x26,
+0x94, 0x26, 0xa7, 0xaa, 0x00, 0x72, 0x61, 0x53, 0xd2, 0x5d, 0x8f, 0x5e, 0x51, 0x88, 0x2d, 0xa4,
+0x28, 0xd5, 0xaf, 0x2d, 0xd2, 0x84, 0x39, 0x75, 0x1e, 0xe7, 0xf0, 0x23, 0xc0, 0x4f, 0x8d, 0xdd,
+0x5c, 0x90, 0xef, 0x6e, 0x53, 0xe0, 0x54, 0x67, 0xe1, 0x5b, 0x10, 0xf1, 0xf5, 0xf8, 0x64, 0x34,
+0x94, 0xeb, 0x37, 0xf7, 0xe9, 0xaa, 0x6c, 0xa4, 0xd8, 0x74, 0x6d, 0xca, 0x8d, 0x1a, 0x31, 0x73,
+0xca, 0xb4, 0xc7, 0x47, 0x34, 0x7f, 0xf8, 0x24, 0x9b, 0xfa, 0xc9, 0xcc, 0xa8, 0x61, 0xb4, 0x0e,
+0x4d, 0x68, 0xc7, 0xa0, 0xcb, 0xea, 0xf0, 0xcc, 0x0a, 0x6c, 0xf2, 0x33, 0x42, 0x99, 0x6c, 0xd8,
+0x74, 0x7f, 0x1e, 0x8a, 0xa3, 0x0a, 0x48, 0x4b, 0x7e, 0xbe, 0xdb, 0x7f, 0x56, 0x69, 0x43, 0xe8,
+0xbf, 0x12, 0xc4, 0x7b, 0xc2, 0xd9, 0xfa, 0x5c, 0xeb, 0x45, 0xca, 0x07, 0x3d, 0xc0, 0xcd, 0x68,
+0x8b, 0xd0, 0x79, 0xea, 0x0a, 0x78, 0x06, 0xdc, 0x81, 0xd7, 0x32, 0x18, 0xb3, 0x65, 0xbe, 0x47,
+0xbb, 0xfa, 0x17, 0x09, 0xe9, 0x31, 0x95, 0x30, 0xef, 0x07, 0x44, 0xec, 0xd0, 0x98, 0x98, 0xc0,
+0x6b, 0x71, 0x5b, 0x23, 0xb8, 0xb6, 0xd2, 0x21, 0xff, 0x51, 0xdd, 0xae, 0x48, 0x29, 0x75, 0x0c,
+0xc3, 0x3d, 0x91, 0xfe, 0x9d, 0xa8, 0x5e, 0xb2, 0x34, 0xb2, 0xd3, 0x81, 0xf6, 0x27, 0x9c, 0xac,
+0x6b, 0x20, 0x56, 0x86, 0xa5, 0x4f, 0x7a, 0xdb, 0xf9, 0xac, 0xa9, 0x8e, 0xe3, 0x73, 0x21, 0x99,
+0x71, 0x2d, 0xaf, 0x27, 0x92, 0x0c, 0xc7, 0xd3, 0x85, 0xb3, 0x40, 0xda, 0x13, 0x4a, 0x04, 0x41,
+0x54, 0xf8, 0xf2, 0x55, 0xb7, 0x80, 0xdd, 0x77, 0xba, 0x01, 0x7a, 0x31, 0xbd, 0x6b, 0xdc, 0x5c,
+0x59, 0xf4, 0x2b, 0xca, 0x25, 0xbb, 0x50, 0xba, 0xfa, 0x42, 0x38, 0xd2, 0x28, 0x10, 0x8b, 0x7b,
+0x96, 0x45, 0x30, 0xbb, 0x7f, 0xf4, 0x5a, 0xf7, 0x28, 0x6f, 0x47, 0xdc, 0xd2, 0x82, 0xf2, 0xf7,
+0xdd, 0x20, 0xb5, 0x0c, 0x7e, 0x53, 0x85, 0xa7, 0xfc, 0x3b, 0x1a, 0xc0, 0x07, 0x7b, 0xa1, 0x43,
+0x05, 0x18, 0x19, 0xd3, 0xfc, 0x41, 0xc2, 0xce, 0xd9, 0x5b, 0x4b, 0x63, 0xe2, 0x8f, 0x86, 0x3a,
+0xd1, 0xd0, 0x1d, 0x74, 0x2e, 0xbc, 0xd3, 0xce, 0x08, 0x0c, 0x10, 0x7a, 0x42, 0x60, 0xc5, 0x3a,
+0xa6, 0xd8, 0xb0, 0x52, 0xcf, 0x53, 0x28, 0x70, 0x45, 0xb7, 0x72, 0x7d, 0x77, 0x66, 0x54, 0x3d,
+0x38, 0x26, 0xcf, 0xd5, 0xbf, 0xe4, 0x80, 0x10, 0xba, 0x2b, 0xe8, 0xdc, 0xc3, 0xfe, 0x28, 0xa3,
+0x52, 0x58, 0x70, 0x4a, 0xde, 0x84, 0x33, 0x5e, 0x93, 0x04, 0xa4, 0x7c, 0xe7, 0xea, 0x8e, 0xba,
+0xeb, 0x8a, 0x19, 0x26, 0x6a, 0x7f, 0x7c, 0x4a, 0x5b, 0xb4, 0x0d, 0xfc, 0xc8, 0x11, 0x1b, 0x41,
+0x68, 0x5d, 0x2a, 0x25, 0x04, 0x4f, 0xc8, 0xf4, 0x65, 0xfc, 0xb9, 0x58, 0xeb, 0xb4, 0x67, 0x50,
+0x24, 0xf5, 0x43, 0xf6, 0x91, 0x4a, 0xb0, 0x0f, 0x32, 0xe0, 0x07, 0x75, 0x69, 0x1b, 0x3c, 0xeb,
+0xb2, 0x65, 0x26, 0x6f, 0xb8, 0x79, 0xe0, 0x78, 0x8c, 0xdc, 0x39, 0x24, 0x48, 0x76, 0x11, 0xd4,
+0x3a, 0xc5, 0xd2, 0x2b, 0xaa, 0x55, 0xfb, 0x92, 0x12, 0x2d, 0x88, 0x05, 0xd1, 0xb1, 0x31, 0x36,
+0x1f, 0xc2, 0x44, 0x1c, 0xab, 0x2e, 0xcd, 0x1c, 0x72, 0x86, 0xf6, 0x83, 0x87, 0x2e, 0x8b, 0xdb,
+0xaa, 0x16, 0x0e, 0x1b, 0xe6, 0x5c, 0x4d, 0x2f, 0x82, 0xbd, 0x49, 0x11, 0x60, 0x22, 0x0f, 0xde,
+0x3b, 0x2b, 0x20, 0x1d, 0x56, 0xb7, 0x21, 0xae, 0x0b, 0x26, 0x4f, 0xde, 0x3d, 0xa6, 0x3f, 0x61,
+0x81, 0xe2, 0x76, 0x60, 0x08, 0xc5, 0x4b, 0x18, 0x0b, 0xd1, 0xf5, 0xff, 0x8d, 0x1a, 0x96, 0x76,
+0x51, 0x15, 0x05, 0x4d, 0x8c, 0x6b, 0x12, 0x90, 0x47, 0xd4, 0xa4, 0x38, 0xb9, 0x48, 0xe4, 0x4c,
+0x05, 0x69, 0x6a, 0x8b, 0x9d, 0x7c, 0xa1, 0xbc, 0x77, 0xeb, 0x86, 0x93, 0x0a, 0x15, 0x84, 0xba,
+0x8f, 0xf5, 0x7c, 0x44, 0x75, 0x31, 0x79, 0x16, 0xc1, 0x81, 0x1a, 0xb6, 0xe6, 0x6c, 0x3d, 0xb8,
+0x15, 0x46, 0xf5, 0xbe, 0x46, 0x04, 0xa6, 0xec, 0xec, 0xd1, 0x74, 0x8b, 0x87, 0x2b, 0xdb, 0xd0,
+0x9f, 0xb3, 0x99, 0x9d, 0x87, 0x8c, 0xc6, 0xaa, 0xd4, 0x64, 0x45, 0xbd, 0xe8, 0xed, 0xa3, 0xc1,
+0x2a, 0x41, 0x1e, 0x26, 0xaf, 0x86, 0x16, 0xed, 0x80, 0x08, 0xca, 0x64, 0x21, 0x3a, 0xce, 0x21,
+0x4c, 0x41, 0xb9, 0x13, 0x2d, 0xf7, 0x1b, 0xdf, 0x2b, 0x33, 0x69, 0xe7, 0x5c, 0x8c, 0x7b, 0xfb,
+0xe3, 0x41, 0xe9, 0xce, 0xd7, 0xff, 0x0e, 0x54, 0xfe, 0xb0, 0x71, 0x78, 0xdc, 0xde, 0x7e, 0xdd,
+0x1f, 0x1c, 0x4a, 0x8f, 0x3e, 0x16, 0xfd, 0x91, 0x82, 0x94, 0xd4, 0xc2, 0xf7, 0xb2, 0x77, 0x89,
+0x16, 0x2c, 0xba, 0xb6, 0xbd, 0xed, 0x95, 0x43, 0x05, 0x9b, 0xf2, 0xc4, 0xbe, 0x46, 0x43, 0x90,
+0x1d, 0xd8, 0x24, 0x02, 0xd2, 0xea, 0xf4, 0x08, 0xd9, 0xf7, 0x84, 0x0e, 0xc6, 0xe7, 0x44, 0xdb,
+0xb8, 0xac, 0x0a, 0x53, 0x39, 0x61, 0x43, 0xdc, 0x22, 0x28, 0x8f, 0x22, 0x2f, 0x73, 0xbf, 0x59,
+0x2d, 0x3c, 0x8c, 0x0b, 0xcc, 0x2a, 0x67, 0xe0, 0x5b, 0x5c, 0x65, 0x5e, 0x6d, 0x98, 0x99, 0xaa,
+0x3b, 0x89, 0x12, 0xe2, 0x99, 0xf6, 0x15, 0xa7, 0xd2, 0x6a, 0x79, 0xb4, 0xf6, 0x0b, 0xf5, 0x0d,
+0x2d, 0x4c, 0xcb, 0x1b, 0x35, 0x93, 0x61, 0x32, 0xa1, 0x8a, 0xa8, 0x27, 0xe8, 0x95, 0x5a, 0x56,
+0x59, 0x04, 0xfe, 0xce, 0xc2, 0xd8, 0x92, 0x97, 0xb2, 0x54, 0x63, 0xd0, 0x3b, 0xde, 0x10, 0x34,
+0x32, 0x16, 0x05, 0x51, 0x1d, 0xfc, 0x96, 0x8e, 0xf1, 0xf6, 0x4b, 0xd7, 0x48, 0x22, 0xce, 0xca,
+0x1c, 0x6b, 0xab, 0x1f, 0x59, 0xa2, 0x74, 0xd6, 0xcd, 0x15, 0x07, 0xab, 0xa2, 0xd5, 0x22, 0x81,
+0xec, 0x20, 0x14, 0x36, 0xac, 0xe4, 0x25, 0x7d, 0xe6, 0x09, 0x00, 0x2c, 0x92, 0x4d, 0x4e, 0xbf,
+0xbf, 0xa1, 0xd4, 0xbe, 0x6b, 0xd4, 0x1f, 0x95, 0x9b, 0xf3, 0xda, 0x99, 0xad, 0xa4, 0x6c, 0x73,
+0x55, 0xd1, 0x9d, 0x4b, 0x16, 0xd4, 0x06, 0xec, 0x46, 0x3d, 0xb7, 0xe7, 0xce, 0xd0, 0x1d, 0x94,
+0x65, 0xde, 0x61, 0xb3, 0xc1, 0x10, 0x65, 0xe5, 0x68, 0x9b, 0xb0, 0xb4, 0x43, 0x0b, 0x92, 0xaf,
+0xb7, 0x40, 0xa2, 0xe5, 0x06, 0x3d, 0x72, 0x00, 0xc5, 0x39, 0xab, 0x35, 0x29, 0x22, 0x4c, 0xa5,
+0xa5, 0x3f, 0x22, 0x90, 0x53, 0xd2, 0x36, 0x63, 0x1e, 0xd3, 0x33, 0xa5, 0xbb, 0x3d, 0xa3, 0x0c,
+0x14, 0x9c, 0x2e, 0x6d, 0x9a, 0x7a, 0xf7, 0xf1, 0x56, 0x66, 0xe5, 0x8d, 0x53, 0x83, 0x34, 0x3f,
+0xa9, 0x83, 0x84, 0x68, 0x90, 0xc9, 0x51, 0xc2, 0xd4, 0x8e, 0x6c, 0xc7, 0x6d, 0xa7, 0x19, 0x61,
+0xa7, 0x2e, 0x36, 0xbc, 0xd2, 0x0f, 0x17, 0x49, 0xd4, 0x6b, 0x36, 0x63, 0xfb, 0x1d, 0xf4, 0xb0,
+0x6b, 0xcf, 0x34, 0x5f, 0xd2, 0x77, 0xae, 0x12, 0xaf, 0xb3, 0xdf, 0x52, 0xf7, 0xc2, 0xc8, 0xf2,
+0x63, 0x61, 0xb6, 0x3e, 0x39, 0xf2, 0xa7, 0x1a, 0x89, 0x9d, 0x0e, 0x8f, 0xaf, 0xe1, 0x01, 0x24,
+0xa6, 0x3a, 0xd5, 0x9a, 0x62, 0x67, 0xa3, 0x66, 0xee, 0xbc, 0xc5, 0x94, 0x4b, 0xc3, 0x15, 0xa1,
+0x7e, 0x07, 0x07, 0x2b, 0xb7, 0x43, 0x2a, 0xb4, 0xb8, 0x25, 0x88, 0x86, 0x23, 0xab, 0xdf, 0x05,
+0xbe, 0x46, 0x56, 0xd7, 0xda, 0xd6, 0x75, 0x53, 0xd9, 0xc8, 0x26, 0x8f, 0x39, 0x67, 0xed, 0x21,
+0x53, 0x1c, 0x9c, 0x89, 0x46, 0xd3, 0xfe, 0x54, 0xe6, 0x1d, 0x02, 0xb9, 0x25, 0x82, 0x66, 0xe6,
+0xf9, 0x45, 0xd9, 0x3f, 0xa5, 0x71, 0xc1, 0x46, 0x66, 0x7a, 0x27, 0x8a, 0x82, 0xc9, 0x21, 0xe9,
+0x17, 0xab, 0x6c, 0xef, 0x45, 0xe5, 0x88, 0x93, 0x87, 0x80, 0xb3, 0x85, 0x25, 0x96, 0x19, 0x41,
+0xab, 0xd6, 0xba, 0x92, 0x76, 0x21, 0x8a, 0x58, 0xbd, 0xe2, 0x4b, 0xec, 0x45, 0x59, 0x2c, 0x13,
+0x1a, 0xb5, 0x13, 0x25, 0x44, 0xe7, 0x71, 0x26, 0x0a, 0x34, 0x33, 0xb9, 0x57, 0x15, 0xa4, 0x90,
+0x60, 0x11, 0x05, 0x8e, 0xc8, 0x8e, 0x74, 0x52, 0x4b, 0x31, 0x71, 0xeb, 0x66, 0x7e, 0xee, 0xb1,
+0x0a, 0x21, 0x52, 0xc0, 0x1a, 0xe9, 0xa1, 0x5a, 0xe3, 0x3a, 0x24, 0xfb, 0xf3, 0x1e, 0xd6, 0x83,
+0x1d, 0xfb, 0x81, 0xa8, 0x91, 0x60, 0x9e, 0xbc, 0x59, 0x20, 0xc9, 0x9e, 0x71, 0x19, 0x83, 0x2b,
+0x6a, 0x48, 0x4e, 0x6b, 0x46, 0x82, 0x89, 0xda, 0x60, 0xff, 0x1a, 0x46, 0x94, 0x55, 0xda, 0xe5,
+0x99, 0xfa, 0x84, 0xd7, 0x3b, 0xb9, 0xa5, 0x34, 0x87, 0x86, 0x5e, 0x6d, 0x75, 0x9a, 0xe7, 0x09,
+0xb8, 0xe6, 0x71, 0x15, 0x10, 0x56, 0xd7, 0xc1, 0xc8, 0xb2, 0x62, 0xbc, 0xec, 0xe0, 0x94, 0xa0,
+0xcd, 0xb4, 0x04, 0xa9, 0xc3, 0x51, 0xee, 0xf8, 0x2e, 0x42, 0x9a, 0xaa, 0x34, 0xd3, 0xb9, 0xb0,
+0x36, 0xf9, 0x47, 0xc1, 0x07, 0x49, 0xde, 0xb8, 0x32, 0x8a, 0x87, 0x68, 0x56, 0x9a, 0x35, 0x79,
+0xd1, 0xac, 0x49, 0x38, 0xc6, 0xfe, 0xfd, 0xdf, 0x6f, 0x3c, 0xda, 0x48, 0xbd, 0x23, 0xfd, 0x85,
+0xf0, 0x96, 0xee, 0x1c, 0x27, 0x18, 0x86, 0xa6, 0xf0, 0x7b, 0xd8, 0x3c, 0xc7, 0x22, 0x3e, 0x2f,
+0xac, 0xb1, 0x37, 0xbd, 0x84, 0x4b, 0xe3, 0x92, 0x82, 0xd0, 0x25, 0x14, 0x22, 0x65, 0xed, 0xeb,
+0xef, 0xb9, 0xb6, 0xe4, 0x95, 0x18, 0x0d, 0x2b, 0x8d, 0x4f, 0xaf, 0xc0, 0xa0, 0x05, 0x8b, 0x35,
+0x5b, 0x94, 0xb2, 0x68, 0x26, 0x4f, 0x4a, 0x9e, 0x85, 0x0e, 0x46, 0xe0, 0x4f, 0x60, 0x66, 0x01,
+0xa4, 0x39, 0xe8, 0x8b, 0x2a, 0x50, 0xf5, 0x18, 0x70, 0xe2, 0xfc, 0xd6, 0xbe, 0xd3, 0x46, 0x4b
+
+ciphertext =
+0x77, 0xF9, 0xF7, 0x7A, 0xA3, 0xCB, 0x68, 0x1A, 0x11, 0x70, 0xD8, 0x7A, 0xB6, 0xE2, 0x37, 0x7E,
+0xD1, 0x57, 0x1C, 0x8E, 0x85, 0xD8, 0x08, 0xBF, 0x57, 0x1F, 0x21, 0x6C, 0xAD, 0xAD, 0x47, 0x1E,
+0x0D, 0x6B, 0x79, 0x39, 0x15, 0x4E, 0x5B, 0x59, 0x2D, 0x76, 0x87, 0xA6, 0xD6, 0x47, 0x8F, 0x82,
+0xB8, 0x51, 0x91, 0x32, 0x60, 0xCB, 0x97, 0xDE, 0xBE, 0xF0, 0xAD, 0xFC, 0x23, 0x2E, 0x22, 0x02,
+0x46, 0x17, 0x3F, 0x8F, 0x24, 0x0E, 0x31, 0x80, 0xEA, 0xD6, 0x85, 0x50, 0xA5, 0xEE, 0xB7, 0x15,
+0xD0, 0x2F, 0xA6, 0x92, 0xEF, 0xCD, 0x8B, 0x91, 0x4A, 0xEA, 0x03, 0x92, 0xB4, 0x65, 0x19, 0x66,
+0x9E, 0x73, 0x79, 0xCE, 0xA7, 0x4D, 0x8B, 0x77, 0x74, 0x44, 0x1C, 0x9F, 0xEE, 0x15, 0x91, 0xF2,
+0xF9, 0x50, 0x7D, 0x2A, 0xC2, 0x6B, 0x58, 0x36, 0xF7, 0x62, 0x25, 0x9C, 0x71, 0x34, 0x43, 0x14,
+0x9E, 0x17, 0xF7, 0xB7, 0x56, 0x1D, 0x91, 0x4C, 0xF6, 0x6C, 0xF2, 0x19, 0x39, 0xA2, 0x29, 0xA3,
+0x22, 0x4F, 0x14, 0x18, 0x76, 0x8A, 0x59, 0xAD, 0x3E, 0x5F, 0xDC, 0xC9, 0x80, 0x07, 0x51, 0xB2,
+0x90, 0x6A, 0xB9, 0x0C, 0xA4, 0x3F, 0x42, 0xBD, 0x40, 0xB7, 0xA7, 0xF5, 0x85, 0xBF, 0xEA, 0xD8,
+0x89, 0xA9, 0xE9, 0xC7, 0x25, 0xEC, 0xFF, 0x80, 0xE8, 0x94, 0x3B, 0xE7, 0xD1, 0x68, 0xDA, 0x1C,
+0xFA, 0x5D, 0xCD, 0x68, 0x09, 0x72, 0x63, 0xBA, 0x34, 0x56, 0xD4, 0x5F, 0xB0, 0xA7, 0xAE, 0xCF,
+0xFB, 0xA8, 0xBD, 0x52, 0x79, 0x98, 0xF6, 0x39, 0x52, 0xD3, 0xA7, 0xE1, 0xFB, 0x75, 0x76, 0x87,
+0xBC, 0x11, 0x18, 0x17, 0x47, 0x65, 0xDA, 0xE3, 0x25, 0x3E, 0x17, 0x43, 0x7B, 0x0D, 0x8B, 0x7F,
+0x20, 0xFF, 0x03, 0xFA, 0x28, 0xC7, 0xD3, 0xF8, 0xC2, 0xA8, 0xC1, 0xE5, 0xDA, 0x77, 0x41, 0x28,
+0x06, 0xC4, 0x20, 0xFC, 0x1B, 0xAA, 0x99, 0x78, 0x5C, 0x28, 0xDA, 0x9A, 0x2B, 0x6C, 0x56, 0x7E,
+0x63, 0x34, 0xCF, 0xCD, 0x5D, 0xB6, 0x13, 0xF5, 0x98, 0x08, 0x2E, 0x02, 0x2C, 0x63, 0xEC, 0xE3,
+0x43, 0xE8, 0x3B, 0xE6, 0x59, 0x8C, 0x61, 0x60, 0xDD, 0x33, 0x3F, 0x29, 0xA4, 0xA5, 0xD5, 0x33,
+0xEF, 0xAA, 0x7E, 0x8C, 0xAE, 0x9C, 0x1B, 0x0D, 0x74, 0xF6, 0x01, 0x8C, 0xF1, 0x04, 0xEB, 0x62,
+0x75, 0xC0, 0x98, 0x24, 0xB2, 0xDF, 0xB1, 0xBA, 0x50, 0xC3, 0x01, 0x5B, 0x13, 0x3A, 0xF9, 0x7A,
+0xF6, 0xF4, 0x75, 0xAF, 0x55, 0x54, 0x10, 0xBE, 0x11, 0x91, 0x7D, 0xF6, 0x66, 0x79, 0xE6, 0x4D,
+0x0E, 0x0B, 0x70, 0x3C, 0x00, 0x68, 0x2E, 0xA3, 0x84, 0xCE, 0xE1, 0x0A, 0xDC, 0xFE, 0xF9, 0xD2,
+0x59, 0x23, 0x05, 0xCA, 0x79, 0xF0, 0x89, 0xB9, 0x76, 0xD9, 0xAA, 0x04, 0x43, 0x30, 0x97, 0x15,
+0x59, 0x0B, 0x7C, 0x22, 0x0E, 0x72, 0xC6, 0x61, 0x19, 0x35, 0xC3, 0x6A, 0xF2, 0x6B, 0x39, 0xB6,
+0x1B, 0xD3, 0xE3, 0xF7, 0xCB, 0x46, 0x26, 0x97, 0x39, 0xBA, 0x41, 0xD8, 0xA4, 0x48, 0x96, 0xBC,
+0x22, 0x38, 0xCF, 0xE2, 0xCF, 0xD6, 0x36, 0x30, 0xD9, 0x96, 0x73, 0xAF, 0xA4, 0x0F, 0x52, 0x9D,
+0x64, 0x28, 0xAB, 0x3D, 0xF7, 0x1B, 0xA6, 0xDB, 0x47, 0x09, 0x45, 0x48, 0x30, 0x27, 0x4B, 0x37,
+0x38, 0x5B, 0xC5, 0x90, 0x8C, 0xCC, 0x82, 0x48, 0x7A, 0x98, 0x1C, 0x46, 0x24, 0xB1, 0xDA, 0xB9,
+0x6C, 0x30, 0x48, 0xF3, 0x6C, 0x84, 0xBD, 0x3F, 0x95, 0x3E, 0xC1, 0x27, 0x8B, 0x3C, 0x2F, 0xDA,
+0xD9, 0xF6, 0x54, 0x73, 0x04, 0x38, 0xD6, 0x45, 0xC5, 0x5C, 0x92, 0xDE, 0xB2, 0xE3, 0x62, 0x31,
+0xCE, 0x70, 0xD7, 0x11, 0x5E, 0x7A, 0x63, 0x0F, 0xA1, 0xD4, 0x8A, 0x2B, 0xDE, 0x38, 0xAA, 0x9F,
+0x33, 0x71, 0x67, 0x05, 0xDB, 0x48, 0xE4, 0x09, 0x73, 0x3A, 0x35, 0x1F, 0xC2, 0x0F, 0x44, 0x99,
+0x35, 0xBD, 0xBD, 0x7E, 0x85, 0x77, 0x46, 0x3A, 0x41, 0x79, 0xAB, 0x67, 0xA5, 0x87, 0xBD, 0x96,
+0xAE, 0xC2, 0x99, 0x35, 0xC3, 0xCA, 0x90, 0x36, 0xB1, 0x15, 0x9C, 0x37, 0x62, 0x54, 0xCA, 0x72,
+0x10, 0x07, 0x07, 0x6E, 0x1D, 0xD0, 0xFE, 0x4C, 0xE8, 0x48, 0x92, 0x7A, 0xA1, 0x7B, 0xA5, 0xAC,
+0xF7, 0xE1, 0x99, 0xC0, 0x99, 0x20, 0xD5, 0x07, 0x77, 0x1D, 0xE5, 0x14, 0x36, 0xA6, 0xF3, 0x77,
+0x9B, 0x61, 0x87, 0x98, 0xD6, 0xD6, 0xF8, 0xE6, 0x34, 0x37, 0x6F, 0x58, 0x29, 0x97, 0x2D, 0xE6,
+0xD1, 0x56, 0xB1, 0xBB, 0x35, 0xBD, 0x2B, 0x44, 0xAD, 0x30, 0x0F, 0x1D, 0x48, 0x5F, 0xDD, 0x58,
+0x7C, 0xB8, 0x2C, 0x2E, 0x26, 0x9B, 0xDA, 0x55, 0x01, 0x06, 0x66, 0xB0, 0x3C, 0xAB, 0xA0, 0x60,
+0x98, 0xF4, 0x72, 0xAF, 0xBC, 0x00, 0xAA, 0x57, 0x6A, 0xD8, 0x47, 0xC7, 0xC1, 0xCE, 0xB1, 0x05,
+0x45, 0x84, 0x63, 0x1E, 0x9C, 0x47, 0x11, 0xB4, 0xE6, 0x80, 0x8D, 0x3E, 0xFF, 0xE9, 0xD9, 0x3A,
+0x56, 0x3D, 0x41, 0x68, 0x2C, 0x6C, 0xA2, 0x23, 0x4C, 0xD6, 0x08, 0x91, 0x93, 0xCD, 0xAA, 0xF7,
+0xAA, 0x2B, 0x55, 0xEC, 0x53, 0xE8, 0xD9, 0x2E, 0xCB, 0xE0, 0x67, 0x1D, 0x9F, 0xFF, 0x94, 0xB8,
+0xBA, 0x82, 0xA7, 0x6A, 0x8C, 0x61, 0x7C, 0x58, 0x90, 0xA5, 0x11, 0x57, 0x21, 0xCF, 0x30, 0xB0,
+0x97, 0x44, 0x7D, 0x1D, 0xD3, 0x91, 0x3F, 0xC2, 0x4F, 0x0E, 0x3B, 0x57, 0x3A, 0x1F, 0x85, 0x82,
+0x79, 0x91, 0x03, 0xB4, 0x9B, 0x70, 0x2A, 0x5F, 0x8B, 0x20, 0x66, 0x6F, 0xF4, 0x10, 0x96, 0x52,
+0x4C, 0x77, 0xA2, 0x45, 0x28, 0xF8, 0xAD, 0xA3, 0x8C, 0x99, 0x3F, 0xD2, 0x39, 0x4A, 0x1A, 0x3A,
+0x72, 0x7E, 0x47, 0x49, 0x25, 0x63, 0x87, 0xCB, 0xEA, 0x89, 0x1D, 0x7F, 0x0C, 0x86, 0x9A, 0x8E,
+0xB1, 0x0C, 0xFF, 0xC6, 0xF2, 0xB1, 0x01, 0x99, 0xEA, 0xF1, 0x4A, 0xF1, 0xF3, 0x71, 0x4B, 0x92,
+0xC6, 0xD6, 0xD8, 0x26, 0xE8, 0x28, 0xF2, 0xF5, 0x5B, 0xE8, 0xF1, 0xE4, 0x4B, 0x36, 0x46, 0xD3,
+0x12, 0x2F, 0x98, 0x61, 0x12, 0xD9, 0x26, 0x58, 0x5C, 0x80, 0x7C, 0x71, 0x4E, 0x57, 0x9A, 0xAC,
+0x59, 0xE0, 0xC3, 0x70, 0x55, 0x57, 0xAE, 0x55, 0xF6, 0xCF, 0x6A, 0xF0, 0x10, 0xDC, 0xF4, 0xED,
+0xCC, 0x32, 0x4B, 0xAC, 0xC1, 0x4B, 0x2F, 0x62, 0x69, 0xD2, 0x15, 0x63, 0x39, 0xD5, 0x29, 0x09,
+0xA2, 0xB5, 0xC7, 0xBC, 0xFA, 0xC7, 0xC7, 0x8C, 0x64, 0xCF, 0x43, 0x9B, 0x4C, 0x60, 0x97, 0x33,
+0xA2, 0xB9, 0x0F, 0x70, 0x05, 0x89, 0x56, 0x62, 0xB1, 0x48, 0x08, 0xB5, 0x77, 0x4C, 0x60, 0x24,
+0x1D, 0x35, 0xEF, 0xD6, 0x53, 0xB0, 0x2E, 0x7F, 0xA6, 0x4B, 0x94, 0xE7, 0xCD, 0xC4, 0xFE, 0xC4,
+0x12, 0x7A, 0xAB, 0xD4, 0x05, 0xA5, 0x32, 0xD4, 0xA1, 0x8D, 0x9C, 0x22, 0x10, 0xDD, 0x39, 0x66,
+0x96, 0x79, 0x49, 0x19, 0x80, 0x1C, 0xE1, 0x1F, 0x01, 0x69, 0x37, 0x03, 0xB5, 0x22, 0x8F, 0x95,
+0xF7, 0xBD, 0x36, 0x89, 0x38, 0x37, 0x29, 0x6C, 0x0E, 0x89, 0x55, 0x4D, 0xC9, 0x64, 0xD3, 0xD5,
+0x9B, 0xB0, 0x51, 0x43, 0xBB, 0xA6, 0x6B, 0xFF, 0x13, 0xB6, 0x1A, 0x06, 0xF3, 0x86, 0x51, 0xFD,
+0xB9, 0xC8, 0x26, 0xA9, 0x8A, 0x4A, 0xC1, 0xE0, 0xD9, 0x3D, 0x31, 0x48, 0x39, 0xC8, 0x48, 0xC7,
+0xDE, 0xB1, 0x58, 0x0F, 0x4D, 0xEC, 0x5B, 0x32, 0x9C, 0x8B, 0xF4, 0x3A, 0x02, 0xE2, 0x92, 0x4A,
+0x7D, 0xCD, 0x38, 0x07, 0x4F, 0xBA, 0xD1, 0xD4, 0xE4, 0x3C, 0xB0, 0x4D, 0xB7, 0xEF, 0xFB, 0x06,
+0xA9, 0x83, 0x20, 0x0D, 0x7A, 0x1F, 0x15, 0x02, 0x70, 0x08, 0x8B, 0x91, 0xE6, 0xFD, 0x8C, 0x0B,
+0x3C, 0xEA, 0x1F, 0x94, 0xB6, 0x17, 0xC6, 0xB2, 0x07, 0x2C, 0x73, 0x7A, 0x4A, 0x76, 0x5F, 0x30,
+0x38, 0xE5, 0x22, 0xC6, 0xA3, 0xA7, 0x4D, 0x6A, 0x3A, 0xA7, 0x82, 0x90, 0xBE, 0xD1, 0xE9, 0x89,
+0x2F, 0xF0, 0xC9, 0x0A, 0xB6, 0xDA, 0x0D, 0x3E, 0x25, 0x8E, 0x99, 0xB2, 0x06, 0xE3, 0x65, 0x53,
+0x3F, 0x1A, 0xD9, 0x45, 0xCE, 0x10, 0xBE, 0x2E, 0xF4, 0x4F, 0x60, 0x25, 0xA7, 0x0A, 0xAE, 0x82,
+0x92, 0xAE, 0xC0, 0xFF, 0xAB, 0x49, 0x97, 0x5C, 0x53, 0x73, 0x4E, 0x78, 0x1A, 0x65, 0x42, 0xD5,
+0x6F, 0x1E, 0xE2, 0x25, 0x76, 0x3B, 0x6D, 0xF8, 0xBC, 0xBD, 0x3A, 0xDE, 0xB5, 0xFB, 0xBD, 0x90,
+0xDC, 0xC2, 0xB8, 0x90, 0xD4, 0x03, 0xD2, 0xDD, 0x35, 0x86, 0x48, 0x58, 0xB4, 0xCB, 0x10, 0xB2,
+0x31, 0xBD, 0x6C, 0x16, 0x92, 0x7A, 0x3D, 0x67, 0x45, 0x6B, 0x57, 0x26, 0xD2, 0xC2, 0xAF, 0xB1,
+0xAB, 0x82, 0x4B, 0x95, 0x08, 0x7D, 0x48, 0x1D, 0x17, 0x9D, 0x8B, 0x16, 0xCF, 0xE0, 0x16, 0x94,
+0xE1, 0xA6, 0xFC, 0x6C, 0xE1, 0x71, 0x3C, 0x57, 0x7F, 0x17, 0xC8, 0x4E, 0xFF, 0x16, 0x46, 0x1E,
+0x21, 0x27, 0x05, 0x41, 0xD3, 0x19, 0x28, 0x58, 0x86, 0xFB, 0x5A, 0xEF, 0xC3, 0x00, 0xE7, 0xA3,
+0x25, 0x1A, 0x94, 0x41, 0xE3, 0x50, 0x98, 0x94, 0x29, 0x42, 0x1F, 0x1C, 0x69, 0x46, 0xF4, 0x89,
+0x30, 0x4E, 0x5C, 0xCE, 0x2F, 0x65, 0xC5, 0x34, 0x71, 0xB7, 0xD9, 0x54, 0xB2, 0xC1, 0xCC, 0xED,
+0x14, 0x3E, 0xF1, 0x7B, 0x5F, 0xAE, 0xD3, 0x8F, 0xA2, 0x18, 0x12, 0x15, 0x23, 0x92, 0x75, 0x61,
+0xFF, 0xFA, 0x8F, 0xD1, 0x77, 0xC8, 0xC7, 0xA3, 0x44, 0x9F, 0x06, 0x2B, 0x1E, 0xA4, 0x4D, 0x4F,
+0x8E, 0x9A, 0x02, 0xA8, 0x4A, 0x67, 0x5D, 0x2D, 0x59, 0xFD, 0x1A, 0x8F, 0xE6, 0x52, 0x0C, 0xC7,
+0x4A, 0x95, 0xAF, 0xDD, 0x04, 0x76, 0x26, 0xCE, 0x4C, 0x97, 0x4E, 0x55, 0x9C, 0x28, 0xA4, 0x1D,
+0x92, 0xD6, 0x84, 0x87, 0x29, 0x28, 0x16, 0x1B, 0x34, 0xE3, 0xBD, 0x2F, 0x9B, 0xF8, 0x6F, 0xDC,
+0x9B, 0x6C, 0xF5, 0xEB, 0x26, 0x51, 0x47, 0x78, 0xA2, 0xB5, 0x4C, 0x24, 0x1E, 0x3D, 0xE5, 0x33,
+0xA3, 0xD9, 0x04, 0x20, 0x8E, 0xA7, 0x32, 0x88, 0xC6, 0x52, 0x0B, 0x71, 0x0D, 0x26, 0xC3, 0x3F,
+0xC4, 0xC8, 0x7F, 0x6F, 0x3A, 0xAD, 0xC7, 0x27, 0x3D, 0xB3, 0xE6, 0x6B, 0x68, 0x66, 0xB3, 0xEE,
+0x6D, 0xC7, 0xAB, 0xD4, 0xA2, 0x88, 0xAF, 0xEB, 0x1A, 0x51, 0x76, 0x19, 0xFC, 0xF7, 0x29, 0xF0,
+0x4D, 0xC5, 0xAB, 0x42, 0x81, 0x9F, 0x10, 0xD9, 0xB0, 0x5C, 0x9D, 0x1A, 0x5A, 0xFE, 0xB3, 0x71,
+0xBC, 0x13, 0x69, 0xDA, 0xCE, 0x15, 0x7C, 0x18, 0x2C, 0x81, 0xFC, 0xA9, 0x1E, 0x0B, 0x33, 0xBF,
+0x82, 0x0D, 0xD5, 0x58, 0xD0, 0xB6, 0x17, 0x34, 0xFE, 0x53, 0x45, 0xE7, 0x57, 0x9B, 0xFA, 0x3C,
+0x04, 0xCF, 0x89, 0x38, 0x73, 0xE9, 0x60, 0xEA, 0xF4, 0x0F, 0xB2, 0x2E, 0x90, 0x60, 0xAE, 0xFB,
+0x57, 0xCB, 0xA5, 0x9D, 0x60, 0x44, 0x46, 0x13, 0x3C, 0xB3, 0xB6, 0x0A, 0x09, 0x12, 0x2B, 0x27,
+0x95, 0x45, 0x29, 0x92, 0x86, 0x00, 0x2A, 0x93, 0x77, 0x8D, 0xAA, 0xC3, 0xF8, 0x46, 0xBE, 0x3A,
+0x6A, 0x0E, 0x51, 0x9D, 0x94, 0x60, 0x9A, 0x76, 0x93, 0xF4, 0x01, 0x19, 0xC3, 0xB1, 0x86, 0xA9,
+0x7E, 0xD1, 0xF6, 0xF1, 0x88, 0x59, 0x4E, 0x9F, 0xCC, 0xF2, 0xF7, 0xDD, 0x1B, 0x91, 0x98, 0xAC,
+0xCC, 0xC6, 0x81, 0x57, 0x3F, 0x07, 0xF2, 0x52, 0x5B, 0x79, 0x5D, 0xFB, 0x07, 0xF7, 0x6A, 0x62,
+0x30, 0xE5, 0x77, 0x81, 0x00, 0x6C, 0xB1, 0x11, 0x8A, 0x1D, 0x0C, 0x9C, 0x94, 0x1A, 0xAD, 0xB6,
+0x85, 0x29, 0x70, 0x19, 0xFB, 0xE1, 0xF5, 0x89, 0x6D, 0xB3, 0x84, 0xC5, 0x56, 0x14, 0x1E, 0x67,
+0x46, 0x57, 0xFE, 0x30, 0xD0, 0x81, 0x2B, 0x27, 0xD6, 0x4B, 0x41, 0x74, 0xF3, 0x51, 0xD0, 0x78,
+0xCE, 0x3A, 0x5C, 0x46, 0xCC, 0xCE, 0x19, 0xC9, 0xC3, 0x1A, 0x81, 0xF4, 0x62, 0x9A, 0x8B, 0xAD,
+0x71, 0x9C, 0x3E, 0x5B, 0x23, 0xA7, 0x9F, 0x7E, 0x26, 0xDD, 0x21, 0xCC, 0x36, 0x75, 0x90, 0x09,
+0x61, 0x0B, 0x85, 0xC1, 0x0A, 0xF4, 0x9D, 0x93, 0x9F, 0x5F, 0x73, 0x71, 0xAB, 0x2B, 0xFA, 0x5E,
+0xD9, 0xA1, 0xF8, 0x7F, 0x0F, 0xD5, 0x07, 0x59, 0xB2, 0x4F, 0xF9, 0x71, 0xD4, 0x35, 0x3E, 0x5D,
+0x85, 0x6A, 0x32, 0x76, 0xDB, 0xBE, 0xC5, 0xD4, 0x2B, 0xC5, 0x70, 0x95, 0x7C, 0x64, 0x04, 0x0E,
+0xC0, 0x4E, 0x59, 0x76, 0x10, 0xBF, 0x93, 0xBE, 0xEC, 0x40, 0x2C, 0xDE, 0x2D, 0xE6, 0xD1, 0x77,
+0xC7, 0x84, 0x4B, 0xD6, 0x1C, 0x9A, 0xA1, 0x93, 0xE4, 0x50, 0xA8, 0x1B, 0x73, 0x29, 0x92, 0xB0,
+0x37, 0x83, 0x15, 0xE3, 0xB5, 0xCD, 0xD1, 0x47, 0x38, 0xD1, 0xB6, 0xB6, 0x04, 0x3D, 0x58, 0x28,
+0xB1, 0xB5, 0x9E, 0xF3, 0x95, 0x12, 0x1A, 0xC2, 0xA1, 0x71, 0x72, 0x45, 0x35, 0x0F, 0xB8, 0xC4,
+0xEF, 0xF7, 0xAD, 0xD6, 0x82, 0x6A, 0x6A, 0x9E, 0x0E, 0xEF, 0xAB, 0xAD, 0x9D, 0x8D, 0xE4, 0x77,
+0xA1, 0x93, 0xAE, 0xE1, 0xBA, 0x0E, 0xAF, 0x83, 0xC4, 0x84, 0x19, 0x6E, 0x5B, 0x15, 0xD7, 0xAE,
+0x33, 0xA4, 0x37, 0xE2, 0xA1, 0x18, 0x2A, 0x4A, 0x9C, 0x5E, 0x7C, 0x61, 0x70, 0x76, 0xE9, 0xE6,
+0x0E, 0x11, 0xEE, 0x71, 0x45, 0xE0, 0x5E, 0x72, 0x3C, 0x88, 0x0C, 0x34, 0x34, 0x78, 0x39, 0xD7,
+0xFB, 0x26, 0x14, 0x1B, 0xCE, 0xEE, 0x15, 0x3C, 0xA4, 0x3F, 0xD3, 0x2A, 0x7C, 0x66, 0x58, 0xDD,
+0x56, 0x46, 0xAF, 0x14, 0x04, 0x35, 0x33, 0xD5, 0x83, 0xA0, 0x07, 0xE0, 0xC0, 0x4B, 0x9D, 0x36,
+0xF0, 0x72, 0x90, 0x7D, 0xFC, 0x4B, 0x3B, 0xDD, 0x07, 0x5E, 0xCD, 0xBE, 0x0B, 0x30, 0x78, 0x8C,
+0x9B, 0x4D, 0xFB, 0xB4, 0x95, 0xC4, 0xDE, 0x57, 0xB3, 0x07, 0xE6, 0x8F, 0x20, 0xE7, 0x54, 0x84,
+0xC8, 0x35, 0x3B, 0x68, 0x15, 0x74, 0x0F, 0x6A, 0xAB, 0xCC, 0x3E, 0x90, 0x6B, 0x38, 0x0A, 0xA8,
+0x5A, 0x3F, 0xF3, 0xAC, 0x27, 0x12, 0xFC, 0x04, 0xF6, 0x93, 0xB4, 0x84, 0xF2, 0x82, 0xED, 0xAE,
+0xF9, 0x64, 0x53, 0x1F, 0x9A, 0x2F, 0xAD, 0xB7, 0x2A, 0x17, 0x60, 0xFC, 0xDB, 0x07, 0xB1, 0x01,
+0xC9, 0xF8, 0x02, 0x5F, 0xF3, 0x5B, 0x5B, 0x90, 0xD4, 0x96, 0x92, 0x99, 0x36, 0x22, 0x53, 0xEA,
+0x62, 0xAE, 0xB0, 0x22, 0x6A, 0xAB, 0x24, 0xCD, 0x19, 0xBB, 0x86, 0x54, 0x17, 0x0F, 0x9D, 0x1A,
+0x4A, 0x3D, 0xE4, 0xF0, 0x0D, 0x03, 0xF2, 0x9A, 0x6D, 0x70, 0xEE, 0xA5, 0x51, 0x5F, 0xE8, 0x74,
+0xC1, 0xAC, 0x4B, 0xC6, 0x1C, 0x58, 0x26, 0x8F, 0xBF, 0xE1, 0x1D, 0xDB, 0x2D, 0xCA, 0x7E, 0x56,
+0xB9, 0x5E, 0x28, 0x4D, 0x63, 0x21, 0xDA, 0x20, 0xC5, 0xBB, 0xE3, 0x23, 0x92, 0x90, 0xB3, 0x2D,
+0xCE, 0x5B, 0x97, 0xF1, 0x66, 0x4A, 0x1D, 0xD0, 0xA4, 0x9E, 0x72, 0xD5, 0x3C, 0xC8, 0x7C, 0xCF,
+0x78, 0x1F, 0x5B, 0x34, 0x9B, 0xFF, 0x92, 0x71, 0xF5, 0x02, 0x0E, 0x01, 0xAC, 0x6A, 0x1E, 0xE0,
+0x2D, 0x15, 0x05, 0x40, 0x37, 0xF1, 0x7B, 0x24, 0xD8, 0x92, 0x5B, 0xE9, 0xEB, 0xD1, 0x7F, 0xC1,
+0xCE, 0x9C, 0xAA, 0x6A, 0x48, 0x38, 0x3A, 0xF5, 0x5A, 0x3F, 0x17, 0xFF, 0x45, 0x09, 0x1B, 0x40
+
+cipher_key =
+0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+0xd0, 0xe7, 0x4b, 0xfb, 0x5d, 0xe5, 0x0c, 0xe7, 0x6f, 0x21, 0xb5, 0x52, 0x2a, 0xbb, 0xc7, 0xf7
+
+auth_key =
+0xaf, 0x96, 0x42, 0xf1, 0x8c, 0x50, 0xdc, 0x67, 0x1a, 0x43, 0x47, 0x62, 0xc7, 0x04, 0xab, 0x05,
+0xf5, 0x0c, 0xe7, 0xa2, 0xa6, 0x23, 0xd5, 0x3d, 0x95, 0xd8, 0xcd, 0x86, 0x79, 0xf5, 0x01, 0x47,
+0x4f, 0xf9, 0x1d, 0x9d, 0x36, 0xf7, 0x68, 0x1a, 0x64, 0x44, 0x58, 0x5d, 0xe5, 0x81, 0x15, 0x2a,
+0x41, 0xe4, 0x0e, 0xaa, 0x1f, 0x04, 0x21, 0xff, 0x2c, 0xf3, 0x73, 0x2b, 0x48, 0x1e, 0xd2, 0xf7,
+0xf6, 0xd9, 0xaf, 0xbf, 0x08, 0x3b, 0xbb, 0x19, 0x5f, 0xf6, 0x7d, 0x25, 0x85, 0xdf, 0x6b, 0x54,
+0xd0, 0xe7, 0x4b, 0x9e, 0xc7, 0xef, 0xca, 0x48, 0x6f, 0x21, 0xd7, 0x51, 0xc8, 0x21, 0xc1, 0x15,
+0xe8, 0x38, 0x36, 0x58, 0x39, 0xd9, 0x9a, 0xc5, 0xe7, 0x3b, 0xc4, 0x47, 0xe2, 0xbd, 0x80, 0x73,
+0xf8, 0xd1, 0x9a, 0x5e, 0x4b, 0xfb, 0x52, 0x6b, 0x50, 0xaf, 0x8b, 0xb7, 0xb5, 0x2c, 0x52, 0x84
+
+cipher_iv =
+0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+
+####################
+# sha_hmac_buff_32 #
+####################
+[sha1_hmac_buff_32]
+digest =
+0x36, 0xCA, 0x49, 0x6A, 0xE3, 0x54, 0xD8, 0x4F, 0x0B, 0x76, 0xD8, 0xAA, 0x78, 0xEB, 0x9D, 0x65,
+0x2C, 0xCA, 0x1F, 0x97
+
+[sha224_hmac_buff_32]
+digest =
+0x48, 0xC1, 0x45, 0x25, 0x29, 0xA0, 0x8B, 0x88, 0x72, 0x7A, 0xBC, 0x00, 0x94, 0x37, 0xE1, 0x22,
+0xEB, 0xFA, 0x1B, 0x7D, 0x89, 0x81, 0x31, 0xC8, 0x64, 0x76, 0x55, 0xA4
+
+[sha256_hmac_buff_32]
+digest =
+0x1C, 0xB2, 0x3D, 0xD1, 0xF9, 0xC7, 0x6C, 0x49, 0x2E, 0xDA, 0x94, 0x8B, 0xF1, 0xCF, 0x96, 0x43,
+0x67, 0x50, 0x39, 0x76, 0xB5, 0xA1, 0xCE, 0xA1, 0xD7, 0x77, 0x10, 0x07, 0x43, 0x37, 0x05, 0xB4
+
+[sha384_hmac_buff_32]
+digest =
+0x6C, 0xBD, 0x1E, 0x2E, 0x75, 0xA7, 0x2C, 0x98, 0xC4, 0x1E, 0x03, 0x4E, 0x39, 0x4B, 0x27, 0x41,
+0xFB, 0xC6, 0x56, 0x87, 0x84, 0xEB, 0xFA, 0xB1, 0x20, 0x1F, 0x11, 0x81, 0x8D, 0xDC, 0xB6, 0xA7,
+0xAD, 0x1F, 0xAC, 0xA9, 0x43, 0x1D, 0x2B, 0xEB, 0x5F, 0x27, 0xC6, 0x0F, 0x9E, 0xFB, 0x1E, 0xB1
+
+[sha512_hmac_buff_32]
+digest =
+0xA4, 0x60, 0x7E, 0xBE, 0x5F, 0x47, 0x58, 0x3B, 0x41, 0x5F, 0x29, 0xDF, 0xE4, 0xD2, 0xFB, 0x30,
+0xF0, 0x2B, 0x09, 0x4E, 0x09, 0x50, 0xEC, 0x1C, 0x0E, 0x34, 0x79, 0xAE, 0xD8, 0x6D, 0xAC, 0xB6,
+0x9B, 0x7C, 0xB9, 0x06, 0xC2, 0x4A, 0x4E, 0x22, 0x14, 0x4D, 0x42, 0x46, 0x20, 0xE0, 0x6C, 0xEE,
+0x2F, 0xE1, 0x23, 0xA2, 0x7A, 0x2F, 0xDB, 0xAF, 0x78, 0x75, 0x56, 0xF7, 0x3A, 0x5E, 0x74, 0xEF
+
+####################
+# sha_hmac_buff_64 #
+####################
+[sha1_hmac_buff_64]
+digest =
+0xFC, 0x17, 0x7E, 0x0E, 0x52, 0x94, 0xE3, 0x27, 0xC0, 0x9B, 0x72, 0xAD, 0xC0, 0x5B, 0xCF, 0xFF,
+0x65, 0x88, 0x43, 0xE7
+
+[sha224_hmac_buff_64]
+digest =
+0xD7, 0x55, 0x25, 0xC0, 0x26, 0xDD, 0x8E, 0x14, 0x17, 0x8B, 0x89, 0x59, 0x8A, 0xBB, 0xEA, 0xD6,
+0x7D, 0x85, 0x00, 0x9F, 0xC2, 0x8A, 0xCB, 0x01, 0x7F, 0x8C, 0x6E, 0x24
+
+[sha256_hmac_buff_64]
+digest =
+0x8F, 0x4B, 0x3B, 0x4C, 0x58, 0x25, 0x3B, 0x07, 0xEB, 0xF8, 0x20, 0x81, 0xD9, 0xD9, 0x92, 0x8F,
+0xF4, 0x32, 0x7C, 0x2A, 0xD9, 0xEC, 0x92, 0x60, 0x8F, 0xE3, 0x90, 0x7F, 0xC5, 0x75, 0x05, 0xB6
+
+[sha384_hmac_buff_64]
+digest =
+0xD1, 0xC7, 0x64, 0x27, 0xF0, 0x30, 0x43, 0x8E, 0xD6, 0xA6, 0x78, 0xF7, 0xE9, 0xCC, 0x8E, 0x69,
+0x6D, 0xB8, 0x3E, 0xFA, 0xA0, 0x81, 0x9C, 0x61, 0x78, 0x72, 0xF0, 0x1C, 0x29, 0x35, 0x51, 0x3E,
+0x4A, 0x95, 0xDE, 0x2C, 0x6A, 0x3F, 0x56, 0xA8, 0x12, 0xBA, 0x44, 0x39, 0x1E, 0xDB, 0xF7, 0xF5
+
+[sha512_hmac_buff_64]
+digest =
+0xE6, 0xE9, 0xD8, 0x1D, 0x90, 0xAE, 0x32, 0x0E, 0xBA, 0x55, 0x58, 0xD5, 0x55, 0x97, 0x40, 0xB3,
+0xE9, 0x12, 0xD3, 0x08, 0xEF, 0x21, 0xED, 0xA5, 0x94, 0x8D, 0xF2, 0x4C, 0x52, 0x2C, 0x50, 0xB2,
+0xD2, 0xEC, 0xB7, 0xE1, 0x95, 0x2D, 0x68, 0xDB, 0xAD, 0xB5, 0x94, 0x50, 0x67, 0xF3, 0x0A, 0x83,
+0x54, 0x03, 0x33, 0x1C, 0xD5, 0x42, 0x7D, 0xB4, 0x3E, 0x69, 0x7C, 0x36, 0x7E, 0x96, 0x0D, 0x3E
+
+#####################
+# sha_hmac_buff_128 #
+#####################
+[sha1_hmac_buff_128]
+digest =
+0xAA, 0x90, 0x55, 0xA5, 0x71, 0xC4, 0x2B, 0xA3, 0x02, 0xAA, 0xB1, 0x1C, 0xB3, 0x88, 0x38, 0x6E,
+0xAD, 0x26, 0x98, 0xA7
+
+[sha224_hmac_buff_128]
+digest =
+0xBE, 0xCC, 0x83, 0x48, 0x4C, 0x58, 0xF9, 0x86, 0xFA, 0x93, 0x5F, 0xD1, 0x3C, 0x11, 0x8A, 0x37,
+0xA6, 0xEE, 0x52, 0x4D, 0xA3, 0x98, 0x3E, 0x35, 0xF1, 0x4F, 0xD9, 0xDB
+
+[sha256_hmac_buff_128]
+digest =
+0xE2, 0x9C, 0xE1, 0xDF, 0xCD, 0xAE, 0x50, 0x4B, 0x9A, 0xA6, 0x41, 0xAC, 0x0C, 0xF1, 0x66, 0xED,
+0xA1, 0x22, 0x05, 0x72, 0x49, 0x97, 0xA1, 0x30, 0xB8, 0xF9, 0xED, 0x36, 0x0A, 0x19, 0xE4, 0x2A
+
+[sha384_hmac_buff_128]
+digest =
+0xD9, 0x3C, 0xEB, 0xF4, 0x20, 0xC6, 0x4F, 0xC7, 0xBD, 0x34, 0xBA, 0xFD, 0x7C, 0xA9, 0xCE, 0xFF,
+0x26, 0x2E, 0xB4, 0x4A, 0xB7, 0x47, 0x71, 0x2C, 0x9E, 0xCF, 0x44, 0x0B, 0xD9, 0xAF, 0x8D, 0x17,
+0x0A, 0x3A, 0x02, 0xD0, 0xE9, 0xDF, 0xCF, 0x52, 0x5F, 0xDA, 0xA7, 0xB6, 0x51, 0x7C, 0x59, 0x09
+
+[sha512_hmac_buff_128]
+digest =
+0xAD, 0x7E, 0xB7, 0x33, 0xFB, 0x8A, 0x17, 0xD0, 0x3C, 0xB0, 0x80, 0x19, 0xF3, 0x9A, 0x6F, 0x90,
+0xDE, 0xF3, 0x53, 0xEA, 0x48, 0x75, 0x0A, 0x1E, 0x49, 0x02, 0xA0, 0x94, 0xC4, 0xE8, 0xFB, 0x87,
+0x83, 0x80, 0xD3, 0xFF, 0x6B, 0x79, 0x73, 0x54, 0xF9, 0x2F, 0x2D, 0x59, 0x69, 0x0E, 0x50, 0x29,
+0x2A, 0xDA, 0x59, 0x38, 0xDD, 0x62, 0xF9, 0x1A, 0x18, 0xA9, 0x51, 0x5A, 0xFE, 0x8E, 0xFD, 0xBF
+
+#####################
+# sha_hmac_buff_256 #
+#####################
+[sha1_hmac_buff_256]
+digest =
+0xB1, 0x18, 0x31, 0xBF, 0xEE, 0x81, 0x7E, 0xFC, 0x68, 0xDA, 0xB6, 0x8A, 0x5D, 0xDE, 0x39, 0x65,
+0xC8, 0xF8, 0xC3, 0xE5
+
+[sha224_hmac_buff_256]
+digest =
+0xCD, 0xF6, 0xC2, 0x6D, 0xFD, 0x33, 0x1A, 0xD8, 0x2F, 0x07, 0x4F, 0x1A, 0xE8, 0x18, 0xBD, 0x04,
+0xB1, 0xE5, 0x8D, 0xC1, 0x21, 0x95, 0x87, 0x75, 0xC2, 0x27, 0x4B, 0xF2
+
+[sha256_hmac_buff_256]
+digest =
+0xC0, 0xFA, 0x8F, 0x6F, 0x55, 0xFC, 0xF3, 0xDF, 0x8E, 0x5D, 0x93, 0x5E, 0x6B, 0x20, 0x0A, 0x9A,
+0x84, 0x3D, 0xCD, 0x4B, 0x57, 0x63, 0x2D, 0x93, 0x51, 0x45, 0xF2, 0x1E, 0xC7, 0xA4, 0xD4, 0x69
+
+[sha384_hmac_buff_256]
+digest =
+0x2B, 0x92, 0x9E, 0x85, 0x5A, 0x89, 0xB5, 0x12, 0x4A, 0x9B, 0x2D, 0xD2, 0xB2, 0x3E, 0xAB, 0xC1,
+0x1E, 0x7F, 0x53, 0xD9, 0x88, 0xEB, 0xEE, 0xA2, 0x49, 0x14, 0xDE, 0x1A, 0x9E, 0x20, 0xCE, 0xEC,
+0x7A, 0x5D, 0x25, 0xD8, 0x8F, 0xFE, 0x8B, 0xB1, 0xB1, 0x04, 0x5F, 0x46, 0x2D, 0x34, 0x2D, 0x72
+
+[sha512_hmac_buff_256]
+digest =
+0x4F, 0x96, 0x89, 0x9E, 0x9D, 0x53, 0xAC, 0x05, 0xC7, 0xA0, 0x0F, 0x4D, 0xB6, 0x3E, 0x06, 0x03,
+0x19, 0x68, 0x41, 0x4F, 0x11, 0x57, 0x77, 0x21, 0xBD, 0x60, 0x3E, 0xB4, 0xFE, 0x6A, 0x0D, 0xBF,
+0xE0, 0x4F, 0x32, 0x5B, 0xF9, 0xDF, 0x13, 0xBD, 0x02, 0x73, 0xD4, 0x0C, 0xE9, 0x9D, 0xB7, 0xD5,
+0x38, 0xA0, 0x20, 0xD9, 0xD1, 0x66, 0x17, 0x19, 0x54, 0x36, 0x18, 0xE1, 0xF5, 0x34, 0x12, 0x9E
+
+#####################
+# sha_hmac_buff_512 #
+#####################
+[sha1_hmac_buff_512]
+digest =
+0x78, 0x14, 0x01, 0xED, 0x93, 0x6F, 0x22, 0xB6, 0x96, 0x5A, 0x32, 0x05, 0xA9, 0xD3, 0x49, 0x04,
+0x55, 0xB0, 0x00, 0x06
+
+[sha224_hmac_buff_512]
+digest =
+0x25, 0xD4, 0x8F, 0x92, 0xE1, 0xD0, 0x4E, 0x3F, 0x34, 0x38, 0x01, 0xB8, 0xFE, 0x57, 0x3D, 0x34,
+0x39, 0x98, 0x82, 0x8D, 0x68, 0x04, 0x5A, 0x74, 0x28, 0x4F, 0x18, 0xCE
+
+[sha256_hmac_buff_512]
+digest =
+0x90, 0x06, 0x97, 0x8A, 0x7A, 0xEF, 0x62, 0x14, 0x4C, 0x14, 0xAA, 0x25, 0x4C, 0xE3, 0x5D, 0xE4,
+0xAD, 0x6C, 0xD6, 0x82, 0x2B, 0x87, 0x53, 0x3E, 0xE9, 0xE4, 0x97, 0x82, 0x82, 0x76, 0xE7, 0xF1
+
+[sha384_hmac_buff_512]
+digest =
+0xD5, 0xDA, 0x7C, 0x8A, 0x0D, 0x1B, 0xBE, 0x3E, 0x25, 0x1E, 0x6C, 0xA4, 0x50, 0x32, 0x92, 0x13,
+0x91, 0x4F, 0xA2, 0x29, 0x2A, 0x0A, 0x57, 0x62, 0x3D, 0x93, 0xF2, 0x45, 0x96, 0x22, 0xF8, 0x0D,
+0xA9, 0xE9, 0xAB, 0xAC, 0x7B, 0x2E, 0x42, 0xC2, 0x3E, 0x75, 0x23, 0xD0, 0xD2, 0xAA, 0x1E, 0xEE
+
+[sha512_hmac_buff_512]
+digest =
+0x57, 0x34, 0x65, 0x3D, 0xDE, 0x8B, 0x7B, 0x99, 0x62, 0x24, 0xF3, 0xAF, 0xA6, 0xB1, 0xF0, 0x01,
+0x23, 0xD4, 0x94, 0xC2, 0x06, 0x70, 0xA5, 0x8C, 0x80, 0x93, 0x49, 0x88, 0xB4, 0xB6, 0x45, 0xE5,
+0x37, 0xC9, 0xE4, 0xA1, 0xAB, 0x6C, 0xA5, 0x23, 0xD2, 0x07, 0x9B, 0x10, 0x4D, 0xFD, 0x75, 0xC0,
+0x28, 0xA1, 0x8A, 0x84, 0x03, 0x35, 0x22, 0xCC, 0xAC, 0x6C, 0x97, 0x93, 0x57, 0x08, 0x48, 0x51
+
+######################
+# sha_hmac_buff_1024 #
+######################
+[sha1_hmac_buff_1024]
+digest =
+0x74, 0xF7, 0x91, 0x04, 0x06, 0xDB, 0xA9, 0xF0, 0x08, 0x0E, 0x93, 0xCE, 0x55, 0xA8, 0x54, 0xF0,
+0x4B, 0x5E, 0x3F, 0xC7
+
+[sha224_hmac_buff_1024]
+digest =
+0x45, 0xDA, 0x2E, 0x83, 0xBD, 0x35, 0xA4, 0x58, 0x14, 0x74, 0xCB, 0xA4, 0x48, 0xA6, 0xBA, 0xDC,
+0x7D, 0x56, 0x6A, 0x44, 0xA7, 0xE9, 0x2F, 0x75, 0x20, 0x47, 0x2A, 0x5A
+
+[sha256_hmac_buff_1024]
+digest =
+0xA2, 0x81, 0xFE, 0x1A, 0x5C, 0x4F, 0x02, 0x72, 0xEF, 0x4F, 0xC6, 0xEE, 0x54, 0x71, 0x69, 0xAF,
+0x5C, 0x71, 0x9F, 0xB0, 0xAC, 0x5B, 0x7F, 0x51, 0xD6, 0x0D, 0x64, 0xD2, 0x2E, 0x0E, 0x30, 0x55
+
+[sha384_hmac_buff_1024]
+digest =
+0x26, 0x44, 0x13, 0x01, 0x25, 0x6E, 0xC7, 0xC3, 0x88, 0x25, 0xD5, 0xDD, 0x1D, 0xCA, 0x0C, 0xB1,
+0xB8, 0x82, 0xB2, 0xB8, 0x15, 0x3F, 0xE5, 0x54, 0x43, 0x47, 0x32, 0x3B, 0xB2, 0xE0, 0xC8, 0x58,
+0x64, 0xE7, 0x78, 0xC9, 0x1F, 0x81, 0x7B, 0xBD, 0x0D, 0x6D, 0x37, 0x9C, 0x01, 0x20, 0x6A, 0x8E
+
+[sha512_hmac_buff_1024]
+digest =
+0xBE, 0xDA, 0x0D, 0x3B, 0x47, 0x24, 0xBA, 0x45, 0xBA, 0xCA, 0x84, 0x5F, 0xEA, 0xAC, 0x33, 0x84,
+0x00, 0x62, 0xA5, 0x29, 0xB6, 0x2F, 0xB7, 0x86, 0xD0, 0x94, 0xFF, 0xFF, 0xE4, 0x1E, 0x5C, 0xFD,
+0xC8, 0xD5, 0x3A, 0xD4, 0xFC, 0xA6, 0x1C, 0x66, 0x4A, 0x6D, 0xF9, 0x2B, 0x1D, 0x7F, 0xA0, 0xCF,
+0x3D, 0x0F, 0x1F, 0x5B, 0xDD, 0x21, 0x12, 0xA8, 0x76, 0xB0, 0xD7, 0x30, 0x66, 0xA6, 0xA0, 0x6C
+
+######################
+# sha_hmac_buff_2048 #
+######################
+[sha1_hmac_buff_2048]
+digest =
+0x99, 0x32, 0xCD, 0xC3, 0xC9, 0x7F, 0x98, 0x1A, 0x96, 0xF6, 0x52, 0xC8, 0xA2, 0x16, 0x9C, 0x29,
+0x9D, 0x6E, 0x96, 0xF5
+
+[sha224_hmac_buff_2048]
+digest =
+0x1A, 0xC4, 0xDC, 0x46, 0xE5, 0x87, 0xFE, 0xE0, 0x47, 0x64, 0x53, 0xA3, 0x6A, 0x1F, 0x78, 0xC0,
+0xC0, 0x02, 0x03, 0x64, 0xB1, 0x55, 0x50, 0x66, 0xDA, 0xD6, 0x9E, 0xBC
+
+[sha256_hmac_buff_2048]
+digest =
+0xA6, 0xC6, 0x4B, 0x0C, 0x95, 0xDE, 0xD5, 0xE2, 0x40, 0x7D, 0x44, 0xC5, 0xBF, 0x00, 0x5A, 0xFB,
+0x6F, 0x3F, 0x5E, 0x69, 0xB1, 0x32, 0x91, 0xAB, 0x6C, 0x90, 0x25, 0xAB, 0xD9, 0x1B, 0x8F, 0x80
+
+[sha384_hmac_buff_2048]
+digest =
+0x16, 0xF1, 0x1B, 0xC1, 0x22, 0xDB, 0x21, 0x90, 0x08, 0xE3, 0x42, 0x0C, 0x9A, 0xF1, 0x0F, 0xF8,
+0x7A, 0xE9, 0x50, 0x09, 0xC6, 0x0C, 0x71, 0x65, 0x3A, 0x40, 0xB3, 0x78, 0x11, 0xE8, 0xD2, 0xD4,
+0xB0, 0x6C, 0xA9, 0x6A, 0x0C, 0xCD, 0xE1, 0x70, 0x7E, 0x90, 0x86, 0x34, 0xC1, 0x08, 0x9E, 0xFC
+
+[sha512_hmac_buff_2048]
+digest =
+0xDF, 0x7F, 0xC3, 0x26, 0x3E, 0x55, 0x80, 0x7D, 0x02, 0x06, 0x5A, 0x4B, 0x8C, 0xFD, 0x2F, 0x33,
+0xF8, 0x0E, 0x9C, 0x59, 0xAE, 0x56, 0xAE, 0x86, 0xA9, 0x25, 0x3F, 0xB7, 0xF7, 0x4C, 0x7A, 0xB4,
+0xD8, 0x0E, 0x43, 0xC0, 0x86, 0xDF, 0xDB, 0xBA, 0xA8, 0xCB, 0x46, 0x2A, 0x92, 0x34, 0xF5, 0x3B,
+0xBD, 0x59, 0x64, 0xDF, 0x30, 0x20, 0xF5, 0x13, 0xD7, 0x78, 0xB9, 0x27, 0xE6, 0xB6, 0x56, 0x19
diff --git a/src/spdk/dpdk/app/test-crypto-perf/main.c b/src/spdk/dpdk/app/test-crypto-perf/main.c
new file mode 100644
index 000000000..7bb286ccb
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/main.c
@@ -0,0 +1,758 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_eal.h>
+#include <rte_cryptodev.h>
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+#include <rte_cryptodev_scheduler.h>
+#endif
+
+#include "cperf.h"
+#include "cperf_options.h"
+#include "cperf_test_vector_parsing.h"
+#include "cperf_test_throughput.h"
+#include "cperf_test_latency.h"
+#include "cperf_test_verify.h"
+#include "cperf_test_pmd_cyclecount.h"
+
+static struct {
+ struct rte_mempool *sess_mp;
+ struct rte_mempool *priv_mp;
+} session_pool_socket[RTE_MAX_NUMA_NODES];
+
+const char *cperf_test_type_strs[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = "throughput",
+ [CPERF_TEST_TYPE_LATENCY] = "latency",
+ [CPERF_TEST_TYPE_VERIFY] = "verify",
+ [CPERF_TEST_TYPE_PMDCC] = "pmd-cyclecount"
+};
+
+const char *cperf_op_type_strs[] = {
+ [CPERF_CIPHER_ONLY] = "cipher-only",
+ [CPERF_AUTH_ONLY] = "auth-only",
+ [CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
+ [CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
+ [CPERF_AEAD] = "aead",
+ [CPERF_PDCP] = "pdcp"
+};
+
+const struct cperf_test cperf_testmap[] = {
+ [CPERF_TEST_TYPE_THROUGHPUT] = {
+ cperf_throughput_test_constructor,
+ cperf_throughput_test_runner,
+ cperf_throughput_test_destructor
+ },
+ [CPERF_TEST_TYPE_LATENCY] = {
+ cperf_latency_test_constructor,
+ cperf_latency_test_runner,
+ cperf_latency_test_destructor
+ },
+ [CPERF_TEST_TYPE_VERIFY] = {
+ cperf_verify_test_constructor,
+ cperf_verify_test_runner,
+ cperf_verify_test_destructor
+ },
+ [CPERF_TEST_TYPE_PMDCC] = {
+ cperf_pmd_cyclecount_test_constructor,
+ cperf_pmd_cyclecount_test_runner,
+ cperf_pmd_cyclecount_test_destructor
+ }
+};
+
+static int
+fill_session_pool_socket(int32_t socket_id, uint32_t session_priv_size,
+ uint32_t nb_sessions)
+{
+ char mp_name[RTE_MEMPOOL_NAMESIZE];
+ struct rte_mempool *sess_mp;
+
+ if (session_pool_socket[socket_id].priv_mp == NULL) {
+ snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
+ "priv_sess_mp_%u", socket_id);
+
+ sess_mp = rte_mempool_create(mp_name,
+ nb_sessions,
+ session_priv_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, socket_id,
+ 0);
+
+ if (sess_mp == NULL) {
+ printf("Cannot create pool \"%s\" on socket %d\n",
+ mp_name, socket_id);
+ return -ENOMEM;
+ }
+
+ printf("Allocated pool \"%s\" on socket %d\n",
+ mp_name, socket_id);
+ session_pool_socket[socket_id].priv_mp = sess_mp;
+ }
+
+ if (session_pool_socket[socket_id].sess_mp == NULL) {
+
+ snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
+ "sess_mp_%u", socket_id);
+
+ sess_mp = rte_cryptodev_sym_session_pool_create(mp_name,
+ nb_sessions, 0, 0, 0, socket_id);
+
+ if (sess_mp == NULL) {
+ printf("Cannot create pool \"%s\" on socket %d\n",
+ mp_name, socket_id);
+ return -ENOMEM;
+ }
+
+ printf("Allocated pool \"%s\" on socket %d\n",
+ mp_name, socket_id);
+ session_pool_socket[socket_id].sess_mp = sess_mp;
+ }
+
+ return 0;
+}
+
+static int
+cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
+{
+ uint8_t enabled_cdev_count = 0, nb_lcores, cdev_id;
+ uint32_t sessions_needed = 0;
+ unsigned int i, j;
+ int ret;
+
+ enabled_cdev_count = rte_cryptodev_devices_get(opts->device_type,
+ enabled_cdevs, RTE_CRYPTO_MAX_DEVS);
+ if (enabled_cdev_count == 0) {
+ printf("No crypto devices type %s available\n",
+ opts->device_type);
+ return -EINVAL;
+ }
+
+ nb_lcores = rte_lcore_count() - 1;
+
+ if (nb_lcores < 1) {
+ RTE_LOG(ERR, USER1,
+ "Number of enabled cores need to be higher than 1\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Use less number of devices,
+ * if there are more available than cores.
+ */
+ if (enabled_cdev_count > nb_lcores)
+ enabled_cdev_count = nb_lcores;
+
+ /* Create a mempool shared by all the devices */
+ uint32_t max_sess_size = 0, sess_size;
+
+ for (cdev_id = 0; cdev_id < rte_cryptodev_count(); cdev_id++) {
+ sess_size = rte_cryptodev_sym_get_private_session_size(cdev_id);
+ if (sess_size > max_sess_size)
+ max_sess_size = sess_size;
+ }
+
+ /*
+ * Calculate number of needed queue pairs, based on the amount
+ * of available number of logical cores and crypto devices.
+ * For instance, if there are 4 cores and 2 crypto devices,
+ * 2 queue pairs will be set up per device.
+ */
+ opts->nb_qps = (nb_lcores % enabled_cdev_count) ?
+ (nb_lcores / enabled_cdev_count) + 1 :
+ nb_lcores / enabled_cdev_count;
+
+ for (i = 0; i < enabled_cdev_count &&
+ i < RTE_CRYPTO_MAX_DEVS; i++) {
+ cdev_id = enabled_cdevs[i];
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+ /*
+ * If multi-core scheduler is used, limit the number
+ * of queue pairs to 1, as there is no way to know
+ * how many cores are being used by the PMD, and
+ * how many will be available for the application.
+ */
+ if (!strcmp((const char *)opts->device_type, "crypto_scheduler") &&
+ rte_cryptodev_scheduler_mode_get(cdev_id) ==
+ CDEV_SCHED_MODE_MULTICORE)
+ opts->nb_qps = 1;
+#endif
+
+ struct rte_cryptodev_info cdev_info;
+ uint8_t socket_id = rte_cryptodev_socket_id(cdev_id);
+ /* range check the socket_id - negative values become big
+ * positive ones due to use of unsigned value
+ */
+ if (socket_id >= RTE_MAX_NUMA_NODES)
+ socket_id = 0;
+
+ rte_cryptodev_info_get(cdev_id, &cdev_info);
+ if (opts->nb_qps > cdev_info.max_nb_queue_pairs) {
+ printf("Number of needed queue pairs is higher "
+ "than the maximum number of queue pairs "
+ "per device.\n");
+ printf("Lower the number of cores or increase "
+ "the number of crypto devices\n");
+ return -EINVAL;
+ }
+ struct rte_cryptodev_config conf = {
+ .nb_queue_pairs = opts->nb_qps,
+ .socket_id = socket_id,
+ .ff_disable = RTE_CRYPTODEV_FF_SECURITY |
+ RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO,
+ };
+
+ struct rte_cryptodev_qp_conf qp_conf = {
+ .nb_descriptors = opts->nb_descriptors
+ };
+
+ /**
+ * Device info specifies the min headroom and tailroom
+ * requirement for the crypto PMD. This need to be honoured
+ * by the application, while creating mbuf.
+ */
+ if (opts->headroom_sz < cdev_info.min_mbuf_headroom_req) {
+ /* Update headroom */
+ opts->headroom_sz = cdev_info.min_mbuf_headroom_req;
+ }
+ if (opts->tailroom_sz < cdev_info.min_mbuf_tailroom_req) {
+ /* Update tailroom */
+ opts->tailroom_sz = cdev_info.min_mbuf_tailroom_req;
+ }
+
+ /* Update segment size to include headroom & tailroom */
+ opts->segment_sz += (opts->headroom_sz + opts->tailroom_sz);
+
+ uint32_t dev_max_nb_sess = cdev_info.sym.max_nb_sessions;
+ /*
+ * Two sessions objects are required for each session
+ * (one for the header, one for the private data)
+ */
+ if (!strcmp((const char *)opts->device_type,
+ "crypto_scheduler")) {
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+ uint32_t nb_slaves =
+ rte_cryptodev_scheduler_slaves_get(cdev_id,
+ NULL);
+
+ sessions_needed = enabled_cdev_count *
+ opts->nb_qps * nb_slaves;
+#endif
+ } else
+ sessions_needed = enabled_cdev_count *
+ opts->nb_qps;
+
+ /*
+ * A single session is required per queue pair
+ * in each device
+ */
+ if (dev_max_nb_sess != 0 && dev_max_nb_sess < opts->nb_qps) {
+ RTE_LOG(ERR, USER1,
+ "Device does not support at least "
+ "%u sessions\n", opts->nb_qps);
+ return -ENOTSUP;
+ }
+
+ ret = fill_session_pool_socket(socket_id, max_sess_size,
+ sessions_needed);
+ if (ret < 0)
+ return ret;
+
+ qp_conf.mp_session = session_pool_socket[socket_id].sess_mp;
+ qp_conf.mp_session_private =
+ session_pool_socket[socket_id].priv_mp;
+
+ ret = rte_cryptodev_configure(cdev_id, &conf);
+ if (ret < 0) {
+ printf("Failed to configure cryptodev %u", cdev_id);
+ return -EINVAL;
+ }
+
+ for (j = 0; j < opts->nb_qps; j++) {
+ ret = rte_cryptodev_queue_pair_setup(cdev_id, j,
+ &qp_conf, socket_id);
+ if (ret < 0) {
+ printf("Failed to setup queue pair %u on "
+ "cryptodev %u", j, cdev_id);
+ return -EINVAL;
+ }
+ }
+
+ ret = rte_cryptodev_start(cdev_id);
+ if (ret < 0) {
+ printf("Failed to start device %u: error %d\n",
+ cdev_id, ret);
+ return -EPERM;
+ }
+ }
+
+ return enabled_cdev_count;
+}
+
+static int
+cperf_verify_devices_capabilities(struct cperf_options *opts,
+ uint8_t *enabled_cdevs, uint8_t nb_cryptodevs)
+{
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *capability;
+
+ uint8_t i, cdev_id;
+ int ret;
+
+ for (i = 0; i < nb_cryptodevs; i++) {
+
+ cdev_id = enabled_cdevs[i];
+
+ if (opts->op_type == CPERF_AUTH_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = opts->auth_algo;
+
+ capability = rte_cryptodev_sym_capability_get(cdev_id,
+ &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ ret = rte_cryptodev_sym_capability_check_auth(
+ capability,
+ opts->auth_key_sz,
+ opts->digest_sz,
+ opts->auth_iv_sz);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (opts->op_type == CPERF_CIPHER_ONLY ||
+ opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = opts->cipher_algo;
+
+ capability = rte_cryptodev_sym_capability_get(cdev_id,
+ &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ ret = rte_cryptodev_sym_capability_check_cipher(
+ capability,
+ opts->cipher_key_sz,
+ opts->cipher_iv_sz);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (opts->op_type == CPERF_AEAD) {
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = opts->aead_algo;
+
+ capability = rte_cryptodev_sym_capability_get(cdev_id,
+ &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ ret = rte_cryptodev_sym_capability_check_aead(
+ capability,
+ opts->aead_key_sz,
+ opts->digest_sz,
+ opts->aead_aad_sz,
+ opts->aead_iv_sz);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int
+cperf_check_test_vector(struct cperf_options *opts,
+ struct cperf_test_vector *test_vec)
+{
+ if (opts->op_type == CPERF_CIPHER_ONLY) {
+ if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ /* Cipher IV is only required for some algorithms */
+ if (opts->cipher_iv_sz &&
+ test_vec->cipher_iv.data == NULL)
+ return -1;
+ if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
+ return -1;
+ if (test_vec->cipher_key.data == NULL)
+ return -1;
+ if (test_vec->cipher_key.length != opts->cipher_key_sz)
+ return -1;
+ }
+ } else if (opts->op_type == CPERF_AUTH_ONLY) {
+ if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ /* Auth key is only required for some algorithms */
+ if (opts->auth_key_sz &&
+ test_vec->auth_key.data == NULL)
+ return -1;
+ if (test_vec->auth_key.length != opts->auth_key_sz)
+ return -1;
+ if (test_vec->auth_iv.length != opts->auth_iv_sz)
+ return -1;
+ /* Auth IV is only required for some algorithms */
+ if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->digest_sz)
+ return -1;
+ }
+
+ } else if (opts->op_type == CPERF_CIPHER_THEN_AUTH ||
+ opts->op_type == CPERF_AUTH_THEN_CIPHER) {
+ if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ } else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->cipher_iv.data == NULL)
+ return -1;
+ if (test_vec->cipher_iv.length != opts->cipher_iv_sz)
+ return -1;
+ if (test_vec->cipher_key.data == NULL)
+ return -1;
+ if (test_vec->cipher_key.length != opts->cipher_key_sz)
+ return -1;
+ }
+ if (opts->auth_algo != RTE_CRYPTO_AUTH_NULL) {
+ if (test_vec->auth_key.data == NULL)
+ return -1;
+ if (test_vec->auth_key.length != opts->auth_key_sz)
+ return -1;
+ if (test_vec->auth_iv.length != opts->auth_iv_sz)
+ return -1;
+ /* Auth IV is only required for some algorithms */
+ if (opts->auth_iv_sz && test_vec->auth_iv.data == NULL)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->digest_sz)
+ return -1;
+ }
+ } else if (opts->op_type == CPERF_AEAD) {
+ if (test_vec->plaintext.data == NULL)
+ return -1;
+ if (test_vec->plaintext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->ciphertext.data == NULL)
+ return -1;
+ if (test_vec->ciphertext.length < opts->max_buffer_size)
+ return -1;
+ if (test_vec->aead_key.data == NULL)
+ return -1;
+ if (test_vec->aead_key.length != opts->aead_key_sz)
+ return -1;
+ if (test_vec->aead_iv.data == NULL)
+ return -1;
+ if (test_vec->aead_iv.length != opts->aead_iv_sz)
+ return -1;
+ if (test_vec->aad.data == NULL)
+ return -1;
+ if (test_vec->aad.length != opts->aead_aad_sz)
+ return -1;
+ if (test_vec->digest.data == NULL)
+ return -1;
+ if (test_vec->digest.length < opts->digest_sz)
+ return -1;
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct cperf_options opts = {0};
+ struct cperf_test_vector *t_vec = NULL;
+ struct cperf_op_fns op_fns;
+ void *ctx[RTE_MAX_LCORE] = { };
+ int nb_cryptodevs = 0;
+ uint16_t total_nb_qps = 0;
+ uint8_t cdev_id, i;
+ uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = { 0 };
+
+ uint8_t buffer_size_idx = 0;
+
+ int ret;
+ uint32_t lcore_id;
+
+ /* Initialise DPDK EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid EAL arguments!\n");
+ argc -= ret;
+ argv += ret;
+
+ cperf_options_default(&opts);
+
+ ret = cperf_options_parse(&opts, argc, argv);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
+ goto err;
+ }
+
+ ret = cperf_options_check(&opts);
+ if (ret) {
+ RTE_LOG(ERR, USER1,
+ "Checking on or more user options failed\n");
+ goto err;
+ }
+
+ nb_cryptodevs = cperf_initialize_cryptodev(&opts, enabled_cdevs);
+
+ if (!opts.silent)
+ cperf_options_dump(&opts);
+
+ if (nb_cryptodevs < 1) {
+ RTE_LOG(ERR, USER1, "Failed to initialise requested crypto "
+ "device type\n");
+ nb_cryptodevs = 0;
+ goto err;
+ }
+
+ ret = cperf_verify_devices_capabilities(&opts, enabled_cdevs,
+ nb_cryptodevs);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Crypto device type does not support "
+ "capabilities requested\n");
+ goto err;
+ }
+
+ if (opts.test_file != NULL) {
+ t_vec = cperf_test_vector_get_from_file(&opts);
+ if (t_vec == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Failed to create test vector for"
+ " specified file\n");
+ goto err;
+ }
+
+ if (cperf_check_test_vector(&opts, t_vec)) {
+ RTE_LOG(ERR, USER1, "Incomplete necessary test vectors"
+ "\n");
+ goto err;
+ }
+ } else {
+ t_vec = cperf_test_vector_get_dummy(&opts);
+ if (t_vec == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Failed to create test vector for"
+ " specified algorithms\n");
+ goto err;
+ }
+ }
+
+ ret = cperf_get_op_functions(&opts, &op_fns);
+ if (ret) {
+ RTE_LOG(ERR, USER1, "Failed to find function ops set for "
+ "specified algorithms combination\n");
+ goto err;
+ }
+
+ if (!opts.silent && opts.test != CPERF_TEST_TYPE_THROUGHPUT &&
+ opts.test != CPERF_TEST_TYPE_LATENCY)
+ show_test_vector(t_vec);
+
+ total_nb_qps = nb_cryptodevs * opts.nb_qps;
+
+ i = 0;
+ uint8_t qp_id = 0, cdev_index = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ cdev_id = enabled_cdevs[cdev_index];
+
+ uint8_t socket_id = rte_cryptodev_socket_id(cdev_id);
+
+ ctx[i] = cperf_testmap[opts.test].constructor(
+ session_pool_socket[socket_id].sess_mp,
+ session_pool_socket[socket_id].priv_mp,
+ cdev_id, qp_id,
+ &opts, t_vec, &op_fns);
+ if (ctx[i] == NULL) {
+ RTE_LOG(ERR, USER1, "Test run constructor failed\n");
+ goto err;
+ }
+ qp_id = (qp_id + 1) % opts.nb_qps;
+ if (qp_id == 0)
+ cdev_index++;
+ i++;
+ }
+
+ if (opts.imix_distribution_count != 0) {
+ uint8_t buffer_size_count = opts.buffer_size_count;
+ uint16_t distribution_total[buffer_size_count];
+ uint32_t op_idx;
+ uint32_t test_average_size = 0;
+ const uint32_t *buffer_size_list = opts.buffer_size_list;
+ const uint32_t *imix_distribution_list = opts.imix_distribution_list;
+
+ opts.imix_buffer_sizes = rte_malloc(NULL,
+ sizeof(uint32_t) * opts.pool_sz,
+ 0);
+ /*
+ * Calculate accumulated distribution of
+ * probabilities per packet size
+ */
+ distribution_total[0] = imix_distribution_list[0];
+ for (i = 1; i < buffer_size_count; i++)
+ distribution_total[i] = imix_distribution_list[i] +
+ distribution_total[i-1];
+
+ /* Calculate a random sequence of packet sizes, based on distribution */
+ for (op_idx = 0; op_idx < opts.pool_sz; op_idx++) {
+ uint16_t random_number = rte_rand() %
+ distribution_total[buffer_size_count - 1];
+ for (i = 0; i < buffer_size_count; i++)
+ if (random_number < distribution_total[i])
+ break;
+
+ opts.imix_buffer_sizes[op_idx] = buffer_size_list[i];
+ }
+
+ /* Calculate average buffer size for the IMIX distribution */
+ for (i = 0; i < buffer_size_count; i++)
+ test_average_size += buffer_size_list[i] *
+ imix_distribution_list[i];
+
+ opts.test_buffer_size = test_average_size /
+ distribution_total[buffer_size_count - 1];
+
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ rte_eal_remote_launch(cperf_testmap[opts.test].runner,
+ ctx[i], lcore_id);
+ i++;
+ }
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+ ret |= rte_eal_wait_lcore(lcore_id);
+ i++;
+ }
+
+ if (ret != EXIT_SUCCESS)
+ goto err;
+ } else {
+
+ /* Get next size from range or list */
+ if (opts.inc_buffer_size != 0)
+ opts.test_buffer_size = opts.min_buffer_size;
+ else
+ opts.test_buffer_size = opts.buffer_size_list[0];
+
+ while (opts.test_buffer_size <= opts.max_buffer_size) {
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ rte_eal_remote_launch(cperf_testmap[opts.test].runner,
+ ctx[i], lcore_id);
+ i++;
+ }
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+ ret |= rte_eal_wait_lcore(lcore_id);
+ i++;
+ }
+
+ if (ret != EXIT_SUCCESS)
+ goto err;
+
+ /* Get next size from range or list */
+ if (opts.inc_buffer_size != 0)
+ opts.test_buffer_size += opts.inc_buffer_size;
+ else {
+ if (++buffer_size_idx == opts.buffer_size_count)
+ break;
+ opts.test_buffer_size =
+ opts.buffer_size_list[buffer_size_idx];
+ }
+ }
+ }
+
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+
+ if (i == total_nb_qps)
+ break;
+
+ cperf_testmap[opts.test].destructor(ctx[i]);
+ i++;
+ }
+
+ for (i = 0; i < nb_cryptodevs &&
+ i < RTE_CRYPTO_MAX_DEVS; i++)
+ rte_cryptodev_stop(enabled_cdevs[i]);
+
+ free_test_vector(t_vec, &opts);
+
+ printf("\n");
+ return EXIT_SUCCESS;
+
+err:
+ i = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (i == total_nb_qps)
+ break;
+
+ if (ctx[i] && cperf_testmap[opts.test].destructor)
+ cperf_testmap[opts.test].destructor(ctx[i]);
+ i++;
+ }
+
+ for (i = 0; i < nb_cryptodevs &&
+ i < RTE_CRYPTO_MAX_DEVS; i++)
+ rte_cryptodev_stop(enabled_cdevs[i]);
+ rte_free(opts.imix_buffer_sizes);
+ free_test_vector(t_vec, &opts);
+
+ printf("\n");
+ return EXIT_FAILURE;
+}
diff --git a/src/spdk/dpdk/app/test-crypto-perf/meson.build b/src/spdk/dpdk/app/test-crypto-perf/meson.build
new file mode 100644
index 000000000..ef28cb5a0
--- /dev/null
+++ b/src/spdk/dpdk/app/test-crypto-perf/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+sources = files('cperf_ops.c',
+ 'cperf_options_parsing.c',
+ 'cperf_test_common.c',
+ 'cperf_test_latency.c',
+ 'cperf_test_pmd_cyclecount.c',
+ 'cperf_test_throughput.c',
+ 'cperf_test_vector_parsing.c',
+ 'cperf_test_vectors.c',
+ 'cperf_test_verify.c',
+ 'main.c')
+deps += ['cryptodev', 'security']
diff --git a/src/spdk/dpdk/app/test-eventdev/Makefile b/src/spdk/dpdk/app/test-eventdev/Makefile
new file mode 100644
index 000000000..e600e21c4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/Makefile
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Cavium, Inc
+#
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+APP = dpdk-test-eventdev
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y := evt_main.c
+SRCS-y += evt_options.c
+SRCS-y += evt_test.c
+SRCS-y += parser.c
+
+SRCS-y += test_order_common.c
+SRCS-y += test_order_queue.c
+SRCS-y += test_order_atq.c
+
+SRCS-y += test_perf_common.c
+SRCS-y += test_perf_queue.c
+SRCS-y += test_perf_atq.c
+
+SRCS-y += test_pipeline_common.c
+SRCS-y += test_pipeline_queue.c
+SRCS-y += test_pipeline_atq.c
+
+include $(RTE_SDK)/mk/rte.app.mk
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_common.h b/src/spdk/dpdk/app/test-eventdev/evt_common.h
new file mode 100644
index 000000000..f9d7378d3
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_common.h
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _EVT_COMMON_
+#define _EVT_COMMON_
+
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_eventdev.h>
+#include <rte_service.h>
+
+#define CLNRM "\x1b[0m"
+#define CLRED "\x1b[31m"
+#define CLGRN "\x1b[32m"
+#define CLYEL "\x1b[33m"
+
+#define evt_err(fmt, args...) \
+ fprintf(stderr, CLRED"error: %s() "fmt CLNRM "\n", __func__, ## args)
+
+#define evt_info(fmt, args...) \
+ fprintf(stdout, CLYEL""fmt CLNRM "\n", ## args)
+
+#define EVT_STR_FMT 20
+
+#define evt_dump(str, fmt, val...) \
+ printf("\t%-*s : "fmt"\n", EVT_STR_FMT, str, ## val)
+
+#define evt_dump_begin(str) printf("\t%-*s : {", EVT_STR_FMT, str)
+
+#define evt_dump_end printf("\b}\n")
+
+#define EVT_MAX_STAGES 64
+#define EVT_MAX_PORTS 256
+#define EVT_MAX_QUEUES 256
+
+enum evt_prod_type {
+ EVT_PROD_TYPE_NONE,
+ EVT_PROD_TYPE_SYNT, /* Producer type Synthetic i.e. CPU. */
+ EVT_PROD_TYPE_ETH_RX_ADPTR, /* Producer type Eth Rx Adapter. */
+ EVT_PROD_TYPE_EVENT_TIMER_ADPTR, /* Producer type Timer Adapter. */
+ EVT_PROD_TYPE_MAX,
+};
+
+struct evt_options {
+#define EVT_TEST_NAME_MAX_LEN 32
+ char test_name[EVT_TEST_NAME_MAX_LEN];
+ bool plcores[RTE_MAX_LCORE];
+ bool wlcores[RTE_MAX_LCORE];
+ int pool_sz;
+ int socket_id;
+ int nb_stages;
+ int verbose_level;
+ uint8_t dev_id;
+ uint8_t timdev_cnt;
+ uint8_t nb_timer_adptrs;
+ uint8_t timdev_use_burst;
+ uint8_t sched_type_list[EVT_MAX_STAGES];
+ uint16_t mbuf_sz;
+ uint16_t wkr_deq_dep;
+ uint32_t nb_flows;
+ uint32_t tx_first;
+ uint32_t max_pkt_sz;
+ uint32_t deq_tmo_nsec;
+ uint32_t q_priority:1;
+ uint32_t fwd_latency:1;
+ uint64_t nb_pkts;
+ uint64_t nb_timers;
+ uint64_t expiry_nsec;
+ uint64_t max_tmo_nsec;
+ uint64_t timer_tick_nsec;
+ uint64_t optm_timer_tick_nsec;
+ enum evt_prod_type prod_type;
+};
+
+static inline bool
+evt_has_distributed_sched(uint8_t dev_id)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(dev_id, &dev_info);
+ return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED) ?
+ true : false;
+}
+
+static inline bool
+evt_has_burst_mode(uint8_t dev_id)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(dev_id, &dev_info);
+ return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE) ?
+ true : false;
+}
+
+
+static inline bool
+evt_has_all_types_queue(uint8_t dev_id)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(dev_id, &dev_info);
+ return (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES) ?
+ true : false;
+}
+
+static inline int
+evt_service_setup(uint32_t service_id)
+{
+ int32_t core_cnt;
+ unsigned int lcore = 0;
+ uint32_t core_array[RTE_MAX_LCORE];
+ uint8_t cnt;
+ uint8_t min_cnt = UINT8_MAX;
+
+ if (!rte_service_lcore_count())
+ return -ENOENT;
+
+ core_cnt = rte_service_lcore_list(core_array,
+ RTE_MAX_LCORE);
+ if (core_cnt < 0)
+ return -ENOENT;
+ /* Get the core which has least number of services running. */
+ while (core_cnt--) {
+ /* Reset default mapping */
+ rte_service_map_lcore_set(service_id,
+ core_array[core_cnt], 0);
+ cnt = rte_service_lcore_count_services(
+ core_array[core_cnt]);
+ if (cnt < min_cnt) {
+ lcore = core_array[core_cnt];
+ min_cnt = cnt;
+ }
+ }
+ if (rte_service_map_lcore_set(service_id, lcore, 1))
+ return -ENOENT;
+
+ return 0;
+}
+
+static inline int
+evt_configure_eventdev(struct evt_options *opt, uint8_t nb_queues,
+ uint8_t nb_ports)
+{
+ struct rte_event_dev_info info;
+ int ret;
+
+ memset(&info, 0, sizeof(struct rte_event_dev_info));
+ ret = rte_event_dev_info_get(opt->dev_id, &info);
+ if (ret) {
+ evt_err("failed to get eventdev info %d", opt->dev_id);
+ return ret;
+ }
+
+ if (opt->deq_tmo_nsec) {
+ if (opt->deq_tmo_nsec < info.min_dequeue_timeout_ns) {
+ opt->deq_tmo_nsec = info.min_dequeue_timeout_ns;
+ evt_info("dequeue_timeout_ns too low, using %d",
+ opt->deq_tmo_nsec);
+ }
+ if (opt->deq_tmo_nsec > info.max_dequeue_timeout_ns) {
+ opt->deq_tmo_nsec = info.max_dequeue_timeout_ns;
+ evt_info("dequeue_timeout_ns too high, using %d",
+ opt->deq_tmo_nsec);
+ }
+ }
+
+ const struct rte_event_dev_config config = {
+ .dequeue_timeout_ns = opt->deq_tmo_nsec,
+ .nb_event_queues = nb_queues,
+ .nb_event_ports = nb_ports,
+ .nb_events_limit = info.max_num_events,
+ .nb_event_queue_flows = opt->nb_flows,
+ .nb_event_port_dequeue_depth =
+ info.max_event_port_dequeue_depth,
+ .nb_event_port_enqueue_depth =
+ info.max_event_port_enqueue_depth,
+ };
+
+ return rte_event_dev_configure(opt->dev_id, &config);
+}
+
+#endif /* _EVT_COMMON_*/
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_main.c b/src/spdk/dpdk/app/test-eventdev/evt_main.c
new file mode 100644
index 000000000..a8d304bab
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_main.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <rte_atomic.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_eventdev.h>
+
+#include "evt_options.h"
+#include "evt_test.h"
+
+struct evt_options opt;
+struct evt_test *test;
+
+static void
+signal_handler(int signum)
+{
+ int i;
+ static uint8_t once;
+
+ if ((signum == SIGINT || signum == SIGTERM) && !once) {
+ once = true;
+ printf("\nSignal %d received, preparing to exit...\n",
+ signum);
+
+ if (test != NULL) {
+ /* request all lcores to exit from the main loop */
+ *(int *)test->test_priv = true;
+ rte_wmb();
+
+ if (test->ops.ethdev_destroy)
+ test->ops.ethdev_destroy(test, &opt);
+
+ rte_eal_mp_wait_lcore();
+
+ if (test->ops.test_result)
+ test->ops.test_result(test, &opt);
+
+ if (opt.prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ RTE_ETH_FOREACH_DEV(i)
+ rte_eth_dev_close(i);
+ }
+
+ if (test->ops.eventdev_destroy)
+ test->ops.eventdev_destroy(test, &opt);
+
+ if (test->ops.mempool_destroy)
+ test->ops.mempool_destroy(test, &opt);
+
+ if (test->ops.test_destroy)
+ test->ops.test_destroy(test, &opt);
+ }
+
+ /* exit with the expected status */
+ signal(signum, SIG_DFL);
+ kill(getpid(), signum);
+ }
+}
+
+static inline void
+evt_options_dump_all(struct evt_test *test, struct evt_options *opts)
+{
+ evt_options_dump(opts);
+ if (test->ops.opt_dump)
+ test->ops.opt_dump(opts);
+}
+
+int
+main(int argc, char **argv)
+{
+ uint8_t evdevs;
+ int ret;
+
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_panic("invalid EAL arguments\n");
+ argc -= ret;
+ argv += ret;
+
+ evdevs = rte_event_dev_count();
+ if (!evdevs)
+ rte_panic("no eventdev devices found\n");
+
+ /* Populate the default values of the options */
+ evt_options_default(&opt);
+
+ /* Parse the command line arguments */
+ ret = evt_options_parse(&opt, argc, argv);
+ if (ret) {
+ evt_err("parsing on or more user options failed");
+ goto error;
+ }
+
+ /* Get struct evt_test *test from name */
+ test = evt_test_get(opt.test_name);
+ if (test == NULL) {
+ evt_err("failed to find requested test: %s", opt.test_name);
+ goto error;
+ }
+
+ if (test->ops.test_result == NULL) {
+ evt_err("%s: ops.test_result not found", opt.test_name);
+ goto error;
+ }
+
+ /* Verify the command line options */
+ if (opt.dev_id >= rte_event_dev_count()) {
+ evt_err("invalid event device %d", opt.dev_id);
+ goto error;
+ }
+ if (test->ops.opt_check) {
+ if (test->ops.opt_check(&opt)) {
+ evt_err("invalid command line argument");
+ evt_options_dump_all(test, &opt);
+ goto error;
+ }
+ }
+
+ /* Check the eventdev capability before proceeding */
+ if (test->ops.cap_check) {
+ if (test->ops.cap_check(&opt) == false) {
+ evt_info("unsupported test: %s", opt.test_name);
+ evt_options_dump_all(test, &opt);
+ ret = EVT_TEST_UNSUPPORTED;
+ goto nocap;
+ }
+ }
+
+ /* Dump the options */
+ if (opt.verbose_level)
+ evt_options_dump_all(test, &opt);
+
+ /* Test specific setup */
+ if (test->ops.test_setup) {
+ if (test->ops.test_setup(test, &opt)) {
+ evt_err("failed to setup test: %s", opt.test_name);
+ goto error;
+
+ }
+ }
+
+ /* Test specific mempool setup */
+ if (test->ops.mempool_setup) {
+ if (test->ops.mempool_setup(test, &opt)) {
+ evt_err("%s: mempool setup failed", opt.test_name);
+ goto test_destroy;
+ }
+ }
+
+ /* Test specific ethdev setup */
+ if (test->ops.ethdev_setup) {
+ if (test->ops.ethdev_setup(test, &opt)) {
+ evt_err("%s: ethdev setup failed", opt.test_name);
+ goto mempool_destroy;
+ }
+ }
+
+ /* Test specific eventdev setup */
+ if (test->ops.eventdev_setup) {
+ if (test->ops.eventdev_setup(test, &opt)) {
+ evt_err("%s: eventdev setup failed", opt.test_name);
+ goto ethdev_destroy;
+ }
+ }
+
+ /* Launch lcores */
+ if (test->ops.launch_lcores) {
+ if (test->ops.launch_lcores(test, &opt)) {
+ evt_err("%s: failed to launch lcores", opt.test_name);
+ goto eventdev_destroy;
+ }
+ }
+
+ rte_eal_mp_wait_lcore();
+
+ /* Print the test result */
+ ret = test->ops.test_result(test, &opt);
+nocap:
+ if (ret == EVT_TEST_SUCCESS) {
+ printf("Result: "CLGRN"%s"CLNRM"\n", "Success");
+ } else if (ret == EVT_TEST_FAILED) {
+ printf("Result: "CLRED"%s"CLNRM"\n", "Failed");
+ return EXIT_FAILURE;
+ } else if (ret == EVT_TEST_UNSUPPORTED) {
+ printf("Result: "CLYEL"%s"CLNRM"\n", "Unsupported");
+ }
+
+ return 0;
+eventdev_destroy:
+ if (test->ops.eventdev_destroy)
+ test->ops.eventdev_destroy(test, &opt);
+
+ethdev_destroy:
+ if (test->ops.ethdev_destroy)
+ test->ops.ethdev_destroy(test, &opt);
+
+mempool_destroy:
+ if (test->ops.mempool_destroy)
+ test->ops.mempool_destroy(test, &opt);
+
+test_destroy:
+ if (test->ops.test_destroy)
+ test->ops.test_destroy(test, &opt);
+error:
+ return EXIT_FAILURE;
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_options.c b/src/spdk/dpdk/app/test-eventdev/evt_options.c
new file mode 100644
index 000000000..c60b61a90
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_options.c
@@ -0,0 +1,450 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_eventdev.h>
+#include <rte_lcore.h>
+
+#include "evt_options.h"
+#include "evt_test.h"
+#include "parser.h"
+
+void
+evt_options_default(struct evt_options *opt)
+{
+ memset(opt, 0, sizeof(*opt));
+ opt->verbose_level = 1; /* Enable minimal prints */
+ opt->dev_id = 0;
+ strncpy(opt->test_name, "order_queue", EVT_TEST_NAME_MAX_LEN);
+ opt->nb_flows = 1024;
+ opt->socket_id = SOCKET_ID_ANY;
+ opt->pool_sz = 16 * 1024;
+ opt->wkr_deq_dep = 16;
+ opt->nb_pkts = (1ULL << 26); /* do ~64M packets */
+ opt->nb_timers = 1E8;
+ opt->nb_timer_adptrs = 1;
+ opt->timer_tick_nsec = 1E3; /* 1000ns ~ 1us */
+ opt->max_tmo_nsec = 1E5; /* 100000ns ~100us */
+ opt->expiry_nsec = 1E4; /* 10000ns ~10us */
+ opt->prod_type = EVT_PROD_TYPE_SYNT;
+}
+
+typedef int (*option_parser_t)(struct evt_options *opt,
+ const char *arg);
+
+struct long_opt_parser {
+ const char *lgopt_name;
+ option_parser_t parser_fn;
+};
+
+static int
+evt_parse_nb_flows(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint32(&(opt->nb_flows), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_dev_id(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint8(&(opt->dev_id), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_verbose(struct evt_options *opt, const char *arg __rte_unused)
+{
+ opt->verbose_level = atoi(arg);
+ return 0;
+}
+
+static int
+evt_parse_fwd_latency(struct evt_options *opt, const char *arg __rte_unused)
+{
+ opt->fwd_latency = 1;
+ return 0;
+}
+
+static int
+evt_parse_queue_priority(struct evt_options *opt, const char *arg __rte_unused)
+{
+ opt->q_priority = 1;
+ return 0;
+}
+
+static int
+evt_parse_deq_tmo_nsec(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint32(&(opt->deq_tmo_nsec), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_eth_prod_type(struct evt_options *opt, const char *arg __rte_unused)
+{
+ opt->prod_type = EVT_PROD_TYPE_ETH_RX_ADPTR;
+ return 0;
+}
+
+static int
+evt_parse_timer_prod_type(struct evt_options *opt, const char *arg __rte_unused)
+{
+ opt->prod_type = EVT_PROD_TYPE_EVENT_TIMER_ADPTR;
+ return 0;
+}
+
+static int
+evt_parse_timer_prod_type_burst(struct evt_options *opt,
+ const char *arg __rte_unused)
+{
+ opt->prod_type = EVT_PROD_TYPE_EVENT_TIMER_ADPTR;
+ opt->timdev_use_burst = 1;
+ return 0;
+}
+
+static int
+evt_parse_test_name(struct evt_options *opt, const char *arg)
+{
+ strlcpy(opt->test_name, arg, EVT_TEST_NAME_MAX_LEN);
+ return 0;
+}
+
+static int
+evt_parse_socket_id(struct evt_options *opt, const char *arg)
+{
+ opt->socket_id = atoi(arg);
+ return 0;
+}
+
+static int
+evt_parse_wkr_deq_dep(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint16(&(opt->wkr_deq_dep), arg);
+ return ret;
+}
+
+static int
+evt_parse_nb_pkts(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint64(&(opt->nb_pkts), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_nb_timers(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint64(&(opt->nb_timers), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_timer_tick_nsec(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint64(&(opt->timer_tick_nsec), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_max_tmo_nsec(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint64(&(opt->max_tmo_nsec), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_expiry_nsec(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint64(&(opt->expiry_nsec), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_nb_timer_adptrs(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint8(&(opt->nb_timer_adptrs), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_pool_sz(struct evt_options *opt, const char *arg)
+{
+ opt->pool_sz = atoi(arg);
+
+ return 0;
+}
+
+static int
+evt_parse_plcores(struct evt_options *opt, const char *corelist)
+{
+ int ret;
+
+ ret = parse_lcores_list(opt->plcores, corelist);
+ if (ret == -E2BIG)
+ evt_err("duplicate lcores in plcores");
+
+ return ret;
+}
+
+static int
+evt_parse_work_lcores(struct evt_options *opt, const char *corelist)
+{
+ int ret;
+
+ ret = parse_lcores_list(opt->wlcores, corelist);
+ if (ret == -E2BIG)
+ evt_err("duplicate lcores in wlcores");
+
+ return ret;
+}
+
+static int
+evt_parse_mbuf_sz(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint16(&(opt->mbuf_sz), arg);
+
+ return ret;
+}
+
+static int
+evt_parse_max_pkt_sz(struct evt_options *opt, const char *arg)
+{
+ int ret;
+
+ ret = parser_read_uint32(&(opt->max_pkt_sz), arg);
+
+ return ret;
+}
+
+static void
+usage(char *program)
+{
+ printf("usage : %s [EAL options] -- [application options]\n", program);
+ printf("application options:\n");
+ printf("\t--verbose : verbose level\n"
+ "\t--dev : device id of the event device\n"
+ "\t--test : name of the test application to run\n"
+ "\t--socket_id : socket_id of application resources\n"
+ "\t--pool_sz : pool size of the mempool\n"
+ "\t--plcores : list of lcore ids for producers\n"
+ "\t--wlcores : list of lcore ids for workers\n"
+ "\t--stlist : list of scheduled types of the stages\n"
+ "\t--nb_flows : number of flows to produce\n"
+ "\t--nb_pkts : number of packets to produce\n"
+ "\t--worker_deq_depth : dequeue depth of the worker\n"
+ "\t--fwd_latency : perform fwd_latency measurement\n"
+ "\t--queue_priority : enable queue priority\n"
+ "\t--deq_tmo_nsec : global dequeue timeout\n"
+ "\t--prod_type_ethdev : use ethernet device as producer.\n"
+ "\t--prod_type_timerdev : use event timer device as producer.\n"
+ "\t expity_nsec would be the timeout\n"
+ "\t in ns.\n"
+ "\t--prod_type_timerdev_burst : use timer device as producer\n"
+ "\t burst mode.\n"
+ "\t--nb_timers : number of timers to arm.\n"
+ "\t--nb_timer_adptrs : number of timer adapters to use.\n"
+ "\t--timer_tick_nsec : timer tick interval in ns.\n"
+ "\t--max_tmo_nsec : max timeout interval in ns.\n"
+ "\t--expiry_nsec : event timer expiry ns.\n"
+ "\t--mbuf_sz : packet mbuf size.\n"
+ "\t--max_pkt_sz : max packet size.\n"
+ );
+ printf("available tests:\n");
+ evt_test_dump_names();
+}
+
+static int
+evt_parse_sched_type_list(struct evt_options *opt, const char *arg)
+{
+ char c;
+ int i = 0, j = -1;
+
+ for (i = 0; i < EVT_MAX_STAGES; i++)
+ opt->sched_type_list[i] = (uint8_t)-1;
+
+ i = 0;
+
+ do {
+ c = arg[++j];
+
+ switch (c) {
+ case 'o':
+ case 'O':
+ opt->sched_type_list[i++] = RTE_SCHED_TYPE_ORDERED;
+ break;
+ case 'a':
+ case 'A':
+ opt->sched_type_list[i++] = RTE_SCHED_TYPE_ATOMIC;
+ break;
+ case 'p':
+ case 'P':
+ opt->sched_type_list[i++] = RTE_SCHED_TYPE_PARALLEL;
+ break;
+ case ',':
+ break;
+ default:
+ if (c != '\0') {
+ evt_err("invalid sched_type %c", c);
+ return -EINVAL;
+ }
+ }
+ } while (c != '\0');
+
+ opt->nb_stages = i;
+ return 0;
+}
+
+static struct option lgopts[] = {
+ { EVT_NB_FLOWS, 1, 0, 0 },
+ { EVT_DEVICE, 1, 0, 0 },
+ { EVT_VERBOSE, 1, 0, 0 },
+ { EVT_TEST, 1, 0, 0 },
+ { EVT_PROD_LCORES, 1, 0, 0 },
+ { EVT_WORK_LCORES, 1, 0, 0 },
+ { EVT_SOCKET_ID, 1, 0, 0 },
+ { EVT_POOL_SZ, 1, 0, 0 },
+ { EVT_NB_PKTS, 1, 0, 0 },
+ { EVT_WKR_DEQ_DEP, 1, 0, 0 },
+ { EVT_SCHED_TYPE_LIST, 1, 0, 0 },
+ { EVT_FWD_LATENCY, 0, 0, 0 },
+ { EVT_QUEUE_PRIORITY, 0, 0, 0 },
+ { EVT_DEQ_TMO_NSEC, 1, 0, 0 },
+ { EVT_PROD_ETHDEV, 0, 0, 0 },
+ { EVT_PROD_TIMERDEV, 0, 0, 0 },
+ { EVT_PROD_TIMERDEV_BURST, 0, 0, 0 },
+ { EVT_NB_TIMERS, 1, 0, 0 },
+ { EVT_NB_TIMER_ADPTRS, 1, 0, 0 },
+ { EVT_TIMER_TICK_NSEC, 1, 0, 0 },
+ { EVT_MAX_TMO_NSEC, 1, 0, 0 },
+ { EVT_EXPIRY_NSEC, 1, 0, 0 },
+ { EVT_MBUF_SZ, 1, 0, 0 },
+ { EVT_MAX_PKT_SZ, 1, 0, 0 },
+ { EVT_HELP, 0, 0, 0 },
+ { NULL, 0, 0, 0 }
+};
+
+static int
+evt_opts_parse_long(int opt_idx, struct evt_options *opt)
+{
+ unsigned int i;
+
+ struct long_opt_parser parsermap[] = {
+ { EVT_NB_FLOWS, evt_parse_nb_flows},
+ { EVT_DEVICE, evt_parse_dev_id},
+ { EVT_VERBOSE, evt_parse_verbose},
+ { EVT_TEST, evt_parse_test_name},
+ { EVT_PROD_LCORES, evt_parse_plcores},
+ { EVT_WORK_LCORES, evt_parse_work_lcores},
+ { EVT_SOCKET_ID, evt_parse_socket_id},
+ { EVT_POOL_SZ, evt_parse_pool_sz},
+ { EVT_NB_PKTS, evt_parse_nb_pkts},
+ { EVT_WKR_DEQ_DEP, evt_parse_wkr_deq_dep},
+ { EVT_SCHED_TYPE_LIST, evt_parse_sched_type_list},
+ { EVT_FWD_LATENCY, evt_parse_fwd_latency},
+ { EVT_QUEUE_PRIORITY, evt_parse_queue_priority},
+ { EVT_DEQ_TMO_NSEC, evt_parse_deq_tmo_nsec},
+ { EVT_PROD_ETHDEV, evt_parse_eth_prod_type},
+ { EVT_PROD_TIMERDEV, evt_parse_timer_prod_type},
+ { EVT_PROD_TIMERDEV_BURST, evt_parse_timer_prod_type_burst},
+ { EVT_NB_TIMERS, evt_parse_nb_timers},
+ { EVT_NB_TIMER_ADPTRS, evt_parse_nb_timer_adptrs},
+ { EVT_TIMER_TICK_NSEC, evt_parse_timer_tick_nsec},
+ { EVT_MAX_TMO_NSEC, evt_parse_max_tmo_nsec},
+ { EVT_EXPIRY_NSEC, evt_parse_expiry_nsec},
+ { EVT_MBUF_SZ, evt_parse_mbuf_sz},
+ { EVT_MAX_PKT_SZ, evt_parse_max_pkt_sz},
+ };
+
+ for (i = 0; i < RTE_DIM(parsermap); i++) {
+ if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+ strlen(lgopts[opt_idx].name)) == 0)
+ return parsermap[i].parser_fn(opt, optarg);
+ }
+
+ return -EINVAL;
+}
+
+int
+evt_options_parse(struct evt_options *opt, int argc, char **argv)
+{
+ int opts, retval, opt_idx;
+
+ while ((opts = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
+ switch (opts) {
+ case 0: /* long options */
+ if (!strcmp(lgopts[opt_idx].name, "help")) {
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+
+ retval = evt_opts_parse_long(opt_idx, opt);
+ if (retval != 0)
+ return retval;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+void
+evt_options_dump(struct evt_options *opt)
+{
+ int lcore_id;
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ evt_dump("driver", "%s", dev_info.driver_name);
+ evt_dump("test", "%s", opt->test_name);
+ evt_dump("dev", "%d", opt->dev_id);
+ evt_dump("verbose_level", "%d", opt->verbose_level);
+ evt_dump("socket_id", "%d", opt->socket_id);
+ evt_dump("pool_sz", "%d", opt->pool_sz);
+ evt_dump("master lcore", "%d", rte_get_master_lcore());
+ evt_dump("nb_pkts", "%"PRIu64, opt->nb_pkts);
+ evt_dump("nb_timers", "%"PRIu64, opt->nb_timers);
+ evt_dump_begin("available lcores");
+ RTE_LCORE_FOREACH(lcore_id)
+ printf("%d ", lcore_id);
+ evt_dump_end;
+ evt_dump_nb_flows(opt);
+ evt_dump_worker_dequeue_depth(opt);
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_options.h b/src/spdk/dpdk/app/test-eventdev/evt_options.h
new file mode 100644
index 000000000..748e54fae
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_options.h
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _EVT_OPTIONS_
+#define _EVT_OPTIONS_
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_lcore.h>
+
+#include "evt_common.h"
+
+#define EVT_BOOL_FMT(x) ((x) ? "true" : "false")
+
+#define EVT_VERBOSE ("verbose")
+#define EVT_DEVICE ("dev")
+#define EVT_TEST ("test")
+#define EVT_PROD_LCORES ("plcores")
+#define EVT_WORK_LCORES ("wlcores")
+#define EVT_NB_FLOWS ("nb_flows")
+#define EVT_SOCKET_ID ("socket_id")
+#define EVT_POOL_SZ ("pool_sz")
+#define EVT_WKR_DEQ_DEP ("worker_deq_depth")
+#define EVT_NB_PKTS ("nb_pkts")
+#define EVT_NB_STAGES ("nb_stages")
+#define EVT_SCHED_TYPE_LIST ("stlist")
+#define EVT_FWD_LATENCY ("fwd_latency")
+#define EVT_QUEUE_PRIORITY ("queue_priority")
+#define EVT_DEQ_TMO_NSEC ("deq_tmo_nsec")
+#define EVT_PROD_ETHDEV ("prod_type_ethdev")
+#define EVT_PROD_TIMERDEV ("prod_type_timerdev")
+#define EVT_PROD_TIMERDEV_BURST ("prod_type_timerdev_burst")
+#define EVT_NB_TIMERS ("nb_timers")
+#define EVT_NB_TIMER_ADPTRS ("nb_timer_adptrs")
+#define EVT_TIMER_TICK_NSEC ("timer_tick_nsec")
+#define EVT_MAX_TMO_NSEC ("max_tmo_nsec")
+#define EVT_EXPIRY_NSEC ("expiry_nsec")
+#define EVT_MBUF_SZ ("mbuf_sz")
+#define EVT_MAX_PKT_SZ ("max_pkt_sz")
+#define EVT_HELP ("help")
+
+void evt_options_default(struct evt_options *opt);
+int evt_options_parse(struct evt_options *opt, int argc, char **argv);
+void evt_options_dump(struct evt_options *opt);
+
+/* options check helpers */
+static inline bool
+evt_lcores_has_overlap(bool lcores[], int lcore)
+{
+ if (lcores[lcore] == true) {
+ evt_err("lcore overlaps at %d", lcore);
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool
+evt_lcores_has_overlap_multi(bool lcoresx[], bool lcoresy[])
+{
+ int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ if (lcoresx[i] && lcoresy[i]) {
+ evt_err("lcores overlaps at %d", i);
+ return true;
+ }
+ }
+ return false;
+}
+
+static inline bool
+evt_has_active_lcore(bool lcores[])
+{
+ int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ if (lcores[i])
+ return true;
+ return false;
+}
+
+static inline int
+evt_nr_active_lcores(bool lcores[])
+{
+ int i;
+ int c = 0;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ if (lcores[i])
+ c++;
+ return c;
+}
+
+static inline int
+evt_get_first_active_lcore(bool lcores[])
+{
+ int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ if (lcores[i])
+ return i;
+ return -1;
+}
+
+static inline bool
+evt_has_disabled_lcore(bool lcores[])
+{
+ int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ if ((lcores[i] == true) && !(rte_lcore_is_enabled(i)))
+ return true;
+ return false;
+}
+
+static inline bool
+evt_has_invalid_stage(struct evt_options *opt)
+{
+ if (!opt->nb_stages) {
+ evt_err("need minimum one stage, check --stlist");
+ return true;
+ }
+ if (opt->nb_stages > EVT_MAX_STAGES) {
+ evt_err("requested changes are beyond EVT_MAX_STAGES=%d",
+ EVT_MAX_STAGES);
+ return true;
+ }
+ return false;
+}
+
+static inline bool
+evt_has_invalid_sched_type(struct evt_options *opt)
+{
+ int i;
+
+ for (i = 0; i < opt->nb_stages; i++) {
+ if (opt->sched_type_list[i] > RTE_SCHED_TYPE_PARALLEL) {
+ evt_err("invalid sched_type %d at %d",
+ opt->sched_type_list[i], i);
+ return true;
+ }
+ }
+ return false;
+}
+
+/* option dump helpers */
+static inline void
+evt_dump_worker_lcores(struct evt_options *opt)
+{
+ int c;
+
+ evt_dump_begin("worker lcores");
+ for (c = 0; c < RTE_MAX_LCORE; c++) {
+ if (opt->wlcores[c])
+ printf("%d ", c);
+ }
+ evt_dump_end;
+}
+
+static inline void
+evt_dump_producer_lcores(struct evt_options *opt)
+{
+ int c;
+
+ evt_dump_begin("producer lcores");
+ for (c = 0; c < RTE_MAX_LCORE; c++) {
+ if (opt->plcores[c])
+ printf("%d ", c);
+ }
+ evt_dump_end;
+}
+
+static inline void
+evt_dump_nb_flows(struct evt_options *opt)
+{
+ evt_dump("nb_flows", "%d", opt->nb_flows);
+}
+
+static inline void
+evt_dump_worker_dequeue_depth(struct evt_options *opt)
+{
+ evt_dump("worker deq depth", "%d", opt->wkr_deq_dep);
+}
+
+static inline void
+evt_dump_nb_stages(struct evt_options *opt)
+{
+ evt_dump("nb_stages", "%d", opt->nb_stages);
+}
+
+static inline void
+evt_dump_fwd_latency(struct evt_options *opt)
+{
+ evt_dump("fwd_latency", "%s", EVT_BOOL_FMT(opt->fwd_latency));
+}
+
+static inline void
+evt_dump_queue_priority(struct evt_options *opt)
+{
+ evt_dump("queue_priority", "%s", EVT_BOOL_FMT(opt->q_priority));
+}
+
+static inline const char*
+evt_sched_type_2_str(uint8_t sched_type)
+{
+
+ if (sched_type == RTE_SCHED_TYPE_ORDERED)
+ return "O";
+ else if (sched_type == RTE_SCHED_TYPE_ATOMIC)
+ return "A";
+ else if (sched_type == RTE_SCHED_TYPE_PARALLEL)
+ return "P";
+ else
+ return "I";
+}
+
+static inline void
+evt_dump_sched_type_list(struct evt_options *opt)
+{
+ int i;
+
+ evt_dump_begin("sched_type_list");
+ for (i = 0; i < opt->nb_stages; i++)
+ printf("%s ", evt_sched_type_2_str(opt->sched_type_list[i]));
+
+ evt_dump_end;
+}
+
+static inline const char *
+evt_prod_id_to_name(enum evt_prod_type prod_type)
+{
+ switch (prod_type) {
+ default:
+ case EVT_PROD_TYPE_SYNT:
+ return "Synthetic producer lcores";
+ case EVT_PROD_TYPE_ETH_RX_ADPTR:
+ return "Ethdev Rx Adapter";
+ case EVT_PROD_TYPE_EVENT_TIMER_ADPTR:
+ return "Event timer adapter";
+ }
+
+ return "";
+}
+
+#define EVT_PROD_MAX_NAME_LEN 50
+static inline void
+evt_dump_producer_type(struct evt_options *opt)
+{
+ char name[EVT_PROD_MAX_NAME_LEN];
+
+ switch (opt->prod_type) {
+ default:
+ case EVT_PROD_TYPE_SYNT:
+ snprintf(name, EVT_PROD_MAX_NAME_LEN,
+ "Synthetic producer lcores");
+ break;
+ case EVT_PROD_TYPE_ETH_RX_ADPTR:
+ snprintf(name, EVT_PROD_MAX_NAME_LEN,
+ "Ethdev Rx Adapter producers");
+ evt_dump("nb_ethdev", "%d", rte_eth_dev_count_avail());
+ break;
+ case EVT_PROD_TYPE_EVENT_TIMER_ADPTR:
+ if (opt->timdev_use_burst)
+ snprintf(name, EVT_PROD_MAX_NAME_LEN,
+ "Event timer adapter burst mode producer");
+ else
+ snprintf(name, EVT_PROD_MAX_NAME_LEN,
+ "Event timer adapter producer");
+ evt_dump("nb_timer_adapters", "%d", opt->nb_timer_adptrs);
+ evt_dump("max_tmo_nsec", "%"PRIu64"", opt->max_tmo_nsec);
+ evt_dump("expiry_nsec", "%"PRIu64"", opt->expiry_nsec);
+ if (opt->optm_timer_tick_nsec)
+ evt_dump("optm_timer_tick_nsec", "%"PRIu64"",
+ opt->optm_timer_tick_nsec);
+ else
+ evt_dump("timer_tick_nsec", "%"PRIu64"",
+ opt->timer_tick_nsec);
+ break;
+ }
+ evt_dump("prod_type", "%s", name);
+}
+
+#endif /* _EVT_OPTIONS_ */
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_test.c b/src/spdk/dpdk/app/test-eventdev/evt_test.c
new file mode 100644
index 000000000..72d6228bc
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_test.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/queue.h>
+
+#include "evt_test.h"
+
+static STAILQ_HEAD(, evt_test_entry) head = STAILQ_HEAD_INITIALIZER(head);
+
+void
+evt_test_register(struct evt_test_entry *entry)
+{
+ STAILQ_INSERT_TAIL(&head, entry, next);
+}
+
+struct evt_test*
+evt_test_get(const char *name)
+{
+ struct evt_test_entry *entry;
+
+ if (!name)
+ return NULL;
+
+ STAILQ_FOREACH(entry, &head, next)
+ if (!strncmp(entry->test.name, name, strlen(name)))
+ return &entry->test;
+
+ return NULL;
+}
+
+void
+evt_test_dump_names(void)
+{
+ struct evt_test_entry *entry;
+
+ STAILQ_FOREACH(entry, &head, next)
+ if (entry->test.name)
+ printf("\t %s\n", entry->test.name);
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/evt_test.h b/src/spdk/dpdk/app/test-eventdev/evt_test.h
new file mode 100644
index 000000000..f07d2c333
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/evt_test.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _EVT_TEST_
+#define _EVT_TEST_
+
+#include <string.h>
+#include <stdbool.h>
+#include <sys/queue.h>
+
+#include <rte_eal.h>
+
+enum evt_test_result {
+ EVT_TEST_SUCCESS,
+ EVT_TEST_FAILED,
+ EVT_TEST_UNSUPPORTED,
+};
+
+struct evt_test;
+struct evt_options;
+
+typedef bool (*evt_test_capability_check_t)(struct evt_options *opt);
+typedef int (*evt_test_options_check_t)(struct evt_options *opt);
+typedef void (*evt_test_options_dump_t)(struct evt_options *opt);
+typedef int (*evt_test_setup_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef int (*evt_test_mempool_setup_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef int (*evt_test_ethdev_setup_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef int (*evt_test_eventdev_setup_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef int (*evt_test_launch_lcores_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef int (*evt_test_result_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef void (*evt_test_eventdev_destroy_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef void (*evt_test_ethdev_destroy_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef void (*evt_test_mempool_destroy_t)
+ (struct evt_test *test, struct evt_options *opt);
+typedef void (*evt_test_destroy_t)
+ (struct evt_test *test, struct evt_options *opt);
+
+struct evt_test_ops {
+ evt_test_capability_check_t cap_check;
+ evt_test_options_check_t opt_check;
+ evt_test_options_dump_t opt_dump;
+ evt_test_setup_t test_setup;
+ evt_test_mempool_setup_t mempool_setup;
+ evt_test_ethdev_setup_t ethdev_setup;
+ evt_test_eventdev_setup_t eventdev_setup;
+ evt_test_launch_lcores_t launch_lcores;
+ evt_test_result_t test_result;
+ evt_test_eventdev_destroy_t eventdev_destroy;
+ evt_test_ethdev_destroy_t ethdev_destroy;
+ evt_test_mempool_destroy_t mempool_destroy;
+ evt_test_destroy_t test_destroy;
+};
+
+struct evt_test {
+ const char *name;
+ void *test_priv;
+ struct evt_test_ops ops;
+};
+
+struct evt_test_entry {
+ struct evt_test test;
+
+ STAILQ_ENTRY(evt_test_entry) next;
+};
+
+void evt_test_register(struct evt_test_entry *test);
+void evt_test_dump_names(void);
+
+#define EVT_TEST_REGISTER(nm) \
+static struct evt_test_entry _evt_test_entry_ ##nm; \
+RTE_INIT(evt_test_ ##nm) \
+{ \
+ _evt_test_entry_ ##nm.test.name = RTE_STR(nm);\
+ memcpy(&_evt_test_entry_ ##nm.test.ops, &nm, \
+ sizeof(struct evt_test_ops)); \
+ evt_test_register(&_evt_test_entry_ ##nm); \
+}
+
+struct evt_test *evt_test_get(const char *name);
+
+static inline void *
+evt_test_priv(struct evt_test *test)
+{
+ return test->test_priv;
+}
+
+#endif /* _EVT_TEST_ */
diff --git a/src/spdk/dpdk/app/test-eventdev/meson.build b/src/spdk/dpdk/app/test-eventdev/meson.build
new file mode 100644
index 000000000..9e588d9ec
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/meson.build
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Cavium, Inc
+
+sources = files('evt_main.c',
+ 'evt_options.c',
+ 'evt_test.c',
+ 'parser.c',
+ 'test_order_common.c',
+ 'test_order_atq.c',
+ 'test_order_queue.c',
+ 'test_perf_common.c',
+ 'test_perf_atq.c',
+ 'test_perf_queue.c',
+ 'test_pipeline_common.c',
+ 'test_pipeline_atq.c',
+ 'test_pipeline_queue.c')
+deps += 'eventdev'
diff --git a/src/spdk/dpdk/app/test-eventdev/parser.c b/src/spdk/dpdk/app/test-eventdev/parser.c
new file mode 100644
index 000000000..24f1855e9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/parser.c
@@ -0,0 +1,359 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Intel Corporation.
+ * Copyright(c) 2017 Cavium, Inc.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <libgen.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdbool.h>
+
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+
+#include "parser.h"
+
+static uint32_t
+get_hex_val(char c)
+{
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ return c - '0';
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return c - 'A' + 10;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ return c - 'a' + 10;
+ default:
+ return 0;
+ }
+}
+
+int
+parser_read_arg_bool(const char *p)
+{
+ p = skip_white_spaces(p);
+ int result = -EINVAL;
+
+ if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
+ ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
+ p += 3;
+ result = 1;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'n')) ||
+ ((p[0] == 'O') && (p[1] == 'N'))) {
+ p += 2;
+ result = 1;
+ }
+
+ if (((p[0] == 'n') && (p[1] == 'o')) ||
+ ((p[0] == 'N') && (p[1] == 'O'))) {
+ p += 2;
+ result = 0;
+ }
+
+ if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
+ ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
+ p += 3;
+ result = 0;
+ }
+
+ p = skip_white_spaces(p);
+
+ if (p[0] != '\0')
+ return -EINVAL;
+
+ return result;
+}
+
+int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtoul(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ p = next;
+ switch (*p) {
+ case 'T':
+ val *= 1024ULL;
+ /* fall through */
+ case 'G':
+ val *= 1024ULL;
+ /* fall through */
+ case 'M':
+ val *= 1024ULL;
+ /* fall through */
+ case 'k':
+ case 'K':
+ val *= 1024ULL;
+ p++;
+ break;
+ }
+
+ p = skip_white_spaces(p);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_int32(int32_t *value, const char *p)
+{
+ char *next;
+ int32_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtol(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+
+ val = strtoul(p, &next, 16);
+ if (p == next)
+ return -EINVAL;
+
+ p = skip_white_spaces(next);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint32_hex(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint16_hex(uint16_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT16_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = parser_read_uint64_hex(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT8_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+ uint32_t i;
+
+ if ((string == NULL) ||
+ (tokens == NULL) ||
+ (*n_tokens < 1))
+ return -EINVAL;
+
+ for (i = 0; i < *n_tokens; i++) {
+ tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+ if (tokens[i] == NULL)
+ break;
+ }
+
+ if ((i == *n_tokens) &&
+ (strtok_r(string, PARSE_DELIMITER, &string) != NULL))
+ return -E2BIG;
+
+ *n_tokens = i;
+ return 0;
+}
+
+int
+parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
+{
+ char *c;
+ uint32_t len, i;
+
+ /* Check input parameters */
+ if ((src == NULL) ||
+ (dst == NULL) ||
+ (size == NULL) ||
+ (*size == 0))
+ return -1;
+
+ len = strlen(src);
+ if (((len & 3) != 0) ||
+ (len > (*size) * 2))
+ return -1;
+ *size = len / 2;
+
+ for (c = src; *c != 0; c++) {
+ if ((((*c) >= '0') && ((*c) <= '9')) ||
+ (((*c) >= 'A') && ((*c) <= 'F')) ||
+ (((*c) >= 'a') && ((*c) <= 'f')))
+ continue;
+
+ return -1;
+ }
+
+ /* Convert chars to bytes */
+ for (i = 0; i < *size; i++)
+ dst[i] = get_hex_val(src[2 * i]) * 16 +
+ get_hex_val(src[2 * i + 1]);
+
+ return 0;
+}
+
+int
+parse_lcores_list(bool lcores[], const char *corelist)
+{
+ int i, idx = 0;
+ int min, max;
+ char *end = NULL;
+
+ if (corelist == NULL)
+ return -1;
+ while (isblank(*corelist))
+ corelist++;
+ i = strlen(corelist);
+ while ((i > 0) && isblank(corelist[i - 1]))
+ i--;
+
+ /* Get list of lcores */
+ min = RTE_MAX_LCORE;
+ do {
+ while (isblank(*corelist))
+ corelist++;
+ if (*corelist == '\0')
+ return -1;
+ idx = strtoul(corelist, &end, 10);
+
+ if (end == NULL)
+ return -1;
+ while (isblank(*end))
+ end++;
+ if (*end == '-') {
+ min = idx;
+ } else if ((*end == ',') || (*end == '\0')) {
+ max = idx;
+ if (min == RTE_MAX_LCORE)
+ min = idx;
+ for (idx = min; idx <= max; idx++) {
+ if (lcores[idx] == 1)
+ return -E2BIG;
+ lcores[idx] = 1;
+ }
+
+ min = RTE_MAX_LCORE;
+ } else
+ return -1;
+ corelist = end + 1;
+ } while (*end != '\0');
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/parser.h b/src/spdk/dpdk/app/test-eventdev/parser.h
new file mode 100644
index 000000000..673ff22d7
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/parser.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#ifndef __INCLUDE_PARSER_H__
+#define __INCLUDE_PARSER_H__
+
+#include <stdint.h>
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+#define skip_white_spaces(pos) \
+({ \
+ __typeof__(pos) _p = (pos); \
+ for ( ; isspace(*_p); _p++) \
+ ; \
+ _p; \
+})
+
+static inline size_t
+skip_digits(const char *src)
+{
+ size_t i;
+
+ for (i = 0; isdigit(src[i]); i++)
+ ;
+
+ return i;
+}
+
+int parser_read_arg_bool(const char *p);
+
+int parser_read_uint64(uint64_t *value, const char *p);
+int parser_read_uint32(uint32_t *value, const char *p);
+int parser_read_uint16(uint16_t *value, const char *p);
+int parser_read_uint8(uint8_t *value, const char *p);
+
+int parser_read_uint64_hex(uint64_t *value, const char *p);
+int parser_read_uint32_hex(uint32_t *value, const char *p);
+int parser_read_uint16_hex(uint16_t *value, const char *p);
+int parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int parser_read_int32(int32_t *value, const char *p);
+
+int parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
+
+int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens);
+
+int parse_lcores_list(bool lcores[], const char *corelist);
+#endif
diff --git a/src/spdk/dpdk/app/test-eventdev/test_order_atq.c b/src/spdk/dpdk/app/test-eventdev/test_order_atq.c
new file mode 100644
index 000000000..3366cfce9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_order_atq.c
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "test_order_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static __rte_always_inline void
+order_atq_process_stage_0(struct rte_event *const ev)
+{
+ ev->sub_event_type = 1; /* move to stage 1 (atomic) on the same queue */
+ ev->op = RTE_EVENT_OP_FORWARD;
+ ev->sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev->event_type = RTE_EVENT_TYPE_CPU;
+}
+
+static int
+order_atq_worker(void *arg)
+{
+ ORDER_WORKER_INIT;
+ struct rte_event ev;
+
+ while (t->err == false) {
+ uint16_t event = rte_event_dequeue_burst(dev_id, port,
+ &ev, 1, 0);
+ if (!event) {
+ if (rte_atomic64_read(outstand_pkts) <= 0)
+ break;
+ rte_pause();
+ continue;
+ }
+
+ if (ev.sub_event_type == 0) { /* stage 0 from producer */
+ order_atq_process_stage_0(&ev);
+ while (rte_event_enqueue_burst(dev_id, port, &ev, 1)
+ != 1)
+ rte_pause();
+ } else if (ev.sub_event_type == 1) { /* stage 1 */
+ order_process_stage_1(t, &ev, nb_flows,
+ expected_flow_seq, outstand_pkts);
+ } else {
+ order_process_stage_invalid(t, &ev);
+ }
+ }
+ return 0;
+}
+
+static int
+order_atq_worker_burst(void *arg)
+{
+ ORDER_WORKER_INIT;
+ struct rte_event ev[BURST_SIZE];
+ uint16_t i;
+
+ while (t->err == false) {
+ uint16_t const nb_rx = rte_event_dequeue_burst(dev_id, port, ev,
+ BURST_SIZE, 0);
+
+ if (nb_rx == 0) {
+ if (rte_atomic64_read(outstand_pkts) <= 0)
+ break;
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ if (ev[i].sub_event_type == 0) { /*stage 0 */
+ order_atq_process_stage_0(&ev[i]);
+ } else if (ev[i].sub_event_type == 1) { /* stage 1 */
+ order_process_stage_1(t, &ev[i], nb_flows,
+ expected_flow_seq, outstand_pkts);
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ } else {
+ order_process_stage_invalid(t, &ev[i]);
+ }
+ }
+
+ uint16_t enq;
+
+ enq = rte_event_enqueue_burst(dev_id, port, ev, nb_rx);
+ while (enq < nb_rx) {
+ enq += rte_event_enqueue_burst(dev_id, port,
+ ev + enq, nb_rx - enq);
+ }
+ }
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ const bool burst = evt_has_burst_mode(w->dev_id);
+
+ if (burst)
+ return order_atq_worker_burst(arg);
+ else
+ return order_atq_worker(arg);
+}
+
+static int
+order_atq_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return order_launch_lcores(test, opt, worker_wrapper);
+}
+
+#define NB_QUEUES 1
+static int
+order_atq_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ int ret;
+
+ const uint8_t nb_workers = evt_nr_active_lcores(opt->wlcores);
+ /* number of active worker cores + 1 producer */
+ const uint8_t nb_ports = nb_workers + 1;
+
+ ret = evt_configure_eventdev(opt, NB_QUEUES, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ /* q0 all types queue configuration */
+ struct rte_event_queue_conf q0_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .event_queue_cfg = RTE_EVENT_QUEUE_CFG_ALL_TYPES,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ ret = rte_event_queue_setup(opt->dev_id, 0, &q0_conf);
+ if (ret) {
+ evt_err("failed to setup queue0 eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ /* setup one port per worker, linking to all queues */
+ ret = order_event_dev_port_setup(test, opt, nb_workers, NB_QUEUES);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void
+order_atq_opt_dump(struct evt_options *opt)
+{
+ order_opt_dump(opt);
+ evt_dump("nb_evdev_queues", "%d", NB_QUEUES);
+}
+
+static bool
+order_atq_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < NB_QUEUES || dev_info.max_event_ports <
+ order_nb_event_ports(opt)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ NB_QUEUES, dev_info.max_event_queues,
+ order_nb_event_ports(opt), dev_info.max_event_ports);
+ return false;
+ }
+
+ if (!evt_has_all_types_queue(opt->dev_id))
+ return false;
+
+ return true;
+}
+
+static const struct evt_test_ops order_atq = {
+ .cap_check = order_atq_capability_check,
+ .opt_check = order_opt_check,
+ .opt_dump = order_atq_opt_dump,
+ .test_setup = order_test_setup,
+ .mempool_setup = order_mempool_setup,
+ .eventdev_setup = order_atq_eventdev_setup,
+ .launch_lcores = order_atq_launch_lcores,
+ .eventdev_destroy = order_eventdev_destroy,
+ .mempool_destroy = order_mempool_destroy,
+ .test_result = order_test_result,
+ .test_destroy = order_test_destroy,
+};
+
+EVT_TEST_REGISTER(order_atq);
diff --git a/src/spdk/dpdk/app/test-eventdev/test_order_common.c b/src/spdk/dpdk/app/test-eventdev/test_order_common.c
new file mode 100644
index 000000000..4190f9ade
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_order_common.c
@@ -0,0 +1,361 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test_order_common.h"
+
+int
+order_test_result(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ struct test_order *t = evt_test_priv(test);
+
+ return t->result;
+}
+
+static inline int
+order_producer(void *arg)
+{
+ struct prod_data *p = arg;
+ struct test_order *t = p->t;
+ struct evt_options *opt = t->opt;
+ const uint8_t dev_id = p->dev_id;
+ const uint8_t port = p->port_id;
+ struct rte_mempool *pool = t->pool;
+ const uint64_t nb_pkts = t->nb_pkts;
+ uint32_t *producer_flow_seq = t->producer_flow_seq;
+ const uint32_t nb_flows = t->nb_flows;
+ uint64_t count = 0;
+ struct rte_mbuf *m;
+ struct rte_event ev;
+
+ if (opt->verbose_level > 1)
+ printf("%s(): lcore %d dev_id %d port=%d queue=%d\n",
+ __func__, rte_lcore_id(), dev_id, port, p->queue_id);
+
+ ev.event = 0;
+ ev.op = RTE_EVENT_OP_NEW;
+ ev.queue_id = p->queue_id;
+ ev.sched_type = RTE_SCHED_TYPE_ORDERED;
+ ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ ev.event_type = RTE_EVENT_TYPE_CPU;
+ ev.sub_event_type = 0; /* stage 0 */
+
+ while (count < nb_pkts && t->err == false) {
+ m = rte_pktmbuf_alloc(pool);
+ if (m == NULL)
+ continue;
+
+ const uint32_t flow = (uintptr_t)m % nb_flows;
+ /* Maintain seq number per flow */
+ m->seqn = producer_flow_seq[flow]++;
+
+ ev.flow_id = flow;
+ ev.mbuf = m;
+
+ while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) {
+ if (t->err)
+ break;
+ rte_pause();
+ }
+
+ count++;
+ }
+ return 0;
+}
+
+int
+order_opt_check(struct evt_options *opt)
+{
+ if (opt->prod_type != EVT_PROD_TYPE_SYNT) {
+ evt_err("Invalid producer type '%s' valid producer '%s'",
+ evt_prod_id_to_name(opt->prod_type),
+ evt_prod_id_to_name(EVT_PROD_TYPE_SYNT));
+ return -1;
+ }
+
+ /* 1 producer + N workers + 1 master */
+ if (rte_lcore_count() < 3) {
+ evt_err("test need minimum 3 lcores");
+ return -1;
+ }
+
+ /* Validate worker lcores */
+ if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
+ evt_err("worker lcores overlaps with master lcore");
+ return -1;
+ }
+
+ if (evt_nr_active_lcores(opt->plcores) == 0) {
+ evt_err("missing the producer lcore");
+ return -1;
+ }
+
+ if (evt_nr_active_lcores(opt->plcores) != 1) {
+ evt_err("only one producer lcore must be selected");
+ return -1;
+ }
+
+ int plcore = evt_get_first_active_lcore(opt->plcores);
+
+ if (plcore < 0) {
+ evt_err("failed to find active producer");
+ return plcore;
+ }
+
+ if (evt_lcores_has_overlap(opt->wlcores, plcore)) {
+ evt_err("worker lcores overlaps producer lcore");
+ return -1;
+ }
+ if (evt_has_disabled_lcore(opt->wlcores)) {
+ evt_err("one or more workers lcores are not enabled");
+ return -1;
+ }
+ if (!evt_has_active_lcore(opt->wlcores)) {
+ evt_err("minimum one worker is required");
+ return -1;
+ }
+
+ /* Validate producer lcore */
+ if (plcore == (int)rte_get_master_lcore()) {
+ evt_err("producer lcore and master lcore should be different");
+ return -1;
+ }
+ if (!rte_lcore_is_enabled(plcore)) {
+ evt_err("producer lcore is not enabled");
+ return -1;
+ }
+
+ /* Fixups */
+ if (opt->nb_pkts == 0)
+ opt->nb_pkts = INT64_MAX;
+
+ return 0;
+}
+
+int
+order_test_setup(struct evt_test *test, struct evt_options *opt)
+{
+ void *test_order;
+
+ test_order = rte_zmalloc_socket(test->name, sizeof(struct test_order),
+ RTE_CACHE_LINE_SIZE, opt->socket_id);
+ if (test_order == NULL) {
+ evt_err("failed to allocate test_order memory");
+ goto nomem;
+ }
+ test->test_priv = test_order;
+
+ struct test_order *t = evt_test_priv(test);
+
+ t->producer_flow_seq = rte_zmalloc_socket("test_producer_flow_seq",
+ sizeof(*t->producer_flow_seq) * opt->nb_flows,
+ RTE_CACHE_LINE_SIZE, opt->socket_id);
+
+ if (t->producer_flow_seq == NULL) {
+ evt_err("failed to allocate t->producer_flow_seq memory");
+ goto prod_nomem;
+ }
+
+ t->expected_flow_seq = rte_zmalloc_socket("test_expected_flow_seq",
+ sizeof(*t->expected_flow_seq) * opt->nb_flows,
+ RTE_CACHE_LINE_SIZE, opt->socket_id);
+
+ if (t->expected_flow_seq == NULL) {
+ evt_err("failed to allocate t->expected_flow_seq memory");
+ goto exp_nomem;
+ }
+ rte_atomic64_set(&t->outstand_pkts, opt->nb_pkts);
+ t->err = false;
+ t->nb_pkts = opt->nb_pkts;
+ t->nb_flows = opt->nb_flows;
+ t->result = EVT_TEST_FAILED;
+ t->opt = opt;
+ return 0;
+
+exp_nomem:
+ rte_free(t->producer_flow_seq);
+prod_nomem:
+ rte_free(test->test_priv);
+nomem:
+ return -ENOMEM;
+}
+
+void
+order_test_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ struct test_order *t = evt_test_priv(test);
+
+ rte_free(t->expected_flow_seq);
+ rte_free(t->producer_flow_seq);
+ rte_free(test->test_priv);
+}
+
+int
+order_mempool_setup(struct evt_test *test, struct evt_options *opt)
+{
+ struct test_order *t = evt_test_priv(test);
+
+ t->pool = rte_pktmbuf_pool_create(test->name, opt->pool_sz,
+ 256 /* Cache */, 0,
+ 512, /* Use very small mbufs */
+ opt->socket_id);
+ if (t->pool == NULL) {
+ evt_err("failed to create mempool");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void
+order_mempool_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ struct test_order *t = evt_test_priv(test);
+
+ rte_mempool_free(t->pool);
+}
+
+void
+order_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(test);
+
+ rte_event_dev_stop(opt->dev_id);
+ rte_event_dev_close(opt->dev_id);
+}
+
+void
+order_opt_dump(struct evt_options *opt)
+{
+ evt_dump_producer_lcores(opt);
+ evt_dump("nb_wrker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
+ evt_dump_worker_lcores(opt);
+ evt_dump("nb_evdev_ports", "%d", order_nb_event_ports(opt));
+}
+
+int
+order_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *))
+{
+ int ret, lcore_id;
+ struct test_order *t = evt_test_priv(test);
+
+ int wkr_idx = 0;
+ /* launch workers */
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (!(opt->wlcores[lcore_id]))
+ continue;
+
+ ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx],
+ lcore_id);
+ if (ret) {
+ evt_err("failed to launch worker %d", lcore_id);
+ return ret;
+ }
+ wkr_idx++;
+ }
+
+ /* launch producer */
+ int plcore = evt_get_first_active_lcore(opt->plcores);
+
+ ret = rte_eal_remote_launch(order_producer, &t->prod, plcore);
+ if (ret) {
+ evt_err("failed to launch order_producer %d", plcore);
+ return ret;
+ }
+
+ uint64_t cycles = rte_get_timer_cycles();
+ int64_t old_remaining = -1;
+
+ while (t->err == false) {
+ uint64_t new_cycles = rte_get_timer_cycles();
+ int64_t remaining = rte_atomic64_read(&t->outstand_pkts);
+
+ if (remaining <= 0) {
+ t->result = EVT_TEST_SUCCESS;
+ break;
+ }
+
+ if (new_cycles - cycles > rte_get_timer_hz() * 1) {
+ printf(CLGRN"\r%"PRId64""CLNRM, remaining);
+ fflush(stdout);
+ if (old_remaining == remaining) {
+ rte_event_dev_dump(opt->dev_id, stdout);
+ evt_err("No schedules for seconds, deadlock");
+ t->err = true;
+ rte_smp_wmb();
+ break;
+ }
+ old_remaining = remaining;
+ cycles = new_cycles;
+ }
+ }
+ printf("\r");
+
+ return 0;
+}
+
+int
+order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t nb_workers, uint8_t nb_queues)
+{
+ int ret;
+ uint8_t port;
+ struct test_order *t = evt_test_priv(test);
+ struct rte_event_dev_info dev_info;
+
+ memset(&dev_info, 0, sizeof(struct rte_event_dev_info));
+ ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (ret) {
+ evt_err("failed to get eventdev info %d", opt->dev_id);
+ return ret;
+ }
+
+ if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
+ opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
+
+ /* port configuration */
+ const struct rte_event_port_conf p_conf = {
+ .dequeue_depth = opt->wkr_deq_dep,
+ .enqueue_depth = dev_info.max_event_port_dequeue_depth,
+ .new_event_threshold = dev_info.max_num_events,
+ };
+
+ /* setup one port per worker, linking to all queues */
+ for (port = 0; port < nb_workers; port++) {
+ struct worker_data *w = &t->worker[port];
+
+ w->dev_id = opt->dev_id;
+ w->port_id = port;
+ w->t = t;
+
+ ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
+ if (ret) {
+ evt_err("failed to setup port %d", port);
+ return ret;
+ }
+
+ ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
+ if (ret != nb_queues) {
+ evt_err("failed to link all queues to port %d", port);
+ return -EINVAL;
+ }
+ }
+ struct prod_data *p = &t->prod;
+
+ p->dev_id = opt->dev_id;
+ p->port_id = port; /* last port */
+ p->queue_id = 0;
+ p->t = t;
+
+ ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
+ if (ret) {
+ evt_err("failed to setup producer port %d", port);
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/test_order_common.h b/src/spdk/dpdk/app/test-eventdev/test_order_common.h
new file mode 100644
index 000000000..e0fe9c968
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_order_common.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _TEST_ORDER_COMMON_
+#define _TEST_ORDER_COMMON_
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#include <rte_cycles.h>
+#include <rte_eventdev.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+
+#include "evt_common.h"
+#include "evt_options.h"
+#include "evt_test.h"
+
+#define BURST_SIZE 16
+
+struct test_order;
+
+struct worker_data {
+ uint8_t dev_id;
+ uint8_t port_id;
+ struct test_order *t;
+};
+
+struct prod_data {
+ uint8_t dev_id;
+ uint8_t port_id;
+ uint8_t queue_id;
+ struct test_order *t;
+};
+
+struct test_order {
+ /* Don't change the offset of "err". Signal handler use this memory
+ * to terminate all lcores work.
+ */
+ int err;
+ /*
+ * The atomic_* is an expensive operation,Since it is a functional test,
+ * We are using the atomic_ operation to reduce the code complexity.
+ */
+ rte_atomic64_t outstand_pkts;
+ enum evt_test_result result;
+ uint32_t nb_flows;
+ uint64_t nb_pkts;
+ struct rte_mempool *pool;
+ struct prod_data prod;
+ struct worker_data worker[EVT_MAX_PORTS];
+ uint32_t *producer_flow_seq;
+ uint32_t *expected_flow_seq;
+ struct evt_options *opt;
+} __rte_cache_aligned;
+
+static inline int
+order_nb_event_ports(struct evt_options *opt)
+{
+ return evt_nr_active_lcores(opt->wlcores) + 1 /* producer */;
+}
+
+static __rte_always_inline void
+order_process_stage_1(struct test_order *const t,
+ struct rte_event *const ev, const uint32_t nb_flows,
+ uint32_t *const expected_flow_seq,
+ rte_atomic64_t *const outstand_pkts)
+{
+ const uint32_t flow = (uintptr_t)ev->mbuf % nb_flows;
+ /* compare the seqn against expected value */
+ if (ev->mbuf->seqn != expected_flow_seq[flow]) {
+ evt_err("flow=%x seqn mismatch got=%x expected=%x",
+ flow, ev->mbuf->seqn, expected_flow_seq[flow]);
+ t->err = true;
+ rte_smp_wmb();
+ }
+ /*
+ * Events from an atomic flow of an event queue can be scheduled only to
+ * a single port at a time. The port is guaranteed to have exclusive
+ * (atomic) access for given atomic flow.So we don't need to update
+ * expected_flow_seq in critical section.
+ */
+ expected_flow_seq[flow]++;
+ rte_pktmbuf_free(ev->mbuf);
+ rte_atomic64_sub(outstand_pkts, 1);
+}
+
+static __rte_always_inline void
+order_process_stage_invalid(struct test_order *const t,
+ struct rte_event *const ev)
+{
+ evt_err("invalid queue %d", ev->queue_id);
+ t->err = true;
+ rte_smp_wmb();
+}
+
+#define ORDER_WORKER_INIT\
+ struct worker_data *w = arg;\
+ struct test_order *t = w->t;\
+ struct evt_options *opt = t->opt;\
+ const uint8_t dev_id = w->dev_id;\
+ const uint8_t port = w->port_id;\
+ const uint32_t nb_flows = t->nb_flows;\
+ uint32_t *expected_flow_seq = t->expected_flow_seq;\
+ rte_atomic64_t *outstand_pkts = &t->outstand_pkts;\
+ if (opt->verbose_level > 1)\
+ printf("%s(): lcore %d dev_id %d port=%d\n",\
+ __func__, rte_lcore_id(), dev_id, port)
+
+int order_test_result(struct evt_test *test, struct evt_options *opt);
+int order_opt_check(struct evt_options *opt);
+int order_test_setup(struct evt_test *test, struct evt_options *opt);
+int order_mempool_setup(struct evt_test *test, struct evt_options *opt);
+int order_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *));
+int order_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t nb_workers, uint8_t nb_queues);
+void order_test_destroy(struct evt_test *test, struct evt_options *opt);
+void order_opt_dump(struct evt_options *opt);
+void order_mempool_destroy(struct evt_test *test, struct evt_options *opt);
+void order_eventdev_destroy(struct evt_test *test, struct evt_options *opt);
+
+#endif /* _TEST_ORDER_COMMON_ */
diff --git a/src/spdk/dpdk/app/test-eventdev/test_order_queue.c b/src/spdk/dpdk/app/test-eventdev/test_order_queue.c
new file mode 100644
index 000000000..495efd92f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_order_queue.c
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "test_order_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static __rte_always_inline void
+order_queue_process_stage_0(struct rte_event *const ev)
+{
+ ev->queue_id = 1; /* q1 atomic queue */
+ ev->op = RTE_EVENT_OP_FORWARD;
+ ev->sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev->event_type = RTE_EVENT_TYPE_CPU;
+}
+
+static int
+order_queue_worker(void *arg)
+{
+ ORDER_WORKER_INIT;
+ struct rte_event ev;
+
+ while (t->err == false) {
+ uint16_t event = rte_event_dequeue_burst(dev_id, port,
+ &ev, 1, 0);
+ if (!event) {
+ if (rte_atomic64_read(outstand_pkts) <= 0)
+ break;
+ rte_pause();
+ continue;
+ }
+
+ if (ev.queue_id == 0) { /* from ordered queue */
+ order_queue_process_stage_0(&ev);
+ while (rte_event_enqueue_burst(dev_id, port, &ev, 1)
+ != 1)
+ rte_pause();
+ } else if (ev.queue_id == 1) { /* from atomic queue */
+ order_process_stage_1(t, &ev, nb_flows,
+ expected_flow_seq, outstand_pkts);
+ } else {
+ order_process_stage_invalid(t, &ev);
+ }
+ }
+ return 0;
+}
+
+static int
+order_queue_worker_burst(void *arg)
+{
+ ORDER_WORKER_INIT;
+ struct rte_event ev[BURST_SIZE];
+ uint16_t i;
+
+ while (t->err == false) {
+ uint16_t const nb_rx = rte_event_dequeue_burst(dev_id, port, ev,
+ BURST_SIZE, 0);
+
+ if (nb_rx == 0) {
+ if (rte_atomic64_read(outstand_pkts) <= 0)
+ break;
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ if (ev[i].queue_id == 0) { /* from ordered queue */
+ order_queue_process_stage_0(&ev[i]);
+ } else if (ev[i].queue_id == 1) {/* from atomic queue */
+ order_process_stage_1(t, &ev[i], nb_flows,
+ expected_flow_seq, outstand_pkts);
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ } else {
+ order_process_stage_invalid(t, &ev[i]);
+ }
+ }
+
+ uint16_t enq;
+
+ enq = rte_event_enqueue_burst(dev_id, port, ev, nb_rx);
+ while (enq < nb_rx) {
+ enq += rte_event_enqueue_burst(dev_id, port,
+ ev + enq, nb_rx - enq);
+ }
+ }
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ const bool burst = evt_has_burst_mode(w->dev_id);
+
+ if (burst)
+ return order_queue_worker_burst(arg);
+ else
+ return order_queue_worker(arg);
+}
+
+static int
+order_queue_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return order_launch_lcores(test, opt, worker_wrapper);
+}
+
+#define NB_QUEUES 2
+static int
+order_queue_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ int ret;
+
+ const uint8_t nb_workers = evt_nr_active_lcores(opt->wlcores);
+ /* number of active worker cores + 1 producer */
+ const uint8_t nb_ports = nb_workers + 1;
+
+ ret = evt_configure_eventdev(opt, NB_QUEUES, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ /* q0 (ordered queue) configuration */
+ struct rte_event_queue_conf q0_ordered_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .schedule_type = RTE_SCHED_TYPE_ORDERED,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ ret = rte_event_queue_setup(opt->dev_id, 0, &q0_ordered_conf);
+ if (ret) {
+ evt_err("failed to setup queue0 eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ /* q1 (atomic queue) configuration */
+ struct rte_event_queue_conf q1_atomic_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .schedule_type = RTE_SCHED_TYPE_ATOMIC,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ ret = rte_event_queue_setup(opt->dev_id, 1, &q1_atomic_conf);
+ if (ret) {
+ evt_err("failed to setup queue1 eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ /* setup one port per worker, linking to all queues */
+ ret = order_event_dev_port_setup(test, opt, nb_workers, NB_QUEUES);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void
+order_queue_opt_dump(struct evt_options *opt)
+{
+ order_opt_dump(opt);
+ evt_dump("nb_evdev_queues", "%d", NB_QUEUES);
+}
+
+static bool
+order_queue_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < NB_QUEUES || dev_info.max_event_ports <
+ order_nb_event_ports(opt)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ NB_QUEUES, dev_info.max_event_queues,
+ order_nb_event_ports(opt), dev_info.max_event_ports);
+ return false;
+ }
+
+ return true;
+}
+
+static const struct evt_test_ops order_queue = {
+ .cap_check = order_queue_capability_check,
+ .opt_check = order_opt_check,
+ .opt_dump = order_queue_opt_dump,
+ .test_setup = order_test_setup,
+ .mempool_setup = order_mempool_setup,
+ .eventdev_setup = order_queue_eventdev_setup,
+ .launch_lcores = order_queue_launch_lcores,
+ .eventdev_destroy = order_eventdev_destroy,
+ .mempool_destroy = order_mempool_destroy,
+ .test_result = order_test_result,
+ .test_destroy = order_test_destroy,
+};
+
+EVT_TEST_REGISTER(order_queue);
diff --git a/src/spdk/dpdk/app/test-eventdev/test_perf_atq.c b/src/spdk/dpdk/app/test-eventdev/test_perf_atq.c
new file mode 100644
index 000000000..8fd51004e
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_perf_atq.c
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test_perf_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static inline int
+atq_nb_event_queues(struct evt_options *opt)
+{
+ /* nb_queues = number of producers */
+ return opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ?
+ rte_eth_dev_count_avail() : evt_nr_active_lcores(opt->plcores);
+}
+
+static __rte_always_inline void
+atq_mark_fwd_latency(struct rte_event *const ev)
+{
+ if (unlikely(ev->sub_event_type == 0)) {
+ struct perf_elt *const m = ev->event_ptr;
+
+ m->timestamp = rte_get_timer_cycles();
+ }
+}
+
+static __rte_always_inline void
+atq_fwd_event(struct rte_event *const ev, uint8_t *const sched_type_list,
+ const uint8_t nb_stages)
+{
+ ev->sub_event_type++;
+ ev->sched_type = sched_type_list[ev->sub_event_type % nb_stages];
+ ev->op = RTE_EVENT_OP_FORWARD;
+ ev->event_type = RTE_EVENT_TYPE_CPU;
+}
+
+static int
+perf_atq_worker(void *arg, const int enable_fwd_latency)
+{
+ PERF_WORKER_INIT;
+ struct rte_event ev;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ if (enable_fwd_latency && !prod_timer_type)
+ /* first stage in pipeline, mark ts to compute fwd latency */
+ atq_mark_fwd_latency(&ev);
+
+ /* last stage in pipeline */
+ if (unlikely((ev.sub_event_type % nb_stages) == laststage)) {
+ if (enable_fwd_latency)
+ cnt = perf_process_last_stage_latency(pool,
+ &ev, w, bufs, sz, cnt);
+ else
+ cnt = perf_process_last_stage(pool, &ev, w,
+ bufs, sz, cnt);
+ } else {
+ atq_fwd_event(&ev, sched_type_list, nb_stages);
+ while (rte_event_enqueue_burst(dev, port, &ev, 1) != 1)
+ rte_pause();
+ }
+ }
+ return 0;
+}
+
+static int
+perf_atq_worker_burst(void *arg, const int enable_fwd_latency)
+{
+ PERF_WORKER_INIT;
+ uint16_t i;
+ /* +1 to avoid prefetch out of array check */
+ struct rte_event ev[BURST_SIZE + 1];
+
+ while (t->done == false) {
+ uint16_t const nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ if (enable_fwd_latency && !prod_timer_type) {
+ rte_prefetch0(ev[i+1].event_ptr);
+ /* first stage in pipeline.
+ * mark time stamp to compute fwd latency
+ */
+ atq_mark_fwd_latency(&ev[i]);
+ }
+ /* last stage in pipeline */
+ if (unlikely((ev[i].sub_event_type % nb_stages)
+ == laststage)) {
+ if (enable_fwd_latency)
+ cnt = perf_process_last_stage_latency(
+ pool, &ev[i], w, bufs, sz, cnt);
+ else
+ cnt = perf_process_last_stage(pool,
+ &ev[i], w, bufs, sz, cnt);
+
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ } else {
+ atq_fwd_event(&ev[i], sched_type_list,
+ nb_stages);
+ }
+ }
+
+ uint16_t enq;
+
+ enq = rte_event_enqueue_burst(dev, port, ev, nb_rx);
+ while (enq < nb_rx) {
+ enq += rte_event_enqueue_burst(dev, port,
+ ev + enq, nb_rx - enq);
+ }
+ }
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ struct evt_options *opt = w->t->opt;
+
+ const bool burst = evt_has_burst_mode(w->dev_id);
+ const int fwd_latency = opt->fwd_latency;
+
+ /* allow compiler to optimize */
+ if (!burst && !fwd_latency)
+ return perf_atq_worker(arg, 0);
+ else if (!burst && fwd_latency)
+ return perf_atq_worker(arg, 1);
+ else if (burst && !fwd_latency)
+ return perf_atq_worker_burst(arg, 0);
+ else if (burst && fwd_latency)
+ return perf_atq_worker_burst(arg, 1);
+
+ rte_panic("invalid worker\n");
+}
+
+static int
+perf_atq_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return perf_launch_lcores(test, opt, worker_wrapper);
+}
+
+static int
+perf_atq_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ int ret;
+ uint8_t queue;
+ uint8_t nb_queues;
+ uint8_t nb_ports;
+ uint16_t prod;
+ struct rte_event_dev_info dev_info;
+ struct test_perf *t = evt_test_priv(test);
+
+ nb_ports = evt_nr_active_lcores(opt->wlcores);
+ nb_ports += (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) ? 0 :
+ evt_nr_active_lcores(opt->plcores);
+
+ nb_queues = atq_nb_event_queues(opt);
+
+ memset(&dev_info, 0, sizeof(struct rte_event_dev_info));
+ ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (ret) {
+ evt_err("failed to get eventdev info %d", opt->dev_id);
+ return ret;
+ }
+
+ ret = evt_configure_eventdev(opt, nb_queues, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ struct rte_event_queue_conf q_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .event_queue_cfg = RTE_EVENT_QUEUE_CFG_ALL_TYPES,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ /* queue configurations */
+ for (queue = 0; queue < nb_queues; queue++) {
+ ret = rte_event_queue_setup(opt->dev_id, queue, &q_conf);
+ if (ret) {
+ evt_err("failed to setup queue=%d", queue);
+ return ret;
+ }
+ }
+
+ if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
+ opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
+
+ /* port configuration */
+ const struct rte_event_port_conf p_conf = {
+ .dequeue_depth = opt->wkr_deq_dep,
+ .enqueue_depth = dev_info.max_event_port_dequeue_depth,
+ .new_event_threshold = dev_info.max_num_events,
+ };
+
+ ret = perf_event_dev_port_setup(test, opt, 1 /* stride */, nb_queues,
+ &p_conf);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_eth_dev_start(prod);
+ if (ret) {
+ evt_err("Ethernet dev [%d] failed to start. Using synthetic producer",
+ prod);
+ return ret;
+ }
+
+ ret = rte_event_eth_rx_adapter_start(prod);
+ if (ret) {
+ evt_err("Rx adapter[%d] start failed", prod);
+ return ret;
+ }
+ printf("%s: Port[%d] using Rx adapter[%d] started\n",
+ __func__, prod, prod);
+ }
+ } else if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ for (prod = 0; prod < opt->nb_timer_adptrs; prod++) {
+ ret = rte_event_timer_adapter_start(
+ t->timer_adptr[prod]);
+ if (ret) {
+ evt_err("failed to Start event timer adapter %d"
+ , prod);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void
+perf_atq_opt_dump(struct evt_options *opt)
+{
+ perf_opt_dump(opt, atq_nb_event_queues(opt));
+}
+
+static int
+perf_atq_opt_check(struct evt_options *opt)
+{
+ return perf_opt_check(opt, atq_nb_event_queues(opt));
+}
+
+static bool
+perf_atq_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < atq_nb_event_queues(opt) ||
+ dev_info.max_event_ports < perf_nb_event_ports(opt)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ atq_nb_event_queues(opt), dev_info.max_event_queues,
+ perf_nb_event_ports(opt), dev_info.max_event_ports);
+ }
+ if (!evt_has_all_types_queue(opt->dev_id))
+ return false;
+
+ return true;
+}
+
+static const struct evt_test_ops perf_atq = {
+ .cap_check = perf_atq_capability_check,
+ .opt_check = perf_atq_opt_check,
+ .opt_dump = perf_atq_opt_dump,
+ .test_setup = perf_test_setup,
+ .ethdev_setup = perf_ethdev_setup,
+ .mempool_setup = perf_mempool_setup,
+ .eventdev_setup = perf_atq_eventdev_setup,
+ .launch_lcores = perf_atq_launch_lcores,
+ .eventdev_destroy = perf_eventdev_destroy,
+ .mempool_destroy = perf_mempool_destroy,
+ .ethdev_destroy = perf_ethdev_destroy,
+ .test_result = perf_test_result,
+ .test_destroy = perf_test_destroy,
+};
+
+EVT_TEST_REGISTER(perf_atq);
diff --git a/src/spdk/dpdk/app/test-eventdev/test_perf_common.c b/src/spdk/dpdk/app/test-eventdev/test_perf_common.c
new file mode 100644
index 000000000..b3af4bfec
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_perf_common.c
@@ -0,0 +1,839 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test_perf_common.h"
+
+int
+perf_test_result(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ int i;
+ uint64_t total = 0;
+ struct test_perf *t = evt_test_priv(test);
+
+ printf("Packet distribution across worker cores :\n");
+ for (i = 0; i < t->nb_workers; i++)
+ total += t->worker[i].processed_pkts;
+ for (i = 0; i < t->nb_workers; i++)
+ printf("Worker %d packets: "CLGRN"%"PRIx64" "CLNRM"percentage:"
+ CLGRN" %3.2f\n"CLNRM, i,
+ t->worker[i].processed_pkts,
+ (((double)t->worker[i].processed_pkts)/total)
+ * 100);
+
+ return t->result;
+}
+
+static inline int
+perf_producer(void *arg)
+{
+ int i;
+ struct prod_data *p = arg;
+ struct test_perf *t = p->t;
+ struct evt_options *opt = t->opt;
+ const uint8_t dev_id = p->dev_id;
+ const uint8_t port = p->port_id;
+ struct rte_mempool *pool = t->pool;
+ const uint64_t nb_pkts = t->nb_pkts;
+ const uint32_t nb_flows = t->nb_flows;
+ uint32_t flow_counter = 0;
+ uint64_t count = 0;
+ struct perf_elt *m[BURST_SIZE + 1] = {NULL};
+ struct rte_event ev;
+
+ if (opt->verbose_level > 1)
+ printf("%s(): lcore %d dev_id %d port=%d queue %d\n", __func__,
+ rte_lcore_id(), dev_id, port, p->queue_id);
+
+ ev.event = 0;
+ ev.op = RTE_EVENT_OP_NEW;
+ ev.queue_id = p->queue_id;
+ ev.sched_type = t->opt->sched_type_list[0];
+ ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ ev.event_type = RTE_EVENT_TYPE_CPU;
+ ev.sub_event_type = 0; /* stage 0 */
+
+ while (count < nb_pkts && t->done == false) {
+ if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0)
+ continue;
+ for (i = 0; i < BURST_SIZE; i++) {
+ ev.flow_id = flow_counter++ % nb_flows;
+ ev.event_ptr = m[i];
+ m[i]->timestamp = rte_get_timer_cycles();
+ while (rte_event_enqueue_burst(dev_id,
+ port, &ev, 1) != 1) {
+ if (t->done)
+ break;
+ rte_pause();
+ m[i]->timestamp = rte_get_timer_cycles();
+ }
+ }
+ count += BURST_SIZE;
+ }
+
+ return 0;
+}
+
+static inline int
+perf_event_timer_producer(void *arg)
+{
+ int i;
+ struct prod_data *p = arg;
+ struct test_perf *t = p->t;
+ struct evt_options *opt = t->opt;
+ uint32_t flow_counter = 0;
+ uint64_t count = 0;
+ uint64_t arm_latency = 0;
+ const uint8_t nb_timer_adptrs = opt->nb_timer_adptrs;
+ const uint32_t nb_flows = t->nb_flows;
+ const uint64_t nb_timers = opt->nb_timers;
+ struct rte_mempool *pool = t->pool;
+ struct perf_elt *m[BURST_SIZE + 1] = {NULL};
+ struct rte_event_timer_adapter **adptr = t->timer_adptr;
+ struct rte_event_timer tim;
+ uint64_t timeout_ticks = opt->expiry_nsec / opt->timer_tick_nsec;
+
+ memset(&tim, 0, sizeof(struct rte_event_timer));
+ timeout_ticks = opt->optm_timer_tick_nsec ?
+ (timeout_ticks * opt->timer_tick_nsec)
+ / opt->optm_timer_tick_nsec : timeout_ticks;
+ timeout_ticks += timeout_ticks ? 0 : 1;
+ tim.ev.event_type = RTE_EVENT_TYPE_TIMER;
+ tim.ev.op = RTE_EVENT_OP_NEW;
+ tim.ev.sched_type = t->opt->sched_type_list[0];
+ tim.ev.queue_id = p->queue_id;
+ tim.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ tim.state = RTE_EVENT_TIMER_NOT_ARMED;
+ tim.timeout_ticks = timeout_ticks;
+
+ if (opt->verbose_level > 1)
+ printf("%s(): lcore %d\n", __func__, rte_lcore_id());
+
+ while (count < nb_timers && t->done == false) {
+ if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0)
+ continue;
+ for (i = 0; i < BURST_SIZE; i++) {
+ rte_prefetch0(m[i + 1]);
+ m[i]->tim = tim;
+ m[i]->tim.ev.flow_id = flow_counter++ % nb_flows;
+ m[i]->tim.ev.event_ptr = m[i];
+ m[i]->timestamp = rte_get_timer_cycles();
+ while (rte_event_timer_arm_burst(
+ adptr[flow_counter % nb_timer_adptrs],
+ (struct rte_event_timer **)&m[i], 1) != 1) {
+ if (t->done)
+ break;
+ m[i]->timestamp = rte_get_timer_cycles();
+ }
+ arm_latency += rte_get_timer_cycles() - m[i]->timestamp;
+ }
+ count += BURST_SIZE;
+ }
+ fflush(stdout);
+ rte_delay_ms(1000);
+ printf("%s(): lcore %d Average event timer arm latency = %.3f us\n",
+ __func__, rte_lcore_id(),
+ count ? (float)(arm_latency / count) /
+ (rte_get_timer_hz() / 1000000) : 0);
+ return 0;
+}
+
+static inline int
+perf_event_timer_producer_burst(void *arg)
+{
+ int i;
+ struct prod_data *p = arg;
+ struct test_perf *t = p->t;
+ struct evt_options *opt = t->opt;
+ uint32_t flow_counter = 0;
+ uint64_t count = 0;
+ uint64_t arm_latency = 0;
+ const uint8_t nb_timer_adptrs = opt->nb_timer_adptrs;
+ const uint32_t nb_flows = t->nb_flows;
+ const uint64_t nb_timers = opt->nb_timers;
+ struct rte_mempool *pool = t->pool;
+ struct perf_elt *m[BURST_SIZE + 1] = {NULL};
+ struct rte_event_timer_adapter **adptr = t->timer_adptr;
+ struct rte_event_timer tim;
+ uint64_t timeout_ticks = opt->expiry_nsec / opt->timer_tick_nsec;
+
+ memset(&tim, 0, sizeof(struct rte_event_timer));
+ timeout_ticks = opt->optm_timer_tick_nsec ?
+ (timeout_ticks * opt->timer_tick_nsec)
+ / opt->optm_timer_tick_nsec : timeout_ticks;
+ timeout_ticks += timeout_ticks ? 0 : 1;
+ tim.ev.event_type = RTE_EVENT_TYPE_TIMER;
+ tim.ev.op = RTE_EVENT_OP_NEW;
+ tim.ev.sched_type = t->opt->sched_type_list[0];
+ tim.ev.queue_id = p->queue_id;
+ tim.ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ tim.state = RTE_EVENT_TIMER_NOT_ARMED;
+ tim.timeout_ticks = timeout_ticks;
+
+ if (opt->verbose_level > 1)
+ printf("%s(): lcore %d\n", __func__, rte_lcore_id());
+
+ while (count < nb_timers && t->done == false) {
+ if (rte_mempool_get_bulk(pool, (void **)m, BURST_SIZE) < 0)
+ continue;
+ for (i = 0; i < BURST_SIZE; i++) {
+ rte_prefetch0(m[i + 1]);
+ m[i]->tim = tim;
+ m[i]->tim.ev.flow_id = flow_counter++ % nb_flows;
+ m[i]->tim.ev.event_ptr = m[i];
+ m[i]->timestamp = rte_get_timer_cycles();
+ }
+ rte_event_timer_arm_tmo_tick_burst(
+ adptr[flow_counter % nb_timer_adptrs],
+ (struct rte_event_timer **)m,
+ tim.timeout_ticks,
+ BURST_SIZE);
+ arm_latency += rte_get_timer_cycles() - m[i - 1]->timestamp;
+ count += BURST_SIZE;
+ }
+ fflush(stdout);
+ rte_delay_ms(1000);
+ printf("%s(): lcore %d Average event timer arm latency = %.3f us\n",
+ __func__, rte_lcore_id(),
+ count ? (float)(arm_latency / count) /
+ (rte_get_timer_hz() / 1000000) : 0);
+ return 0;
+}
+
+static int
+perf_producer_wrapper(void *arg)
+{
+ struct prod_data *p = arg;
+ struct test_perf *t = p->t;
+ /* Launch the producer function only in case of synthetic producer. */
+ if (t->opt->prod_type == EVT_PROD_TYPE_SYNT)
+ return perf_producer(arg);
+ else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR &&
+ !t->opt->timdev_use_burst)
+ return perf_event_timer_producer(arg);
+ else if (t->opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR &&
+ t->opt->timdev_use_burst)
+ return perf_event_timer_producer_burst(arg);
+ return 0;
+}
+
+static inline uint64_t
+processed_pkts(struct test_perf *t)
+{
+ uint8_t i;
+ uint64_t total = 0;
+
+ rte_smp_rmb();
+ for (i = 0; i < t->nb_workers; i++)
+ total += t->worker[i].processed_pkts;
+
+ return total;
+}
+
+static inline uint64_t
+total_latency(struct test_perf *t)
+{
+ uint8_t i;
+ uint64_t total = 0;
+
+ rte_smp_rmb();
+ for (i = 0; i < t->nb_workers; i++)
+ total += t->worker[i].latency;
+
+ return total;
+}
+
+
+int
+perf_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *))
+{
+ int ret, lcore_id;
+ struct test_perf *t = evt_test_priv(test);
+
+ int port_idx = 0;
+ /* launch workers */
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (!(opt->wlcores[lcore_id]))
+ continue;
+
+ ret = rte_eal_remote_launch(worker,
+ &t->worker[port_idx], lcore_id);
+ if (ret) {
+ evt_err("failed to launch worker %d", lcore_id);
+ return ret;
+ }
+ port_idx++;
+ }
+
+ /* launch producers */
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (!(opt->plcores[lcore_id]))
+ continue;
+
+ ret = rte_eal_remote_launch(perf_producer_wrapper,
+ &t->prod[port_idx], lcore_id);
+ if (ret) {
+ evt_err("failed to launch perf_producer %d", lcore_id);
+ return ret;
+ }
+ port_idx++;
+ }
+
+ const uint64_t total_pkts = t->outstand_pkts;
+
+ uint64_t dead_lock_cycles = rte_get_timer_cycles();
+ int64_t dead_lock_remaining = total_pkts;
+ const uint64_t dead_lock_sample = rte_get_timer_hz() * 5;
+
+ uint64_t perf_cycles = rte_get_timer_cycles();
+ int64_t perf_remaining = total_pkts;
+ const uint64_t perf_sample = rte_get_timer_hz();
+
+ static float total_mpps;
+ static uint64_t samples;
+
+ const uint64_t freq_mhz = rte_get_timer_hz() / 1000000;
+ int64_t remaining = t->outstand_pkts - processed_pkts(t);
+
+ while (t->done == false) {
+ const uint64_t new_cycles = rte_get_timer_cycles();
+
+ if ((new_cycles - perf_cycles) > perf_sample) {
+ const uint64_t latency = total_latency(t);
+ const uint64_t pkts = processed_pkts(t);
+
+ remaining = t->outstand_pkts - pkts;
+ float mpps = (float)(perf_remaining-remaining)/1000000;
+
+ perf_remaining = remaining;
+ perf_cycles = new_cycles;
+ total_mpps += mpps;
+ ++samples;
+ if (opt->fwd_latency && pkts > 0) {
+ printf(CLGRN"\r%.3f mpps avg %.3f mpps [avg fwd latency %.3f us] "CLNRM,
+ mpps, total_mpps/samples,
+ (float)(latency/pkts)/freq_mhz);
+ } else {
+ printf(CLGRN"\r%.3f mpps avg %.3f mpps"CLNRM,
+ mpps, total_mpps/samples);
+ }
+ fflush(stdout);
+
+ if (remaining <= 0) {
+ t->result = EVT_TEST_SUCCESS;
+ if (opt->prod_type == EVT_PROD_TYPE_SYNT ||
+ opt->prod_type ==
+ EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ t->done = true;
+ rte_smp_wmb();
+ break;
+ }
+ }
+ }
+
+ if (new_cycles - dead_lock_cycles > dead_lock_sample &&
+ (opt->prod_type == EVT_PROD_TYPE_SYNT ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR)) {
+ remaining = t->outstand_pkts - processed_pkts(t);
+ if (dead_lock_remaining == remaining) {
+ rte_event_dev_dump(opt->dev_id, stdout);
+ evt_err("No schedules for seconds, deadlock");
+ t->done = true;
+ rte_smp_wmb();
+ break;
+ }
+ dead_lock_remaining = remaining;
+ dead_lock_cycles = new_cycles;
+ }
+ }
+ printf("\n");
+ return 0;
+}
+
+static int
+perf_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride,
+ struct rte_event_port_conf prod_conf)
+{
+ int ret = 0;
+ uint16_t prod;
+ struct rte_event_eth_rx_adapter_queue_conf queue_conf;
+
+ memset(&queue_conf, 0,
+ sizeof(struct rte_event_eth_rx_adapter_queue_conf));
+ queue_conf.ev.sched_type = opt->sched_type_list[0];
+ RTE_ETH_FOREACH_DEV(prod) {
+ uint32_t cap;
+
+ ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id,
+ prod, &cap);
+ if (ret) {
+ evt_err("failed to get event rx adapter[%d]"
+ " capabilities",
+ opt->dev_id);
+ return ret;
+ }
+ queue_conf.ev.queue_id = prod * stride;
+ ret = rte_event_eth_rx_adapter_create(prod, opt->dev_id,
+ &prod_conf);
+ if (ret) {
+ evt_err("failed to create rx adapter[%d]", prod);
+ return ret;
+ }
+ ret = rte_event_eth_rx_adapter_queue_add(prod, prod, -1,
+ &queue_conf);
+ if (ret) {
+ evt_err("failed to add rx queues to adapter[%d]", prod);
+ return ret;
+ }
+
+ if (!(cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) {
+ uint32_t service_id;
+
+ rte_event_eth_rx_adapter_service_id_get(prod,
+ &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("Failed to setup service core"
+ " for Rx adapter\n");
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int
+perf_event_timer_adapter_setup(struct test_perf *t)
+{
+ int i;
+ int ret;
+ struct rte_event_timer_adapter_info adapter_info;
+ struct rte_event_timer_adapter *wl;
+ uint8_t nb_producers = evt_nr_active_lcores(t->opt->plcores);
+ uint8_t flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES;
+
+ if (nb_producers == 1)
+ flags |= RTE_EVENT_TIMER_ADAPTER_F_SP_PUT;
+
+ for (i = 0; i < t->opt->nb_timer_adptrs; i++) {
+ struct rte_event_timer_adapter_conf config = {
+ .event_dev_id = t->opt->dev_id,
+ .timer_adapter_id = i,
+ .timer_tick_ns = t->opt->timer_tick_nsec,
+ .max_tmo_ns = t->opt->max_tmo_nsec,
+ .nb_timers = t->opt->pool_sz,
+ .flags = flags,
+ };
+
+ wl = rte_event_timer_adapter_create(&config);
+ if (wl == NULL) {
+ evt_err("failed to create event timer ring %d", i);
+ return rte_errno;
+ }
+
+ memset(&adapter_info, 0,
+ sizeof(struct rte_event_timer_adapter_info));
+ rte_event_timer_adapter_get_info(wl, &adapter_info);
+ t->opt->optm_timer_tick_nsec = adapter_info.min_resolution_ns;
+
+ if (!(adapter_info.caps &
+ RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
+ uint32_t service_id = -1U;
+
+ rte_event_timer_adapter_service_id_get(wl,
+ &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("Failed to setup service core"
+ " for timer adapter\n");
+ return ret;
+ }
+ rte_service_runstate_set(service_id, 1);
+ }
+ t->timer_adptr[i] = wl;
+ }
+ return 0;
+}
+
+int
+perf_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t stride, uint8_t nb_queues,
+ const struct rte_event_port_conf *port_conf)
+{
+ struct test_perf *t = evt_test_priv(test);
+ uint16_t port, prod;
+ int ret = -1;
+
+ /* setup one port per worker, linking to all queues */
+ for (port = 0; port < evt_nr_active_lcores(opt->wlcores);
+ port++) {
+ struct worker_data *w = &t->worker[port];
+
+ w->dev_id = opt->dev_id;
+ w->port_id = port;
+ w->t = t;
+ w->processed_pkts = 0;
+ w->latency = 0;
+
+ ret = rte_event_port_setup(opt->dev_id, port, port_conf);
+ if (ret) {
+ evt_err("failed to setup port %d", port);
+ return ret;
+ }
+
+ ret = rte_event_port_link(opt->dev_id, port, NULL, NULL, 0);
+ if (ret != nb_queues) {
+ evt_err("failed to link all queues to port %d", port);
+ return -EINVAL;
+ }
+ }
+
+ /* port for producers, no links */
+ if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ for ( ; port < perf_nb_event_ports(opt); port++) {
+ struct prod_data *p = &t->prod[port];
+ p->t = t;
+ }
+
+ ret = perf_event_rx_adapter_setup(opt, stride, *port_conf);
+ if (ret)
+ return ret;
+ } else if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ prod = 0;
+ for ( ; port < perf_nb_event_ports(opt); port++) {
+ struct prod_data *p = &t->prod[port];
+ p->queue_id = prod * stride;
+ p->t = t;
+ prod++;
+ }
+
+ ret = perf_event_timer_adapter_setup(t);
+ if (ret)
+ return ret;
+ } else {
+ prod = 0;
+ for ( ; port < perf_nb_event_ports(opt); port++) {
+ struct prod_data *p = &t->prod[port];
+
+ p->dev_id = opt->dev_id;
+ p->port_id = port;
+ p->queue_id = prod * stride;
+ p->t = t;
+
+ ret = rte_event_port_setup(opt->dev_id, port,
+ port_conf);
+ if (ret) {
+ evt_err("failed to setup port %d", port);
+ return ret;
+ }
+ prod++;
+ }
+ }
+
+ return ret;
+}
+
+int
+perf_opt_check(struct evt_options *opt, uint64_t nb_queues)
+{
+ unsigned int lcores;
+
+ /* N producer + N worker + 1 master when producer cores are used
+ * Else N worker + 1 master when Rx adapter is used
+ */
+ lcores = opt->prod_type == EVT_PROD_TYPE_SYNT ? 3 : 2;
+
+ if (rte_lcore_count() < lcores) {
+ evt_err("test need minimum %d lcores", lcores);
+ return -1;
+ }
+
+ /* Validate worker lcores */
+ if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
+ evt_err("worker lcores overlaps with master lcore");
+ return -1;
+ }
+ if (evt_lcores_has_overlap_multi(opt->wlcores, opt->plcores)) {
+ evt_err("worker lcores overlaps producer lcores");
+ return -1;
+ }
+ if (evt_has_disabled_lcore(opt->wlcores)) {
+ evt_err("one or more workers lcores are not enabled");
+ return -1;
+ }
+ if (!evt_has_active_lcore(opt->wlcores)) {
+ evt_err("minimum one worker is required");
+ return -1;
+ }
+
+ if (opt->prod_type == EVT_PROD_TYPE_SYNT ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ /* Validate producer lcores */
+ if (evt_lcores_has_overlap(opt->plcores,
+ rte_get_master_lcore())) {
+ evt_err("producer lcores overlaps with master lcore");
+ return -1;
+ }
+ if (evt_has_disabled_lcore(opt->plcores)) {
+ evt_err("one or more producer lcores are not enabled");
+ return -1;
+ }
+ if (!evt_has_active_lcore(opt->plcores)) {
+ evt_err("minimum one producer is required");
+ return -1;
+ }
+ }
+
+ if (evt_has_invalid_stage(opt))
+ return -1;
+
+ if (evt_has_invalid_sched_type(opt))
+ return -1;
+
+ if (nb_queues > EVT_MAX_QUEUES) {
+ evt_err("number of queues exceeds %d", EVT_MAX_QUEUES);
+ return -1;
+ }
+ if (perf_nb_event_ports(opt) > EVT_MAX_PORTS) {
+ evt_err("number of ports exceeds %d", EVT_MAX_PORTS);
+ return -1;
+ }
+
+ /* Fixups */
+ if ((opt->nb_stages == 1 &&
+ opt->prod_type != EVT_PROD_TYPE_EVENT_TIMER_ADPTR) &&
+ opt->fwd_latency) {
+ evt_info("fwd_latency is valid when nb_stages > 1, disabling");
+ opt->fwd_latency = 0;
+ }
+
+ if (opt->fwd_latency && !opt->q_priority) {
+ evt_info("enabled queue priority for latency measurement");
+ opt->q_priority = 1;
+ }
+ if (opt->nb_pkts == 0)
+ opt->nb_pkts = INT64_MAX/evt_nr_active_lcores(opt->plcores);
+
+ return 0;
+}
+
+void
+perf_opt_dump(struct evt_options *opt, uint8_t nb_queues)
+{
+ evt_dump("nb_prod_lcores", "%d", evt_nr_active_lcores(opt->plcores));
+ evt_dump_producer_lcores(opt);
+ evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
+ evt_dump_worker_lcores(opt);
+ evt_dump_nb_stages(opt);
+ evt_dump("nb_evdev_ports", "%d", perf_nb_event_ports(opt));
+ evt_dump("nb_evdev_queues", "%d", nb_queues);
+ evt_dump_queue_priority(opt);
+ evt_dump_sched_type_list(opt);
+ evt_dump_producer_type(opt);
+}
+
+void
+perf_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ int i;
+ struct test_perf *t = evt_test_priv(test);
+
+ if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ for (i = 0; i < opt->nb_timer_adptrs; i++)
+ rte_event_timer_adapter_stop(t->timer_adptr[i]);
+ }
+ rte_event_dev_stop(opt->dev_id);
+ rte_event_dev_close(opt->dev_id);
+}
+
+static inline void
+perf_elt_init(struct rte_mempool *mp, void *arg __rte_unused,
+ void *obj, unsigned i __rte_unused)
+{
+ memset(obj, 0, mp->elt_size);
+}
+
+#define NB_RX_DESC 128
+#define NB_TX_DESC 512
+int
+perf_ethdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ uint16_t i;
+ int ret;
+ struct test_perf *t = evt_test_priv(test);
+ struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_RSS,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IP,
+ },
+ },
+ };
+
+ if (opt->prod_type == EVT_PROD_TYPE_SYNT ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR)
+ return 0;
+
+ if (!rte_eth_dev_count_avail()) {
+ evt_err("No ethernet ports found.");
+ return -ENODEV;
+ }
+
+ RTE_ETH_FOREACH_DEV(i) {
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_conf local_port_conf = port_conf;
+
+ ret = rte_eth_dev_info_get(i, &dev_info);
+ if (ret != 0) {
+ evt_err("Error during getting device (port %u) info: %s\n",
+ i, strerror(-ret));
+ return ret;
+ }
+
+ local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
+ dev_info.flow_type_rss_offloads;
+ if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
+ port_conf.rx_adv_conf.rss_conf.rss_hf) {
+ evt_info("Port %u modified RSS hash function based on hardware support,"
+ "requested:%#"PRIx64" configured:%#"PRIx64"\n",
+ i,
+ port_conf.rx_adv_conf.rss_conf.rss_hf,
+ local_port_conf.rx_adv_conf.rss_conf.rss_hf);
+ }
+
+ if (rte_eth_dev_configure(i, 1, 1, &local_port_conf) < 0) {
+ evt_err("Failed to configure eth port [%d]", i);
+ return -EINVAL;
+ }
+
+ if (rte_eth_rx_queue_setup(i, 0, NB_RX_DESC,
+ rte_socket_id(), NULL, t->pool) < 0) {
+ evt_err("Failed to setup eth port [%d] rx_queue: %d.",
+ i, 0);
+ return -EINVAL;
+ }
+
+ if (rte_eth_tx_queue_setup(i, 0, NB_TX_DESC,
+ rte_socket_id(), NULL) < 0) {
+ evt_err("Failed to setup eth port [%d] tx_queue: %d.",
+ i, 0);
+ return -EINVAL;
+ }
+
+ ret = rte_eth_promiscuous_enable(i);
+ if (ret != 0) {
+ evt_err("Failed to enable promiscuous mode for eth port [%d]: %s",
+ i, rte_strerror(-ret));
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void perf_ethdev_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ uint16_t i;
+ RTE_SET_USED(test);
+
+ if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ RTE_ETH_FOREACH_DEV(i) {
+ rte_event_eth_rx_adapter_stop(i);
+ rte_eth_dev_stop(i);
+ }
+ }
+}
+
+int
+perf_mempool_setup(struct evt_test *test, struct evt_options *opt)
+{
+ struct test_perf *t = evt_test_priv(test);
+
+ if (opt->prod_type == EVT_PROD_TYPE_SYNT ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ t->pool = rte_mempool_create(test->name, /* mempool name */
+ opt->pool_sz, /* number of elements*/
+ sizeof(struct perf_elt), /* element size*/
+ 512, /* cache size*/
+ 0, NULL, NULL,
+ perf_elt_init, /* obj constructor */
+ NULL, opt->socket_id, 0); /* flags */
+ } else {
+ t->pool = rte_pktmbuf_pool_create(test->name, /* mempool name */
+ opt->pool_sz, /* number of elements*/
+ 512, /* cache size*/
+ 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ opt->socket_id); /* flags */
+
+ }
+
+ if (t->pool == NULL) {
+ evt_err("failed to create mempool");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void
+perf_mempool_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ struct test_perf *t = evt_test_priv(test);
+
+ rte_mempool_free(t->pool);
+}
+
+int
+perf_test_setup(struct evt_test *test, struct evt_options *opt)
+{
+ void *test_perf;
+
+ test_perf = rte_zmalloc_socket(test->name, sizeof(struct test_perf),
+ RTE_CACHE_LINE_SIZE, opt->socket_id);
+ if (test_perf == NULL) {
+ evt_err("failed to allocate test_perf memory");
+ goto nomem;
+ }
+ test->test_priv = test_perf;
+
+ struct test_perf *t = evt_test_priv(test);
+
+ if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ t->outstand_pkts = opt->nb_timers *
+ evt_nr_active_lcores(opt->plcores);
+ t->nb_pkts = opt->nb_timers;
+ } else {
+ t->outstand_pkts = opt->nb_pkts *
+ evt_nr_active_lcores(opt->plcores);
+ t->nb_pkts = opt->nb_pkts;
+ }
+
+ t->nb_workers = evt_nr_active_lcores(opt->wlcores);
+ t->done = false;
+ t->nb_flows = opt->nb_flows;
+ t->result = EVT_TEST_FAILED;
+ t->opt = opt;
+ memcpy(t->sched_type_list, opt->sched_type_list,
+ sizeof(opt->sched_type_list));
+ return 0;
+nomem:
+ return -ENOMEM;
+}
+
+void
+perf_test_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+
+ rte_free(test->test_priv);
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/test_perf_common.h b/src/spdk/dpdk/app/test-eventdev/test_perf_common.h
new file mode 100644
index 000000000..ff9705df8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_perf_common.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _TEST_PERF_COMMON_
+#define _TEST_PERF_COMMON_
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_event_eth_rx_adapter.h>
+#include <rte_event_timer_adapter.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_prefetch.h>
+
+#include "evt_common.h"
+#include "evt_options.h"
+#include "evt_test.h"
+
+struct test_perf;
+
+struct worker_data {
+ uint64_t processed_pkts;
+ uint64_t latency;
+ uint8_t dev_id;
+ uint8_t port_id;
+ struct test_perf *t;
+} __rte_cache_aligned;
+
+struct prod_data {
+ uint8_t dev_id;
+ uint8_t port_id;
+ uint8_t queue_id;
+ struct test_perf *t;
+} __rte_cache_aligned;
+
+
+struct test_perf {
+ /* Don't change the offset of "done". Signal handler use this memory
+ * to terminate all lcores work.
+ */
+ int done;
+ uint64_t outstand_pkts;
+ uint8_t nb_workers;
+ enum evt_test_result result;
+ uint32_t nb_flows;
+ uint64_t nb_pkts;
+ struct rte_mempool *pool;
+ struct prod_data prod[EVT_MAX_PORTS];
+ struct worker_data worker[EVT_MAX_PORTS];
+ struct evt_options *opt;
+ uint8_t sched_type_list[EVT_MAX_STAGES] __rte_cache_aligned;
+ struct rte_event_timer_adapter *timer_adptr[
+ RTE_EVENT_TIMER_ADAPTER_NUM_MAX] __rte_cache_aligned;
+} __rte_cache_aligned;
+
+struct perf_elt {
+ union {
+ struct rte_event_timer tim;
+ struct {
+ char pad[offsetof(struct rte_event_timer, user_meta)];
+ uint64_t timestamp;
+ };
+ };
+} __rte_cache_aligned;
+
+#define BURST_SIZE 16
+
+#define PERF_WORKER_INIT\
+ struct worker_data *w = arg;\
+ struct test_perf *t = w->t;\
+ struct evt_options *opt = t->opt;\
+ const uint8_t dev = w->dev_id;\
+ const uint8_t port = w->port_id;\
+ const uint8_t prod_timer_type = \
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR;\
+ uint8_t *const sched_type_list = &t->sched_type_list[0];\
+ struct rte_mempool *const pool = t->pool;\
+ const uint8_t nb_stages = t->opt->nb_stages;\
+ const uint8_t laststage = nb_stages - 1;\
+ uint8_t cnt = 0;\
+ void *bufs[16] __rte_cache_aligned;\
+ int const sz = RTE_DIM(bufs);\
+ if (opt->verbose_level > 1)\
+ printf("%s(): lcore %d dev_id %d port=%d\n", __func__,\
+ rte_lcore_id(), dev, port)
+
+static __rte_always_inline int
+perf_process_last_stage(struct rte_mempool *const pool,
+ struct rte_event *const ev, struct worker_data *const w,
+ void *bufs[], int const buf_sz, uint8_t count)
+{
+ bufs[count++] = ev->event_ptr;
+ w->processed_pkts++;
+ rte_smp_wmb();
+
+ if (unlikely(count == buf_sz)) {
+ count = 0;
+ rte_mempool_put_bulk(pool, bufs, buf_sz);
+ }
+ return count;
+}
+
+static __rte_always_inline uint8_t
+perf_process_last_stage_latency(struct rte_mempool *const pool,
+ struct rte_event *const ev, struct worker_data *const w,
+ void *bufs[], int const buf_sz, uint8_t count)
+{
+ uint64_t latency;
+ struct perf_elt *const m = ev->event_ptr;
+
+ bufs[count++] = ev->event_ptr;
+ w->processed_pkts++;
+
+ if (unlikely(count == buf_sz)) {
+ count = 0;
+ latency = rte_get_timer_cycles() - m->timestamp;
+ rte_mempool_put_bulk(pool, bufs, buf_sz);
+ } else {
+ latency = rte_get_timer_cycles() - m->timestamp;
+ }
+
+ w->latency += latency;
+ rte_smp_wmb();
+ return count;
+}
+
+
+static inline int
+perf_nb_event_ports(struct evt_options *opt)
+{
+ return evt_nr_active_lcores(opt->wlcores) +
+ evt_nr_active_lcores(opt->plcores);
+}
+
+int perf_test_result(struct evt_test *test, struct evt_options *opt);
+int perf_opt_check(struct evt_options *opt, uint64_t nb_queues);
+int perf_test_setup(struct evt_test *test, struct evt_options *opt);
+int perf_ethdev_setup(struct evt_test *test, struct evt_options *opt);
+int perf_mempool_setup(struct evt_test *test, struct evt_options *opt);
+int perf_event_dev_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t stride, uint8_t nb_queues,
+ const struct rte_event_port_conf *port_conf);
+int perf_event_dev_service_setup(uint8_t dev_id);
+int perf_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *));
+void perf_opt_dump(struct evt_options *opt, uint8_t nb_queues);
+void perf_test_destroy(struct evt_test *test, struct evt_options *opt);
+void perf_eventdev_destroy(struct evt_test *test, struct evt_options *opt);
+void perf_ethdev_destroy(struct evt_test *test, struct evt_options *opt);
+void perf_mempool_destroy(struct evt_test *test, struct evt_options *opt);
+
+#endif /* _TEST_PERF_COMMON_ */
diff --git a/src/spdk/dpdk/app/test-eventdev/test_perf_queue.c b/src/spdk/dpdk/app/test-eventdev/test_perf_queue.c
new file mode 100644
index 000000000..f4ea3a795
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_perf_queue.c
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test_perf_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static inline int
+perf_queue_nb_event_queues(struct evt_options *opt)
+{
+ /* nb_queues = number of producers * number of stages */
+ uint8_t nb_prod = opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ?
+ rte_eth_dev_count_avail() : evt_nr_active_lcores(opt->plcores);
+ return nb_prod * opt->nb_stages;
+}
+
+static __rte_always_inline void
+mark_fwd_latency(struct rte_event *const ev,
+ const uint8_t nb_stages)
+{
+ if (unlikely((ev->queue_id % nb_stages) == 0)) {
+ struct perf_elt *const m = ev->event_ptr;
+
+ m->timestamp = rte_get_timer_cycles();
+ }
+}
+
+static __rte_always_inline void
+fwd_event(struct rte_event *const ev, uint8_t *const sched_type_list,
+ const uint8_t nb_stages)
+{
+ ev->queue_id++;
+ ev->sched_type = sched_type_list[ev->queue_id % nb_stages];
+ ev->op = RTE_EVENT_OP_FORWARD;
+ ev->event_type = RTE_EVENT_TYPE_CPU;
+}
+
+static int
+perf_queue_worker(void *arg, const int enable_fwd_latency)
+{
+ PERF_WORKER_INIT;
+ struct rte_event ev;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+ if (enable_fwd_latency && !prod_timer_type)
+ /* first q in pipeline, mark timestamp to compute fwd latency */
+ mark_fwd_latency(&ev, nb_stages);
+
+ /* last stage in pipeline */
+ if (unlikely((ev.queue_id % nb_stages) == laststage)) {
+ if (enable_fwd_latency)
+ cnt = perf_process_last_stage_latency(pool,
+ &ev, w, bufs, sz, cnt);
+ else
+ cnt = perf_process_last_stage(pool,
+ &ev, w, bufs, sz, cnt);
+ } else {
+ fwd_event(&ev, sched_type_list, nb_stages);
+ while (rte_event_enqueue_burst(dev, port, &ev, 1) != 1)
+ rte_pause();
+ }
+ }
+ return 0;
+}
+
+static int
+perf_queue_worker_burst(void *arg, const int enable_fwd_latency)
+{
+ PERF_WORKER_INIT;
+ uint16_t i;
+ /* +1 to avoid prefetch out of array check */
+ struct rte_event ev[BURST_SIZE + 1];
+
+ while (t->done == false) {
+ uint16_t const nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ if (enable_fwd_latency && !prod_timer_type) {
+ rte_prefetch0(ev[i+1].event_ptr);
+ /* first queue in pipeline.
+ * mark time stamp to compute fwd latency
+ */
+ mark_fwd_latency(&ev[i], nb_stages);
+ }
+ /* last stage in pipeline */
+ if (unlikely((ev[i].queue_id % nb_stages) ==
+ laststage)) {
+ if (enable_fwd_latency)
+ cnt = perf_process_last_stage_latency(
+ pool, &ev[i], w, bufs, sz, cnt);
+ else
+ cnt = perf_process_last_stage(pool,
+ &ev[i], w, bufs, sz, cnt);
+
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ } else {
+ fwd_event(&ev[i], sched_type_list, nb_stages);
+ }
+ }
+
+ uint16_t enq;
+
+ enq = rte_event_enqueue_burst(dev, port, ev, nb_rx);
+ while (enq < nb_rx) {
+ enq += rte_event_enqueue_burst(dev, port,
+ ev + enq, nb_rx - enq);
+ }
+ }
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ struct evt_options *opt = w->t->opt;
+
+ const bool burst = evt_has_burst_mode(w->dev_id);
+ const int fwd_latency = opt->fwd_latency;
+
+ /* allow compiler to optimize */
+ if (!burst && !fwd_latency)
+ return perf_queue_worker(arg, 0);
+ else if (!burst && fwd_latency)
+ return perf_queue_worker(arg, 1);
+ else if (burst && !fwd_latency)
+ return perf_queue_worker_burst(arg, 0);
+ else if (burst && fwd_latency)
+ return perf_queue_worker_burst(arg, 1);
+
+ rte_panic("invalid worker\n");
+}
+
+static int
+perf_queue_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return perf_launch_lcores(test, opt, worker_wrapper);
+}
+
+static int
+perf_queue_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ uint8_t queue;
+ int nb_stages = opt->nb_stages;
+ int ret;
+ int nb_ports;
+ int nb_queues;
+ uint16_t prod;
+ struct rte_event_dev_info dev_info;
+ struct test_perf *t = evt_test_priv(test);
+
+ nb_ports = evt_nr_active_lcores(opt->wlcores);
+ nb_ports += opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ||
+ opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR ? 0 :
+ evt_nr_active_lcores(opt->plcores);
+
+ nb_queues = perf_queue_nb_event_queues(opt);
+
+ memset(&dev_info, 0, sizeof(struct rte_event_dev_info));
+ ret = rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (ret) {
+ evt_err("failed to get eventdev info %d", opt->dev_id);
+ return ret;
+ }
+
+ ret = evt_configure_eventdev(opt, nb_queues, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ struct rte_event_queue_conf q_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ /* queue configurations */
+ for (queue = 0; queue < nb_queues; queue++) {
+ q_conf.schedule_type =
+ (opt->sched_type_list[queue % nb_stages]);
+
+ if (opt->q_priority) {
+ uint8_t stage_pos = queue % nb_stages;
+ /* Configure event queues(stage 0 to stage n) with
+ * RTE_EVENT_DEV_PRIORITY_LOWEST to
+ * RTE_EVENT_DEV_PRIORITY_HIGHEST.
+ */
+ uint8_t step = RTE_EVENT_DEV_PRIORITY_LOWEST /
+ (nb_stages - 1);
+ /* Higher prio for the queues closer to last stage */
+ q_conf.priority = RTE_EVENT_DEV_PRIORITY_LOWEST -
+ (step * stage_pos);
+ }
+ ret = rte_event_queue_setup(opt->dev_id, queue, &q_conf);
+ if (ret) {
+ evt_err("failed to setup queue=%d", queue);
+ return ret;
+ }
+ }
+
+ if (opt->wkr_deq_dep > dev_info.max_event_port_dequeue_depth)
+ opt->wkr_deq_dep = dev_info.max_event_port_dequeue_depth;
+
+ /* port configuration */
+ const struct rte_event_port_conf p_conf = {
+ .dequeue_depth = opt->wkr_deq_dep,
+ .enqueue_depth = dev_info.max_event_port_dequeue_depth,
+ .new_event_threshold = dev_info.max_num_events,
+ };
+
+ ret = perf_event_dev_port_setup(test, opt, nb_stages /* stride */,
+ nb_queues, &p_conf);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ if (opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_eth_dev_start(prod);
+ if (ret) {
+ evt_err("Ethernet dev [%d] failed to start. Using synthetic producer",
+ prod);
+ return ret;
+ }
+
+ ret = rte_event_eth_rx_adapter_start(prod);
+ if (ret) {
+ evt_err("Rx adapter[%d] start failed", prod);
+ return ret;
+ }
+ printf("%s: Port[%d] using Rx adapter[%d] started\n",
+ __func__, prod, prod);
+ }
+ } else if (opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR) {
+ for (prod = 0; prod < opt->nb_timer_adptrs; prod++) {
+ ret = rte_event_timer_adapter_start(
+ t->timer_adptr[prod]);
+ if (ret) {
+ evt_err("failed to Start event timer adapter %d"
+ , prod);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void
+perf_queue_opt_dump(struct evt_options *opt)
+{
+ evt_dump_fwd_latency(opt);
+ perf_opt_dump(opt, perf_queue_nb_event_queues(opt));
+}
+
+static int
+perf_queue_opt_check(struct evt_options *opt)
+{
+ return perf_opt_check(opt, perf_queue_nb_event_queues(opt));
+}
+
+static bool
+perf_queue_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < perf_queue_nb_event_queues(opt) ||
+ dev_info.max_event_ports < perf_nb_event_ports(opt)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ perf_queue_nb_event_queues(opt),
+ dev_info.max_event_queues,
+ perf_nb_event_ports(opt), dev_info.max_event_ports);
+ }
+
+ return true;
+}
+
+static const struct evt_test_ops perf_queue = {
+ .cap_check = perf_queue_capability_check,
+ .opt_check = perf_queue_opt_check,
+ .opt_dump = perf_queue_opt_dump,
+ .test_setup = perf_test_setup,
+ .mempool_setup = perf_mempool_setup,
+ .ethdev_setup = perf_ethdev_setup,
+ .eventdev_setup = perf_queue_eventdev_setup,
+ .launch_lcores = perf_queue_launch_lcores,
+ .eventdev_destroy = perf_eventdev_destroy,
+ .mempool_destroy = perf_mempool_destroy,
+ .ethdev_destroy = perf_ethdev_destroy,
+ .test_result = perf_test_result,
+ .test_destroy = perf_test_destroy,
+};
+
+EVT_TEST_REGISTER(perf_queue);
diff --git a/src/spdk/dpdk/app/test-eventdev/test_pipeline_atq.c b/src/spdk/dpdk/app/test-eventdev/test_pipeline_atq.c
new file mode 100644
index 000000000..8e8686c14
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_pipeline_atq.c
@@ -0,0 +1,518 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 Cavium, Inc.
+ */
+
+#include "test_pipeline_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static __rte_always_inline int
+pipeline_atq_nb_event_queues(struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+
+ return rte_eth_dev_count_avail();
+}
+
+static __rte_noinline int
+pipeline_atq_worker_single_stage_tx(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_INIT;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ pipeline_event_tx(dev, port, &ev);
+ w->processed_pkts++;
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_single_stage_fwd(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ ev.queue_id = tx_queue[ev.mbuf->port];
+ pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+ pipeline_event_enqueue(dev, port, &ev);
+ w->processed_pkts++;
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_single_stage_burst_tx(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
+ }
+
+ pipeline_event_tx_burst(dev, port, ev, nb_rx);
+ w->processed_pkts += nb_rx;
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_single_stage_burst_fwd(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
+ ev[i].queue_id = tx_queue[ev[i].mbuf->port];
+ pipeline_fwd_event(&ev[i], RTE_SCHED_TYPE_ATOMIC);
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ w->processed_pkts += nb_rx;
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_multi_stage_tx(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_INIT;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ cq_id = ev.sub_event_type % nb_stages;
+
+ if (cq_id == last_queue) {
+ pipeline_event_tx(dev, port, &ev);
+ w->processed_pkts++;
+ continue;
+ }
+
+ ev.sub_event_type++;
+ pipeline_fwd_event(&ev, sched_type_list[cq_id]);
+ pipeline_event_enqueue(dev, port, &ev);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_multi_stage_fwd(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ cq_id = ev.sub_event_type % nb_stages;
+
+ if (cq_id == last_queue) {
+ ev.queue_id = tx_queue[ev.mbuf->port];
+ pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+ w->processed_pkts++;
+ } else {
+ ev.sub_event_type++;
+ pipeline_fwd_event(&ev, sched_type_list[cq_id]);
+ }
+
+ pipeline_event_enqueue(dev, port, &ev);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_multi_stage_burst_tx(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ cq_id = ev[i].sub_event_type % nb_stages;
+
+ if (cq_id == last_queue) {
+ pipeline_event_tx(dev, port, &ev[i]);
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ w->processed_pkts++;
+ continue;
+ }
+
+ ev[i].sub_event_type++;
+ pipeline_fwd_event(&ev[i], sched_type_list[cq_id]);
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_atq_worker_multi_stage_burst_fwd(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ cq_id = ev[i].sub_event_type % nb_stages;
+
+ if (cq_id == last_queue) {
+ w->processed_pkts++;
+ ev[i].queue_id = tx_queue[ev[i].mbuf->port];
+ pipeline_fwd_event(&ev[i],
+ RTE_SCHED_TYPE_ATOMIC);
+ } else {
+ ev[i].sub_event_type++;
+ pipeline_fwd_event(&ev[i],
+ sched_type_list[cq_id]);
+ }
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ }
+
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ struct evt_options *opt = w->t->opt;
+ const bool burst = evt_has_burst_mode(w->dev_id);
+ const bool internal_port = w->t->internal_port;
+ const uint8_t nb_stages = opt->nb_stages;
+ RTE_SET_USED(opt);
+
+ if (nb_stages == 1) {
+ if (!burst && internal_port)
+ return pipeline_atq_worker_single_stage_tx(arg);
+ else if (!burst && !internal_port)
+ return pipeline_atq_worker_single_stage_fwd(arg);
+ else if (burst && internal_port)
+ return pipeline_atq_worker_single_stage_burst_tx(arg);
+ else if (burst && !internal_port)
+ return pipeline_atq_worker_single_stage_burst_fwd(arg);
+ } else {
+ if (!burst && internal_port)
+ return pipeline_atq_worker_multi_stage_tx(arg);
+ else if (!burst && !internal_port)
+ return pipeline_atq_worker_multi_stage_fwd(arg);
+ if (burst && internal_port)
+ return pipeline_atq_worker_multi_stage_burst_tx(arg);
+ else if (burst && !internal_port)
+ return pipeline_atq_worker_multi_stage_burst_fwd(arg);
+ }
+
+ rte_panic("invalid worker\n");
+}
+
+static int
+pipeline_atq_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return pipeline_launch_lcores(test, opt, worker_wrapper);
+}
+
+static int
+pipeline_atq_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ int ret;
+ int nb_ports;
+ int nb_queues;
+ uint8_t queue;
+ uint8_t tx_evqueue_id[RTE_MAX_ETHPORTS];
+ uint8_t queue_arr[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t nb_worker_queues = 0;
+ uint8_t tx_evport_id = 0;
+ uint16_t prod = 0;
+ struct rte_event_dev_info info;
+ struct test_pipeline *t = evt_test_priv(test);
+
+ nb_ports = evt_nr_active_lcores(opt->wlcores);
+ nb_queues = rte_eth_dev_count_avail();
+
+ memset(tx_evqueue_id, 0, sizeof(uint8_t) * RTE_MAX_ETHPORTS);
+ memset(queue_arr, 0, sizeof(uint8_t) * RTE_EVENT_MAX_QUEUES_PER_DEV);
+ /* One queue for Tx adapter per port */
+ if (!t->internal_port) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ tx_evqueue_id[prod] = nb_queues;
+ nb_queues++;
+ }
+ }
+
+ rte_event_dev_info_get(opt->dev_id, &info);
+
+ ret = evt_configure_eventdev(opt, nb_queues, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ struct rte_event_queue_conf q_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ /* queue configurations */
+ for (queue = 0; queue < nb_queues; queue++) {
+ q_conf.event_queue_cfg = RTE_EVENT_QUEUE_CFG_ALL_TYPES;
+
+ if (!t->internal_port) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ if (queue == tx_evqueue_id[prod]) {
+ q_conf.event_queue_cfg =
+ RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
+ } else {
+ queue_arr[nb_worker_queues] = queue;
+ nb_worker_queues++;
+ }
+ }
+ }
+
+ ret = rte_event_queue_setup(opt->dev_id, queue, &q_conf);
+ if (ret) {
+ evt_err("failed to setup queue=%d", queue);
+ return ret;
+ }
+ }
+
+ if (opt->wkr_deq_dep > info.max_event_port_dequeue_depth)
+ opt->wkr_deq_dep = info.max_event_port_dequeue_depth;
+
+ /* port configuration */
+ const struct rte_event_port_conf p_conf = {
+ .dequeue_depth = opt->wkr_deq_dep,
+ .enqueue_depth = info.max_event_port_dequeue_depth,
+ .new_event_threshold = info.max_num_events,
+ };
+
+ if (!t->internal_port)
+ ret = pipeline_event_port_setup(test, opt, queue_arr,
+ nb_worker_queues, p_conf);
+ else
+ ret = pipeline_event_port_setup(test, opt, NULL, nb_queues,
+ p_conf);
+
+ if (ret)
+ return ret;
+
+ /*
+ * The pipelines are setup in the following manner:
+ *
+ * eth_dev_count = 2, nb_stages = 2, atq mode
+ *
+ * eth0, eth1 have Internal port capability :
+ * queues = 2
+ * stride = 1
+ *
+ * event queue pipelines:
+ * eth0 -> q0 ->Tx
+ * eth1 -> q1 ->Tx
+ *
+ * q0, q1 are configured as ATQ so, all the different stages can
+ * be enqueued on the same queue.
+ *
+ * eth0, eth1 use Tx adapters service core :
+ * queues = 4
+ * stride = 1
+ *
+ * event queue pipelines:
+ * eth0 -> q0 -> q2 -> Tx
+ * eth1 -> q1 -> q3 -> Tx
+ *
+ * q0, q1 are configured as stated above.
+ * q2, q3 configured as SINGLE_LINK.
+ */
+ ret = pipeline_event_rx_adapter_setup(opt, 1, p_conf);
+ if (ret)
+ return ret;
+ ret = pipeline_event_tx_adapter_setup(opt, p_conf);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ /* Connect the tx_evqueue_id to the Tx adapter port */
+ if (!t->internal_port) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_event_eth_tx_adapter_event_port_get(prod,
+ &tx_evport_id);
+ if (ret) {
+ evt_err("Unable to get Tx adapter[%d]", prod);
+ return ret;
+ }
+
+ if (rte_event_port_link(opt->dev_id, tx_evport_id,
+ &tx_evqueue_id[prod],
+ NULL, 1) != 1) {
+ evt_err("Unable to link Tx adptr[%d] evprt[%d]",
+ prod, tx_evport_id);
+ return ret;
+ }
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_eth_dev_start(prod);
+ if (ret) {
+ evt_err("Ethernet dev [%d] failed to start."
+ " Using synthetic producer", prod);
+ return ret;
+ }
+ }
+
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_event_eth_rx_adapter_start(prod);
+ if (ret) {
+ evt_err("Rx adapter[%d] start failed", prod);
+ return ret;
+ }
+
+ ret = rte_event_eth_tx_adapter_start(prod);
+ if (ret) {
+ evt_err("Tx adapter[%d] start failed", prod);
+ return ret;
+ }
+ }
+
+ memcpy(t->tx_evqueue_id, tx_evqueue_id, sizeof(uint8_t) *
+ RTE_MAX_ETHPORTS);
+
+ return 0;
+}
+
+static void
+pipeline_atq_opt_dump(struct evt_options *opt)
+{
+ pipeline_opt_dump(opt, pipeline_atq_nb_event_queues(opt));
+}
+
+static int
+pipeline_atq_opt_check(struct evt_options *opt)
+{
+ return pipeline_opt_check(opt, pipeline_atq_nb_event_queues(opt));
+}
+
+static bool
+pipeline_atq_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < pipeline_atq_nb_event_queues(opt) ||
+ dev_info.max_event_ports <
+ evt_nr_active_lcores(opt->wlcores)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ pipeline_atq_nb_event_queues(opt),
+ dev_info.max_event_queues,
+ evt_nr_active_lcores(opt->wlcores),
+ dev_info.max_event_ports);
+ }
+
+ return true;
+}
+
+static const struct evt_test_ops pipeline_atq = {
+ .cap_check = pipeline_atq_capability_check,
+ .opt_check = pipeline_atq_opt_check,
+ .opt_dump = pipeline_atq_opt_dump,
+ .test_setup = pipeline_test_setup,
+ .mempool_setup = pipeline_mempool_setup,
+ .ethdev_setup = pipeline_ethdev_setup,
+ .eventdev_setup = pipeline_atq_eventdev_setup,
+ .launch_lcores = pipeline_atq_launch_lcores,
+ .eventdev_destroy = pipeline_eventdev_destroy,
+ .mempool_destroy = pipeline_mempool_destroy,
+ .ethdev_destroy = pipeline_ethdev_destroy,
+ .test_result = pipeline_test_result,
+ .test_destroy = pipeline_test_destroy,
+};
+
+EVT_TEST_REGISTER(pipeline_atq);
diff --git a/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.c b/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.c
new file mode 100644
index 000000000..17088b1b4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.c
@@ -0,0 +1,534 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 Cavium, Inc.
+ */
+
+#include "test_pipeline_common.h"
+
+int
+pipeline_test_result(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ int i;
+ uint64_t total = 0;
+ struct test_pipeline *t = evt_test_priv(test);
+
+ evt_info("Packet distribution across worker cores :");
+ for (i = 0; i < t->nb_workers; i++)
+ total += t->worker[i].processed_pkts;
+ for (i = 0; i < t->nb_workers; i++)
+ evt_info("Worker %d packets: "CLGRN"%"PRIx64""CLNRM" percentage:"
+ CLGRN" %3.2f"CLNRM, i,
+ t->worker[i].processed_pkts,
+ (((double)t->worker[i].processed_pkts)/total)
+ * 100);
+ return t->result;
+}
+
+void
+pipeline_opt_dump(struct evt_options *opt, uint8_t nb_queues)
+{
+ evt_dump("nb_worker_lcores", "%d", evt_nr_active_lcores(opt->wlcores));
+ evt_dump_worker_lcores(opt);
+ evt_dump_nb_stages(opt);
+ evt_dump("nb_evdev_ports", "%d", pipeline_nb_event_ports(opt));
+ evt_dump("nb_evdev_queues", "%d", nb_queues);
+ evt_dump_queue_priority(opt);
+ evt_dump_sched_type_list(opt);
+ evt_dump_producer_type(opt);
+}
+
+static inline uint64_t
+processed_pkts(struct test_pipeline *t)
+{
+ uint8_t i;
+ uint64_t total = 0;
+
+ rte_smp_rmb();
+ for (i = 0; i < t->nb_workers; i++)
+ total += t->worker[i].processed_pkts;
+
+ return total;
+}
+
+int
+pipeline_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *))
+{
+ int ret, lcore_id;
+ struct test_pipeline *t = evt_test_priv(test);
+
+ int port_idx = 0;
+ /* launch workers */
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (!(opt->wlcores[lcore_id]))
+ continue;
+
+ ret = rte_eal_remote_launch(worker,
+ &t->worker[port_idx], lcore_id);
+ if (ret) {
+ evt_err("failed to launch worker %d", lcore_id);
+ return ret;
+ }
+ port_idx++;
+ }
+
+ uint64_t perf_cycles = rte_get_timer_cycles();
+ const uint64_t perf_sample = rte_get_timer_hz();
+
+ static float total_mpps;
+ static uint64_t samples;
+
+ uint64_t prev_pkts = 0;
+
+ while (t->done == false) {
+ const uint64_t new_cycles = rte_get_timer_cycles();
+
+ if ((new_cycles - perf_cycles) > perf_sample) {
+ const uint64_t curr_pkts = processed_pkts(t);
+
+ float mpps = (float)(curr_pkts - prev_pkts)/1000000;
+
+ prev_pkts = curr_pkts;
+ perf_cycles = new_cycles;
+ total_mpps += mpps;
+ ++samples;
+ printf(CLGRN"\r%.3f mpps avg %.3f mpps"CLNRM,
+ mpps, total_mpps/samples);
+ fflush(stdout);
+ }
+ }
+ printf("\n");
+ return 0;
+}
+
+int
+pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues)
+{
+ unsigned int lcores;
+ /*
+ * N worker + 1 master
+ */
+ lcores = 2;
+
+ if (opt->prod_type != EVT_PROD_TYPE_ETH_RX_ADPTR) {
+ evt_err("Invalid producer type '%s' valid producer '%s'",
+ evt_prod_id_to_name(opt->prod_type),
+ evt_prod_id_to_name(EVT_PROD_TYPE_ETH_RX_ADPTR));
+ return -1;
+ }
+
+ if (!rte_eth_dev_count_avail()) {
+ evt_err("test needs minimum 1 ethernet dev");
+ return -1;
+ }
+
+ if (rte_lcore_count() < lcores) {
+ evt_err("test need minimum %d lcores", lcores);
+ return -1;
+ }
+
+ /* Validate worker lcores */
+ if (evt_lcores_has_overlap(opt->wlcores, rte_get_master_lcore())) {
+ evt_err("worker lcores overlaps with master lcore");
+ return -1;
+ }
+ if (evt_has_disabled_lcore(opt->wlcores)) {
+ evt_err("one or more workers lcores are not enabled");
+ return -1;
+ }
+ if (!evt_has_active_lcore(opt->wlcores)) {
+ evt_err("minimum one worker is required");
+ return -1;
+ }
+
+ if (nb_queues > EVT_MAX_QUEUES) {
+ evt_err("number of queues exceeds %d", EVT_MAX_QUEUES);
+ return -1;
+ }
+ if (pipeline_nb_event_ports(opt) > EVT_MAX_PORTS) {
+ evt_err("number of ports exceeds %d", EVT_MAX_PORTS);
+ return -1;
+ }
+
+ if (evt_has_invalid_stage(opt))
+ return -1;
+
+ if (evt_has_invalid_sched_type(opt))
+ return -1;
+
+ return 0;
+}
+
+#define NB_RX_DESC 128
+#define NB_TX_DESC 512
+int
+pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ uint16_t i;
+ int ret;
+ uint8_t nb_queues = 1;
+ struct test_pipeline *t = evt_test_priv(test);
+ struct rte_eth_rxconf rx_conf;
+ struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_RSS,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IP,
+ },
+ },
+ };
+
+ if (!rte_eth_dev_count_avail()) {
+ evt_err("No ethernet ports found.");
+ return -ENODEV;
+ }
+
+ if (opt->max_pkt_sz < RTE_ETHER_MIN_LEN) {
+ evt_err("max_pkt_sz can not be less than %d",
+ RTE_ETHER_MIN_LEN);
+ return -EINVAL;
+ }
+
+ port_conf.rxmode.max_rx_pkt_len = opt->max_pkt_sz;
+ if (opt->max_pkt_sz > RTE_ETHER_MAX_LEN)
+ port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+
+ t->internal_port = 1;
+ RTE_ETH_FOREACH_DEV(i) {
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_conf local_port_conf = port_conf;
+ uint32_t caps = 0;
+
+ ret = rte_event_eth_tx_adapter_caps_get(opt->dev_id, i, &caps);
+ if (ret != 0) {
+ evt_err("failed to get event tx adapter[%d] caps", i);
+ return ret;
+ }
+
+ if (!(caps & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT))
+ t->internal_port = 0;
+
+ ret = rte_eth_dev_info_get(i, &dev_info);
+ if (ret != 0) {
+ evt_err("Error during getting device (port %u) info: %s\n",
+ i, strerror(-ret));
+ return ret;
+ }
+
+ rx_conf = dev_info.default_rxconf;
+ rx_conf.offloads = port_conf.rxmode.offloads;
+
+ local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
+ dev_info.flow_type_rss_offloads;
+ if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
+ port_conf.rx_adv_conf.rss_conf.rss_hf) {
+ evt_info("Port %u modified RSS hash function based on hardware support,"
+ "requested:%#"PRIx64" configured:%#"PRIx64"",
+ i,
+ port_conf.rx_adv_conf.rss_conf.rss_hf,
+ local_port_conf.rx_adv_conf.rss_conf.rss_hf);
+ }
+
+ if (rte_eth_dev_configure(i, nb_queues, nb_queues,
+ &local_port_conf)
+ < 0) {
+ evt_err("Failed to configure eth port [%d]", i);
+ return -EINVAL;
+ }
+
+ if (rte_eth_rx_queue_setup(i, 0, NB_RX_DESC,
+ rte_socket_id(), &rx_conf, t->pool) < 0) {
+ evt_err("Failed to setup eth port [%d] rx_queue: %d.",
+ i, 0);
+ return -EINVAL;
+ }
+ if (rte_eth_tx_queue_setup(i, 0, NB_TX_DESC,
+ rte_socket_id(), NULL) < 0) {
+ evt_err("Failed to setup eth port [%d] tx_queue: %d.",
+ i, 0);
+ return -EINVAL;
+ }
+
+ ret = rte_eth_promiscuous_enable(i);
+ if (ret != 0) {
+ evt_err("Failed to enable promiscuous mode for eth port [%d]: %s",
+ i, rte_strerror(-ret));
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int
+pipeline_event_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t *queue_arr, uint8_t nb_queues,
+ const struct rte_event_port_conf p_conf)
+{
+ int ret;
+ uint8_t port;
+ struct test_pipeline *t = evt_test_priv(test);
+
+
+ /* setup one port per worker, linking to all queues */
+ for (port = 0; port < evt_nr_active_lcores(opt->wlcores); port++) {
+ struct worker_data *w = &t->worker[port];
+
+ w->dev_id = opt->dev_id;
+ w->port_id = port;
+ w->t = t;
+ w->processed_pkts = 0;
+
+ ret = rte_event_port_setup(opt->dev_id, port, &p_conf);
+ if (ret) {
+ evt_err("failed to setup port %d", port);
+ return ret;
+ }
+
+ if (rte_event_port_link(opt->dev_id, port, queue_arr, NULL,
+ nb_queues) != nb_queues)
+ goto link_fail;
+ }
+
+ return 0;
+
+link_fail:
+ evt_err("failed to link queues to port %d", port);
+ return -EINVAL;
+}
+
+int
+pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride,
+ struct rte_event_port_conf prod_conf)
+{
+ int ret = 0;
+ uint16_t prod;
+ struct rte_event_eth_rx_adapter_queue_conf queue_conf;
+
+ memset(&queue_conf, 0,
+ sizeof(struct rte_event_eth_rx_adapter_queue_conf));
+ queue_conf.ev.sched_type = opt->sched_type_list[0];
+ RTE_ETH_FOREACH_DEV(prod) {
+ uint32_t cap;
+
+ ret = rte_event_eth_rx_adapter_caps_get(opt->dev_id,
+ prod, &cap);
+ if (ret) {
+ evt_err("failed to get event rx adapter[%d]"
+ " capabilities",
+ opt->dev_id);
+ return ret;
+ }
+ queue_conf.ev.queue_id = prod * stride;
+ ret = rte_event_eth_rx_adapter_create(prod, opt->dev_id,
+ &prod_conf);
+ if (ret) {
+ evt_err("failed to create rx adapter[%d]", prod);
+ return ret;
+ }
+ ret = rte_event_eth_rx_adapter_queue_add(prod, prod, -1,
+ &queue_conf);
+ if (ret) {
+ evt_err("failed to add rx queues to adapter[%d]", prod);
+ return ret;
+ }
+
+ if (!(cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) {
+ uint32_t service_id = -1U;
+
+ rte_event_eth_rx_adapter_service_id_get(prod,
+ &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("Failed to setup service core"
+ " for Rx adapter");
+ return ret;
+ }
+ }
+
+ evt_info("Port[%d] using Rx adapter[%d] configured", prod,
+ prod);
+ }
+
+ return ret;
+}
+
+int
+pipeline_event_tx_adapter_setup(struct evt_options *opt,
+ struct rte_event_port_conf port_conf)
+{
+ int ret = 0;
+ uint16_t consm;
+
+ RTE_ETH_FOREACH_DEV(consm) {
+ uint32_t cap;
+
+ ret = rte_event_eth_tx_adapter_caps_get(opt->dev_id,
+ consm, &cap);
+ if (ret) {
+ evt_err("failed to get event tx adapter[%d] caps",
+ consm);
+ return ret;
+ }
+
+ ret = rte_event_eth_tx_adapter_create(consm, opt->dev_id,
+ &port_conf);
+ if (ret) {
+ evt_err("failed to create tx adapter[%d]", consm);
+ return ret;
+ }
+
+ ret = rte_event_eth_tx_adapter_queue_add(consm, consm, -1);
+ if (ret) {
+ evt_err("failed to add tx queues to adapter[%d]",
+ consm);
+ return ret;
+ }
+
+ if (!(cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)) {
+ uint32_t service_id = -1U;
+
+ ret = rte_event_eth_tx_adapter_service_id_get(consm,
+ &service_id);
+ if (ret != -ESRCH && ret != 0) {
+ evt_err("Failed to get Tx adptr service ID");
+ return ret;
+ }
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("Failed to setup service core"
+ " for Tx adapter");
+ return ret;
+ }
+ }
+
+ evt_info("Port[%d] using Tx adapter[%d] Configured", consm,
+ consm);
+ }
+
+ return ret;
+}
+
+void
+pipeline_ethdev_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ uint16_t i;
+ RTE_SET_USED(test);
+ RTE_SET_USED(opt);
+
+ RTE_ETH_FOREACH_DEV(i) {
+ rte_event_eth_rx_adapter_stop(i);
+ rte_event_eth_tx_adapter_stop(i);
+ rte_eth_dev_stop(i);
+ }
+}
+
+void
+pipeline_eventdev_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(test);
+
+ rte_event_dev_stop(opt->dev_id);
+ rte_event_dev_close(opt->dev_id);
+}
+
+int
+pipeline_mempool_setup(struct evt_test *test, struct evt_options *opt)
+{
+ struct test_pipeline *t = evt_test_priv(test);
+ int i, ret;
+
+ if (!opt->mbuf_sz)
+ opt->mbuf_sz = RTE_MBUF_DEFAULT_BUF_SIZE;
+
+ if (!opt->max_pkt_sz)
+ opt->max_pkt_sz = RTE_ETHER_MAX_LEN;
+
+ RTE_ETH_FOREACH_DEV(i) {
+ struct rte_eth_dev_info dev_info;
+ uint16_t data_size = 0;
+
+ memset(&dev_info, 0, sizeof(dev_info));
+ ret = rte_eth_dev_info_get(i, &dev_info);
+ if (ret != 0) {
+ evt_err("Error during getting device (port %u) info: %s\n",
+ i, strerror(-ret));
+ return ret;
+ }
+
+ if (dev_info.rx_desc_lim.nb_mtu_seg_max != UINT16_MAX &&
+ dev_info.rx_desc_lim.nb_mtu_seg_max != 0) {
+ data_size = opt->max_pkt_sz /
+ dev_info.rx_desc_lim.nb_mtu_seg_max;
+ data_size += RTE_PKTMBUF_HEADROOM;
+
+ if (data_size > opt->mbuf_sz)
+ opt->mbuf_sz = data_size;
+ }
+ }
+
+ t->pool = rte_pktmbuf_pool_create(test->name, /* mempool name */
+ opt->pool_sz, /* number of elements*/
+ 512, /* cache size*/
+ 0,
+ opt->mbuf_sz,
+ opt->socket_id); /* flags */
+
+ if (t->pool == NULL) {
+ evt_err("failed to create mempool");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void
+pipeline_mempool_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+ struct test_pipeline *t = evt_test_priv(test);
+
+ rte_mempool_free(t->pool);
+}
+
+int
+pipeline_test_setup(struct evt_test *test, struct evt_options *opt)
+{
+ void *test_pipeline;
+
+ test_pipeline = rte_zmalloc_socket(test->name,
+ sizeof(struct test_pipeline), RTE_CACHE_LINE_SIZE,
+ opt->socket_id);
+ if (test_pipeline == NULL) {
+ evt_err("failed to allocate test_pipeline memory");
+ goto nomem;
+ }
+ test->test_priv = test_pipeline;
+
+ struct test_pipeline *t = evt_test_priv(test);
+
+ t->nb_workers = evt_nr_active_lcores(opt->wlcores);
+ t->outstand_pkts = opt->nb_pkts * evt_nr_active_lcores(opt->wlcores);
+ t->done = false;
+ t->nb_flows = opt->nb_flows;
+ t->result = EVT_TEST_FAILED;
+ t->opt = opt;
+ opt->prod_type = EVT_PROD_TYPE_ETH_RX_ADPTR;
+ memcpy(t->sched_type_list, opt->sched_type_list,
+ sizeof(opt->sched_type_list));
+ return 0;
+nomem:
+ return -ENOMEM;
+}
+
+void
+pipeline_test_destroy(struct evt_test *test, struct evt_options *opt)
+{
+ RTE_SET_USED(opt);
+
+ rte_free(test->test_priv);
+}
diff --git a/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.h b/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.h
new file mode 100644
index 000000000..6e73c6ab2
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_pipeline_common.h
@@ -0,0 +1,173 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 Cavium, Inc.
+ */
+
+#ifndef _TEST_PIPELINE_COMMON_
+#define _TEST_PIPELINE_COMMON_
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_event_eth_rx_adapter.h>
+#include <rte_event_eth_tx_adapter.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_prefetch.h>
+#include <rte_spinlock.h>
+#include <rte_service.h>
+#include <rte_service_component.h>
+
+#include "evt_common.h"
+#include "evt_options.h"
+#include "evt_test.h"
+
+struct test_pipeline;
+
+struct worker_data {
+ uint64_t processed_pkts;
+ uint8_t dev_id;
+ uint8_t port_id;
+ struct test_pipeline *t;
+} __rte_cache_aligned;
+
+struct test_pipeline {
+ /* Don't change the offset of "done". Signal handler use this memory
+ * to terminate all lcores work.
+ */
+ int done;
+ uint8_t nb_workers;
+ uint8_t internal_port;
+ uint8_t tx_evqueue_id[RTE_MAX_ETHPORTS];
+ enum evt_test_result result;
+ uint32_t nb_flows;
+ uint64_t outstand_pkts;
+ struct rte_mempool *pool;
+ struct worker_data worker[EVT_MAX_PORTS];
+ struct evt_options *opt;
+ uint8_t sched_type_list[EVT_MAX_STAGES] __rte_cache_aligned;
+} __rte_cache_aligned;
+
+#define BURST_SIZE 16
+
+#define PIPELINE_WORKER_SINGLE_STAGE_INIT \
+ struct worker_data *w = arg; \
+ struct test_pipeline *t = w->t; \
+ const uint8_t dev = w->dev_id; \
+ const uint8_t port = w->port_id; \
+ struct rte_event ev __rte_cache_aligned
+
+#define PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT \
+ int i; \
+ struct worker_data *w = arg; \
+ struct test_pipeline *t = w->t; \
+ const uint8_t dev = w->dev_id; \
+ const uint8_t port = w->port_id; \
+ struct rte_event ev[BURST_SIZE + 1] __rte_cache_aligned
+
+#define PIPELINE_WORKER_MULTI_STAGE_INIT \
+ struct worker_data *w = arg; \
+ struct test_pipeline *t = w->t; \
+ uint8_t cq_id; \
+ const uint8_t dev = w->dev_id; \
+ const uint8_t port = w->port_id; \
+ const uint8_t last_queue = t->opt->nb_stages - 1; \
+ uint8_t *const sched_type_list = &t->sched_type_list[0]; \
+ const uint8_t nb_stages = t->opt->nb_stages + 1; \
+ struct rte_event ev __rte_cache_aligned
+
+#define PIPELINE_WORKER_MULTI_STAGE_BURST_INIT \
+ int i; \
+ struct worker_data *w = arg; \
+ struct test_pipeline *t = w->t; \
+ uint8_t cq_id; \
+ const uint8_t dev = w->dev_id; \
+ const uint8_t port = w->port_id; \
+ const uint8_t last_queue = t->opt->nb_stages - 1; \
+ uint8_t *const sched_type_list = &t->sched_type_list[0]; \
+ const uint8_t nb_stages = t->opt->nb_stages + 1; \
+ struct rte_event ev[BURST_SIZE + 1] __rte_cache_aligned
+
+static __rte_always_inline void
+pipeline_fwd_event(struct rte_event *ev, uint8_t sched)
+{
+ ev->event_type = RTE_EVENT_TYPE_CPU;
+ ev->op = RTE_EVENT_OP_FORWARD;
+ ev->sched_type = sched;
+}
+
+static __rte_always_inline void
+pipeline_event_tx(const uint8_t dev, const uint8_t port,
+ struct rte_event * const ev)
+{
+ rte_event_eth_tx_adapter_txq_set(ev->mbuf, 0);
+ while (!rte_event_eth_tx_adapter_enqueue(dev, port, ev, 1, 0))
+ rte_pause();
+}
+
+static __rte_always_inline void
+pipeline_event_tx_burst(const uint8_t dev, const uint8_t port,
+ struct rte_event *ev, const uint16_t nb_rx)
+{
+ uint16_t enq;
+
+ enq = rte_event_eth_tx_adapter_enqueue(dev, port, ev, nb_rx, 0);
+ while (enq < nb_rx) {
+ enq += rte_event_eth_tx_adapter_enqueue(dev, port,
+ ev + enq, nb_rx - enq, 0);
+ }
+}
+
+static __rte_always_inline void
+pipeline_event_enqueue(const uint8_t dev, const uint8_t port,
+ struct rte_event *ev)
+{
+ while (rte_event_enqueue_burst(dev, port, ev, 1) != 1)
+ rte_pause();
+}
+
+static __rte_always_inline void
+pipeline_event_enqueue_burst(const uint8_t dev, const uint8_t port,
+ struct rte_event *ev, const uint16_t nb_rx)
+{
+ uint16_t enq;
+
+ enq = rte_event_enqueue_burst(dev, port, ev, nb_rx);
+ while (enq < nb_rx) {
+ enq += rte_event_enqueue_burst(dev, port,
+ ev + enq, nb_rx - enq);
+ }
+}
+
+static inline int
+pipeline_nb_event_ports(struct evt_options *opt)
+{
+ return evt_nr_active_lcores(opt->wlcores);
+}
+
+int pipeline_test_result(struct evt_test *test, struct evt_options *opt);
+int pipeline_opt_check(struct evt_options *opt, uint64_t nb_queues);
+int pipeline_test_setup(struct evt_test *test, struct evt_options *opt);
+int pipeline_ethdev_setup(struct evt_test *test, struct evt_options *opt);
+int pipeline_event_rx_adapter_setup(struct evt_options *opt, uint8_t stride,
+ struct rte_event_port_conf prod_conf);
+int pipeline_event_tx_adapter_setup(struct evt_options *opt,
+ struct rte_event_port_conf prod_conf);
+int pipeline_mempool_setup(struct evt_test *test, struct evt_options *opt);
+int pipeline_event_port_setup(struct evt_test *test, struct evt_options *opt,
+ uint8_t *queue_arr, uint8_t nb_queues,
+ const struct rte_event_port_conf p_conf);
+int pipeline_launch_lcores(struct evt_test *test, struct evt_options *opt,
+ int (*worker)(void *));
+void pipeline_opt_dump(struct evt_options *opt, uint8_t nb_queues);
+void pipeline_test_destroy(struct evt_test *test, struct evt_options *opt);
+void pipeline_eventdev_destroy(struct evt_test *test, struct evt_options *opt);
+void pipeline_ethdev_destroy(struct evt_test *test, struct evt_options *opt);
+void pipeline_mempool_destroy(struct evt_test *test, struct evt_options *opt);
+
+#endif /* _TEST_PIPELINE_COMMON_ */
diff --git a/src/spdk/dpdk/app/test-eventdev/test_pipeline_queue.c b/src/spdk/dpdk/app/test-eventdev/test_pipeline_queue.c
new file mode 100644
index 000000000..7bebac34f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-eventdev/test_pipeline_queue.c
@@ -0,0 +1,533 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 Cavium, Inc.
+ */
+
+#include "test_pipeline_common.h"
+
+/* See http://doc.dpdk.org/guides/tools/testeventdev.html for test details */
+
+static __rte_always_inline int
+pipeline_queue_nb_event_queues(struct evt_options *opt)
+{
+ uint16_t eth_count = rte_eth_dev_count_avail();
+
+ return (eth_count * opt->nb_stages) + eth_count;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_single_stage_tx(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_INIT;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ if (ev.sched_type == RTE_SCHED_TYPE_ATOMIC) {
+ pipeline_event_tx(dev, port, &ev);
+ w->processed_pkts++;
+ } else {
+ ev.queue_id++;
+ pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+ pipeline_event_enqueue(dev, port, &ev);
+ }
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_single_stage_fwd(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ ev.queue_id = tx_queue[ev.mbuf->port];
+ rte_event_eth_tx_adapter_txq_set(ev.mbuf, 0);
+ pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+ pipeline_event_enqueue(dev, port, &ev);
+ w->processed_pkts++;
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_single_stage_burst_tx(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ if (ev[i].sched_type == RTE_SCHED_TYPE_ATOMIC) {
+ pipeline_event_tx(dev, port, &ev[i]);
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ w->processed_pkts++;
+ } else {
+ ev[i].queue_id++;
+ pipeline_fwd_event(&ev[i],
+ RTE_SCHED_TYPE_ATOMIC);
+ }
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_single_stage_burst_fwd(void *arg)
+{
+ PIPELINE_WORKER_SINGLE_STAGE_BURST_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ ev[i].queue_id = tx_queue[ev[i].mbuf->port];
+ rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
+ pipeline_fwd_event(&ev[i], RTE_SCHED_TYPE_ATOMIC);
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ w->processed_pkts += nb_rx;
+ }
+
+ return 0;
+}
+
+
+static __rte_noinline int
+pipeline_queue_worker_multi_stage_tx(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ cq_id = ev.queue_id % nb_stages;
+
+ if (ev.queue_id == tx_queue[ev.mbuf->port]) {
+ pipeline_event_tx(dev, port, &ev);
+ w->processed_pkts++;
+ continue;
+ }
+
+ ev.queue_id++;
+ pipeline_fwd_event(&ev, cq_id != last_queue ?
+ sched_type_list[cq_id] :
+ RTE_SCHED_TYPE_ATOMIC);
+ pipeline_event_enqueue(dev, port, &ev);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_multi_stage_fwd(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t event = rte_event_dequeue_burst(dev, port, &ev, 1, 0);
+
+ if (!event) {
+ rte_pause();
+ continue;
+ }
+
+ cq_id = ev.queue_id % nb_stages;
+
+ if (cq_id == last_queue) {
+ ev.queue_id = tx_queue[ev.mbuf->port];
+ rte_event_eth_tx_adapter_txq_set(ev.mbuf, 0);
+ pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+ w->processed_pkts++;
+ } else {
+ ev.queue_id++;
+ pipeline_fwd_event(&ev, sched_type_list[cq_id]);
+ }
+
+ pipeline_event_enqueue(dev, port, &ev);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_multi_stage_burst_tx(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ cq_id = ev[i].queue_id % nb_stages;
+
+ if (ev[i].queue_id == tx_queue[ev[i].mbuf->port]) {
+ pipeline_event_tx(dev, port, &ev[i]);
+ ev[i].op = RTE_EVENT_OP_RELEASE;
+ w->processed_pkts++;
+ continue;
+ }
+
+ ev[i].queue_id++;
+ pipeline_fwd_event(&ev[i], cq_id != last_queue ?
+ sched_type_list[cq_id] :
+ RTE_SCHED_TYPE_ATOMIC);
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ }
+
+ return 0;
+}
+
+static __rte_noinline int
+pipeline_queue_worker_multi_stage_burst_fwd(void *arg)
+{
+ PIPELINE_WORKER_MULTI_STAGE_BURST_INIT;
+ const uint8_t *tx_queue = t->tx_evqueue_id;
+
+ while (t->done == false) {
+ uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
+ BURST_SIZE, 0);
+
+ if (!nb_rx) {
+ rte_pause();
+ continue;
+ }
+
+ for (i = 0; i < nb_rx; i++) {
+ rte_prefetch0(ev[i + 1].mbuf);
+ cq_id = ev[i].queue_id % nb_stages;
+
+ if (cq_id == last_queue) {
+ ev[i].queue_id = tx_queue[ev[i].mbuf->port];
+ rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
+ pipeline_fwd_event(&ev[i],
+ RTE_SCHED_TYPE_ATOMIC);
+ w->processed_pkts++;
+ } else {
+ ev[i].queue_id++;
+ pipeline_fwd_event(&ev[i],
+ sched_type_list[cq_id]);
+ }
+ }
+
+ pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+ }
+
+ return 0;
+}
+
+static int
+worker_wrapper(void *arg)
+{
+ struct worker_data *w = arg;
+ struct evt_options *opt = w->t->opt;
+ const bool burst = evt_has_burst_mode(w->dev_id);
+ const bool internal_port = w->t->internal_port;
+ const uint8_t nb_stages = opt->nb_stages;
+ RTE_SET_USED(opt);
+
+ if (nb_stages == 1) {
+ if (!burst && internal_port)
+ return pipeline_queue_worker_single_stage_tx(arg);
+ else if (!burst && !internal_port)
+ return pipeline_queue_worker_single_stage_fwd(arg);
+ else if (burst && internal_port)
+ return pipeline_queue_worker_single_stage_burst_tx(arg);
+ else if (burst && !internal_port)
+ return pipeline_queue_worker_single_stage_burst_fwd(
+ arg);
+ } else {
+ if (!burst && internal_port)
+ return pipeline_queue_worker_multi_stage_tx(arg);
+ else if (!burst && !internal_port)
+ return pipeline_queue_worker_multi_stage_fwd(arg);
+ else if (burst && internal_port)
+ return pipeline_queue_worker_multi_stage_burst_tx(arg);
+ else if (burst && !internal_port)
+ return pipeline_queue_worker_multi_stage_burst_fwd(arg);
+
+ }
+ rte_panic("invalid worker\n");
+}
+
+static int
+pipeline_queue_launch_lcores(struct evt_test *test, struct evt_options *opt)
+{
+ return pipeline_launch_lcores(test, opt, worker_wrapper);
+}
+
+static int
+pipeline_queue_eventdev_setup(struct evt_test *test, struct evt_options *opt)
+{
+ int ret;
+ int nb_ports;
+ int nb_queues;
+ int nb_stages = opt->nb_stages;
+ uint8_t queue;
+ uint8_t tx_evport_id = 0;
+ uint8_t tx_evqueue_id[RTE_MAX_ETHPORTS];
+ uint8_t queue_arr[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t nb_worker_queues = 0;
+ uint16_t prod = 0;
+ struct rte_event_dev_info info;
+ struct test_pipeline *t = evt_test_priv(test);
+
+ nb_ports = evt_nr_active_lcores(opt->wlcores);
+ nb_queues = rte_eth_dev_count_avail() * (nb_stages);
+
+ /* One queue for Tx adapter per port */
+ nb_queues += rte_eth_dev_count_avail();
+
+ memset(tx_evqueue_id, 0, sizeof(uint8_t) * RTE_MAX_ETHPORTS);
+ memset(queue_arr, 0, sizeof(uint8_t) * RTE_EVENT_MAX_QUEUES_PER_DEV);
+
+ rte_event_dev_info_get(opt->dev_id, &info);
+ ret = evt_configure_eventdev(opt, nb_queues, nb_ports);
+ if (ret) {
+ evt_err("failed to configure eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+ struct rte_event_queue_conf q_conf = {
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .nb_atomic_flows = opt->nb_flows,
+ .nb_atomic_order_sequences = opt->nb_flows,
+ };
+ /* queue configurations */
+ for (queue = 0; queue < nb_queues; queue++) {
+ uint8_t slot;
+
+ q_conf.event_queue_cfg = 0;
+ slot = queue % (nb_stages + 1);
+ if (slot == nb_stages) {
+ q_conf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
+ if (!t->internal_port) {
+ q_conf.event_queue_cfg =
+ RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
+ }
+ tx_evqueue_id[prod++] = queue;
+ } else {
+ q_conf.schedule_type = opt->sched_type_list[slot];
+ queue_arr[nb_worker_queues] = queue;
+ nb_worker_queues++;
+ }
+
+ ret = rte_event_queue_setup(opt->dev_id, queue, &q_conf);
+ if (ret) {
+ evt_err("failed to setup queue=%d", queue);
+ return ret;
+ }
+ }
+
+ if (opt->wkr_deq_dep > info.max_event_port_dequeue_depth)
+ opt->wkr_deq_dep = info.max_event_port_dequeue_depth;
+
+ /* port configuration */
+ const struct rte_event_port_conf p_conf = {
+ .dequeue_depth = opt->wkr_deq_dep,
+ .enqueue_depth = info.max_event_port_dequeue_depth,
+ .new_event_threshold = info.max_num_events,
+ };
+
+ if (!t->internal_port) {
+ ret = pipeline_event_port_setup(test, opt, queue_arr,
+ nb_worker_queues, p_conf);
+ if (ret)
+ return ret;
+ } else
+ ret = pipeline_event_port_setup(test, opt, NULL, nb_queues,
+ p_conf);
+
+ if (ret)
+ return ret;
+ /*
+ * The pipelines are setup in the following manner:
+ *
+ * eth_dev_count = 2, nb_stages = 2.
+ *
+ * queues = 6
+ * stride = 3
+ *
+ * event queue pipelines:
+ * eth0 -> q0 -> q1 -> (q2->tx)
+ * eth1 -> q3 -> q4 -> (q5->tx)
+ *
+ * q2, q5 configured as ATOMIC | SINGLE_LINK
+ *
+ */
+ ret = pipeline_event_rx_adapter_setup(opt, nb_stages + 1, p_conf);
+ if (ret)
+ return ret;
+
+ ret = pipeline_event_tx_adapter_setup(opt, p_conf);
+ if (ret)
+ return ret;
+
+ if (!evt_has_distributed_sched(opt->dev_id)) {
+ uint32_t service_id;
+ rte_event_dev_service_id_get(opt->dev_id, &service_id);
+ ret = evt_service_setup(service_id);
+ if (ret) {
+ evt_err("No service lcore found to run event dev.");
+ return ret;
+ }
+ }
+
+ /* Connect the tx_evqueue_id to the Tx adapter port */
+ if (!t->internal_port) {
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_event_eth_tx_adapter_event_port_get(prod,
+ &tx_evport_id);
+ if (ret) {
+ evt_err("Unable to get Tx adptr[%d] evprt[%d]",
+ prod, tx_evport_id);
+ return ret;
+ }
+
+ if (rte_event_port_link(opt->dev_id, tx_evport_id,
+ &tx_evqueue_id[prod],
+ NULL, 1) != 1) {
+ evt_err("Unable to link Tx adptr[%d] evprt[%d]",
+ prod, tx_evport_id);
+ return ret;
+ }
+ }
+ }
+
+ ret = rte_event_dev_start(opt->dev_id);
+ if (ret) {
+ evt_err("failed to start eventdev %d", opt->dev_id);
+ return ret;
+ }
+
+
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_eth_dev_start(prod);
+ if (ret) {
+ evt_err("Ethernet dev [%d] failed to start."
+ " Using synthetic producer", prod);
+ return ret;
+ }
+
+ }
+
+ RTE_ETH_FOREACH_DEV(prod) {
+ ret = rte_event_eth_rx_adapter_start(prod);
+ if (ret) {
+ evt_err("Rx adapter[%d] start failed", prod);
+ return ret;
+ }
+
+ ret = rte_event_eth_tx_adapter_start(prod);
+ if (ret) {
+ evt_err("Tx adapter[%d] start failed", prod);
+ return ret;
+ }
+ }
+
+ memcpy(t->tx_evqueue_id, tx_evqueue_id, sizeof(uint8_t) *
+ RTE_MAX_ETHPORTS);
+
+ return 0;
+}
+
+static void
+pipeline_queue_opt_dump(struct evt_options *opt)
+{
+ pipeline_opt_dump(opt, pipeline_queue_nb_event_queues(opt));
+}
+
+static int
+pipeline_queue_opt_check(struct evt_options *opt)
+{
+ return pipeline_opt_check(opt, pipeline_queue_nb_event_queues(opt));
+}
+
+static bool
+pipeline_queue_capability_check(struct evt_options *opt)
+{
+ struct rte_event_dev_info dev_info;
+
+ rte_event_dev_info_get(opt->dev_id, &dev_info);
+ if (dev_info.max_event_queues < pipeline_queue_nb_event_queues(opt) ||
+ dev_info.max_event_ports <
+ evt_nr_active_lcores(opt->wlcores)) {
+ evt_err("not enough eventdev queues=%d/%d or ports=%d/%d",
+ pipeline_queue_nb_event_queues(opt),
+ dev_info.max_event_queues,
+ evt_nr_active_lcores(opt->wlcores),
+ dev_info.max_event_ports);
+ }
+
+ return true;
+}
+
+static const struct evt_test_ops pipeline_queue = {
+ .cap_check = pipeline_queue_capability_check,
+ .opt_check = pipeline_queue_opt_check,
+ .opt_dump = pipeline_queue_opt_dump,
+ .test_setup = pipeline_test_setup,
+ .mempool_setup = pipeline_mempool_setup,
+ .ethdev_setup = pipeline_ethdev_setup,
+ .eventdev_setup = pipeline_queue_eventdev_setup,
+ .launch_lcores = pipeline_queue_launch_lcores,
+ .eventdev_destroy = pipeline_eventdev_destroy,
+ .mempool_destroy = pipeline_mempool_destroy,
+ .ethdev_destroy = pipeline_ethdev_destroy,
+ .test_result = pipeline_test_result,
+ .test_destroy = pipeline_test_destroy,
+};
+
+EVT_TEST_REGISTER(pipeline_queue);
diff --git a/src/spdk/dpdk/app/test-fib/Makefile b/src/spdk/dpdk/app/test-fib/Makefile
new file mode 100644
index 000000000..2ea799c0e
--- /dev/null
+++ b/src/spdk/dpdk/app/test-fib/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_FIB),y)
+
+APP = testfib
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-fib/main.c b/src/spdk/dpdk/app/test-fib/main.c
new file mode 100644
index 000000000..9cf01b16e
--- /dev/null
+++ b/src/spdk/dpdk/app/test-fib/main.c
@@ -0,0 +1,1264 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <getopt.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_ip.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+#include <rte_lpm.h>
+#include <rte_lpm6.h>
+#include <rte_fib.h>
+#include <rte_fib6.h>
+
+#define PRINT_USAGE_START "%s [EAL options] --\n"
+
+#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \
+ unsigned long val; \
+ char *end_fld; \
+ errno = 0; \
+ val = strtoul((in), &end_fld, (base)); \
+ if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \
+ return -EINVAL; \
+ (fd) = (typeof(fd))val; \
+ (in) = end_fld + 1; \
+} while (0)
+
+#define DEF_ROUTES_NUM 0x10000
+#define DEF_LOOKUP_IPS_NUM 0x100000
+#define BURST_SZ 64
+#define DEFAULT_LPM_TBL8 100000U
+
+#define CMP_FLAG (1 << 0)
+#define CMP_ALL_FLAG (1 << 1)
+#define IPV6_FLAG (1 << 2)
+#define FIB_RIB_TYPE (1 << 3)
+#define FIB_V4_DIR_TYPE (1 << 4)
+#define FIB_V6_TRIE_TYPE (1 << 4)
+#define FIB_TYPE_MASK (FIB_RIB_TYPE|FIB_V4_DIR_TYPE|FIB_V6_TRIE_TYPE)
+#define SHUFFLE_FLAG (1 << 7)
+#define DRY_RUN_FLAG (1 << 8)
+
+static char *distrib_string;
+static char line[LINE_MAX];
+
+enum {
+ RT_PREFIX,
+ RT_NEXTHOP,
+ RT_NUM
+};
+
+#ifndef NIPQUAD
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+#define NIPQUAD(addr) \
+ (unsigned)((unsigned char *)&addr)[3], \
+ (unsigned)((unsigned char *)&addr)[2], \
+ (unsigned)((unsigned char *)&addr)[1], \
+ (unsigned)((unsigned char *)&addr)[0]
+
+#define NIPQUAD6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD6(addr) \
+ ((uint8_t *)addr)[0] << 8 | \
+ ((uint8_t *)addr)[1], \
+ ((uint8_t *)addr)[2] << 8 | \
+ ((uint8_t *)addr)[3], \
+ ((uint8_t *)addr)[4] << 8 | \
+ ((uint8_t *)addr)[5], \
+ ((uint8_t *)addr)[6] << 8 | \
+ ((uint8_t *)addr)[7], \
+ ((uint8_t *)addr)[8] << 8 | \
+ ((uint8_t *)addr)[9], \
+ ((uint8_t *)addr)[10] << 8 | \
+ ((uint8_t *)addr)[11], \
+ ((uint8_t *)addr)[12] << 8 | \
+ ((uint8_t *)addr)[13], \
+ ((uint8_t *)addr)[14] << 8 | \
+ ((uint8_t *)addr)[15]
+#endif
+
+static struct {
+ const char *prgname;
+ const char *routes_file;
+ const char *lookup_ips_file;
+ const char *routes_file_s;
+ const char *lookup_ips_file_s;
+ void *rt;
+ void *lookup_tbl;
+ uint32_t nb_routes;
+ uint32_t nb_lookup_ips;
+ uint32_t nb_lookup_ips_rnd;
+ uint32_t nb_routes_per_depth[128 + 1];
+ uint32_t flags;
+ uint32_t tbl8;
+ uint8_t ent_sz;
+ uint8_t rnd_lookup_ips_ratio;
+ uint8_t print_fract;
+} config = {
+ .routes_file = NULL,
+ .lookup_ips_file = NULL,
+ .nb_routes = DEF_ROUTES_NUM,
+ .nb_lookup_ips = DEF_LOOKUP_IPS_NUM,
+ .nb_lookup_ips_rnd = 0,
+ .nb_routes_per_depth = {0},
+ .flags = FIB_V4_DIR_TYPE,
+ .tbl8 = DEFAULT_LPM_TBL8,
+ .ent_sz = 4,
+ .rnd_lookup_ips_ratio = 0,
+ .print_fract = 10
+};
+
+struct rt_rule_4 {
+ uint32_t addr;
+ uint8_t depth;
+ uint64_t nh;
+};
+
+struct rt_rule_6 {
+ uint8_t addr[16];
+ uint8_t depth;
+ uint64_t nh;
+};
+
+static uint64_t
+get_rnd_rng(uint64_t l, uint64_t u)
+{
+ if (l == u)
+ return l;
+ else
+ return (rte_rand() % (u - l) + l);
+}
+
+static __rte_always_inline __attribute__((pure)) uint8_t
+bits_in_nh(uint8_t nh_sz)
+{
+ return 8 * (1 << nh_sz);
+}
+
+static __rte_always_inline __attribute__((pure)) uint64_t
+get_max_nh(uint8_t nh_sz)
+{
+ /* min between fib and lpm6 which is 21 bits */
+ return RTE_MIN(((1ULL << (bits_in_nh(nh_sz) - 1)) - 1),
+ (1ULL << 21) - 1);
+}
+
+static int
+get_fib_type(void)
+{
+ if (config.flags & IPV6_FLAG) {
+ if ((config.flags & FIB_TYPE_MASK) == FIB_V6_TRIE_TYPE)
+ return RTE_FIB6_TRIE;
+ else
+ return RTE_FIB6_DUMMY;
+ } else {
+ if ((config.flags & FIB_TYPE_MASK) == FIB_V4_DIR_TYPE)
+ return RTE_FIB_DIR24_8;
+ if ((config.flags & FIB_TYPE_MASK) == FIB_RIB_TYPE)
+ return RTE_FIB_DUMMY;
+ }
+ return -1;
+}
+
+static int
+complete_distrib(uint8_t depth_lim, const uint32_t n, uint8_t rpd[],
+ uint32_t nrpd[])
+{
+ uint8_t depth;
+ uint32_t nr = 0;
+ uint8_t m = 0;
+
+ /*
+ * complete number of routes for every depth
+ * that was configured with ratio
+ */
+ for (depth = 0; depth <= depth_lim; depth++) {
+ if (rpd[depth] != 0) {
+ if (rpd[depth] == UINT8_MAX)
+ config.nb_routes_per_depth[depth] =
+ nrpd[depth];
+ else
+ config.nb_routes_per_depth[depth] =
+ (n * rpd[depth]) / 100;
+
+ nr += config.nb_routes_per_depth[depth];
+ m++;
+ }
+ }
+
+ if (nr > n) {
+ printf("Too much configured routes\n");
+ return -1;
+ }
+
+ /*complete number of routes for every unspecified depths*/
+ for (depth = 0; depth <= depth_lim; depth++) {
+ if (rpd[depth] == 0) {
+ /*we don't need more than two /1 routes*/
+ uint64_t max_routes_per_depth =
+ 1ULL << RTE_MIN(depth, 63);
+ uint32_t avg_routes_left = (n - nr) /
+ (depth_lim + 1 - m++);
+ config.nb_routes_per_depth[depth] =
+ RTE_MIN(max_routes_per_depth, avg_routes_left);
+ nr += config.nb_routes_per_depth[depth];
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_distrib(uint8_t depth_lim, const uint32_t n)
+{
+ uint8_t rpd[128 + 1] = {0}; /*routes ratios per depth including /0 */
+ uint32_t nrpd[128 + 1] = {0}; /* number of routes per depth */
+ uint32_t n_routes;
+ uint8_t depth, ratio, ratio_acc = 0;
+ char *in;
+
+ in = strtok(distrib_string, ",");
+
+ /*parse configures routes percentage ratios*/
+ while (in != NULL) {
+ GET_CB_FIELD(in, depth, 0, UINT8_MAX, ':');
+ if (in[strlen(in) - 1] == '%') {
+ in[strlen(in) - 1] = 0;
+ GET_CB_FIELD(in, ratio, 0, UINT8_MAX, '\0');
+ if (depth > depth_lim) {
+ printf("Depth /%d is bigger than maximum "
+ "allowed depth /%d for this AF\n",
+ depth, depth_lim);
+ return -EINVAL;
+ }
+ if (ratio > 100) {
+ printf("Ratio for depth /%d is bigger "
+ "than 100%%\n", depth);
+ return -EINVAL;
+ }
+ if ((depth < 64) && ((n * ratio) / 100) >
+ (1ULL << depth)) {
+ printf("Configured ratio %d%% for depth /%d "
+ "has %d different routes, but maximum "
+ "is %lu\n", ratio, depth,
+ ((n * ratio) / 100), (1UL << depth));
+ return -EINVAL;
+ }
+ rpd[depth] = ratio;
+ /*configured zero routes for a given depth*/
+ if (ratio == 0)
+ rpd[depth] = UINT8_MAX;
+ /*sum of all percentage ratios*/
+ ratio_acc += ratio;
+ } else {
+ GET_CB_FIELD(in, n_routes, 0, UINT32_MAX, '\0');
+ rpd[depth] = UINT8_MAX;
+ nrpd[depth] = n_routes;
+ }
+
+ /*number of configured depths in*/
+ in = strtok(NULL, ",");
+ }
+
+ if (ratio_acc > 100) {
+ printf("Total ratio's sum is bigger than 100%%\n");
+ return -EINVAL;
+ }
+
+ return complete_distrib(depth_lim, n, rpd, nrpd);
+}
+
+static void
+shuffle_rt_4(struct rt_rule_4 *rt, int n)
+{
+ struct rt_rule_4 tmp;
+ int i, j;
+
+ for (i = 0; i < n; i++) {
+ j = rte_rand() % n;
+ tmp.addr = rt[i].addr;
+ tmp.depth = rt[i].depth;
+ tmp.nh = rt[i].nh;
+
+ rt[i].addr = rt[j].addr;
+ rt[i].depth = rt[j].depth;
+ rt[i].nh = rt[j].nh;
+
+ rt[j].addr = tmp.addr;
+ rt[j].depth = tmp.depth;
+ rt[j].nh = tmp.nh;
+ }
+}
+
+static void
+shuffle_rt_6(struct rt_rule_6 *rt, int n)
+{
+ struct rt_rule_6 tmp;
+ int i, j;
+
+ for (i = 0; i < n; i++) {
+ j = rte_rand() % n;
+ memcpy(tmp.addr, rt[i].addr, 16);
+ tmp.depth = rt[i].depth;
+ tmp.nh = rt[i].nh;
+
+ memcpy(rt[i].addr, rt[j].addr, 16);
+ rt[i].depth = rt[j].depth;
+ rt[i].nh = rt[j].nh;
+
+ memcpy(rt[j].addr, tmp.addr, 16);
+ rt[j].depth = tmp.depth;
+ rt[j].nh = tmp.nh;
+ }
+}
+
+static void
+gen_random_rt_4(struct rt_rule_4 *rt, int nh_sz)
+{
+ uint32_t i, j, k = 0;
+
+ if (config.nb_routes_per_depth[0] != 0) {
+ rt[k].addr = 0;
+ rt[k].depth = 0;
+ rt[k++].nh = rte_rand() & get_max_nh(nh_sz);
+ }
+
+ for (i = 1; i <= 32; i++) {
+ double edge = 0;
+ double step;
+ step = (double)(1ULL << i) / config.nb_routes_per_depth[i];
+ for (j = 0; j < config.nb_routes_per_depth[i];
+ j++, k++, edge += step) {
+ uint64_t rnd_val = get_rnd_rng((uint64_t)edge,
+ (uint64_t)(edge + step));
+ rt[k].addr = rnd_val << (32 - i);
+ rt[k].depth = i;
+ rt[k].nh = rte_rand() & get_max_nh(nh_sz);
+ }
+ }
+}
+
+static void
+complete_v6_addr(uint32_t *addr, uint32_t rnd, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ addr[i] = rte_rand();
+ addr[i++] = rnd;
+ for (; i < 4; i++)
+ addr[i] = 0;
+}
+
+static void
+gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz)
+{
+ uint32_t a, i, j, k = 0;
+
+ if (config.nb_routes_per_depth[0] != 0) {
+ memset(rt[k].addr, 0, 16);
+ rt[k].depth = 0;
+ rt[k++].nh = rte_rand() & get_max_nh(nh_sz);
+ }
+
+ for (a = 0; a < 4; a++) {
+ for (i = 1; i <= 32; i++) {
+ uint32_t rnd;
+ double edge = 0;
+ double step = (double)(1ULL << i) /
+ config.nb_routes_per_depth[(a * 32) + i];
+ for (j = 0; j < config.nb_routes_per_depth[a * 32 + i];
+ j++, k++, edge += step) {
+ uint64_t rnd_val = get_rnd_rng((uint64_t)edge,
+ (uint64_t)(edge + step));
+ rnd = rte_cpu_to_be_32(rnd_val << (32 - i));
+ complete_v6_addr((uint32_t *)rt[k].addr,
+ rnd, a);
+ rt[k].depth = (a * 32) + i;
+ rt[k].nh = rte_rand() & get_max_nh(nh_sz);
+ }
+ }
+ }
+}
+
+static inline void
+set_rnd_ipv6(uint8_t *addr, uint8_t *route, int depth)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ addr[i] = rte_rand();
+
+ for (i = 0; i < 16; i++) {
+ if (depth >= 8)
+ addr[i] = route[i];
+ else if (depth > 0) {
+ addr[i] &= (uint16_t)UINT8_MAX >> depth;
+ addr[i] |= route[i] & UINT8_MAX << (8 - depth);
+ } else
+ return;
+ depth -= 8;
+ }
+}
+
+static void
+gen_rnd_lookup_tbl(int af)
+{
+ uint32_t *tbl4 = config.lookup_tbl;
+ uint8_t *tbl6 = config.lookup_tbl;
+ struct rt_rule_4 *rt4 = (struct rt_rule_4 *)config.rt;
+ struct rt_rule_6 *rt6 = (struct rt_rule_6 *)config.rt;
+ uint32_t i, j;
+
+ if (af == AF_INET) {
+ for (i = 0, j = 0; i < config.nb_lookup_ips;
+ i++, j = (j + 1) % config.nb_routes) {
+ if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) {
+ tbl4[i] = rte_rand();
+ config.nb_lookup_ips_rnd++;
+ } else
+ tbl4[i] = rt4[j].addr | (rte_rand() &
+ ((1ULL << (32 - rt4[j].depth)) - 1));
+ }
+ } else {
+ for (i = 0, j = 0; i < config.nb_lookup_ips;
+ i++, j = (j + 1) % config.nb_routes) {
+ if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) {
+ set_rnd_ipv6(&tbl6[i * 16], rt6[j].addr, 0);
+ config.nb_lookup_ips_rnd++;
+ } else {
+ set_rnd_ipv6(&tbl6[i * 16], rt6[j].addr,
+ rt6[j].depth);
+ }
+ }
+ }
+}
+
+static int
+_inet_net_pton(int af, char *prefix, void *addr)
+{
+ const char *dlm = "/";
+ char *s, *sp;
+ int ret, depth;
+ unsigned int max_depth;
+
+ if ((prefix == NULL) || (addr == NULL))
+ return -EINVAL;
+
+ s = strtok_r(prefix, dlm, &sp);
+ if (s == NULL)
+ return -EINVAL;
+
+ ret = inet_pton(af, s, addr);
+ if (ret != 1)
+ return -errno;
+
+ s = strtok_r(NULL, dlm, &sp);
+ max_depth = (af == AF_INET) ? 32 : 128;
+ GET_CB_FIELD(s, depth, 0, max_depth, 0);
+
+ return depth;
+}
+
+static int
+parse_rt_4(FILE *f)
+{
+ int ret, i, j = 0;
+ char *s, *sp, *in[RT_NUM];
+ static const char *dlm = " \t\n";
+ int string_tok_nb = RTE_DIM(in);
+ struct rt_rule_4 *rt;
+
+ rt = (struct rt_rule_4 *)config.rt;
+
+ while (fgets(line, sizeof(line), f) != NULL) {
+ s = line;
+ for (i = 0; i != string_tok_nb; i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ ret = _inet_net_pton(AF_INET, in[RT_PREFIX], &rt[j].addr);
+ if (ret == -1)
+ return -errno;
+
+ rt[j].addr = rte_be_to_cpu_32(rt[j].addr);
+ rt[j].depth = ret;
+ config.nb_routes_per_depth[ret]++;
+ GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0,
+ UINT32_MAX, 0);
+ j++;
+ }
+ return 0;
+}
+
+static int
+parse_rt_6(FILE *f)
+{
+ int ret, i, j = 0;
+ char *s, *sp, *in[RT_NUM];
+ static const char *dlm = " \t\n";
+ int string_tok_nb = RTE_DIM(in);
+ struct rt_rule_6 *rt;
+
+ rt = (struct rt_rule_6 *)config.rt;
+
+ while (fgets(line, sizeof(line), f) != NULL) {
+ s = line;
+ for (i = 0; i != string_tok_nb; i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ ret = _inet_net_pton(AF_INET6, in[RT_PREFIX], rt[j].addr);
+ if (ret < 0)
+ return ret;
+
+ rt[j].depth = ret;
+ config.nb_routes_per_depth[ret]++;
+ GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0,
+ UINT32_MAX, 0);
+ j++;
+ }
+
+ return 0;
+}
+
+static int
+parse_lookup(FILE *f, int af)
+{
+ int ret, i = 0;
+ uint8_t *tbl = (uint8_t *)config.lookup_tbl;
+ int step = (af == AF_INET) ? 4 : 16;
+ char *s;
+
+ while (fgets(line, sizeof(line), f) != NULL) {
+ s = strtok(line, " \t\n");
+ if (s == NULL)
+ return -EINVAL;
+ ret = inet_pton(af, s, &tbl[i]);
+ if (ret != 1)
+ return -EINVAL;
+ i += step;
+ }
+ return 0;
+}
+
+static int
+dump_lookup(int af)
+{
+ FILE *f;
+ uint32_t *tbl4 = config.lookup_tbl;
+ uint8_t *tbl6 = config.lookup_tbl;
+ uint32_t i;
+
+ f = fopen(config.lookup_ips_file_s, "w");
+ if (f == NULL) {
+ printf("Can not open file %s\n", config.lookup_ips_file_s);
+ return -1;
+ }
+
+ if (af == AF_INET) {
+ for (i = 0; i < config.nb_lookup_ips; i++)
+ fprintf(f, NIPQUAD_FMT"\n", NIPQUAD(tbl4[i]));
+ } else {
+ for (i = 0; i < config.nb_lookup_ips; i++)
+ fprintf(f, NIPQUAD6_FMT"\n", NIPQUAD6(&tbl6[i * 16]));
+ }
+ fclose(f);
+ return 0;
+}
+
+static void
+print_config(void)
+{
+ uint8_t depth_lim;
+ char dlm;
+ int i;
+
+ depth_lim = ((config.flags & IPV6_FLAG) == IPV6_FLAG) ? 128 : 32;
+
+ fprintf(stdout,
+ "Routes total: %u\n"
+ "Routes distribution:\n", config.nb_routes);
+
+ for (i = 1; i <= depth_lim; i++) {
+ fprintf(stdout,
+ "depth /%d:%u", i, config.nb_routes_per_depth[i]);
+ if (i % 4 == 0)
+ dlm = '\n';
+ else
+ dlm = '\t';
+ fprintf(stdout, "%c", dlm);
+ }
+
+ fprintf(stdout,
+ "Lookup tuples: %u\n"
+ "Configured ratios of random ips for lookup: %u\n"
+ "Random lookup ips: %u\n",
+ config.nb_lookup_ips, config.rnd_lookup_ips_ratio,
+ config.nb_lookup_ips_rnd);
+}
+
+static void
+print_usage(void)
+{
+ fprintf(stdout,
+ PRINT_USAGE_START
+ "[-f <routes file>]\n"
+ "[-t <ip's file for lookup>]\n"
+ "[-n <number of routes (if -f is not specified)>]\n"
+ "[-l <number of ip's for lookup (if -t is not specified)>]\n"
+ "[-d <\",\" separated \"depth:n%%\"routes depth distribution"
+ "(if -f is not specified)>]\n"
+ "[-r <percentage ratio of random ip's to lookup"
+ "(if -t is not specified)>]\n"
+ "[-c <do comarison with LPM library>]\n"
+ "[-6 <do tests with ipv6 (default ipv4)>]\n"
+ "[-s <shuffle randomly generated routes>]\n"
+ "[-a <check nexthops for all ipv4 address space"
+ "(only valid with -c)>]\n"
+ "[-b <fib algorithm>]\n\tavailible options for ipv4\n"
+ "\t\trib - RIB based FIB\n"
+ "\t\tdir - DIR24_8 based FIB\n"
+ "\tavailible options for ipv6:\n"
+ "\t\trib - RIB based FIB\n"
+ "\t\ttrie - TRIE based FIB\n"
+ "defaults are: dir for ipv4 and trie for ipv6\n"
+ "[-e <entry size (valid only for dir and trie fib types): "
+ "1/2/4/8 (default 4)>]\n"
+ "[-g <number of tbl8's for dir24_8 or trie FIBs>]\n"
+ "[-w <path to the file to dump routing table>]\n"
+ "[-u <path to the file to dump ip's for lookup>]\n",
+ config.prgname);
+}
+
+static int
+check_config(void)
+{
+ if ((config.routes_file == NULL) && (config.lookup_ips_file != NULL)) {
+ printf("-t option only valid with -f option\n");
+ return -1;
+ }
+
+ if ((config.flags & CMP_ALL_FLAG) && (config.flags & IPV6_FLAG)) {
+ printf("-a flag is only valid for ipv4\n");
+ return -1;
+ }
+
+ if ((config.flags & CMP_ALL_FLAG) &&
+ ((config.flags & CMP_FLAG) != CMP_FLAG)) {
+ printf("-a flag is valid only with -c flag\n");
+ return -1;
+ }
+
+ if (!((config.ent_sz == 1) || (config.ent_sz == 2) ||
+ (config.ent_sz == 4) || (config.ent_sz == 8))) {
+ printf("wrong -e option %d, can be 1 or 2 or 4 or 8\n",
+ config.ent_sz);
+ return -1;
+ }
+
+ if ((config.ent_sz == 1) && (config.flags & IPV6_FLAG)) {
+ printf("-e 1 is valid only for ipv4\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void
+parse_opts(int argc, char **argv)
+{
+ int opt;
+ char *endptr;
+
+ while ((opt = getopt(argc, argv, "f:t:n:d:l:r:c6ab:e:g:w:u:s")) !=
+ -1) {
+ switch (opt) {
+ case 'f':
+ config.routes_file = optarg;
+ break;
+ case 't':
+ config.lookup_ips_file = optarg;
+ break;
+ case 'w':
+ config.routes_file_s = optarg;
+ config.flags |= DRY_RUN_FLAG;
+ break;
+ case 'u':
+ config.lookup_ips_file_s = optarg;
+ config.flags |= DRY_RUN_FLAG;
+ break;
+ case 'n':
+ errno = 0;
+ config.nb_routes = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.nb_routes == 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -n\n");
+ }
+ break;
+ case 'd':
+ distrib_string = optarg;
+ break;
+ case 'l':
+ errno = 0;
+ config.nb_lookup_ips = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.nb_lookup_ips == 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -l\n");
+ }
+ break;
+ case 'r':
+ errno = 0;
+ config.rnd_lookup_ips_ratio =
+ strtoul(optarg, &endptr, 10);
+ if ((errno != 0) ||
+ (config.rnd_lookup_ips_ratio == 0) ||
+ (config.rnd_lookup_ips_ratio >= 100)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -r\n");
+ }
+ break;
+ case 's':
+ config.flags |= SHUFFLE_FLAG;
+ break;
+ case 'c':
+ config.flags |= CMP_FLAG;
+ break;
+ case '6':
+ config.flags |= IPV6_FLAG;
+ break;
+ case 'a':
+ config.flags |= CMP_ALL_FLAG;
+ break;
+ case 'b':
+ if (strcmp(optarg, "rib") == 0) {
+ config.flags &= ~FIB_TYPE_MASK;
+ config.flags |= FIB_RIB_TYPE;
+ } else if (strcmp(optarg, "dir") == 0) {
+ config.flags &= ~FIB_TYPE_MASK;
+ config.flags |= FIB_V4_DIR_TYPE;
+ } else if (strcmp(optarg, "trie") == 0) {
+ config.flags &= ~FIB_TYPE_MASK;
+ config.flags |= FIB_V6_TRIE_TYPE;
+ } else
+ rte_exit(-EINVAL, "Invalid option -b\n");
+ break;
+ case 'e':
+ errno = 0;
+ config.ent_sz = strtoul(optarg, &endptr, 10);
+ if (errno != 0) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -e\n");
+ }
+ break;
+ case 'g':
+ errno = 0;
+ config.tbl8 = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.tbl8 == 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -g\n");
+ }
+ break;
+ default:
+ print_usage();
+ rte_exit(-EINVAL, "Invalid options\n");
+ }
+ }
+}
+
+static int
+dump_rt_4(struct rt_rule_4 *rt)
+{
+ FILE *f;
+ uint32_t i;
+
+ f = fopen(config.routes_file_s, "w");
+ if (f == NULL) {
+ printf("Can not open file %s\n", config.routes_file_s);
+ return -1;
+ }
+
+ for (i = 0; i < config.nb_routes; i++)
+ fprintf(f, NIPQUAD_FMT"/%d %"PRIu64"\n", NIPQUAD(rt[i].addr),
+ rt[i].depth, rt[i].nh);
+
+ fclose(f);
+ return 0;
+}
+
+static inline void
+print_depth_err(void)
+{
+ printf("LPM does not support /0 prefix length (default route), use "
+ "-d 0:0 option or remove /0 prefix from routes file\n");
+}
+
+static int
+run_v4(void)
+{
+ uint64_t start, acc;
+ uint64_t def_nh = 0;
+ struct rte_fib *fib;
+ struct rte_fib_conf conf = {0};
+ struct rt_rule_4 *rt;
+ uint32_t i, j, k;
+ int ret = 0;
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config lpm_conf;
+ uint32_t *tbl4 = config.lookup_tbl;
+ uint64_t fib_nh[BURST_SZ];
+ uint32_t lpm_nh[BURST_SZ];
+
+ rt = (struct rt_rule_4 *)config.rt;
+
+ if (config.flags & DRY_RUN_FLAG) {
+ if (config.routes_file_s != NULL)
+ ret = dump_rt_4(rt);
+ if (ret != 0)
+ return ret;
+ if (config.lookup_ips_file_s != NULL)
+ ret = dump_lookup(AF_INET);
+ return ret;
+ }
+
+ conf.type = get_fib_type();
+ conf.default_nh = def_nh;
+ conf.max_routes = config.nb_routes * 2;
+ if (conf.type == RTE_FIB_DIR24_8) {
+ conf.dir24_8.nh_sz = __builtin_ctz(config.ent_sz);
+ conf.dir24_8.num_tbl8 = RTE_MIN(config.tbl8,
+ get_max_nh(conf.dir24_8.nh_sz));
+ }
+
+ fib = rte_fib_create("test", -1, &conf);
+ if (fib == NULL) {
+ printf("Can not alloc FIB, err %d\n", rte_errno);
+ return -rte_errno;
+ }
+
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++) {
+ ret = rte_fib_add(fib, rt[i + j].addr, rt[i + j].depth,
+ rt[i + j].nh);
+ if (unlikely(ret != 0)) {
+ printf("Can not add a route to FIB, err %d\n",
+ ret);
+ return -ret;
+ }
+ }
+ printf("AVG FIB add %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+
+ if (config.flags & CMP_FLAG) {
+ lpm_conf.max_rules = config.nb_routes * 2;
+ lpm_conf.number_tbl8s = RTE_MAX(conf.dir24_8.num_tbl8,
+ config.tbl8);
+
+ lpm = rte_lpm_create("test_lpm", -1, &lpm_conf);
+ if (lpm == NULL) {
+ printf("Can not alloc LPM, err %d\n", rte_errno);
+ return -rte_errno;
+ }
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++) {
+ ret = rte_lpm_add(lpm, rt[i + j].addr,
+ rt[i + j].depth, rt[i + j].nh);
+ if (ret != 0) {
+ if (rt[i + j].depth == 0)
+ print_depth_err();
+ printf("Can not add a route to LPM, "
+ "err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG LPM add %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+ }
+
+ acc = 0;
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ start = rte_rdtsc_precise();
+ ret = rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ);
+ acc += rte_rdtsc_precise() - start;
+ if (ret != 0) {
+ printf("FIB lookup fails, err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG FIB lookup %.1f\n", (double)acc / (double)i);
+
+ if (config.flags & CMP_FLAG) {
+ acc = 0;
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ start = rte_rdtsc_precise();
+ ret = rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh,
+ BURST_SZ);
+ acc += rte_rdtsc_precise() - start;
+ if (ret != 0) {
+ printf("LPM lookup fails, err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG LPM lookup %.1f\n", (double)acc / (double)i);
+
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ);
+ rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh, BURST_SZ);
+ for (j = 0; j < BURST_SZ; j++) {
+ struct rte_lpm_tbl_entry *tbl;
+ tbl = (struct rte_lpm_tbl_entry *)&lpm_nh[j];
+ if ((fib_nh[j] != tbl->next_hop) &&
+ !((tbl->valid == 0) &&
+ (fib_nh[j] == def_nh))) {
+ printf("FAIL\n");
+ return -1;
+ }
+ }
+ }
+ printf("FIB and LPM lookup returns same values\n");
+ }
+
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++)
+ rte_fib_delete(fib, rt[i + j].addr, rt[i + j].depth);
+
+ printf("AVG FIB delete %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+
+ if (config.flags & CMP_FLAG) {
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++)
+ rte_lpm_delete(lpm, rt[i + j].addr,
+ rt[i + j].depth);
+
+ printf("AVG LPM delete %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+ }
+
+ return 0;
+}
+
+static int
+dump_rt_6(struct rt_rule_6 *rt)
+{
+ FILE *f;
+ uint32_t i;
+
+ f = fopen(config.routes_file_s, "w");
+ if (f == NULL) {
+ printf("Can not open file %s\n", config.routes_file_s);
+ return -1;
+ }
+
+ for (i = 0; i < config.nb_routes; i++) {
+ fprintf(f, NIPQUAD6_FMT"/%d %"PRIu64"\n", NIPQUAD6(rt[i].addr),
+ rt[i].depth, rt[i].nh);
+
+ }
+ fclose(f);
+ return 0;
+}
+
+static int
+run_v6(void)
+{
+ uint64_t start, acc;
+ uint64_t def_nh = 0;
+ struct rte_fib6 *fib;
+ struct rte_fib6_conf conf = {0};
+ struct rt_rule_6 *rt;
+ uint32_t i, j, k;
+ int ret = 0;
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config lpm_conf;
+ uint8_t *tbl6;
+ uint64_t fib_nh[BURST_SZ];
+ int32_t lpm_nh[BURST_SZ];
+
+ rt = (struct rt_rule_6 *)config.rt;
+ tbl6 = config.lookup_tbl;
+
+ if (config.flags & DRY_RUN_FLAG) {
+ if (config.routes_file_s != NULL)
+ ret = dump_rt_6(rt);
+ if (ret != 0)
+ return ret;
+ if (config.lookup_ips_file_s != NULL)
+ ret = dump_lookup(AF_INET6);
+ return ret;
+ }
+
+ conf.type = get_fib_type();
+ conf.default_nh = def_nh;
+ conf.max_routes = config.nb_routes * 2;
+ if (conf.type == RTE_FIB6_TRIE) {
+ conf.trie.nh_sz = __builtin_ctz(config.ent_sz);
+ conf.trie.num_tbl8 = RTE_MIN(config.tbl8,
+ get_max_nh(conf.trie.nh_sz));
+ }
+
+ fib = rte_fib6_create("test", -1, &conf);
+ if (fib == NULL) {
+ printf("Can not alloc FIB, err %d\n", rte_errno);
+ return -rte_errno;
+ }
+
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++) {
+ ret = rte_fib6_add(fib, rt[i + j].addr,
+ rt[i + j].depth, rt[i + j].nh);
+ if (unlikely(ret != 0)) {
+ printf("Can not add a route to FIB, err %d\n",
+ ret);
+ return -ret;
+ }
+ }
+ printf("AVG FIB add %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+
+ if (config.flags & CMP_FLAG) {
+ lpm_conf.max_rules = config.nb_routes * 2;
+ lpm_conf.number_tbl8s = RTE_MAX(conf.trie.num_tbl8,
+ config.tbl8);
+
+ lpm = rte_lpm6_create("test_lpm", -1, &lpm_conf);
+ if (lpm == NULL) {
+ printf("Can not alloc LPM, err %d\n", rte_errno);
+ return -rte_errno;
+ }
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++) {
+ ret = rte_lpm6_add(lpm, rt[i + j].addr,
+ rt[i + j].depth, rt[i + j].nh);
+ if (ret != 0) {
+ if (rt[i + j].depth == 0)
+ print_depth_err();
+ printf("Can not add a route to LPM, "
+ "err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG LPM add %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+ }
+
+ acc = 0;
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ start = rte_rdtsc_precise();
+ ret = rte_fib6_lookup_bulk(fib, (uint8_t (*)[16])(tbl6 + i*16),
+ fib_nh, BURST_SZ);
+ acc += rte_rdtsc_precise() - start;
+ if (ret != 0) {
+ printf("FIB lookup fails, err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG FIB lookup %.1f\n", (double)acc / (double)i);
+
+ if (config.flags & CMP_FLAG) {
+ acc = 0;
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ start = rte_rdtsc_precise();
+ ret = rte_lpm6_lookup_bulk_func(lpm,
+ (uint8_t (*)[16])(tbl6 + i*16),
+ lpm_nh, BURST_SZ);
+ acc += rte_rdtsc_precise() - start;
+ if (ret != 0) {
+ printf("LPM lookup fails, err %d\n", ret);
+ return -ret;
+ }
+ }
+ printf("AVG LPM lookup %.1f\n", (double)acc / (double)i);
+
+ for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
+ rte_fib6_lookup_bulk(fib,
+ (uint8_t (*)[16])(tbl6 + i*16),
+ fib_nh, BURST_SZ);
+ rte_lpm6_lookup_bulk_func(lpm,
+ (uint8_t (*)[16])(tbl6 + i*16),
+ lpm_nh, BURST_SZ);
+ for (j = 0; j < BURST_SZ; j++) {
+ if ((fib_nh[j] != (uint32_t)lpm_nh[j]) &&
+ !((lpm_nh[j] == -1) &&
+ (fib_nh[j] == def_nh))) {
+ printf("FAIL\n");
+ return -1;
+ }
+ }
+ }
+ printf("FIB and LPM lookup returns same values\n");
+ }
+
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++)
+ rte_fib6_delete(fib, rt[i + j].addr, rt[i + j].depth);
+
+ printf("AVG FIB delete %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+
+ if (config.flags & CMP_FLAG) {
+ for (k = config.print_fract, i = 0; k > 0; k--) {
+ start = rte_rdtsc_precise();
+ for (j = 0; j < (config.nb_routes - i) / k; j++)
+ rte_lpm6_delete(lpm, rt[i + j].addr,
+ rt[i + j].depth);
+
+ printf("AVG LPM delete %"PRIu64"\n",
+ (rte_rdtsc_precise() - start) / j);
+ i += j;
+ }
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret, af, rt_ent_sz, lookup_ent_sz;
+ FILE *fr = NULL;
+ FILE *fl = NULL;
+ uint8_t depth_lim;
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= ret;
+ argv += ret;
+
+ config.prgname = argv[0];
+
+ parse_opts(argc, argv);
+
+ ret = check_config();
+ if (ret != 0)
+ rte_exit(-ret, "Bad configuration\n");
+
+ af = ((config.flags & IPV6_FLAG) == 0) ? AF_INET : AF_INET6;
+ depth_lim = (af == AF_INET) ? 32 : 128;
+ rt_ent_sz = (af == AF_INET) ? sizeof(struct rt_rule_4) :
+ sizeof(struct rt_rule_6);
+ lookup_ent_sz = (af == AF_INET) ? 4 : 16;
+
+ /* Count number of rules in file*/
+ if (config.routes_file != NULL) {
+ fr = fopen(config.routes_file, "r");
+ if (fr == NULL)
+ rte_exit(-errno, "Can not open file with routes %s\n",
+ config.routes_file);
+
+ config.nb_routes = 0;
+ while (fgets(line, sizeof(line), fr) != NULL)
+ config.nb_routes++;
+ rewind(fr);
+ }
+
+ /* Count number of ip's in file*/
+ if (config.lookup_ips_file != NULL) {
+ fl = fopen(config.lookup_ips_file, "r");
+ if (fl == NULL)
+ rte_exit(-errno, "Can not open file with ip's %s\n",
+ config.lookup_ips_file);
+
+ config.nb_lookup_ips = 0;
+ while (fgets(line, sizeof(line), fl) != NULL)
+ config.nb_lookup_ips++;
+ rewind(fl);
+ }
+
+ /* Alloc routes table*/
+ config.rt = rte_malloc(NULL, rt_ent_sz * config.nb_routes, 0);
+ if (config.rt == NULL)
+ rte_exit(-ENOMEM, "Can not alloc rt\n");
+
+ /* Alloc table with ip's for lookup*/
+ config.lookup_tbl = rte_malloc(NULL, lookup_ent_sz *
+ config.nb_lookup_ips, 0);
+ if (config.lookup_tbl == NULL)
+ rte_exit(-ENOMEM, "Can not alloc lookup table\n");
+
+ /* Fill routes table */
+ if (fr == NULL) {
+ if (distrib_string != NULL)
+ ret = parse_distrib(depth_lim, config.nb_routes);
+ else {
+ uint8_t rpd[129] = {0};
+ uint32_t nrpd[129] = {0};
+ ret = complete_distrib(depth_lim, config.nb_routes,
+ rpd, nrpd);
+ }
+ if (ret != 0)
+ rte_exit(-ret,
+ "Bad routes distribution configuration\n");
+ if (af == AF_INET) {
+ gen_random_rt_4(config.rt,
+ __builtin_ctz(config.ent_sz));
+ if (config.flags & SHUFFLE_FLAG)
+ shuffle_rt_4(config.rt, config.nb_routes);
+ } else {
+ gen_random_rt_6(config.rt,
+ __builtin_ctz(config.ent_sz));
+ if (config.flags & SHUFFLE_FLAG)
+ shuffle_rt_6(config.rt, config.nb_routes);
+ }
+ } else {
+ if (af == AF_INET)
+ ret = parse_rt_4(fr);
+ else
+ ret = parse_rt_6(fr);
+
+ if (ret != 0) {
+ rte_exit(-ret, "failed to parse routes file %s\n",
+ config.routes_file);
+ }
+ }
+
+ /* Fill lookup table with ip's*/
+ if (fl == NULL)
+ gen_rnd_lookup_tbl(af);
+ else {
+ ret = parse_lookup(fl, af);
+ if (ret != 0)
+ rte_exit(-ret, "failed to parse lookup file\n");
+ }
+
+ print_config();
+
+ if (af == AF_INET)
+ ret = run_v4();
+ else
+ ret = run_v6();
+
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-fib/meson.build b/src/spdk/dpdk/app/test-fib/meson.build
new file mode 100644
index 000000000..f74ac651c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-fib/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+sources = files('main.c')
+deps += ['fib', 'lpm', 'net']
diff --git a/src/spdk/dpdk/app/test-pipeline/Makefile b/src/spdk/dpdk/app/test-pipeline/Makefile
new file mode 100644
index 000000000..fc3a50440
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/Makefile
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2015 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_PIPELINE),y)
+
+#
+# library name
+#
+APP = testpipeline
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y := main.c
+SRCS-y += config.c
+SRCS-y += init.c
+SRCS-y += runtime.c
+SRCS-y += pipeline_stub.c
+SRCS-y += pipeline_hash.c
+SRCS-y += pipeline_lpm.c
+SRCS-y += pipeline_lpm_ipv6.c
+
+# include ACL lib if available
+SRCS-$(CONFIG_RTE_LIBRTE_ACL) += pipeline_acl.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-pipeline/config.c b/src/spdk/dpdk/app/test-pipeline/config.c
new file mode 100644
index 000000000..33f3f1c82
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/config.c
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_lpm6.h>
+#include <rte_string_fns.h>
+
+#include "main.h"
+
+static const char usage[] = "\n";
+
+void
+app_print_usage(void)
+{
+ printf(usage);
+}
+
+static int
+app_parse_port_mask(const char *arg)
+{
+ char *end = NULL;
+ uint64_t port_mask;
+ uint32_t i;
+
+ if (arg[0] == '\0')
+ return -1;
+
+ port_mask = strtoul(arg, &end, 16);
+ if ((end == NULL) || (*end != '\0'))
+ return -2;
+
+ if (port_mask == 0)
+ return -3;
+
+ app.n_ports = 0;
+ for (i = 0; i < 64; i++) {
+ if ((port_mask & (1LLU << i)) == 0)
+ continue;
+
+ if (app.n_ports >= APP_MAX_PORTS)
+ return -4;
+
+ app.ports[app.n_ports] = i;
+ app.n_ports++;
+ }
+
+ if (!rte_is_power_of_2(app.n_ports))
+ return -5;
+
+ return 0;
+}
+
+struct {
+ const char *name;
+ uint32_t value;
+} app_args_table[] = {
+ {"none", e_APP_PIPELINE_NONE},
+ {"stub", e_APP_PIPELINE_STUB},
+ {"hash-8-ext", e_APP_PIPELINE_HASH_KEY8_EXT},
+ {"hash-8-lru", e_APP_PIPELINE_HASH_KEY8_LRU},
+ {"hash-16-ext", e_APP_PIPELINE_HASH_KEY16_EXT},
+ {"hash-16-lru", e_APP_PIPELINE_HASH_KEY16_LRU},
+ {"hash-32-ext", e_APP_PIPELINE_HASH_KEY32_EXT},
+ {"hash-32-lru", e_APP_PIPELINE_HASH_KEY32_LRU},
+ {"hash-spec-8-ext", e_APP_PIPELINE_HASH_SPEC_KEY8_EXT},
+ {"hash-spec-8-lru", e_APP_PIPELINE_HASH_SPEC_KEY8_LRU},
+ {"hash-spec-16-ext", e_APP_PIPELINE_HASH_SPEC_KEY16_EXT},
+ {"hash-spec-16-lru", e_APP_PIPELINE_HASH_SPEC_KEY16_LRU},
+ {"hash-spec-32-ext", e_APP_PIPELINE_HASH_SPEC_KEY32_EXT},
+ {"hash-spec-32-lru", e_APP_PIPELINE_HASH_SPEC_KEY32_LRU},
+ {"acl", e_APP_PIPELINE_ACL},
+ {"lpm", e_APP_PIPELINE_LPM},
+ {"lpm-ipv6", e_APP_PIPELINE_LPM_IPV6},
+ {"hash-cuckoo-8", e_APP_PIPELINE_HASH_CUCKOO_KEY8},
+ {"hash-cuckoo-16", e_APP_PIPELINE_HASH_CUCKOO_KEY16},
+ {"hash-cuckoo-32", e_APP_PIPELINE_HASH_CUCKOO_KEY32},
+ {"hash-cuckoo-48", e_APP_PIPELINE_HASH_CUCKOO_KEY48},
+ {"hash-cuckoo-64", e_APP_PIPELINE_HASH_CUCKOO_KEY64},
+ {"hash-cuckoo-80", e_APP_PIPELINE_HASH_CUCKOO_KEY80},
+ {"hash-cuckoo-96", e_APP_PIPELINE_HASH_CUCKOO_KEY96},
+ {"hash-cuckoo-112", e_APP_PIPELINE_HASH_CUCKOO_KEY112},
+ {"hash-cuckoo-128", e_APP_PIPELINE_HASH_CUCKOO_KEY128},
+};
+
+int
+app_parse_args(int argc, char **argv)
+{
+ int opt, ret;
+ char **argvopt;
+ int option_index;
+ char *prgname = argv[0];
+ static struct option lgopts[] = {
+ {"none", 0, 0, 0},
+ {"stub", 0, 0, 0},
+ {"hash-8-ext", 0, 0, 0},
+ {"hash-8-lru", 0, 0, 0},
+ {"hash-16-ext", 0, 0, 0},
+ {"hash-16-lru", 0, 0, 0},
+ {"hash-32-ext", 0, 0, 0},
+ {"hash-32-lru", 0, 0, 0},
+ {"hash-spec-8-ext", 0, 0, 0},
+ {"hash-spec-8-lru", 0, 0, 0},
+ {"hash-spec-16-ext", 0, 0, 0},
+ {"hash-spec-16-lru", 0, 0, 0},
+ {"hash-spec-32-ext", 0, 0, 0},
+ {"hash-spec-32-lru", 0, 0, 0},
+ {"acl", 0, 0, 0},
+ {"lpm", 0, 0, 0},
+ {"lpm-ipv6", 0, 0, 0},
+ {"hash-cuckoo-8", 0, 0, 0},
+ {"hash-cuckoo-16", 0, 0, 0},
+ {"hash-cuckoo-32", 0, 0, 0},
+ {"hash-cuckoo-48", 0, 0, 0},
+ {"hash-cuckoo-64", 0, 0, 0},
+ {"hash-cuckoo-80", 0, 0, 0},
+ {"hash-cuckoo-96", 0, 0, 0},
+ {"hash-cuckoo-112", 0, 0, 0},
+ {"hash-cuckoo-128", 0, 0, 0},
+ {NULL, 0, 0, 0}
+ };
+ uint32_t lcores[3], n_lcores, lcore_id, pipeline_type_provided;
+
+ /* EAL args */
+ n_lcores = 0;
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (rte_lcore_is_enabled(lcore_id) == 0)
+ continue;
+
+ if (n_lcores >= 3) {
+ RTE_LOG(ERR, USER1, "Number of cores must be 3\n");
+ app_print_usage();
+ return -1;
+ }
+
+ lcores[n_lcores] = lcore_id;
+ n_lcores++;
+ }
+
+ if (n_lcores != 3) {
+ RTE_LOG(ERR, USER1, "Number of cores must be 3\n");
+ app_print_usage();
+ return -1;
+ }
+
+ app.core_rx = lcores[0];
+ app.core_worker = lcores[1];
+ app.core_tx = lcores[2];
+
+ /* Non-EAL args */
+ argvopt = argv;
+
+ app.pipeline_type = e_APP_PIPELINE_HASH_KEY16_LRU;
+ pipeline_type_provided = 0;
+
+ while ((opt = getopt_long(argc, argvopt, "p:",
+ lgopts, &option_index)) != EOF) {
+ switch (opt) {
+ case 'p':
+ if (app_parse_port_mask(optarg) < 0) {
+ app_print_usage();
+ return -1;
+ }
+ break;
+
+ case 0: /* long options */
+ if (!pipeline_type_provided) {
+ uint32_t i;
+
+ for (i = 0; i < e_APP_PIPELINES; i++) {
+ if (!strcmp(lgopts[option_index].name,
+ app_args_table[i].name)) {
+ app.pipeline_type =
+ app_args_table[i].value;
+ pipeline_type_provided = 1;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ app_print_usage();
+ return -1;
+
+ default:
+ return -1;
+ }
+ }
+
+ if (optind >= 0)
+ argv[optind - 1] = prgname;
+
+ ret = optind - 1;
+ optind = 1; /* reset getopt lib */
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/init.c b/src/spdk/dpdk/app/test-pipeline/init.c
new file mode 100644
index 000000000..67d54ae05
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/init.c
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_lpm6.h>
+
+#include "main.h"
+
+struct app_params app = {
+ /* Ports*/
+ .n_ports = APP_MAX_PORTS,
+ .port_rx_ring_size = 128,
+ .port_tx_ring_size = 512,
+
+ /* Rings */
+ .ring_rx_size = 128,
+ .ring_tx_size = 128,
+
+ /* Buffer pool */
+ .pool_buffer_size = 2048 + RTE_PKTMBUF_HEADROOM,
+ .pool_size = 32 * 1024,
+ .pool_cache_size = 256,
+
+ /* Burst sizes */
+ .burst_size_rx_read = 64,
+ .burst_size_rx_write = 64,
+ .burst_size_worker_read = 64,
+ .burst_size_worker_write = 64,
+ .burst_size_tx_read = 64,
+ .burst_size_tx_write = 64,
+};
+
+static struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .split_hdr_size = 0,
+ .offloads = DEV_RX_OFFLOAD_CHECKSUM,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IP,
+ },
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+};
+
+static struct rte_eth_rxconf rx_conf = {
+ .rx_thresh = {
+ .pthresh = 8,
+ .hthresh = 8,
+ .wthresh = 4,
+ },
+ .rx_free_thresh = 64,
+ .rx_drop_en = 0,
+};
+
+static struct rte_eth_txconf tx_conf = {
+ .tx_thresh = {
+ .pthresh = 36,
+ .hthresh = 0,
+ .wthresh = 0,
+ },
+ .tx_free_thresh = 0,
+ .tx_rs_thresh = 0,
+};
+
+static void
+app_init_mbuf_pools(void)
+{
+ /* Init the buffer pool */
+ RTE_LOG(INFO, USER1, "Creating the mbuf pool ...\n");
+ app.pool = rte_pktmbuf_pool_create("mempool", app.pool_size,
+ app.pool_cache_size, 0, app.pool_buffer_size, rte_socket_id());
+ if (app.pool == NULL)
+ rte_panic("Cannot create mbuf pool\n");
+}
+
+static void
+app_init_rings(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < app.n_ports; i++) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "app_ring_rx_%u", i);
+
+ app.rings_rx[i] = rte_ring_create(
+ name,
+ app.ring_rx_size,
+ rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+
+ if (app.rings_rx[i] == NULL)
+ rte_panic("Cannot create RX ring %u\n", i);
+ }
+
+ for (i = 0; i < app.n_ports; i++) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "app_ring_tx_%u", i);
+
+ app.rings_tx[i] = rte_ring_create(
+ name,
+ app.ring_tx_size,
+ rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+
+ if (app.rings_tx[i] == NULL)
+ rte_panic("Cannot create TX ring %u\n", i);
+ }
+
+}
+
+static void
+app_ports_check_link(void)
+{
+ uint32_t all_ports_up, i;
+
+ all_ports_up = 1;
+
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_eth_link link;
+ uint16_t port;
+ int ret;
+
+ port = app.ports[i];
+ memset(&link, 0, sizeof(link));
+ ret = rte_eth_link_get_nowait(port, &link);
+ if (ret < 0) {
+ RTE_LOG(INFO, USER1,
+ "Failed to get port %u link status: %s\n",
+ port, rte_strerror(-ret));
+ all_ports_up = 0;
+ continue;
+ }
+
+ RTE_LOG(INFO, USER1, "Port %u (%u Gbps) %s\n",
+ port,
+ link.link_speed / 1000,
+ link.link_status ? "UP" : "DOWN");
+
+ if (link.link_status == ETH_LINK_DOWN)
+ all_ports_up = 0;
+ }
+
+ if (all_ports_up == 0)
+ rte_panic("Some NIC ports are DOWN\n");
+}
+
+static void
+app_init_ports(void)
+{
+ uint32_t i;
+
+ /* Init NIC ports, then start the ports */
+ for (i = 0; i < app.n_ports; i++) {
+ uint16_t port;
+ int ret;
+
+ port = app.ports[i];
+ RTE_LOG(INFO, USER1, "Initializing NIC port %u ...\n", port);
+
+ /* Init port */
+ ret = rte_eth_dev_configure(
+ port,
+ 1,
+ 1,
+ &port_conf);
+ if (ret < 0)
+ rte_panic("Cannot init NIC port %u (%d)\n", port, ret);
+
+ ret = rte_eth_promiscuous_enable(port);
+ if (ret != 0)
+ rte_panic("Cannot enable promiscuous mode for port %u: %s\n",
+ port, rte_strerror(-ret));
+
+ /* Init RX queues */
+ ret = rte_eth_rx_queue_setup(
+ port,
+ 0,
+ app.port_rx_ring_size,
+ rte_eth_dev_socket_id(port),
+ &rx_conf,
+ app.pool);
+ if (ret < 0)
+ rte_panic("Cannot init RX for port %u (%d)\n",
+ (uint32_t) port, ret);
+
+ /* Init TX queues */
+ ret = rte_eth_tx_queue_setup(
+ port,
+ 0,
+ app.port_tx_ring_size,
+ rte_eth_dev_socket_id(port),
+ &tx_conf);
+ if (ret < 0)
+ rte_panic("Cannot init TX for port %u (%d)\n",
+ (uint32_t) port, ret);
+
+ /* Start port */
+ ret = rte_eth_dev_start(port);
+ if (ret < 0)
+ rte_panic("Cannot start port %u (%d)\n", port, ret);
+ }
+
+ app_ports_check_link();
+}
+
+void
+app_init(void)
+{
+ app_init_mbuf_pools();
+ app_init_rings();
+ app_init_ports();
+
+ RTE_LOG(INFO, USER1, "Initialization completed\n");
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/main.c b/src/spdk/dpdk/app/test-pipeline/main.c
new file mode 100644
index 000000000..7f0d6d3f1
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/main.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_lpm6.h>
+
+#include "main.h"
+
+int
+main(int argc, char **argv)
+{
+ uint32_t lcore;
+ int ret;
+
+ /* Init EAL */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ return -1;
+ argc -= ret;
+ argv += ret;
+
+ /* Parse application arguments (after the EAL ones) */
+ ret = app_parse_args(argc, argv);
+ if (ret < 0) {
+ app_print_usage();
+ return -1;
+ }
+
+ /* Init */
+ app_init();
+
+ /* Launch per-lcore init on every lcore */
+ rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(lcore) {
+ if (rte_eal_wait_lcore(lcore) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+app_lcore_main_loop(__rte_unused void *arg)
+{
+ unsigned lcore;
+
+ lcore = rte_lcore_id();
+
+ if (lcore == app.core_rx) {
+ switch (app.pipeline_type) {
+ case e_APP_PIPELINE_ACL:
+ app_main_loop_rx();
+ return 0;
+
+ default:
+ app_main_loop_rx_metadata();
+ return 0;
+ }
+ }
+
+ if (lcore == app.core_worker) {
+ switch (app.pipeline_type) {
+ case e_APP_PIPELINE_STUB:
+ app_main_loop_worker_pipeline_stub();
+ return 0;
+
+ case e_APP_PIPELINE_HASH_KEY8_EXT:
+ case e_APP_PIPELINE_HASH_KEY8_LRU:
+ case e_APP_PIPELINE_HASH_KEY16_EXT:
+ case e_APP_PIPELINE_HASH_KEY16_LRU:
+ case e_APP_PIPELINE_HASH_KEY32_EXT:
+ case e_APP_PIPELINE_HASH_KEY32_LRU:
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT:
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU:
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT:
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU:
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT:
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU:
+ /* cases for cuckoo hash table types */
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY8:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY16:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY32:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY48:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY64:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY80:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY96:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY112:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY128:
+ app_main_loop_worker_pipeline_hash();
+ return 0;
+
+ case e_APP_PIPELINE_ACL:
+#ifndef RTE_LIBRTE_ACL
+ rte_exit(EXIT_FAILURE, "ACL not present in build\n");
+#else
+ app_main_loop_worker_pipeline_acl();
+ return 0;
+#endif
+
+ case e_APP_PIPELINE_LPM:
+ app_main_loop_worker_pipeline_lpm();
+ return 0;
+
+ case e_APP_PIPELINE_LPM_IPV6:
+ app_main_loop_worker_pipeline_lpm_ipv6();
+ return 0;
+
+ case e_APP_PIPELINE_NONE:
+ default:
+ app_main_loop_worker();
+ return 0;
+ }
+ }
+
+ if (lcore == app.core_tx) {
+ app_main_loop_tx();
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/main.h b/src/spdk/dpdk/app/test-pipeline/main.h
new file mode 100644
index 000000000..59dcfddbf
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/main.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#ifndef APP_MBUF_ARRAY_SIZE
+#define APP_MBUF_ARRAY_SIZE 256
+#endif
+
+struct app_mbuf_array {
+ struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE];
+ uint16_t n_mbufs;
+};
+
+#ifndef APP_MAX_PORTS
+#define APP_MAX_PORTS 4
+#endif
+
+struct app_params {
+ /* CPU cores */
+ uint32_t core_rx;
+ uint32_t core_worker;
+ uint32_t core_tx;
+
+ /* Ports*/
+ uint32_t ports[APP_MAX_PORTS];
+ uint32_t n_ports;
+ uint32_t port_rx_ring_size;
+ uint32_t port_tx_ring_size;
+
+ /* Rings */
+ struct rte_ring *rings_rx[APP_MAX_PORTS];
+ struct rte_ring *rings_tx[APP_MAX_PORTS];
+ uint32_t ring_rx_size;
+ uint32_t ring_tx_size;
+
+ /* Internal buffers */
+ struct app_mbuf_array mbuf_rx;
+ struct app_mbuf_array mbuf_tx[APP_MAX_PORTS];
+
+ /* Buffer pool */
+ struct rte_mempool *pool;
+ uint32_t pool_buffer_size;
+ uint32_t pool_size;
+ uint32_t pool_cache_size;
+
+ /* Burst sizes */
+ uint32_t burst_size_rx_read;
+ uint32_t burst_size_rx_write;
+ uint32_t burst_size_worker_read;
+ uint32_t burst_size_worker_write;
+ uint32_t burst_size_tx_read;
+ uint32_t burst_size_tx_write;
+
+ /* App behavior */
+ uint32_t pipeline_type;
+} __rte_cache_aligned;
+
+extern struct app_params app;
+
+int app_parse_args(int argc, char **argv);
+void app_print_usage(void);
+void app_init(void);
+int app_lcore_main_loop(void *arg);
+
+/* Pipeline */
+enum {
+ e_APP_PIPELINE_NONE = 0,
+ e_APP_PIPELINE_STUB,
+
+ e_APP_PIPELINE_HASH_KEY8_EXT,
+ e_APP_PIPELINE_HASH_KEY8_LRU,
+ e_APP_PIPELINE_HASH_KEY16_EXT,
+ e_APP_PIPELINE_HASH_KEY16_LRU,
+ e_APP_PIPELINE_HASH_KEY32_EXT,
+ e_APP_PIPELINE_HASH_KEY32_LRU,
+
+ e_APP_PIPELINE_HASH_SPEC_KEY8_EXT,
+ e_APP_PIPELINE_HASH_SPEC_KEY8_LRU,
+ e_APP_PIPELINE_HASH_SPEC_KEY16_EXT,
+ e_APP_PIPELINE_HASH_SPEC_KEY16_LRU,
+ e_APP_PIPELINE_HASH_SPEC_KEY32_EXT,
+ e_APP_PIPELINE_HASH_SPEC_KEY32_LRU,
+
+ e_APP_PIPELINE_ACL,
+ e_APP_PIPELINE_LPM,
+ e_APP_PIPELINE_LPM_IPV6,
+
+ e_APP_PIPELINE_HASH_CUCKOO_KEY8,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY16,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY32,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY48,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY64,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY80,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY96,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY112,
+ e_APP_PIPELINE_HASH_CUCKOO_KEY128,
+ e_APP_PIPELINES
+};
+
+void app_main_loop_rx(void);
+void app_main_loop_rx_metadata(void);
+uint64_t test_hash(void *key,
+ void *key_mask,
+ uint32_t key_size,
+ uint64_t seed);
+
+uint32_t test_hash_cuckoo(const void *key,
+ uint32_t key_size,
+ uint32_t seed);
+
+void app_main_loop_worker(void);
+void app_main_loop_worker_pipeline_stub(void);
+void app_main_loop_worker_pipeline_hash(void);
+void app_main_loop_worker_pipeline_acl(void);
+void app_main_loop_worker_pipeline_lpm(void);
+void app_main_loop_worker_pipeline_lpm_ipv6(void);
+
+void app_main_loop_tx(void);
+
+#define APP_FLUSH 0
+#ifndef APP_FLUSH
+#define APP_FLUSH 0x3FF
+#endif
+
+#define APP_METADATA_OFFSET(offset) (sizeof(struct rte_mbuf) + (offset))
+
+#endif /* _MAIN_H_ */
diff --git a/src/spdk/dpdk/app/test-pipeline/meson.build b/src/spdk/dpdk/app/test-pipeline/meson.build
new file mode 100644
index 000000000..d5eddaba9
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/meson.build
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+sources = files(
+ 'config.c',
+ 'init.c',
+ 'main.c',
+ 'pipeline_acl.c',
+ 'pipeline_hash.c',
+ 'pipeline_lpm.c',
+ 'pipeline_lpm_ipv6.c',
+ 'pipeline_stub.c',
+ 'runtime.c')
+deps += ['pipeline', 'pci']
diff --git a/src/spdk/dpdk/app/test-pipeline/pipeline_acl.c b/src/spdk/dpdk/app/test-pipeline/pipeline_acl.c
new file mode 100644
index 000000000..5857bc285
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/pipeline_acl.c
@@ -0,0 +1,249 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_acl.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+};
+
+/*
+ * Here we define the 'shape' of the data we're searching for,
+ * by defining the meta-data of the ACL rules.
+ * in this case, we're defining 5 tuples. IP addresses, ports,
+ * and protocol.
+ */
+struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_FIELD_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, next_proto_id),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_FIELD_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, src_addr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_FIELD_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, dst_addr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr) + sizeof(uint16_t),
+ },
+};
+
+
+
+void
+app_main_loop_worker_pipeline_acl(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1,
+ "Core %u is doing work (pipeline with ACL table)\n",
+ rte_lcore_id());
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.burst_size_worker_read,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings_tx[i],
+ .tx_burst_sz = app.burst_size_worker_write,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ {
+ struct rte_table_acl_params table_acl_params = {
+ .name = "test", /* unique identifier for acl contexts */
+ .n_rules = 1 << 5,
+ .n_rule_fields = DIM(ipv4_field_formats),
+ };
+
+ /* Copy in the rule meta-data defined above into the params */
+ memcpy(table_acl_params.field_format, ipv4_field_formats,
+ sizeof(ipv4_field_formats));
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_acl_ops,
+ .arg_create = &table_acl_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the ACL table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Add entries to tables */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_entry table_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i & (app.n_ports - 1)]},
+ };
+ struct rte_table_acl_rule_add_params rule_params;
+ struct rte_pipeline_table_entry *entry_ptr;
+ int key_found, ret;
+
+ memset(&rule_params, 0, sizeof(rule_params));
+
+ /* Set the rule values */
+ rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0;
+ rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0;
+ rule_params.field_value[DST_FIELD_IPV4].value.u32 =
+ i << (24 - __builtin_popcount(app.n_ports - 1));
+ rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 =
+ 8 + __builtin_popcount(app.n_ports - 1);
+ rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0;
+ rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
+ UINT16_MAX;
+ rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0;
+ rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
+ UINT16_MAX;
+ rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0;
+ rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0;
+
+ rule_params.priority = 0;
+
+ uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4].
+ value.u32;
+ uint32_t dst_mask =
+ rule_params.field_value[DST_FIELD_IPV4].mask_range.u32;
+
+ printf("Adding rule to ACL table (IPv4 destination = "
+ "%u.%u.%u.%u/%u => port out = %u)\n",
+ (dst_addr & 0xFF000000) >> 24,
+ (dst_addr & 0x00FF0000) >> 16,
+ (dst_addr & 0x0000FF00) >> 8,
+ dst_addr & 0x000000FF,
+ dst_mask,
+ table_entry.port_id);
+
+ /* For ACL, add needs an rte_table_acl_rule_add_params struct */
+ ret = rte_pipeline_table_entry_add(p, table_id, &rule_params,
+ &table_entry, &key_found, &entry_ptr);
+ if (ret < 0)
+ rte_panic("Unable to add entry to table %u (%d)\n",
+ table_id, ret);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Run-time */
+#if APP_FLUSH == 0
+ for ( ; ; )
+ rte_pipeline_run(p);
+#else
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+#endif
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/pipeline_hash.c b/src/spdk/dpdk/app/test-pipeline/pipeline_hash.c
new file mode 100644
index 000000000..2dd8928d4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/pipeline_hash.c
@@ -0,0 +1,469 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_hash.h>
+#include <rte_hash.h>
+#include <rte_table_hash_cuckoo.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+static void
+translate_options(uint32_t *special, uint32_t *ext, uint32_t *key_size)
+{
+ switch (app.pipeline_type) {
+ case e_APP_PIPELINE_HASH_KEY8_EXT:
+ *special = 0; *ext = 1; *key_size = 8; return;
+ case e_APP_PIPELINE_HASH_KEY8_LRU:
+ *special = 0; *ext = 0; *key_size = 8; return;
+ case e_APP_PIPELINE_HASH_KEY16_EXT:
+ *special = 0; *ext = 1; *key_size = 16; return;
+ case e_APP_PIPELINE_HASH_KEY16_LRU:
+ *special = 0; *ext = 0; *key_size = 16; return;
+ case e_APP_PIPELINE_HASH_KEY32_EXT:
+ *special = 0; *ext = 1; *key_size = 32; return;
+ case e_APP_PIPELINE_HASH_KEY32_LRU:
+ *special = 0; *ext = 0; *key_size = 32; return;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT:
+ *special = 1; *ext = 1; *key_size = 8; return;
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU:
+ *special = 1; *ext = 0; *key_size = 8; return;
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT:
+ *special = 1; *ext = 1; *key_size = 16; return;
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU:
+ *special = 1; *ext = 0; *key_size = 16; return;
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT:
+ *special = 1; *ext = 1; *key_size = 32; return;
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU:
+ *special = 1; *ext = 0; *key_size = 32; return;
+
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY8:
+ *special = 0; *ext = 0; *key_size = 8; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY16:
+ *special = 0; *ext = 0; *key_size = 16; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY32:
+ *special = 0; *ext = 0; *key_size = 32; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY48:
+ *special = 0; *ext = 0; *key_size = 48; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY64:
+ *special = 0; *ext = 0; *key_size = 64; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY80:
+ *special = 0; *ext = 0; *key_size = 80; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY96:
+ *special = 0; *ext = 0; *key_size = 96; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY112:
+ *special = 0; *ext = 0; *key_size = 112; return;
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY128:
+ *special = 0; *ext = 0; *key_size = 128; return;
+
+ default:
+ rte_panic("Invalid hash table type or key size\n");
+ }
+}
+void
+app_main_loop_worker_pipeline_hash(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+ uint32_t special, ext, key_size;
+
+ translate_options(&special, &ext, &key_size);
+
+ RTE_LOG(INFO, USER1, "Core %u is doing work "
+ "(pipeline with hash table, %s, %s, %d-byte key)\n",
+ rte_lcore_id(),
+ special ? "specialized" : "non-specialized",
+ ext ? "extendible bucket" : "LRU",
+ key_size);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.burst_size_worker_read,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings_tx[i],
+ .tx_burst_sz = app.burst_size_worker_write,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ struct rte_table_hash_params table_hash_params = {
+ .name = "TABLE",
+ .key_size = key_size,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 24,
+ .n_buckets = 1 << 22,
+ .f_hash = test_hash,
+ .seed = 0,
+ };
+
+ struct rte_table_hash_cuckoo_params table_hash_cuckoo_params = {
+ .name = "TABLE",
+ .key_size = key_size,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 24,
+ .n_buckets = 1 << 22,
+ .f_hash = test_hash_cuckoo,
+ .seed = 0,
+ };
+
+ /* Table configuration */
+ switch (app.pipeline_type) {
+ case e_APP_PIPELINE_HASH_KEY8_EXT:
+ case e_APP_PIPELINE_HASH_KEY16_EXT:
+ case e_APP_PIPELINE_HASH_KEY32_EXT:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_ext_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_KEY8_LRU:
+ case e_APP_PIPELINE_HASH_KEY16_LRU:
+ case e_APP_PIPELINE_HASH_KEY32_LRU:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_lru_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_EXT:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key8_ext_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY8_LRU:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key8_lru_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_EXT:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key16_ext_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table)\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY16_LRU:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key16_lru_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_EXT:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key32_ext_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+
+ case e_APP_PIPELINE_HASH_SPEC_KEY32_LRU:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_key32_lru_ops,
+ .arg_create = &table_hash_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY8:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY16:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY32:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY48:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY64:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY80:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY96:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY112:
+ case e_APP_PIPELINE_HASH_CUCKOO_KEY128:
+ {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_hash_cuckoo_ops,
+ .arg_create = &table_hash_cuckoo_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the hash table\n");
+ }
+ break;
+
+ default:
+ rte_panic("Invalid hash table type or key size\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Add entries to tables */
+ for (i = 0; i < (1 << 24); i++) {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i & (app.n_ports - 1)]},
+ };
+ struct rte_pipeline_table_entry *entry_ptr;
+ uint8_t key[32];
+ uint32_t *k32 = (uint32_t *) key;
+ int key_found, status;
+
+ memset(key, 0, sizeof(key));
+ k32[0] = rte_be_to_cpu_32(i);
+
+ status = rte_pipeline_table_entry_add(p, table_id, key, &entry,
+ &key_found, &entry_ptr);
+ if (status < 0)
+ rte_panic("Unable to add entry to table %u (%d)\n",
+ table_id, status);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Run-time */
+#if APP_FLUSH == 0
+ for ( ; ; )
+ rte_pipeline_run(p);
+#else
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+#endif
+}
+
+uint64_t test_hash(
+ void *key,
+ __rte_unused void *key_mask,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint64_t seed)
+{
+ uint32_t *k32 = key;
+ uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
+ uint64_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30);
+
+ return signature;
+}
+
+uint32_t test_hash_cuckoo(
+ const void *key,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint32_t seed)
+{
+ const uint32_t *k32 = key;
+ uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
+ uint32_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30);
+
+ return signature;
+}
+
+void
+app_main_loop_rx_metadata(void) {
+ uint32_t i, j;
+ int ret;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing RX (with meta-data)\n",
+ rte_lcore_id());
+
+ for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
+ uint16_t n_mbufs;
+
+ n_mbufs = rte_eth_rx_burst(
+ app.ports[i],
+ 0,
+ app.mbuf_rx.array,
+ app.burst_size_rx_read);
+
+ if (n_mbufs == 0)
+ continue;
+
+ for (j = 0; j < n_mbufs; j++) {
+ struct rte_mbuf *m;
+ uint8_t *m_data, *key;
+ struct rte_ipv4_hdr *ip_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ uint32_t ip_dst;
+ uint8_t *ipv6_dst;
+ uint32_t *signature, *k32;
+
+ m = app.mbuf_rx.array[j];
+ m_data = rte_pktmbuf_mtod(m, uint8_t *);
+ signature = RTE_MBUF_METADATA_UINT32_PTR(m,
+ APP_METADATA_OFFSET(0));
+ key = RTE_MBUF_METADATA_UINT8_PTR(m,
+ APP_METADATA_OFFSET(32));
+
+ if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
+ ip_hdr = (struct rte_ipv4_hdr *)
+ &m_data[sizeof(struct rte_ether_hdr)];
+ ip_dst = ip_hdr->dst_addr;
+
+ k32 = (uint32_t *) key;
+ k32[0] = ip_dst & 0xFFFFFF00;
+ } else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {
+ ipv6_hdr = (struct rte_ipv6_hdr *)
+ &m_data[sizeof(struct rte_ether_hdr)];
+ ipv6_dst = ipv6_hdr->dst_addr;
+
+ memcpy(key, ipv6_dst, 16);
+ } else
+ continue;
+
+ *signature = test_hash(key, NULL, 0, 0);
+ }
+
+ do {
+ ret = rte_ring_sp_enqueue_bulk(
+ app.rings_rx[i],
+ (void **) app.mbuf_rx.array,
+ n_mbufs,
+ NULL);
+ } while (ret == 0);
+ }
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/pipeline_lpm.c b/src/spdk/dpdk/app/test-pipeline/pipeline_lpm.c
new file mode 100644
index 000000000..8add5e71b
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/pipeline_lpm.c
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_lpm.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+#ifndef PIPELINE_LPM_TABLE_NUMBER_TABLE8s
+#define PIPELINE_LPM_TABLE_NUMBER_TABLE8s 256
+#endif
+
+void
+app_main_loop_worker_pipeline_lpm(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with "
+ "LPM table)\n", rte_lcore_id());
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.burst_size_worker_read,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings_tx[i],
+ .tx_burst_sz = app.burst_size_worker_write,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ {
+ struct rte_table_lpm_params table_lpm_params = {
+ .name = "LPM",
+ .n_rules = 1 << 24,
+ .number_tbl8s = PIPELINE_LPM_TABLE_NUMBER_TABLE8s,
+ .flags = 0,
+ .entry_unique_size =
+ sizeof(struct rte_pipeline_table_entry),
+ .offset = APP_METADATA_OFFSET(32),
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_lpm_ops,
+ .arg_create = &table_lpm_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the LPM table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Add entries to tables */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i & (app.n_ports - 1)]},
+ };
+
+ struct rte_table_lpm_key key = {
+ .ip = i << (24 - __builtin_popcount(app.n_ports - 1)),
+ .depth = 8 + __builtin_popcount(app.n_ports - 1),
+ };
+
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ int key_found, status;
+
+ printf("Adding rule to LPM table (IPv4 destination = %"
+ PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu8
+ " => port out = %" PRIu32 ")\n",
+ (key.ip & 0xFF000000) >> 24,
+ (key.ip & 0x00FF0000) >> 16,
+ (key.ip & 0x0000FF00) >> 8,
+ key.ip & 0x000000FF,
+ key.depth,
+ i);
+
+ status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
+ &key_found, &entry_ptr);
+ if (status < 0)
+ rte_panic("Unable to add entry to table %u (%d)\n",
+ table_id, status);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Run-time */
+#if APP_FLUSH == 0
+ for ( ; ; )
+ rte_pipeline_run(p);
+#else
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+#endif
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/pipeline_lpm_ipv6.c b/src/spdk/dpdk/app/test-pipeline/pipeline_lpm_ipv6.c
new file mode 100644
index 000000000..26b325180
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/pipeline_lpm_ipv6.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+
+#include <rte_port_ring.h>
+#include <rte_table_lpm_ipv6.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+void
+app_main_loop_worker_pipeline_lpm_ipv6(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id;
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1,
+ "Core %u is doing work (pipeline with IPv6 LPM table)\n",
+ rte_lcore_id());
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.burst_size_worker_read,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings_tx[i],
+ .tx_burst_sz = app.burst_size_worker_write,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ {
+ struct rte_table_lpm_ipv6_params table_lpm_ipv6_params = {
+ .name = "LPM",
+ .n_rules = 1 << 24,
+ .number_tbl8s = 1 << 21,
+ .entry_unique_size =
+ sizeof(struct rte_pipeline_table_entry),
+ .offset = APP_METADATA_OFFSET(32),
+ };
+
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_lpm_ipv6_ops,
+ .arg_create = &table_lpm_ipv6_params,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id))
+ rte_panic("Unable to configure the IPv6 LPM table\n");
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id);
+
+ /* Add entries to tables */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i & (app.n_ports - 1)]},
+ };
+
+ struct rte_table_lpm_ipv6_key key;
+ struct rte_pipeline_table_entry *entry_ptr;
+ uint32_t ip;
+ int key_found, status;
+
+ key.depth = 8 + __builtin_popcount(app.n_ports - 1);
+
+ ip = rte_bswap32(i << (24 -
+ __builtin_popcount(app.n_ports - 1)));
+ memcpy(key.ip, &ip, sizeof(uint32_t));
+
+ printf("Adding rule to IPv6 LPM table (IPv6 destination = "
+ "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:"
+ "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%u => "
+ "port out = %u)\n",
+ key.ip[0], key.ip[1], key.ip[2], key.ip[3],
+ key.ip[4], key.ip[5], key.ip[6], key.ip[7],
+ key.ip[8], key.ip[9], key.ip[10], key.ip[11],
+ key.ip[12], key.ip[13], key.ip[14], key.ip[15],
+ key.depth, i);
+
+ status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
+ &key_found, &entry_ptr);
+ if (status < 0)
+ rte_panic("Unable to add entry to table %u (%d)\n",
+ table_id, status);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Run-time */
+#if APP_FLUSH == 0
+ for ( ; ; )
+ rte_pipeline_run(p);
+#else
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+#endif
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/pipeline_stub.c b/src/spdk/dpdk/app/test-pipeline/pipeline_stub.c
new file mode 100644
index 000000000..b6750d51b
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/pipeline_stub.c
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <rte_log.h>
+#include <rte_port_ring.h>
+#include <rte_table_stub.h>
+#include <rte_pipeline.h>
+
+#include "main.h"
+
+void
+app_main_loop_worker_pipeline_stub(void) {
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = rte_socket_id(),
+ };
+
+ struct rte_pipeline *p;
+ uint32_t port_in_id[APP_MAX_PORTS];
+ uint32_t port_out_id[APP_MAX_PORTS];
+ uint32_t table_id[APP_MAX_PORTS];
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with stub "
+ "tables)\n", rte_lcore_id());
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL)
+ rte_panic("Unable to configure the pipeline\n");
+
+ /* Input port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = app.rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ .burst_size = app.burst_size_worker_read,
+ };
+
+ if (rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]))
+ rte_panic("Unable to configure input port for "
+ "ring %d\n", i);
+ }
+
+ /* Output port configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = app.rings_tx[i],
+ .tx_burst_sz = app.burst_size_worker_write,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i]))
+ rte_panic("Unable to configure output port for "
+ "ring %d\n", i);
+ }
+
+ /* Table configuration */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_stub_ops,
+ .arg_create = NULL,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id[i]))
+ rte_panic("Unable to configure table %u\n", i);
+ }
+
+ /* Interconnecting ports and tables */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id[i]))
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id[i]);
+
+ /* Add entries to tables */
+ for (i = 0; i < app.n_ports; i++) {
+ struct rte_pipeline_table_entry entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i ^ 1]},
+ };
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ if (rte_pipeline_table_default_entry_add(p, table_id[i], &entry,
+ &default_entry_ptr))
+ rte_panic("Unable to add default entry to table %u\n",
+ table_id[i]);
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < app.n_ports; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0)
+ rte_panic("Pipeline consistency check failed\n");
+
+ /* Run-time */
+#if APP_FLUSH == 0
+ for ( ; ; )
+ rte_pipeline_run(p);
+#else
+ for (i = 0; ; i++) {
+ rte_pipeline_run(p);
+
+ if ((i & APP_FLUSH) == 0)
+ rte_pipeline_flush(p);
+ }
+#endif
+}
diff --git a/src/spdk/dpdk/app/test-pipeline/runtime.c b/src/spdk/dpdk/app/test-pipeline/runtime.c
new file mode 100644
index 000000000..159192bcd
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pipeline/runtime.c
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_lpm6.h>
+#include <rte_malloc.h>
+
+#include "main.h"
+
+void
+app_main_loop_rx(void) {
+ uint32_t i;
+ int ret;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing RX\n", rte_lcore_id());
+
+ for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
+ uint16_t n_mbufs;
+
+ n_mbufs = rte_eth_rx_burst(
+ app.ports[i],
+ 0,
+ app.mbuf_rx.array,
+ app.burst_size_rx_read);
+
+ if (n_mbufs == 0)
+ continue;
+
+ do {
+ ret = rte_ring_sp_enqueue_bulk(
+ app.rings_rx[i],
+ (void **) app.mbuf_rx.array,
+ n_mbufs, NULL);
+ } while (ret == 0);
+ }
+}
+
+void
+app_main_loop_worker(void) {
+ struct app_mbuf_array *worker_mbuf;
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing work (no pipeline)\n",
+ rte_lcore_id());
+
+ worker_mbuf = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array),
+ RTE_CACHE_LINE_SIZE, rte_socket_id());
+ if (worker_mbuf == NULL)
+ rte_panic("Worker thread: cannot allocate buffer space\n");
+
+ for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
+ int ret;
+
+ ret = rte_ring_sc_dequeue_bulk(
+ app.rings_rx[i],
+ (void **) worker_mbuf->array,
+ app.burst_size_worker_read,
+ NULL);
+
+ if (ret == 0)
+ continue;
+
+ do {
+ ret = rte_ring_sp_enqueue_bulk(
+ app.rings_tx[i ^ 1],
+ (void **) worker_mbuf->array,
+ app.burst_size_worker_write,
+ NULL);
+ } while (ret == 0);
+ }
+}
+
+void
+app_main_loop_tx(void) {
+ uint32_t i;
+
+ RTE_LOG(INFO, USER1, "Core %u is doing TX\n", rte_lcore_id());
+
+ for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) {
+ uint16_t n_mbufs, n_pkts;
+ int ret;
+
+ n_mbufs = app.mbuf_tx[i].n_mbufs;
+
+ ret = rte_ring_sc_dequeue_bulk(
+ app.rings_tx[i],
+ (void **) &app.mbuf_tx[i].array[n_mbufs],
+ app.burst_size_tx_read,
+ NULL);
+
+ if (ret == 0)
+ continue;
+
+ n_mbufs += app.burst_size_tx_read;
+
+ if (n_mbufs < app.burst_size_tx_write) {
+ app.mbuf_tx[i].n_mbufs = n_mbufs;
+ continue;
+ }
+
+ n_pkts = rte_eth_tx_burst(
+ app.ports[i],
+ 0,
+ app.mbuf_tx[i].array,
+ n_mbufs);
+
+ if (n_pkts < n_mbufs) {
+ uint16_t k;
+
+ for (k = n_pkts; k < n_mbufs; k++) {
+ struct rte_mbuf *pkt_to_free;
+
+ pkt_to_free = app.mbuf_tx[i].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ app.mbuf_tx[i].n_mbufs = 0;
+ }
+}
diff --git a/src/spdk/dpdk/app/test-pmd/Makefile b/src/spdk/dpdk/app/test-pmd/Makefile
new file mode 100644
index 000000000..ea818de22
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/Makefile
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2015 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_TEST_PMD),y)
+
+#
+# library name
+#
+APP = testpmd
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -Wno-deprecated-declarations
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-y := testpmd.c
+SRCS-y += parameters.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_flow.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_mtr.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += cmdline_tm.c
+SRCS-y += config.c
+SRCS-y += iofwd.c
+SRCS-y += macfwd.c
+SRCS-y += macswap.c
+SRCS-y += flowgen.c
+SRCS-y += rxonly.c
+SRCS-y += txonly.c
+SRCS-y += csumonly.c
+SRCS-y += icmpecho.c
+SRCS-y += noisy_vnf.c
+SRCS-$(CONFIG_RTE_LIBRTE_IEEE1588) += ieee1588fwd.c
+SRCS-$(CONFIG_RTE_LIBRTE_BPF) += bpf_cmd.c
+SRCS-y += util.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC), y)
+SRCS-y += softnicfwd.c
+endif
+
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
+LDLIBS += -lrte_pmd_bond
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_DPAA_BUS)$(CONFIG_RTE_LIBRTE_DPAA_PMD),yy)
+LDLIBS += -lrte_pmd_dpaa
+LDLIBS += -lrte_bus_dpaa
+LDLIBS += -lrte_mempool_dpaa
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_IXGBE_PMD),y)
+LDLIBS += -lrte_pmd_ixgbe
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_I40E_PMD),y)
+LDLIBS += -lrte_pmd_i40e
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_BNXT_PMD),y)
+LDLIBS += -lrte_pmd_bnxt
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_SOFTNIC),y)
+LDLIBS += -lrte_pmd_softnic
+endif
+
+endif
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-pmd/bpf_cmd.c b/src/spdk/dpdk/app/test-pmd/bpf_cmd.c
new file mode 100644
index 000000000..0f984ccf4
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/bpf_cmd.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_bpf_ethdev.h>
+
+#include <cmdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include "testpmd.h"
+
+static const struct rte_bpf_xsym bpf_xsym[] = {
+ {
+ .name = RTE_STR(stdout),
+ .type = RTE_BPF_XTYPE_VAR,
+ .var = {
+ .val = &stdout,
+ .desc = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(stdout),
+ },
+ },
+ },
+ {
+ .name = RTE_STR(rte_pktmbuf_dump),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)rte_pktmbuf_dump,
+ .nb_args = 3,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uintptr_t),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_PTR_MBUF,
+ .size = sizeof(struct rte_mbuf),
+ },
+ [2] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint32_t),
+ },
+ },
+ },
+ },
+};
+
+/* *** load BPF program *** */
+struct cmd_bpf_ld_result {
+ cmdline_fixed_string_t bpf;
+ cmdline_fixed_string_t dir;
+ uint8_t port;
+ uint16_t queue;
+ cmdline_fixed_string_t op;
+ cmdline_fixed_string_t flags;
+ cmdline_fixed_string_t prm;
+};
+
+static void
+bpf_parse_flags(const char *str, struct rte_bpf_arg *arg, uint32_t *flags)
+{
+ uint32_t i, v;
+
+ *flags = RTE_BPF_ETH_F_NONE;
+ arg->type = RTE_BPF_ARG_PTR;
+ arg->size = mbuf_data_size;
+
+ for (i = 0; str[i] != 0; i++) {
+ v = toupper(str[i]);
+ if (v == 'J')
+ *flags |= RTE_BPF_ETH_F_JIT;
+ else if (v == 'M') {
+ arg->type = RTE_BPF_ARG_PTR_MBUF;
+ arg->size = sizeof(struct rte_mbuf);
+ arg->buf_size = mbuf_data_size;
+ } else if (v == '-')
+ continue;
+ else
+ printf("unknown flag: \'%c\'", v);
+ }
+}
+
+static void cmd_operate_bpf_ld_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int32_t rc;
+ uint32_t flags;
+ struct cmd_bpf_ld_result *res;
+ struct rte_bpf_prm prm;
+ const char *fname, *sname;
+
+ res = parsed_result;
+ memset(&prm, 0, sizeof(prm));
+ prm.xsym = bpf_xsym;
+ prm.nb_xsym = RTE_DIM(bpf_xsym);
+
+ bpf_parse_flags(res->flags, &prm.prog_arg, &flags);
+ fname = res->prm;
+ sname = ".text";
+
+ if (strcmp(res->dir, "rx") == 0) {
+ rc = rte_bpf_eth_rx_elf_load(res->port, res->queue, &prm,
+ fname, sname, flags);
+ printf("%d:%s\n", rc, strerror(-rc));
+ } else if (strcmp(res->dir, "tx") == 0) {
+ rc = rte_bpf_eth_tx_elf_load(res->port, res->queue, &prm,
+ fname, sname, flags);
+ printf("%d:%s\n", rc, strerror(-rc));
+ } else
+ printf("invalid value: %s\n", res->dir);
+}
+
+cmdline_parse_token_string_t cmd_load_bpf_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
+ bpf, "bpf-load");
+cmdline_parse_token_string_t cmd_load_bpf_dir =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
+ dir, "rx#tx");
+cmdline_parse_token_num_t cmd_load_bpf_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_bpf_ld_result, port, UINT8);
+cmdline_parse_token_num_t cmd_load_bpf_queue =
+ TOKEN_NUM_INITIALIZER(struct cmd_bpf_ld_result, queue, UINT16);
+cmdline_parse_token_string_t cmd_load_bpf_flags =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
+ flags, NULL);
+cmdline_parse_token_string_t cmd_load_bpf_prm =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_ld_result,
+ prm, NULL);
+
+cmdline_parse_inst_t cmd_operate_bpf_ld_parse = {
+ .f = cmd_operate_bpf_ld_parsed,
+ .data = NULL,
+ .help_str = "bpf-load rx|tx <port> <queue> <J|M|B> <file_name>",
+ .tokens = {
+ (void *)&cmd_load_bpf_start,
+ (void *)&cmd_load_bpf_dir,
+ (void *)&cmd_load_bpf_port,
+ (void *)&cmd_load_bpf_queue,
+ (void *)&cmd_load_bpf_flags,
+ (void *)&cmd_load_bpf_prm,
+ NULL,
+ },
+};
+
+/* *** unload BPF program *** */
+struct cmd_bpf_unld_result {
+ cmdline_fixed_string_t bpf;
+ cmdline_fixed_string_t dir;
+ uint8_t port;
+ uint16_t queue;
+};
+
+static void cmd_operate_bpf_unld_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_bpf_unld_result *res;
+
+ res = parsed_result;
+
+ if (strcmp(res->dir, "rx") == 0)
+ rte_bpf_eth_rx_unload(res->port, res->queue);
+ else if (strcmp(res->dir, "tx") == 0)
+ rte_bpf_eth_tx_unload(res->port, res->queue);
+ else
+ printf("invalid value: %s\n", res->dir);
+}
+
+cmdline_parse_token_string_t cmd_unload_bpf_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_unld_result,
+ bpf, "bpf-unload");
+cmdline_parse_token_string_t cmd_unload_bpf_dir =
+ TOKEN_STRING_INITIALIZER(struct cmd_bpf_unld_result,
+ dir, "rx#tx");
+cmdline_parse_token_num_t cmd_unload_bpf_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_bpf_unld_result, port, UINT8);
+cmdline_parse_token_num_t cmd_unload_bpf_queue =
+ TOKEN_NUM_INITIALIZER(struct cmd_bpf_unld_result, queue, UINT16);
+
+cmdline_parse_inst_t cmd_operate_bpf_unld_parse = {
+ .f = cmd_operate_bpf_unld_parsed,
+ .data = NULL,
+ .help_str = "bpf-unload rx|tx <port> <queue>",
+ .tokens = {
+ (void *)&cmd_unload_bpf_start,
+ (void *)&cmd_unload_bpf_dir,
+ (void *)&cmd_unload_bpf_port,
+ (void *)&cmd_unload_bpf_queue,
+ NULL,
+ },
+};
diff --git a/src/spdk/dpdk/app/test-pmd/bpf_cmd.h b/src/spdk/dpdk/app/test-pmd/bpf_cmd.h
new file mode 100644
index 000000000..5ee4c9f79
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/bpf_cmd.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _BPF_CMD_H_
+#define _BPF_CMD_H_
+
+#ifdef RTE_LIBRTE_BPF
+
+ /* BPF CLI */
+extern cmdline_parse_inst_t cmd_operate_bpf_ld_parse;
+extern cmdline_parse_inst_t cmd_operate_bpf_unld_parse;
+
+#endif /* RTE_LIBRTE_BPF */
+
+#endif /* _BPF_CMD_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline.c b/src/spdk/dpdk/app/test-pmd/cmdline.c
new file mode 100644
index 000000000..996a49876
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline.c
@@ -0,0 +1,19763 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ */
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_devargs.h>
+#include <rte_flow.h>
+#include <rte_gro.h>
+#include <rte_mbuf_dyn.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+#ifdef RTE_LIBRTE_PMD_BOND
+#include <rte_eth_bond.h>
+#include <rte_eth_bond_8023ad.h>
+#endif
+#if defined RTE_LIBRTE_DPAA_BUS && defined RTE_LIBRTE_DPAA_PMD
+#include <rte_pmd_dpaa.h>
+#endif
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+#include <rte_pmd_bnxt.h>
+#endif
+#include "testpmd.h"
+#include "cmdline_mtr.h"
+#include "cmdline_tm.h"
+#include "bpf_cmd.h"
+
+static struct cmdline *testpmd_cl;
+
+static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue);
+
+/* *** Help command with introduction. *** */
+struct cmd_help_brief_result {
+ cmdline_fixed_string_t help;
+};
+
+static void cmd_help_brief_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(
+ cl,
+ "\n"
+ "Help is available for the following sections:\n\n"
+ " help control : Start and stop forwarding.\n"
+ " help display : Displaying port, stats and config "
+ "information.\n"
+ " help config : Configuration information.\n"
+ " help ports : Configuring ports.\n"
+ " help registers : Reading and setting port registers.\n"
+ " help filters : Filters configuration help.\n"
+ " help traffic_management : Traffic Management commands.\n"
+ " help devices : Device related cmds.\n"
+ " help all : All of the above sections.\n\n"
+ );
+
+}
+
+cmdline_parse_token_string_t cmd_help_brief_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_brief_result, help, "help");
+
+cmdline_parse_inst_t cmd_help_brief = {
+ .f = cmd_help_brief_parsed,
+ .data = NULL,
+ .help_str = "help: Show help",
+ .tokens = {
+ (void *)&cmd_help_brief_help,
+ NULL,
+ },
+};
+
+/* *** Help command with help sections. *** */
+struct cmd_help_long_result {
+ cmdline_fixed_string_t help;
+ cmdline_fixed_string_t section;
+};
+
+static void cmd_help_long_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int show_all = 0;
+ struct cmd_help_long_result *res = parsed_result;
+
+ if (!strcmp(res->section, "all"))
+ show_all = 1;
+
+ if (show_all || !strcmp(res->section, "control")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Control forwarding:\n"
+ "-------------------\n\n"
+
+ "start\n"
+ " Start packet forwarding with current configuration.\n\n"
+
+ "start tx_first\n"
+ " Start packet forwarding with current config"
+ " after sending one burst of packets.\n\n"
+
+ "stop\n"
+ " Stop packet forwarding, and display accumulated"
+ " statistics.\n\n"
+
+ "quit\n"
+ " Quit to prompt.\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "display")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Display:\n"
+ "--------\n\n"
+
+ "show port (info|stats|summary|xstats|fdir|stat_qmap|dcb_tc|cap) (port_id|all)\n"
+ " Display information for port_id, or all.\n\n"
+
+ "show port X rss reta (size) (mask0,mask1,...)\n"
+ " Display the rss redirection table entry indicated"
+ " by masks on port X. size is used to indicate the"
+ " hardware supported reta size\n\n"
+
+ "show port (port_id) rss-hash [key]\n"
+ " Display the RSS hash functions and RSS hash key of port\n\n"
+
+ "clear port (info|stats|xstats|fdir|stat_qmap) (port_id|all)\n"
+ " Clear information for port_id, or all.\n\n"
+
+ "show (rxq|txq) info (port_id) (queue_id)\n"
+ " Display information for configured RX/TX queue.\n\n"
+
+ "show config (rxtx|cores|fwd|txpkts)\n"
+ " Display the given configuration.\n\n"
+
+ "read rxd (port_id) (queue_id) (rxd_id)\n"
+ " Display an RX descriptor of a port RX queue.\n\n"
+
+ "read txd (port_id) (queue_id) (txd_id)\n"
+ " Display a TX descriptor of a port TX queue.\n\n"
+
+ "ddp get list (port_id)\n"
+ " Get ddp profile info list\n\n"
+
+ "ddp get info (profile_path)\n"
+ " Get ddp profile information.\n\n"
+
+ "show vf stats (port_id) (vf_id)\n"
+ " Display a VF's statistics.\n\n"
+
+ "clear vf stats (port_id) (vf_id)\n"
+ " Reset a VF's statistics.\n\n"
+
+ "show port (port_id) pctype mapping\n"
+ " Get flow ptype to pctype mapping on a port\n\n"
+
+ "show port meter stats (port_id) (meter_id) (clear)\n"
+ " Get meter stats on a port\n\n"
+
+ "show fwd stats all\n"
+ " Display statistics for all fwd engines.\n\n"
+
+ "clear fwd stats all\n"
+ " Clear statistics for all fwd engines.\n\n"
+
+ "show port (port_id) rx_offload capabilities\n"
+ " List all per queue and per port Rx offloading"
+ " capabilities of a port\n\n"
+
+ "show port (port_id) rx_offload configuration\n"
+ " List port level and all queue level"
+ " Rx offloading configuration\n\n"
+
+ "show port (port_id) tx_offload capabilities\n"
+ " List all per queue and per port"
+ " Tx offloading capabilities of a port\n\n"
+
+ "show port (port_id) tx_offload configuration\n"
+ " List port level and all queue level"
+ " Tx offloading configuration\n\n"
+
+ "show port (port_id) tx_metadata\n"
+ " Show Tx metadata value set"
+ " for a specific port\n\n"
+
+ "show port (port_id) ptypes\n"
+ " Show port supported ptypes"
+ " for a specific port\n\n"
+
+ "show device info (<identifier>|all)"
+ " Show general information about devices probed.\n\n"
+
+ "show port (port_id) rxq|txq (queue_id) desc (desc_id) status"
+ " Show status of rx|tx descriptor.\n\n"
+
+ "show port (port_id) macs|mcast_macs"
+ " Display list of mac addresses added to port.\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "config")) {
+ cmdline_printf(
+ cl,
+ "\n"
+ "Configuration:\n"
+ "--------------\n"
+ "Configuration changes only become active when"
+ " forwarding is started/restarted.\n\n"
+
+ "set default\n"
+ " Reset forwarding to the default configuration.\n\n"
+
+ "set verbose (level)\n"
+ " Set the debug verbosity level X.\n\n"
+
+ "set log global|(type) (level)\n"
+ " Set the log level.\n\n"
+
+ "set nbport (num)\n"
+ " Set number of ports.\n\n"
+
+ "set nbcore (num)\n"
+ " Set number of cores.\n\n"
+
+ "set coremask (mask)\n"
+ " Set the forwarding cores hexadecimal mask.\n\n"
+
+ "set portmask (mask)\n"
+ " Set the forwarding ports hexadecimal mask.\n\n"
+
+ "set burst (num)\n"
+ " Set number of packets per burst.\n\n"
+
+ "set burst tx delay (microseconds) retry (num)\n"
+ " Set the transmit delay time and number of retries,"
+ " effective when retry is enabled.\n\n"
+
+ "set txpkts (x[,y]*)\n"
+ " Set the length of each segment of TXONLY"
+ " and optionally CSUM packets.\n\n"
+
+ "set txsplit (off|on|rand)\n"
+ " Set the split policy for the TX packets."
+ " Right now only applicable for CSUM and TXONLY"
+ " modes\n\n"
+
+ "set corelist (x[,y]*)\n"
+ " Set the list of forwarding cores.\n\n"
+
+ "set portlist (x[,y]*)\n"
+ " Set the list of forwarding ports.\n\n"
+
+ "set port setup on (iterator|event)\n"
+ " Select how attached port is retrieved for setup.\n\n"
+
+ "set tx loopback (port_id) (on|off)\n"
+ " Enable or disable tx loopback.\n\n"
+
+ "set all queues drop (port_id) (on|off)\n"
+ " Set drop enable bit for all queues.\n\n"
+
+ "set vf split drop (port_id) (vf_id) (on|off)\n"
+ " Set split drop enable bit for a VF from the PF.\n\n"
+
+ "set vf mac antispoof (port_id) (vf_id) (on|off).\n"
+ " Set MAC antispoof for a VF from the PF.\n\n"
+
+ "set macsec offload (port_id) on encrypt (on|off) replay-protect (on|off)\n"
+ " Enable MACsec offload.\n\n"
+
+ "set macsec offload (port_id) off\n"
+ " Disable MACsec offload.\n\n"
+
+ "set macsec sc (tx|rx) (port_id) (mac) (pi)\n"
+ " Configure MACsec secure connection (SC).\n\n"
+
+ "set macsec sa (tx|rx) (port_id) (idx) (an) (pn) (key)\n"
+ " Configure MACsec secure association (SA).\n\n"
+
+ "set vf broadcast (port_id) (vf_id) (on|off)\n"
+ " Set VF broadcast for a VF from the PF.\n\n"
+
+ "vlan set stripq (on|off) (port_id,queue_id)\n"
+ " Set the VLAN strip for a queue on a port.\n\n"
+
+ "set vf vlan stripq (port_id) (vf_id) (on|off)\n"
+ " Set the VLAN strip for all queues in a pool for a VF from the PF.\n\n"
+
+ "set vf vlan insert (port_id) (vf_id) (vlan_id)\n"
+ " Set VLAN insert for a VF from the PF.\n\n"
+
+ "set vf vlan antispoof (port_id) (vf_id) (on|off)\n"
+ " Set VLAN antispoof for a VF from the PF.\n\n"
+
+ "set vf vlan tag (port_id) (vf_id) (on|off)\n"
+ " Set VLAN tag for a VF from the PF.\n\n"
+
+ "set vf tx max-bandwidth (port_id) (vf_id) (bandwidth)\n"
+ " Set a VF's max bandwidth(Mbps).\n\n"
+
+ "set vf tc tx min-bandwidth (port_id) (vf_id) (bw1, bw2, ...)\n"
+ " Set all TCs' min bandwidth(%%) on a VF.\n\n"
+
+ "set vf tc tx max-bandwidth (port_id) (vf_id) (tc_no) (bandwidth)\n"
+ " Set a TC's max bandwidth(Mbps) on a VF.\n\n"
+
+ "set tx strict-link-priority (port_id) (tc_bitmap)\n"
+ " Set some TCs' strict link priority mode on a physical port.\n\n"
+
+ "set tc tx min-bandwidth (port_id) (bw1, bw2, ...)\n"
+ " Set all TCs' min bandwidth(%%) for all PF and VFs.\n\n"
+
+ "vlan set (strip|filter|qinq_strip|extend) (on|off) (port_id)\n"
+ " Set the VLAN strip or filter or qinq strip or extend\n\n"
+
+ "vlan set (inner|outer) tpid (value) (port_id)\n"
+ " Set the VLAN TPID for Packet Filtering on"
+ " a port\n\n"
+
+ "rx_vlan add (vlan_id|all) (port_id)\n"
+ " Add a vlan_id, or all identifiers, to the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "rx_vlan rm (vlan_id|all) (port_id)\n"
+ " Remove a vlan_id, or all identifiers, from the set"
+ " of VLAN identifiers filtered by port_id.\n\n"
+
+ "rx_vlan add (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Add a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "rx_vlan rm (vlan_id) port (port_id) vf (vf_mask)\n"
+ " Remove a vlan_id, to the set of VLAN identifiers"
+ "filtered for VF(s) from port_id.\n\n"
+
+ "tunnel_filter add (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre|vxlan-gpe) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " add a tunnel filter of a port.\n\n"
+
+ "tunnel_filter rm (port_id) (outer_mac) (inner_mac) (ip_addr) "
+ "(inner_vlan) (vxlan|nvgre|ipingre|vxlan-gpe) (imac-ivlan|imac-ivlan-tenid|"
+ "imac-tenid|imac|omac-imac-tenid|oip|iip) (tenant_id) (queue_id)\n"
+ " remove a tunnel filter of a port.\n\n"
+
+ "rx_vxlan_port add (udp_port) (port_id)\n"
+ " Add an UDP port for VXLAN packet filter on a port\n\n"
+
+ "rx_vxlan_port rm (udp_port) (port_id)\n"
+ " Remove an UDP port for VXLAN packet filter on a port\n\n"
+
+ "tx_vlan set (port_id) vlan_id[, vlan_id_outer]\n"
+ " Set hardware insertion of VLAN IDs (single or double VLAN "
+ "depends on the number of VLAN IDs) in packets sent on a port.\n\n"
+
+ "tx_vlan set pvid port_id vlan_id (on|off)\n"
+ " Set port based TX VLAN insertion.\n\n"
+
+ "tx_vlan reset (port_id)\n"
+ " Disable hardware insertion of a VLAN header in"
+ " packets sent on a port.\n\n"
+
+ "csum set (ip|udp|tcp|sctp|outer-ip|outer-udp) (hw|sw) (port_id)\n"
+ " Select hardware or software calculation of the"
+ " checksum when transmitting a packet using the"
+ " csum forward engine.\n"
+ " ip|udp|tcp|sctp always concern the inner layer.\n"
+ " outer-ip concerns the outer IP layer in"
+ " outer-udp concerns the outer UDP layer in"
+ " case the packet is recognized as a tunnel packet by"
+ " the forward engine (vxlan, gre and ipip are supported)\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "csum parse-tunnel (on|off) (tx_port_id)\n"
+ " If disabled, treat tunnel packets as non-tunneled"
+ " packets (treat inner headers as payload). The port\n"
+ " argument is the port used for TX in csum forward"
+ " engine.\n\n"
+
+ "csum show (port_id)\n"
+ " Display tx checksum offload configuration\n\n"
+
+ "tso set (segsize) (portid)\n"
+ " Enable TCP Segmentation Offload in csum forward"
+ " engine.\n"
+ " Please check the NIC datasheet for HW limits.\n\n"
+
+ "tso show (portid)"
+ " Display the status of TCP Segmentation Offload.\n\n"
+
+ "set port (port_id) gro on|off\n"
+ " Enable or disable Generic Receive Offload in"
+ " csum forwarding engine.\n\n"
+
+ "show port (port_id) gro\n"
+ " Display GRO configuration.\n\n"
+
+ "set gro flush (cycles)\n"
+ " Set the cycle to flush GROed packets from"
+ " reassembly tables.\n\n"
+
+ "set port (port_id) gso (on|off)"
+ " Enable or disable Generic Segmentation Offload in"
+ " csum forwarding engine.\n\n"
+
+ "set gso segsz (length)\n"
+ " Set max packet length for output GSO segments,"
+ " including packet header and payload.\n\n"
+
+ "show port (port_id) gso\n"
+ " Show GSO configuration.\n\n"
+
+ "set fwd (%s)\n"
+ " Set packet forwarding mode.\n\n"
+
+ "mac_addr add (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Add a MAC address on port_id.\n\n"
+
+ "mac_addr remove (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Remove a MAC address from port_id.\n\n"
+
+ "mac_addr set (port_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Set the default MAC address for port_id.\n\n"
+
+ "mac_addr add port (port_id) vf (vf_id) (mac_address)\n"
+ " Add a MAC address for a VF on the port.\n\n"
+
+ "set vf mac addr (port_id) (vf_id) (XX:XX:XX:XX:XX:XX)\n"
+ " Set the MAC address for a VF from the PF.\n\n"
+
+ "set eth-peer (port_id) (peer_addr)\n"
+ " set the peer address for certain port.\n\n"
+
+ "set port (port_id) uta (mac_address|all) (on|off)\n"
+ " Add/Remove a or all unicast hash filter(s)"
+ "from port X.\n\n"
+
+ "set promisc (port_id|all) (on|off)\n"
+ " Set the promiscuous mode on port_id, or all.\n\n"
+
+ "set allmulti (port_id|all) (on|off)\n"
+ " Set the allmulti mode on port_id, or all.\n\n"
+
+ "set vf promisc (port_id) (vf_id) (on|off)\n"
+ " Set unicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set vf allmulti (port_id) (vf_id) (on|off)\n"
+ " Set multicast promiscuous mode for a VF from the PF.\n\n"
+
+ "set flow_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (send_xon) mac_ctrl_frame_fwd"
+ " (on|off) autoneg (on|off) (port_id)\n"
+ "set flow_ctrl rx (on|off) (portid)\n"
+ "set flow_ctrl tx (on|off) (portid)\n"
+ "set flow_ctrl high_water (high_water) (portid)\n"
+ "set flow_ctrl low_water (low_water) (portid)\n"
+ "set flow_ctrl pause_time (pause_time) (portid)\n"
+ "set flow_ctrl send_xon (send_xon) (portid)\n"
+ "set flow_ctrl mac_ctrl_frame_fwd (on|off) (portid)\n"
+ "set flow_ctrl autoneg (on|off) (port_id)\n"
+ " Set the link flow control parameter on a port.\n\n"
+
+ "set pfc_ctrl rx (on|off) tx (on|off) (high_water)"
+ " (low_water) (pause_time) (priority) (port_id)\n"
+ " Set the priority flow control parameter on a"
+ " port.\n\n"
+
+ "set stat_qmap (tx|rx) (port_id) (queue_id) (qmapping)\n"
+ " Set statistics mapping (qmapping 0..15) for RX/TX"
+ " queue on port.\n"
+ " e.g., 'set stat_qmap rx 0 2 5' sets rx queue 2"
+ " on port 0 to mapping 5.\n\n"
+
+ "set xstats-hide-zero on|off\n"
+ " Set the option to hide the zero values"
+ " for xstats display.\n"
+
+ "set port (port_id) vf (vf_id) rx|tx on|off\n"
+ " Enable/Disable a VF receive/tranmit from a port\n\n"
+
+ "set port (port_id) vf (vf_id) (mac_addr)"
+ " (exact-mac#exact-mac-vlan#hashmac|hashmac-vlan) on|off\n"
+ " Add/Remove unicast or multicast MAC addr filter"
+ " for a VF.\n\n"
+
+ "set port (port_id) vf (vf_id) rxmode (AUPE|ROPE|BAM"
+ "|MPE) (on|off)\n"
+ " AUPE:accepts untagged VLAN;"
+ "ROPE:accept unicast hash\n\n"
+ " BAM:accepts broadcast packets;"
+ "MPE:accepts all multicast packets\n\n"
+ " Enable/Disable a VF receive mode of a port\n\n"
+
+ "set port (port_id) queue (queue_id) rate (rate_num)\n"
+ " Set rate limit for a queue of a port\n\n"
+
+ "set port (port_id) vf (vf_id) rate (rate_num) "
+ "queue_mask (queue_mask_value)\n"
+ " Set rate limit for queues in VF of a port\n\n"
+
+ "set port (port_id) mirror-rule (rule_id)"
+ " (pool-mirror-up|pool-mirror-down|vlan-mirror)"
+ " (poolmask|vlanid[,vlanid]*) dst-pool (pool_id) (on|off)\n"
+ " Set pool or vlan type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 vlan-mirror 0,1"
+ " dst-pool 0 on' enable mirror traffic with vlan 0,1"
+ " to pool 0.\n\n"
+
+ "set port (port_id) mirror-rule (rule_id)"
+ " (uplink-mirror|downlink-mirror) dst-pool"
+ " (pool_id) (on|off)\n"
+ " Set uplink or downlink type mirror rule on a port.\n"
+ " e.g., 'set port 0 mirror-rule 0 uplink-mirror dst-pool"
+ " 0 on' enable mirror income traffic to pool 0.\n\n"
+
+ "reset port (port_id) mirror-rule (rule_id)\n"
+ " Reset a mirror rule.\n\n"
+
+ "set flush_rx (on|off)\n"
+ " Flush (default) or don't flush RX streams before"
+ " forwarding. Mainly used with PCAP drivers.\n\n"
+
+ "set bypass mode (normal|bypass|isolate) (port_id)\n"
+ " Set the bypass mode for the lowest port on bypass enabled"
+ " NIC.\n\n"
+
+ "set bypass event (timeout|os_on|os_off|power_on|power_off) "
+ "mode (normal|bypass|isolate) (port_id)\n"
+ " Set the event required to initiate specified bypass mode for"
+ " the lowest port on a bypass enabled NIC where:\n"
+ " timeout = enable bypass after watchdog timeout.\n"
+ " os_on = enable bypass when OS/board is powered on.\n"
+ " os_off = enable bypass when OS/board is powered off.\n"
+ " power_on = enable bypass when power supply is turned on.\n"
+ " power_off = enable bypass when power supply is turned off."
+ "\n\n"
+
+ "set bypass timeout (0|1.5|2|3|4|8|16|32)\n"
+ " Set the bypass watchdog timeout to 'n' seconds"
+ " where 0 = instant.\n\n"
+
+ "show bypass config (port_id)\n"
+ " Show the bypass configuration for a bypass enabled NIC"
+ " using the lowest port on the NIC.\n\n"
+
+#ifdef RTE_LIBRTE_PMD_BOND
+ "create bonded device (mode) (socket)\n"
+ " Create a new bonded device with specific bonding mode and socket.\n\n"
+
+ "add bonding slave (slave_id) (port_id)\n"
+ " Add a slave device to a bonded device.\n\n"
+
+ "remove bonding slave (slave_id) (port_id)\n"
+ " Remove a slave device from a bonded device.\n\n"
+
+ "set bonding mode (value) (port_id)\n"
+ " Set the bonding mode on a bonded device.\n\n"
+
+ "set bonding primary (slave_id) (port_id)\n"
+ " Set the primary slave for a bonded device.\n\n"
+
+ "show bonding config (port_id)\n"
+ " Show the bonding config for port_id.\n\n"
+
+ "set bonding mac_addr (port_id) (address)\n"
+ " Set the MAC address of a bonded device.\n\n"
+
+ "set bonding mode IEEE802.3AD aggregator policy (port_id) (agg_name)"
+ " Set Aggregation mode for IEEE802.3AD (mode 4)"
+
+ "set bonding xmit_balance_policy (port_id) (l2|l23|l34)\n"
+ " Set the transmit balance policy for bonded device running in balance mode.\n\n"
+
+ "set bonding mon_period (port_id) (value)\n"
+ " Set the bonding link status monitoring polling period in ms.\n\n"
+
+ "set bonding lacp dedicated_queues <port_id> (enable|disable)\n"
+ " Enable/disable dedicated queues for LACP control traffic.\n\n"
+
+#endif
+ "set link-up port (port_id)\n"
+ " Set link up for a port.\n\n"
+
+ "set link-down port (port_id)\n"
+ " Set link down for a port.\n\n"
+
+ "E-tag set insertion on port-tag-id (value)"
+ " port (port_id) vf (vf_id)\n"
+ " Enable E-tag insertion for a VF on a port\n\n"
+
+ "E-tag set insertion off port (port_id) vf (vf_id)\n"
+ " Disable E-tag insertion for a VF on a port\n\n"
+
+ "E-tag set stripping (on|off) port (port_id)\n"
+ " Enable/disable E-tag stripping on a port\n\n"
+
+ "E-tag set forwarding (on|off) port (port_id)\n"
+ " Enable/disable E-tag based forwarding"
+ " on a port\n\n"
+
+ "E-tag set filter add e-tag-id (value) dst-pool"
+ " (pool_id) port (port_id)\n"
+ " Add an E-tag forwarding filter on a port\n\n"
+
+ "E-tag set filter del e-tag-id (value) port (port_id)\n"
+ " Delete an E-tag forwarding filter on a port\n\n"
+
+ "ddp add (port_id) (profile_path[,backup_profile_path])\n"
+ " Load a profile package on a port\n\n"
+
+ "ddp del (port_id) (backup_profile_path)\n"
+ " Delete a profile package from a port\n\n"
+
+ "ptype mapping get (port_id) (valid_only)\n"
+ " Get ptype mapping on a port\n\n"
+
+ "ptype mapping replace (port_id) (target) (mask) (pky_type)\n"
+ " Replace target with the pkt_type in ptype mapping\n\n"
+
+ "ptype mapping reset (port_id)\n"
+ " Reset ptype mapping on a port\n\n"
+
+ "ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
+ " Update a ptype mapping item on a port\n\n"
+
+ "set port (port_id) ptype_mask (ptype_mask)\n"
+ " set packet types classification for a specific port\n\n"
+
+ "set port (port_id) queue-region region_id (value) "
+ "queue_start_index (value) queue_num (value)\n"
+ " Set a queue region on a port\n\n"
+
+ "set port (port_id) queue-region region_id (value) "
+ "flowtype (value)\n"
+ " Set a flowtype region index on a port\n\n"
+
+ "set port (port_id) queue-region UP (value) region_id (value)\n"
+ " Set the mapping of User Priority to "
+ "queue region on a port\n\n"
+
+ "set port (port_id) queue-region flush (on|off)\n"
+ " flush all queue region related configuration\n\n"
+
+ "show port meter cap (port_id)\n"
+ " Show port meter capability information\n\n"
+
+ "add port meter profile srtcm_rfc2697 (port_id) (profile_id) (cir) (cbs) (ebs)\n"
+ " meter profile add - srtcm rfc 2697\n\n"
+
+ "add port meter profile trtcm_rfc2698 (port_id) (profile_id) (cir) (pir) (cbs) (pbs)\n"
+ " meter profile add - trtcm rfc 2698\n\n"
+
+ "add port meter profile trtcm_rfc4115 (port_id) (profile_id) (cir) (eir) (cbs) (ebs)\n"
+ " meter profile add - trtcm rfc 4115\n\n"
+
+ "del port meter profile (port_id) (profile_id)\n"
+ " meter profile delete\n\n"
+
+ "create port meter (port_id) (mtr_id) (profile_id) (meter_enable)\n"
+ "(g_action) (y_action) (r_action) (stats_mask) (shared)\n"
+ "(use_pre_meter_color) [(dscp_tbl_entry0) (dscp_tbl_entry1)...\n"
+ "(dscp_tbl_entry63)]\n"
+ " meter create\n\n"
+
+ "enable port meter (port_id) (mtr_id)\n"
+ " meter enable\n\n"
+
+ "disable port meter (port_id) (mtr_id)\n"
+ " meter disable\n\n"
+
+ "del port meter (port_id) (mtr_id)\n"
+ " meter delete\n\n"
+
+ "set port meter profile (port_id) (mtr_id) (profile_id)\n"
+ " meter update meter profile\n\n"
+
+ "set port meter dscp table (port_id) (mtr_id) [(dscp_tbl_entry0)\n"
+ "(dscp_tbl_entry1)...(dscp_tbl_entry63)]\n"
+ " update meter dscp table entries\n\n"
+
+ "set port meter policer action (port_id) (mtr_id) (action_mask)\n"
+ "(action0) [(action1) (action2)]\n"
+ " meter update policer action\n\n"
+
+ "set port meter stats mask (port_id) (mtr_id) (stats_mask)\n"
+ " meter update stats\n\n"
+
+ "show port (port_id) queue-region\n"
+ " show all queue region related configuration info\n\n"
+
+ , list_pkt_forwarding_modes()
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "ports")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Port Operations:\n"
+ "----------------\n\n"
+
+ "port start (port_id|all)\n"
+ " Start all ports or port_id.\n\n"
+
+ "port stop (port_id|all)\n"
+ " Stop all ports or port_id.\n\n"
+
+ "port close (port_id|all)\n"
+ " Close all ports or port_id.\n\n"
+
+ "port reset (port_id|all)\n"
+ " Reset all ports or port_id.\n\n"
+
+ "port attach (ident)\n"
+ " Attach physical or virtual dev by pci address or virtual device name\n\n"
+
+ "port detach (port_id)\n"
+ " Detach physical or virtual dev by port_id\n\n"
+
+ "port config (port_id|all)"
+ " speed (10|100|1000|10000|25000|40000|50000|100000|200000|auto)"
+ " duplex (half|full|auto)\n"
+ " Set speed and duplex for all ports or port_id\n\n"
+
+ "port config (port_id|all) loopback (mode)\n"
+ " Set loopback mode for all ports or port_id\n\n"
+
+ "port config all (rxq|txq|rxd|txd) (value)\n"
+ " Set number for rxq/txq/rxd/txd.\n\n"
+
+ "port config all max-pkt-len (value)\n"
+ " Set the max packet length.\n\n"
+
+ "port config all max-lro-pkt-size (value)\n"
+ " Set the max LRO aggregated packet size.\n\n"
+
+ "port config all drop-en (on|off)\n"
+ " Enable or disable packet drop on all RX queues of all ports when no "
+ "receive buffers available.\n\n"
+
+ "port config all rss (all|default|ip|tcp|udp|sctp|"
+ "ether|port|vxlan|geneve|nvgre|vxlan-gpe|none|<flowtype_id>)\n"
+ " Set the RSS mode.\n\n"
+
+ "port config port-id rss reta (hash,queue)[,(hash,queue)]\n"
+ " Set the RSS redirection table.\n\n"
+
+ "port config (port_id) dcb vt (on|off) (traffic_class)"
+ " pfc (on|off)\n"
+ " Set the DCB mode.\n\n"
+
+ "port config all burst (value)\n"
+ " Set the number of packets per burst.\n\n"
+
+ "port config all (txpt|txht|txwt|rxpt|rxht|rxwt)"
+ " (value)\n"
+ " Set the ring prefetch/host/writeback threshold"
+ " for tx/rx queue.\n\n"
+
+ "port config all (txfreet|txrst|rxfreet) (value)\n"
+ " Set free threshold for rx/tx, or set"
+ " tx rs bit threshold.\n\n"
+ "port config mtu X value\n"
+ " Set the MTU of port X to a given value\n\n"
+
+ "port config (port_id) (rxq|txq) (queue_id) ring_size (value)\n"
+ " Set a rx/tx queue's ring size configuration, the new"
+ " value will take effect after command that (re-)start the port"
+ " or command that setup the specific queue\n\n"
+
+ "port (port_id) (rxq|txq) (queue_id) (start|stop)\n"
+ " Start/stop a rx/tx queue of port X. Only take effect"
+ " when port X is started\n\n"
+
+ "port (port_id) (rxq|txq) (queue_id) deferred_start (on|off)\n"
+ " Switch on/off a deferred start of port X rx/tx queue. Only"
+ " take effect when port X is stopped.\n\n"
+
+ "port (port_id) (rxq|txq) (queue_id) setup\n"
+ " Setup a rx/tx queue of port X.\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag ether-type"
+ " (value)\n"
+ " Set the value of E-tag ether-type.\n\n"
+
+ "port config (port_id|all) l2-tunnel E-tag"
+ " (enable|disable)\n"
+ " Enable/disable the E-tag support.\n\n"
+
+ "port config (port_id) pctype mapping reset\n"
+ " Reset flow type to pctype mapping on a port\n\n"
+
+ "port config (port_id) pctype mapping update"
+ " (pctype_id_0[,pctype_id_1]*) (flow_type_id)\n"
+ " Update a flow type to pctype mapping item on a port\n\n"
+
+ "port config (port_id) pctype (pctype_id) hash_inset|"
+ "fdir_inset|fdir_flx_inset get|set|clear field\n"
+ " (field_idx)\n"
+ " Configure RSS|FDIR|FDIR_FLX input set for some pctype\n\n"
+
+ "port config (port_id) pctype (pctype_id) hash_inset|"
+ "fdir_inset|fdir_flx_inset clear all"
+ " Clear RSS|FDIR|FDIR_FLX input set completely for some pctype\n\n"
+
+ "port config (port_id) udp_tunnel_port add|rm vxlan|geneve (udp_port)\n\n"
+ " Add/remove UDP tunnel port for tunneling offload\n\n"
+
+ "port config <port_id> rx_offload vlan_strip|"
+ "ipv4_cksum|udp_cksum|tcp_cksum|tcp_lro|qinq_strip|"
+ "outer_ipv4_cksum|macsec_strip|header_split|"
+ "vlan_filter|vlan_extend|jumbo_frame|"
+ "scatter|timestamp|security|keep_crc on|off\n"
+ " Enable or disable a per port Rx offloading"
+ " on all Rx queues of a port\n\n"
+
+ "port (port_id) rxq (queue_id) rx_offload vlan_strip|"
+ "ipv4_cksum|udp_cksum|tcp_cksum|tcp_lro|qinq_strip|"
+ "outer_ipv4_cksum|macsec_strip|header_split|"
+ "vlan_filter|vlan_extend|jumbo_frame|"
+ "scatter|timestamp|security|keep_crc on|off\n"
+ " Enable or disable a per queue Rx offloading"
+ " only on a specific Rx queue\n\n"
+
+ "port config (port_id) tx_offload vlan_insert|"
+ "ipv4_cksum|udp_cksum|tcp_cksum|sctp_cksum|tcp_tso|"
+ "udp_tso|outer_ipv4_cksum|qinq_insert|vxlan_tnl_tso|"
+ "gre_tnl_tso|ipip_tnl_tso|geneve_tnl_tso|"
+ "macsec_insert|mt_lockfree|multi_segs|mbuf_fast_free|"
+ "security on|off\n"
+ " Enable or disable a per port Tx offloading"
+ " on all Tx queues of a port\n\n"
+
+ "port (port_id) txq (queue_id) tx_offload vlan_insert|"
+ "ipv4_cksum|udp_cksum|tcp_cksum|sctp_cksum|tcp_tso|"
+ "udp_tso|outer_ipv4_cksum|qinq_insert|vxlan_tnl_tso|"
+ "gre_tnl_tso|ipip_tnl_tso|geneve_tnl_tso|macsec_insert"
+ "|mt_lockfree|multi_segs|mbuf_fast_free|security"
+ " on|off\n"
+ " Enable or disable a per queue Tx offloading"
+ " only on a specific Tx queue\n\n"
+
+ "bpf-load rx|tx (port) (queue) (J|M|B) (file_name)\n"
+ " Load an eBPF program as a callback"
+ " for particular RX/TX queue\n\n"
+
+ "bpf-unload rx|tx (port) (queue)\n"
+ " Unload previously loaded eBPF program"
+ " for particular RX/TX queue\n\n"
+
+ "port config (port_id) tx_metadata (value)\n"
+ " Set Tx metadata value per port. Testpmd will add this value"
+ " to any Tx packet sent from this port\n\n"
+
+ "port config (port_id) dynf (name) set|clear\n"
+ " Register a dynf and Set/clear this flag on Tx. "
+ "Testpmd will set this value to any Tx packet "
+ "sent from this port\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "registers")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "Registers:\n"
+ "----------\n\n"
+
+ "read reg (port_id) (address)\n"
+ " Display value of a port register.\n\n"
+
+ "read regfield (port_id) (address) (bit_x) (bit_y)\n"
+ " Display a port register bit field.\n\n"
+
+ "read regbit (port_id) (address) (bit_x)\n"
+ " Display a single port register bit.\n\n"
+
+ "write reg (port_id) (address) (value)\n"
+ " Set value of a port register.\n\n"
+
+ "write regfield (port_id) (address) (bit_x) (bit_y)"
+ " (value)\n"
+ " Set bit field of a port register.\n\n"
+
+ "write regbit (port_id) (address) (bit_x) (value)\n"
+ " Set single bit value of a port register.\n\n"
+ );
+ }
+ if (show_all || !strcmp(res->section, "filters")) {
+
+ cmdline_printf(
+ cl,
+ "\n"
+ "filters:\n"
+ "--------\n\n"
+
+ "ethertype_filter (port_id) (add|del)"
+ " (mac_addr|mac_ignr) (mac_address) ethertype"
+ " (ether_type) (drop|fwd) queue (queue_id)\n"
+ " Add/Del an ethertype filter.\n\n"
+
+ "2tuple_filter (port_id) (add|del)"
+ " dst_port (dst_port_value) protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 2tuple filter.\n\n"
+
+ "5tuple_filter (port_id) (add|del)"
+ " dst_ip (dst_address) src_ip (src_address)"
+ " dst_port (dst_port_value) src_port (src_port_value)"
+ " protocol (protocol_value)"
+ " mask (mask_value) tcp_flags (tcp_flags_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a 5tuple filter.\n\n"
+
+ "syn_filter (port_id) (add|del) priority (high|low) queue (queue_id)"
+ " Add/Del syn filter.\n\n"
+
+ "flex_filter (port_id) (add|del) len (len_value)"
+ " bytes (bytes_value) mask (mask_value)"
+ " priority (prio_value) queue (queue_id)\n"
+ " Add/Del a flex filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag)"
+ " src (src_ip_address) dst (dst_ip_address)"
+ " tos (tos_value) proto (proto_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an IP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value) flexbytes (flexbytes_value)"
+ " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
+ " fd_id (fd_id_value)\n"
+ " Add/Del an UDP/TCP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow (ipv4-sctp|ipv6-sctp)"
+ " src (src_ip_address) (src_port)"
+ " dst (dst_ip_address) (dst_port)"
+ " tag (verification_tag) "
+ " tos (tos_value) ttl (ttl_value)"
+ " vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a SCTP type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode IP (add|del|update)"
+ " flow l2_payload ether (ethertype)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a l2 payload type flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode MAC-VLAN (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a MAC-VLAN flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode Tunnel (add|del|update)"
+ " mac (mac_address) vlan (vlan_value)"
+ " tunnel (NVGRE|VxLAN) tunnel-id (tunnel_id_value)"
+ " flexbytes (flexbytes_value) (drop|fwd)"
+ " queue (queue_id) fd_id (fd_id_value)\n"
+ " Add/Del a Tunnel flow director filter.\n\n"
+
+ "flow_director_filter (port_id) mode raw (add|del|update)"
+ " flow (flow_id) (drop|fwd) queue (queue_id)"
+ " fd_id (fd_id_value) packet (packet file name)\n"
+ " Add/Del a raw type flow director filter.\n\n"
+
+ "flush_flow_director (port_id)\n"
+ " Flush all flow director entries of a device.\n\n"
+
+ "flow_director_mask (port_id) mode IP vlan (vlan_value)"
+ " src_mask (ipv4_src) (ipv6_src) (src_port)"
+ " dst_mask (ipv4_dst) (ipv6_dst) (dst_port)\n"
+ " Set flow director IP mask.\n\n"
+
+ "flow_director_mask (port_id) mode MAC-VLAN"
+ " vlan (vlan_value)\n"
+ " Set flow director MAC-VLAN mask.\n\n"
+
+ "flow_director_mask (port_id) mode Tunnel"
+ " vlan (vlan_value) mac (mac_value)"
+ " tunnel-type (tunnel_type_value)"
+ " tunnel-id (tunnel_id_value)\n"
+ " Set flow director Tunnel mask.\n\n"
+
+ "flow_director_flex_mask (port_id)"
+ " flow (none|ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
+ "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|l2_payload|all)"
+ " (mask)\n"
+ " Configure mask of flex payload.\n\n"
+
+ "flow_director_flex_payload (port_id)"
+ " (raw|l2|l3|l4) (config)\n"
+ " Configure flex payload selection.\n\n"
+
+ "get_sym_hash_ena_per_port (port_id)\n"
+ " get symmetric hash enable configuration per port.\n\n"
+
+ "set_sym_hash_ena_per_port (port_id) (enable|disable)\n"
+ " set symmetric hash enable configuration per port"
+ " to enable or disable.\n\n"
+
+ "get_hash_global_config (port_id)\n"
+ " Get the global configurations of hash filters.\n\n"
+
+ "set_hash_global_config (port_id) (toeplitz|simple_xor|symmetric_toeplitz|default)"
+ " (ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload)"
+ " (enable|disable)\n"
+ " Set the global configurations of hash filters.\n\n"
+
+ "set_hash_input_set (port_id) (ipv4|ipv4-frag|"
+ "ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|ipv6|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload|<flowtype_id>) (ovlan|ivlan|src-ipv4|dst-ipv4|"
+ "src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|ipv6-tc|"
+ "ipv6-next-header|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|"
+ "sctp-dst-port|sctp-veri-tag|udp-key|gre-key|fld-1st|"
+ "fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|fld-7th|"
+ "fld-8th|none) (select|add)\n"
+ " Set the input set for hash.\n\n"
+
+ "set_fdir_input_set (port_id) "
+ "(ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload) (ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|"
+ "dst-ipv6|ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|"
+ "ipv6-next-header|ipv6-hop-limits|udp-src-port|"
+ "udp-dst-port|tcp-src-port|tcp-dst-port|"
+ "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)"
+ " (select|add)\n"
+ " Set the input set for FDir.\n\n"
+
+ "flow validate {port_id}"
+ " [group {group_id}] [priority {level}]"
+ " [ingress] [egress]"
+ " pattern {item} [/ {item} [...]] / end"
+ " actions {action} [/ {action} [...]] / end\n"
+ " Check whether a flow rule can be created.\n\n"
+
+ "flow create {port_id}"
+ " [group {group_id}] [priority {level}]"
+ " [ingress] [egress]"
+ " pattern {item} [/ {item} [...]] / end"
+ " actions {action} [/ {action} [...]] / end\n"
+ " Create a flow rule.\n\n"
+
+ "flow destroy {port_id} rule {rule_id} [...]\n"
+ " Destroy specific flow rules.\n\n"
+
+ "flow flush {port_id}\n"
+ " Destroy all flow rules.\n\n"
+
+ "flow query {port_id} {rule_id} {action}\n"
+ " Query an existing flow rule.\n\n"
+
+ "flow list {port_id} [group {group_id}] [...]\n"
+ " List existing flow rules sorted by priority,"
+ " filtered by group identifiers.\n\n"
+
+ "flow isolate {port_id} {boolean}\n"
+ " Restrict ingress traffic to the defined"
+ " flow rules\n\n"
+
+ "flow aged {port_id} [destroy]\n"
+ " List and destroy aged flows"
+ " flow rules\n\n"
+
+ "set vxlan ip-version (ipv4|ipv6) vni (vni) udp-src"
+ " (udp-src) udp-dst (udp-dst) ip-src (ip-src) ip-dst"
+ " (ip-dst) eth-src (eth-src) eth-dst (eth-dst)\n"
+ " Configure the VXLAN encapsulation for flows.\n\n"
+
+ "set vxlan-with-vlan ip-version (ipv4|ipv6) vni (vni)"
+ " udp-src (udp-src) udp-dst (udp-dst) ip-src (ip-src)"
+ " ip-dst (ip-dst) vlan-tci (vlan-tci) eth-src (eth-src)"
+ " eth-dst (eth-dst)\n"
+ " Configure the VXLAN encapsulation for flows.\n\n"
+
+ "set vxlan-tos-ttl ip-version (ipv4|ipv6) vni (vni) udp-src"
+ " (udp-src) udp-dst (udp-dst) ip-tos (ip-tos) ip-ttl (ip-ttl)"
+ " ip-src (ip-src) ip-dst (ip-dst) eth-src (eth-src)"
+ " eth-dst (eth-dst)\n"
+ " Configure the VXLAN encapsulation for flows.\n\n"
+
+ "set nvgre ip-version (ipv4|ipv6) tni (tni) ip-src"
+ " (ip-src) ip-dst (ip-dst) eth-src (eth-src) eth-dst"
+ " (eth-dst)\n"
+ " Configure the NVGRE encapsulation for flows.\n\n"
+
+ "set nvgre-with-vlan ip-version (ipv4|ipv6) tni (tni)"
+ " ip-src (ip-src) ip-dst (ip-dst) vlan-tci (vlan-tci)"
+ " eth-src (eth-src) eth-dst (eth-dst)\n"
+ " Configure the NVGRE encapsulation for flows.\n\n"
+
+ "set raw_encap {flow items}\n"
+ " Configure the encapsulation with raw data.\n\n"
+
+ "set raw_decap {flow items}\n"
+ " Configure the decapsulation with raw data.\n\n"
+
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "traffic_management")) {
+ cmdline_printf(
+ cl,
+ "\n"
+ "Traffic Management:\n"
+ "--------------\n"
+ "show port tm cap (port_id)\n"
+ " Display the port TM capability.\n\n"
+
+ "show port tm level cap (port_id) (level_id)\n"
+ " Display the port TM hierarchical level capability.\n\n"
+
+ "show port tm node cap (port_id) (node_id)\n"
+ " Display the port TM node capability.\n\n"
+
+ "show port tm node type (port_id) (node_id)\n"
+ " Display the port TM node type.\n\n"
+
+ "show port tm node stats (port_id) (node_id) (clear)\n"
+ " Display the port TM node stats.\n\n"
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
+ "set port tm hierarchy default (port_id)\n"
+ " Set default traffic Management hierarchy on a port\n\n"
+#endif
+
+ "add port tm node shaper profile (port_id) (shaper_profile_id)"
+ " (cmit_tb_rate) (cmit_tb_size) (peak_tb_rate) (peak_tb_size)"
+ " (packet_length_adjust)\n"
+ " Add port tm node private shaper profile.\n\n"
+
+ "del port tm node shaper profile (port_id) (shaper_profile_id)\n"
+ " Delete port tm node private shaper profile.\n\n"
+
+ "add port tm node shared shaper (port_id) (shared_shaper_id)"
+ " (shaper_profile_id)\n"
+ " Add/update port tm node shared shaper.\n\n"
+
+ "del port tm node shared shaper (port_id) (shared_shaper_id)\n"
+ " Delete port tm node shared shaper.\n\n"
+
+ "set port tm node shaper profile (port_id) (node_id)"
+ " (shaper_profile_id)\n"
+ " Set port tm node shaper profile.\n\n"
+
+ "add port tm node wred profile (port_id) (wred_profile_id)"
+ " (color_g) (min_th_g) (max_th_g) (maxp_inv_g) (wq_log2_g)"
+ " (color_y) (min_th_y) (max_th_y) (maxp_inv_y) (wq_log2_y)"
+ " (color_r) (min_th_r) (max_th_r) (maxp_inv_r) (wq_log2_r)\n"
+ " Add port tm node wred profile.\n\n"
+
+ "del port tm node wred profile (port_id) (wred_profile_id)\n"
+ " Delete port tm node wred profile.\n\n"
+
+ "add port tm nonleaf node (port_id) (node_id) (parent_node_id)"
+ " (priority) (weight) (level_id) (shaper_profile_id)"
+ " (n_sp_priorities) (stats_mask) (n_shared_shapers)"
+ " [(shared_shaper_id_0) (shared_shaper_id_1)...]\n"
+ " Add port tm nonleaf node.\n\n"
+
+ "add port tm leaf node (port_id) (node_id) (parent_node_id)"
+ " (priority) (weight) (level_id) (shaper_profile_id)"
+ " (cman_mode) (wred_profile_id) (stats_mask) (n_shared_shapers)"
+ " [(shared_shaper_id_0) (shared_shaper_id_1)...]\n"
+ " Add port tm leaf node.\n\n"
+
+ "del port tm node (port_id) (node_id)\n"
+ " Delete port tm node.\n\n"
+
+ "set port tm node parent (port_id) (node_id) (parent_node_id)"
+ " (priority) (weight)\n"
+ " Set port tm node parent.\n\n"
+
+ "suspend port tm node (port_id) (node_id)"
+ " Suspend tm node.\n\n"
+
+ "resume port tm node (port_id) (node_id)"
+ " Resume tm node.\n\n"
+
+ "port tm hierarchy commit (port_id) (clean_on_fail)\n"
+ " Commit tm hierarchy.\n\n"
+
+ "set port tm mark ip_ecn (port) (green) (yellow)"
+ " (red)\n"
+ " Enables/Disables the traffic management marking"
+ " for IP ECN (Explicit Congestion Notification)"
+ " packets on a given port\n\n"
+
+ "set port tm mark ip_dscp (port) (green) (yellow)"
+ " (red)\n"
+ " Enables/Disables the traffic management marking"
+ " on the port for IP dscp packets\n\n"
+
+ "set port tm mark vlan_dei (port) (green) (yellow)"
+ " (red)\n"
+ " Enables/Disables the traffic management marking"
+ " on the port for VLAN packets with DEI enabled\n\n"
+ );
+ }
+
+ if (show_all || !strcmp(res->section, "devices")) {
+ cmdline_printf(
+ cl,
+ "\n"
+ "Device Operations:\n"
+ "--------------\n"
+ "device detach (identifier)\n"
+ " Detach device by identifier.\n\n"
+ );
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_help_long_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, help, "help");
+
+cmdline_parse_token_string_t cmd_help_long_section =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section,
+ "all#control#display#config#"
+ "ports#registers#filters#traffic_management#devices");
+
+cmdline_parse_inst_t cmd_help_long = {
+ .f = cmd_help_long_parsed,
+ .data = NULL,
+ .help_str = "help all|control|display|config|ports|register|"
+ "filters|traffic_management|devices: "
+ "Show help",
+ .tokens = {
+ (void *)&cmd_help_long_help,
+ (void *)&cmd_help_long_section,
+ NULL,
+ },
+};
+
+
+/* *** start/stop/close all ports *** */
+struct cmd_operate_port_result {
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void cmd_operate_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_operate_port_result *res = parsed_result;
+
+ if (!strcmp(res->name, "start"))
+ start_port(RTE_PORT_ALL);
+ else if (!strcmp(res->name, "stop"))
+ stop_port(RTE_PORT_ALL);
+ else if (!strcmp(res->name, "close"))
+ close_port(RTE_PORT_ALL);
+ else if (!strcmp(res->name, "reset"))
+ reset_port(RTE_PORT_ALL);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_port_all_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, keyword,
+ "port");
+cmdline_parse_token_string_t cmd_operate_port_all_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, name,
+ "start#stop#close#reset");
+cmdline_parse_token_string_t cmd_operate_port_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_port_result, value, "all");
+
+cmdline_parse_inst_t cmd_operate_port = {
+ .f = cmd_operate_port_parsed,
+ .data = NULL,
+ .help_str = "port start|stop|close all: Start/Stop/Close/Reset all ports",
+ .tokens = {
+ (void *)&cmd_operate_port_all_cmd,
+ (void *)&cmd_operate_port_all_port,
+ (void *)&cmd_operate_port_all_all,
+ NULL,
+ },
+};
+
+/* *** start/stop/close specific port *** */
+struct cmd_operate_specific_port_result {
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t name;
+ uint8_t value;
+};
+
+static void cmd_operate_specific_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_operate_specific_port_result *res = parsed_result;
+
+ if (!strcmp(res->name, "start"))
+ start_port(res->value);
+ else if (!strcmp(res->name, "stop"))
+ stop_port(res->value);
+ else if (!strcmp(res->name, "close"))
+ close_port(res->value);
+ else if (!strcmp(res->name, "reset"))
+ reset_port(res->value);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_specific_port_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
+ keyword, "port");
+cmdline_parse_token_string_t cmd_operate_specific_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_specific_port_result,
+ name, "start#stop#close#reset");
+cmdline_parse_token_num_t cmd_operate_specific_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_operate_specific_port_result,
+ value, UINT8);
+
+cmdline_parse_inst_t cmd_operate_specific_port = {
+ .f = cmd_operate_specific_port_parsed,
+ .data = NULL,
+ .help_str = "port start|stop|close <port_id>: Start/Stop/Close/Reset port_id",
+ .tokens = {
+ (void *)&cmd_operate_specific_port_cmd,
+ (void *)&cmd_operate_specific_port_port,
+ (void *)&cmd_operate_specific_port_id,
+ NULL,
+ },
+};
+
+/* *** enable port setup (after attach) via iterator or event *** */
+struct cmd_set_port_setup_on_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t setup;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_port_setup_on_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_setup_on_result *res = parsed_result;
+
+ if (strcmp(res->mode, "event") == 0)
+ setup_on_probe_event = true;
+ else if (strcmp(res->mode, "iterator") == 0)
+ setup_on_probe_event = false;
+ else
+ printf("Unknown mode\n");
+}
+
+cmdline_parse_token_string_t cmd_set_port_setup_on_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_setup_on_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_port_setup_on_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_setup_on_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_set_port_setup_on_setup =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_setup_on_result,
+ setup, "setup");
+cmdline_parse_token_string_t cmd_set_port_setup_on_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_setup_on_result,
+ on, "on");
+cmdline_parse_token_string_t cmd_set_port_setup_on_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_setup_on_result,
+ mode, "iterator#event");
+
+cmdline_parse_inst_t cmd_set_port_setup_on = {
+ .f = cmd_set_port_setup_on_parsed,
+ .data = NULL,
+ .help_str = "set port setup on iterator|event",
+ .tokens = {
+ (void *)&cmd_set_port_setup_on_set,
+ (void *)&cmd_set_port_setup_on_port,
+ (void *)&cmd_set_port_setup_on_setup,
+ (void *)&cmd_set_port_setup_on_on,
+ (void *)&cmd_set_port_setup_on_mode,
+ NULL,
+ },
+};
+
+/* *** attach a specified port *** */
+struct cmd_operate_attach_port_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_multi_string_t identifier;
+};
+
+static void cmd_operate_attach_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_operate_attach_port_result *res = parsed_result;
+
+ if (!strcmp(res->keyword, "attach"))
+ attach_port(res->identifier);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_attach_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_operate_attach_port_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ keyword, "attach");
+cmdline_parse_token_string_t cmd_operate_attach_port_identifier =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
+ identifier, TOKEN_STRING_MULTI);
+
+cmdline_parse_inst_t cmd_operate_attach_port = {
+ .f = cmd_operate_attach_port_parsed,
+ .data = NULL,
+ .help_str = "port attach <identifier>: "
+ "(identifier: pci address or virtual dev name)",
+ .tokens = {
+ (void *)&cmd_operate_attach_port_port,
+ (void *)&cmd_operate_attach_port_keyword,
+ (void *)&cmd_operate_attach_port_identifier,
+ NULL,
+ },
+};
+
+/* *** detach a specified port *** */
+struct cmd_operate_detach_port_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ portid_t port_id;
+};
+
+static void cmd_operate_detach_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_operate_detach_port_result *res = parsed_result;
+
+ if (!strcmp(res->keyword, "detach")) {
+ RTE_ETH_VALID_PORTID_OR_RET(res->port_id);
+ detach_port_device(res->port_id);
+ } else {
+ printf("Unknown parameter\n");
+ }
+}
+
+cmdline_parse_token_string_t cmd_operate_detach_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_operate_detach_port_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_port_result,
+ keyword, "detach");
+cmdline_parse_token_num_t cmd_operate_detach_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_operate_detach_port_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_operate_detach_port = {
+ .f = cmd_operate_detach_port_parsed,
+ .data = NULL,
+ .help_str = "port detach <port_id>",
+ .tokens = {
+ (void *)&cmd_operate_detach_port_port,
+ (void *)&cmd_operate_detach_port_keyword,
+ (void *)&cmd_operate_detach_port_port_id,
+ NULL,
+ },
+};
+
+/* *** detach device by identifier *** */
+struct cmd_operate_detach_device_result {
+ cmdline_fixed_string_t device;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t identifier;
+};
+
+static void cmd_operate_detach_device_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_operate_detach_device_result *res = parsed_result;
+
+ if (!strcmp(res->keyword, "detach"))
+ detach_devargs(res->identifier);
+ else
+ printf("Unknown parameter\n");
+}
+
+cmdline_parse_token_string_t cmd_operate_detach_device_device =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+ device, "device");
+cmdline_parse_token_string_t cmd_operate_detach_device_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+ keyword, "detach");
+cmdline_parse_token_string_t cmd_operate_detach_device_identifier =
+ TOKEN_STRING_INITIALIZER(struct cmd_operate_detach_device_result,
+ identifier, NULL);
+
+cmdline_parse_inst_t cmd_operate_detach_device = {
+ .f = cmd_operate_detach_device_parsed,
+ .data = NULL,
+ .help_str = "device detach <identifier>:"
+ "(identifier: pci address or virtual dev name)",
+ .tokens = {
+ (void *)&cmd_operate_detach_device_device,
+ (void *)&cmd_operate_detach_device_keyword,
+ (void *)&cmd_operate_detach_device_identifier,
+ NULL,
+ },
+};
+/* *** configure speed for all ports *** */
+struct cmd_config_speed_all {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t item2;
+ cmdline_fixed_string_t value1;
+ cmdline_fixed_string_t value2;
+};
+
+static int
+parse_and_check_speed_duplex(char *speedstr, char *duplexstr, uint32_t *speed)
+{
+
+ int duplex;
+
+ if (!strcmp(duplexstr, "half")) {
+ duplex = ETH_LINK_HALF_DUPLEX;
+ } else if (!strcmp(duplexstr, "full")) {
+ duplex = ETH_LINK_FULL_DUPLEX;
+ } else if (!strcmp(duplexstr, "auto")) {
+ duplex = ETH_LINK_FULL_DUPLEX;
+ } else {
+ printf("Unknown duplex parameter\n");
+ return -1;
+ }
+
+ if (!strcmp(speedstr, "10")) {
+ *speed = (duplex == ETH_LINK_HALF_DUPLEX) ?
+ ETH_LINK_SPEED_10M_HD : ETH_LINK_SPEED_10M;
+ } else if (!strcmp(speedstr, "100")) {
+ *speed = (duplex == ETH_LINK_HALF_DUPLEX) ?
+ ETH_LINK_SPEED_100M_HD : ETH_LINK_SPEED_100M;
+ } else {
+ if (duplex != ETH_LINK_FULL_DUPLEX) {
+ printf("Invalid speed/duplex parameters\n");
+ return -1;
+ }
+ if (!strcmp(speedstr, "1000")) {
+ *speed = ETH_LINK_SPEED_1G;
+ } else if (!strcmp(speedstr, "10000")) {
+ *speed = ETH_LINK_SPEED_10G;
+ } else if (!strcmp(speedstr, "25000")) {
+ *speed = ETH_LINK_SPEED_25G;
+ } else if (!strcmp(speedstr, "40000")) {
+ *speed = ETH_LINK_SPEED_40G;
+ } else if (!strcmp(speedstr, "50000")) {
+ *speed = ETH_LINK_SPEED_50G;
+ } else if (!strcmp(speedstr, "100000")) {
+ *speed = ETH_LINK_SPEED_100G;
+ } else if (!strcmp(speedstr, "200000")) {
+ *speed = ETH_LINK_SPEED_200G;
+ } else if (!strcmp(speedstr, "auto")) {
+ *speed = ETH_LINK_SPEED_AUTONEG;
+ } else {
+ printf("Unknown speed parameter\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+cmd_config_speed_all_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_speed_all *res = parsed_result;
+ uint32_t link_speed;
+ portid_t pid;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (parse_and_check_speed_duplex(res->value1, res->value2,
+ &link_speed) < 0)
+ return;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ ports[pid].dev_conf.link_speeds = link_speed;
+ }
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_speed_all_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, port, "port");
+cmdline_parse_token_string_t cmd_config_speed_all_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_speed_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, all, "all");
+cmdline_parse_token_string_t cmd_config_speed_all_item1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item1, "speed");
+cmdline_parse_token_string_t cmd_config_speed_all_value1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value1,
+ "10#100#1000#10000#25000#40000#50000#100000#200000#auto");
+cmdline_parse_token_string_t cmd_config_speed_all_item2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, item2, "duplex");
+cmdline_parse_token_string_t cmd_config_speed_all_value2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_all, value2,
+ "half#full#auto");
+
+cmdline_parse_inst_t cmd_config_speed_all = {
+ .f = cmd_config_speed_all_parsed,
+ .data = NULL,
+ .help_str = "port config all speed "
+ "10|100|1000|10000|25000|40000|50000|100000|200000|auto duplex "
+ "half|full|auto",
+ .tokens = {
+ (void *)&cmd_config_speed_all_port,
+ (void *)&cmd_config_speed_all_keyword,
+ (void *)&cmd_config_speed_all_all,
+ (void *)&cmd_config_speed_all_item1,
+ (void *)&cmd_config_speed_all_value1,
+ (void *)&cmd_config_speed_all_item2,
+ (void *)&cmd_config_speed_all_value2,
+ NULL,
+ },
+};
+
+/* *** configure speed for specific port *** */
+struct cmd_config_speed_specific {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ portid_t id;
+ cmdline_fixed_string_t item1;
+ cmdline_fixed_string_t item2;
+ cmdline_fixed_string_t value1;
+ cmdline_fixed_string_t value2;
+};
+
+static void
+cmd_config_speed_specific_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_speed_specific *res = parsed_result;
+ uint32_t link_speed;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ if (parse_and_check_speed_duplex(res->value1, res->value2,
+ &link_speed) < 0)
+ return;
+
+ ports[res->id].dev_conf.link_speeds = link_speed;
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+
+cmdline_parse_token_string_t cmd_config_speed_specific_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_speed_specific_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, keyword,
+ "config");
+cmdline_parse_token_num_t cmd_config_speed_specific_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_speed_specific, id, UINT16);
+cmdline_parse_token_string_t cmd_config_speed_specific_item1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item1,
+ "speed");
+cmdline_parse_token_string_t cmd_config_speed_specific_value1 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value1,
+ "10#100#1000#10000#25000#40000#50000#100000#200000#auto");
+cmdline_parse_token_string_t cmd_config_speed_specific_item2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, item2,
+ "duplex");
+cmdline_parse_token_string_t cmd_config_speed_specific_value2 =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_speed_specific, value2,
+ "half#full#auto");
+
+cmdline_parse_inst_t cmd_config_speed_specific = {
+ .f = cmd_config_speed_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> speed "
+ "10|100|1000|10000|25000|40000|50000|100000|200000|auto duplex "
+ "half|full|auto",
+ .tokens = {
+ (void *)&cmd_config_speed_specific_port,
+ (void *)&cmd_config_speed_specific_keyword,
+ (void *)&cmd_config_speed_specific_id,
+ (void *)&cmd_config_speed_specific_item1,
+ (void *)&cmd_config_speed_specific_value1,
+ (void *)&cmd_config_speed_specific_item2,
+ (void *)&cmd_config_speed_specific_value2,
+ NULL,
+ },
+};
+
+/* *** configure loopback for all ports *** */
+struct cmd_config_loopback_all {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t item;
+ uint32_t mode;
+};
+
+static void
+cmd_config_loopback_all_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_loopback_all *res = parsed_result;
+ portid_t pid;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ ports[pid].dev_conf.lpbk_mode = res->mode;
+ }
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_loopback_all_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_all, port, "port");
+cmdline_parse_token_string_t cmd_config_loopback_all_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_all, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_loopback_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_all, all, "all");
+cmdline_parse_token_string_t cmd_config_loopback_all_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_all, item,
+ "loopback");
+cmdline_parse_token_num_t cmd_config_loopback_all_mode =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_loopback_all, mode, UINT32);
+
+cmdline_parse_inst_t cmd_config_loopback_all = {
+ .f = cmd_config_loopback_all_parsed,
+ .data = NULL,
+ .help_str = "port config all loopback <mode>",
+ .tokens = {
+ (void *)&cmd_config_loopback_all_port,
+ (void *)&cmd_config_loopback_all_keyword,
+ (void *)&cmd_config_loopback_all_all,
+ (void *)&cmd_config_loopback_all_item,
+ (void *)&cmd_config_loopback_all_mode,
+ NULL,
+ },
+};
+
+/* *** configure loopback for specific port *** */
+struct cmd_config_loopback_specific {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint16_t port_id;
+ cmdline_fixed_string_t item;
+ uint32_t mode;
+};
+
+static void
+cmd_config_loopback_specific_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_loopback_specific *res = parsed_result;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %u first\n", res->port_id);
+ return;
+ }
+
+ ports[res->port_id].dev_conf.lpbk_mode = res->mode;
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+
+cmdline_parse_token_string_t cmd_config_loopback_specific_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_specific, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_loopback_specific_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_specific, keyword,
+ "config");
+cmdline_parse_token_num_t cmd_config_loopback_specific_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_loopback_specific, port_id,
+ UINT16);
+cmdline_parse_token_string_t cmd_config_loopback_specific_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_loopback_specific, item,
+ "loopback");
+cmdline_parse_token_num_t cmd_config_loopback_specific_mode =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_loopback_specific, mode,
+ UINT32);
+
+cmdline_parse_inst_t cmd_config_loopback_specific = {
+ .f = cmd_config_loopback_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> loopback <mode>",
+ .tokens = {
+ (void *)&cmd_config_loopback_specific_port,
+ (void *)&cmd_config_loopback_specific_keyword,
+ (void *)&cmd_config_loopback_specific_id,
+ (void *)&cmd_config_loopback_specific_item,
+ (void *)&cmd_config_loopback_specific_mode,
+ NULL,
+ },
+};
+
+/* *** configure txq/rxq, txd/rxd *** */
+struct cmd_config_rx_tx {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_rx_tx_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rx_tx *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+ if (!strcmp(res->name, "rxq")) {
+ if (!res->value && !nb_txq) {
+ printf("Warning: Either rx or tx queues should be non zero\n");
+ return;
+ }
+ if (check_nb_rxq(res->value) != 0)
+ return;
+ nb_rxq = res->value;
+ }
+ else if (!strcmp(res->name, "txq")) {
+ if (!res->value && !nb_rxq) {
+ printf("Warning: Either rx or tx queues should be non zero\n");
+ return;
+ }
+ if (check_nb_txq(res->value) != 0)
+ return;
+ nb_txq = res->value;
+ }
+ else if (!strcmp(res->name, "rxd")) {
+ if (check_nb_rxd(res->value) != 0)
+ return;
+ nb_rxd = res->value;
+ } else if (!strcmp(res->name, "txd")) {
+ if (check_nb_txd(res->value) != 0)
+ return;
+
+ nb_txd = res->value;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ fwd_config_setup();
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_rx_tx_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, port, "port");
+cmdline_parse_token_string_t cmd_config_rx_tx_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, keyword, "config");
+cmdline_parse_token_string_t cmd_config_rx_tx_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, all, "all");
+cmdline_parse_token_string_t cmd_config_rx_tx_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_tx, name,
+ "rxq#txq#rxd#txd");
+cmdline_parse_token_num_t cmd_config_rx_tx_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rx_tx, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_rx_tx = {
+ .f = cmd_config_rx_tx_parsed,
+ .data = NULL,
+ .help_str = "port config all rxq|txq|rxd|txd <value>",
+ .tokens = {
+ (void *)&cmd_config_rx_tx_port,
+ (void *)&cmd_config_rx_tx_keyword,
+ (void *)&cmd_config_rx_tx_all,
+ (void *)&cmd_config_rx_tx_name,
+ (void *)&cmd_config_rx_tx_value,
+ NULL,
+ },
+};
+
+/* *** config max packet length *** */
+struct cmd_config_max_pkt_len_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint32_t value;
+};
+
+static void
+cmd_config_max_pkt_len_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_max_pkt_len_result *res = parsed_result;
+ portid_t pid;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ struct rte_port *port = &ports[pid];
+ uint64_t rx_offloads = port->dev_conf.rxmode.offloads;
+
+ if (!strcmp(res->name, "max-pkt-len")) {
+ if (res->value < RTE_ETHER_MIN_LEN) {
+ printf("max-pkt-len can not be less than %d\n",
+ RTE_ETHER_MIN_LEN);
+ return;
+ }
+ if (res->value == port->dev_conf.rxmode.max_rx_pkt_len)
+ return;
+
+ port->dev_conf.rxmode.max_rx_pkt_len = res->value;
+ if (res->value > RTE_ETHER_MAX_LEN)
+ rx_offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+ else
+ rx_offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
+ port->dev_conf.rxmode.offloads = rx_offloads;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_max_pkt_len_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, all,
+ "all");
+cmdline_parse_token_string_t cmd_config_max_pkt_len_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_pkt_len_result, name,
+ "max-pkt-len");
+cmdline_parse_token_num_t cmd_config_max_pkt_len_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_max_pkt_len_result, value,
+ UINT32);
+
+cmdline_parse_inst_t cmd_config_max_pkt_len = {
+ .f = cmd_config_max_pkt_len_parsed,
+ .data = NULL,
+ .help_str = "port config all max-pkt-len <value>",
+ .tokens = {
+ (void *)&cmd_config_max_pkt_len_port,
+ (void *)&cmd_config_max_pkt_len_keyword,
+ (void *)&cmd_config_max_pkt_len_all,
+ (void *)&cmd_config_max_pkt_len_name,
+ (void *)&cmd_config_max_pkt_len_value,
+ NULL,
+ },
+};
+
+/* *** config max LRO aggregated packet size *** */
+struct cmd_config_max_lro_pkt_size_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint32_t value;
+};
+
+static void
+cmd_config_max_lro_pkt_size_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_max_lro_pkt_size_result *res = parsed_result;
+ portid_t pid;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ struct rte_port *port = &ports[pid];
+
+ if (!strcmp(res->name, "max-lro-pkt-size")) {
+ if (res->value ==
+ port->dev_conf.rxmode.max_lro_pkt_size)
+ return;
+
+ port->dev_conf.rxmode.max_lro_pkt_size = res->value;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_max_lro_pkt_size_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_lro_pkt_size_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_max_lro_pkt_size_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_lro_pkt_size_result,
+ keyword, "config");
+cmdline_parse_token_string_t cmd_config_max_lro_pkt_size_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_lro_pkt_size_result,
+ all, "all");
+cmdline_parse_token_string_t cmd_config_max_lro_pkt_size_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_max_lro_pkt_size_result,
+ name, "max-lro-pkt-size");
+cmdline_parse_token_num_t cmd_config_max_lro_pkt_size_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_max_lro_pkt_size_result,
+ value, UINT32);
+
+cmdline_parse_inst_t cmd_config_max_lro_pkt_size = {
+ .f = cmd_config_max_lro_pkt_size_parsed,
+ .data = NULL,
+ .help_str = "port config all max-lro-pkt-size <value>",
+ .tokens = {
+ (void *)&cmd_config_max_lro_pkt_size_port,
+ (void *)&cmd_config_max_lro_pkt_size_keyword,
+ (void *)&cmd_config_max_lro_pkt_size_all,
+ (void *)&cmd_config_max_lro_pkt_size_name,
+ (void *)&cmd_config_max_lro_pkt_size_value,
+ NULL,
+ },
+};
+
+/* *** configure port MTU *** */
+struct cmd_config_mtu_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t mtu;
+ portid_t port_id;
+ uint16_t value;
+};
+
+static void
+cmd_config_mtu_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_mtu_result *res = parsed_result;
+
+ if (res->value < RTE_ETHER_MIN_LEN) {
+ printf("mtu cannot be less than %d\n", RTE_ETHER_MIN_LEN);
+ return;
+ }
+ port_mtu_set(res->port_id, res->value);
+}
+
+cmdline_parse_token_string_t cmd_config_mtu_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_mtu_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_mtu_mtu =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_mtu_result, keyword,
+ "mtu");
+cmdline_parse_token_num_t cmd_config_mtu_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_config_mtu_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_mtu_result, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_mtu = {
+ .f = cmd_config_mtu_parsed,
+ .data = NULL,
+ .help_str = "port config mtu <port_id> <value>",
+ .tokens = {
+ (void *)&cmd_config_mtu_port,
+ (void *)&cmd_config_mtu_keyword,
+ (void *)&cmd_config_mtu_mtu,
+ (void *)&cmd_config_mtu_port_id,
+ (void *)&cmd_config_mtu_value,
+ NULL,
+ },
+};
+
+/* *** configure rx mode *** */
+struct cmd_config_rx_mode_flag {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_config_rx_mode_flag_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rx_mode_flag *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "drop-en")) {
+ if (!strcmp(res->value, "on"))
+ rx_drop_en = 1;
+ else if (!strcmp(res->value, "off"))
+ rx_drop_en = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, port, "port");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, all, "all");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, name,
+ "drop-en");
+cmdline_parse_token_string_t cmd_config_rx_mode_flag_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rx_mode_flag, value,
+ "on#off");
+
+cmdline_parse_inst_t cmd_config_rx_mode_flag = {
+ .f = cmd_config_rx_mode_flag_parsed,
+ .data = NULL,
+ .help_str = "port config all drop-en on|off",
+ .tokens = {
+ (void *)&cmd_config_rx_mode_flag_port,
+ (void *)&cmd_config_rx_mode_flag_keyword,
+ (void *)&cmd_config_rx_mode_flag_all,
+ (void *)&cmd_config_rx_mode_flag_name,
+ (void *)&cmd_config_rx_mode_flag_value,
+ NULL,
+ },
+};
+
+/* *** configure rss *** */
+struct cmd_config_rss {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_config_rss_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rss *res = parsed_result;
+ struct rte_eth_rss_conf rss_conf = { .rss_key_len = 0, };
+ struct rte_eth_dev_info dev_info = { .flow_type_rss_offloads = 0, };
+ int use_default = 0;
+ int all_updated = 1;
+ int diag;
+ uint16_t i;
+ int ret;
+
+ if (!strcmp(res->value, "all"))
+ rss_conf.rss_hf = ETH_RSS_ETH | ETH_RSS_VLAN | ETH_RSS_IP |
+ ETH_RSS_TCP | ETH_RSS_UDP | ETH_RSS_SCTP |
+ ETH_RSS_L2_PAYLOAD | ETH_RSS_L2TPV3 | ETH_RSS_ESP |
+ ETH_RSS_AH | ETH_RSS_PFCP;
+ else if (!strcmp(res->value, "eth"))
+ rss_conf.rss_hf = ETH_RSS_ETH;
+ else if (!strcmp(res->value, "vlan"))
+ rss_conf.rss_hf = ETH_RSS_VLAN;
+ else if (!strcmp(res->value, "ip"))
+ rss_conf.rss_hf = ETH_RSS_IP;
+ else if (!strcmp(res->value, "udp"))
+ rss_conf.rss_hf = ETH_RSS_UDP;
+ else if (!strcmp(res->value, "tcp"))
+ rss_conf.rss_hf = ETH_RSS_TCP;
+ else if (!strcmp(res->value, "sctp"))
+ rss_conf.rss_hf = ETH_RSS_SCTP;
+ else if (!strcmp(res->value, "ether"))
+ rss_conf.rss_hf = ETH_RSS_L2_PAYLOAD;
+ else if (!strcmp(res->value, "port"))
+ rss_conf.rss_hf = ETH_RSS_PORT;
+ else if (!strcmp(res->value, "vxlan"))
+ rss_conf.rss_hf = ETH_RSS_VXLAN;
+ else if (!strcmp(res->value, "geneve"))
+ rss_conf.rss_hf = ETH_RSS_GENEVE;
+ else if (!strcmp(res->value, "nvgre"))
+ rss_conf.rss_hf = ETH_RSS_NVGRE;
+ else if (!strcmp(res->value, "l3-src-only"))
+ rss_conf.rss_hf = ETH_RSS_L3_SRC_ONLY;
+ else if (!strcmp(res->value, "l3-dst-only"))
+ rss_conf.rss_hf = ETH_RSS_L3_DST_ONLY;
+ else if (!strcmp(res->value, "l4-src-only"))
+ rss_conf.rss_hf = ETH_RSS_L4_SRC_ONLY;
+ else if (!strcmp(res->value, "l4-dst-only"))
+ rss_conf.rss_hf = ETH_RSS_L4_DST_ONLY;
+ else if (!strcmp(res->value, "l2-src-only"))
+ rss_conf.rss_hf = ETH_RSS_L2_SRC_ONLY;
+ else if (!strcmp(res->value, "l2-dst-only"))
+ rss_conf.rss_hf = ETH_RSS_L2_DST_ONLY;
+ else if (!strcmp(res->value, "l2tpv3"))
+ rss_conf.rss_hf = ETH_RSS_L2TPV3;
+ else if (!strcmp(res->value, "esp"))
+ rss_conf.rss_hf = ETH_RSS_ESP;
+ else if (!strcmp(res->value, "ah"))
+ rss_conf.rss_hf = ETH_RSS_AH;
+ else if (!strcmp(res->value, "pfcp"))
+ rss_conf.rss_hf = ETH_RSS_PFCP;
+ else if (!strcmp(res->value, "none"))
+ rss_conf.rss_hf = 0;
+ else if (!strcmp(res->value, "default"))
+ use_default = 1;
+ else if (isdigit(res->value[0]) && atoi(res->value) > 0 &&
+ atoi(res->value) < 64)
+ rss_conf.rss_hf = 1ULL << atoi(res->value);
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+ rss_conf.rss_key = NULL;
+ /* Update global configuration for RSS types. */
+ RTE_ETH_FOREACH_DEV(i) {
+ struct rte_eth_rss_conf local_rss_conf;
+
+ ret = eth_dev_info_get_print_err(i, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (use_default)
+ rss_conf.rss_hf = dev_info.flow_type_rss_offloads;
+
+ local_rss_conf = rss_conf;
+ local_rss_conf.rss_hf = rss_conf.rss_hf &
+ dev_info.flow_type_rss_offloads;
+ if (local_rss_conf.rss_hf != rss_conf.rss_hf) {
+ printf("Port %u modified RSS hash function based on hardware support,"
+ "requested:%#"PRIx64" configured:%#"PRIx64"\n",
+ i, rss_conf.rss_hf, local_rss_conf.rss_hf);
+ }
+ diag = rte_eth_dev_rss_hash_update(i, &local_rss_conf);
+ if (diag < 0) {
+ all_updated = 0;
+ printf("Configuration of RSS hash at ethernet port %d "
+ "failed with error (%d): %s.\n",
+ i, -diag, strerror(-diag));
+ }
+ }
+ if (all_updated && !use_default) {
+ rss_hf = rss_conf.rss_hf;
+ printf("rss_hf %#"PRIx64"\n", rss_hf);
+ }
+}
+
+cmdline_parse_token_string_t cmd_config_rss_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, keyword, "config");
+cmdline_parse_token_string_t cmd_config_rss_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, all, "all");
+cmdline_parse_token_string_t cmd_config_rss_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, name, "rss");
+cmdline_parse_token_string_t cmd_config_rss_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss, value, NULL);
+
+cmdline_parse_inst_t cmd_config_rss = {
+ .f = cmd_config_rss_parsed,
+ .data = NULL,
+ .help_str = "port config all rss "
+ "all|default|eth|vlan|ip|tcp|udp|sctp|ether|port|vxlan|geneve|"
+ "nvgre|vxlan-gpe|l2tpv3|esp|ah|pfcp|none|<flowtype_id>",
+ .tokens = {
+ (void *)&cmd_config_rss_port,
+ (void *)&cmd_config_rss_keyword,
+ (void *)&cmd_config_rss_all,
+ (void *)&cmd_config_rss_name,
+ (void *)&cmd_config_rss_value,
+ NULL,
+ },
+};
+
+/* *** configure rss hash key *** */
+struct cmd_config_rss_hash_key {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t rss_hash_key;
+ cmdline_fixed_string_t rss_type;
+ cmdline_fixed_string_t key;
+};
+
+static uint8_t
+hexa_digit_to_value(char hexa_digit)
+{
+ if ((hexa_digit >= '0') && (hexa_digit <= '9'))
+ return (uint8_t) (hexa_digit - '0');
+ if ((hexa_digit >= 'a') && (hexa_digit <= 'f'))
+ return (uint8_t) ((hexa_digit - 'a') + 10);
+ if ((hexa_digit >= 'A') && (hexa_digit <= 'F'))
+ return (uint8_t) ((hexa_digit - 'A') + 10);
+ /* Invalid hexa digit */
+ return 0xFF;
+}
+
+static uint8_t
+parse_and_check_key_hexa_digit(char *key, int idx)
+{
+ uint8_t hexa_v;
+
+ hexa_v = hexa_digit_to_value(key[idx]);
+ if (hexa_v == 0xFF)
+ printf("invalid key: character %c at position %d is not a "
+ "valid hexa digit\n", key[idx], idx);
+ return hexa_v;
+}
+
+static void
+cmd_config_rss_hash_key_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rss_hash_key *res = parsed_result;
+ uint8_t hash_key[RSS_HASH_KEY_LENGTH];
+ uint8_t xdgt0;
+ uint8_t xdgt1;
+ int i;
+ struct rte_eth_dev_info dev_info;
+ uint8_t hash_key_size;
+ uint32_t key_len;
+ int ret;
+
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (dev_info.hash_key_size > 0 &&
+ dev_info.hash_key_size <= sizeof(hash_key))
+ hash_key_size = dev_info.hash_key_size;
+ else {
+ printf("dev_info did not provide a valid hash key size\n");
+ return;
+ }
+ /* Check the length of the RSS hash key */
+ key_len = strlen(res->key);
+ if (key_len != (hash_key_size * 2)) {
+ printf("key length: %d invalid - key must be a string of %d"
+ " hexa-decimal numbers\n",
+ (int) key_len, hash_key_size * 2);
+ return;
+ }
+ /* Translate RSS hash key into binary representation */
+ for (i = 0; i < hash_key_size; i++) {
+ xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+ if (xdgt0 == 0xFF)
+ return;
+ xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+ if (xdgt1 == 0xFF)
+ return;
+ hash_key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1);
+ }
+ port_rss_hash_key_update(res->port_id, res->rss_type, hash_key,
+ hash_key_size);
+}
+
+cmdline_parse_token_string_t cmd_config_rss_hash_key_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, config,
+ "config");
+cmdline_parse_token_num_t cmd_config_rss_hash_key_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rss_hash_key, port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_hash_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key,
+ rss_hash_key, "rss-hash-key");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_rss_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, rss_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv4-other#ipv6#ipv6-frag#ipv6-tcp#ipv6-udp#"
+ "ipv6-sctp#ipv6-other#l2-payload#ipv6-ex#"
+ "ipv6-tcp-ex#ipv6-udp-ex#"
+ "l3-src-only#l3-dst-only#l4-src-only#l4-dst-only#"
+ "l2-src-only#l2-dst-only#s-vlan#c-vlan#"
+ "l2tpv3#esp#ah#pfcp");
+cmdline_parse_token_string_t cmd_config_rss_hash_key_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_hash_key, key, NULL);
+
+cmdline_parse_inst_t cmd_config_rss_hash_key = {
+ .f = cmd_config_rss_hash_key_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rss-hash-key "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2-payload|ipv6-ex|ipv6-tcp-ex|ipv6-udp-ex|"
+ "l3-src-only|l3-dst-only|l4-src-only|l4-dst-only|"
+ "l2-src-only|l2-dst-only|s-vlan|c-vlan|"
+ "l2tpv3|esp|ah|pfcp "
+ "<string of hex digits (variable length, NIC dependent)>",
+ .tokens = {
+ (void *)&cmd_config_rss_hash_key_port,
+ (void *)&cmd_config_rss_hash_key_config,
+ (void *)&cmd_config_rss_hash_key_port_id,
+ (void *)&cmd_config_rss_hash_key_rss_hash_key,
+ (void *)&cmd_config_rss_hash_key_rss_type,
+ (void *)&cmd_config_rss_hash_key_value,
+ NULL,
+ },
+};
+
+/* *** configure port rxq/txq ring size *** */
+struct cmd_config_rxtx_ring_size {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t portid;
+ cmdline_fixed_string_t rxtxq;
+ uint16_t qid;
+ cmdline_fixed_string_t rsize;
+ uint16_t size;
+};
+
+static void
+cmd_config_rxtx_ring_size_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rxtx_ring_size *res = parsed_result;
+ struct rte_port *port;
+ uint8_t isrx;
+
+ if (port_id_is_invalid(res->portid, ENABLED_WARN))
+ return;
+
+ if (res->portid == (portid_t)RTE_PORT_ALL) {
+ printf("Invalid port id\n");
+ return;
+ }
+
+ port = &ports[res->portid];
+
+ if (!strcmp(res->rxtxq, "rxq"))
+ isrx = 1;
+ else if (!strcmp(res->rxtxq, "txq"))
+ isrx = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isrx && rx_queue_id_is_invalid(res->qid))
+ return;
+ else if (!isrx && tx_queue_id_is_invalid(res->qid))
+ return;
+
+ if (isrx && res->size != 0 && res->size <= rx_free_thresh) {
+ printf("Invalid rx ring_size, must > rx_free_thresh: %d\n",
+ rx_free_thresh);
+ return;
+ }
+
+ if (isrx)
+ port->nb_rx_desc[res->qid] = res->size;
+ else
+ port->nb_tx_desc[res->qid] = res->size;
+
+ cmd_reconfig_device_queue(res->portid, 0, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_rxtx_ring_size_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_rxtx_ring_size_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ config, "config");
+cmdline_parse_token_num_t cmd_config_rxtx_ring_size_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ portid, UINT16);
+cmdline_parse_token_string_t cmd_config_rxtx_ring_size_rxtxq =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ rxtxq, "rxq#txq");
+cmdline_parse_token_num_t cmd_config_rxtx_ring_size_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ qid, UINT16);
+cmdline_parse_token_string_t cmd_config_rxtx_ring_size_rsize =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ rsize, "ring_size");
+cmdline_parse_token_num_t cmd_config_rxtx_ring_size_size =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_ring_size,
+ size, UINT16);
+
+cmdline_parse_inst_t cmd_config_rxtx_ring_size = {
+ .f = cmd_config_rxtx_ring_size_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rxq|txq <queue_id> ring_size <value>",
+ .tokens = {
+ (void *)&cmd_config_rxtx_ring_size_port,
+ (void *)&cmd_config_rxtx_ring_size_config,
+ (void *)&cmd_config_rxtx_ring_size_portid,
+ (void *)&cmd_config_rxtx_ring_size_rxtxq,
+ (void *)&cmd_config_rxtx_ring_size_qid,
+ (void *)&cmd_config_rxtx_ring_size_rsize,
+ (void *)&cmd_config_rxtx_ring_size_size,
+ NULL,
+ },
+};
+
+/* *** configure port rxq/txq start/stop *** */
+struct cmd_config_rxtx_queue {
+ cmdline_fixed_string_t port;
+ portid_t portid;
+ cmdline_fixed_string_t rxtxq;
+ uint16_t qid;
+ cmdline_fixed_string_t opname;
+};
+
+static void
+cmd_config_rxtx_queue_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_rxtx_queue *res = parsed_result;
+ uint8_t isrx;
+ uint8_t isstart;
+ int ret = 0;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ if (port_id_is_invalid(res->portid, ENABLED_WARN))
+ return;
+
+ if (port_is_started(res->portid) != 1) {
+ printf("Please start port %u first\n", res->portid);
+ return;
+ }
+
+ if (!strcmp(res->rxtxq, "rxq"))
+ isrx = 1;
+ else if (!strcmp(res->rxtxq, "txq"))
+ isrx = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isrx && rx_queue_id_is_invalid(res->qid))
+ return;
+ else if (!isrx && tx_queue_id_is_invalid(res->qid))
+ return;
+
+ if (!strcmp(res->opname, "start"))
+ isstart = 1;
+ else if (!strcmp(res->opname, "stop"))
+ isstart = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isstart && isrx)
+ ret = rte_eth_dev_rx_queue_start(res->portid, res->qid);
+ else if (!isstart && isrx)
+ ret = rte_eth_dev_rx_queue_stop(res->portid, res->qid);
+ else if (isstart && !isrx)
+ ret = rte_eth_dev_tx_queue_start(res->portid, res->qid);
+ else
+ ret = rte_eth_dev_tx_queue_stop(res->portid, res->qid);
+
+ if (ret == -ENOTSUP)
+ printf("Function not supported in PMD driver\n");
+}
+
+cmdline_parse_token_string_t cmd_config_rxtx_queue_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, port, "port");
+cmdline_parse_token_num_t cmd_config_rxtx_queue_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, portid, UINT16);
+cmdline_parse_token_string_t cmd_config_rxtx_queue_rxtxq =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, rxtxq, "rxq#txq");
+cmdline_parse_token_num_t cmd_config_rxtx_queue_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rxtx_queue, qid, UINT16);
+cmdline_parse_token_string_t cmd_config_rxtx_queue_opname =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rxtx_queue, opname,
+ "start#stop");
+
+cmdline_parse_inst_t cmd_config_rxtx_queue = {
+ .f = cmd_config_rxtx_queue_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> rxq|txq <queue_id> start|stop",
+ .tokens = {
+ (void *)&cmd_config_rxtx_queue_port,
+ (void *)&cmd_config_rxtx_queue_portid,
+ (void *)&cmd_config_rxtx_queue_rxtxq,
+ (void *)&cmd_config_rxtx_queue_qid,
+ (void *)&cmd_config_rxtx_queue_opname,
+ NULL,
+ },
+};
+
+/* *** configure port rxq/txq deferred start on/off *** */
+struct cmd_config_deferred_start_rxtx_queue {
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rxtxq;
+ uint16_t qid;
+ cmdline_fixed_string_t opname;
+ cmdline_fixed_string_t state;
+};
+
+static void
+cmd_config_deferred_start_rxtx_queue_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_deferred_start_rxtx_queue *res = parsed_result;
+ struct rte_port *port;
+ uint8_t isrx;
+ uint8_t ison;
+ uint8_t needreconfig = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (port_is_started(res->port_id) != 0) {
+ printf("Please stop port %u first\n", res->port_id);
+ return;
+ }
+
+ port = &ports[res->port_id];
+
+ isrx = !strcmp(res->rxtxq, "rxq");
+
+ if (isrx && rx_queue_id_is_invalid(res->qid))
+ return;
+ else if (!isrx && tx_queue_id_is_invalid(res->qid))
+ return;
+
+ ison = !strcmp(res->state, "on");
+
+ if (isrx && port->rx_conf[res->qid].rx_deferred_start != ison) {
+ port->rx_conf[res->qid].rx_deferred_start = ison;
+ needreconfig = 1;
+ } else if (!isrx && port->tx_conf[res->qid].tx_deferred_start != ison) {
+ port->tx_conf[res->qid].tx_deferred_start = ison;
+ needreconfig = 1;
+ }
+
+ if (needreconfig)
+ cmd_reconfig_device_queue(res->port_id, 0, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_deferred_start_rxtx_queue_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ port, "port");
+cmdline_parse_token_num_t cmd_config_deferred_start_rxtx_queue_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_deferred_start_rxtx_queue_rxtxq =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ rxtxq, "rxq#txq");
+cmdline_parse_token_num_t cmd_config_deferred_start_rxtx_queue_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ qid, UINT16);
+cmdline_parse_token_string_t cmd_config_deferred_start_rxtx_queue_opname =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ opname, "deferred_start");
+cmdline_parse_token_string_t cmd_config_deferred_start_rxtx_queue_state =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_deferred_start_rxtx_queue,
+ state, "on#off");
+
+cmdline_parse_inst_t cmd_config_deferred_start_rxtx_queue = {
+ .f = cmd_config_deferred_start_rxtx_queue_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> rxq|txq <queue_id> deferred_start on|off",
+ .tokens = {
+ (void *)&cmd_config_deferred_start_rxtx_queue_port,
+ (void *)&cmd_config_deferred_start_rxtx_queue_port_id,
+ (void *)&cmd_config_deferred_start_rxtx_queue_rxtxq,
+ (void *)&cmd_config_deferred_start_rxtx_queue_qid,
+ (void *)&cmd_config_deferred_start_rxtx_queue_opname,
+ (void *)&cmd_config_deferred_start_rxtx_queue_state,
+ NULL,
+ },
+};
+
+/* *** configure port rxq/txq setup *** */
+struct cmd_setup_rxtx_queue {
+ cmdline_fixed_string_t port;
+ portid_t portid;
+ cmdline_fixed_string_t rxtxq;
+ uint16_t qid;
+ cmdline_fixed_string_t setup;
+};
+
+/* Common CLI fields for queue setup */
+cmdline_parse_token_string_t cmd_setup_rxtx_queue_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_setup_rxtx_queue, port, "port");
+cmdline_parse_token_num_t cmd_setup_rxtx_queue_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_setup_rxtx_queue, portid, UINT16);
+cmdline_parse_token_string_t cmd_setup_rxtx_queue_rxtxq =
+ TOKEN_STRING_INITIALIZER(struct cmd_setup_rxtx_queue, rxtxq, "rxq#txq");
+cmdline_parse_token_num_t cmd_setup_rxtx_queue_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_setup_rxtx_queue, qid, UINT16);
+cmdline_parse_token_string_t cmd_setup_rxtx_queue_setup =
+ TOKEN_STRING_INITIALIZER(struct cmd_setup_rxtx_queue, setup, "setup");
+
+static void
+cmd_setup_rxtx_queue_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_setup_rxtx_queue *res = parsed_result;
+ struct rte_port *port;
+ struct rte_mempool *mp;
+ unsigned int socket_id;
+ uint8_t isrx = 0;
+ int ret;
+
+ if (port_id_is_invalid(res->portid, ENABLED_WARN))
+ return;
+
+ if (res->portid == (portid_t)RTE_PORT_ALL) {
+ printf("Invalid port id\n");
+ return;
+ }
+
+ if (!strcmp(res->rxtxq, "rxq"))
+ isrx = 1;
+ else if (!strcmp(res->rxtxq, "txq"))
+ isrx = 0;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ if (isrx && rx_queue_id_is_invalid(res->qid)) {
+ printf("Invalid rx queue\n");
+ return;
+ } else if (!isrx && tx_queue_id_is_invalid(res->qid)) {
+ printf("Invalid tx queue\n");
+ return;
+ }
+
+ port = &ports[res->portid];
+ if (isrx) {
+ socket_id = rxring_numa[res->portid];
+ if (!numa_support || socket_id == NUMA_NO_CONFIG)
+ socket_id = port->socket_id;
+
+ mp = mbuf_pool_find(socket_id);
+ if (mp == NULL) {
+ printf("Failed to setup RX queue: "
+ "No mempool allocation"
+ " on the socket %d\n",
+ rxring_numa[res->portid]);
+ return;
+ }
+ ret = rte_eth_rx_queue_setup(res->portid,
+ res->qid,
+ port->nb_rx_desc[res->qid],
+ socket_id,
+ &port->rx_conf[res->qid],
+ mp);
+ if (ret)
+ printf("Failed to setup RX queue\n");
+ } else {
+ socket_id = txring_numa[res->portid];
+ if (!numa_support || socket_id == NUMA_NO_CONFIG)
+ socket_id = port->socket_id;
+
+ ret = rte_eth_tx_queue_setup(res->portid,
+ res->qid,
+ port->nb_tx_desc[res->qid],
+ socket_id,
+ &port->tx_conf[res->qid]);
+ if (ret)
+ printf("Failed to setup TX queue\n");
+ }
+}
+
+cmdline_parse_inst_t cmd_setup_rxtx_queue = {
+ .f = cmd_setup_rxtx_queue_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> rxq|txq <queue_idx> setup",
+ .tokens = {
+ (void *)&cmd_setup_rxtx_queue_port,
+ (void *)&cmd_setup_rxtx_queue_portid,
+ (void *)&cmd_setup_rxtx_queue_rxtxq,
+ (void *)&cmd_setup_rxtx_queue_qid,
+ (void *)&cmd_setup_rxtx_queue_setup,
+ NULL,
+ },
+};
+
+
+/* *** Configure RSS RETA *** */
+struct cmd_config_rss_reta {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ portid_t port_id;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t list_name;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static int
+parse_reta_config(const char *str,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries)
+{
+ int i;
+ unsigned size;
+ uint16_t hash_index, idx, shift;
+ uint16_t nb_queue;
+ char s[256];
+ const char *p, *p0 = str;
+ char *end;
+ enum fieldnames {
+ FLD_HASH_INDEX = 0,
+ FLD_QUEUE,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] ||
+ int_fld[i] > 65535)
+ return -1;
+ }
+
+ hash_index = (uint16_t)int_fld[FLD_HASH_INDEX];
+ nb_queue = (uint16_t)int_fld[FLD_QUEUE];
+
+ if (hash_index >= nb_entries) {
+ printf("Invalid RETA hash index=%d\n", hash_index);
+ return -1;
+ }
+
+ idx = hash_index / RTE_RETA_GROUP_SIZE;
+ shift = hash_index % RTE_RETA_GROUP_SIZE;
+ reta_conf[idx].mask |= (1ULL << shift);
+ reta_conf[idx].reta[shift] = nb_queue;
+ }
+
+ return 0;
+}
+
+static void
+cmd_set_rss_reta_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret;
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rss_reta_entry64 reta_conf[8];
+ struct cmd_config_rss_reta *res = parsed_result;
+
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (dev_info.reta_size == 0) {
+ printf("Redirection table size is 0 which is "
+ "invalid for RSS\n");
+ return;
+ } else
+ printf("The reta size of port %d is %u\n",
+ res->port_id, dev_info.reta_size);
+ if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) {
+ printf("Currently do not support more than %u entries of "
+ "redirection table\n", ETH_RSS_RETA_SIZE_512);
+ return;
+ }
+
+ memset(reta_conf, 0, sizeof(reta_conf));
+ if (!strcmp(res->list_name, "reta")) {
+ if (parse_reta_config(res->list_of_items, reta_conf,
+ dev_info.reta_size)) {
+ printf("Invalid RSS Redirection Table "
+ "config entered\n");
+ return;
+ }
+ ret = rte_eth_dev_rss_reta_update(res->port_id,
+ reta_conf, dev_info.reta_size);
+ if (ret != 0)
+ printf("Bad redirection table parameter, "
+ "return code = %d \n", ret);
+ }
+}
+
+cmdline_parse_token_string_t cmd_config_rss_reta_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, port, "port");
+cmdline_parse_token_string_t cmd_config_rss_reta_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, keyword, "config");
+cmdline_parse_token_num_t cmd_config_rss_reta_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_rss_reta, port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_rss_reta_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, name, "rss");
+cmdline_parse_token_string_t cmd_config_rss_reta_list_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_name, "reta");
+cmdline_parse_token_string_t cmd_config_rss_reta_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_rss_reta, list_of_items,
+ NULL);
+cmdline_parse_inst_t cmd_config_rss_reta = {
+ .f = cmd_set_rss_reta_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rss reta <hash,queue[,hash,queue]*>",
+ .tokens = {
+ (void *)&cmd_config_rss_reta_port,
+ (void *)&cmd_config_rss_reta_keyword,
+ (void *)&cmd_config_rss_reta_port_id,
+ (void *)&cmd_config_rss_reta_name,
+ (void *)&cmd_config_rss_reta_list_name,
+ (void *)&cmd_config_rss_reta_list_of_items,
+ NULL,
+ },
+};
+
+/* *** SHOW PORT RETA INFO *** */
+struct cmd_showport_reta {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rss;
+ cmdline_fixed_string_t reta;
+ uint16_t size;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static int
+showport_parse_reta_config(struct rte_eth_rss_reta_entry64 *conf,
+ uint16_t nb_entries,
+ char *str)
+{
+ uint32_t size;
+ const char *p, *p0 = str;
+ char s[256];
+ char *end;
+ char *str_fld[8];
+ uint16_t i;
+ uint16_t num = (nb_entries + RTE_RETA_GROUP_SIZE - 1) /
+ RTE_RETA_GROUP_SIZE;
+ int ret;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ p++;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+ size = p0 - p;
+ if (size >= sizeof(s)) {
+ printf("The string size exceeds the internal buffer size\n");
+ return -1;
+ }
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, num, ',');
+ if (ret <= 0 || ret != num) {
+ printf("The bits of masks do not match the number of "
+ "reta entries: %u\n", num);
+ return -1;
+ }
+ for (i = 0; i < ret; i++)
+ conf[i].mask = (uint64_t)strtoul(str_fld[i], &end, 0);
+
+ return 0;
+}
+
+static void
+cmd_showport_reta_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showport_reta *res = parsed_result;
+ struct rte_eth_rss_reta_entry64 reta_conf[8];
+ struct rte_eth_dev_info dev_info;
+ uint16_t max_reta_size;
+ int ret;
+
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ max_reta_size = RTE_MIN(dev_info.reta_size, ETH_RSS_RETA_SIZE_512);
+ if (res->size == 0 || res->size > max_reta_size) {
+ printf("Invalid redirection table size: %u (1-%u)\n",
+ res->size, max_reta_size);
+ return;
+ }
+
+ memset(reta_conf, 0, sizeof(reta_conf));
+ if (showport_parse_reta_config(reta_conf, res->size,
+ res->list_of_items) < 0) {
+ printf("Invalid string: %s for reta masks\n",
+ res->list_of_items);
+ return;
+ }
+ port_rss_reta_info(res->port_id, reta_conf, res->size);
+}
+
+cmdline_parse_token_string_t cmd_showport_reta_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, show, "show");
+cmdline_parse_token_string_t cmd_showport_reta_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, port, "port");
+cmdline_parse_token_num_t cmd_showport_reta_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, port_id, UINT16);
+cmdline_parse_token_string_t cmd_showport_reta_rss =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, rss, "rss");
+cmdline_parse_token_string_t cmd_showport_reta_reta =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta, reta, "reta");
+cmdline_parse_token_num_t cmd_showport_reta_size =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_reta, size, UINT16);
+cmdline_parse_token_string_t cmd_showport_reta_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_reta,
+ list_of_items, NULL);
+
+cmdline_parse_inst_t cmd_showport_reta = {
+ .f = cmd_showport_reta_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rss reta <size> <mask0[,mask1]*>",
+ .tokens = {
+ (void *)&cmd_showport_reta_show,
+ (void *)&cmd_showport_reta_port,
+ (void *)&cmd_showport_reta_port_id,
+ (void *)&cmd_showport_reta_rss,
+ (void *)&cmd_showport_reta_reta,
+ (void *)&cmd_showport_reta_size,
+ (void *)&cmd_showport_reta_list_of_items,
+ NULL,
+ },
+};
+
+/* *** Show RSS hash configuration *** */
+struct cmd_showport_rss_hash {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rss_hash;
+ cmdline_fixed_string_t rss_type;
+ cmdline_fixed_string_t key; /* optional argument */
+};
+
+static void cmd_showport_rss_hash_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *show_rss_key)
+{
+ struct cmd_showport_rss_hash *res = parsed_result;
+
+ port_rss_hash_conf_show(res->port_id, show_rss_key != NULL);
+}
+
+cmdline_parse_token_string_t cmd_showport_rss_hash_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, show, "show");
+cmdline_parse_token_string_t cmd_showport_rss_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, port, "port");
+cmdline_parse_token_num_t cmd_showport_rss_hash_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_rss_hash, port_id, UINT16);
+cmdline_parse_token_string_t cmd_showport_rss_hash_rss_hash =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, rss_hash,
+ "rss-hash");
+cmdline_parse_token_string_t cmd_showport_rss_hash_rss_key =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_rss_hash, key, "key");
+
+cmdline_parse_inst_t cmd_showport_rss_hash = {
+ .f = cmd_showport_rss_hash_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rss-hash",
+ .tokens = {
+ (void *)&cmd_showport_rss_hash_show,
+ (void *)&cmd_showport_rss_hash_port,
+ (void *)&cmd_showport_rss_hash_port_id,
+ (void *)&cmd_showport_rss_hash_rss_hash,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_showport_rss_hash_key = {
+ .f = cmd_showport_rss_hash_parsed,
+ .data = (void *)1,
+ .help_str = "show port <port_id> rss-hash key",
+ .tokens = {
+ (void *)&cmd_showport_rss_hash_show,
+ (void *)&cmd_showport_rss_hash_port,
+ (void *)&cmd_showport_rss_hash_port_id,
+ (void *)&cmd_showport_rss_hash_rss_hash,
+ (void *)&cmd_showport_rss_hash_rss_key,
+ NULL,
+ },
+};
+
+/* *** Configure DCB *** */
+struct cmd_config_dcb {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t dcb;
+ cmdline_fixed_string_t vt;
+ cmdline_fixed_string_t vt_en;
+ uint8_t num_tcs;
+ cmdline_fixed_string_t pfc;
+ cmdline_fixed_string_t pfc_en;
+};
+
+static void
+cmd_config_dcb_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_dcb *res = parsed_result;
+ portid_t port_id = res->port_id;
+ struct rte_port *port;
+ uint8_t pfc_en;
+ int ret;
+
+ port = &ports[port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", port_id);
+ return;
+ }
+
+ if ((res->num_tcs != ETH_4_TCS) && (res->num_tcs != ETH_8_TCS)) {
+ printf("The invalid number of traffic class,"
+ " only 4 or 8 allowed.\n");
+ return;
+ }
+
+ if (nb_fwd_lcores < res->num_tcs) {
+ printf("nb_cores shouldn't be less than number of TCs.\n");
+ return;
+ }
+ if (!strncmp(res->pfc_en, "on", 2))
+ pfc_en = 1;
+ else
+ pfc_en = 0;
+
+ /* DCB in VT mode */
+ if (!strncmp(res->vt_en, "on", 2))
+ ret = init_port_dcb_config(port_id, DCB_VT_ENABLED,
+ (enum rte_eth_nb_tcs)res->num_tcs,
+ pfc_en);
+ else
+ ret = init_port_dcb_config(port_id, DCB_ENABLED,
+ (enum rte_eth_nb_tcs)res->num_tcs,
+ pfc_en);
+
+
+ if (ret != 0) {
+ printf("Cannot initialize network ports.\n");
+ return;
+ }
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_dcb_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, port, "port");
+cmdline_parse_token_string_t cmd_config_dcb_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, config, "config");
+cmdline_parse_token_num_t cmd_config_dcb_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_dcb_dcb =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, dcb, "dcb");
+cmdline_parse_token_string_t cmd_config_dcb_vt =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt, "vt");
+cmdline_parse_token_string_t cmd_config_dcb_vt_en =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, vt_en, "on#off");
+cmdline_parse_token_num_t cmd_config_dcb_num_tcs =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_dcb, num_tcs, UINT8);
+cmdline_parse_token_string_t cmd_config_dcb_pfc=
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc, "pfc");
+cmdline_parse_token_string_t cmd_config_dcb_pfc_en =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_dcb, pfc_en, "on#off");
+
+cmdline_parse_inst_t cmd_config_dcb = {
+ .f = cmd_config_dcb_parsed,
+ .data = NULL,
+ .help_str = "port config <port-id> dcb vt on|off <num_tcs> pfc on|off",
+ .tokens = {
+ (void *)&cmd_config_dcb_port,
+ (void *)&cmd_config_dcb_config,
+ (void *)&cmd_config_dcb_port_id,
+ (void *)&cmd_config_dcb_dcb,
+ (void *)&cmd_config_dcb_vt,
+ (void *)&cmd_config_dcb_vt_en,
+ (void *)&cmd_config_dcb_num_tcs,
+ (void *)&cmd_config_dcb_pfc,
+ (void *)&cmd_config_dcb_pfc_en,
+ NULL,
+ },
+};
+
+/* *** configure number of packets per burst *** */
+struct cmd_config_burst {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_burst_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_burst *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ uint16_t rec_nb_pkts;
+ int ret;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "burst")) {
+ if (res->value == 0) {
+ /* If user gives a value of zero, query the PMD for
+ * its recommended Rx burst size. Testpmd uses a single
+ * size for all ports, so assume all ports are the same
+ * NIC model and use the values from Port 0.
+ */
+ ret = eth_dev_info_get_print_err(0, &dev_info);
+ if (ret != 0)
+ return;
+
+ rec_nb_pkts = dev_info.default_rxportconf.burst_size;
+
+ if (rec_nb_pkts == 0) {
+ printf("PMD does not recommend a burst size.\n"
+ "User provided value must be between"
+ " 1 and %d\n", MAX_PKT_BURST);
+ return;
+ } else if (rec_nb_pkts > MAX_PKT_BURST) {
+ printf("PMD recommended burst size of %d"
+ " exceeds maximum value of %d\n",
+ rec_nb_pkts, MAX_PKT_BURST);
+ return;
+ }
+ printf("Using PMD-provided burst value of %d\n",
+ rec_nb_pkts);
+ nb_pkt_per_burst = rec_nb_pkts;
+ } else if (res->value > MAX_PKT_BURST) {
+ printf("burst must be >= 1 && <= %d\n", MAX_PKT_BURST);
+ return;
+ } else
+ nb_pkt_per_burst = res->value;
+ } else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_burst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, port, "port");
+cmdline_parse_token_string_t cmd_config_burst_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, keyword, "config");
+cmdline_parse_token_string_t cmd_config_burst_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, all, "all");
+cmdline_parse_token_string_t cmd_config_burst_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_burst, name, "burst");
+cmdline_parse_token_num_t cmd_config_burst_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_burst, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_burst = {
+ .f = cmd_config_burst_parsed,
+ .data = NULL,
+ .help_str = "port config all burst <value>",
+ .tokens = {
+ (void *)&cmd_config_burst_port,
+ (void *)&cmd_config_burst_keyword,
+ (void *)&cmd_config_burst_all,
+ (void *)&cmd_config_burst_name,
+ (void *)&cmd_config_burst_value,
+ NULL,
+ },
+};
+
+/* *** configure rx/tx queues *** */
+struct cmd_config_thresh {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint8_t value;
+};
+
+static void
+cmd_config_thresh_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_thresh *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "txpt"))
+ tx_pthresh = res->value;
+ else if(!strcmp(res->name, "txht"))
+ tx_hthresh = res->value;
+ else if(!strcmp(res->name, "txwt"))
+ tx_wthresh = res->value;
+ else if(!strcmp(res->name, "rxpt"))
+ rx_pthresh = res->value;
+ else if(!strcmp(res->name, "rxht"))
+ rx_hthresh = res->value;
+ else if(!strcmp(res->name, "rxwt"))
+ rx_wthresh = res->value;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_thresh_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, port, "port");
+cmdline_parse_token_string_t cmd_config_thresh_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, keyword, "config");
+cmdline_parse_token_string_t cmd_config_thresh_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, all, "all");
+cmdline_parse_token_string_t cmd_config_thresh_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_thresh, name,
+ "txpt#txht#txwt#rxpt#rxht#rxwt");
+cmdline_parse_token_num_t cmd_config_thresh_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_thresh, value, UINT8);
+
+cmdline_parse_inst_t cmd_config_thresh = {
+ .f = cmd_config_thresh_parsed,
+ .data = NULL,
+ .help_str = "port config all txpt|txht|txwt|rxpt|rxht|rxwt <value>",
+ .tokens = {
+ (void *)&cmd_config_thresh_port,
+ (void *)&cmd_config_thresh_keyword,
+ (void *)&cmd_config_thresh_all,
+ (void *)&cmd_config_thresh_name,
+ (void *)&cmd_config_thresh_value,
+ NULL,
+ },
+};
+
+/* *** configure free/rs threshold *** */
+struct cmd_config_threshold {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t name;
+ uint16_t value;
+};
+
+static void
+cmd_config_threshold_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_threshold *res = parsed_result;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ if (!strcmp(res->name, "txfreet"))
+ tx_free_thresh = res->value;
+ else if (!strcmp(res->name, "txrst"))
+ tx_rs_thresh = res->value;
+ else if (!strcmp(res->name, "rxfreet"))
+ rx_free_thresh = res->value;
+ else {
+ printf("Unknown parameter\n");
+ return;
+ }
+
+ init_port_config();
+
+ cmd_reconfig_device_queue(RTE_PORT_ALL, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_config_threshold_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, port, "port");
+cmdline_parse_token_string_t cmd_config_threshold_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, keyword,
+ "config");
+cmdline_parse_token_string_t cmd_config_threshold_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, all, "all");
+cmdline_parse_token_string_t cmd_config_threshold_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_threshold, name,
+ "txfreet#txrst#rxfreet");
+cmdline_parse_token_num_t cmd_config_threshold_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_threshold, value, UINT16);
+
+cmdline_parse_inst_t cmd_config_threshold = {
+ .f = cmd_config_threshold_parsed,
+ .data = NULL,
+ .help_str = "port config all txfreet|txrst|rxfreet <value>",
+ .tokens = {
+ (void *)&cmd_config_threshold_port,
+ (void *)&cmd_config_threshold_keyword,
+ (void *)&cmd_config_threshold_all,
+ (void *)&cmd_config_threshold_name,
+ (void *)&cmd_config_threshold_value,
+ NULL,
+ },
+};
+
+/* *** stop *** */
+struct cmd_stop_result {
+ cmdline_fixed_string_t stop;
+};
+
+static void cmd_stop_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ stop_packet_forwarding();
+}
+
+cmdline_parse_token_string_t cmd_stop_stop =
+ TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop");
+
+cmdline_parse_inst_t cmd_stop = {
+ .f = cmd_stop_parsed,
+ .data = NULL,
+ .help_str = "stop: Stop packet forwarding",
+ .tokens = {
+ (void *)&cmd_stop_stop,
+ NULL,
+ },
+};
+
+/* *** SET CORELIST and PORTLIST CONFIGURATION *** */
+
+unsigned int
+parse_item_list(char* str, const char* item_name, unsigned int max_items,
+ unsigned int *parsed_items, int check_unique_values)
+{
+ unsigned int nb_item;
+ unsigned int value;
+ unsigned int i;
+ unsigned int j;
+ int value_ok;
+ char c;
+
+ /*
+ * First parse all items in the list and store their value.
+ */
+ value = 0;
+ nb_item = 0;
+ value_ok = 0;
+ for (i = 0; i < strnlen(str, STR_TOKEN_SIZE); i++) {
+ c = str[i];
+ if ((c >= '0') && (c <= '9')) {
+ value = (unsigned int) (value * 10 + (c - '0'));
+ value_ok = 1;
+ continue;
+ }
+ if (c != ',') {
+ printf("character %c is not a decimal digit\n", c);
+ return 0;
+ }
+ if (! value_ok) {
+ printf("No valid value before comma\n");
+ return 0;
+ }
+ if (nb_item < max_items) {
+ parsed_items[nb_item] = value;
+ value_ok = 0;
+ value = 0;
+ }
+ nb_item++;
+ }
+ if (nb_item >= max_items) {
+ printf("Number of %s = %u > %u (maximum items)\n",
+ item_name, nb_item + 1, max_items);
+ return 0;
+ }
+ parsed_items[nb_item++] = value;
+ if (! check_unique_values)
+ return nb_item;
+
+ /*
+ * Then, check that all values in the list are differents.
+ * No optimization here...
+ */
+ for (i = 0; i < nb_item; i++) {
+ for (j = i + 1; j < nb_item; j++) {
+ if (parsed_items[j] == parsed_items[i]) {
+ printf("duplicated %s %u at index %u and %u\n",
+ item_name, parsed_items[i], i, j);
+ return 0;
+ }
+ }
+ }
+ return nb_item;
+}
+
+struct cmd_set_list_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t list_name;
+ cmdline_fixed_string_t list_of_items;
+};
+
+static void cmd_set_list_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_list_result *res;
+ union {
+ unsigned int lcorelist[RTE_MAX_LCORE];
+ unsigned int portlist[RTE_MAX_ETHPORTS];
+ } parsed_items;
+ unsigned int nb_item;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ res = parsed_result;
+ if (!strcmp(res->list_name, "corelist")) {
+ nb_item = parse_item_list(res->list_of_items, "core",
+ RTE_MAX_LCORE,
+ parsed_items.lcorelist, 1);
+ if (nb_item > 0) {
+ set_fwd_lcores_list(parsed_items.lcorelist, nb_item);
+ fwd_config_setup();
+ }
+ return;
+ }
+ if (!strcmp(res->list_name, "portlist")) {
+ nb_item = parse_item_list(res->list_of_items, "port",
+ RTE_MAX_ETHPORTS,
+ parsed_items.portlist, 1);
+ if (nb_item > 0) {
+ set_fwd_ports_list(parsed_items.portlist, nb_item);
+ fwd_config_setup();
+ }
+ }
+}
+
+cmdline_parse_token_string_t cmd_set_list_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, cmd_keyword,
+ "set");
+cmdline_parse_token_string_t cmd_set_list_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_name,
+ "corelist#portlist");
+cmdline_parse_token_string_t cmd_set_list_of_items =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_list_result, list_of_items,
+ NULL);
+
+cmdline_parse_inst_t cmd_set_fwd_list = {
+ .f = cmd_set_list_parsed,
+ .data = NULL,
+ .help_str = "set corelist|portlist <list0[,list1]*>",
+ .tokens = {
+ (void *)&cmd_set_list_keyword,
+ (void *)&cmd_set_list_name,
+ (void *)&cmd_set_list_of_items,
+ NULL,
+ },
+};
+
+/* *** SET COREMASK and PORTMASK CONFIGURATION *** */
+
+struct cmd_setmask_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mask;
+ uint64_t hexavalue;
+};
+
+static void cmd_set_mask_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_setmask_result *res = parsed_result;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+ if (!strcmp(res->mask, "coremask")) {
+ set_fwd_lcores_mask(res->hexavalue);
+ fwd_config_setup();
+ } else if (!strcmp(res->mask, "portmask")) {
+ set_fwd_ports_mask(res->hexavalue);
+ fwd_config_setup();
+ }
+}
+
+cmdline_parse_token_string_t cmd_setmask_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, set, "set");
+cmdline_parse_token_string_t cmd_setmask_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_setmask_result, mask,
+ "coremask#portmask");
+cmdline_parse_token_num_t cmd_setmask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_setmask_result, hexavalue, UINT64);
+
+cmdline_parse_inst_t cmd_set_fwd_mask = {
+ .f = cmd_set_mask_parsed,
+ .data = NULL,
+ .help_str = "set coremask|portmask <hexadecimal value>",
+ .tokens = {
+ (void *)&cmd_setmask_set,
+ (void *)&cmd_setmask_mask,
+ (void *)&cmd_setmask_value,
+ NULL,
+ },
+};
+
+/*
+ * SET NBPORT, NBCORE, PACKET BURST, and VERBOSE LEVEL CONFIGURATION
+ */
+struct cmd_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t what;
+ uint16_t value;
+};
+
+static void cmd_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_result *res = parsed_result;
+ if (!strcmp(res->what, "nbport")) {
+ set_fwd_ports_number(res->value);
+ fwd_config_setup();
+ } else if (!strcmp(res->what, "nbcore")) {
+ set_fwd_lcores_number(res->value);
+ fwd_config_setup();
+ } else if (!strcmp(res->what, "burst"))
+ set_nb_pkt_per_burst(res->value);
+ else if (!strcmp(res->what, "verbose"))
+ set_verbose_level(res->value);
+}
+
+cmdline_parse_token_string_t cmd_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_result, set, "set");
+cmdline_parse_token_string_t cmd_set_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_result, what,
+ "nbport#nbcore#burst#verbose");
+cmdline_parse_token_num_t cmd_set_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_result, value, UINT16);
+
+cmdline_parse_inst_t cmd_set_numbers = {
+ .f = cmd_set_parsed,
+ .data = NULL,
+ .help_str = "set nbport|nbcore|burst|verbose <value>",
+ .tokens = {
+ (void *)&cmd_set_set,
+ (void *)&cmd_set_what,
+ (void *)&cmd_set_value,
+ NULL,
+ },
+};
+
+/* *** SET LOG LEVEL CONFIGURATION *** */
+
+struct cmd_set_log_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t log;
+ cmdline_fixed_string_t type;
+ uint32_t level;
+};
+
+static void
+cmd_set_log_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_log_result *res;
+ int ret;
+
+ res = parsed_result;
+ if (!strcmp(res->type, "global"))
+ rte_log_set_global_level(res->level);
+ else {
+ ret = rte_log_set_level_regexp(res->type, res->level);
+ if (ret < 0)
+ printf("Unable to set log level\n");
+ }
+}
+
+cmdline_parse_token_string_t cmd_set_log_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_log_result, set, "set");
+cmdline_parse_token_string_t cmd_set_log_log =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_log_result, log, "log");
+cmdline_parse_token_string_t cmd_set_log_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_log_result, type, NULL);
+cmdline_parse_token_num_t cmd_set_log_level =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_log_result, level, UINT32);
+
+cmdline_parse_inst_t cmd_set_log = {
+ .f = cmd_set_log_parsed,
+ .data = NULL,
+ .help_str = "set log global|<type> <level>",
+ .tokens = {
+ (void *)&cmd_set_log_set,
+ (void *)&cmd_set_log_log,
+ (void *)&cmd_set_log_type,
+ (void *)&cmd_set_log_level,
+ NULL,
+ },
+};
+
+/* *** SET SEGMENT LENGTHS OF TXONLY PACKETS *** */
+
+struct cmd_set_txpkts_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t txpkts;
+ cmdline_fixed_string_t seg_lengths;
+};
+
+static void
+cmd_set_txpkts_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_txpkts_result *res;
+ unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
+ unsigned int nb_segs;
+
+ res = parsed_result;
+ nb_segs = parse_item_list(res->seg_lengths, "segment lengths",
+ RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+ if (nb_segs > 0)
+ set_tx_pkt_segments(seg_lengths, nb_segs);
+}
+
+cmdline_parse_token_string_t cmd_set_txpkts_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ cmd_keyword, "set");
+cmdline_parse_token_string_t cmd_set_txpkts_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ txpkts, "txpkts");
+cmdline_parse_token_string_t cmd_set_txpkts_lengths =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txpkts_result,
+ seg_lengths, NULL);
+
+cmdline_parse_inst_t cmd_set_txpkts = {
+ .f = cmd_set_txpkts_parsed,
+ .data = NULL,
+ .help_str = "set txpkts <len0[,len1]*>",
+ .tokens = {
+ (void *)&cmd_set_txpkts_keyword,
+ (void *)&cmd_set_txpkts_name,
+ (void *)&cmd_set_txpkts_lengths,
+ NULL,
+ },
+};
+
+/* *** SET COPY AND SPLIT POLICY ON TX PACKETS *** */
+
+struct cmd_set_txsplit_result {
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t txsplit;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_txsplit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_txsplit_result *res;
+
+ res = parsed_result;
+ set_tx_pkt_split(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_set_txsplit_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ cmd_keyword, "set");
+cmdline_parse_token_string_t cmd_set_txsplit_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ txsplit, "txsplit");
+cmdline_parse_token_string_t cmd_set_txsplit_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_txsplit_result,
+ mode, NULL);
+
+cmdline_parse_inst_t cmd_set_txsplit = {
+ .f = cmd_set_txsplit_parsed,
+ .data = NULL,
+ .help_str = "set txsplit on|off|rand",
+ .tokens = {
+ (void *)&cmd_set_txsplit_keyword,
+ (void *)&cmd_set_txsplit_name,
+ (void *)&cmd_set_txsplit_mode,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE ALL VLAN IDENTIFIERS TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_rx_vlan_filter_all_result {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t all;
+ portid_t port_id;
+};
+
+static void
+cmd_rx_vlan_filter_all_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_rx_vlan_filter_all_result *res = parsed_result;
+
+ if (!strcmp(res->what, "add"))
+ rx_vlan_all_filter_set(res->port_id, 1);
+ else
+ rx_vlan_all_filter_set(res->port_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ what, "add#rm");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_all_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_rx_vlan_filter_all_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_all_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_rx_vlan_filter_all = {
+ .f = cmd_rx_vlan_filter_all_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm all <port_id>: "
+ "Add/Remove all identifiers to/from the set of VLAN "
+ "identifiers filtered by a port",
+ .tokens = {
+ (void *)&cmd_rx_vlan_filter_all_rx_vlan,
+ (void *)&cmd_rx_vlan_filter_all_what,
+ (void *)&cmd_rx_vlan_filter_all_all,
+ (void *)&cmd_rx_vlan_filter_all_portid,
+ NULL,
+ },
+};
+
+/* *** VLAN OFFLOAD SET ON A PORT *** */
+struct cmd_vlan_offload_result {
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vlan_type;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t port_id;
+};
+
+static void
+cmd_vlan_offload_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int on;
+ struct cmd_vlan_offload_result *res = parsed_result;
+ char *str;
+ int i, len = 0;
+ portid_t port_id = 0;
+ unsigned int tmp;
+
+ str = res->port_id;
+ len = strnlen(str, STR_TOKEN_SIZE);
+ i = 0;
+ /* Get port_id first */
+ while(i < len){
+ if(str[i] == ',')
+ break;
+
+ i++;
+ }
+ str[i]='\0';
+ tmp = strtoul(str, NULL, 0);
+ /* If port_id greater that what portid_t can represent, return */
+ if(tmp >= RTE_MAX_ETHPORTS)
+ return;
+ port_id = (portid_t)tmp;
+
+ if (!strcmp(res->on, "on"))
+ on = 1;
+ else
+ on = 0;
+
+ if (!strcmp(res->what, "strip"))
+ rx_vlan_strip_set(port_id, on);
+ else if(!strcmp(res->what, "stripq")){
+ uint16_t queue_id = 0;
+
+ /* No queue_id, return */
+ if(i + 1 >= len) {
+ printf("must specify (port,queue_id)\n");
+ return;
+ }
+ tmp = strtoul(str + i + 1, NULL, 0);
+ /* If queue_id greater that what 16-bits can represent, return */
+ if(tmp > 0xffff)
+ return;
+
+ queue_id = (uint16_t)tmp;
+ rx_vlan_strip_set_on_queue(port_id, queue_id, on);
+ }
+ else if (!strcmp(res->what, "filter"))
+ rx_vlan_filter_set(port_id, on);
+ else if (!strcmp(res->what, "qinq_strip"))
+ rx_vlan_qinq_strip_set(port_id, on);
+ else
+ vlan_extend_set(port_id, on);
+
+ return;
+}
+
+cmdline_parse_token_string_t cmd_vlan_offload_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vlan_offload_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vlan_offload_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ what, "strip#filter#qinq_strip#extend#stripq");
+cmdline_parse_token_string_t cmd_vlan_offload_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ on, "on#off");
+cmdline_parse_token_string_t cmd_vlan_offload_portid =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_offload_result,
+ port_id, NULL);
+
+cmdline_parse_inst_t cmd_vlan_offload = {
+ .f = cmd_vlan_offload_parsed,
+ .data = NULL,
+ .help_str = "vlan set strip|filter|qinq_strip|extend|stripq on|off "
+ "<port_id[,queue_id]>: "
+ "Strip/Filter/QinQ for rx side Extend for both rx/tx sides",
+ .tokens = {
+ (void *)&cmd_vlan_offload_vlan,
+ (void *)&cmd_vlan_offload_set,
+ (void *)&cmd_vlan_offload_what,
+ (void *)&cmd_vlan_offload_on,
+ (void *)&cmd_vlan_offload_portid,
+ NULL,
+ },
+};
+
+/* *** VLAN TPID SET ON A PORT *** */
+struct cmd_vlan_tpid_result {
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vlan_type;
+ cmdline_fixed_string_t what;
+ uint16_t tp_id;
+ portid_t port_id;
+};
+
+static void
+cmd_vlan_tpid_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vlan_tpid_result *res = parsed_result;
+ enum rte_vlan_type vlan_type;
+
+ if (!strcmp(res->vlan_type, "inner"))
+ vlan_type = ETH_VLAN_TYPE_INNER;
+ else if (!strcmp(res->vlan_type, "outer"))
+ vlan_type = ETH_VLAN_TYPE_OUTER;
+ else {
+ printf("Unknown vlan type\n");
+ return;
+ }
+ vlan_tpid_set(res->port_id, vlan_type, res->tp_id);
+}
+
+cmdline_parse_token_string_t cmd_vlan_tpid_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vlan_tpid_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vlan_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ vlan_type, "inner#outer");
+cmdline_parse_token_string_t cmd_vlan_tpid_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vlan_tpid_result,
+ what, "tpid");
+cmdline_parse_token_num_t cmd_vlan_tpid_tpid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result,
+ tp_id, UINT16);
+cmdline_parse_token_num_t cmd_vlan_tpid_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vlan_tpid_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_vlan_tpid = {
+ .f = cmd_vlan_tpid_parsed,
+ .data = NULL,
+ .help_str = "vlan set inner|outer tpid <tp_id> <port_id>: "
+ "Set the VLAN Ether type",
+ .tokens = {
+ (void *)&cmd_vlan_tpid_vlan,
+ (void *)&cmd_vlan_tpid_set,
+ (void *)&cmd_vlan_type,
+ (void *)&cmd_vlan_tpid_what,
+ (void *)&cmd_vlan_tpid_tpid,
+ (void *)&cmd_vlan_tpid_portid,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_rx_vlan_filter_result {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ uint16_t vlan_id;
+ portid_t port_id;
+};
+
+static void
+cmd_rx_vlan_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_rx_vlan_filter_result *res = parsed_result;
+
+ if (!strcmp(res->what, "add"))
+ rx_vft_set(res->port_id, res->vlan_id, 1);
+ else
+ rx_vft_set(res->port_id, res->vlan_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_rx_vlan_filter_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_rx_vlan_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_rx_vlan_filter_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ vlan_id, UINT16);
+cmdline_parse_token_num_t cmd_rx_vlan_filter_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rx_vlan_filter_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_rx_vlan_filter = {
+ .f = cmd_rx_vlan_filter_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm <vlan_id> <port_id>: "
+ "Add/Remove a VLAN identifier to/from the set of VLAN "
+ "identifiers filtered by a port",
+ .tokens = {
+ (void *)&cmd_rx_vlan_filter_rx_vlan,
+ (void *)&cmd_rx_vlan_filter_what,
+ (void *)&cmd_rx_vlan_filter_vlanid,
+ (void *)&cmd_rx_vlan_filter_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_set_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ portid_t port_id;
+ uint16_t vlan_id;
+};
+
+static void
+cmd_tx_vlan_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_vlan_set_result *res = parsed_result;
+
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ tx_vlan_set(res->port_id, res->vlan_id);
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_result,
+ set, "set");
+cmdline_parse_token_num_t cmd_tx_vlan_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_tx_vlan_set_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_result,
+ vlan_id, UINT16);
+
+cmdline_parse_inst_t cmd_tx_vlan_set = {
+ .f = cmd_tx_vlan_set_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set <port_id> <vlan_id>: "
+ "Enable hardware insertion of a single VLAN header "
+ "with a given TAG Identifier in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_tx_vlan,
+ (void *)&cmd_tx_vlan_set_set,
+ (void *)&cmd_tx_vlan_set_portid,
+ (void *)&cmd_tx_vlan_set_vlanid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE INSERTION OF Double VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_set_qinq_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ portid_t port_id;
+ uint16_t vlan_id;
+ uint16_t vlan_id_outer;
+};
+
+static void
+cmd_tx_vlan_set_qinq_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_vlan_set_qinq_result *res = parsed_result;
+
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ tx_qinq_set(res->port_id, res->vlan_id, res->vlan_id_outer);
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_qinq_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ set, "set");
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ vlan_id, UINT16);
+cmdline_parse_token_num_t cmd_tx_vlan_set_qinq_vlanid_outer =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_qinq_result,
+ vlan_id_outer, UINT16);
+
+cmdline_parse_inst_t cmd_tx_vlan_set_qinq = {
+ .f = cmd_tx_vlan_set_qinq_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set <port_id> <vlan_id> <outer_vlan_id>: "
+ "Enable hardware insertion of double VLAN header "
+ "with given TAG Identifiers in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_qinq_tx_vlan,
+ (void *)&cmd_tx_vlan_set_qinq_set,
+ (void *)&cmd_tx_vlan_set_qinq_portid,
+ (void *)&cmd_tx_vlan_set_qinq_vlanid,
+ (void *)&cmd_tx_vlan_set_qinq_vlanid_outer,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE PORT BASED TX VLAN INSERTION *** */
+struct cmd_tx_vlan_set_pvid_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t pvid;
+ portid_t port_id;
+ uint16_t vlan_id;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_tx_vlan_set_pvid_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_vlan_set_pvid_result *res = parsed_result;
+
+ if (strcmp(res->mode, "on") == 0)
+ tx_vlan_pvid_set(res->port_id, res->vlan_id, 1);
+ else
+ tx_vlan_pvid_set(res->port_id, res->vlan_id, 0);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_pvid =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ pvid, "pvid");
+cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_tx_vlan_set_pvid_vlan_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ vlan_id, UINT16);
+cmdline_parse_token_string_t cmd_tx_vlan_set_pvid_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_set_pvid_result,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_tx_vlan_set_pvid = {
+ .f = cmd_tx_vlan_set_pvid_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan set pvid <port_id> <vlan_id> on|off",
+ .tokens = {
+ (void *)&cmd_tx_vlan_set_pvid_tx_vlan,
+ (void *)&cmd_tx_vlan_set_pvid_set,
+ (void *)&cmd_tx_vlan_set_pvid_pvid,
+ (void *)&cmd_tx_vlan_set_pvid_port_id,
+ (void *)&cmd_tx_vlan_set_pvid_vlan_id,
+ (void *)&cmd_tx_vlan_set_pvid_mode,
+ NULL,
+ },
+};
+
+/* *** DISABLE HARDWARE INSERTION OF VLAN HEADER IN TX PACKETS *** */
+struct cmd_tx_vlan_reset_result {
+ cmdline_fixed_string_t tx_vlan;
+ cmdline_fixed_string_t reset;
+ portid_t port_id;
+};
+
+static void
+cmd_tx_vlan_reset_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_vlan_reset_result *res = parsed_result;
+
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ tx_vlan_reset(res->port_id);
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_tx_vlan_reset_tx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ tx_vlan, "tx_vlan");
+cmdline_parse_token_string_t cmd_tx_vlan_reset_reset =
+ TOKEN_STRING_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ reset, "reset");
+cmdline_parse_token_num_t cmd_tx_vlan_reset_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tx_vlan_reset_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_tx_vlan_reset = {
+ .f = cmd_tx_vlan_reset_parsed,
+ .data = NULL,
+ .help_str = "tx_vlan reset <port_id>: Disable hardware insertion of a "
+ "VLAN header in packets sent on a port",
+ .tokens = {
+ (void *)&cmd_tx_vlan_reset_tx_vlan,
+ (void *)&cmd_tx_vlan_reset_reset,
+ (void *)&cmd_tx_vlan_reset_portid,
+ NULL,
+ },
+};
+
+
+/* *** ENABLE HARDWARE INSERTION OF CHECKSUM IN TX PACKETS *** */
+struct cmd_csum_result {
+ cmdline_fixed_string_t csum;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t proto;
+ cmdline_fixed_string_t hwsw;
+ portid_t port_id;
+};
+
+static void
+csum_show(int port_id)
+{
+ struct rte_eth_dev_info dev_info;
+ uint64_t tx_offloads;
+ int ret;
+
+ tx_offloads = ports[port_id].dev_conf.txmode.offloads;
+ printf("Parse tunnel is %s\n",
+ (ports[port_id].parse_tunnel) ? "on" : "off");
+ printf("IP checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_IPV4_CKSUM) ? "hw" : "sw");
+ printf("UDP checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_UDP_CKSUM) ? "hw" : "sw");
+ printf("TCP checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_TCP_CKSUM) ? "hw" : "sw");
+ printf("SCTP checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_SCTP_CKSUM) ? "hw" : "sw");
+ printf("Outer-Ip checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) ? "hw" : "sw");
+ printf("Outer-Udp checksum offload is %s\n",
+ (tx_offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) ? "hw" : "sw");
+
+ /* display warnings if configuration is not supported by the NIC */
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if ((tx_offloads & DEV_TX_OFFLOAD_IPV4_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) == 0) {
+ printf("Warning: hardware IP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((tx_offloads & DEV_TX_OFFLOAD_UDP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) {
+ printf("Warning: hardware UDP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((tx_offloads & DEV_TX_OFFLOAD_TCP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) {
+ printf("Warning: hardware TCP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((tx_offloads & DEV_TX_OFFLOAD_SCTP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) == 0) {
+ printf("Warning: hardware SCTP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((tx_offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) == 0) {
+ printf("Warning: hardware outer IP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+ if ((tx_offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
+ == 0) {
+ printf("Warning: hardware outer UDP checksum enabled but not "
+ "supported by port %d\n", port_id);
+ }
+}
+
+static void
+cmd_config_queue_tx_offloads(struct rte_port *port)
+{
+ int k;
+
+ /* Apply queue tx offloads configuration */
+ for (k = 0; k < port->dev_info.max_rx_queues; k++)
+ port->tx_conf[k].offloads =
+ port->dev_conf.txmode.offloads;
+}
+
+static void
+cmd_csum_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_csum_result *res = parsed_result;
+ int hw = 0;
+ uint64_t csum_offloads = 0;
+ struct rte_eth_dev_info dev_info;
+ int ret;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN)) {
+ printf("invalid port %d\n", res->port_id);
+ return;
+ }
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (!strcmp(res->mode, "set")) {
+
+ if (!strcmp(res->hwsw, "hw"))
+ hw = 1;
+
+ if (!strcmp(res->proto, "ip")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_IPV4_CKSUM)) {
+ csum_offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
+ } else {
+ printf("IP checksum offload is not supported "
+ "by port %u\n", res->port_id);
+ }
+ } else if (!strcmp(res->proto, "udp")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_UDP_CKSUM)) {
+ csum_offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
+ } else {
+ printf("UDP checksum offload is not supported "
+ "by port %u\n", res->port_id);
+ }
+ } else if (!strcmp(res->proto, "tcp")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_TCP_CKSUM)) {
+ csum_offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
+ } else {
+ printf("TCP checksum offload is not supported "
+ "by port %u\n", res->port_id);
+ }
+ } else if (!strcmp(res->proto, "sctp")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_SCTP_CKSUM)) {
+ csum_offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
+ } else {
+ printf("SCTP checksum offload is not supported "
+ "by port %u\n", res->port_id);
+ }
+ } else if (!strcmp(res->proto, "outer-ip")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)) {
+ csum_offloads |=
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM;
+ } else {
+ printf("Outer IP checksum offload is not "
+ "supported by port %u\n", res->port_id);
+ }
+ } else if (!strcmp(res->proto, "outer-udp")) {
+ if (hw == 0 || (dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)) {
+ csum_offloads |=
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM;
+ } else {
+ printf("Outer UDP checksum offload is not "
+ "supported by port %u\n", res->port_id);
+ }
+ }
+
+ if (hw) {
+ ports[res->port_id].dev_conf.txmode.offloads |=
+ csum_offloads;
+ } else {
+ ports[res->port_id].dev_conf.txmode.offloads &=
+ (~csum_offloads);
+ }
+ cmd_config_queue_tx_offloads(&ports[res->port_id]);
+ }
+ csum_show(res->port_id);
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_csum_csum =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ csum, "csum");
+cmdline_parse_token_string_t cmd_csum_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ mode, "set");
+cmdline_parse_token_string_t cmd_csum_proto =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ proto, "ip#tcp#udp#sctp#outer-ip#outer-udp");
+cmdline_parse_token_string_t cmd_csum_hwsw =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ hwsw, "hw#sw");
+cmdline_parse_token_num_t cmd_csum_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_csum_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_csum_set = {
+ .f = cmd_csum_parsed,
+ .data = NULL,
+ .help_str = "csum set ip|tcp|udp|sctp|outer-ip|outer-udp hw|sw <port_id>: "
+ "Enable/Disable hardware calculation of L3/L4 checksum when "
+ "using csum forward engine",
+ .tokens = {
+ (void *)&cmd_csum_csum,
+ (void *)&cmd_csum_mode,
+ (void *)&cmd_csum_proto,
+ (void *)&cmd_csum_hwsw,
+ (void *)&cmd_csum_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_csum_mode_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_result,
+ mode, "show");
+
+cmdline_parse_inst_t cmd_csum_show = {
+ .f = cmd_csum_parsed,
+ .data = NULL,
+ .help_str = "csum show <port_id>: Show checksum offload configuration",
+ .tokens = {
+ (void *)&cmd_csum_csum,
+ (void *)&cmd_csum_mode_show,
+ (void *)&cmd_csum_portid,
+ NULL,
+ },
+};
+
+/* Enable/disable tunnel parsing */
+struct cmd_csum_tunnel_result {
+ cmdline_fixed_string_t csum;
+ cmdline_fixed_string_t parse;
+ cmdline_fixed_string_t onoff;
+ portid_t port_id;
+};
+
+static void
+cmd_csum_tunnel_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_csum_tunnel_result *res = parsed_result;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (!strcmp(res->onoff, "on"))
+ ports[res->port_id].parse_tunnel = 1;
+ else
+ ports[res->port_id].parse_tunnel = 0;
+
+ csum_show(res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_csum_tunnel_csum =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ csum, "csum");
+cmdline_parse_token_string_t cmd_csum_tunnel_parse =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ parse, "parse-tunnel");
+cmdline_parse_token_string_t cmd_csum_tunnel_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_csum_tunnel_result,
+ onoff, "on#off");
+cmdline_parse_token_num_t cmd_csum_tunnel_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_csum_tunnel_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_csum_tunnel = {
+ .f = cmd_csum_tunnel_parsed,
+ .data = NULL,
+ .help_str = "csum parse-tunnel on|off <port_id>: "
+ "Enable/Disable parsing of tunnels for csum engine",
+ .tokens = {
+ (void *)&cmd_csum_tunnel_csum,
+ (void *)&cmd_csum_tunnel_parse,
+ (void *)&cmd_csum_tunnel_onoff,
+ (void *)&cmd_csum_tunnel_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE SEGMENTATION IN TX NON-TUNNELED PACKETS *** */
+struct cmd_tso_set_result {
+ cmdline_fixed_string_t tso;
+ cmdline_fixed_string_t mode;
+ uint16_t tso_segsz;
+ portid_t port_id;
+};
+
+static void
+cmd_tso_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tso_set_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ int ret;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ if (!strcmp(res->mode, "set"))
+ ports[res->port_id].tso_segsz = res->tso_segsz;
+
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if ((ports[res->port_id].tso_segsz != 0) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) {
+ printf("Error: TSO is not supported by port %d\n",
+ res->port_id);
+ return;
+ }
+
+ if (ports[res->port_id].tso_segsz == 0) {
+ ports[res->port_id].dev_conf.txmode.offloads &=
+ ~DEV_TX_OFFLOAD_TCP_TSO;
+ printf("TSO for non-tunneled packets is disabled\n");
+ } else {
+ ports[res->port_id].dev_conf.txmode.offloads |=
+ DEV_TX_OFFLOAD_TCP_TSO;
+ printf("TSO segment size for non-tunneled packets is %d\n",
+ ports[res->port_id].tso_segsz);
+ }
+ cmd_config_queue_tx_offloads(&ports[res->port_id]);
+
+ /* display warnings if configuration is not supported by the NIC */
+ ret = eth_dev_info_get_print_err(res->port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if ((ports[res->port_id].tso_segsz != 0) &&
+ (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) {
+ printf("Warning: TSO enabled but not "
+ "supported by port %d\n", res->port_id);
+ }
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_tso_set_tso =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ tso, "tso");
+cmdline_parse_token_string_t cmd_tso_set_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ mode, "set");
+cmdline_parse_token_num_t cmd_tso_set_tso_segsz =
+ TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result,
+ tso_segsz, UINT16);
+cmdline_parse_token_num_t cmd_tso_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_tso_set = {
+ .f = cmd_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tso set <tso_segsz> <port_id>: "
+ "Set TSO segment size of non-tunneled packets for csum engine "
+ "(0 to disable)",
+ .tokens = {
+ (void *)&cmd_tso_set_tso,
+ (void *)&cmd_tso_set_mode,
+ (void *)&cmd_tso_set_tso_segsz,
+ (void *)&cmd_tso_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_tso_show_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result,
+ mode, "show");
+
+
+cmdline_parse_inst_t cmd_tso_show = {
+ .f = cmd_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tso show <port_id>: "
+ "Show TSO segment size of non-tunneled packets for csum engine",
+ .tokens = {
+ (void *)&cmd_tso_set_tso,
+ (void *)&cmd_tso_show_mode,
+ (void *)&cmd_tso_set_portid,
+ NULL,
+ },
+};
+
+/* *** ENABLE HARDWARE SEGMENTATION IN TX TUNNELED PACKETS *** */
+struct cmd_tunnel_tso_set_result {
+ cmdline_fixed_string_t tso;
+ cmdline_fixed_string_t mode;
+ uint16_t tso_segsz;
+ portid_t port_id;
+};
+
+static struct rte_eth_dev_info
+check_tunnel_tso_nic_support(portid_t port_id)
+{
+ struct rte_eth_dev_info dev_info;
+
+ if (eth_dev_info_get_print_err(port_id, &dev_info) != 0)
+ return dev_info;
+
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO))
+ printf("Warning: VXLAN TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO))
+ printf("Warning: GRE TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO))
+ printf("Warning: IPIP TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO))
+ printf("Warning: GENEVE TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO))
+ printf("Warning: IP TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ if (!(dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO))
+ printf("Warning: UDP TUNNEL TSO not supported therefore "
+ "not enabled for port %d\n", port_id);
+ return dev_info;
+}
+
+static void
+cmd_tunnel_tso_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tunnel_tso_set_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+ if (!port_is_stopped(res->port_id)) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ if (!strcmp(res->mode, "set"))
+ ports[res->port_id].tunnel_tso_segsz = res->tso_segsz;
+
+ dev_info = check_tunnel_tso_nic_support(res->port_id);
+ if (ports[res->port_id].tunnel_tso_segsz == 0) {
+ ports[res->port_id].dev_conf.txmode.offloads &=
+ ~(DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+ DEV_TX_OFFLOAD_GRE_TNL_TSO |
+ DEV_TX_OFFLOAD_IPIP_TNL_TSO |
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
+ DEV_TX_OFFLOAD_IP_TNL_TSO |
+ DEV_TX_OFFLOAD_UDP_TNL_TSO);
+ printf("TSO for tunneled packets is disabled\n");
+ } else {
+ uint64_t tso_offloads = (DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+ DEV_TX_OFFLOAD_GRE_TNL_TSO |
+ DEV_TX_OFFLOAD_IPIP_TNL_TSO |
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO |
+ DEV_TX_OFFLOAD_IP_TNL_TSO |
+ DEV_TX_OFFLOAD_UDP_TNL_TSO);
+
+ ports[res->port_id].dev_conf.txmode.offloads |=
+ (tso_offloads & dev_info.tx_offload_capa);
+ printf("TSO segment size for tunneled packets is %d\n",
+ ports[res->port_id].tunnel_tso_segsz);
+
+ /* Below conditions are needed to make it work:
+ * (1) tunnel TSO is supported by the NIC;
+ * (2) "csum parse_tunnel" must be set so that tunneled pkts
+ * are recognized;
+ * (3) for tunneled pkts with outer L3 of IPv4,
+ * "csum set outer-ip" must be set to hw, because after tso,
+ * total_len of outer IP header is changed, and the checksum
+ * of outer IP header calculated by sw should be wrong; that
+ * is not necessary for IPv6 tunneled pkts because there's no
+ * checksum in IP header anymore.
+ */
+
+ if (!ports[res->port_id].parse_tunnel)
+ printf("Warning: csum parse_tunnel must be set "
+ "so that tunneled packets are recognized\n");
+ if (!(ports[res->port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM))
+ printf("Warning: csum set outer-ip must be set to hw "
+ "if outer L3 is IPv4; not necessary for IPv6\n");
+ }
+
+ cmd_config_queue_tx_offloads(&ports[res->port_id]);
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_tunnel_tso_set_tso =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ tso, "tunnel_tso");
+cmdline_parse_token_string_t cmd_tunnel_tso_set_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ mode, "set");
+cmdline_parse_token_num_t cmd_tunnel_tso_set_tso_segsz =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ tso_segsz, UINT16);
+cmdline_parse_token_num_t cmd_tunnel_tso_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_tunnel_tso_set = {
+ .f = cmd_tunnel_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tunnel_tso set <tso_segsz> <port_id>: "
+ "Set TSO segment size of tunneled packets for csum engine "
+ "(0 to disable)",
+ .tokens = {
+ (void *)&cmd_tunnel_tso_set_tso,
+ (void *)&cmd_tunnel_tso_set_mode,
+ (void *)&cmd_tunnel_tso_set_tso_segsz,
+ (void *)&cmd_tunnel_tso_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_token_string_t cmd_tunnel_tso_show_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_tso_set_result,
+ mode, "show");
+
+
+cmdline_parse_inst_t cmd_tunnel_tso_show = {
+ .f = cmd_tunnel_tso_set_parsed,
+ .data = NULL,
+ .help_str = "tunnel_tso show <port_id> "
+ "Show TSO segment size of tunneled packets for csum engine",
+ .tokens = {
+ (void *)&cmd_tunnel_tso_set_tso,
+ (void *)&cmd_tunnel_tso_show_mode,
+ (void *)&cmd_tunnel_tso_set_portid,
+ NULL,
+ },
+};
+
+/* *** SET GRO FOR A PORT *** */
+struct cmd_gro_enable_result {
+ cmdline_fixed_string_t cmd_set;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t cmd_onoff;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_gro_enable_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gro_enable_result *res;
+
+ res = parsed_result;
+ if (!strcmp(res->cmd_keyword, "gro"))
+ setup_gro(res->cmd_onoff, res->cmd_pid);
+}
+
+cmdline_parse_token_string_t cmd_gro_enable_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_enable_result,
+ cmd_set, "set");
+cmdline_parse_token_string_t cmd_gro_enable_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_enable_result,
+ cmd_keyword, "port");
+cmdline_parse_token_num_t cmd_gro_enable_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_gro_enable_result,
+ cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_gro_enable_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_enable_result,
+ cmd_keyword, "gro");
+cmdline_parse_token_string_t cmd_gro_enable_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_enable_result,
+ cmd_onoff, "on#off");
+
+cmdline_parse_inst_t cmd_gro_enable = {
+ .f = cmd_gro_enable_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> gro on|off",
+ .tokens = {
+ (void *)&cmd_gro_enable_set,
+ (void *)&cmd_gro_enable_port,
+ (void *)&cmd_gro_enable_pid,
+ (void *)&cmd_gro_enable_keyword,
+ (void *)&cmd_gro_enable_onoff,
+ NULL,
+ },
+};
+
+/* *** DISPLAY GRO CONFIGURATION *** */
+struct cmd_gro_show_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_gro_show_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gro_show_result *res;
+
+ res = parsed_result;
+ if (!strcmp(res->cmd_keyword, "gro"))
+ show_gro(res->cmd_pid);
+}
+
+cmdline_parse_token_string_t cmd_gro_show_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_show_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_gro_show_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_show_result,
+ cmd_port, "port");
+cmdline_parse_token_num_t cmd_gro_show_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_gro_show_result,
+ cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_gro_show_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_show_result,
+ cmd_keyword, "gro");
+
+cmdline_parse_inst_t cmd_gro_show = {
+ .f = cmd_gro_show_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> gro",
+ .tokens = {
+ (void *)&cmd_gro_show_show,
+ (void *)&cmd_gro_show_port,
+ (void *)&cmd_gro_show_pid,
+ (void *)&cmd_gro_show_keyword,
+ NULL,
+ },
+};
+
+/* *** SET FLUSH CYCLES FOR GRO *** */
+struct cmd_gro_flush_result {
+ cmdline_fixed_string_t cmd_set;
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t cmd_flush;
+ uint8_t cmd_cycles;
+};
+
+static void
+cmd_gro_flush_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gro_flush_result *res;
+
+ res = parsed_result;
+ if ((!strcmp(res->cmd_keyword, "gro")) &&
+ (!strcmp(res->cmd_flush, "flush")))
+ setup_gro_flush_cycles(res->cmd_cycles);
+}
+
+cmdline_parse_token_string_t cmd_gro_flush_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_flush_result,
+ cmd_set, "set");
+cmdline_parse_token_string_t cmd_gro_flush_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_flush_result,
+ cmd_keyword, "gro");
+cmdline_parse_token_string_t cmd_gro_flush_flush =
+ TOKEN_STRING_INITIALIZER(struct cmd_gro_flush_result,
+ cmd_flush, "flush");
+cmdline_parse_token_num_t cmd_gro_flush_cycles =
+ TOKEN_NUM_INITIALIZER(struct cmd_gro_flush_result,
+ cmd_cycles, UINT8);
+
+cmdline_parse_inst_t cmd_gro_flush = {
+ .f = cmd_gro_flush_parsed,
+ .data = NULL,
+ .help_str = "set gro flush <cycles>",
+ .tokens = {
+ (void *)&cmd_gro_flush_set,
+ (void *)&cmd_gro_flush_keyword,
+ (void *)&cmd_gro_flush_flush,
+ (void *)&cmd_gro_flush_cycles,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE GSO *** */
+struct cmd_gso_enable_result {
+ cmdline_fixed_string_t cmd_set;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t cmd_mode;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_gso_enable_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gso_enable_result *res;
+
+ res = parsed_result;
+ if (!strcmp(res->cmd_keyword, "gso"))
+ setup_gso(res->cmd_mode, res->cmd_pid);
+}
+
+cmdline_parse_token_string_t cmd_gso_enable_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,
+ cmd_set, "set");
+cmdline_parse_token_string_t cmd_gso_enable_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,
+ cmd_port, "port");
+cmdline_parse_token_string_t cmd_gso_enable_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,
+ cmd_keyword, "gso");
+cmdline_parse_token_string_t cmd_gso_enable_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_enable_result,
+ cmd_mode, "on#off");
+cmdline_parse_token_num_t cmd_gso_enable_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_gso_enable_result,
+ cmd_pid, UINT16);
+
+cmdline_parse_inst_t cmd_gso_enable = {
+ .f = cmd_gso_enable_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> gso on|off",
+ .tokens = {
+ (void *)&cmd_gso_enable_set,
+ (void *)&cmd_gso_enable_port,
+ (void *)&cmd_gso_enable_pid,
+ (void *)&cmd_gso_enable_keyword,
+ (void *)&cmd_gso_enable_mode,
+ NULL,
+ },
+};
+
+/* *** SET MAX PACKET LENGTH FOR GSO SEGMENTS *** */
+struct cmd_gso_size_result {
+ cmdline_fixed_string_t cmd_set;
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t cmd_segsz;
+ uint16_t cmd_size;
+};
+
+static void
+cmd_gso_size_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gso_size_result *res = parsed_result;
+
+ if (test_done == 0) {
+ printf("Before setting GSO segsz, please first"
+ " stop forwarding\n");
+ return;
+ }
+
+ if (!strcmp(res->cmd_keyword, "gso") &&
+ !strcmp(res->cmd_segsz, "segsz")) {
+ if (res->cmd_size < RTE_GSO_SEG_SIZE_MIN)
+ printf("gso_size should be larger than %zu."
+ " Please input a legal value\n",
+ RTE_GSO_SEG_SIZE_MIN);
+ else
+ gso_max_segment_size = res->cmd_size;
+ }
+}
+
+cmdline_parse_token_string_t cmd_gso_size_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,
+ cmd_set, "set");
+cmdline_parse_token_string_t cmd_gso_size_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,
+ cmd_keyword, "gso");
+cmdline_parse_token_string_t cmd_gso_size_segsz =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_size_result,
+ cmd_segsz, "segsz");
+cmdline_parse_token_num_t cmd_gso_size_size =
+ TOKEN_NUM_INITIALIZER(struct cmd_gso_size_result,
+ cmd_size, UINT16);
+
+cmdline_parse_inst_t cmd_gso_size = {
+ .f = cmd_gso_size_parsed,
+ .data = NULL,
+ .help_str = "set gso segsz <length>",
+ .tokens = {
+ (void *)&cmd_gso_size_set,
+ (void *)&cmd_gso_size_keyword,
+ (void *)&cmd_gso_size_segsz,
+ (void *)&cmd_gso_size_size,
+ NULL,
+ },
+};
+
+/* *** SHOW GSO CONFIGURATION *** */
+struct cmd_gso_show_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_gso_show_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_gso_show_result *res = parsed_result;
+
+ if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+ printf("invalid port id %u\n", res->cmd_pid);
+ return;
+ }
+ if (!strcmp(res->cmd_keyword, "gso")) {
+ if (gso_ports[res->cmd_pid].enable) {
+ printf("Max GSO'd packet size: %uB\n"
+ "Supported GSO types: TCP/IPv4, "
+ "UDP/IPv4, VxLAN with inner "
+ "TCP/IPv4 packet, GRE with inner "
+ "TCP/IPv4 packet\n",
+ gso_max_segment_size);
+ } else
+ printf("GSO is not enabled on Port %u\n", res->cmd_pid);
+ }
+}
+
+cmdline_parse_token_string_t cmd_gso_show_show =
+TOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_gso_show_port =
+TOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,
+ cmd_port, "port");
+cmdline_parse_token_string_t cmd_gso_show_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_gso_show_result,
+ cmd_keyword, "gso");
+cmdline_parse_token_num_t cmd_gso_show_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_gso_show_result,
+ cmd_pid, UINT16);
+
+cmdline_parse_inst_t cmd_gso_show = {
+ .f = cmd_gso_show_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> gso",
+ .tokens = {
+ (void *)&cmd_gso_show_show,
+ (void *)&cmd_gso_show_port,
+ (void *)&cmd_gso_show_pid,
+ (void *)&cmd_gso_show_keyword,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE FLUSH ON RX STREAMS *** */
+struct cmd_set_flush_rx {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t flush_rx;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_flush_rx_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_flush_rx *res = parsed_result;
+ no_flush_rx = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1);
+}
+
+cmdline_parse_token_string_t cmd_setflushrx_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ set, "set");
+cmdline_parse_token_string_t cmd_setflushrx_flush_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ flush_rx, "flush_rx");
+cmdline_parse_token_string_t cmd_setflushrx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_flush_rx,
+ mode, "on#off");
+
+
+cmdline_parse_inst_t cmd_set_flush_rx = {
+ .f = cmd_set_flush_rx_parsed,
+ .help_str = "set flush_rx on|off: Enable/Disable flush on rx streams",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setflushrx_set,
+ (void *)&cmd_setflushrx_flush_rx,
+ (void *)&cmd_setflushrx_mode,
+ NULL,
+ },
+};
+
+/* *** ENABLE/DISABLE LINK STATUS CHECK *** */
+struct cmd_set_link_check {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_check;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_link_check_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_link_check *res = parsed_result;
+ no_link_check = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1);
+}
+
+cmdline_parse_token_string_t cmd_setlinkcheck_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ set, "set");
+cmdline_parse_token_string_t cmd_setlinkcheck_link_check =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ link_check, "link_check");
+cmdline_parse_token_string_t cmd_setlinkcheck_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_check,
+ mode, "on#off");
+
+
+cmdline_parse_inst_t cmd_set_link_check = {
+ .f = cmd_set_link_check_parsed,
+ .help_str = "set link_check on|off: Enable/Disable link status check "
+ "when starting/stopping a port",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setlinkcheck_set,
+ (void *)&cmd_setlinkcheck_link_check,
+ (void *)&cmd_setlinkcheck_mode,
+ NULL,
+ },
+};
+
+/* *** SET NIC BYPASS MODE *** */
+struct cmd_set_bypass_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t value;
+ portid_t port_id;
+};
+
+static void
+cmd_set_bypass_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bypass_mode_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ int32_t rc = -EINVAL;
+
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+ uint32_t bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_NORMAL;
+
+ if (!strcmp(res->value, "bypass"))
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(res->value, "isolate"))
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_ISOLATE;
+ else
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_NORMAL;
+
+ /* Set the bypass mode for the relevant port. */
+ rc = rte_pmd_ixgbe_bypass_state_set(port_id, &bypass_mode);
+#endif
+ if (rc != 0)
+ printf("\t Failed to set bypass mode for port = %d.\n", port_id);
+}
+
+cmdline_parse_token_string_t cmd_setbypass_mode_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_mode_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_mode_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_setbypass_mode_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_mode_result,
+ value, "normal#bypass#isolate");
+cmdline_parse_token_num_t cmd_setbypass_mode_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_mode_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_set_bypass_mode = {
+ .f = cmd_set_bypass_mode_parsed,
+ .help_str = "set bypass mode normal|bypass|isolate <port_id>: "
+ "Set the NIC bypass mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_mode_set,
+ (void *)&cmd_setbypass_mode_bypass,
+ (void *)&cmd_setbypass_mode_mode,
+ (void *)&cmd_setbypass_mode_value,
+ (void *)&cmd_setbypass_mode_port,
+ NULL,
+ },
+};
+
+/* *** SET NIC BYPASS EVENT *** */
+struct cmd_set_bypass_event_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t event;
+ cmdline_fixed_string_t event_value;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ portid_t port_id;
+};
+
+static void
+cmd_set_bypass_event_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int32_t rc = -EINVAL;
+ struct cmd_set_bypass_event_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+ uint32_t bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_NONE;
+ uint32_t bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_NORMAL;
+
+ if (!strcmp(res->event_value, "timeout"))
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_TIMEOUT;
+ else if (!strcmp(res->event_value, "os_on"))
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_OS_ON;
+ else if (!strcmp(res->event_value, "os_off"))
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_OS_OFF;
+ else if (!strcmp(res->event_value, "power_on"))
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_POWER_ON;
+ else if (!strcmp(res->event_value, "power_off"))
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_POWER_OFF;
+ else
+ bypass_event = RTE_PMD_IXGBE_BYPASS_EVENT_NONE;
+
+ if (!strcmp(res->mode_value, "bypass"))
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_BYPASS;
+ else if (!strcmp(res->mode_value, "isolate"))
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_ISOLATE;
+ else
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_NORMAL;
+
+ /* Set the watchdog timeout. */
+ if (bypass_event == RTE_PMD_IXGBE_BYPASS_EVENT_TIMEOUT) {
+
+ rc = -EINVAL;
+ if (RTE_PMD_IXGBE_BYPASS_TMT_VALID(bypass_timeout)) {
+ rc = rte_pmd_ixgbe_bypass_wd_timeout_store(port_id,
+ bypass_timeout);
+ }
+ if (rc != 0) {
+ printf("Failed to set timeout value %u "
+ "for port %d, errto code: %d.\n",
+ bypass_timeout, port_id, rc);
+ }
+ }
+
+ /* Set the bypass event to transition to bypass mode. */
+ rc = rte_pmd_ixgbe_bypass_event_store(port_id, bypass_event,
+ bypass_mode);
+#endif
+
+ if (rc != 0)
+ printf("\t Failed to set bypass event for port = %d.\n",
+ port_id);
+}
+
+cmdline_parse_token_string_t cmd_setbypass_event_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_event_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_event_event =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ event, "event");
+cmdline_parse_token_string_t cmd_setbypass_event_event_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ event_value, "none#timeout#os_off#os_on#power_on#power_off");
+cmdline_parse_token_string_t cmd_setbypass_event_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_setbypass_event_mode_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_event_result,
+ mode_value, "normal#bypass#isolate");
+cmdline_parse_token_num_t cmd_setbypass_event_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bypass_event_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_set_bypass_event = {
+ .f = cmd_set_bypass_event_parsed,
+ .help_str = "set bypass event none|timeout|os_on|os_off|power_on|"
+ "power_off mode normal|bypass|isolate <port_id>: "
+ "Set the NIC bypass event mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_event_set,
+ (void *)&cmd_setbypass_event_bypass,
+ (void *)&cmd_setbypass_event_event,
+ (void *)&cmd_setbypass_event_event_value,
+ (void *)&cmd_setbypass_event_mode,
+ (void *)&cmd_setbypass_event_mode_value,
+ (void *)&cmd_setbypass_event_port,
+ NULL,
+ },
+};
+
+
+/* *** SET NIC BYPASS TIMEOUT *** */
+struct cmd_set_bypass_timeout_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t timeout;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_set_bypass_timeout_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ __rte_unused struct cmd_set_bypass_timeout_result *res = parsed_result;
+
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+ if (!strcmp(res->value, "1.5"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_1_5_SEC;
+ else if (!strcmp(res->value, "2"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_2_SEC;
+ else if (!strcmp(res->value, "3"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_3_SEC;
+ else if (!strcmp(res->value, "4"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_4_SEC;
+ else if (!strcmp(res->value, "8"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_8_SEC;
+ else if (!strcmp(res->value, "16"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_16_SEC;
+ else if (!strcmp(res->value, "32"))
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_32_SEC;
+ else
+ bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
+#endif
+}
+
+cmdline_parse_token_string_t cmd_setbypass_timeout_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbypass_timeout_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_setbypass_timeout_timeout =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ timeout, "timeout");
+cmdline_parse_token_string_t cmd_setbypass_timeout_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bypass_timeout_result,
+ value, "0#1.5#2#3#4#8#16#32");
+
+cmdline_parse_inst_t cmd_set_bypass_timeout = {
+ .f = cmd_set_bypass_timeout_parsed,
+ .help_str = "set bypass timeout 0|1.5|2|3|4|8|16|32: "
+ "Set the NIC bypass watchdog timeout in seconds",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbypass_timeout_set,
+ (void *)&cmd_setbypass_timeout_bypass,
+ (void *)&cmd_setbypass_timeout_timeout,
+ (void *)&cmd_setbypass_timeout_value,
+ NULL,
+ },
+};
+
+/* *** SHOW NIC BYPASS MODE *** */
+struct cmd_show_bypass_config_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t bypass;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+};
+
+static void
+cmd_show_bypass_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_bypass_config_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ int rc = -EINVAL;
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+ uint32_t event_mode;
+ uint32_t bypass_mode;
+ uint32_t timeout = bypass_timeout;
+ unsigned int i;
+
+ static const char * const timeouts[RTE_PMD_IXGBE_BYPASS_TMT_NUM] =
+ {"off", "1.5", "2", "3", "4", "8", "16", "32"};
+ static const char * const modes[RTE_PMD_IXGBE_BYPASS_MODE_NUM] =
+ {"UNKNOWN", "normal", "bypass", "isolate"};
+ static const char * const events[RTE_PMD_IXGBE_BYPASS_EVENT_NUM] = {
+ "NONE",
+ "OS/board on",
+ "power supply on",
+ "OS/board off",
+ "power supply off",
+ "timeout"};
+
+ /* Display the bypass mode.*/
+ if (rte_pmd_ixgbe_bypass_state_show(port_id, &bypass_mode) != 0) {
+ printf("\tFailed to get bypass mode for port = %d\n", port_id);
+ return;
+ }
+ else {
+ if (!RTE_PMD_IXGBE_BYPASS_MODE_VALID(bypass_mode))
+ bypass_mode = RTE_PMD_IXGBE_BYPASS_MODE_NONE;
+
+ printf("\tbypass mode = %s\n", modes[bypass_mode]);
+ }
+
+ /* Display the bypass timeout.*/
+ if (!RTE_PMD_IXGBE_BYPASS_TMT_VALID(timeout))
+ timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
+
+ printf("\tbypass timeout = %s\n", timeouts[timeout]);
+
+ /* Display the bypass events and associated modes. */
+ for (i = RTE_PMD_IXGBE_BYPASS_EVENT_START; i < RTE_DIM(events); i++) {
+
+ if (rte_pmd_ixgbe_bypass_event_show(port_id, i, &event_mode)) {
+ printf("\tFailed to get bypass mode for event = %s\n",
+ events[i]);
+ } else {
+ if (!RTE_PMD_IXGBE_BYPASS_MODE_VALID(event_mode))
+ event_mode = RTE_PMD_IXGBE_BYPASS_MODE_NONE;
+
+ printf("\tbypass event: %-16s = %s\n", events[i],
+ modes[event_mode]);
+ }
+ }
+#endif
+ if (rc != 0)
+ printf("\tFailed to get bypass configuration for port = %d\n",
+ port_id);
+}
+
+cmdline_parse_token_string_t cmd_showbypass_config_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_showbypass_config_bypass =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ bypass, "bypass");
+cmdline_parse_token_string_t cmd_showbypass_config_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_bypass_config_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_showbypass_config_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_bypass_config_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_show_bypass_config = {
+ .f = cmd_show_bypass_config_parsed,
+ .help_str = "show bypass config <port_id>: "
+ "Show the NIC bypass config for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_showbypass_config_show,
+ (void *)&cmd_showbypass_config_bypass,
+ (void *)&cmd_showbypass_config_config,
+ (void *)&cmd_showbypass_config_port,
+ NULL,
+ },
+};
+
+#ifdef RTE_LIBRTE_PMD_BOND
+/* *** SET BONDING MODE *** */
+struct cmd_set_bonding_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mode;
+ uint8_t value;
+ portid_t port_id;
+};
+
+static void cmd_set_bonding_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bonding_mode_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+
+ /* Set the bonding mode for the relevant port. */
+ if (0 != rte_eth_bond_mode_set(port_id, res->value))
+ printf("\t Failed to set bonding mode for port = %d.\n", port_id);
+}
+
+cmdline_parse_token_string_t cmd_setbonding_mode_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_mode_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_mode_mode =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_mode_result,
+ mode, "mode");
+cmdline_parse_token_num_t cmd_setbonding_mode_value =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result,
+ value, UINT8);
+cmdline_parse_token_num_t cmd_setbonding_mode_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_mode_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_set_bonding_mode = {
+ .f = cmd_set_bonding_mode_parsed,
+ .help_str = "set bonding mode <mode_value> <port_id>: "
+ "Set the bonding mode for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *) &cmd_setbonding_mode_set,
+ (void *) &cmd_setbonding_mode_bonding,
+ (void *) &cmd_setbonding_mode_mode,
+ (void *) &cmd_setbonding_mode_value,
+ (void *) &cmd_setbonding_mode_port,
+ NULL
+ }
+};
+
+/* *** SET BONDING SLOW_QUEUE SW/HW *** */
+struct cmd_set_bonding_lacp_dedicated_queues_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t lacp;
+ cmdline_fixed_string_t dedicated_queues;
+ portid_t port_id;
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_bonding_lacp_dedicated_queues_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bonding_lacp_dedicated_queues_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ struct rte_port *port;
+
+ port = &ports[port_id];
+
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", port_id);
+ return;
+ }
+
+ if (!strcmp(res->mode, "enable")) {
+ if (rte_eth_bond_8023ad_dedicated_queues_enable(port_id) == 0)
+ printf("Dedicate queues for LACP control packets"
+ " enabled\n");
+ else
+ printf("Enabling dedicate queues for LACP control "
+ "packets on port %d failed\n", port_id);
+ } else if (!strcmp(res->mode, "disable")) {
+ if (rte_eth_bond_8023ad_dedicated_queues_disable(port_id) == 0)
+ printf("Dedicated queues for LACP control packets "
+ "disabled\n");
+ else
+ printf("Disabling dedicated queues for LACP control "
+ "traffic on port %d failed\n", port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setbonding_lacp_dedicated_queues_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_lacp_dedicated_queues_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_lacp_dedicated_queues_lacp =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ lacp, "lacp");
+cmdline_parse_token_string_t cmd_setbonding_lacp_dedicated_queues_dedicated_queues =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ dedicated_queues, "dedicated_queues");
+cmdline_parse_token_num_t cmd_setbonding_lacp_dedicated_queues_port_id =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_setbonding_lacp_dedicated_queues_mode =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_lacp_dedicated_queues_result,
+ mode, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_lacp_dedicated_queues = {
+ .f = cmd_set_bonding_lacp_dedicated_queues_parsed,
+ .help_str = "set bonding lacp dedicated_queues <port_id> "
+ "enable|disable: "
+ "Enable/disable dedicated queues for LACP control traffic for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbonding_lacp_dedicated_queues_set,
+ (void *)&cmd_setbonding_lacp_dedicated_queues_bonding,
+ (void *)&cmd_setbonding_lacp_dedicated_queues_lacp,
+ (void *)&cmd_setbonding_lacp_dedicated_queues_dedicated_queues,
+ (void *)&cmd_setbonding_lacp_dedicated_queues_port_id,
+ (void *)&cmd_setbonding_lacp_dedicated_queues_mode,
+ NULL
+ }
+};
+
+/* *** SET BALANCE XMIT POLICY *** */
+struct cmd_set_bonding_balance_xmit_policy_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t balance_xmit_policy;
+ portid_t port_id;
+ cmdline_fixed_string_t policy;
+};
+
+static void cmd_set_bonding_balance_xmit_policy_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bonding_balance_xmit_policy_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ uint8_t policy;
+
+ if (!strcmp(res->policy, "l2")) {
+ policy = BALANCE_XMIT_POLICY_LAYER2;
+ } else if (!strcmp(res->policy, "l23")) {
+ policy = BALANCE_XMIT_POLICY_LAYER23;
+ } else if (!strcmp(res->policy, "l34")) {
+ policy = BALANCE_XMIT_POLICY_LAYER34;
+ } else {
+ printf("\t Invalid xmit policy selection");
+ return;
+ }
+
+ /* Set the bonding mode for the relevant port. */
+ if (0 != rte_eth_bond_xmit_policy_set(port_id, policy)) {
+ printf("\t Failed to set bonding balance xmit policy for port = %d.\n",
+ port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_balance_xmit_policy =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ balance_xmit_policy, "balance_xmit_policy");
+cmdline_parse_token_num_t cmd_setbonding_balance_xmit_policy_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_setbonding_balance_xmit_policy_policy =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_balance_xmit_policy_result,
+ policy, "l2#l23#l34");
+
+cmdline_parse_inst_t cmd_set_balance_xmit_policy = {
+ .f = cmd_set_bonding_balance_xmit_policy_parsed,
+ .help_str = "set bonding balance_xmit_policy <port_id> "
+ "l2|l23|l34: "
+ "Set the bonding balance_xmit_policy for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbonding_balance_xmit_policy_set,
+ (void *)&cmd_setbonding_balance_xmit_policy_bonding,
+ (void *)&cmd_setbonding_balance_xmit_policy_balance_xmit_policy,
+ (void *)&cmd_setbonding_balance_xmit_policy_port,
+ (void *)&cmd_setbonding_balance_xmit_policy_policy,
+ NULL
+ }
+};
+
+/* *** SHOW NIC BONDING CONFIGURATION *** */
+struct cmd_show_bonding_config_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+};
+
+static void cmd_show_bonding_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_bonding_config_result *res = parsed_result;
+ int bonding_mode, agg_mode;
+ portid_t slaves[RTE_MAX_ETHPORTS];
+ int num_slaves, num_active_slaves;
+ int primary_id;
+ int i;
+ portid_t port_id = res->port_id;
+
+ /* Display the bonding mode.*/
+ bonding_mode = rte_eth_bond_mode_get(port_id);
+ if (bonding_mode < 0) {
+ printf("\tFailed to get bonding mode for port = %d\n", port_id);
+ return;
+ } else
+ printf("\tBonding mode: %d\n", bonding_mode);
+
+ if (bonding_mode == BONDING_MODE_BALANCE) {
+ int balance_xmit_policy;
+
+ balance_xmit_policy = rte_eth_bond_xmit_policy_get(port_id);
+ if (balance_xmit_policy < 0) {
+ printf("\tFailed to get balance xmit policy for port = %d\n",
+ port_id);
+ return;
+ } else {
+ printf("\tBalance Xmit Policy: ");
+
+ switch (balance_xmit_policy) {
+ case BALANCE_XMIT_POLICY_LAYER2:
+ printf("BALANCE_XMIT_POLICY_LAYER2");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER23:
+ printf("BALANCE_XMIT_POLICY_LAYER23");
+ break;
+ case BALANCE_XMIT_POLICY_LAYER34:
+ printf("BALANCE_XMIT_POLICY_LAYER34");
+ break;
+ }
+ printf("\n");
+ }
+ }
+
+ if (bonding_mode == BONDING_MODE_8023AD) {
+ agg_mode = rte_eth_bond_8023ad_agg_selection_get(port_id);
+ printf("\tIEEE802.3AD Aggregator Mode: ");
+ switch (agg_mode) {
+ case AGG_BANDWIDTH:
+ printf("bandwidth");
+ break;
+ case AGG_STABLE:
+ printf("stable");
+ break;
+ case AGG_COUNT:
+ printf("count");
+ break;
+ }
+ printf("\n");
+ }
+
+ num_slaves = rte_eth_bond_slaves_get(port_id, slaves, RTE_MAX_ETHPORTS);
+
+ if (num_slaves < 0) {
+ printf("\tFailed to get slave list for port = %d\n", port_id);
+ return;
+ }
+ if (num_slaves > 0) {
+ printf("\tSlaves (%d): [", num_slaves);
+ for (i = 0; i < num_slaves - 1; i++)
+ printf("%d ", slaves[i]);
+
+ printf("%d]\n", slaves[num_slaves - 1]);
+ } else {
+ printf("\tSlaves: []\n");
+
+ }
+
+ num_active_slaves = rte_eth_bond_active_slaves_get(port_id, slaves,
+ RTE_MAX_ETHPORTS);
+
+ if (num_active_slaves < 0) {
+ printf("\tFailed to get active slave list for port = %d\n", port_id);
+ return;
+ }
+ if (num_active_slaves > 0) {
+ printf("\tActive Slaves (%d): [", num_active_slaves);
+ for (i = 0; i < num_active_slaves - 1; i++)
+ printf("%d ", slaves[i]);
+
+ printf("%d]\n", slaves[num_active_slaves - 1]);
+
+ } else {
+ printf("\tActive Slaves: []\n");
+
+ }
+
+ primary_id = rte_eth_bond_primary_get(port_id);
+ if (primary_id < 0) {
+ printf("\tFailed to get primary slave for port = %d\n", port_id);
+ return;
+ } else
+ printf("\tPrimary: [%d]\n", primary_id);
+
+}
+
+cmdline_parse_token_string_t cmd_showbonding_config_show =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_showbonding_config_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_showbonding_config_config =
+TOKEN_STRING_INITIALIZER(struct cmd_show_bonding_config_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_showbonding_config_port =
+TOKEN_NUM_INITIALIZER(struct cmd_show_bonding_config_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_show_bonding_config = {
+ .f = cmd_show_bonding_config_parsed,
+ .help_str = "show bonding config <port_id>: "
+ "Show the bonding config for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_showbonding_config_show,
+ (void *)&cmd_showbonding_config_bonding,
+ (void *)&cmd_showbonding_config_config,
+ (void *)&cmd_showbonding_config_port,
+ NULL
+ }
+};
+
+/* *** SET BONDING PRIMARY *** */
+struct cmd_set_bonding_primary_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t primary;
+ portid_t slave_id;
+ portid_t port_id;
+};
+
+static void cmd_set_bonding_primary_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bonding_primary_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* Set the primary slave for a bonded device. */
+ if (0 != rte_eth_bond_primary_set(master_port_id, slave_port_id)) {
+ printf("\t Failed to set primary slave for port = %d.\n",
+ master_port_id);
+ return;
+ }
+ init_port_config();
+}
+
+cmdline_parse_token_string_t cmd_setbonding_primary_set =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setbonding_primary_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_setbonding_primary_primary =
+TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_primary_result,
+ primary, "primary");
+cmdline_parse_token_num_t cmd_setbonding_primary_slave =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result,
+ slave_id, UINT16);
+cmdline_parse_token_num_t cmd_setbonding_primary_port =
+TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_primary_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_set_bonding_primary = {
+ .f = cmd_set_bonding_primary_parsed,
+ .help_str = "set bonding primary <slave_id> <port_id>: "
+ "Set the primary slave for port_id",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_setbonding_primary_set,
+ (void *)&cmd_setbonding_primary_bonding,
+ (void *)&cmd_setbonding_primary_primary,
+ (void *)&cmd_setbonding_primary_slave,
+ (void *)&cmd_setbonding_primary_port,
+ NULL
+ }
+};
+
+/* *** ADD SLAVE *** */
+struct cmd_add_bonding_slave_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t slave;
+ portid_t slave_id;
+ portid_t port_id;
+};
+
+static void cmd_add_bonding_slave_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_bonding_slave_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* add the slave for a bonded device. */
+ if (0 != rte_eth_bond_slave_add(master_port_id, slave_port_id)) {
+ printf("\t Failed to add slave %d to master port = %d.\n",
+ slave_port_id, master_port_id);
+ return;
+ }
+ init_port_config();
+ set_port_slave_flag(slave_port_id);
+}
+
+cmdline_parse_token_string_t cmd_addbonding_slave_add =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ add, "add");
+cmdline_parse_token_string_t cmd_addbonding_slave_bonding =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_addbonding_slave_slave =
+TOKEN_STRING_INITIALIZER(struct cmd_add_bonding_slave_result,
+ slave, "slave");
+cmdline_parse_token_num_t cmd_addbonding_slave_slaveid =
+TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result,
+ slave_id, UINT16);
+cmdline_parse_token_num_t cmd_addbonding_slave_port =
+TOKEN_NUM_INITIALIZER(struct cmd_add_bonding_slave_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_add_bonding_slave = {
+ .f = cmd_add_bonding_slave_parsed,
+ .help_str = "add bonding slave <slave_id> <port_id>: "
+ "Add a slave device to a bonded device",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_addbonding_slave_add,
+ (void *)&cmd_addbonding_slave_bonding,
+ (void *)&cmd_addbonding_slave_slave,
+ (void *)&cmd_addbonding_slave_slaveid,
+ (void *)&cmd_addbonding_slave_port,
+ NULL
+ }
+};
+
+/* *** REMOVE SLAVE *** */
+struct cmd_remove_bonding_slave_result {
+ cmdline_fixed_string_t remove;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t slave;
+ portid_t slave_id;
+ portid_t port_id;
+};
+
+static void cmd_remove_bonding_slave_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_remove_bonding_slave_result *res = parsed_result;
+ portid_t master_port_id = res->port_id;
+ portid_t slave_port_id = res->slave_id;
+
+ /* remove the slave from a bonded device. */
+ if (0 != rte_eth_bond_slave_remove(master_port_id, slave_port_id)) {
+ printf("\t Failed to remove slave %d from master port = %d.\n",
+ slave_port_id, master_port_id);
+ return;
+ }
+ init_port_config();
+ clear_port_slave_flag(slave_port_id);
+}
+
+cmdline_parse_token_string_t cmd_removebonding_slave_remove =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ remove, "remove");
+cmdline_parse_token_string_t cmd_removebonding_slave_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_removebonding_slave_slave =
+ TOKEN_STRING_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ slave, "slave");
+cmdline_parse_token_num_t cmd_removebonding_slave_slaveid =
+ TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ slave_id, UINT16);
+cmdline_parse_token_num_t cmd_removebonding_slave_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_remove_bonding_slave_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_remove_bonding_slave = {
+ .f = cmd_remove_bonding_slave_parsed,
+ .help_str = "remove bonding slave <slave_id> <port_id>: "
+ "Remove a slave device from a bonded device",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_removebonding_slave_remove,
+ (void *)&cmd_removebonding_slave_bonding,
+ (void *)&cmd_removebonding_slave_slave,
+ (void *)&cmd_removebonding_slave_slaveid,
+ (void *)&cmd_removebonding_slave_port,
+ NULL
+ }
+};
+
+/* *** CREATE BONDED DEVICE *** */
+struct cmd_create_bonded_device_result {
+ cmdline_fixed_string_t create;
+ cmdline_fixed_string_t bonded;
+ cmdline_fixed_string_t device;
+ uint8_t mode;
+ uint8_t socket;
+};
+
+static int bond_dev_num = 0;
+
+static void cmd_create_bonded_device_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_create_bonded_device_result *res = parsed_result;
+ char ethdev_name[RTE_ETH_NAME_MAX_LEN];
+ int port_id;
+ int ret;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+
+ snprintf(ethdev_name, RTE_ETH_NAME_MAX_LEN, "net_bonding_testpmd_%d",
+ bond_dev_num++);
+
+ /* Create a new bonded device. */
+ port_id = rte_eth_bond_create(ethdev_name, res->mode, res->socket);
+ if (port_id < 0) {
+ printf("\t Failed to create bonded device.\n");
+ return;
+ } else {
+ printf("Created new bonded device %s on (port %d).\n", ethdev_name,
+ port_id);
+
+ /* Update number of ports */
+ nb_ports = rte_eth_dev_count_avail();
+ reconfig(port_id, res->socket);
+ ret = rte_eth_promiscuous_enable(port_id);
+ if (ret != 0)
+ printf("Failed to enable promiscuous mode for port %u: %s - ignore\n",
+ port_id, rte_strerror(-ret));
+
+ ports[port_id].need_setup = 0;
+ ports[port_id].port_status = RTE_PORT_STOPPED;
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_createbonded_device_create =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ create, "create");
+cmdline_parse_token_string_t cmd_createbonded_device_bonded =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ bonded, "bonded");
+cmdline_parse_token_string_t cmd_createbonded_device_device =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_bonded_device_result,
+ device, "device");
+cmdline_parse_token_num_t cmd_createbonded_device_mode =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result,
+ mode, UINT8);
+cmdline_parse_token_num_t cmd_createbonded_device_socket =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_bonded_device_result,
+ socket, UINT8);
+
+cmdline_parse_inst_t cmd_create_bonded_device = {
+ .f = cmd_create_bonded_device_parsed,
+ .help_str = "create bonded device <mode> <socket>: "
+ "Create a new bonded device with specific bonding mode and socket",
+ .data = NULL,
+ .tokens = {
+ (void *)&cmd_createbonded_device_create,
+ (void *)&cmd_createbonded_device_bonded,
+ (void *)&cmd_createbonded_device_device,
+ (void *)&cmd_createbonded_device_mode,
+ (void *)&cmd_createbonded_device_socket,
+ NULL
+ }
+};
+
+/* *** SET MAC ADDRESS IN BONDED DEVICE *** */
+struct cmd_set_bond_mac_addr_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mac_addr;
+ uint16_t port_num;
+ struct rte_ether_addr address;
+};
+
+static void cmd_set_bond_mac_addr_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bond_mac_addr_result *res = parsed_result;
+ int ret;
+
+ if (port_id_is_invalid(res->port_num, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_bond_mac_address_set(res->port_num, &res->address);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, set, "set");
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, bonding,
+ "bonding");
+cmdline_parse_token_string_t cmd_set_bond_mac_addr_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mac_addr_result, mac_addr,
+ "mac_addr");
+cmdline_parse_token_num_t cmd_set_bond_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mac_addr_result,
+ port_num, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_bond_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_bond_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_set_bond_mac_addr = {
+ .f = cmd_set_bond_mac_addr_parsed,
+ .data = (void *) 0,
+ .help_str = "set bonding mac_addr <port_id> <mac_addr>",
+ .tokens = {
+ (void *)&cmd_set_bond_mac_addr_set,
+ (void *)&cmd_set_bond_mac_addr_bonding,
+ (void *)&cmd_set_bond_mac_addr_mac,
+ (void *)&cmd_set_bond_mac_addr_portnum,
+ (void *)&cmd_set_bond_mac_addr_addr,
+ NULL
+ }
+};
+
+
+/* *** SET LINK STATUS MONITORING POLLING PERIOD ON BONDED DEVICE *** */
+struct cmd_set_bond_mon_period_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t mon_period;
+ uint16_t port_num;
+ uint32_t period_ms;
+};
+
+static void cmd_set_bond_mon_period_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bond_mon_period_result *res = parsed_result;
+ int ret;
+
+ ret = rte_eth_bond_link_monitoring_set(res->port_num, res->period_ms);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("set_bond_mac_addr error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_set_bond_mon_period_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ bonding, "bonding");
+cmdline_parse_token_string_t cmd_set_bond_mon_period_mon_period =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ mon_period, "mon_period");
+cmdline_parse_token_num_t cmd_set_bond_mon_period_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ port_num, UINT16);
+cmdline_parse_token_num_t cmd_set_bond_mon_period_period_ms =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bond_mon_period_result,
+ period_ms, UINT32);
+
+cmdline_parse_inst_t cmd_set_bond_mon_period = {
+ .f = cmd_set_bond_mon_period_parsed,
+ .data = (void *) 0,
+ .help_str = "set bonding mon_period <port_id> <period_ms>",
+ .tokens = {
+ (void *)&cmd_set_bond_mon_period_set,
+ (void *)&cmd_set_bond_mon_period_bonding,
+ (void *)&cmd_set_bond_mon_period_mon_period,
+ (void *)&cmd_set_bond_mon_period_portnum,
+ (void *)&cmd_set_bond_mon_period_period_ms,
+ NULL
+ }
+};
+
+
+
+struct cmd_set_bonding_agg_mode_policy_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t bonding;
+ cmdline_fixed_string_t agg_mode;
+ uint16_t port_num;
+ cmdline_fixed_string_t policy;
+};
+
+
+static void
+cmd_set_bonding_agg_mode(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_bonding_agg_mode_policy_result *res = parsed_result;
+ uint8_t policy = AGG_BANDWIDTH;
+
+ if (!strcmp(res->policy, "bandwidth"))
+ policy = AGG_BANDWIDTH;
+ else if (!strcmp(res->policy, "stable"))
+ policy = AGG_STABLE;
+ else if (!strcmp(res->policy, "count"))
+ policy = AGG_COUNT;
+
+ rte_eth_bond_8023ad_agg_selection_set(res->port_num, policy);
+}
+
+
+cmdline_parse_token_string_t cmd_set_bonding_agg_mode_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_agg_mode_policy_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_bonding_agg_mode_bonding =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_agg_mode_policy_result,
+ bonding, "bonding");
+
+cmdline_parse_token_string_t cmd_set_bonding_agg_mode_agg_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_bonding_agg_mode_policy_result,
+ agg_mode, "agg_mode");
+
+cmdline_parse_token_num_t cmd_set_bonding_agg_mode_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_bonding_agg_mode_policy_result,
+ port_num, UINT16);
+
+cmdline_parse_token_string_t cmd_set_bonding_agg_mode_policy_string =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_bonding_balance_xmit_policy_result,
+ policy, "stable#bandwidth#count");
+
+cmdline_parse_inst_t cmd_set_bonding_agg_mode_policy = {
+ .f = cmd_set_bonding_agg_mode,
+ .data = (void *) 0,
+ .help_str = "set bonding mode IEEE802.3AD aggregator policy <port_id> <agg_name>",
+ .tokens = {
+ (void *)&cmd_set_bonding_agg_mode_set,
+ (void *)&cmd_set_bonding_agg_mode_bonding,
+ (void *)&cmd_set_bonding_agg_mode_agg_mode,
+ (void *)&cmd_set_bonding_agg_mode_portnum,
+ (void *)&cmd_set_bonding_agg_mode_policy_string,
+ NULL
+ }
+};
+
+
+#endif /* RTE_LIBRTE_PMD_BOND */
+
+/* *** SET FORWARDING MODE *** */
+struct cmd_set_fwd_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_fwd_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_fwd_mode_result *res = parsed_result;
+
+ retry_enabled = 0;
+ set_pkt_forwarding_mode(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_setfwd_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setfwd_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, fwd, "fwd");
+cmdline_parse_token_string_t cmd_setfwd_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, mode,
+ "" /* defined at init */);
+
+cmdline_parse_inst_t cmd_set_fwd_mode = {
+ .f = cmd_set_fwd_mode_parsed,
+ .data = NULL,
+ .help_str = NULL, /* defined at init */
+ .tokens = {
+ (void *)&cmd_setfwd_set,
+ (void *)&cmd_setfwd_fwd,
+ (void *)&cmd_setfwd_mode,
+ NULL,
+ },
+};
+
+static void cmd_set_fwd_mode_init(void)
+{
+ char *modes, *c;
+ static char token[128];
+ static char help[256];
+ cmdline_parse_token_string_t *token_struct;
+
+ modes = list_pkt_forwarding_modes();
+ snprintf(help, sizeof(help), "set fwd %s: "
+ "Set packet forwarding mode", modes);
+ cmd_set_fwd_mode.help_str = help;
+
+ /* string token separator is # */
+ for (c = token; *modes != '\0'; modes++)
+ if (*modes == '|')
+ *c++ = '#';
+ else
+ *c++ = *modes;
+ token_struct = (cmdline_parse_token_string_t*)cmd_set_fwd_mode.tokens[2];
+ token_struct->string_data.str = token;
+}
+
+/* *** SET RETRY FORWARDING MODE *** */
+struct cmd_set_fwd_retry_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t retry;
+};
+
+static void cmd_set_fwd_retry_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_fwd_retry_mode_result *res = parsed_result;
+
+ retry_enabled = 1;
+ set_pkt_forwarding_mode(res->mode);
+}
+
+cmdline_parse_token_string_t cmd_setfwd_retry_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setfwd_retry_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ fwd, "fwd");
+cmdline_parse_token_string_t cmd_setfwd_retry_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ mode,
+ "" /* defined at init */);
+cmdline_parse_token_string_t cmd_setfwd_retry_retry =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_retry_mode_result,
+ retry, "retry");
+
+cmdline_parse_inst_t cmd_set_fwd_retry_mode = {
+ .f = cmd_set_fwd_retry_mode_parsed,
+ .data = NULL,
+ .help_str = NULL, /* defined at init */
+ .tokens = {
+ (void *)&cmd_setfwd_retry_set,
+ (void *)&cmd_setfwd_retry_fwd,
+ (void *)&cmd_setfwd_retry_mode,
+ (void *)&cmd_setfwd_retry_retry,
+ NULL,
+ },
+};
+
+static void cmd_set_fwd_retry_mode_init(void)
+{
+ char *modes, *c;
+ static char token[128];
+ static char help[256];
+ cmdline_parse_token_string_t *token_struct;
+
+ modes = list_pkt_forwarding_retry_modes();
+ snprintf(help, sizeof(help), "set fwd %s retry: "
+ "Set packet forwarding mode with retry", modes);
+ cmd_set_fwd_retry_mode.help_str = help;
+
+ /* string token separator is # */
+ for (c = token; *modes != '\0'; modes++)
+ if (*modes == '|')
+ *c++ = '#';
+ else
+ *c++ = *modes;
+ token_struct = (cmdline_parse_token_string_t *)
+ cmd_set_fwd_retry_mode.tokens[2];
+ token_struct->string_data.str = token;
+}
+
+/* *** SET BURST TX DELAY TIME RETRY NUMBER *** */
+struct cmd_set_burst_tx_retry_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t burst;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t delay;
+ uint32_t time;
+ cmdline_fixed_string_t retry;
+ uint32_t retry_num;
+};
+
+static void cmd_set_burst_tx_retry_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_burst_tx_retry_result *res = parsed_result;
+
+ if (!strcmp(res->set, "set") && !strcmp(res->burst, "burst")
+ && !strcmp(res->tx, "tx")) {
+ if (!strcmp(res->delay, "delay"))
+ burst_tx_delay_time = res->time;
+ if (!strcmp(res->retry, "retry"))
+ burst_tx_retry_num = res->retry_num;
+ }
+
+}
+
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, set, "set");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_burst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, burst,
+ "burst");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, tx, "tx");
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_delay =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, delay, "delay");
+cmdline_parse_token_num_t cmd_set_burst_tx_retry_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, time, UINT32);
+cmdline_parse_token_string_t cmd_set_burst_tx_retry_retry =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry, "retry");
+cmdline_parse_token_num_t cmd_set_burst_tx_retry_retry_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_burst_tx_retry_result, retry_num, UINT32);
+
+cmdline_parse_inst_t cmd_set_burst_tx_retry = {
+ .f = cmd_set_burst_tx_retry_parsed,
+ .help_str = "set burst tx delay <delay_usec> retry <num_retry>",
+ .tokens = {
+ (void *)&cmd_set_burst_tx_retry_set,
+ (void *)&cmd_set_burst_tx_retry_burst,
+ (void *)&cmd_set_burst_tx_retry_tx,
+ (void *)&cmd_set_burst_tx_retry_delay,
+ (void *)&cmd_set_burst_tx_retry_time,
+ (void *)&cmd_set_burst_tx_retry_retry,
+ (void *)&cmd_set_burst_tx_retry_retry_num,
+ NULL,
+ },
+};
+
+/* *** SET PROMISC MODE *** */
+struct cmd_set_promisc_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t promisc;
+ cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */
+ uint16_t port_num; /* valid if "allports" argument == 0 */
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_promisc_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *allports)
+{
+ struct cmd_set_promisc_mode_result *res = parsed_result;
+ int enable;
+ portid_t i;
+
+ if (!strcmp(res->mode, "on"))
+ enable = 1;
+ else
+ enable = 0;
+
+ /* all ports */
+ if (allports) {
+ RTE_ETH_FOREACH_DEV(i)
+ eth_set_promisc_mode(i, enable);
+ } else {
+ eth_set_promisc_mode(res->port_num, enable);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setpromisc_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setpromisc_promisc =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, promisc,
+ "promisc");
+cmdline_parse_token_string_t cmd_setpromisc_portall =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, port_all,
+ "all");
+cmdline_parse_token_num_t cmd_setpromisc_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_promisc_mode_result, port_num,
+ UINT16);
+cmdline_parse_token_string_t cmd_setpromisc_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_promisc_mode_result, mode,
+ "on#off");
+
+cmdline_parse_inst_t cmd_set_promisc_mode_all = {
+ .f = cmd_set_promisc_mode_parsed,
+ .data = (void *)1,
+ .help_str = "set promisc all on|off: Set promisc mode for all ports",
+ .tokens = {
+ (void *)&cmd_setpromisc_set,
+ (void *)&cmd_setpromisc_promisc,
+ (void *)&cmd_setpromisc_portall,
+ (void *)&cmd_setpromisc_mode,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_promisc_mode_one = {
+ .f = cmd_set_promisc_mode_parsed,
+ .data = (void *)0,
+ .help_str = "set promisc <port_id> on|off: Set promisc mode on port_id",
+ .tokens = {
+ (void *)&cmd_setpromisc_set,
+ (void *)&cmd_setpromisc_promisc,
+ (void *)&cmd_setpromisc_portnum,
+ (void *)&cmd_setpromisc_mode,
+ NULL,
+ },
+};
+
+/* *** SET ALLMULTI MODE *** */
+struct cmd_set_allmulti_mode_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t allmulti;
+ cmdline_fixed_string_t port_all; /* valid if "allports" argument == 1 */
+ uint16_t port_num; /* valid if "allports" argument == 0 */
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_allmulti_mode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *allports)
+{
+ struct cmd_set_allmulti_mode_result *res = parsed_result;
+ int enable;
+ portid_t i;
+
+ if (!strcmp(res->mode, "on"))
+ enable = 1;
+ else
+ enable = 0;
+
+ /* all ports */
+ if (allports) {
+ RTE_ETH_FOREACH_DEV(i) {
+ eth_set_allmulticast_mode(i, enable);
+ }
+ }
+ else {
+ eth_set_allmulticast_mode(res->port_num, enable);
+ }
+}
+
+cmdline_parse_token_string_t cmd_setallmulti_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, set, "set");
+cmdline_parse_token_string_t cmd_setallmulti_allmulti =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, allmulti,
+ "allmulti");
+cmdline_parse_token_string_t cmd_setallmulti_portall =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, port_all,
+ "all");
+cmdline_parse_token_num_t cmd_setallmulti_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_allmulti_mode_result, port_num,
+ UINT16);
+cmdline_parse_token_string_t cmd_setallmulti_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_allmulti_mode_result, mode,
+ "on#off");
+
+cmdline_parse_inst_t cmd_set_allmulti_mode_all = {
+ .f = cmd_set_allmulti_mode_parsed,
+ .data = (void *)1,
+ .help_str = "set allmulti all on|off: Set allmulti mode for all ports",
+ .tokens = {
+ (void *)&cmd_setallmulti_set,
+ (void *)&cmd_setallmulti_allmulti,
+ (void *)&cmd_setallmulti_portall,
+ (void *)&cmd_setallmulti_mode,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_allmulti_mode_one = {
+ .f = cmd_set_allmulti_mode_parsed,
+ .data = (void *)0,
+ .help_str = "set allmulti <port_id> on|off: "
+ "Set allmulti mode on port_id",
+ .tokens = {
+ (void *)&cmd_setallmulti_set,
+ (void *)&cmd_setallmulti_allmulti,
+ (void *)&cmd_setallmulti_portnum,
+ (void *)&cmd_setallmulti_mode,
+ NULL,
+ },
+};
+
+/* *** SETUP ETHERNET LINK FLOW CONTROL *** */
+struct cmd_link_flow_ctrl_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t flow_ctrl;
+ cmdline_fixed_string_t rx;
+ cmdline_fixed_string_t rx_lfc_mode;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t tx_lfc_mode;
+ cmdline_fixed_string_t mac_ctrl_frame_fwd;
+ cmdline_fixed_string_t mac_ctrl_frame_fwd_mode;
+ cmdline_fixed_string_t autoneg_str;
+ cmdline_fixed_string_t autoneg;
+ cmdline_fixed_string_t hw_str;
+ uint32_t high_water;
+ cmdline_fixed_string_t lw_str;
+ uint32_t low_water;
+ cmdline_fixed_string_t pt_str;
+ uint16_t pause_time;
+ cmdline_fixed_string_t xon_str;
+ uint16_t send_xon;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_lfc_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_lfc_set_flow_ctrl =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ flow_ctrl, "flow_ctrl");
+cmdline_parse_token_string_t cmd_lfc_set_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ rx, "rx");
+cmdline_parse_token_string_t cmd_lfc_set_rx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ rx_lfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_lfc_set_tx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ tx_lfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_high_water_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ hw_str, "high_water");
+cmdline_parse_token_num_t cmd_lfc_set_high_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ high_water, UINT32);
+cmdline_parse_token_string_t cmd_lfc_set_low_water_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ lw_str, "low_water");
+cmdline_parse_token_num_t cmd_lfc_set_low_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ low_water, UINT32);
+cmdline_parse_token_string_t cmd_lfc_set_pause_time_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ pt_str, "pause_time");
+cmdline_parse_token_num_t cmd_lfc_set_pause_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ pause_time, UINT16);
+cmdline_parse_token_string_t cmd_lfc_set_send_xon_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ xon_str, "send_xon");
+cmdline_parse_token_num_t cmd_lfc_set_send_xon =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ send_xon, UINT16);
+cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ mac_ctrl_frame_fwd, "mac_ctrl_frame_fwd");
+cmdline_parse_token_string_t cmd_lfc_set_mac_ctrl_frame_fwd =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ mac_ctrl_frame_fwd_mode, "on#off");
+cmdline_parse_token_string_t cmd_lfc_set_autoneg_str =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ autoneg_str, "autoneg");
+cmdline_parse_token_string_t cmd_lfc_set_autoneg =
+ TOKEN_STRING_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ autoneg, "on#off");
+cmdline_parse_token_num_t cmd_lfc_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_link_flow_ctrl_set_result,
+ port_id, UINT16);
+
+/* forward declaration */
+static void
+cmd_link_flow_ctrl_set_parsed(void *parsed_result, struct cmdline *cl,
+ void *data);
+
+cmdline_parse_inst_t cmd_link_flow_control_set = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = NULL,
+ .help_str = "set flow_ctrl rx on|off tx on|off <high_water> "
+ "<low_water> <pause_time> <send_xon> mac_ctrl_frame_fwd on|off "
+ "autoneg on|off <port_id>: Configure the Ethernet flow control",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_rx,
+ (void *)&cmd_lfc_set_rx_mode,
+ (void *)&cmd_lfc_set_tx,
+ (void *)&cmd_lfc_set_tx_mode,
+ (void *)&cmd_lfc_set_high_water,
+ (void *)&cmd_lfc_set_low_water,
+ (void *)&cmd_lfc_set_pause_time,
+ (void *)&cmd_lfc_set_send_xon,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd,
+ (void *)&cmd_lfc_set_autoneg_str,
+ (void *)&cmd_lfc_set_autoneg,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_rx = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_rx,
+ .help_str = "set flow_ctrl rx on|off <port_id>: "
+ "Change rx flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_rx,
+ (void *)&cmd_lfc_set_rx_mode,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_tx = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_tx,
+ .help_str = "set flow_ctrl tx on|off <port_id>: "
+ "Change tx flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_tx,
+ (void *)&cmd_lfc_set_tx_mode,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_hw = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_hw,
+ .help_str = "set flow_ctrl high_water <value> <port_id>: "
+ "Change high water flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_high_water_str,
+ (void *)&cmd_lfc_set_high_water,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_lw = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_lw,
+ .help_str = "set flow_ctrl low_water <value> <port_id>: "
+ "Change low water flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_low_water_str,
+ (void *)&cmd_lfc_set_low_water,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_pt = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_pt,
+ .help_str = "set flow_ctrl pause_time <value> <port_id>: "
+ "Change pause time flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_pause_time_str,
+ (void *)&cmd_lfc_set_pause_time,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_xon = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_xon,
+ .help_str = "set flow_ctrl send_xon <value> <port_id>: "
+ "Change send_xon flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_send_xon_str,
+ (void *)&cmd_lfc_set_send_xon,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_macfwd = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_macfwd,
+ .help_str = "set flow_ctrl mac_ctrl_frame_fwd on|off <port_id>: "
+ "Change mac ctrl fwd flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd_mode,
+ (void *)&cmd_lfc_set_mac_ctrl_frame_fwd,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_link_flow_control_set_autoneg = {
+ .f = cmd_link_flow_ctrl_set_parsed,
+ .data = (void *)&cmd_link_flow_control_set_autoneg,
+ .help_str = "set flow_ctrl autoneg on|off <port_id>: "
+ "Change autoneg flow control parameter",
+ .tokens = {
+ (void *)&cmd_lfc_set_set,
+ (void *)&cmd_lfc_set_flow_ctrl,
+ (void *)&cmd_lfc_set_autoneg_str,
+ (void *)&cmd_lfc_set_autoneg,
+ (void *)&cmd_lfc_set_portid,
+ NULL,
+ },
+};
+
+static void
+cmd_link_flow_ctrl_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ void *data)
+{
+ struct cmd_link_flow_ctrl_set_result *res = parsed_result;
+ cmdline_parse_inst_t *cmd = data;
+ struct rte_eth_fc_conf fc_conf;
+ int rx_fc_en = 0;
+ int tx_fc_en = 0;
+ int ret;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_lfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL}
+ };
+
+ /* Partial command line, retrieve current configuration */
+ if (cmd) {
+ ret = rte_eth_dev_flow_ctrl_get(res->port_id, &fc_conf);
+ if (ret != 0) {
+ printf("cannot get current flow ctrl parameters, return"
+ "code = %d\n", ret);
+ return;
+ }
+
+ if ((fc_conf.mode == RTE_FC_RX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ rx_fc_en = 1;
+ if ((fc_conf.mode == RTE_FC_TX_PAUSE) ||
+ (fc_conf.mode == RTE_FC_FULL))
+ tx_fc_en = 1;
+ }
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_rx)
+ rx_fc_en = (!strcmp(res->rx_lfc_mode, "on")) ? 1 : 0;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_tx)
+ tx_fc_en = (!strcmp(res->tx_lfc_mode, "on")) ? 1 : 0;
+
+ fc_conf.mode = rx_tx_onoff_2_lfc_mode[rx_fc_en][tx_fc_en];
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_hw)
+ fc_conf.high_water = res->high_water;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_lw)
+ fc_conf.low_water = res->low_water;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_pt)
+ fc_conf.pause_time = res->pause_time;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_xon)
+ fc_conf.send_xon = res->send_xon;
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_macfwd) {
+ if (!strcmp(res->mac_ctrl_frame_fwd_mode, "on"))
+ fc_conf.mac_ctrl_frame_fwd = 1;
+ else
+ fc_conf.mac_ctrl_frame_fwd = 0;
+ }
+
+ if (!cmd || cmd == &cmd_link_flow_control_set_autoneg)
+ fc_conf.autoneg = (!strcmp(res->autoneg, "on")) ? 1 : 0;
+
+ ret = rte_eth_dev_flow_ctrl_set(res->port_id, &fc_conf);
+ if (ret != 0)
+ printf("bad flow contrl parameter, return code = %d \n", ret);
+}
+
+/* *** SETUP ETHERNET PRIORITY FLOW CONTROL *** */
+struct cmd_priority_flow_ctrl_set_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t pfc_ctrl;
+ cmdline_fixed_string_t rx;
+ cmdline_fixed_string_t rx_pfc_mode;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t tx_pfc_mode;
+ uint32_t high_water;
+ uint32_t low_water;
+ uint16_t pause_time;
+ uint8_t priority;
+ portid_t port_id;
+};
+
+static void
+cmd_priority_flow_ctrl_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_priority_flow_ctrl_set_result *res = parsed_result;
+ struct rte_eth_pfc_conf pfc_conf;
+ int rx_fc_enable, tx_fc_enable;
+ int ret;
+
+ /*
+ * Rx on/off, flow control is enabled/disabled on RX side. This can indicate
+ * the RTE_FC_TX_PAUSE, Transmit pause frame at the Rx side.
+ * Tx on/off, flow control is enabled/disabled on TX side. This can indicate
+ * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
+ */
+ static enum rte_eth_fc_mode rx_tx_onoff_2_pfc_mode[2][2] = {
+ {RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL}
+ };
+
+ memset(&pfc_conf, 0, sizeof(struct rte_eth_pfc_conf));
+ rx_fc_enable = (!strncmp(res->rx_pfc_mode, "on",2)) ? 1 : 0;
+ tx_fc_enable = (!strncmp(res->tx_pfc_mode, "on",2)) ? 1 : 0;
+ pfc_conf.fc.mode = rx_tx_onoff_2_pfc_mode[rx_fc_enable][tx_fc_enable];
+ pfc_conf.fc.high_water = res->high_water;
+ pfc_conf.fc.low_water = res->low_water;
+ pfc_conf.fc.pause_time = res->pause_time;
+ pfc_conf.priority = res->priority;
+
+ ret = rte_eth_dev_priority_flow_ctrl_set(res->port_id, &pfc_conf);
+ if (ret != 0)
+ printf("bad priority flow contrl parameter, return code = %d \n", ret);
+}
+
+cmdline_parse_token_string_t cmd_pfc_set_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_pfc_set_flow_ctrl =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ pfc_ctrl, "pfc_ctrl");
+cmdline_parse_token_string_t cmd_pfc_set_rx =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ rx, "rx");
+cmdline_parse_token_string_t cmd_pfc_set_rx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ rx_pfc_mode, "on#off");
+cmdline_parse_token_string_t cmd_pfc_set_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_pfc_set_tx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ tx_pfc_mode, "on#off");
+cmdline_parse_token_num_t cmd_pfc_set_high_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ high_water, UINT32);
+cmdline_parse_token_num_t cmd_pfc_set_low_water =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ low_water, UINT32);
+cmdline_parse_token_num_t cmd_pfc_set_pause_time =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ pause_time, UINT16);
+cmdline_parse_token_num_t cmd_pfc_set_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ priority, UINT8);
+cmdline_parse_token_num_t cmd_pfc_set_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_priority_flow_ctrl_set_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_priority_flow_control_set = {
+ .f = cmd_priority_flow_ctrl_set_parsed,
+ .data = NULL,
+ .help_str = "set pfc_ctrl rx on|off tx on|off <high_water> <low_water> "
+ "<pause_time> <priority> <port_id>: "
+ "Configure the Ethernet priority flow control",
+ .tokens = {
+ (void *)&cmd_pfc_set_set,
+ (void *)&cmd_pfc_set_flow_ctrl,
+ (void *)&cmd_pfc_set_rx,
+ (void *)&cmd_pfc_set_rx_mode,
+ (void *)&cmd_pfc_set_tx,
+ (void *)&cmd_pfc_set_tx_mode,
+ (void *)&cmd_pfc_set_high_water,
+ (void *)&cmd_pfc_set_low_water,
+ (void *)&cmd_pfc_set_pause_time,
+ (void *)&cmd_pfc_set_priority,
+ (void *)&cmd_pfc_set_portid,
+ NULL,
+ },
+};
+
+/* *** RESET CONFIGURATION *** */
+struct cmd_reset_result {
+ cmdline_fixed_string_t reset;
+ cmdline_fixed_string_t def;
+};
+
+static void cmd_reset_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_printf(cl, "Reset to default forwarding configuration...\n");
+ set_def_fwd_config();
+}
+
+cmdline_parse_token_string_t cmd_reset_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_reset_result, reset, "set");
+cmdline_parse_token_string_t cmd_reset_def =
+ TOKEN_STRING_INITIALIZER(struct cmd_reset_result, def,
+ "default");
+
+cmdline_parse_inst_t cmd_reset = {
+ .f = cmd_reset_parsed,
+ .data = NULL,
+ .help_str = "set default: Reset default forwarding configuration",
+ .tokens = {
+ (void *)&cmd_reset_set,
+ (void *)&cmd_reset_def,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING *** */
+struct cmd_start_result {
+ cmdline_fixed_string_t start;
+};
+
+cmdline_parse_token_string_t cmd_start_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start");
+
+static void cmd_start_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ start_packet_forwarding(0);
+}
+
+cmdline_parse_inst_t cmd_start = {
+ .f = cmd_start_parsed,
+ .data = NULL,
+ .help_str = "start: Start packet forwarding",
+ .tokens = {
+ (void *)&cmd_start_start,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING WITH ONE TX BURST FIRST *** */
+struct cmd_start_tx_first_result {
+ cmdline_fixed_string_t start;
+ cmdline_fixed_string_t tx_first;
+};
+
+static void
+cmd_start_tx_first_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ start_packet_forwarding(1);
+}
+
+cmdline_parse_token_string_t cmd_start_tx_first_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result, start,
+ "start");
+cmdline_parse_token_string_t cmd_start_tx_first_tx_first =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_result,
+ tx_first, "tx_first");
+
+cmdline_parse_inst_t cmd_start_tx_first = {
+ .f = cmd_start_tx_first_parsed,
+ .data = NULL,
+ .help_str = "start tx_first: Start packet forwarding, "
+ "after sending 1 burst of packets",
+ .tokens = {
+ (void *)&cmd_start_tx_first_start,
+ (void *)&cmd_start_tx_first_tx_first,
+ NULL,
+ },
+};
+
+/* *** START FORWARDING WITH N TX BURST FIRST *** */
+struct cmd_start_tx_first_n_result {
+ cmdline_fixed_string_t start;
+ cmdline_fixed_string_t tx_first;
+ uint32_t tx_num;
+};
+
+static void
+cmd_start_tx_first_n_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_start_tx_first_n_result *res = parsed_result;
+
+ start_packet_forwarding(res->tx_num);
+}
+
+cmdline_parse_token_string_t cmd_start_tx_first_n_start =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_n_result,
+ start, "start");
+cmdline_parse_token_string_t cmd_start_tx_first_n_tx_first =
+ TOKEN_STRING_INITIALIZER(struct cmd_start_tx_first_n_result,
+ tx_first, "tx_first");
+cmdline_parse_token_num_t cmd_start_tx_first_n_tx_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_start_tx_first_n_result,
+ tx_num, UINT32);
+
+cmdline_parse_inst_t cmd_start_tx_first_n = {
+ .f = cmd_start_tx_first_n_parsed,
+ .data = NULL,
+ .help_str = "start tx_first <num>: "
+ "packet forwarding, after sending <num> bursts of packets",
+ .tokens = {
+ (void *)&cmd_start_tx_first_n_start,
+ (void *)&cmd_start_tx_first_n_tx_first,
+ (void *)&cmd_start_tx_first_n_tx_num,
+ NULL,
+ },
+};
+
+/* *** SET LINK UP *** */
+struct cmd_set_link_up_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_up;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_set_link_up_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, set, "set");
+cmdline_parse_token_string_t cmd_set_link_up_link_up =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, link_up,
+ "link-up");
+cmdline_parse_token_string_t cmd_set_link_up_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_up_result, port, "port");
+cmdline_parse_token_num_t cmd_set_link_up_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_link_up_result, port_id, UINT16);
+
+static void cmd_set_link_up_parsed(__rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_link_up_result *res = parsed_result;
+ dev_set_link_up(res->port_id);
+}
+
+cmdline_parse_inst_t cmd_set_link_up = {
+ .f = cmd_set_link_up_parsed,
+ .data = NULL,
+ .help_str = "set link-up port <port id>",
+ .tokens = {
+ (void *)&cmd_set_link_up_set,
+ (void *)&cmd_set_link_up_link_up,
+ (void *)&cmd_set_link_up_port,
+ (void *)&cmd_set_link_up_port_id,
+ NULL,
+ },
+};
+
+/* *** SET LINK DOWN *** */
+struct cmd_set_link_down_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t link_down;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_set_link_down_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, set, "set");
+cmdline_parse_token_string_t cmd_set_link_down_link_down =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, link_down,
+ "link-down");
+cmdline_parse_token_string_t cmd_set_link_down_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_link_down_result, port, "port");
+cmdline_parse_token_num_t cmd_set_link_down_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_link_down_result, port_id, UINT16);
+
+static void cmd_set_link_down_parsed(
+ __rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_link_down_result *res = parsed_result;
+ dev_set_link_down(res->port_id);
+}
+
+cmdline_parse_inst_t cmd_set_link_down = {
+ .f = cmd_set_link_down_parsed,
+ .data = NULL,
+ .help_str = "set link-down port <port id>",
+ .tokens = {
+ (void *)&cmd_set_link_down_set,
+ (void *)&cmd_set_link_down_link_down,
+ (void *)&cmd_set_link_down_port,
+ (void *)&cmd_set_link_down_port_id,
+ NULL,
+ },
+};
+
+/* *** SHOW CFG *** */
+struct cmd_showcfg_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t cfg;
+ cmdline_fixed_string_t what;
+};
+
+static void cmd_showcfg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showcfg_result *res = parsed_result;
+ if (!strcmp(res->what, "rxtx"))
+ rxtx_config_display();
+ else if (!strcmp(res->what, "cores"))
+ fwd_lcores_config_display();
+ else if (!strcmp(res->what, "fwd"))
+ pkt_fwd_config_display(&cur_fwd_config);
+ else if (!strcmp(res->what, "txpkts"))
+ show_tx_pkt_segments();
+}
+
+cmdline_parse_token_string_t cmd_showcfg_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, show, "show");
+cmdline_parse_token_string_t cmd_showcfg_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, cfg, "config");
+cmdline_parse_token_string_t cmd_showcfg_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showcfg_result, what,
+ "rxtx#cores#fwd#txpkts");
+
+cmdline_parse_inst_t cmd_showcfg = {
+ .f = cmd_showcfg_parsed,
+ .data = NULL,
+ .help_str = "show config rxtx|cores|fwd|txpkts",
+ .tokens = {
+ (void *)&cmd_showcfg_show,
+ (void *)&cmd_showcfg_port,
+ (void *)&cmd_showcfg_what,
+ NULL,
+ },
+};
+
+/* *** SHOW ALL PORT INFO *** */
+struct cmd_showportall_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t all;
+};
+
+static void cmd_showportall_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ portid_t i;
+
+ struct cmd_showportall_result *res = parsed_result;
+ if (!strcmp(res->show, "clear")) {
+ if (!strcmp(res->what, "stats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_clear(i);
+ else if (!strcmp(res->what, "xstats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_xstats_clear(i);
+ } else if (!strcmp(res->what, "info"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_infos_display(i);
+ else if (!strcmp(res->what, "summary")) {
+ port_summary_header_display();
+ RTE_ETH_FOREACH_DEV(i)
+ port_summary_display(i);
+ }
+ else if (!strcmp(res->what, "stats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_display(i);
+ else if (!strcmp(res->what, "xstats"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_xstats_display(i);
+ else if (!strcmp(res->what, "fdir"))
+ RTE_ETH_FOREACH_DEV(i)
+ fdir_get_infos(i);
+ else if (!strcmp(res->what, "stat_qmap"))
+ RTE_ETH_FOREACH_DEV(i)
+ nic_stats_mapping_display(i);
+ else if (!strcmp(res->what, "dcb_tc"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_dcb_info_display(i);
+ else if (!strcmp(res->what, "cap"))
+ RTE_ETH_FOREACH_DEV(i)
+ port_offload_cap_display(i);
+}
+
+cmdline_parse_token_string_t cmd_showportall_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, show,
+ "show#clear");
+cmdline_parse_token_string_t cmd_showportall_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, port, "port");
+cmdline_parse_token_string_t cmd_showportall_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, what,
+ "info#summary#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
+cmdline_parse_token_string_t cmd_showportall_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_showportall_result, all, "all");
+cmdline_parse_inst_t cmd_showportall = {
+ .f = cmd_showportall_parsed,
+ .data = NULL,
+ .help_str = "show|clear port "
+ "info|summary|stats|xstats|fdir|stat_qmap|dcb_tc|cap all",
+ .tokens = {
+ (void *)&cmd_showportall_show,
+ (void *)&cmd_showportall_port,
+ (void *)&cmd_showportall_what,
+ (void *)&cmd_showportall_all,
+ NULL,
+ },
+};
+
+/* *** SHOW PORT INFO *** */
+struct cmd_showport_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t what;
+ uint16_t portnum;
+};
+
+static void cmd_showport_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showport_result *res = parsed_result;
+ if (!strcmp(res->show, "clear")) {
+ if (!strcmp(res->what, "stats"))
+ nic_stats_clear(res->portnum);
+ else if (!strcmp(res->what, "xstats"))
+ nic_xstats_clear(res->portnum);
+ } else if (!strcmp(res->what, "info"))
+ port_infos_display(res->portnum);
+ else if (!strcmp(res->what, "summary")) {
+ port_summary_header_display();
+ port_summary_display(res->portnum);
+ }
+ else if (!strcmp(res->what, "stats"))
+ nic_stats_display(res->portnum);
+ else if (!strcmp(res->what, "xstats"))
+ nic_xstats_display(res->portnum);
+ else if (!strcmp(res->what, "fdir"))
+ fdir_get_infos(res->portnum);
+ else if (!strcmp(res->what, "stat_qmap"))
+ nic_stats_mapping_display(res->portnum);
+ else if (!strcmp(res->what, "dcb_tc"))
+ port_dcb_info_display(res->portnum);
+ else if (!strcmp(res->what, "cap"))
+ port_offload_cap_display(res->portnum);
+}
+
+cmdline_parse_token_string_t cmd_showport_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, show,
+ "show#clear");
+cmdline_parse_token_string_t cmd_showport_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, port, "port");
+cmdline_parse_token_string_t cmd_showport_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_result, what,
+ "info#summary#stats#xstats#fdir#stat_qmap#dcb_tc#cap");
+cmdline_parse_token_num_t cmd_showport_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_result, portnum, UINT16);
+
+cmdline_parse_inst_t cmd_showport = {
+ .f = cmd_showport_parsed,
+ .data = NULL,
+ .help_str = "show|clear port "
+ "info|summary|stats|xstats|fdir|stat_qmap|dcb_tc|cap "
+ "<port_id>",
+ .tokens = {
+ (void *)&cmd_showport_show,
+ (void *)&cmd_showport_port,
+ (void *)&cmd_showport_what,
+ (void *)&cmd_showport_portnum,
+ NULL,
+ },
+};
+
+/* *** SHOW DEVICE INFO *** */
+struct cmd_showdevice_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t device;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t identifier;
+};
+
+static void cmd_showdevice_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showdevice_result *res = parsed_result;
+ if (!strcmp(res->what, "info")) {
+ if (!strcmp(res->identifier, "all"))
+ device_infos_display(NULL);
+ else
+ device_infos_display(res->identifier);
+ }
+}
+
+cmdline_parse_token_string_t cmd_showdevice_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, show,
+ "show");
+cmdline_parse_token_string_t cmd_showdevice_device =
+ TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, device, "device");
+cmdline_parse_token_string_t cmd_showdevice_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result, what,
+ "info");
+cmdline_parse_token_string_t cmd_showdevice_identifier =
+ TOKEN_STRING_INITIALIZER(struct cmd_showdevice_result,
+ identifier, NULL);
+
+cmdline_parse_inst_t cmd_showdevice = {
+ .f = cmd_showdevice_parsed,
+ .data = NULL,
+ .help_str = "show device info <identifier>|all",
+ .tokens = {
+ (void *)&cmd_showdevice_show,
+ (void *)&cmd_showdevice_device,
+ (void *)&cmd_showdevice_what,
+ (void *)&cmd_showdevice_identifier,
+ NULL,
+ },
+};
+/* *** SHOW QUEUE INFO *** */
+struct cmd_showqueue_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t type;
+ cmdline_fixed_string_t what;
+ uint16_t portnum;
+ uint16_t queuenum;
+};
+
+static void
+cmd_showqueue_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showqueue_result *res = parsed_result;
+
+ if (!strcmp(res->type, "rxq"))
+ rx_queue_infos_display(res->portnum, res->queuenum);
+ else if (!strcmp(res->type, "txq"))
+ tx_queue_infos_display(res->portnum, res->queuenum);
+}
+
+cmdline_parse_token_string_t cmd_showqueue_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, show, "show");
+cmdline_parse_token_string_t cmd_showqueue_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, type, "rxq#txq");
+cmdline_parse_token_string_t cmd_showqueue_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_showqueue_result, what, "info");
+cmdline_parse_token_num_t cmd_showqueue_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, portnum, UINT16);
+cmdline_parse_token_num_t cmd_showqueue_queuenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_showqueue_result, queuenum, UINT16);
+
+cmdline_parse_inst_t cmd_showqueue = {
+ .f = cmd_showqueue_parsed,
+ .data = NULL,
+ .help_str = "show rxq|txq info <port_id> <queue_id>",
+ .tokens = {
+ (void *)&cmd_showqueue_show,
+ (void *)&cmd_showqueue_type,
+ (void *)&cmd_showqueue_what,
+ (void *)&cmd_showqueue_portnum,
+ (void *)&cmd_showqueue_queuenum,
+ NULL,
+ },
+};
+
+/* show/clear fwd engine statistics */
+struct fwd_result {
+ cmdline_fixed_string_t action;
+ cmdline_fixed_string_t fwd;
+ cmdline_fixed_string_t stats;
+ cmdline_fixed_string_t all;
+};
+
+cmdline_parse_token_string_t cmd_fwd_action =
+ TOKEN_STRING_INITIALIZER(struct fwd_result, action, "show#clear");
+cmdline_parse_token_string_t cmd_fwd_fwd =
+ TOKEN_STRING_INITIALIZER(struct fwd_result, fwd, "fwd");
+cmdline_parse_token_string_t cmd_fwd_stats =
+ TOKEN_STRING_INITIALIZER(struct fwd_result, stats, "stats");
+cmdline_parse_token_string_t cmd_fwd_all =
+ TOKEN_STRING_INITIALIZER(struct fwd_result, all, "all");
+
+static void
+cmd_showfwdall_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct fwd_result *res = parsed_result;
+
+ if (!strcmp(res->action, "show"))
+ fwd_stats_display();
+ else
+ fwd_stats_reset();
+}
+
+static cmdline_parse_inst_t cmd_showfwdall = {
+ .f = cmd_showfwdall_parsed,
+ .data = NULL,
+ .help_str = "show|clear fwd stats all",
+ .tokens = {
+ (void *)&cmd_fwd_action,
+ (void *)&cmd_fwd_fwd,
+ (void *)&cmd_fwd_stats,
+ (void *)&cmd_fwd_all,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER *** */
+struct cmd_read_reg_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t reg;
+ portid_t port_id;
+ uint32_t reg_off;
+};
+
+static void
+cmd_read_reg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_read_reg_result *res = parsed_result;
+ port_reg_display(res->port_id, res->reg_off);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, read, "read");
+cmdline_parse_token_string_t cmd_read_reg_reg =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_result, reg, "reg");
+cmdline_parse_token_num_t cmd_read_reg_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_read_reg_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_result, reg_off, UINT32);
+
+cmdline_parse_inst_t cmd_read_reg = {
+ .f = cmd_read_reg_parsed,
+ .data = NULL,
+ .help_str = "read reg <port_id> <reg_off>",
+ .tokens = {
+ (void *)&cmd_read_reg_read,
+ (void *)&cmd_read_reg_reg,
+ (void *)&cmd_read_reg_port_id,
+ (void *)&cmd_read_reg_reg_off,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER BIT FIELD *** */
+struct cmd_read_reg_bit_field_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t regfield;
+ portid_t port_id;
+ uint32_t reg_off;
+ uint8_t bit1_pos;
+ uint8_t bit2_pos;
+};
+
+static void
+cmd_read_reg_bit_field_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_read_reg_bit_field_result *res = parsed_result;
+ port_reg_bit_field_display(res->port_id, res->reg_off,
+ res->bit1_pos, res->bit2_pos);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_bit_field_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result, read,
+ "read");
+cmdline_parse_token_string_t cmd_read_reg_bit_field_regfield =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_field_result,
+ regfield, "regfield");
+cmdline_parse_token_num_t cmd_read_reg_bit_field_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, port_id,
+ UINT16);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, reg_off,
+ UINT32);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_bit1_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit1_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_read_reg_bit_field_bit2_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_field_result, bit2_pos,
+ UINT8);
+
+cmdline_parse_inst_t cmd_read_reg_bit_field = {
+ .f = cmd_read_reg_bit_field_parsed,
+ .data = NULL,
+ .help_str = "read regfield <port_id> <reg_off> <bit_x> <bit_y>: "
+ "Read register bit field between bit_x and bit_y included",
+ .tokens = {
+ (void *)&cmd_read_reg_bit_field_read,
+ (void *)&cmd_read_reg_bit_field_regfield,
+ (void *)&cmd_read_reg_bit_field_port_id,
+ (void *)&cmd_read_reg_bit_field_reg_off,
+ (void *)&cmd_read_reg_bit_field_bit1_pos,
+ (void *)&cmd_read_reg_bit_field_bit2_pos,
+ NULL,
+ },
+};
+
+/* *** READ PORT REGISTER BIT *** */
+struct cmd_read_reg_bit_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t regbit;
+ portid_t port_id;
+ uint32_t reg_off;
+ uint8_t bit_pos;
+};
+
+static void
+cmd_read_reg_bit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_read_reg_bit_result *res = parsed_result;
+ port_reg_bit_display(res->port_id, res->reg_off, res->bit_pos);
+}
+
+cmdline_parse_token_string_t cmd_read_reg_bit_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result, read, "read");
+cmdline_parse_token_string_t cmd_read_reg_bit_regbit =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_reg_bit_result,
+ regbit, "regbit");
+cmdline_parse_token_num_t cmd_read_reg_bit_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_read_reg_bit_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_read_reg_bit_bit_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_reg_bit_result, bit_pos, UINT8);
+
+cmdline_parse_inst_t cmd_read_reg_bit = {
+ .f = cmd_read_reg_bit_parsed,
+ .data = NULL,
+ .help_str = "read regbit <port_id> <reg_off> <bit_x>: 0 <= bit_x <= 31",
+ .tokens = {
+ (void *)&cmd_read_reg_bit_read,
+ (void *)&cmd_read_reg_bit_regbit,
+ (void *)&cmd_read_reg_bit_port_id,
+ (void *)&cmd_read_reg_bit_reg_off,
+ (void *)&cmd_read_reg_bit_bit_pos,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER *** */
+struct cmd_write_reg_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t reg;
+ portid_t port_id;
+ uint32_t reg_off;
+ uint32_t value;
+};
+
+static void
+cmd_write_reg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_write_reg_result *res = parsed_result;
+ port_reg_set(res->port_id, res->reg_off, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, write, "write");
+cmdline_parse_token_string_t cmd_write_reg_reg =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_result, reg, "reg");
+cmdline_parse_token_num_t cmd_write_reg_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_write_reg_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_write_reg_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_result, value, UINT32);
+
+cmdline_parse_inst_t cmd_write_reg = {
+ .f = cmd_write_reg_parsed,
+ .data = NULL,
+ .help_str = "write reg <port_id> <reg_off> <reg_value>",
+ .tokens = {
+ (void *)&cmd_write_reg_write,
+ (void *)&cmd_write_reg_reg,
+ (void *)&cmd_write_reg_port_id,
+ (void *)&cmd_write_reg_reg_off,
+ (void *)&cmd_write_reg_value,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER BIT FIELD *** */
+struct cmd_write_reg_bit_field_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t regfield;
+ portid_t port_id;
+ uint32_t reg_off;
+ uint8_t bit1_pos;
+ uint8_t bit2_pos;
+ uint32_t value;
+};
+
+static void
+cmd_write_reg_bit_field_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_write_reg_bit_field_result *res = parsed_result;
+ port_reg_bit_field_set(res->port_id, res->reg_off,
+ res->bit1_pos, res->bit2_pos, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_bit_field_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result, write,
+ "write");
+cmdline_parse_token_string_t cmd_write_reg_bit_field_regfield =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_field_result,
+ regfield, "regfield");
+cmdline_parse_token_num_t cmd_write_reg_bit_field_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, port_id,
+ UINT16);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, reg_off,
+ UINT32);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_bit1_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit1_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_bit2_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, bit2_pos,
+ UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_field_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_field_result, value,
+ UINT32);
+
+cmdline_parse_inst_t cmd_write_reg_bit_field = {
+ .f = cmd_write_reg_bit_field_parsed,
+ .data = NULL,
+ .help_str = "write regfield <port_id> <reg_off> <bit_x> <bit_y> "
+ "<reg_value>: "
+ "Set register bit field between bit_x and bit_y included",
+ .tokens = {
+ (void *)&cmd_write_reg_bit_field_write,
+ (void *)&cmd_write_reg_bit_field_regfield,
+ (void *)&cmd_write_reg_bit_field_port_id,
+ (void *)&cmd_write_reg_bit_field_reg_off,
+ (void *)&cmd_write_reg_bit_field_bit1_pos,
+ (void *)&cmd_write_reg_bit_field_bit2_pos,
+ (void *)&cmd_write_reg_bit_field_value,
+ NULL,
+ },
+};
+
+/* *** WRITE PORT REGISTER BIT *** */
+struct cmd_write_reg_bit_result {
+ cmdline_fixed_string_t write;
+ cmdline_fixed_string_t regbit;
+ portid_t port_id;
+ uint32_t reg_off;
+ uint8_t bit_pos;
+ uint8_t value;
+};
+
+static void
+cmd_write_reg_bit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_write_reg_bit_result *res = parsed_result;
+ port_reg_bit_set(res->port_id, res->reg_off, res->bit_pos, res->value);
+}
+
+cmdline_parse_token_string_t cmd_write_reg_bit_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result, write,
+ "write");
+cmdline_parse_token_string_t cmd_write_reg_bit_regbit =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_reg_bit_result,
+ regbit, "regbit");
+cmdline_parse_token_num_t cmd_write_reg_bit_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_write_reg_bit_reg_off =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, reg_off, UINT32);
+cmdline_parse_token_num_t cmd_write_reg_bit_bit_pos =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, bit_pos, UINT8);
+cmdline_parse_token_num_t cmd_write_reg_bit_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_reg_bit_result, value, UINT8);
+
+cmdline_parse_inst_t cmd_write_reg_bit = {
+ .f = cmd_write_reg_bit_parsed,
+ .data = NULL,
+ .help_str = "write regbit <port_id> <reg_off> <bit_x> 0|1: "
+ "0 <= bit_x <= 31",
+ .tokens = {
+ (void *)&cmd_write_reg_bit_write,
+ (void *)&cmd_write_reg_bit_regbit,
+ (void *)&cmd_write_reg_bit_port_id,
+ (void *)&cmd_write_reg_bit_reg_off,
+ (void *)&cmd_write_reg_bit_bit_pos,
+ (void *)&cmd_write_reg_bit_value,
+ NULL,
+ },
+};
+
+/* *** READ A RING DESCRIPTOR OF A PORT RX/TX QUEUE *** */
+struct cmd_read_rxd_txd_result {
+ cmdline_fixed_string_t read;
+ cmdline_fixed_string_t rxd_txd;
+ portid_t port_id;
+ uint16_t queue_id;
+ uint16_t desc_id;
+};
+
+static void
+cmd_read_rxd_txd_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_read_rxd_txd_result *res = parsed_result;
+
+ if (!strcmp(res->rxd_txd, "rxd"))
+ rx_ring_desc_display(res->port_id, res->queue_id, res->desc_id);
+ else if (!strcmp(res->rxd_txd, "txd"))
+ tx_ring_desc_display(res->port_id, res->queue_id, res->desc_id);
+}
+
+cmdline_parse_token_string_t cmd_read_rxd_txd_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, read, "read");
+cmdline_parse_token_string_t cmd_read_rxd_txd_rxd_txd =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_rxd_txd_result, rxd_txd,
+ "rxd#txd");
+cmdline_parse_token_num_t cmd_read_rxd_txd_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_read_rxd_txd_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, queue_id, UINT16);
+cmdline_parse_token_num_t cmd_read_rxd_txd_desc_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_read_rxd_txd_result, desc_id, UINT16);
+
+cmdline_parse_inst_t cmd_read_rxd_txd = {
+ .f = cmd_read_rxd_txd_parsed,
+ .data = NULL,
+ .help_str = "read rxd|txd <port_id> <queue_id> <desc_id>",
+ .tokens = {
+ (void *)&cmd_read_rxd_txd_read,
+ (void *)&cmd_read_rxd_txd_rxd_txd,
+ (void *)&cmd_read_rxd_txd_port_id,
+ (void *)&cmd_read_rxd_txd_queue_id,
+ (void *)&cmd_read_rxd_txd_desc_id,
+ NULL,
+ },
+};
+
+/* *** QUIT *** */
+struct cmd_quit_result {
+ cmdline_fixed_string_t quit;
+};
+
+static void cmd_quit_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_quit(cl);
+}
+
+cmdline_parse_token_string_t cmd_quit_quit =
+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
+
+cmdline_parse_inst_t cmd_quit = {
+ .f = cmd_quit_parsed,
+ .data = NULL,
+ .help_str = "quit: Exit application",
+ .tokens = {
+ (void *)&cmd_quit_quit,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE MAC ADDRESS FROM A PORT *** */
+struct cmd_mac_addr_result {
+ cmdline_fixed_string_t mac_addr_cmd;
+ cmdline_fixed_string_t what;
+ uint16_t port_num;
+ struct rte_ether_addr address;
+};
+
+static void cmd_mac_addr_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_mac_addr_result *res = parsed_result;
+ int ret;
+
+ if (strcmp(res->what, "add") == 0)
+ ret = rte_eth_dev_mac_addr_add(res->port_num, &res->address, 0);
+ else if (strcmp(res->what, "set") == 0)
+ ret = rte_eth_dev_default_mac_addr_set(res->port_num,
+ &res->address);
+ else
+ ret = rte_eth_dev_mac_addr_remove(res->port_num, &res->address);
+
+ /* check the return value and print it if is < 0 */
+ if(ret < 0)
+ printf("mac_addr_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_mac_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, mac_addr_cmd,
+ "mac_addr");
+cmdline_parse_token_string_t cmd_mac_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_mac_addr_result, what,
+ "add#remove#set");
+cmdline_parse_token_num_t cmd_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_mac_addr_result, port_num,
+ UINT16);
+cmdline_parse_token_etheraddr_t cmd_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_mac_addr = {
+ .f = cmd_mac_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mac_addr add|remove|set <port_id> <mac_addr>: "
+ "Add/Remove/Set MAC address on port_id",
+ .tokens = {
+ (void *)&cmd_mac_addr_cmd,
+ (void *)&cmd_mac_addr_what,
+ (void *)&cmd_mac_addr_portnum,
+ (void *)&cmd_mac_addr_addr,
+ NULL,
+ },
+};
+
+/* *** SET THE PEER ADDRESS FOR CERTAIN PORT *** */
+struct cmd_eth_peer_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t eth_peer;
+ portid_t port_id;
+ cmdline_fixed_string_t peer_addr;
+};
+
+static void cmd_set_eth_peer_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_eth_peer_result *res = parsed_result;
+
+ if (test_done == 0) {
+ printf("Please stop forwarding first\n");
+ return;
+ }
+ if (!strcmp(res->eth_peer, "eth-peer")) {
+ set_fwd_eth_peer(res->port_id, res->peer_addr);
+ fwd_config_setup();
+ }
+}
+cmdline_parse_token_string_t cmd_eth_peer_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_eth_peer_result, set, "set");
+cmdline_parse_token_string_t cmd_eth_peer =
+ TOKEN_STRING_INITIALIZER(struct cmd_eth_peer_result, eth_peer, "eth-peer");
+cmdline_parse_token_num_t cmd_eth_peer_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_eth_peer_result, port_id, UINT16);
+cmdline_parse_token_string_t cmd_eth_peer_addr =
+ TOKEN_STRING_INITIALIZER(struct cmd_eth_peer_result, peer_addr, NULL);
+
+cmdline_parse_inst_t cmd_set_fwd_eth_peer = {
+ .f = cmd_set_eth_peer_parsed,
+ .data = NULL,
+ .help_str = "set eth-peer <port_id> <peer_mac>",
+ .tokens = {
+ (void *)&cmd_eth_peer_set,
+ (void *)&cmd_eth_peer,
+ (void *)&cmd_eth_peer_port_id,
+ (void *)&cmd_eth_peer_addr,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE QUEUE STATS COUNTER MAPPINGS *** */
+struct cmd_set_qmap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t qmap;
+ cmdline_fixed_string_t what;
+ portid_t port_id;
+ uint16_t queue_id;
+ uint8_t map_value;
+};
+
+static void
+cmd_set_qmap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_qmap_result *res = parsed_result;
+ int is_rx = (strcmp(res->what, "tx") == 0) ? 0 : 1;
+
+ set_qmap(res->port_id, (uint8_t)is_rx, res->queue_id, res->map_value);
+}
+
+cmdline_parse_token_string_t cmd_setqmap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_setqmap_qmap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ qmap, "stat_qmap");
+cmdline_parse_token_string_t cmd_setqmap_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_qmap_result,
+ what, "tx#rx");
+cmdline_parse_token_num_t cmd_setqmap_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_setqmap_queueid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ queue_id, UINT16);
+cmdline_parse_token_num_t cmd_setqmap_mapvalue =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_qmap_result,
+ map_value, UINT8);
+
+cmdline_parse_inst_t cmd_set_qmap = {
+ .f = cmd_set_qmap_parsed,
+ .data = NULL,
+ .help_str = "set stat_qmap rx|tx <port_id> <queue_id> <map_value>: "
+ "Set statistics mapping value on tx|rx queue_id of port_id",
+ .tokens = {
+ (void *)&cmd_setqmap_set,
+ (void *)&cmd_setqmap_qmap,
+ (void *)&cmd_setqmap_what,
+ (void *)&cmd_setqmap_portid,
+ (void *)&cmd_setqmap_queueid,
+ (void *)&cmd_setqmap_mapvalue,
+ NULL,
+ },
+};
+
+/* *** SET OPTION TO HIDE ZERO VALUES FOR XSTATS DISPLAY *** */
+struct cmd_set_xstats_hide_zero_result {
+ cmdline_fixed_string_t keyword;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t on_off;
+};
+
+static void
+cmd_set_xstats_hide_zero_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_xstats_hide_zero_result *res;
+ uint16_t on_off = 0;
+
+ res = parsed_result;
+ on_off = !strcmp(res->on_off, "on") ? 1 : 0;
+ set_xstats_hide_zero(on_off);
+}
+
+cmdline_parse_token_string_t cmd_set_xstats_hide_zero_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_xstats_hide_zero_result,
+ keyword, "set");
+cmdline_parse_token_string_t cmd_set_xstats_hide_zero_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_xstats_hide_zero_result,
+ name, "xstats-hide-zero");
+cmdline_parse_token_string_t cmd_set_xstats_hide_zero_on_off =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_xstats_hide_zero_result,
+ on_off, "on#off");
+
+cmdline_parse_inst_t cmd_set_xstats_hide_zero = {
+ .f = cmd_set_xstats_hide_zero_parsed,
+ .data = NULL,
+ .help_str = "set xstats-hide-zero on|off",
+ .tokens = {
+ (void *)&cmd_set_xstats_hide_zero_keyword,
+ (void *)&cmd_set_xstats_hide_zero_name,
+ (void *)&cmd_set_xstats_hide_zero_on_off,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE UNICAST HASH TABLE *** */
+struct cmd_set_uc_hash_table {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t what;
+ struct rte_ether_addr address;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_uc_hash_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret=0;
+ struct cmd_set_uc_hash_table *res = parsed_result;
+
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if (strcmp(res->what, "uta") == 0)
+ ret = rte_eth_dev_uc_hash_table_set(res->port_id,
+ &res->address,(uint8_t)is_on);
+ if (ret < 0)
+ printf("bad unicast hash table parameter, return code = %d \n", ret);
+
+}
+
+cmdline_parse_token_string_t cmd_set_uc_hash_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_uc_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_uc_hash_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_uc_hash_table,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_uc_hash_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ what, "uta");
+cmdline_parse_token_etheraddr_t cmd_set_uc_hash_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_uc_hash_table,
+ address);
+cmdline_parse_token_string_t cmd_set_uc_hash_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_hash_table,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_uc_hash_filter = {
+ .f = cmd_set_uc_hash_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> uta <mac_addr> on|off)",
+ .tokens = {
+ (void *)&cmd_set_uc_hash_set,
+ (void *)&cmd_set_uc_hash_port,
+ (void *)&cmd_set_uc_hash_portid,
+ (void *)&cmd_set_uc_hash_what,
+ (void *)&cmd_set_uc_hash_mac,
+ (void *)&cmd_set_uc_hash_mode,
+ NULL,
+ },
+};
+
+struct cmd_set_uc_all_hash_table {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t value;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_uc_all_hash_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret=0;
+ struct cmd_set_uc_all_hash_table *res = parsed_result;
+
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if ((strcmp(res->what, "uta") == 0) &&
+ (strcmp(res->value, "all") == 0))
+ ret = rte_eth_dev_uc_all_hash_table_set(res->port_id,(uint8_t) is_on);
+ if (ret < 0)
+ printf("bad unicast hash table parameter,"
+ "return code = %d \n", ret);
+}
+
+cmdline_parse_token_string_t cmd_set_uc_all_hash_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_uc_all_hash_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_uc_all_hash_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ what, "uta");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ value,"all");
+cmdline_parse_token_string_t cmd_set_uc_all_hash_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_uc_all_hash_table,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_uc_all_hash_filter = {
+ .f = cmd_set_uc_all_hash_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> uta all on|off",
+ .tokens = {
+ (void *)&cmd_set_uc_all_hash_set,
+ (void *)&cmd_set_uc_all_hash_port,
+ (void *)&cmd_set_uc_all_hash_portid,
+ (void *)&cmd_set_uc_all_hash_what,
+ (void *)&cmd_set_uc_all_hash_value,
+ (void *)&cmd_set_uc_all_hash_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE MACVLAN FILTER FOR VF(s) *** */
+struct cmd_set_vf_macvlan_filter {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ struct rte_ether_addr address;
+ cmdline_fixed_string_t filter_type;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_vf_macvlan_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int is_on, ret = 0;
+ struct cmd_set_vf_macvlan_filter *res = parsed_result;
+ struct rte_eth_mac_filter filter;
+
+ memset(&filter, 0, sizeof(struct rte_eth_mac_filter));
+
+ rte_memcpy(&filter.mac_addr, &res->address, RTE_ETHER_ADDR_LEN);
+
+ /* set VF MAC filter */
+ filter.is_vf = 1;
+
+ /* set VF ID */
+ filter.dst_id = res->vf_id;
+
+ if (!strcmp(res->filter_type, "exact-mac"))
+ filter.filter_type = RTE_MAC_PERFECT_MATCH;
+ else if (!strcmp(res->filter_type, "exact-mac-vlan"))
+ filter.filter_type = RTE_MACVLAN_PERFECT_MATCH;
+ else if (!strcmp(res->filter_type, "hashmac"))
+ filter.filter_type = RTE_MAC_HASH_MATCH;
+ else if (!strcmp(res->filter_type, "hashmac-vlan"))
+ filter.filter_type = RTE_MACVLAN_HASH_MATCH;
+
+ is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ if (is_on)
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_MACVLAN,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_MACVLAN,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+
+ if (ret < 0)
+ printf("bad set MAC hash parameter, return code = %d\n", ret);
+
+}
+
+cmdline_parse_token_string_t cmd_set_vf_macvlan_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_macvlan_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_vf_macvlan_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_macvlan_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_set_vf_macvlan_vf_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ vf_id, UINT8);
+cmdline_parse_token_etheraddr_t cmd_set_vf_macvlan_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ address);
+cmdline_parse_token_string_t cmd_set_vf_macvlan_filter_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ filter_type, "exact-mac#exact-mac-vlan"
+ "#hashmac#hashmac-vlan");
+cmdline_parse_token_string_t cmd_set_vf_macvlan_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_macvlan_filter,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_macvlan_filter = {
+ .f = cmd_set_vf_macvlan_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> <mac_addr> "
+ "exact-mac|exact-mac-vlan|hashmac|hashmac-vlan on|off: "
+ "Exact match rule: exact match of MAC or MAC and VLAN; "
+ "hash match rule: hash match of MAC and exact match of VLAN",
+ .tokens = {
+ (void *)&cmd_set_vf_macvlan_set,
+ (void *)&cmd_set_vf_macvlan_port,
+ (void *)&cmd_set_vf_macvlan_portid,
+ (void *)&cmd_set_vf_macvlan_vf,
+ (void *)&cmd_set_vf_macvlan_vf_id,
+ (void *)&cmd_set_vf_macvlan_mac,
+ (void *)&cmd_set_vf_macvlan_filter_type,
+ (void *)&cmd_set_vf_macvlan_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VF TRAFFIC CONTROL *** */
+struct cmd_set_vf_traffic {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t mode;
+};
+
+static void
+cmd_set_vf_traffic_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_vf_traffic *res = parsed_result;
+ int is_rx = (strcmp(res->what, "rx") == 0) ? 1 : 0;
+ int is_on = (strcmp(res->mode, "on") == 0) ? 1 : 0;
+
+ set_vf_traffic(res->port_id, (uint8_t)is_rx, res->vf_id,(uint8_t) is_on);
+}
+
+cmdline_parse_token_string_t cmd_setvf_traffic_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ set, "set");
+cmdline_parse_token_string_t cmd_setvf_traffic_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ port, "port");
+cmdline_parse_token_num_t cmd_setvf_traffic_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_setvf_traffic_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_setvf_traffic_vfid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_traffic,
+ vf_id, UINT8);
+cmdline_parse_token_string_t cmd_setvf_traffic_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ what, "tx#rx");
+cmdline_parse_token_string_t cmd_setvf_traffic_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_traffic,
+ mode, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_traffic = {
+ .f = cmd_set_vf_traffic_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> rx|tx on|off",
+ .tokens = {
+ (void *)&cmd_setvf_traffic_set,
+ (void *)&cmd_setvf_traffic_port,
+ (void *)&cmd_setvf_traffic_portid,
+ (void *)&cmd_setvf_traffic_vf,
+ (void *)&cmd_setvf_traffic_vfid,
+ (void *)&cmd_setvf_traffic_what,
+ (void *)&cmd_setvf_traffic_mode,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VF RECEIVE MODE *** */
+struct cmd_set_vf_rxmode {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t on;
+};
+
+static void
+cmd_set_vf_rxmode_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret = -ENOTSUP;
+ uint16_t vf_rxmode = 0;
+ struct cmd_set_vf_rxmode *res = parsed_result;
+
+ int is_on = (strcmp(res->on, "on") == 0) ? 1 : 0;
+ if (!strcmp(res->what,"rxmode")) {
+ if (!strcmp(res->mode, "AUPE"))
+ vf_rxmode |= ETH_VMDQ_ACCEPT_UNTAG;
+ else if (!strcmp(res->mode, "ROPE"))
+ vf_rxmode |= ETH_VMDQ_ACCEPT_HASH_UC;
+ else if (!strcmp(res->mode, "BAM"))
+ vf_rxmode |= ETH_VMDQ_ACCEPT_BROADCAST;
+ else if (!strncmp(res->mode, "MPE",3))
+ vf_rxmode |= ETH_VMDQ_ACCEPT_MULTICAST;
+ }
+
+ RTE_SET_USED(is_on);
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_rxmode(res->port_id, res->vf_id,
+ vf_rxmode, (uint8_t)is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_rxmode(res->port_id, res->vf_id,
+ vf_rxmode, (uint8_t)is_on);
+#endif
+ if (ret < 0)
+ printf("bad VF receive mode parameter, return code = %d \n",
+ ret);
+}
+
+cmdline_parse_token_string_t cmd_set_vf_rxmode_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_vf_rxmode_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_rxmode_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_set_vf_rxmode_vfid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vf_rxmode,
+ vf_id, UINT8);
+cmdline_parse_token_string_t cmd_set_vf_rxmode_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ what, "rxmode");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ mode, "AUPE#ROPE#BAM#MPE");
+cmdline_parse_token_string_t cmd_set_vf_rxmode_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vf_rxmode,
+ on, "on#off");
+
+cmdline_parse_inst_t cmd_set_vf_rxmode = {
+ .f = cmd_set_vf_rxmode_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> vf <vf_id> rxmode "
+ "AUPE|ROPE|BAM|MPE on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_rxmode_set,
+ (void *)&cmd_set_vf_rxmode_port,
+ (void *)&cmd_set_vf_rxmode_portid,
+ (void *)&cmd_set_vf_rxmode_vf,
+ (void *)&cmd_set_vf_rxmode_vfid,
+ (void *)&cmd_set_vf_rxmode_what,
+ (void *)&cmd_set_vf_rxmode_mode,
+ (void *)&cmd_set_vf_rxmode_on,
+ NULL,
+ },
+};
+
+/* *** ADD MAC ADDRESS FILTER FOR A VF OF A PORT *** */
+struct cmd_vf_mac_addr_result {
+ cmdline_fixed_string_t mac_addr_cmd;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t port;
+ uint16_t port_num;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_num;
+ struct rte_ether_addr address;
+};
+
+static void cmd_vf_mac_addr_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_mac_addr_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (strcmp(res->what, "add") != 0)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_add_vf_mac_addr(res->port_num, res->vf_num,
+ &res->address);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_mac_addr_add(res->port_num, &res->address,
+ res->vf_num);
+#endif
+
+ if(ret < 0)
+ printf("vf_mac_addr_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_vf_mac_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ mac_addr_cmd,"mac_addr");
+cmdline_parse_token_string_t cmd_vf_mac_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ what,"add");
+cmdline_parse_token_string_t cmd_vf_mac_addr_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ port,"port");
+cmdline_parse_token_num_t cmd_vf_mac_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result,
+ port_num, UINT16);
+cmdline_parse_token_string_t cmd_vf_mac_addr_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_mac_addr_result,
+ vf,"vf");
+cmdline_parse_token_num_t cmd_vf_mac_addr_vfnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_mac_addr_result,
+ vf_num, UINT8);
+cmdline_parse_token_etheraddr_t cmd_vf_mac_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_vf_mac_addr_result,
+ address);
+
+cmdline_parse_inst_t cmd_vf_mac_addr_filter = {
+ .f = cmd_vf_mac_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mac_addr add port <port_id> vf <vf_id> <mac_addr>: "
+ "Add MAC address filtering for a VF on port_id",
+ .tokens = {
+ (void *)&cmd_vf_mac_addr_cmd,
+ (void *)&cmd_vf_mac_addr_what,
+ (void *)&cmd_vf_mac_addr_port,
+ (void *)&cmd_vf_mac_addr_portnum,
+ (void *)&cmd_vf_mac_addr_vf,
+ (void *)&cmd_vf_mac_addr_vfnum,
+ (void *)&cmd_vf_mac_addr_addr,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A VLAN IDENTIFIER TO/FROM A PORT VLAN RX FILTER *** */
+struct cmd_vf_rx_vlan_filter {
+ cmdline_fixed_string_t rx_vlan;
+ cmdline_fixed_string_t what;
+ uint16_t vlan_id;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t vf;
+ uint64_t vf_mask;
+};
+
+static void
+cmd_vf_rx_vlan_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_rx_vlan_filter *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_add = (strcmp(res->what, "add") == 0) ? 1 : 0;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_filter(res->port_id,
+ res->vlan_id, res->vf_mask, is_add);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_filter(res->port_id,
+ res->vlan_id, res->vf_mask, is_add);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_vlan_filter(res->port_id,
+ res->vlan_id, res->vf_mask, is_add);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vlan_id %d or vf_mask %"PRIu64"\n",
+ res->vlan_id, res->vf_mask);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_rx_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ rx_vlan, "rx_vlan");
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vlanid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vlan_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ port, "port");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_rx_vlan_filter_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_vf_rx_vlan_filter_vf_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rx_vlan_filter,
+ vf_mask, UINT64);
+
+cmdline_parse_inst_t cmd_vf_rxvlan_filter = {
+ .f = cmd_vf_rx_vlan_filter_parsed,
+ .data = NULL,
+ .help_str = "rx_vlan add|rm <vlan_id> port <port_id> vf <vf_mask>: "
+ "(vf_mask = hexadecimal VF mask)",
+ .tokens = {
+ (void *)&cmd_vf_rx_vlan_filter_rx_vlan,
+ (void *)&cmd_vf_rx_vlan_filter_what,
+ (void *)&cmd_vf_rx_vlan_filter_vlanid,
+ (void *)&cmd_vf_rx_vlan_filter_port,
+ (void *)&cmd_vf_rx_vlan_filter_portid,
+ (void *)&cmd_vf_rx_vlan_filter_vf,
+ (void *)&cmd_vf_rx_vlan_filter_vf_mask,
+ NULL,
+ },
+};
+
+/* *** SET RATE LIMIT FOR A QUEUE OF A PORT *** */
+struct cmd_queue_rate_limit_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint16_t port_num;
+ cmdline_fixed_string_t queue;
+ uint8_t queue_num;
+ cmdline_fixed_string_t rate;
+ uint16_t rate_num;
+};
+
+static void cmd_queue_rate_limit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_queue_rate_limit_result *res = parsed_result;
+ int ret = 0;
+
+ if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0)
+ && (strcmp(res->queue, "queue") == 0)
+ && (strcmp(res->rate, "rate") == 0))
+ ret = set_queue_rate_limit(res->port_num, res->queue_num,
+ res->rate_num);
+ if (ret < 0)
+ printf("queue_rate_limit_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_queue_rate_limit_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_queue_rate_limit_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_queue_rate_limit_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ port_num, UINT16);
+cmdline_parse_token_string_t cmd_queue_rate_limit_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_queue_rate_limit_queuenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ queue_num, UINT8);
+cmdline_parse_token_string_t cmd_queue_rate_limit_rate =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_rate_limit_result,
+ rate, "rate");
+cmdline_parse_token_num_t cmd_queue_rate_limit_ratenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_rate_limit_result,
+ rate_num, UINT16);
+
+cmdline_parse_inst_t cmd_queue_rate_limit = {
+ .f = cmd_queue_rate_limit_parsed,
+ .data = (void *)0,
+ .help_str = "set port <port_id> queue <queue_id> rate <rate_value>: "
+ "Set rate limit for a queue on port_id",
+ .tokens = {
+ (void *)&cmd_queue_rate_limit_set,
+ (void *)&cmd_queue_rate_limit_port,
+ (void *)&cmd_queue_rate_limit_portnum,
+ (void *)&cmd_queue_rate_limit_queue,
+ (void *)&cmd_queue_rate_limit_queuenum,
+ (void *)&cmd_queue_rate_limit_rate,
+ (void *)&cmd_queue_rate_limit_ratenum,
+ NULL,
+ },
+};
+
+/* *** SET RATE LIMIT FOR A VF OF A PORT *** */
+struct cmd_vf_rate_limit_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ uint16_t port_num;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_num;
+ cmdline_fixed_string_t rate;
+ uint16_t rate_num;
+ cmdline_fixed_string_t q_msk;
+ uint64_t q_msk_val;
+};
+
+static void cmd_vf_rate_limit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_rate_limit_result *res = parsed_result;
+ int ret = 0;
+
+ if ((strcmp(res->set, "set") == 0) && (strcmp(res->port, "port") == 0)
+ && (strcmp(res->vf, "vf") == 0)
+ && (strcmp(res->rate, "rate") == 0)
+ && (strcmp(res->q_msk, "queue_mask") == 0))
+ ret = set_vf_rate_limit(res->port_num, res->vf_num,
+ res->rate_num, res->q_msk_val);
+ if (ret < 0)
+ printf("vf_rate_limit_cmd error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_vf_rate_limit_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_rate_limit_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_vf_rate_limit_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ port_num, UINT16);
+cmdline_parse_token_string_t cmd_vf_rate_limit_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_vf_rate_limit_vfnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ vf_num, UINT8);
+cmdline_parse_token_string_t cmd_vf_rate_limit_rate =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ rate, "rate");
+cmdline_parse_token_num_t cmd_vf_rate_limit_ratenum =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ rate_num, UINT16);
+cmdline_parse_token_string_t cmd_vf_rate_limit_q_msk =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_rate_limit_result,
+ q_msk, "queue_mask");
+cmdline_parse_token_num_t cmd_vf_rate_limit_q_msk_val =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_rate_limit_result,
+ q_msk_val, UINT64);
+
+cmdline_parse_inst_t cmd_vf_rate_limit = {
+ .f = cmd_vf_rate_limit_parsed,
+ .data = (void *)0,
+ .help_str = "set port <port_id> vf <vf_id> rate <rate_value> "
+ "queue_mask <queue_mask_value>: "
+ "Set rate limit for queues of VF on port_id",
+ .tokens = {
+ (void *)&cmd_vf_rate_limit_set,
+ (void *)&cmd_vf_rate_limit_port,
+ (void *)&cmd_vf_rate_limit_portnum,
+ (void *)&cmd_vf_rate_limit_vf,
+ (void *)&cmd_vf_rate_limit_vfnum,
+ (void *)&cmd_vf_rate_limit_rate,
+ (void *)&cmd_vf_rate_limit_ratenum,
+ (void *)&cmd_vf_rate_limit_q_msk,
+ (void *)&cmd_vf_rate_limit_q_msk_val,
+ NULL,
+ },
+};
+
+/* *** ADD TUNNEL FILTER OF A PORT *** */
+struct cmd_tunnel_filter_result {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t what;
+ portid_t port_id;
+ struct rte_ether_addr outer_mac;
+ struct rte_ether_addr inner_mac;
+ cmdline_ipaddr_t ip_value;
+ uint16_t inner_vlan;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t filter_type;
+ uint32_t tenant_id;
+ uint16_t queue_num;
+};
+
+static void
+cmd_tunnel_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tunnel_filter_result *res = parsed_result;
+ struct rte_eth_tunnel_filter_conf tunnel_filter_conf;
+ int ret = 0;
+
+ memset(&tunnel_filter_conf, 0, sizeof(tunnel_filter_conf));
+
+ rte_ether_addr_copy(&res->outer_mac, &tunnel_filter_conf.outer_mac);
+ rte_ether_addr_copy(&res->inner_mac, &tunnel_filter_conf.inner_mac);
+ tunnel_filter_conf.inner_vlan = res->inner_vlan;
+
+ if (res->ip_value.family == AF_INET) {
+ tunnel_filter_conf.ip_addr.ipv4_addr =
+ res->ip_value.addr.ipv4.s_addr;
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV4;
+ } else {
+ memcpy(&(tunnel_filter_conf.ip_addr.ipv6_addr),
+ &(res->ip_value.addr.ipv6),
+ sizeof(struct in6_addr));
+ tunnel_filter_conf.ip_type = RTE_TUNNEL_IPTYPE_IPV6;
+ }
+
+ if (!strcmp(res->filter_type, "imac-ivlan"))
+ tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_IVLAN;
+ else if (!strcmp(res->filter_type, "imac-ivlan-tenid"))
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_IMAC_IVLAN_TENID;
+ else if (!strcmp(res->filter_type, "imac-tenid"))
+ tunnel_filter_conf.filter_type = RTE_TUNNEL_FILTER_IMAC_TENID;
+ else if (!strcmp(res->filter_type, "imac"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IMAC;
+ else if (!strcmp(res->filter_type, "omac-imac-tenid"))
+ tunnel_filter_conf.filter_type =
+ RTE_TUNNEL_FILTER_OMAC_TENID_IMAC;
+ else if (!strcmp(res->filter_type, "oip"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_OIP;
+ else if (!strcmp(res->filter_type, "iip"))
+ tunnel_filter_conf.filter_type = ETH_TUNNEL_FILTER_IIP;
+ else {
+ printf("The filter type is not supported");
+ return;
+ }
+
+ if (!strcmp(res->tunnel_type, "vxlan"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN;
+ else if (!strcmp(res->tunnel_type, "vxlan-gpe"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_VXLAN_GPE;
+ else if (!strcmp(res->tunnel_type, "nvgre"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_NVGRE;
+ else if (!strcmp(res->tunnel_type, "ipingre"))
+ tunnel_filter_conf.tunnel_type = RTE_TUNNEL_TYPE_IP_IN_GRE;
+ else {
+ printf("The tunnel type %s not supported.\n", res->tunnel_type);
+ return;
+ }
+
+ tunnel_filter_conf.tenant_id = res->tenant_id;
+ tunnel_filter_conf.queue_id = res->queue_num;
+ if (!strcmp(res->what, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &tunnel_filter_conf);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &tunnel_filter_conf);
+ if (ret < 0)
+ printf("cmd_tunnel_filter_parsed error: (%s)\n",
+ strerror(-ret));
+
+}
+cmdline_parse_token_string_t cmd_tunnel_filter_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ cmd, "tunnel_filter");
+cmdline_parse_token_string_t cmd_tunnel_filter_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_tunnel_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_tunnel_filter_outer_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ outer_mac);
+cmdline_parse_token_etheraddr_t cmd_tunnel_filter_inner_mac =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ inner_mac);
+cmdline_parse_token_num_t cmd_tunnel_filter_innner_vlan =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ inner_vlan, UINT16);
+cmdline_parse_token_ipaddr_t cmd_tunnel_filter_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_tunnel_filter_result,
+ ip_value);
+cmdline_parse_token_string_t cmd_tunnel_filter_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ tunnel_type, "vxlan#nvgre#ipingre#vxlan-gpe");
+
+cmdline_parse_token_string_t cmd_tunnel_filter_filter_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_filter_result,
+ filter_type, "oip#iip#imac-ivlan#imac-ivlan-tenid#imac-tenid#"
+ "imac#omac-imac-tenid");
+cmdline_parse_token_num_t cmd_tunnel_filter_tenant_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ tenant_id, UINT32);
+cmdline_parse_token_num_t cmd_tunnel_filter_queue_num =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_filter_result,
+ queue_num, UINT16);
+
+cmdline_parse_inst_t cmd_tunnel_filter = {
+ .f = cmd_tunnel_filter_parsed,
+ .data = (void *)0,
+ .help_str = "tunnel_filter add|rm <port_id> <outer_mac> <inner_mac> "
+ "<ip> <inner_vlan> vxlan|nvgre|ipingre oip|iip|imac-ivlan|"
+ "imac-ivlan-tenid|imac-tenid|imac|omac-imac-tenid <tenant_id> "
+ "<queue_id>: Add/Rm tunnel filter of a port",
+ .tokens = {
+ (void *)&cmd_tunnel_filter_cmd,
+ (void *)&cmd_tunnel_filter_what,
+ (void *)&cmd_tunnel_filter_port_id,
+ (void *)&cmd_tunnel_filter_outer_mac,
+ (void *)&cmd_tunnel_filter_inner_mac,
+ (void *)&cmd_tunnel_filter_ip_value,
+ (void *)&cmd_tunnel_filter_innner_vlan,
+ (void *)&cmd_tunnel_filter_tunnel_type,
+ (void *)&cmd_tunnel_filter_filter_type,
+ (void *)&cmd_tunnel_filter_tenant_id,
+ (void *)&cmd_tunnel_filter_queue_num,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE TUNNEL UDP PORT *** */
+struct cmd_tunnel_udp_config {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t what;
+ uint16_t udp_port;
+ portid_t port_id;
+};
+
+static void
+cmd_tunnel_udp_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tunnel_udp_config *res = parsed_result;
+ struct rte_eth_udp_tunnel tunnel_udp;
+ int ret;
+
+ tunnel_udp.udp_port = res->udp_port;
+
+ if (!strcmp(res->cmd, "rx_vxlan_port"))
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
+
+ if (!strcmp(res->what, "add"))
+ ret = rte_eth_dev_udp_tunnel_port_add(res->port_id,
+ &tunnel_udp);
+ else
+ ret = rte_eth_dev_udp_tunnel_port_delete(res->port_id,
+ &tunnel_udp);
+
+ if (ret < 0)
+ printf("udp tunneling add error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_tunnel_udp_config_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config,
+ cmd, "rx_vxlan_port");
+cmdline_parse_token_string_t cmd_tunnel_udp_config_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_tunnel_udp_config,
+ what, "add#rm");
+cmdline_parse_token_num_t cmd_tunnel_udp_config_udp_port =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config,
+ udp_port, UINT16);
+cmdline_parse_token_num_t cmd_tunnel_udp_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_tunnel_udp_config,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_tunnel_udp_config = {
+ .f = cmd_tunnel_udp_config_parsed,
+ .data = (void *)0,
+ .help_str = "rx_vxlan_port add|rm <udp_port> <port_id>: "
+ "Add/Remove a tunneling UDP port filter",
+ .tokens = {
+ (void *)&cmd_tunnel_udp_config_cmd,
+ (void *)&cmd_tunnel_udp_config_what,
+ (void *)&cmd_tunnel_udp_config_udp_port,
+ (void *)&cmd_tunnel_udp_config_port_id,
+ NULL,
+ },
+};
+
+struct cmd_config_tunnel_udp_port {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t udp_tunnel_port;
+ cmdline_fixed_string_t action;
+ cmdline_fixed_string_t tunnel_type;
+ uint16_t udp_port;
+};
+
+static void
+cmd_cfg_tunnel_udp_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_tunnel_udp_port *res = parsed_result;
+ struct rte_eth_udp_tunnel tunnel_udp;
+ int ret = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ tunnel_udp.udp_port = res->udp_port;
+
+ if (!strcmp(res->tunnel_type, "vxlan")) {
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN;
+ } else if (!strcmp(res->tunnel_type, "geneve")) {
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_GENEVE;
+ } else if (!strcmp(res->tunnel_type, "vxlan-gpe")) {
+ tunnel_udp.prot_type = RTE_TUNNEL_TYPE_VXLAN_GPE;
+ } else {
+ printf("Invalid tunnel type\n");
+ return;
+ }
+
+ if (!strcmp(res->action, "add"))
+ ret = rte_eth_dev_udp_tunnel_port_add(res->port_id,
+ &tunnel_udp);
+ else
+ ret = rte_eth_dev_udp_tunnel_port_delete(res->port_id,
+ &tunnel_udp);
+
+ if (ret < 0)
+ printf("udp tunneling port add error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_config_tunnel_udp_port_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tunnel_udp_port, port,
+ "port");
+cmdline_parse_token_string_t cmd_config_tunnel_udp_port_config =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tunnel_udp_port, config,
+ "config");
+cmdline_parse_token_num_t cmd_config_tunnel_udp_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_tunnel_udp_port, port_id,
+ UINT16);
+cmdline_parse_token_string_t cmd_config_tunnel_udp_port_tunnel_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tunnel_udp_port,
+ udp_tunnel_port,
+ "udp_tunnel_port");
+cmdline_parse_token_string_t cmd_config_tunnel_udp_port_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tunnel_udp_port, action,
+ "add#rm");
+cmdline_parse_token_string_t cmd_config_tunnel_udp_port_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tunnel_udp_port, tunnel_type,
+ "vxlan#geneve#vxlan-gpe");
+cmdline_parse_token_num_t cmd_config_tunnel_udp_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_tunnel_udp_port, udp_port,
+ UINT16);
+
+cmdline_parse_inst_t cmd_cfg_tunnel_udp_port = {
+ .f = cmd_cfg_tunnel_udp_port_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> udp_tunnel_port add|rm vxlan|geneve|vxlan-gpe <udp_port>",
+ .tokens = {
+ (void *)&cmd_config_tunnel_udp_port_port,
+ (void *)&cmd_config_tunnel_udp_port_config,
+ (void *)&cmd_config_tunnel_udp_port_port_id,
+ (void *)&cmd_config_tunnel_udp_port_tunnel_port,
+ (void *)&cmd_config_tunnel_udp_port_action,
+ (void *)&cmd_config_tunnel_udp_port_tunnel_type,
+ (void *)&cmd_config_tunnel_udp_port_value,
+ NULL,
+ },
+};
+
+/* *** GLOBAL CONFIG *** */
+struct cmd_global_config_result {
+ cmdline_fixed_string_t cmd;
+ portid_t port_id;
+ cmdline_fixed_string_t cfg_type;
+ uint8_t len;
+};
+
+static void
+cmd_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_global_config_result *res = parsed_result;
+ struct rte_eth_global_cfg conf;
+ int ret;
+
+ memset(&conf, 0, sizeof(conf));
+ conf.cfg_type = RTE_ETH_GLOBAL_CFG_TYPE_GRE_KEY_LEN;
+ conf.cfg.gre_key_len = res->len;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_NONE,
+ RTE_ETH_FILTER_SET, &conf);
+ if (ret != 0)
+ printf("Global config error\n");
+}
+
+cmdline_parse_token_string_t cmd_global_config_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_global_config_result, cmd,
+ "global_config");
+cmdline_parse_token_num_t cmd_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_global_config_result, port_id,
+ UINT16);
+cmdline_parse_token_string_t cmd_global_config_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_global_config_result,
+ cfg_type, "gre-key-len");
+cmdline_parse_token_num_t cmd_global_config_gre_key_len =
+ TOKEN_NUM_INITIALIZER(struct cmd_global_config_result,
+ len, UINT8);
+
+cmdline_parse_inst_t cmd_global_config = {
+ .f = cmd_global_config_parsed,
+ .data = (void *)NULL,
+ .help_str = "global_config <port_id> gre-key-len <key_len>",
+ .tokens = {
+ (void *)&cmd_global_config_cmd,
+ (void *)&cmd_global_config_port_id,
+ (void *)&cmd_global_config_type,
+ (void *)&cmd_global_config_gre_key_len,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VM MIRROR VLAN/POOL RULE *** */
+struct cmd_set_mirror_mask_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t value;
+ cmdline_fixed_string_t dstpool;
+ uint8_t dstpool_id;
+ cmdline_fixed_string_t on;
+};
+
+cmdline_parse_token_string_t cmd_mirror_mask_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_mirror_mask_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_mirror_mask_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_mirror_mask_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_mirror_mask_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ rule_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_mask_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ what, "pool-mirror-up#pool-mirror-down"
+ "#vlan-mirror");
+cmdline_parse_token_string_t cmd_mirror_mask_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ value, NULL);
+cmdline_parse_token_string_t cmd_mirror_mask_dstpool =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ dstpool, "dst-pool");
+cmdline_parse_token_num_t cmd_mirror_mask_poolid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_mask_result,
+ dstpool_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_mask_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_mask_result,
+ on, "on#off");
+
+static void
+cmd_set_mirror_mask_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret,nb_item,i;
+ struct cmd_set_mirror_mask_result *res = parsed_result;
+ struct rte_eth_mirror_conf mr_conf;
+
+ memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
+
+ unsigned int vlan_list[ETH_MIRROR_MAX_VLANS];
+
+ mr_conf.dst_pool = res->dstpool_id;
+
+ if (!strcmp(res->what, "pool-mirror-up")) {
+ mr_conf.pool_mask = strtoull(res->value, NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_UP;
+ } else if (!strcmp(res->what, "pool-mirror-down")) {
+ mr_conf.pool_mask = strtoull(res->value, NULL, 16);
+ mr_conf.rule_type = ETH_MIRROR_VIRTUAL_POOL_DOWN;
+ } else if (!strcmp(res->what, "vlan-mirror")) {
+ mr_conf.rule_type = ETH_MIRROR_VLAN;
+ nb_item = parse_item_list(res->value, "vlan",
+ ETH_MIRROR_MAX_VLANS, vlan_list, 1);
+ if (nb_item <= 0)
+ return;
+
+ for (i = 0; i < nb_item; i++) {
+ if (vlan_list[i] > RTE_ETHER_MAX_VLAN_ID) {
+ printf("Invalid vlan_id: must be < 4096\n");
+ return;
+ }
+
+ mr_conf.vlan.vlan_id[i] = (uint16_t)vlan_list[i];
+ mr_conf.vlan.vlan_mask |= 1ULL << i;
+ }
+ }
+
+ if (!strcmp(res->on, "on"))
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 1);
+ else
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 0);
+ if (ret < 0)
+ printf("mirror rule add error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_set_mirror_mask = {
+ .f = cmd_set_mirror_mask_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> mirror-rule <rule_id> "
+ "pool-mirror-up|pool-mirror-down|vlan-mirror "
+ "<pool_mask|vlan_id[,vlan_id]*> dst-pool <pool_id> on|off",
+ .tokens = {
+ (void *)&cmd_mirror_mask_set,
+ (void *)&cmd_mirror_mask_port,
+ (void *)&cmd_mirror_mask_portid,
+ (void *)&cmd_mirror_mask_mirror,
+ (void *)&cmd_mirror_mask_ruleid,
+ (void *)&cmd_mirror_mask_what,
+ (void *)&cmd_mirror_mask_value,
+ (void *)&cmd_mirror_mask_dstpool,
+ (void *)&cmd_mirror_mask_poolid,
+ (void *)&cmd_mirror_mask_on,
+ NULL,
+ },
+};
+
+/* *** CONFIGURE VM MIRROR UPLINK/DOWNLINK RULE *** */
+struct cmd_set_mirror_link_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+ cmdline_fixed_string_t what;
+ cmdline_fixed_string_t dstpool;
+ uint8_t dstpool_id;
+ cmdline_fixed_string_t on;
+};
+
+cmdline_parse_token_string_t cmd_mirror_link_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_mirror_link_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_mirror_link_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_mirror_link_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_mirror_link_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ rule_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_link_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ what, "uplink-mirror#downlink-mirror");
+cmdline_parse_token_string_t cmd_mirror_link_dstpool =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ dstpool, "dst-pool");
+cmdline_parse_token_num_t cmd_mirror_link_poolid =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mirror_link_result,
+ dstpool_id, UINT8);
+cmdline_parse_token_string_t cmd_mirror_link_on =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mirror_link_result,
+ on, "on#off");
+
+static void
+cmd_set_mirror_link_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret;
+ struct cmd_set_mirror_link_result *res = parsed_result;
+ struct rte_eth_mirror_conf mr_conf;
+
+ memset(&mr_conf, 0, sizeof(struct rte_eth_mirror_conf));
+ if (!strcmp(res->what, "uplink-mirror"))
+ mr_conf.rule_type = ETH_MIRROR_UPLINK_PORT;
+ else
+ mr_conf.rule_type = ETH_MIRROR_DOWNLINK_PORT;
+
+ mr_conf.dst_pool = res->dstpool_id;
+
+ if (!strcmp(res->on, "on"))
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 1);
+ else
+ ret = rte_eth_mirror_rule_set(res->port_id, &mr_conf,
+ res->rule_id, 0);
+
+ /* check the return value and print it if is < 0 */
+ if (ret < 0)
+ printf("mirror rule add error: (%s)\n", strerror(-ret));
+
+}
+
+cmdline_parse_inst_t cmd_set_mirror_link = {
+ .f = cmd_set_mirror_link_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> mirror-rule <rule_id> "
+ "uplink-mirror|downlink-mirror dst-pool <pool_id> on|off",
+ .tokens = {
+ (void *)&cmd_mirror_link_set,
+ (void *)&cmd_mirror_link_port,
+ (void *)&cmd_mirror_link_portid,
+ (void *)&cmd_mirror_link_mirror,
+ (void *)&cmd_mirror_link_ruleid,
+ (void *)&cmd_mirror_link_what,
+ (void *)&cmd_mirror_link_dstpool,
+ (void *)&cmd_mirror_link_poolid,
+ (void *)&cmd_mirror_link_on,
+ NULL,
+ },
+};
+
+/* *** RESET VM MIRROR RULE *** */
+struct cmd_rm_mirror_rule_result {
+ cmdline_fixed_string_t reset;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t mirror;
+ uint8_t rule_id;
+};
+
+cmdline_parse_token_string_t cmd_rm_mirror_rule_reset =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ reset, "reset");
+cmdline_parse_token_string_t cmd_rm_mirror_rule_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_rm_mirror_rule_portid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_rm_mirror_rule_mirror =
+ TOKEN_STRING_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ mirror, "mirror-rule");
+cmdline_parse_token_num_t cmd_rm_mirror_rule_ruleid =
+ TOKEN_NUM_INITIALIZER(struct cmd_rm_mirror_rule_result,
+ rule_id, UINT8);
+
+static void
+cmd_reset_mirror_rule_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret;
+ struct cmd_set_mirror_link_result *res = parsed_result;
+ /* check rule_id */
+ ret = rte_eth_mirror_rule_reset(res->port_id,res->rule_id);
+ if(ret < 0)
+ printf("mirror rule remove error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_reset_mirror_rule = {
+ .f = cmd_reset_mirror_rule_parsed,
+ .data = NULL,
+ .help_str = "reset port <port_id> mirror-rule <rule_id>",
+ .tokens = {
+ (void *)&cmd_rm_mirror_rule_reset,
+ (void *)&cmd_rm_mirror_rule_port,
+ (void *)&cmd_rm_mirror_rule_portid,
+ (void *)&cmd_rm_mirror_rule_mirror,
+ (void *)&cmd_rm_mirror_rule_ruleid,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+struct cmd_dump_result {
+ cmdline_fixed_string_t dump;
+};
+
+static void
+dump_struct_sizes(void)
+{
+#define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
+ DUMP_SIZE(struct rte_mbuf);
+ DUMP_SIZE(struct rte_mempool);
+ DUMP_SIZE(struct rte_ring);
+#undef DUMP_SIZE
+}
+
+
+/* Dump the socket memory statistics on console */
+static void
+dump_socket_mem(FILE *f)
+{
+ struct rte_malloc_socket_stats socket_stats;
+ unsigned int i;
+ size_t total = 0;
+ size_t alloc = 0;
+ size_t free = 0;
+ unsigned int n_alloc = 0;
+ unsigned int n_free = 0;
+ static size_t last_allocs;
+ static size_t last_total;
+
+
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ if (rte_malloc_get_socket_stats(i, &socket_stats) ||
+ !socket_stats.heap_totalsz_bytes)
+ continue;
+ total += socket_stats.heap_totalsz_bytes;
+ alloc += socket_stats.heap_allocsz_bytes;
+ free += socket_stats.heap_freesz_bytes;
+ n_alloc += socket_stats.alloc_count;
+ n_free += socket_stats.free_count;
+ fprintf(f,
+ "Socket %u: size(M) total: %.6lf alloc: %.6lf(%.3lf%%) free: %.6lf \tcount alloc: %-4u free: %u\n",
+ i,
+ (double)socket_stats.heap_totalsz_bytes / (1024 * 1024),
+ (double)socket_stats.heap_allocsz_bytes / (1024 * 1024),
+ (double)socket_stats.heap_allocsz_bytes * 100 /
+ (double)socket_stats.heap_totalsz_bytes,
+ (double)socket_stats.heap_freesz_bytes / (1024 * 1024),
+ socket_stats.alloc_count,
+ socket_stats.free_count);
+ }
+ fprintf(f,
+ "Total : size(M) total: %.6lf alloc: %.6lf(%.3lf%%) free: %.6lf \tcount alloc: %-4u free: %u\n",
+ (double)total / (1024 * 1024), (double)alloc / (1024 * 1024),
+ (double)alloc * 100 / (double)total,
+ (double)free / (1024 * 1024),
+ n_alloc, n_free);
+ if (last_allocs)
+ fprintf(stdout, "Memory total change: %.6lf(M), allocation change: %.6lf(M)\n",
+ ((double)total - (double)last_total) / (1024 * 1024),
+ (double)(alloc - (double)last_allocs) / 1024 / 1024);
+ last_allocs = alloc;
+ last_total = total;
+}
+
+static void cmd_dump_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_dump_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_physmem"))
+ rte_dump_physmem_layout(stdout);
+ else if (!strcmp(res->dump, "dump_socket_mem"))
+ dump_socket_mem(stdout);
+ else if (!strcmp(res->dump, "dump_memzone"))
+ rte_memzone_dump(stdout);
+ else if (!strcmp(res->dump, "dump_struct_sizes"))
+ dump_struct_sizes();
+ else if (!strcmp(res->dump, "dump_ring"))
+ rte_ring_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_mempool"))
+ rte_mempool_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_devargs"))
+ rte_devargs_dump(stdout);
+ else if (!strcmp(res->dump, "dump_log_types"))
+ rte_log_dump(stdout);
+}
+
+cmdline_parse_token_string_t cmd_dump_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
+ "dump_physmem#"
+ "dump_memzone#"
+ "dump_socket_mem#"
+ "dump_struct_sizes#"
+ "dump_ring#"
+ "dump_mempool#"
+ "dump_devargs#"
+ "dump_log_types");
+
+cmdline_parse_inst_t cmd_dump = {
+ .f = cmd_dump_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Dump status",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_dump,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+struct cmd_dump_one_result {
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t name;
+};
+
+static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_dump_one_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_ring")) {
+ struct rte_ring *r;
+ r = rte_ring_lookup(res->name);
+ if (r == NULL) {
+ cmdline_printf(cl, "Cannot find ring\n");
+ return;
+ }
+ rte_ring_dump(stdout, r);
+ } else if (!strcmp(res->dump, "dump_mempool")) {
+ struct rte_mempool *mp;
+ mp = rte_mempool_lookup(res->name);
+ if (mp == NULL) {
+ cmdline_printf(cl, "Cannot find mempool\n");
+ return;
+ }
+ rte_mempool_dump(stdout, mp);
+ }
+}
+
+cmdline_parse_token_string_t cmd_dump_one_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump,
+ "dump_ring#dump_mempool");
+
+cmdline_parse_token_string_t cmd_dump_one_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL);
+
+cmdline_parse_inst_t cmd_dump_one = {
+ .f = cmd_dump_one_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "dump_ring|dump_mempool <name>: Dump one ring/mempool",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_one_dump,
+ (void *)&cmd_dump_one_name,
+ NULL,
+ },
+};
+
+/* *** Add/Del syn filter *** */
+struct cmd_syn_filter_result {
+ cmdline_fixed_string_t filter;
+ portid_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t priority;
+ cmdline_fixed_string_t high;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_syn_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_syn_filter_result *res = parsed_result;
+ struct rte_eth_syn_filter syn_filter;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_SYN);
+ if (ret < 0) {
+ printf("syn filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&syn_filter, 0, sizeof(syn_filter));
+
+ if (!strcmp(res->ops, "add")) {
+ if (!strcmp(res->high, "high"))
+ syn_filter.hig_pri = 1;
+ else
+ syn_filter.hig_pri = 0;
+
+ syn_filter.queue = res->queue_id;
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_ADD,
+ &syn_filter);
+ } else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_SYN,
+ RTE_ETH_FILTER_DELETE,
+ &syn_filter);
+
+ if (ret < 0)
+ printf("syn filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_syn_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ filter, "syn_filter");
+cmdline_parse_token_num_t cmd_syn_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_syn_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_syn_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ priority, "priority");
+cmdline_parse_token_string_t cmd_syn_filter_high =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ high, "high#low");
+cmdline_parse_token_string_t cmd_syn_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_syn_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_syn_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_syn_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_syn_filter = {
+ .f = cmd_syn_filter_parsed,
+ .data = NULL,
+ .help_str = "syn_filter <port_id> add|del priority high|low queue "
+ "<queue_id>: Add/Delete syn filter",
+ .tokens = {
+ (void *)&cmd_syn_filter_filter,
+ (void *)&cmd_syn_filter_port_id,
+ (void *)&cmd_syn_filter_ops,
+ (void *)&cmd_syn_filter_priority,
+ (void *)&cmd_syn_filter_high,
+ (void *)&cmd_syn_filter_queue,
+ (void *)&cmd_syn_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t region;
+ uint8_t region_id;
+ cmdline_fixed_string_t queue_start_index;
+ uint8_t queue_id;
+ cmdline_fixed_string_t queue_num;
+ uint8_t queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_queue_region_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_queue_region_conf region_conf;
+ enum rte_pmd_i40e_queue_region_op op_type;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ memset(&region_conf, 0, sizeof(region_conf));
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_SET;
+ region_conf.region_id = res->region_id;
+ region_conf.queue_num = res->queue_num_value;
+ region_conf.queue_start_index = res->queue_id;
+
+ ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+ op_type, &region_conf);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("queue region config error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+ cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+ region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+ region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+ queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+ queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+ TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+ queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+ queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+ .f = cmd_queue_region_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> queue-region region_id <value> "
+ "queue_start_index <value> queue_num <value>: Set a queue region",
+ .tokens = {
+ (void *)&cmd_queue_region_set,
+ (void *)&cmd_queue_region_port,
+ (void *)&cmd_queue_region_port_id,
+ (void *)&cmd_queue_region_cmd,
+ (void *)&cmd_queue_region_id,
+ (void *)&cmd_queue_region_index,
+ (void *)&cmd_queue_region_queue_start_index,
+ (void *)&cmd_queue_region_queue_id,
+ (void *)&cmd_queue_region_queue_num,
+ (void *)&cmd_queue_region_queue_num_value,
+ NULL,
+ },
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t region;
+ uint8_t region_id;
+ cmdline_fixed_string_t flowtype;
+ uint8_t flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_region_flowtype_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_queue_region_conf region_conf;
+ enum rte_pmd_i40e_queue_region_op op_type;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ memset(&region_conf, 0, sizeof(region_conf));
+
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_FLOWTYPE_SET;
+ region_conf.region_id = res->region_id;
+ region_conf.hw_flowtype = res->flowtype_id;
+
+ ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+ op_type, &region_conf);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("region flowtype config error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+ cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+ TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+ region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+ region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+ TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+ flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+ flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+ .f = cmd_region_flowtype_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> queue-region region_id <value> "
+ "flowtype <value>: Set a flowtype region index",
+ .tokens = {
+ (void *)&cmd_region_flowtype_set,
+ (void *)&cmd_region_flowtype_port,
+ (void *)&cmd_region_flowtype_port_index,
+ (void *)&cmd_region_flowtype_cmd,
+ (void *)&cmd_region_flowtype_index,
+ (void *)&cmd_region_flowtype_id,
+ (void *)&cmd_region_flowtype_flow_index,
+ (void *)&cmd_region_flowtype_flow_id,
+ NULL,
+ },
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t user_priority;
+ uint8_t user_priority_id;
+ cmdline_fixed_string_t region;
+ uint8_t region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_user_priority_region_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_queue_region_conf region_conf;
+ enum rte_pmd_i40e_queue_region_op op_type;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ memset(&region_conf, 0, sizeof(region_conf));
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_USER_PRIORITY_SET;
+ region_conf.user_priority = res->user_priority_id;
+ region_conf.region_id = res->region_id;
+
+ ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+ op_type, &region_conf);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("user_priority region config error: (%s)\n",
+ strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+ cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+ TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+ user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+ user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+ TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+ region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+ region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+ .f = cmd_user_priority_region_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> queue-region UP <value> "
+ "region_id <value>: Set the mapping of User Priority (UP) "
+ "to queue region (region_id) ",
+ .tokens = {
+ (void *)&cmd_user_priority_region_set,
+ (void *)&cmd_user_priority_region_port,
+ (void *)&cmd_user_priority_region_port_index,
+ (void *)&cmd_user_priority_region_cmd,
+ (void *)&cmd_user_priority_region_UP,
+ (void *)&cmd_user_priority_region_UP_id,
+ (void *)&cmd_user_priority_region_region,
+ (void *)&cmd_user_priority_region_region_id,
+ NULL,
+ },
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t flush;
+ cmdline_fixed_string_t what;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flush_queue_region_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_queue_region_conf region_conf;
+ enum rte_pmd_i40e_queue_region_op op_type;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ memset(&region_conf, 0, sizeof(region_conf));
+
+ if (strcmp(res->what, "on") == 0)
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+ else
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+ ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+ op_type, &region_conf);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("queue region config flush error: (%s)\n",
+ strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+ cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+ flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+ what, "on#off");
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+ .f = cmd_flush_queue_region_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> queue-region flush on|off"
+ ": flush all queue region related configuration",
+ .tokens = {
+ (void *)&cmd_flush_queue_region_set,
+ (void *)&cmd_flush_queue_region_port,
+ (void *)&cmd_flush_queue_region_port_index,
+ (void *)&cmd_flush_queue_region_cmd,
+ (void *)&cmd_flush_queue_region_flush,
+ (void *)&cmd_flush_queue_region_what,
+ NULL,
+ },
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_show_queue_region_info {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t cmd;
+};
+
+static void
+cmd_show_queue_region_info_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_queue_region_info *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_queue_regions rte_pmd_regions;
+ enum rte_pmd_i40e_queue_region_op op_type;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ memset(&rte_pmd_regions, 0, sizeof(rte_pmd_regions));
+
+ op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+ ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+ op_type, &rte_pmd_regions);
+
+ port_queue_region_info_display(res->port_id, &rte_pmd_regions);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOTSUP:
+ printf("function not implemented or supported\n");
+ break;
+ default:
+ printf("queue region config info show error: (%s)\n",
+ strerror(-ret));
+ }
+}
+
+cmdline_parse_token_string_t cmd_show_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_queue_region_info_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+ port, "port");
+cmdline_parse_token_num_t cmd_show_queue_region_info_port_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_queue_region_info,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_show_queue_region_info_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+ cmd, "queue-region");
+
+cmdline_parse_inst_t cmd_show_queue_region_info_all = {
+ .f = cmd_show_queue_region_info_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> queue-region"
+ ": show all queue region related configuration info",
+ .tokens = {
+ (void *)&cmd_show_queue_region_info_get,
+ (void *)&cmd_show_queue_region_info_port,
+ (void *)&cmd_show_queue_region_info_port_index,
+ (void *)&cmd_show_queue_region_info_cmd,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A 2tuple FILTER *** */
+struct cmd_2tuple_filter_result {
+ cmdline_fixed_string_t filter;
+ portid_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t dst_port;
+ uint16_t dst_port_value;
+ cmdline_fixed_string_t protocol;
+ uint8_t protocol_value;
+ cmdline_fixed_string_t mask;
+ uint8_t mask_value;
+ cmdline_fixed_string_t tcp_flags;
+ uint8_t tcp_flags_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_2tuple_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct rte_eth_ntuple_filter filter;
+ struct cmd_2tuple_filter_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_2TUPLE_FLAGS;
+ filter.dst_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0;
+ filter.proto = res->protocol_value;
+ filter.priority = res->priority_value;
+ if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return;
+ }
+ if (res->tcp_flags_value > RTE_NTUPLE_TCP_FLAGS_MASK) {
+ printf("invalid TCP flags.\n");
+ return;
+ }
+
+ if (res->tcp_flags_value != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = res->tcp_flags_value;
+ }
+
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("2tuple filter programming error: (%s)\n",
+ strerror(-ret));
+
+}
+
+cmdline_parse_token_string_t cmd_2tuple_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ filter, "2tuple_filter");
+cmdline_parse_token_num_t cmd_2tuple_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_2tuple_filter_dst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_2tuple_filter_dst_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_2tuple_filter_protocol =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ protocol, "protocol");
+cmdline_parse_token_num_t cmd_2tuple_filter_protocol_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ mask, "mask");
+cmdline_parse_token_num_t cmd_2tuple_filter_mask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ mask_value, INT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_tcp_flags =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ tcp_flags, "tcp_flags");
+cmdline_parse_token_num_t cmd_2tuple_filter_tcp_flags_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ tcp_flags_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_2tuple_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_2tuple_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_2tuple_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_2tuple_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_2tuple_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_2tuple_filter = {
+ .f = cmd_2tuple_filter_parsed,
+ .data = NULL,
+ .help_str = "2tuple_filter <port_id> add|del dst_port <value> protocol "
+ "<value> mask <value> tcp_flags <value> priority <value> queue "
+ "<queue_id>: Add a 2tuple filter",
+ .tokens = {
+ (void *)&cmd_2tuple_filter_filter,
+ (void *)&cmd_2tuple_filter_port_id,
+ (void *)&cmd_2tuple_filter_ops,
+ (void *)&cmd_2tuple_filter_dst_port,
+ (void *)&cmd_2tuple_filter_dst_port_value,
+ (void *)&cmd_2tuple_filter_protocol,
+ (void *)&cmd_2tuple_filter_protocol_value,
+ (void *)&cmd_2tuple_filter_mask,
+ (void *)&cmd_2tuple_filter_mask_value,
+ (void *)&cmd_2tuple_filter_tcp_flags,
+ (void *)&cmd_2tuple_filter_tcp_flags_value,
+ (void *)&cmd_2tuple_filter_priority,
+ (void *)&cmd_2tuple_filter_priority_value,
+ (void *)&cmd_2tuple_filter_queue,
+ (void *)&cmd_2tuple_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A 5tuple FILTER *** */
+struct cmd_5tuple_filter_result {
+ cmdline_fixed_string_t filter;
+ portid_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t dst_ip;
+ cmdline_ipaddr_t dst_ip_value;
+ cmdline_fixed_string_t src_ip;
+ cmdline_ipaddr_t src_ip_value;
+ cmdline_fixed_string_t dst_port;
+ uint16_t dst_port_value;
+ cmdline_fixed_string_t src_port;
+ uint16_t src_port_value;
+ cmdline_fixed_string_t protocol;
+ uint8_t protocol_value;
+ cmdline_fixed_string_t mask;
+ uint8_t mask_value;
+ cmdline_fixed_string_t tcp_flags;
+ uint8_t tcp_flags_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static void
+cmd_5tuple_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct rte_eth_ntuple_filter filter;
+ struct cmd_5tuple_filter_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_NTUPLE);
+ if (ret < 0) {
+ printf("ntuple filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(struct rte_eth_ntuple_filter));
+
+ filter.flags = RTE_5TUPLE_FLAGS;
+ filter.dst_ip_mask = (res->mask_value & 0x10) ? UINT32_MAX : 0;
+ filter.src_ip_mask = (res->mask_value & 0x08) ? UINT32_MAX : 0;
+ filter.dst_port_mask = (res->mask_value & 0x04) ? UINT16_MAX : 0;
+ filter.src_port_mask = (res->mask_value & 0x02) ? UINT16_MAX : 0;
+ filter.proto_mask = (res->mask_value & 0x01) ? UINT8_MAX : 0;
+ filter.proto = res->protocol_value;
+ filter.priority = res->priority_value;
+ if (res->tcp_flags_value != 0 && filter.proto != IPPROTO_TCP) {
+ printf("nonzero tcp_flags is only meaningful"
+ " when protocol is TCP.\n");
+ return;
+ }
+ if (res->tcp_flags_value > RTE_NTUPLE_TCP_FLAGS_MASK) {
+ printf("invalid TCP flags.\n");
+ return;
+ }
+
+ if (res->tcp_flags_value != 0) {
+ filter.flags |= RTE_NTUPLE_FLAGS_TCP_FLAG;
+ filter.tcp_flags = res->tcp_flags_value;
+ }
+
+ if (res->dst_ip_value.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.dst_ip = res->dst_ip_value.addr.ipv4.s_addr;
+ else {
+ if (filter.dst_ip_mask == 0) {
+ printf("can not support ipv6 involved compare.\n");
+ return;
+ }
+ filter.dst_ip = 0;
+ }
+
+ if (res->src_ip_value.family == AF_INET)
+ /* no need to convert, already big endian. */
+ filter.src_ip = res->src_ip_value.addr.ipv4.s_addr;
+ else {
+ if (filter.src_ip_mask == 0) {
+ printf("can not support ipv6 involved compare.\n");
+ return;
+ }
+ filter.src_ip = 0;
+ }
+ /* need convert to big endian. */
+ filter.dst_port = rte_cpu_to_be_16(res->dst_port_value);
+ filter.src_port = rte_cpu_to_be_16(res->src_port_value);
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_NTUPLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("5tuple filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_5tuple_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ filter, "5tuple_filter");
+cmdline_parse_token_num_t cmd_5tuple_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_ip, "dst_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_dst_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_ip, "src_ip");
+cmdline_parse_token_ipaddr_t cmd_5tuple_filter_src_ip_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_ip_value);
+cmdline_parse_token_string_t cmd_5tuple_filter_dst_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_port, "dst_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_dst_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ dst_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_src_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_port, "src_port");
+cmdline_parse_token_num_t cmd_5tuple_filter_src_port_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ src_port_value, UINT16);
+cmdline_parse_token_string_t cmd_5tuple_filter_protocol =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ protocol, "protocol");
+cmdline_parse_token_num_t cmd_5tuple_filter_protocol_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ protocol_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ mask, "mask");
+cmdline_parse_token_num_t cmd_5tuple_filter_mask_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ mask_value, INT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_tcp_flags =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ tcp_flags, "tcp_flags");
+cmdline_parse_token_num_t cmd_5tuple_filter_tcp_flags_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ tcp_flags_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_5tuple_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_5tuple_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_5tuple_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_5tuple_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_5tuple_filter_result,
+ queue_id, UINT16);
+
+cmdline_parse_inst_t cmd_5tuple_filter = {
+ .f = cmd_5tuple_filter_parsed,
+ .data = NULL,
+ .help_str = "5tuple_filter <port_id> add|del dst_ip <value> "
+ "src_ip <value> dst_port <value> src_port <value> "
+ "protocol <value> mask <value> tcp_flags <value> "
+ "priority <value> queue <queue_id>: Add/Del a 5tuple filter",
+ .tokens = {
+ (void *)&cmd_5tuple_filter_filter,
+ (void *)&cmd_5tuple_filter_port_id,
+ (void *)&cmd_5tuple_filter_ops,
+ (void *)&cmd_5tuple_filter_dst_ip,
+ (void *)&cmd_5tuple_filter_dst_ip_value,
+ (void *)&cmd_5tuple_filter_src_ip,
+ (void *)&cmd_5tuple_filter_src_ip_value,
+ (void *)&cmd_5tuple_filter_dst_port,
+ (void *)&cmd_5tuple_filter_dst_port_value,
+ (void *)&cmd_5tuple_filter_src_port,
+ (void *)&cmd_5tuple_filter_src_port_value,
+ (void *)&cmd_5tuple_filter_protocol,
+ (void *)&cmd_5tuple_filter_protocol_value,
+ (void *)&cmd_5tuple_filter_mask,
+ (void *)&cmd_5tuple_filter_mask_value,
+ (void *)&cmd_5tuple_filter_tcp_flags,
+ (void *)&cmd_5tuple_filter_tcp_flags_value,
+ (void *)&cmd_5tuple_filter_priority,
+ (void *)&cmd_5tuple_filter_priority_value,
+ (void *)&cmd_5tuple_filter_queue,
+ (void *)&cmd_5tuple_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A flex FILTER *** */
+struct cmd_flex_filter_result {
+ cmdline_fixed_string_t filter;
+ cmdline_fixed_string_t ops;
+ portid_t port_id;
+ cmdline_fixed_string_t len;
+ uint8_t len_value;
+ cmdline_fixed_string_t bytes;
+ cmdline_fixed_string_t bytes_value;
+ cmdline_fixed_string_t mask;
+ cmdline_fixed_string_t mask_value;
+ cmdline_fixed_string_t priority;
+ uint8_t priority_value;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+static int xdigit2val(unsigned char c)
+{
+ int val;
+ if (isdigit(c))
+ val = c - '0';
+ else if (isupper(c))
+ val = c - 'A' + 10;
+ else
+ val = c - 'a' + 10;
+ return val;
+}
+
+static void
+cmd_flex_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ int ret = 0;
+ struct rte_eth_flex_filter filter;
+ struct cmd_flex_filter_result *res = parsed_result;
+ char *bytes_ptr, *mask_ptr;
+ uint16_t len, i, j = 0;
+ char c;
+ int val;
+ uint8_t byte = 0;
+
+ if (res->len_value > RTE_FLEX_FILTER_MAXLEN) {
+ printf("the len exceed the max length 128\n");
+ return;
+ }
+ memset(&filter, 0, sizeof(struct rte_eth_flex_filter));
+ filter.len = res->len_value;
+ filter.priority = res->priority_value;
+ filter.queue = res->queue_id;
+ bytes_ptr = res->bytes_value;
+ mask_ptr = res->mask_value;
+
+ /* translate bytes string to array. */
+ if (bytes_ptr[0] == '0' && ((bytes_ptr[1] == 'x') ||
+ (bytes_ptr[1] == 'X')))
+ bytes_ptr += 2;
+ len = strnlen(bytes_ptr, res->len_value * 2);
+ if (len == 0 || (len % 8 != 0)) {
+ printf("please check len and bytes input\n");
+ return;
+ }
+ for (i = 0; i < len; i++) {
+ c = bytes_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.bytes[j] = byte;
+ printf("bytes[%d]:%02x ", j, filter.bytes[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+ /* translate mask string to uint8_t array. */
+ if (mask_ptr[0] == '0' && ((mask_ptr[1] == 'x') ||
+ (mask_ptr[1] == 'X')))
+ mask_ptr += 2;
+ len = strnlen(mask_ptr, (res->len_value + 3) / 4);
+ if (len == 0) {
+ printf("invalid input\n");
+ return;
+ }
+ j = 0;
+ byte = 0;
+ for (i = 0; i < len; i++) {
+ c = mask_ptr[i];
+ if (isxdigit(c) == 0) {
+ /* invalid characters. */
+ printf("invalid input\n");
+ return;
+ }
+ val = xdigit2val(c);
+ if (i % 2) {
+ byte |= val;
+ filter.mask[j] = byte;
+ printf("mask[%d]:%02x ", j, filter.mask[j]);
+ j++;
+ byte = 0;
+ } else
+ byte |= val << 4;
+ }
+ printf("\n");
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_FLEXIBLE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+
+ if (ret < 0)
+ printf("flex filter setting error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flex_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ filter, "flex_filter");
+cmdline_parse_token_num_t cmd_flex_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flex_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_flex_filter_len =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ len, "len");
+cmdline_parse_token_num_t cmd_flex_filter_len_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ len_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_bytes =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ bytes, "bytes");
+cmdline_parse_token_string_t cmd_flex_filter_bytes_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ bytes_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ mask, "mask");
+cmdline_parse_token_string_t cmd_flex_filter_mask_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ mask_value, NULL);
+cmdline_parse_token_string_t cmd_flex_filter_priority =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ priority, "priority");
+cmdline_parse_token_num_t cmd_flex_filter_priority_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ priority_value, UINT8);
+cmdline_parse_token_string_t cmd_flex_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_flex_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_flex_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flex_filter_result,
+ queue_id, UINT16);
+cmdline_parse_inst_t cmd_flex_filter = {
+ .f = cmd_flex_filter_parsed,
+ .data = NULL,
+ .help_str = "flex_filter <port_id> add|del len <value> bytes "
+ "<value> mask <value> priority <value> queue <queue_id>: "
+ "Add/Del a flex filter",
+ .tokens = {
+ (void *)&cmd_flex_filter_filter,
+ (void *)&cmd_flex_filter_port_id,
+ (void *)&cmd_flex_filter_ops,
+ (void *)&cmd_flex_filter_len,
+ (void *)&cmd_flex_filter_len_value,
+ (void *)&cmd_flex_filter_bytes,
+ (void *)&cmd_flex_filter_bytes_value,
+ (void *)&cmd_flex_filter_mask,
+ (void *)&cmd_flex_filter_mask_value,
+ (void *)&cmd_flex_filter_priority,
+ (void *)&cmd_flex_filter_priority_value,
+ (void *)&cmd_flex_filter_queue,
+ (void *)&cmd_flex_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** Filters Control *** */
+
+/* *** deal with ethertype filter *** */
+struct cmd_ethertype_filter_result {
+ cmdline_fixed_string_t filter;
+ portid_t port_id;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t mac;
+ struct rte_ether_addr mac_addr;
+ cmdline_fixed_string_t ethertype;
+ uint16_t ethertype_value;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+};
+
+cmdline_parse_token_string_t cmd_ethertype_filter_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ filter, "ethertype_filter");
+cmdline_parse_token_num_t cmd_ethertype_filter_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ ops, "add#del");
+cmdline_parse_token_string_t cmd_ethertype_filter_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ mac, "mac_addr#mac_ignr");
+cmdline_parse_token_etheraddr_t cmd_ethertype_filter_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_ethertype_filter_result,
+ mac_addr);
+cmdline_parse_token_string_t cmd_ethertype_filter_ethertype =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ ethertype, "ethertype");
+cmdline_parse_token_num_t cmd_ethertype_filter_ethertype_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ ethertype_value, UINT16);
+cmdline_parse_token_string_t cmd_ethertype_filter_drop =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_ethertype_filter_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_ethertype_filter_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_ethertype_filter_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ethertype_filter_result,
+ queue_id, UINT16);
+
+static void
+cmd_ethertype_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ethertype_filter_result *res = parsed_result;
+ struct rte_eth_ethertype_filter filter;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE);
+ if (ret < 0) {
+ printf("ethertype filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&filter, 0, sizeof(filter));
+ if (!strcmp(res->mac, "mac_addr")) {
+ filter.flags |= RTE_ETHTYPE_FLAGS_MAC;
+ rte_memcpy(&filter.mac_addr, &res->mac_addr,
+ sizeof(struct rte_ether_addr));
+ }
+ if (!strcmp(res->drop, "drop"))
+ filter.flags |= RTE_ETHTYPE_FLAGS_DROP;
+ filter.ether_type = res->ethertype_value;
+ filter.queue = res->queue_id;
+
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_ADD,
+ &filter);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_ETHERTYPE,
+ RTE_ETH_FILTER_DELETE,
+ &filter);
+ if (ret < 0)
+ printf("ethertype filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_ethertype_filter = {
+ .f = cmd_ethertype_filter_parsed,
+ .data = NULL,
+ .help_str = "ethertype_filter <port_id> add|del mac_addr|mac_ignr "
+ "<mac_addr> ethertype <value> drop|fw queue <queue_id>: "
+ "Add or delete an ethertype filter entry",
+ .tokens = {
+ (void *)&cmd_ethertype_filter_filter,
+ (void *)&cmd_ethertype_filter_port_id,
+ (void *)&cmd_ethertype_filter_ops,
+ (void *)&cmd_ethertype_filter_mac,
+ (void *)&cmd_ethertype_filter_mac_addr,
+ (void *)&cmd_ethertype_filter_ethertype,
+ (void *)&cmd_ethertype_filter_ethertype_value,
+ (void *)&cmd_ethertype_filter_drop,
+ (void *)&cmd_ethertype_filter_queue,
+ (void *)&cmd_ethertype_filter_queue_id,
+ NULL,
+ },
+};
+
+/* *** deal with flow director filter *** */
+struct cmd_flow_director_result {
+ cmdline_fixed_string_t flow_director_filter;
+ portid_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t ether;
+ uint16_t ether_type;
+ cmdline_fixed_string_t src;
+ cmdline_ipaddr_t ip_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t verify_tag;
+ uint32_t verify_tag_value;
+ cmdline_fixed_string_t tos;
+ uint8_t tos_value;
+ cmdline_fixed_string_t proto;
+ uint8_t proto_value;
+ cmdline_fixed_string_t ttl;
+ uint8_t ttl_value;
+ cmdline_fixed_string_t vlan;
+ uint16_t vlan_value;
+ cmdline_fixed_string_t flexbytes;
+ cmdline_fixed_string_t flexbytes_value;
+ cmdline_fixed_string_t pf_vf;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+ cmdline_fixed_string_t fd_id;
+ uint32_t fd_id_value;
+ cmdline_fixed_string_t mac;
+ struct rte_ether_addr mac_addr;
+ cmdline_fixed_string_t tunnel;
+ cmdline_fixed_string_t tunnel_type;
+ cmdline_fixed_string_t tunnel_id;
+ uint32_t tunnel_id_value;
+ cmdline_fixed_string_t packet;
+ char filepath[];
+};
+
+static inline int
+parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT8_MAX)
+ return -1;
+ flexbytes[i] = (uint8_t)int_fld;
+ }
+ return ret;
+}
+
+static uint16_t
+str2flowtype(char *string)
+{
+ uint8_t i = 0;
+ static const struct {
+ char str[32];
+ uint16_t type;
+ } flowtype_str[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str); i++) {
+ if (!strcmp(flowtype_str[i].str, string))
+ return flowtype_str[i].type;
+ }
+
+ if (isdigit(string[0]) && atoi(string) > 0 && atoi(string) < 64)
+ return (uint16_t)atoi(string);
+
+ return RTE_ETH_FLOW_UNKNOWN;
+}
+
+static enum rte_eth_fdir_tunnel_type
+str2fdir_tunneltype(char *string)
+{
+ uint8_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_fdir_tunnel_type type;
+ } tunneltype_str[] = {
+ {"NVGRE", RTE_FDIR_TUNNEL_TYPE_NVGRE},
+ {"VxLAN", RTE_FDIR_TUNNEL_TYPE_VXLAN},
+ };
+
+ for (i = 0; i < RTE_DIM(tunneltype_str); i++) {
+ if (!strcmp(tunneltype_str[i].str, string))
+ return tunneltype_str[i].type;
+ }
+ return RTE_FDIR_TUNNEL_TYPE_UNKNOWN;
+}
+
+#define IPV4_ADDR_TO_UINT(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET) \
+ (ip) = (ip_addr).addr.ipv4.s_addr; \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+#define IPV6_ADDR_TO_ARRAY(ip_addr, ip) \
+do { \
+ if ((ip_addr).family == AF_INET6) \
+ rte_memcpy(&(ip), \
+ &((ip_addr).addr.ipv6), \
+ sizeof(struct in6_addr)); \
+ else { \
+ printf("invalid parameter.\n"); \
+ return; \
+ } \
+} while (0)
+
+static void
+cmd_flow_director_filter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_director_result *res = parsed_result;
+ struct rte_eth_fdir_filter entry;
+ uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
+ char *end;
+ unsigned long vf_id;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+ memset(flexbytes, 0, sizeof(flexbytes));
+ memset(&entry, 0, sizeof(struct rte_eth_fdir_filter));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(res->mode_value, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return;
+ }
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(res->mode_value, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return;
+ }
+ } else {
+ if (!strcmp(res->mode_value, "raw")) {
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_flow_type_mapping
+ mapping[RTE_PMD_I40E_FLOW_TYPE_MAX];
+ struct rte_pmd_i40e_pkt_template_conf conf;
+ uint16_t flow_type = str2flowtype(res->flow_type);
+ uint16_t i, port = res->port_id;
+ uint8_t add;
+
+ memset(&conf, 0, sizeof(conf));
+
+ if (flow_type == RTE_ETH_FLOW_UNKNOWN) {
+ printf("Invalid flow type specified.\n");
+ return;
+ }
+ ret = rte_pmd_i40e_flow_type_mapping_get(res->port_id,
+ mapping);
+ if (ret)
+ return;
+ if (mapping[flow_type].pctype == 0ULL) {
+ printf("Invalid flow type specified.\n");
+ return;
+ }
+ for (i = 0; i < RTE_PMD_I40E_PCTYPE_MAX; i++) {
+ if (mapping[flow_type].pctype & (1ULL << i)) {
+ conf.input.pctype = i;
+ break;
+ }
+ }
+
+ conf.input.packet = open_file(res->filepath,
+ &conf.input.length);
+ if (!conf.input.packet)
+ return;
+ if (!strcmp(res->drop, "drop"))
+ conf.action.behavior =
+ RTE_PMD_I40E_PKT_TEMPLATE_REJECT;
+ else
+ conf.action.behavior =
+ RTE_PMD_I40E_PKT_TEMPLATE_ACCEPT;
+ conf.action.report_status =
+ RTE_PMD_I40E_PKT_TEMPLATE_REPORT_ID;
+ conf.action.rx_queue = res->queue_id;
+ conf.soft_id = res->fd_id_value;
+ add = strcmp(res->ops, "del") ? 1 : 0;
+ ret = rte_pmd_i40e_flow_add_del_packet_template(port,
+ &conf,
+ add);
+ if (ret < 0)
+ printf("flow director config error: (%s)\n",
+ strerror(-ret));
+ close_file(conf.input.packet);
+#endif
+ return;
+ } else if (strcmp(res->mode_value, "IP")) {
+ printf("Please set mode to IP or raw.\n");
+ return;
+ }
+ entry.input.flow_type = str2flowtype(res->flow_type);
+ }
+
+ ret = parse_flexbytes(res->flexbytes_value,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flexbytes input.\n");
+ return;
+ }
+
+ switch (entry.input.flow_type) {
+ case RTE_ETH_FLOW_FRAG_IPV4:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
+ entry.input.flow.ip4_flow.proto = res->proto_value;
+ /* fall-through */
+ case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.ip4_flow.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.ip4_flow.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
+ IPV4_ADDR_TO_UINT(res->ip_dst,
+ entry.input.flow.sctp4_flow.ip.dst_ip);
+ IPV4_ADDR_TO_UINT(res->ip_src,
+ entry.input.flow.sctp4_flow.ip.src_ip);
+ entry.input.flow.ip4_flow.tos = res->tos_value;
+ entry.input.flow.ip4_flow.ttl = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp4_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp4_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp4_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+ case RTE_ETH_FLOW_FRAG_IPV6:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+ entry.input.flow.ipv6_flow.proto = res->proto_value;
+ /* fall-through */
+ case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+ case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.ipv6_flow.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.ipv6_flow.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.udp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.udp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ break;
+ case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
+ IPV6_ADDR_TO_ARRAY(res->ip_dst,
+ entry.input.flow.sctp6_flow.ip.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ip_src,
+ entry.input.flow.sctp6_flow.ip.src_ip);
+ entry.input.flow.ipv6_flow.tc = res->tos_value;
+ entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
+ /* need convert to big endian. */
+ entry.input.flow.sctp6_flow.dst_port =
+ rte_cpu_to_be_16(res->port_dst);
+ entry.input.flow.sctp6_flow.src_port =
+ rte_cpu_to_be_16(res->port_src);
+ entry.input.flow.sctp6_flow.verify_tag =
+ rte_cpu_to_be_32(res->verify_tag_value);
+ break;
+ case RTE_ETH_FLOW_L2_PAYLOAD:
+ entry.input.flow.l2_flow.ether_type =
+ rte_cpu_to_be_16(res->ether_type);
+ break;
+ default:
+ break;
+ }
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ rte_memcpy(&entry.input.flow.mac_vlan_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct rte_ether_addr));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr,
+ &res->mac_addr,
+ sizeof(struct rte_ether_addr));
+ entry.input.flow.tunnel_flow.tunnel_type =
+ str2fdir_tunneltype(res->tunnel_type);
+ entry.input.flow.tunnel_flow.tunnel_id =
+ rte_cpu_to_be_32(res->tunnel_id_value);
+ }
+
+ rte_memcpy(entry.input.flow_ext.flexbytes,
+ flexbytes,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+
+ entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(res->vlan_value);
+
+ entry.action.flex_off = 0; /*use 0 by default */
+ if (!strcmp(res->drop, "drop"))
+ entry.action.behavior = RTE_ETH_FDIR_REJECT;
+ else
+ entry.action.behavior = RTE_ETH_FDIR_ACCEPT;
+
+ if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
+ fdir_conf.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (!strcmp(res->pf_vf, "pf"))
+ entry.input.flow_ext.is_vf = 0;
+ else if (!strncmp(res->pf_vf, "vf", 2)) {
+ struct rte_eth_dev_info dev_info;
+
+ ret = eth_dev_info_get_print_err(res->port_id,
+ &dev_info);
+ if (ret != 0)
+ return;
+
+ errno = 0;
+ vf_id = strtoul(res->pf_vf + 2, &end, 10);
+ if (errno != 0 || *end != '\0' ||
+ vf_id >= dev_info.max_vfs) {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ entry.input.flow_ext.is_vf = 1;
+ entry.input.flow_ext.dst_id = (uint16_t)vf_id;
+ } else {
+ printf("invalid parameter %s.\n", res->pf_vf);
+ return;
+ }
+ }
+
+ /* set to report FD ID by default */
+ entry.action.report_status = RTE_ETH_FDIR_REPORT_ID;
+ entry.action.rx_queue = res->queue_id;
+ entry.soft_id = res->fd_id_value;
+ if (!strcmp(res->ops, "add"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_ADD, &entry);
+ else if (!strcmp(res->ops, "del"))
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_DELETE, &entry);
+ else
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_UPDATE, &entry);
+ if (ret < 0)
+ printf("flow director programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flow_director_filter =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_director_filter, "flow_director_filter");
+cmdline_parse_token_num_t cmd_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_ops =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ops, "add#del#update");
+cmdline_parse_token_string_t cmd_flow_director_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_flow_director_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flow_type, NULL);
+cmdline_parse_token_string_t cmd_flow_director_ether =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ether, "ether");
+cmdline_parse_token_num_t cmd_flow_director_ether_type =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ether_type, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ src, "src");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_src);
+cmdline_parse_token_num_t cmd_flow_director_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ dst, "dst");
+cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
+ ip_dst);
+cmdline_parse_token_num_t cmd_flow_director_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ port_dst, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_verify_tag =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ verify_tag, "verify_tag");
+cmdline_parse_token_num_t cmd_flow_director_verify_tag_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ verify_tag_value, UINT32);
+cmdline_parse_token_string_t cmd_flow_director_tos =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tos, "tos");
+cmdline_parse_token_num_t cmd_flow_director_tos_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ tos_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_proto =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ proto, "proto");
+cmdline_parse_token_num_t cmd_flow_director_proto_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ proto_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ ttl, "ttl");
+cmdline_parse_token_num_t cmd_flow_director_ttl_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ ttl_value, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ vlan, "vlan");
+cmdline_parse_token_num_t cmd_flow_director_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ vlan_value, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_flexbytes =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes, "flexbytes");
+cmdline_parse_token_string_t cmd_flow_director_flexbytes_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ flexbytes_value, NULL);
+cmdline_parse_token_string_t cmd_flow_director_drop =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ drop, "drop#fwd");
+cmdline_parse_token_string_t cmd_flow_director_pf_vf =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ pf_vf, NULL);
+cmdline_parse_token_string_t cmd_flow_director_queue =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ queue, "queue");
+cmdline_parse_token_num_t cmd_flow_director_queue_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_fd_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ fd_id, "fd_id");
+cmdline_parse_token_num_t cmd_flow_director_fd_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ fd_id_value, UINT32);
+
+cmdline_parse_token_string_t cmd_flow_director_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_flow_director_mode_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "IP");
+cmdline_parse_token_string_t cmd_flow_director_mode_mac_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "MAC-VLAN");
+cmdline_parse_token_string_t cmd_flow_director_mode_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "Tunnel");
+cmdline_parse_token_string_t cmd_flow_director_mode_raw =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mode_value, "raw");
+cmdline_parse_token_string_t cmd_flow_director_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ mac, "mac");
+cmdline_parse_token_etheraddr_t cmd_flow_director_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_flow_director_result,
+ mac_addr);
+cmdline_parse_token_string_t cmd_flow_director_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel, "tunnel");
+cmdline_parse_token_string_t cmd_flow_director_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_type, "NVGRE#VxLAN");
+cmdline_parse_token_string_t cmd_flow_director_tunnel_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_id, "tunnel-id");
+cmdline_parse_token_num_t cmd_flow_director_tunnel_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
+ tunnel_id_value, UINT32);
+cmdline_parse_token_string_t cmd_flow_director_packet =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ packet, "packet");
+cmdline_parse_token_string_t cmd_flow_director_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
+ filepath, NULL);
+
+cmdline_parse_inst_t cmd_add_del_ip_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter <port_id> mode IP add|del|update flow"
+ " ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
+ "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|"
+ "l2_payload src <src_ip> dst <dst_ip> tos <tos_value> "
+ "proto <proto_value> ttl <ttl_value> vlan <vlan_value> "
+ "flexbytes <flexbyte_values> drop|fw <pf_vf> queue <queue_id> "
+ "fd_id <fd_id_value>: "
+ "Add or delete an ip flow director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_proto,
+ (void *)&cmd_flow_director_proto_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_udp_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete an udp/tcp flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_port_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_sctp_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a sctp flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_src,
+ (void *)&cmd_flow_director_ip_src,
+ (void *)&cmd_flow_director_port_src,
+ (void *)&cmd_flow_director_dst,
+ (void *)&cmd_flow_director_ip_dst,
+ (void *)&cmd_flow_director_port_dst,
+ (void *)&cmd_flow_director_verify_tag,
+ (void *)&cmd_flow_director_verify_tag_value,
+ (void *)&cmd_flow_director_tos,
+ (void *)&cmd_flow_director_tos_value,
+ (void *)&cmd_flow_director_ttl,
+ (void *)&cmd_flow_director_ttl_value,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_l2_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a L2 flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_ip,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_ether,
+ (void *)&cmd_flow_director_ether_type,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_pf_vf,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_mac_vlan_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a MAC VLAN flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_mac_vlan,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_mac,
+ (void *)&cmd_flow_director_mac_addr,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_tunnel_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a tunnel flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_tunnel,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_mac,
+ (void *)&cmd_flow_director_mac_addr,
+ (void *)&cmd_flow_director_vlan,
+ (void *)&cmd_flow_director_vlan_value,
+ (void *)&cmd_flow_director_tunnel,
+ (void *)&cmd_flow_director_tunnel_type,
+ (void *)&cmd_flow_director_tunnel_id,
+ (void *)&cmd_flow_director_tunnel_id_value,
+ (void *)&cmd_flow_director_flexbytes,
+ (void *)&cmd_flow_director_flexbytes_value,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_add_del_raw_flow_director = {
+ .f = cmd_flow_director_filter_parsed,
+ .data = NULL,
+ .help_str = "flow_director_filter ... : Add or delete a raw flow "
+ "director entry on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_filter,
+ (void *)&cmd_flow_director_port_id,
+ (void *)&cmd_flow_director_mode,
+ (void *)&cmd_flow_director_mode_raw,
+ (void *)&cmd_flow_director_ops,
+ (void *)&cmd_flow_director_flow,
+ (void *)&cmd_flow_director_flow_type,
+ (void *)&cmd_flow_director_drop,
+ (void *)&cmd_flow_director_queue,
+ (void *)&cmd_flow_director_queue_id,
+ (void *)&cmd_flow_director_fd_id,
+ (void *)&cmd_flow_director_fd_id_value,
+ (void *)&cmd_flow_director_packet,
+ (void *)&cmd_flow_director_filepath,
+ NULL,
+ },
+};
+
+struct cmd_flush_flow_director_result {
+ cmdline_fixed_string_t flush_flow_director;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_flush_flow_director_flush =
+ TOKEN_STRING_INITIALIZER(struct cmd_flush_flow_director_result,
+ flush_flow_director, "flush_flow_director");
+cmdline_parse_token_num_t cmd_flush_flow_director_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flush_flow_director_result,
+ port_id, UINT16);
+
+static void
+cmd_flush_flow_director_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_director_result *res = parsed_result;
+ int ret = 0;
+
+ ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("flow director is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_FLUSH, NULL);
+ if (ret < 0)
+ printf("flow director table flushing error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_flush_flow_director = {
+ .f = cmd_flush_flow_director_parsed,
+ .data = NULL,
+ .help_str = "flush_flow_director <port_id>: "
+ "Flush all flow director entries of a device on NIC",
+ .tokens = {
+ (void *)&cmd_flush_flow_director_flush,
+ (void *)&cmd_flush_flow_director_port_id,
+ NULL,
+ },
+};
+
+/* *** deal with flow director mask *** */
+struct cmd_flow_director_mask_result {
+ cmdline_fixed_string_t flow_director_mask;
+ portid_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t vlan;
+ uint16_t vlan_mask;
+ cmdline_fixed_string_t src_mask;
+ cmdline_ipaddr_t ipv4_src;
+ cmdline_ipaddr_t ipv6_src;
+ uint16_t port_src;
+ cmdline_fixed_string_t dst_mask;
+ cmdline_ipaddr_t ipv4_dst;
+ cmdline_ipaddr_t ipv6_dst;
+ uint16_t port_dst;
+ cmdline_fixed_string_t mac;
+ uint8_t mac_addr_byte_mask;
+ cmdline_fixed_string_t tunnel_id;
+ uint32_t tunnel_id_mask;
+ cmdline_fixed_string_t tunnel_type;
+ uint8_t tunnel_type_mask;
+};
+
+static void
+cmd_flow_director_mask_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_director_mask_result *res = parsed_result;
+ struct rte_eth_fdir_masks *mask;
+ struct rte_port *port;
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ mask = &port->dev_conf.fdir_conf.mask;
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ if (strcmp(res->mode_value, "MAC-VLAN")) {
+ printf("Please set mode to MAC-VLAN.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ if (strcmp(res->mode_value, "Tunnel")) {
+ printf("Please set mode to Tunnel.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ mask->mac_addr_byte_mask = res->mac_addr_byte_mask;
+ mask->tunnel_id_mask = rte_cpu_to_be_32(res->tunnel_id_mask);
+ mask->tunnel_type_mask = res->tunnel_type_mask;
+ } else {
+ if (strcmp(res->mode_value, "IP")) {
+ printf("Please set mode to IP.\n");
+ return;
+ }
+
+ mask->vlan_tci_mask = rte_cpu_to_be_16(res->vlan_mask);
+ IPV4_ADDR_TO_UINT(res->ipv4_src, mask->ipv4_mask.src_ip);
+ IPV4_ADDR_TO_UINT(res->ipv4_dst, mask->ipv4_mask.dst_ip);
+ IPV6_ADDR_TO_ARRAY(res->ipv6_src, mask->ipv6_mask.src_ip);
+ IPV6_ADDR_TO_ARRAY(res->ipv6_dst, mask->ipv6_mask.dst_ip);
+ mask->src_port_mask = rte_cpu_to_be_16(res->port_src);
+ mask->dst_port_mask = rte_cpu_to_be_16(res->port_dst);
+ }
+
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ flow_director_mask, "flow_director_mask");
+cmdline_parse_token_num_t cmd_flow_director_mask_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_mask_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ vlan, "vlan");
+cmdline_parse_token_num_t cmd_flow_director_mask_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ vlan_mask, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_mask_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ src_mask, "src_mask");
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv4_src);
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_src =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv6_src);
+cmdline_parse_token_num_t cmd_flow_director_mask_port_src =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_src, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_mask_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ dst_mask, "dst_mask");
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv4_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv4_dst);
+cmdline_parse_token_ipaddr_t cmd_flow_director_mask_ipv6_dst =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_mask_result,
+ ipv6_dst);
+cmdline_parse_token_num_t cmd_flow_director_mask_port_dst =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ port_dst, UINT16);
+
+cmdline_parse_token_string_t cmd_flow_director_mask_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode, "mode");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_ip =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "IP");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_mac_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "MAC-VLAN");
+cmdline_parse_token_string_t cmd_flow_director_mask_mode_tunnel =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mode_value, "Tunnel");
+cmdline_parse_token_string_t cmd_flow_director_mask_mac =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ mac, "mac");
+cmdline_parse_token_num_t cmd_flow_director_mask_mac_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ mac_addr_byte_mask, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_mask_tunnel_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_type, "tunnel-type");
+cmdline_parse_token_num_t cmd_flow_director_mask_tunnel_type_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_type_mask, UINT8);
+cmdline_parse_token_string_t cmd_flow_director_mask_tunnel_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_id, "tunnel-id");
+cmdline_parse_token_num_t cmd_flow_director_mask_tunnel_id_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_mask_result,
+ tunnel_id_mask, UINT32);
+
+cmdline_parse_inst_t cmd_set_flow_director_ip_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : "
+ "Set IP mode flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_ip,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ (void *)&cmd_flow_director_mask_src,
+ (void *)&cmd_flow_director_mask_ipv4_src,
+ (void *)&cmd_flow_director_mask_ipv6_src,
+ (void *)&cmd_flow_director_mask_port_src,
+ (void *)&cmd_flow_director_mask_dst,
+ (void *)&cmd_flow_director_mask_ipv4_dst,
+ (void *)&cmd_flow_director_mask_ipv6_dst,
+ (void *)&cmd_flow_director_mask_port_dst,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_flow_director_mac_vlan_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : Set MAC VLAN mode "
+ "flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_mac_vlan,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_flow_director_tunnel_mask = {
+ .f = cmd_flow_director_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_mask ... : Set tunnel mode "
+ "flow director's mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_mask,
+ (void *)&cmd_flow_director_mask_port_id,
+ (void *)&cmd_flow_director_mask_mode,
+ (void *)&cmd_flow_director_mask_mode_tunnel,
+ (void *)&cmd_flow_director_mask_vlan,
+ (void *)&cmd_flow_director_mask_vlan_value,
+ (void *)&cmd_flow_director_mask_mac,
+ (void *)&cmd_flow_director_mask_mac_value,
+ (void *)&cmd_flow_director_mask_tunnel_type,
+ (void *)&cmd_flow_director_mask_tunnel_type_value,
+ (void *)&cmd_flow_director_mask_tunnel_id,
+ (void *)&cmd_flow_director_mask_tunnel_id_value,
+ NULL,
+ },
+};
+
+/* *** deal with flow director mask on flexible payload *** */
+struct cmd_flow_director_flex_mask_result {
+ cmdline_fixed_string_t flow_director_flexmask;
+ portid_t port_id;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t mask;
+};
+
+static void
+cmd_flow_director_flex_mask_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_director_flex_mask_result *res = parsed_result;
+ struct rte_eth_fdir_info fdir_info;
+ struct rte_eth_fdir_flex_mask flex_mask;
+ struct rte_port *port;
+ uint64_t flow_type_mask;
+ uint16_t i;
+ int ret;
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ memset(&flex_mask, 0, sizeof(struct rte_eth_fdir_flex_mask));
+ ret = parse_flexbytes(res->mask,
+ flex_mask.mask,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse mask input.\n");
+ return;
+ }
+
+ memset(&fdir_info, 0, sizeof(fdir_info));
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, &fdir_info);
+ if (ret < 0) {
+ printf("Cannot get FDir filter info\n");
+ return;
+ }
+
+ if (!strcmp(res->flow_type, "none")) {
+ /* means don't specify the flow type */
+ flex_mask.flow_type = RTE_ETH_FLOW_UNKNOWN;
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++)
+ memset(&port->dev_conf.fdir_conf.flex_conf.flex_mask[i],
+ 0, sizeof(struct rte_eth_fdir_flex_mask));
+ port->dev_conf.fdir_conf.flex_conf.nb_flexmasks = 1;
+ rte_memcpy(&port->dev_conf.fdir_conf.flex_conf.flex_mask[0],
+ &flex_mask,
+ sizeof(struct rte_eth_fdir_flex_mask));
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+ return;
+ }
+ flow_type_mask = fdir_info.flow_types_mask[0];
+ if (!strcmp(res->flow_type, "all")) {
+ if (!flow_type_mask) {
+ printf("No flow type supported\n");
+ return;
+ }
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+ if (flow_type_mask & (1ULL << i)) {
+ flex_mask.flow_type = i;
+ fdir_set_flex_mask(res->port_id, &flex_mask);
+ }
+ }
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+ return;
+ }
+ flex_mask.flow_type = str2flowtype(res->flow_type);
+ if (!(flow_type_mask & (1ULL << flex_mask.flow_type))) {
+ printf("Flow type %s not supported on port %d\n",
+ res->flow_type, res->port_id);
+ return;
+ }
+ fdir_set_flex_mask(res->port_id, &flex_mask);
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexmask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_director_flexmask,
+ "flow_director_flex_mask");
+cmdline_parse_token_num_t cmd_flow_director_flexmask_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow, "flow");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ flow_type, "none#ipv4-other#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#"
+ "ipv6-other#ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#l2_payload#all");
+cmdline_parse_token_string_t cmd_flow_director_flexmask_mask =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flex_mask_result,
+ mask, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_mask = {
+ .f = cmd_flow_director_flex_mask_parsed,
+ .data = NULL,
+ .help_str = "flow_director_flex_mask ... : "
+ "Set flow director's flex mask on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexmask,
+ (void *)&cmd_flow_director_flexmask_port_id,
+ (void *)&cmd_flow_director_flexmask_flow,
+ (void *)&cmd_flow_director_flexmask_flow_type,
+ (void *)&cmd_flow_director_flexmask_mask,
+ NULL,
+ },
+};
+
+/* *** deal with flow director flexible payload configuration *** */
+struct cmd_flow_director_flexpayload_result {
+ cmdline_fixed_string_t flow_director_flexpayload;
+ portid_t port_id;
+ cmdline_fixed_string_t payload_layer;
+ cmdline_fixed_string_t payload_cfg;
+};
+
+static inline int
+parse_offsets(const char *q_arg, uint16_t *offsets, uint16_t max_num)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ unsigned long int_fld;
+ char *str_fld[max_num];
+ int i;
+ unsigned size;
+ int ret = -1;
+
+ p = strchr(p0, '(');
+ if (p == NULL)
+ return -1;
+ ++p;
+ p0 = strchr(p, ')');
+ if (p0 == NULL)
+ return -1;
+
+ size = p0 - p;
+ if (size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, max_num, ',');
+ if (ret < 0 || ret > max_num)
+ return -1;
+ for (i = 0; i < ret; i++) {
+ errno = 0;
+ int_fld = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || *end != '\0' || int_fld > UINT16_MAX)
+ return -1;
+ offsets[i] = (uint16_t)int_fld;
+ }
+ return ret;
+}
+
+static void
+cmd_flow_director_flxpld_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_flow_director_flexpayload_result *res = parsed_result;
+ struct rte_eth_flex_payload_cfg flex_cfg;
+ struct rte_port *port;
+ int ret = 0;
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ memset(&flex_cfg, 0, sizeof(struct rte_eth_flex_payload_cfg));
+
+ if (!strcmp(res->payload_layer, "raw"))
+ flex_cfg.type = RTE_ETH_RAW_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l2"))
+ flex_cfg.type = RTE_ETH_L2_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l3"))
+ flex_cfg.type = RTE_ETH_L3_PAYLOAD;
+ else if (!strcmp(res->payload_layer, "l4"))
+ flex_cfg.type = RTE_ETH_L4_PAYLOAD;
+
+ ret = parse_offsets(res->payload_cfg, flex_cfg.src_offset,
+ RTE_ETH_FDIR_MAX_FLEXLEN);
+ if (ret < 0) {
+ printf("error: Cannot parse flex payload input.\n");
+ return;
+ }
+
+ fdir_set_flex_payload(res->port_id, &flex_cfg);
+ cmd_reconfig_device_queue(res->port_id, 1, 1);
+}
+
+cmdline_parse_token_string_t cmd_flow_director_flexpayload =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ flow_director_flexpayload,
+ "flow_director_flex_payload");
+cmdline_parse_token_num_t cmd_flow_director_flexpayload_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_layer =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_layer, "raw#l2#l3#l4");
+cmdline_parse_token_string_t cmd_flow_director_flexpayload_payload_cfg =
+ TOKEN_STRING_INITIALIZER(struct cmd_flow_director_flexpayload_result,
+ payload_cfg, NULL);
+
+cmdline_parse_inst_t cmd_set_flow_director_flex_payload = {
+ .f = cmd_flow_director_flxpld_parsed,
+ .data = NULL,
+ .help_str = "flow_director_flexpayload ... : "
+ "Set flow director's flex payload on NIC",
+ .tokens = {
+ (void *)&cmd_flow_director_flexpayload,
+ (void *)&cmd_flow_director_flexpayload_port_id,
+ (void *)&cmd_flow_director_flexpayload_payload_layer,
+ (void *)&cmd_flow_director_flexpayload_payload_cfg,
+ NULL,
+ },
+};
+
+/* Generic flow interface command. */
+extern cmdline_parse_inst_t cmd_flow;
+
+/* *** Classification Filters Control *** */
+/* *** Get symmetric hash enable per port *** */
+struct cmd_get_sym_hash_ena_per_port_result {
+ cmdline_fixed_string_t get_sym_hash_ena_per_port;
+ portid_t port_id;
+};
+
+static void
+cmd_get_sym_hash_per_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_get_sym_hash_ena_per_port_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+
+ if (ret < 0) {
+ printf("Cannot get symmetric hash enable per port "
+ "on port %u\n", res->port_id);
+ return;
+ }
+
+ printf("Symmetric hash is %s on port %u\n", info.info.enable ?
+ "enabled" : "disabled", res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_get_sym_hash_ena_per_port_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result,
+ get_sym_hash_ena_per_port, "get_sym_hash_ena_per_port");
+cmdline_parse_token_num_t cmd_get_sym_hash_ena_per_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_get_sym_hash_ena_per_port_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_get_sym_hash_ena_per_port = {
+ .f = cmd_get_sym_hash_per_port_parsed,
+ .data = NULL,
+ .help_str = "get_sym_hash_ena_per_port <port_id>",
+ .tokens = {
+ (void *)&cmd_get_sym_hash_ena_per_port_all,
+ (void *)&cmd_get_sym_hash_ena_per_port_port_id,
+ NULL,
+ },
+};
+
+/* *** Set symmetric hash enable per port *** */
+struct cmd_set_sym_hash_ena_per_port_result {
+ cmdline_fixed_string_t set_sym_hash_ena_per_port;
+ cmdline_fixed_string_t enable;
+ portid_t port_id;
+};
+
+static void
+cmd_set_sym_hash_per_port_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_sym_hash_ena_per_port_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port: %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
+ if (!strcmp(res->enable, "enable"))
+ info.info.enable = 1;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0) {
+ printf("Cannot set symmetric hash enable per port on "
+ "port %u\n", res->port_id);
+ return;
+ }
+ printf("Symmetric hash has been set to %s on port %u\n",
+ res->enable, res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ set_sym_hash_ena_per_port, "set_sym_hash_ena_per_port");
+cmdline_parse_token_num_t cmd_set_sym_hash_ena_per_port_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_sym_hash_ena_per_port_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_sym_hash_ena_per_port_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_sym_hash_ena_per_port = {
+ .f = cmd_set_sym_hash_per_port_parsed,
+ .data = NULL,
+ .help_str = "set_sym_hash_ena_per_port <port_id> enable|disable",
+ .tokens = {
+ (void *)&cmd_set_sym_hash_ena_per_port_all,
+ (void *)&cmd_set_sym_hash_ena_per_port_port_id,
+ (void *)&cmd_set_sym_hash_ena_per_port_enable,
+ NULL,
+ },
+};
+
+/* Get global config of hash function */
+struct cmd_get_hash_global_config_result {
+ cmdline_fixed_string_t get_hash_global_config;
+ portid_t port_id;
+};
+
+static char *
+flowtype_to_str(uint16_t ftype)
+{
+ uint16_t i;
+ static struct {
+ char str[16];
+ uint16_t ftype;
+ } ftype_table[] = {
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ {"port", RTE_ETH_FLOW_PORT},
+ {"vxlan", RTE_ETH_FLOW_VXLAN},
+ {"geneve", RTE_ETH_FLOW_GENEVE},
+ {"nvgre", RTE_ETH_FLOW_NVGRE},
+ {"vxlan-gpe", RTE_ETH_FLOW_VXLAN_GPE},
+ };
+
+ for (i = 0; i < RTE_DIM(ftype_table); i++) {
+ if (ftype_table[i].ftype == ftype)
+ return ftype_table[i].str;
+ }
+
+ return NULL;
+}
+
+static void
+cmd_get_hash_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_get_hash_global_config_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ uint32_t idx, offset;
+ uint16_t i;
+ char *str;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ res->port_id);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_GET, &info);
+ if (ret < 0) {
+ printf("Cannot get hash global configurations by port %d\n",
+ res->port_id);
+ return;
+ }
+
+ switch (info.info.global_conf.hash_func) {
+ case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
+ printf("Hash function is Toeplitz\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
+ printf("Hash function is Simple XOR\n");
+ break;
+ case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
+ printf("Hash function is Symmetric Toeplitz\n");
+ break;
+ default:
+ printf("Unknown hash function\n");
+ break;
+ }
+
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
+ idx = i / UINT64_BIT;
+ offset = i % UINT64_BIT;
+ if (!(info.info.global_conf.valid_bit_mask[idx] &
+ (1ULL << offset)))
+ continue;
+ str = flowtype_to_str(i);
+ if (!str)
+ continue;
+ printf("Symmetric hash is %s globally for flow type %s "
+ "by port %d\n",
+ ((info.info.global_conf.sym_hash_enable_mask[idx] &
+ (1ULL << offset)) ? "enabled" : "disabled"), str,
+ res->port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_get_hash_global_config_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_get_hash_global_config_result,
+ get_hash_global_config, "get_hash_global_config");
+cmdline_parse_token_num_t cmd_get_hash_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_get_hash_global_config_result,
+ port_id, UINT16);
+
+cmdline_parse_inst_t cmd_get_hash_global_config = {
+ .f = cmd_get_hash_global_config_parsed,
+ .data = NULL,
+ .help_str = "get_hash_global_config <port_id>",
+ .tokens = {
+ (void *)&cmd_get_hash_global_config_all,
+ (void *)&cmd_get_hash_global_config_port_id,
+ NULL,
+ },
+};
+
+/* Set global config of hash function */
+struct cmd_set_hash_global_config_result {
+ cmdline_fixed_string_t set_hash_global_config;
+ portid_t port_id;
+ cmdline_fixed_string_t hash_func;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t enable;
+};
+
+static void
+cmd_set_hash_global_config_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_global_config_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+ uint32_t ftype, idx, offset;
+ int ret;
+
+ if (rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_HASH) < 0) {
+ printf("RTE_ETH_FILTER_HASH not supported on port %d\n",
+ res->port_id);
+ return;
+ }
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
+ if (!strcmp(res->hash_func, "toeplitz"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+ else if (!strcmp(res->hash_func, "simple_xor"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+ else if (!strcmp(res->hash_func, "symmetric_toeplitz"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
+ else if (!strcmp(res->hash_func, "default"))
+ info.info.global_conf.hash_func =
+ RTE_ETH_HASH_FUNCTION_DEFAULT;
+
+ ftype = str2flowtype(res->flow_type);
+ idx = ftype / UINT64_BIT;
+ offset = ftype % UINT64_BIT;
+ info.info.global_conf.valid_bit_mask[idx] |= (1ULL << offset);
+ if (!strcmp(res->enable, "enable"))
+ info.info.global_conf.sym_hash_enable_mask[idx] |=
+ (1ULL << offset);
+ ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+ if (ret < 0)
+ printf("Cannot set global hash configurations by port %d\n",
+ res->port_id);
+ else
+ printf("Global hash configurations have been set "
+ "successfully by port %d\n", res->port_id);
+}
+
+cmdline_parse_token_string_t cmd_set_hash_global_config_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ set_hash_global_config, "set_hash_global_config");
+cmdline_parse_token_num_t cmd_set_hash_global_config_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_hash_global_config_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_hash_global_config_hash_func =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ hash_func, "toeplitz#simple_xor#symmetric_toeplitz#default");
+cmdline_parse_token_string_t cmd_set_hash_global_config_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ flow_type,
+ "ipv4#ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#ipv6#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_hash_global_config_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_global_config_result,
+ enable, "enable#disable");
+
+cmdline_parse_inst_t cmd_set_hash_global_config = {
+ .f = cmd_set_hash_global_config_parsed,
+ .data = NULL,
+ .help_str = "set_hash_global_config <port_id> "
+ "toeplitz|simple_xor|symmetric_toeplitz|default "
+ "ipv4|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
+ "l2_payload enable|disable",
+ .tokens = {
+ (void *)&cmd_set_hash_global_config_all,
+ (void *)&cmd_set_hash_global_config_port_id,
+ (void *)&cmd_set_hash_global_config_hash_func,
+ (void *)&cmd_set_hash_global_config_flow_type,
+ (void *)&cmd_set_hash_global_config_enable,
+ NULL,
+ },
+};
+
+/* Set hash input set */
+struct cmd_set_hash_input_set_result {
+ cmdline_fixed_string_t set_hash_input_set;
+ portid_t port_id;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t inset_field;
+ cmdline_fixed_string_t select;
+};
+
+static enum rte_eth_input_set_field
+str2inset(char *string)
+{
+ uint16_t i;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_input_set_field inset;
+ } inset_table[] = {
+ {"ethertype", RTE_ETH_INPUT_SET_L2_ETHERTYPE},
+ {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN},
+ {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN},
+ {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4},
+ {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4},
+ {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS},
+ {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO},
+ {"ipv4-ttl", RTE_ETH_INPUT_SET_L3_IP4_TTL},
+ {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6},
+ {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6},
+ {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC},
+ {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER},
+ {"ipv6-hop-limits", RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS},
+ {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},
+ {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT},
+ {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},
+ {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT},
+ {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},
+ {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},
+ {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG},
+ {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY},
+ {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY},
+ {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD},
+ {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD},
+ {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD},
+ {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD},
+ {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD},
+ {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD},
+ {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD},
+ {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD},
+ {"none", RTE_ETH_INPUT_SET_NONE},
+ };
+
+ for (i = 0; i < RTE_DIM(inset_table); i++) {
+ if (!strcmp(string, inset_table[i].str))
+ return inset_table[i].inset;
+ }
+
+ return RTE_ETH_INPUT_SET_UNKNOWN;
+}
+
+static void
+cmd_set_hash_input_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_hash_input_set_result *res = parsed_result;
+ struct rte_eth_hash_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_HASH,
+ RTE_ETH_FILTER_SET, &info);
+}
+
+cmdline_parse_token_string_t cmd_set_hash_input_set_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ set_hash_input_set, "set_hash_input_set");
+cmdline_parse_token_num_t cmd_set_hash_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_hash_input_set_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_hash_input_set_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ flow_type, NULL);
+cmdline_parse_token_string_t cmd_set_hash_input_set_field =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ inset_field,
+ "ovlan#ivlan#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#"
+ "ipv4-tos#ipv4-proto#ipv6-tc#ipv6-next-header#udp-src-port#"
+ "udp-dst-port#tcp-src-port#tcp-dst-port#sctp-src-port#"
+ "sctp-dst-port#sctp-veri-tag#udp-key#gre-key#fld-1st#"
+ "fld-2nd#fld-3rd#fld-4th#fld-5th#fld-6th#fld-7th#"
+ "fld-8th#none");
+cmdline_parse_token_string_t cmd_set_hash_input_set_select =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_hash_input_set_result,
+ select, "select#add");
+
+cmdline_parse_inst_t cmd_set_hash_input_set = {
+ .f = cmd_set_hash_input_set_parsed,
+ .data = NULL,
+ .help_str = "set_hash_input_set <port_id> "
+ "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload|<flowtype_id> "
+ "ovlan|ivlan|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|ipv4-tos|ipv4-proto|"
+ "ipv6-tc|ipv6-next-header|udp-src-port|udp-dst-port|tcp-src-port|"
+ "tcp-dst-port|sctp-src-port|sctp-dst-port|sctp-veri-tag|udp-key|"
+ "gre-key|fld-1st|fld-2nd|fld-3rd|fld-4th|fld-5th|fld-6th|"
+ "fld-7th|fld-8th|none select|add",
+ .tokens = {
+ (void *)&cmd_set_hash_input_set_cmd,
+ (void *)&cmd_set_hash_input_set_port_id,
+ (void *)&cmd_set_hash_input_set_flow_type,
+ (void *)&cmd_set_hash_input_set_field,
+ (void *)&cmd_set_hash_input_set_select,
+ NULL,
+ },
+};
+
+/* Set flow director input set */
+struct cmd_set_fdir_input_set_result {
+ cmdline_fixed_string_t set_fdir_input_set;
+ portid_t port_id;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t inset_field;
+ cmdline_fixed_string_t select;
+};
+
+static void
+cmd_set_fdir_input_set_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_fdir_input_set_result *res = parsed_result;
+ struct rte_eth_fdir_filter_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT;
+ info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
+ info.info.input_set_conf.field[0] = str2inset(res->inset_field);
+ info.info.input_set_conf.inset_size = 1;
+ if (!strcmp(res->select, "select"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
+ else if (!strcmp(res->select, "add"))
+ info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
+ rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_SET, &info);
+}
+
+cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ set_fdir_input_set, "set_fdir_input_set");
+cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ flow_type,
+ "ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#"
+ "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
+cmdline_parse_token_string_t cmd_set_fdir_input_set_field =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ inset_field,
+ "ivlan#ethertype#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#"
+ "ipv4-tos#ipv4-proto#ipv4-ttl#ipv6-tc#ipv6-next-header#"
+ "ipv6-hop-limits#udp-src-port#udp-dst-port#"
+ "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#"
+ "sctp-veri-tag#none");
+cmdline_parse_token_string_t cmd_set_fdir_input_set_select =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
+ select, "select#add");
+
+cmdline_parse_inst_t cmd_set_fdir_input_set = {
+ .f = cmd_set_fdir_input_set_parsed,
+ .data = NULL,
+ .help_str = "set_fdir_input_set <port_id> "
+ "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
+ "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
+ "ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|"
+ "ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|"
+ "ipv6-hop-limits|udp-src-port|udp-dst-port|"
+ "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|"
+ "sctp-veri-tag|none select|add",
+ .tokens = {
+ (void *)&cmd_set_fdir_input_set_cmd,
+ (void *)&cmd_set_fdir_input_set_port_id,
+ (void *)&cmd_set_fdir_input_set_flow_type,
+ (void *)&cmd_set_fdir_input_set_field,
+ (void *)&cmd_set_fdir_input_set_select,
+ NULL,
+ },
+};
+
+/* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */
+struct cmd_mcast_addr_result {
+ cmdline_fixed_string_t mcast_addr_cmd;
+ cmdline_fixed_string_t what;
+ uint16_t port_num;
+ struct rte_ether_addr mc_addr;
+};
+
+static void cmd_mcast_addr_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_mcast_addr_result *res = parsed_result;
+
+ if (!rte_is_multicast_ether_addr(&res->mc_addr)) {
+ printf("Invalid multicast addr %02X:%02X:%02X:%02X:%02X:%02X\n",
+ res->mc_addr.addr_bytes[0], res->mc_addr.addr_bytes[1],
+ res->mc_addr.addr_bytes[2], res->mc_addr.addr_bytes[3],
+ res->mc_addr.addr_bytes[4], res->mc_addr.addr_bytes[5]);
+ return;
+ }
+ if (strcmp(res->what, "add") == 0)
+ mcast_addr_add(res->port_num, &res->mc_addr);
+ else
+ mcast_addr_remove(res->port_num, &res->mc_addr);
+}
+
+cmdline_parse_token_string_t cmd_mcast_addr_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result,
+ mcast_addr_cmd, "mcast_addr");
+cmdline_parse_token_string_t cmd_mcast_addr_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, what,
+ "add#remove");
+cmdline_parse_token_num_t cmd_mcast_addr_portnum =
+ TOKEN_NUM_INITIALIZER(struct cmd_mcast_addr_result, port_num, UINT16);
+cmdline_parse_token_etheraddr_t cmd_mcast_addr_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address);
+
+cmdline_parse_inst_t cmd_mcast_addr = {
+ .f = cmd_mcast_addr_parsed,
+ .data = (void *)0,
+ .help_str = "mcast_addr add|remove <port_id> <mcast_addr>: "
+ "Add/Remove multicast MAC address on port_id",
+ .tokens = {
+ (void *)&cmd_mcast_addr_cmd,
+ (void *)&cmd_mcast_addr_what,
+ (void *)&cmd_mcast_addr_portnum,
+ (void *)&cmd_mcast_addr_addr,
+ NULL,
+ },
+};
+
+/* l2 tunnel config
+ * only support E-tag now.
+ */
+
+/* Ether type config */
+struct cmd_config_l2_tunnel_eth_type_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ cmdline_fixed_string_t all;
+ portid_t id;
+ cmdline_fixed_string_t l2_tunnel;
+ cmdline_fixed_string_t l2_tunnel_type;
+ cmdline_fixed_string_t eth_type;
+ uint16_t eth_type_val;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_all_str =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ id, UINT16);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_l2_tunnel_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_eth_type_eth_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ eth_type, "ether-type");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_eth_type_eth_type_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_eth_type_result,
+ eth_type_val, UINT16);
+
+static enum rte_eth_tunnel_type
+str2fdir_l2_tunnel_type(char *string)
+{
+ uint32_t i = 0;
+
+ static const struct {
+ char str[32];
+ enum rte_eth_tunnel_type type;
+ } l2_tunnel_type_str[] = {
+ {"E-tag", RTE_L2_TUNNEL_TYPE_E_TAG},
+ };
+
+ for (i = 0; i < RTE_DIM(l2_tunnel_type_str); i++) {
+ if (!strcmp(l2_tunnel_type_str[i].str, string))
+ return l2_tunnel_type_str[i].type;
+ }
+ return RTE_TUNNEL_TYPE_NONE;
+}
+
+/* ether type config for all ports */
+static void
+cmd_config_l2_tunnel_eth_type_all_parsed
+ (void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_l2_tunnel_eth_type_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ portid_t pid;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+ entry.ether_type = res->eth_type_val;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_eth_type_conf(pid, &entry);
+ }
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_all = {
+ .f = cmd_config_l2_tunnel_eth_type_all_parsed,
+ .data = NULL,
+ .help_str = "port config all l2-tunnel E-tag ether-type <value>",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_eth_type_port,
+ (void *)&cmd_config_l2_tunnel_eth_type_config,
+ (void *)&cmd_config_l2_tunnel_eth_type_all_str,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+ NULL,
+ },
+};
+
+/* ether type config for a specific port */
+static void
+cmd_config_l2_tunnel_eth_type_specific_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_l2_tunnel_eth_type_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+ entry.ether_type = res->eth_type_val;
+
+ rte_eth_dev_l2_tunnel_eth_type_conf(res->id, &entry);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_eth_type_specific = {
+ .f = cmd_config_l2_tunnel_eth_type_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> l2-tunnel E-tag ether-type <value>",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_eth_type_port,
+ (void *)&cmd_config_l2_tunnel_eth_type_config,
+ (void *)&cmd_config_l2_tunnel_eth_type_id,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_eth_type_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type,
+ (void *)&cmd_config_l2_tunnel_eth_type_eth_type_val,
+ NULL,
+ },
+};
+
+/* Enable/disable l2 tunnel */
+struct cmd_config_l2_tunnel_en_dis_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ cmdline_fixed_string_t all;
+ portid_t id;
+ cmdline_fixed_string_t l2_tunnel;
+ cmdline_fixed_string_t l2_tunnel_type;
+ cmdline_fixed_string_t en_dis;
+};
+
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ config, "config");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_all_str =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ all, "all");
+cmdline_parse_token_num_t cmd_config_l2_tunnel_en_dis_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ id, UINT16);
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ l2_tunnel, "l2-tunnel");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_l2_tunnel_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ l2_tunnel_type, "E-tag");
+cmdline_parse_token_string_t cmd_config_l2_tunnel_en_dis_en_dis =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_l2_tunnel_en_dis_result,
+ en_dis, "enable#disable");
+
+/* enable/disable l2 tunnel for all ports */
+static void
+cmd_config_l2_tunnel_en_dis_all_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_l2_tunnel_en_dis_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ portid_t pid;
+ uint8_t en;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+ if (!strcmp("enable", res->en_dis))
+ en = 1;
+ else
+ en = 0;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ rte_eth_dev_l2_tunnel_offload_set(pid,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ en);
+ }
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_all = {
+ .f = cmd_config_l2_tunnel_en_dis_all_parsed,
+ .data = NULL,
+ .help_str = "port config all l2-tunnel E-tag enable|disable",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_en_dis_port,
+ (void *)&cmd_config_l2_tunnel_en_dis_config,
+ (void *)&cmd_config_l2_tunnel_en_dis_all_str,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+ NULL,
+ },
+};
+
+/* enable/disable l2 tunnel for a port */
+static void
+cmd_config_l2_tunnel_en_dis_specific_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_l2_tunnel_en_dis_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = str2fdir_l2_tunnel_type(res->l2_tunnel_type);
+
+ if (!strcmp("enable", res->en_dis))
+ rte_eth_dev_l2_tunnel_offload_set(res->id,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set(res->id,
+ &entry,
+ ETH_L2_TUNNEL_ENABLE_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_l2_tunnel_en_dis_specific = {
+ .f = cmd_config_l2_tunnel_en_dis_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> l2-tunnel E-tag enable|disable",
+ .tokens = {
+ (void *)&cmd_config_l2_tunnel_en_dis_port,
+ (void *)&cmd_config_l2_tunnel_en_dis_config,
+ (void *)&cmd_config_l2_tunnel_en_dis_id,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel,
+ (void *)&cmd_config_l2_tunnel_en_dis_l2_tunnel_type,
+ (void *)&cmd_config_l2_tunnel_en_dis_en_dis,
+ NULL,
+ },
+};
+
+/* E-tag configuration */
+
+/* Common result structure for all E-tag configuration */
+struct cmd_config_e_tag_result {
+ cmdline_fixed_string_t e_tag;
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t insertion;
+ cmdline_fixed_string_t stripping;
+ cmdline_fixed_string_t forwarding;
+ cmdline_fixed_string_t filter;
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t off;
+ cmdline_fixed_string_t on_off;
+ cmdline_fixed_string_t port_tag_id;
+ uint32_t port_tag_id_val;
+ cmdline_fixed_string_t e_tag_id;
+ uint16_t e_tag_id_val;
+ cmdline_fixed_string_t dst_pool;
+ uint8_t dst_pool_val;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t vf;
+ uint8_t vf_id;
+};
+
+/* Common CLI fields for all E-tag configuration */
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag, "E-tag");
+cmdline_parse_token_string_t cmd_config_e_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_config_e_tag_insertion =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ insertion, "insertion");
+cmdline_parse_token_string_t cmd_config_e_tag_stripping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ stripping, "stripping");
+cmdline_parse_token_string_t cmd_config_e_tag_forwarding =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ forwarding, "forwarding");
+cmdline_parse_token_string_t cmd_config_e_tag_filter =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ filter, "filter");
+cmdline_parse_token_string_t cmd_config_e_tag_add =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ add, "add");
+cmdline_parse_token_string_t cmd_config_e_tag_del =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ del, "del");
+cmdline_parse_token_string_t cmd_config_e_tag_on =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ on, "on");
+cmdline_parse_token_string_t cmd_config_e_tag_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ off, "off");
+cmdline_parse_token_string_t cmd_config_e_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ on_off, "on#off");
+cmdline_parse_token_string_t cmd_config_e_tag_port_tag_id =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_tag_id, "port-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_port_tag_id_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_tag_id_val, UINT32);
+cmdline_parse_token_string_t cmd_config_e_tag_e_tag_id =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag_id, "e-tag-id");
+cmdline_parse_token_num_t cmd_config_e_tag_e_tag_id_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ e_tag_id_val, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_dst_pool =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ dst_pool, "dst-pool");
+cmdline_parse_token_num_t cmd_config_e_tag_dst_pool_val =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ dst_pool_val, UINT8);
+cmdline_parse_token_string_t cmd_config_e_tag_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_config_e_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_e_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ vf, "vf");
+cmdline_parse_token_num_t cmd_config_e_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_e_tag_result,
+ vf_id, UINT8);
+
+/* E-tag insertion configuration */
+static void
+cmd_config_e_tag_insertion_en_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->port_tag_id_val;
+ entry.vf_id = res->vf_id;
+ rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 1);
+}
+
+static void
+cmd_config_e_tag_insertion_dis_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.vf_id = res->vf_id;
+
+ rte_eth_dev_l2_tunnel_offload_set(res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_INSERTION_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_en = {
+ .f = cmd_config_e_tag_insertion_en_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag insertion enable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_insertion,
+ (void *)&cmd_config_e_tag_on,
+ (void *)&cmd_config_e_tag_port_tag_id,
+ (void *)&cmd_config_e_tag_port_tag_id_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ (void *)&cmd_config_e_tag_vf,
+ (void *)&cmd_config_e_tag_vf_id,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_config_e_tag_insertion_dis = {
+ .f = cmd_config_e_tag_insertion_dis_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag insertion disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_insertion,
+ (void *)&cmd_config_e_tag_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ (void *)&cmd_config_e_tag_vf,
+ (void *)&cmd_config_e_tag_vf_id,
+ NULL,
+ },
+};
+
+/* E-tag stripping configuration */
+static void
+cmd_config_e_tag_stripping_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res =
+ parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ if (!strcmp(res->on_off, "on"))
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_STRIPPING_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_STRIPPING_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_stripping_en_dis = {
+ .f = cmd_config_e_tag_stripping_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag stripping enable/disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_stripping,
+ (void *)&cmd_config_e_tag_on_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* E-tag forwarding configuration */
+static void
+cmd_config_e_tag_forwarding_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+
+ if (!strcmp(res->on_off, "on"))
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_FORWARDING_MASK,
+ 1);
+ else
+ rte_eth_dev_l2_tunnel_offload_set
+ (res->port_id,
+ &entry,
+ ETH_L2_TUNNEL_FORWARDING_MASK,
+ 0);
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_forwarding_en_dis = {
+ .f = cmd_config_e_tag_forwarding_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag forwarding enable/disable",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_forwarding,
+ (void *)&cmd_config_e_tag_on_off,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* E-tag filter configuration */
+static void
+cmd_config_e_tag_filter_add_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ int ret = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (res->e_tag_id_val > 0x3fff) {
+ printf("e-tag-id must be equal or less than 0x3fff.\n");
+ return;
+ }
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (ret < 0) {
+ printf("E-tag filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->e_tag_id_val;
+ entry.pool = res->dst_pool_val;
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_ADD,
+ &entry);
+ if (ret < 0)
+ printf("E-tag filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_add = {
+ .f = cmd_config_e_tag_filter_add_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag filter add",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_filter,
+ (void *)&cmd_config_e_tag_add,
+ (void *)&cmd_config_e_tag_e_tag_id,
+ (void *)&cmd_config_e_tag_e_tag_id_val,
+ (void *)&cmd_config_e_tag_dst_pool,
+ (void *)&cmd_config_e_tag_dst_pool_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+static void
+cmd_config_e_tag_filter_del_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_e_tag_result *res = parsed_result;
+ struct rte_eth_l2_tunnel_conf entry;
+ int ret = 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ if (res->e_tag_id_val > 0x3fff) {
+ printf("e-tag-id must be less than 0x3fff.\n");
+ return;
+ }
+
+ ret = rte_eth_dev_filter_supported(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL);
+ if (ret < 0) {
+ printf("E-tag filter is not supported on port %u.\n",
+ res->port_id);
+ return;
+ }
+
+ entry.l2_tunnel_type = RTE_L2_TUNNEL_TYPE_E_TAG;
+ entry.tunnel_id = res->e_tag_id_val;
+
+ ret = rte_eth_dev_filter_ctrl(res->port_id,
+ RTE_ETH_FILTER_L2_TUNNEL,
+ RTE_ETH_FILTER_DELETE,
+ &entry);
+ if (ret < 0)
+ printf("E-tag filter programming error: (%s)\n",
+ strerror(-ret));
+}
+
+cmdline_parse_inst_t cmd_config_e_tag_filter_del = {
+ .f = cmd_config_e_tag_filter_del_parsed,
+ .data = NULL,
+ .help_str = "E-tag ... : E-tag filter delete",
+ .tokens = {
+ (void *)&cmd_config_e_tag_e_tag,
+ (void *)&cmd_config_e_tag_set,
+ (void *)&cmd_config_e_tag_filter,
+ (void *)&cmd_config_e_tag_del,
+ (void *)&cmd_config_e_tag_e_tag_id,
+ (void *)&cmd_config_e_tag_e_tag_id_val,
+ (void *)&cmd_config_e_tag_port,
+ (void *)&cmd_config_e_tag_port_id,
+ NULL,
+ },
+};
+
+/* vf vlan anti spoof configuration */
+
+/* Common result structure for vf vlan anti spoof */
+struct cmd_vf_vlan_anti_spoof_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t antispoof;
+ portid_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_antispoof =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_anti_spoof_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_vlan_anti_spoof_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_anti_spoof_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_anti_spoof_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_vlan_anti_spoof_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_vlan_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_anti_spoof = {
+ .f = cmd_set_vf_vlan_anti_spoof_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan antispoof <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_vlan_anti_spoof_set,
+ (void *)&cmd_vf_vlan_anti_spoof_vf,
+ (void *)&cmd_vf_vlan_anti_spoof_vlan,
+ (void *)&cmd_vf_vlan_anti_spoof_antispoof,
+ (void *)&cmd_vf_vlan_anti_spoof_port_id,
+ (void *)&cmd_vf_vlan_anti_spoof_vf_id,
+ (void *)&cmd_vf_vlan_anti_spoof_on_off,
+ NULL,
+ },
+};
+
+/* vf mac anti spoof configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_mac_anti_spoof_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t mac;
+ cmdline_fixed_string_t antispoof;
+ portid_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf mac anti spoof enable disable */
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_mac =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ mac, "mac");
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_antispoof =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ antispoof, "antispoof");
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_mac_anti_spoof_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_mac_anti_spoof_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_mac_anti_spoof_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_mac_anti_spoof_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_mac_anti_spoof_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_mac_anti_spoof(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_anti_spoof = {
+ .f = cmd_set_vf_mac_anti_spoof_parsed,
+ .data = NULL,
+ .help_str = "set vf mac antispoof <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_mac_anti_spoof_set,
+ (void *)&cmd_vf_mac_anti_spoof_vf,
+ (void *)&cmd_vf_mac_anti_spoof_mac,
+ (void *)&cmd_vf_mac_anti_spoof_antispoof,
+ (void *)&cmd_vf_mac_anti_spoof_port_id,
+ (void *)&cmd_vf_mac_anti_spoof_vf_id,
+ (void *)&cmd_vf_mac_anti_spoof_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan strip queue configuration */
+
+/* Common result structure for vf mac anti spoof */
+struct cmd_vf_vlan_stripq_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t stripq;
+ portid_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan strip enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_stripq =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ stripq, "stripq");
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_stripq_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_vlan_stripq_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_stripq_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_stripq_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_vlan_stripq_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_vlan_stripq(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_stripq = {
+ .f = cmd_set_vf_vlan_stripq_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan stripq <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_vlan_stripq_set,
+ (void *)&cmd_vf_vlan_stripq_vf,
+ (void *)&cmd_vf_vlan_stripq_vlan,
+ (void *)&cmd_vf_vlan_stripq_stripq,
+ (void *)&cmd_vf_vlan_stripq_port_id,
+ (void *)&cmd_vf_vlan_stripq_vf_id,
+ (void *)&cmd_vf_vlan_stripq_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan insert configuration */
+
+/* Common result structure for vf vlan insert */
+struct cmd_vf_vlan_insert_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t insert;
+ portid_t port_id;
+ uint16_t vf_id;
+ uint16_t vlan_id;
+};
+
+/* Common CLI fields for vf vlan insert enable disable */
+cmdline_parse_token_string_t cmd_vf_vlan_insert_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_vf_vlan_insert_insert =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ insert, "insert");
+cmdline_parse_token_num_t cmd_vf_vlan_insert_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_vlan_insert_vlan_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_vlan_insert_result,
+ vlan_id, UINT16);
+
+static void
+cmd_set_vf_vlan_insert_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_vlan_insert_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_vlan_insert(res->port_id, res->vf_id,
+ res->vlan_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or vlan_id %d\n", res->vf_id, res->vlan_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_insert = {
+ .f = cmd_set_vf_vlan_insert_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan insert <port_id> <vf_id> <vlan_id>",
+ .tokens = {
+ (void *)&cmd_vf_vlan_insert_set,
+ (void *)&cmd_vf_vlan_insert_vf,
+ (void *)&cmd_vf_vlan_insert_vlan,
+ (void *)&cmd_vf_vlan_insert_insert,
+ (void *)&cmd_vf_vlan_insert_port_id,
+ (void *)&cmd_vf_vlan_insert_vf_id,
+ (void *)&cmd_vf_vlan_insert_vlan_id,
+ NULL,
+ },
+};
+
+/* tx loopback configuration */
+
+/* Common result structure for tx loopback */
+struct cmd_tx_loopback_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t loopback;
+ portid_t port_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_tx_loopback_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_tx_loopback_tx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_tx_loopback_loopback =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ loopback, "loopback");
+cmdline_parse_token_num_t cmd_tx_loopback_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_tx_loopback_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_loopback_result,
+ on_off, "on#off");
+
+static void
+cmd_set_tx_loopback_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_loopback_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_tx_loopback(res->port_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_tx_loopback(res->port_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_tx_loopback(res->port_id, is_on);
+#endif
+#if defined RTE_LIBRTE_DPAA_BUS && defined RTE_LIBRTE_DPAA_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_dpaa_set_tx_loopback(res->port_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid is_on %d\n", is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_tx_loopback = {
+ .f = cmd_set_tx_loopback_parsed,
+ .data = NULL,
+ .help_str = "set tx loopback <port_id> on|off",
+ .tokens = {
+ (void *)&cmd_tx_loopback_set,
+ (void *)&cmd_tx_loopback_tx,
+ (void *)&cmd_tx_loopback_loopback,
+ (void *)&cmd_tx_loopback_port_id,
+ (void *)&cmd_tx_loopback_on_off,
+ NULL,
+ },
+};
+
+/* all queues drop enable configuration */
+
+/* Common result structure for all queues drop enable */
+struct cmd_all_queues_drop_en_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t all;
+ cmdline_fixed_string_t queues;
+ cmdline_fixed_string_t drop;
+ portid_t port_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for tx loopback enable disable */
+cmdline_parse_token_string_t cmd_all_queues_drop_en_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_all =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ all, "all");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_queues =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ queues, "queues");
+cmdline_parse_token_string_t cmd_all_queues_drop_en_drop =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ drop, "drop");
+cmdline_parse_token_num_t cmd_all_queues_drop_en_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_all_queues_drop_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_all_queues_drop_en_result,
+ on_off, "on#off");
+
+static void
+cmd_set_all_queues_drop_en_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_all_queues_drop_en_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_all_queues_drop_en(res->port_id, is_on);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_all_queues_drop_en(res->port_id, is_on);
+#endif
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid is_on %d\n", is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_all_queues_drop_en = {
+ .f = cmd_set_all_queues_drop_en_parsed,
+ .data = NULL,
+ .help_str = "set all queues drop <port_id> on|off",
+ .tokens = {
+ (void *)&cmd_all_queues_drop_en_set,
+ (void *)&cmd_all_queues_drop_en_all,
+ (void *)&cmd_all_queues_drop_en_queues,
+ (void *)&cmd_all_queues_drop_en_drop,
+ (void *)&cmd_all_queues_drop_en_port_id,
+ (void *)&cmd_all_queues_drop_en_on_off,
+ NULL,
+ },
+};
+
+/* vf split drop enable configuration */
+
+/* Common result structure for vf split drop enable */
+struct cmd_vf_split_drop_en_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t split;
+ cmdline_fixed_string_t drop;
+ portid_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_vf_split_drop_en_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_split =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ split, "split");
+cmdline_parse_token_string_t cmd_vf_split_drop_en_drop =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ drop, "drop");
+cmdline_parse_token_num_t cmd_vf_split_drop_en_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_split_drop_en_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_vf_split_drop_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_split_drop_en_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_split_drop_en_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_split_drop_en_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = rte_pmd_ixgbe_set_vf_split_drop_en(res->port_id, res->vf_id,
+ is_on);
+#endif
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("not supported on port %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_split_drop_en = {
+ .f = cmd_set_vf_split_drop_en_parsed,
+ .data = NULL,
+ .help_str = "set vf split drop <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_vf_split_drop_en_set,
+ (void *)&cmd_vf_split_drop_en_vf,
+ (void *)&cmd_vf_split_drop_en_split,
+ (void *)&cmd_vf_split_drop_en_drop,
+ (void *)&cmd_vf_split_drop_en_port_id,
+ (void *)&cmd_vf_split_drop_en_vf_id,
+ (void *)&cmd_vf_split_drop_en_on_off,
+ NULL,
+ },
+};
+
+/* vf mac address configuration */
+
+/* Common result structure for vf mac address */
+struct cmd_set_vf_mac_addr_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t mac;
+ cmdline_fixed_string_t addr;
+ portid_t port_id;
+ uint16_t vf_id;
+ struct rte_ether_addr mac_addr;
+
+};
+
+/* Common CLI fields for vf split drop enable disable */
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_mac =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ mac, "mac");
+cmdline_parse_token_string_t cmd_set_vf_mac_addr_addr =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ addr, "addr");
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_vf_mac_addr_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_mac_addr_result,
+ vf_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_set_vf_mac_addr_mac_addr =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vf_mac_addr_result,
+ mac_addr);
+
+static void
+cmd_set_vf_mac_addr_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_vf_mac_addr_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_ixgbe_set_vf_mac_addr(res->port_id, res->vf_id,
+ &res->mac_addr);
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_set_vf_mac_addr(res->port_id, res->vf_id,
+ &res->mac_addr);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_set_vf_mac_addr(res->port_id, res->vf_id,
+ &res->mac_addr);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or mac_addr\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_mac_addr = {
+ .f = cmd_set_vf_mac_addr_parsed,
+ .data = NULL,
+ .help_str = "set vf mac addr <port_id> <vf_id> <mac_addr>",
+ .tokens = {
+ (void *)&cmd_set_vf_mac_addr_set,
+ (void *)&cmd_set_vf_mac_addr_vf,
+ (void *)&cmd_set_vf_mac_addr_mac,
+ (void *)&cmd_set_vf_mac_addr_addr,
+ (void *)&cmd_set_vf_mac_addr_port_id,
+ (void *)&cmd_set_vf_mac_addr_vf_id,
+ (void *)&cmd_set_vf_mac_addr_mac_addr,
+ NULL,
+ },
+};
+
+/* MACsec configuration */
+
+/* Common result structure for MACsec offload enable */
+struct cmd_macsec_offload_on_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t offload;
+ portid_t port_id;
+ cmdline_fixed_string_t on;
+ cmdline_fixed_string_t encrypt;
+ cmdline_fixed_string_t en_on_off;
+ cmdline_fixed_string_t replay_protect;
+ cmdline_fixed_string_t rp_on_off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_on_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_on_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_on_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_on_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_macsec_offload_on_on =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ on, "on");
+cmdline_parse_token_string_t cmd_macsec_offload_on_encrypt =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ encrypt, "encrypt");
+cmdline_parse_token_string_t cmd_macsec_offload_on_en_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ en_on_off, "on#off");
+cmdline_parse_token_string_t cmd_macsec_offload_on_replay_protect =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ replay_protect, "replay-protect");
+cmdline_parse_token_string_t cmd_macsec_offload_on_rp_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_on_result,
+ rp_on_off, "on#off");
+
+static void
+cmd_set_macsec_offload_on_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_macsec_offload_on_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ portid_t port_id = res->port_id;
+ int en = (strcmp(res->en_on_off, "on") == 0) ? 1 : 0;
+ int rp = (strcmp(res->rp_on_off, "on") == 0) ? 1 : 0;
+ struct rte_eth_dev_info dev_info;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (!port_is_stopped(port_id)) {
+ printf("Please stop port %d first\n", port_id);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MACSEC_INSERT) {
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = rte_pmd_ixgbe_macsec_enable(port_id, en, rp);
+#endif
+ }
+ RTE_SET_USED(en);
+ RTE_SET_USED(rp);
+
+ switch (ret) {
+ case 0:
+ ports[port_id].dev_conf.txmode.offloads |=
+ DEV_TX_OFFLOAD_MACSEC_INSERT;
+ cmd_reconfig_device_queue(port_id, 1, 1);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("not supported on port %d\n", port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_on = {
+ .f = cmd_set_macsec_offload_on_parsed,
+ .data = NULL,
+ .help_str = "set macsec offload <port_id> on "
+ "encrypt on|off replay-protect on|off",
+ .tokens = {
+ (void *)&cmd_macsec_offload_on_set,
+ (void *)&cmd_macsec_offload_on_macsec,
+ (void *)&cmd_macsec_offload_on_offload,
+ (void *)&cmd_macsec_offload_on_port_id,
+ (void *)&cmd_macsec_offload_on_on,
+ (void *)&cmd_macsec_offload_on_encrypt,
+ (void *)&cmd_macsec_offload_on_en_on_off,
+ (void *)&cmd_macsec_offload_on_replay_protect,
+ (void *)&cmd_macsec_offload_on_rp_on_off,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec offload disable */
+struct cmd_macsec_offload_off_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t offload;
+ portid_t port_id;
+ cmdline_fixed_string_t off;
+};
+
+/* Common CLI fields for MACsec offload disable */
+cmdline_parse_token_string_t cmd_macsec_offload_off_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_offload_off_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_offload_off_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ offload, "offload");
+cmdline_parse_token_num_t cmd_macsec_offload_off_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_macsec_offload_off_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_offload_off_result,
+ off, "off");
+
+static void
+cmd_set_macsec_offload_off_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_macsec_offload_off_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (!port_is_stopped(port_id)) {
+ printf("Please stop port %d first\n", port_id);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MACSEC_INSERT) {
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = rte_pmd_ixgbe_macsec_disable(port_id);
+#endif
+ }
+ switch (ret) {
+ case 0:
+ ports[port_id].dev_conf.txmode.offloads &=
+ ~DEV_TX_OFFLOAD_MACSEC_INSERT;
+ cmd_reconfig_device_queue(port_id, 1, 1);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("not supported on port %d\n", port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_offload_off = {
+ .f = cmd_set_macsec_offload_off_parsed,
+ .data = NULL,
+ .help_str = "set macsec offload <port_id> off",
+ .tokens = {
+ (void *)&cmd_macsec_offload_off_set,
+ (void *)&cmd_macsec_offload_off_macsec,
+ (void *)&cmd_macsec_offload_off_offload,
+ (void *)&cmd_macsec_offload_off_port_id,
+ (void *)&cmd_macsec_offload_off_off,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t sc;
+ cmdline_fixed_string_t tx_rx;
+ portid_t port_id;
+ struct rte_ether_addr mac;
+ uint16_t pi;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_sc_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sc_sc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ sc, "sc");
+cmdline_parse_token_string_t cmd_macsec_sc_tx_rx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ port_id, UINT16);
+cmdline_parse_token_etheraddr_t cmd_macsec_sc_mac =
+ TOKEN_ETHERADDR_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ mac);
+cmdline_parse_token_num_t cmd_macsec_sc_pi =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sc_result,
+ pi, UINT16);
+
+static void
+cmd_set_macsec_sc_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_macsec_sc_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = is_tx ?
+ rte_pmd_ixgbe_macsec_config_txsc(res->port_id,
+ res->mac.addr_bytes) :
+ rte_pmd_ixgbe_macsec_config_rxsc(res->port_id,
+ res->mac.addr_bytes, res->pi);
+#endif
+ RTE_SET_USED(is_tx);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("not supported on port %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sc = {
+ .f = cmd_set_macsec_sc_parsed,
+ .data = NULL,
+ .help_str = "set macsec sc tx|rx <port_id> <mac> <pi>",
+ .tokens = {
+ (void *)&cmd_macsec_sc_set,
+ (void *)&cmd_macsec_sc_macsec,
+ (void *)&cmd_macsec_sc_sc,
+ (void *)&cmd_macsec_sc_tx_rx,
+ (void *)&cmd_macsec_sc_port_id,
+ (void *)&cmd_macsec_sc_mac,
+ (void *)&cmd_macsec_sc_pi,
+ NULL,
+ },
+};
+
+/* Common result structure for MACsec secure connection configure */
+struct cmd_macsec_sa_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t macsec;
+ cmdline_fixed_string_t sa;
+ cmdline_fixed_string_t tx_rx;
+ portid_t port_id;
+ uint8_t idx;
+ uint8_t an;
+ uint32_t pn;
+ cmdline_fixed_string_t key;
+};
+
+/* Common CLI fields for MACsec secure connection configure */
+cmdline_parse_token_string_t cmd_macsec_sa_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_macsec_sa_macsec =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ macsec, "macsec");
+cmdline_parse_token_string_t cmd_macsec_sa_sa =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ sa, "sa");
+cmdline_parse_token_string_t cmd_macsec_sa_tx_rx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ tx_rx, "tx#rx");
+cmdline_parse_token_num_t cmd_macsec_sa_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_macsec_sa_idx =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ idx, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_an =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ an, UINT8);
+cmdline_parse_token_num_t cmd_macsec_sa_pn =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ pn, UINT32);
+cmdline_parse_token_string_t cmd_macsec_sa_key =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_macsec_sa_result,
+ key, NULL);
+
+static void
+cmd_set_macsec_sa_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_macsec_sa_result *res = parsed_result;
+ int ret = -ENOTSUP;
+ int is_tx = (strcmp(res->tx_rx, "tx") == 0) ? 1 : 0;
+ uint8_t key[16] = { 0 };
+ uint8_t xdgt0;
+ uint8_t xdgt1;
+ int key_len;
+ int i;
+
+ key_len = strlen(res->key) / 2;
+ if (key_len > 16)
+ key_len = 16;
+
+ for (i = 0; i < key_len; i++) {
+ xdgt0 = parse_and_check_key_hexa_digit(res->key, (i * 2));
+ if (xdgt0 == 0xFF)
+ return;
+ xdgt1 = parse_and_check_key_hexa_digit(res->key, (i * 2) + 1);
+ if (xdgt1 == 0xFF)
+ return;
+ key[i] = (uint8_t) ((xdgt0 * 16) + xdgt1);
+ }
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = is_tx ?
+ rte_pmd_ixgbe_macsec_select_txsa(res->port_id,
+ res->idx, res->an, res->pn, key) :
+ rte_pmd_ixgbe_macsec_select_rxsa(res->port_id,
+ res->idx, res->an, res->pn, key);
+#endif
+ RTE_SET_USED(is_tx);
+ RTE_SET_USED(key);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid idx %d or an %d\n", res->idx, res->an);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("not supported on port %d\n", res->port_id);
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_macsec_sa = {
+ .f = cmd_set_macsec_sa_parsed,
+ .data = NULL,
+ .help_str = "set macsec sa tx|rx <port_id> <idx> <an> <pn> <key>",
+ .tokens = {
+ (void *)&cmd_macsec_sa_set,
+ (void *)&cmd_macsec_sa_macsec,
+ (void *)&cmd_macsec_sa_sa,
+ (void *)&cmd_macsec_sa_tx_rx,
+ (void *)&cmd_macsec_sa_port_id,
+ (void *)&cmd_macsec_sa_idx,
+ (void *)&cmd_macsec_sa_an,
+ (void *)&cmd_macsec_sa_pn,
+ (void *)&cmd_macsec_sa_key,
+ NULL,
+ },
+};
+
+/* VF unicast promiscuous mode configuration */
+
+/* Common result structure for VF unicast promiscuous mode */
+struct cmd_vf_promisc_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t promisc;
+ portid_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF unicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_promisc_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_promisc_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_promisc_promisc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ promisc, "promisc");
+cmdline_parse_token_num_t cmd_vf_promisc_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_promisc_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_promisc_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_promisc_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_promisc_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_promisc_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_unicast_promisc(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_promisc = {
+ .f = cmd_set_vf_promisc_parsed,
+ .data = NULL,
+ .help_str = "set vf promisc <port_id> <vf_id> on|off: "
+ "Set unicast promiscuous mode for a VF from the PF",
+ .tokens = {
+ (void *)&cmd_vf_promisc_set,
+ (void *)&cmd_vf_promisc_vf,
+ (void *)&cmd_vf_promisc_promisc,
+ (void *)&cmd_vf_promisc_port_id,
+ (void *)&cmd_vf_promisc_vf_id,
+ (void *)&cmd_vf_promisc_on_off,
+ NULL,
+ },
+};
+
+/* VF multicast promiscuous mode configuration */
+
+/* Common result structure for VF multicast promiscuous mode */
+struct cmd_vf_allmulti_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t allmulti;
+ portid_t port_id;
+ uint32_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for VF multicast promiscuous mode enable disable */
+cmdline_parse_token_string_t cmd_vf_allmulti_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_allmulti_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_allmulti_allmulti =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ allmulti, "allmulti");
+cmdline_parse_token_num_t cmd_vf_allmulti_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_allmulti_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ vf_id, UINT32);
+cmdline_parse_token_string_t cmd_vf_allmulti_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_allmulti_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_allmulti_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_allmulti_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_multicast_promisc(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_allmulti = {
+ .f = cmd_set_vf_allmulti_parsed,
+ .data = NULL,
+ .help_str = "set vf allmulti <port_id> <vf_id> on|off: "
+ "Set multicast promiscuous mode for a VF from the PF",
+ .tokens = {
+ (void *)&cmd_vf_allmulti_set,
+ (void *)&cmd_vf_allmulti_vf,
+ (void *)&cmd_vf_allmulti_allmulti,
+ (void *)&cmd_vf_allmulti_port_id,
+ (void *)&cmd_vf_allmulti_vf_id,
+ (void *)&cmd_vf_allmulti_on_off,
+ NULL,
+ },
+};
+
+/* vf broadcast mode configuration */
+
+/* Common result structure for vf broadcast */
+struct cmd_set_vf_broadcast_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t broadcast;
+ portid_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf broadcast enable disable */
+cmdline_parse_token_string_t cmd_set_vf_broadcast_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_broadcast_broadcast =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ broadcast, "broadcast");
+cmdline_parse_token_num_t cmd_set_vf_broadcast_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_vf_broadcast_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_broadcast_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_broadcast_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_broadcast_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_vf_broadcast_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_broadcast(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_broadcast = {
+ .f = cmd_set_vf_broadcast_parsed,
+ .data = NULL,
+ .help_str = "set vf broadcast <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_broadcast_set,
+ (void *)&cmd_set_vf_broadcast_vf,
+ (void *)&cmd_set_vf_broadcast_broadcast,
+ (void *)&cmd_set_vf_broadcast_port_id,
+ (void *)&cmd_set_vf_broadcast_vf_id,
+ (void *)&cmd_set_vf_broadcast_on_off,
+ NULL,
+ },
+};
+
+/* vf vlan tag configuration */
+
+/* Common result structure for vf vlan tag */
+struct cmd_set_vf_vlan_tag_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t vlan;
+ cmdline_fixed_string_t tag;
+ portid_t port_id;
+ uint16_t vf_id;
+ cmdline_fixed_string_t on_off;
+};
+
+/* Common CLI fields for vf vlan tag enable disable */
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_vlan =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vlan, "vlan");
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_tag =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ tag, "tag");
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_vf_vlan_tag_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ vf_id, UINT16);
+cmdline_parse_token_string_t cmd_set_vf_vlan_tag_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_vf_vlan_tag_result,
+ on_off, "on#off");
+
+static void
+cmd_set_vf_vlan_tag_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_vf_vlan_tag_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ __rte_unused int is_on = (strcmp(res->on_off, "on") == 0) ? 1 : 0;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_vlan_tag(res->port_id,
+ res->vf_id, is_on);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or is_on %d\n", res->vf_id, is_on);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_set_vf_vlan_tag = {
+ .f = cmd_set_vf_vlan_tag_parsed,
+ .data = NULL,
+ .help_str = "set vf vlan tag <port_id> <vf_id> on|off",
+ .tokens = {
+ (void *)&cmd_set_vf_vlan_tag_set,
+ (void *)&cmd_set_vf_vlan_tag_vf,
+ (void *)&cmd_set_vf_vlan_tag_vlan,
+ (void *)&cmd_set_vf_vlan_tag_tag,
+ (void *)&cmd_set_vf_vlan_tag_port_id,
+ (void *)&cmd_set_vf_vlan_tag_vf_id,
+ (void *)&cmd_set_vf_vlan_tag_on_off,
+ NULL,
+ },
+};
+
+/* Common definition of VF and TC TX bandwidth configuration */
+struct cmd_vf_tc_bw_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t tc;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t min_bw;
+ cmdline_fixed_string_t max_bw;
+ cmdline_fixed_string_t strict_link_prio;
+ portid_t port_id;
+ uint16_t vf_id;
+ uint8_t tc_no;
+ uint32_t bw;
+ cmdline_fixed_string_t bw_list;
+ uint8_t tc_map;
+};
+
+cmdline_parse_token_string_t cmd_vf_tc_bw_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_vf_tc_bw_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_vf_tc_bw_tc =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc, "tc");
+cmdline_parse_token_string_t cmd_vf_tc_bw_tx =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tx, "tx");
+cmdline_parse_token_string_t cmd_vf_tc_bw_strict_link_prio =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ strict_link_prio, "strict-link-priority");
+cmdline_parse_token_string_t cmd_vf_tc_bw_min_bw =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ min_bw, "min-bandwidth");
+cmdline_parse_token_string_t cmd_vf_tc_bw_max_bw =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ max_bw, "max-bandwidth");
+cmdline_parse_token_num_t cmd_vf_tc_bw_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_tc_bw_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ vf_id, UINT16);
+cmdline_parse_token_num_t cmd_vf_tc_bw_tc_no =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc_no, UINT8);
+cmdline_parse_token_num_t cmd_vf_tc_bw_bw =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ bw, UINT32);
+cmdline_parse_token_string_t cmd_vf_tc_bw_bw_list =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ bw_list, NULL);
+cmdline_parse_token_num_t cmd_vf_tc_bw_tc_map =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_vf_tc_bw_result,
+ tc_map, UINT8);
+
+/* VF max bandwidth setting */
+static void
+cmd_vf_max_bw_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_max_bw(res->port_id,
+ res->vf_id, res->bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or bandwidth %d\n",
+ res->vf_id, res->bw);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_max_bw = {
+ .f = cmd_vf_max_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tx max-bandwidth <port_id> <vf_id> <bandwidth>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_max_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_bw,
+ NULL,
+ },
+};
+
+static int
+vf_tc_min_bw_parse_bw_list(uint8_t *bw_list,
+ uint8_t *tc_num,
+ char *str)
+{
+ uint32_t size;
+ const char *p, *p0 = str;
+ char s[256];
+ char *end;
+ char *str_fld[16];
+ uint16_t i;
+ int ret;
+
+ p = strchr(p0, '(');
+ if (p == NULL) {
+ printf("The bandwidth-list should be '(bw1, bw2, ...)'\n");
+ return -1;
+ }
+ p++;
+ p0 = strchr(p, ')');
+ if (p0 == NULL) {
+ printf("The bandwidth-list should be '(bw1, bw2, ...)'\n");
+ return -1;
+ }
+ size = p0 - p;
+ if (size >= sizeof(s)) {
+ printf("The string size exceeds the internal buffer size\n");
+ return -1;
+ }
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, 16, ',');
+ if (ret <= 0) {
+ printf("Failed to get the bandwidth list. ");
+ return -1;
+ }
+ *tc_num = ret;
+ for (i = 0; i < ret; i++)
+ bw_list[i] = (uint8_t)strtoul(str_fld[i], &end, 0);
+
+ return 0;
+}
+
+/* TC min bandwidth setting */
+static void
+cmd_vf_tc_min_bw_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ uint8_t tc_num;
+ uint8_t bw[16];
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ ret = vf_tc_min_bw_parse_bw_list(bw, &tc_num, res->bw_list);
+ if (ret)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_tc_bw_alloc(res->port_id, res->vf_id,
+ tc_num, bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d or bandwidth\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_tc_min_bw = {
+ .f = cmd_vf_tc_min_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tc tx min-bandwidth <port_id> <vf_id>"
+ " <bw1, bw2, ...>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_min_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_bw_list,
+ NULL,
+ },
+};
+
+static void
+cmd_tc_min_bw_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ struct rte_port *port;
+ uint8_t tc_num;
+ uint8_t bw[16];
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[res->port_id];
+ /** Check if the port is not started **/
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Please stop port %d first\n", res->port_id);
+ return;
+ }
+
+ ret = vf_tc_min_bw_parse_bw_list(bw, &tc_num, res->bw_list);
+ if (ret)
+ return;
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ ret = rte_pmd_ixgbe_set_tc_bw_alloc(res->port_id, tc_num, bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid bandwidth\n");
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_tc_min_bw = {
+ .f = cmd_tc_min_bw_parsed,
+ .data = NULL,
+ .help_str = "set tc tx min-bandwidth <port_id> <bw1, bw2, ...>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_min_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_bw_list,
+ NULL,
+ },
+};
+
+/* TC max bandwidth setting */
+static void
+cmd_vf_tc_max_bw_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_vf_tc_max_bw(res->port_id, res->vf_id,
+ res->tc_no, res->bw);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d, tc_no %d or bandwidth %d\n",
+ res->vf_id, res->tc_no, res->bw);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_vf_tc_max_bw = {
+ .f = cmd_vf_tc_max_bw_parsed,
+ .data = NULL,
+ .help_str = "set vf tc tx max-bandwidth <port_id> <vf_id> <tc_no>"
+ " <bandwidth>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_vf,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_max_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_vf_id,
+ (void *)&cmd_vf_tc_bw_tc_no,
+ (void *)&cmd_vf_tc_bw_bw,
+ NULL,
+ },
+};
+
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
+
+/* *** Set Port default Traffic Management Hierarchy *** */
+struct cmd_set_port_tm_hierarchy_default_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t hierarchy;
+ cmdline_fixed_string_t def;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result, tm, "tm");
+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_hierarchy =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result,
+ hierarchy, "hierarchy");
+cmdline_parse_token_string_t cmd_set_port_tm_hierarchy_default_default =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result,
+ def, "default");
+cmdline_parse_token_num_t cmd_set_port_tm_hierarchy_default_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_tm_hierarchy_default_result,
+ port_id, UINT16);
+
+static void cmd_set_port_tm_hierarchy_default_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_tm_hierarchy_default_result *res = parsed_result;
+ struct rte_port *p;
+ portid_t port_id = res->port_id;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ p = &ports[port_id];
+
+ /* Forward mode: tm */
+ if (strcmp(cur_fwd_config.fwd_eng->fwd_mode_name, "softnic")) {
+ printf(" softnicfwd mode not enabled(error)\n");
+ return;
+ }
+
+ /* Set the default tm hierarchy */
+ p->softport.default_tm_hierarchy_enable = 1;
+}
+
+cmdline_parse_inst_t cmd_set_port_tm_hierarchy_default = {
+ .f = cmd_set_port_tm_hierarchy_default_parsed,
+ .data = NULL,
+ .help_str = "set port tm hierarchy default <port_id>",
+ .tokens = {
+ (void *)&cmd_set_port_tm_hierarchy_default_set,
+ (void *)&cmd_set_port_tm_hierarchy_default_port,
+ (void *)&cmd_set_port_tm_hierarchy_default_tm,
+ (void *)&cmd_set_port_tm_hierarchy_default_hierarchy,
+ (void *)&cmd_set_port_tm_hierarchy_default_default,
+ (void *)&cmd_set_port_tm_hierarchy_default_port_id,
+ NULL,
+ },
+};
+#endif
+
+/** Set VXLAN encapsulation details */
+struct cmd_set_vxlan_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t vxlan;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+ uint32_t vni;
+ uint16_t udp_src;
+ uint16_t udp_dst;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t tci;
+ uint8_t tos;
+ uint8_t ttl;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_vxlan_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, set, "set");
+cmdline_parse_token_string_t cmd_set_vxlan_vxlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, vxlan, "vxlan");
+cmdline_parse_token_string_t cmd_set_vxlan_vxlan_tos_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, vxlan,
+ "vxlan-tos-ttl");
+cmdline_parse_token_string_t cmd_set_vxlan_vxlan_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, vxlan,
+ "vxlan-with-vlan");
+cmdline_parse_token_string_t cmd_set_vxlan_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "ip-version");
+cmdline_parse_token_string_t cmd_set_vxlan_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, ip_version,
+ "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_vxlan_vni =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "vni");
+cmdline_parse_token_num_t cmd_set_vxlan_vni_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, vni, UINT32);
+cmdline_parse_token_string_t cmd_set_vxlan_udp_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "udp-src");
+cmdline_parse_token_num_t cmd_set_vxlan_udp_src_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, udp_src, UINT16);
+cmdline_parse_token_string_t cmd_set_vxlan_udp_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "udp-dst");
+cmdline_parse_token_num_t cmd_set_vxlan_udp_dst_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, udp_dst, UINT16);
+cmdline_parse_token_string_t cmd_set_vxlan_ip_tos =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "ip-tos");
+cmdline_parse_token_num_t cmd_set_vxlan_ip_tos_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, tos, UINT8);
+cmdline_parse_token_string_t cmd_set_vxlan_ip_ttl =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "ip-ttl");
+cmdline_parse_token_num_t cmd_set_vxlan_ip_ttl_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, ttl, UINT8);
+cmdline_parse_token_string_t cmd_set_vxlan_ip_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "ip-src");
+cmdline_parse_token_ipaddr_t cmd_set_vxlan_ip_src_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_vxlan_result, ip_src);
+cmdline_parse_token_string_t cmd_set_vxlan_ip_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "ip-dst");
+cmdline_parse_token_ipaddr_t cmd_set_vxlan_ip_dst_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_vxlan_result, ip_dst);
+cmdline_parse_token_string_t cmd_set_vxlan_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "vlan-tci");
+cmdline_parse_token_num_t cmd_set_vxlan_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_vxlan_result, tci, UINT16);
+cmdline_parse_token_string_t cmd_set_vxlan_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_vxlan_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vxlan_result, eth_src);
+cmdline_parse_token_string_t cmd_set_vxlan_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_vxlan_result, pos_token,
+ "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_vxlan_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_vxlan_result, eth_dst);
+
+static void cmd_set_vxlan_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_vxlan_result *res = parsed_result;
+ union {
+ uint32_t vxlan_id;
+ uint8_t vni[4];
+ } id = {
+ .vxlan_id = rte_cpu_to_be_32(res->vni) & RTE_BE32(0x00ffffff),
+ };
+
+ vxlan_encap_conf.select_tos_ttl = 0;
+ if (strcmp(res->vxlan, "vxlan") == 0)
+ vxlan_encap_conf.select_vlan = 0;
+ else if (strcmp(res->vxlan, "vxlan-with-vlan") == 0)
+ vxlan_encap_conf.select_vlan = 1;
+ else if (strcmp(res->vxlan, "vxlan-tos-ttl") == 0) {
+ vxlan_encap_conf.select_vlan = 0;
+ vxlan_encap_conf.select_tos_ttl = 1;
+ }
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ vxlan_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ vxlan_encap_conf.select_ipv4 = 0;
+ else
+ return;
+ rte_memcpy(vxlan_encap_conf.vni, &id.vni[1], 3);
+ vxlan_encap_conf.udp_src = rte_cpu_to_be_16(res->udp_src);
+ vxlan_encap_conf.udp_dst = rte_cpu_to_be_16(res->udp_dst);
+ vxlan_encap_conf.ip_tos = res->tos;
+ vxlan_encap_conf.ip_ttl = res->ttl;
+ if (vxlan_encap_conf.select_ipv4) {
+ IPV4_ADDR_TO_UINT(res->ip_src, vxlan_encap_conf.ipv4_src);
+ IPV4_ADDR_TO_UINT(res->ip_dst, vxlan_encap_conf.ipv4_dst);
+ } else {
+ IPV6_ADDR_TO_ARRAY(res->ip_src, vxlan_encap_conf.ipv6_src);
+ IPV6_ADDR_TO_ARRAY(res->ip_dst, vxlan_encap_conf.ipv6_dst);
+ }
+ if (vxlan_encap_conf.select_vlan)
+ vxlan_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(vxlan_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(vxlan_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_vxlan = {
+ .f = cmd_set_vxlan_parsed,
+ .data = NULL,
+ .help_str = "set vxlan ip-version ipv4|ipv6 vni <vni> udp-src"
+ " <udp-src> udp-dst <udp-dst> ip-src <ip-src> ip-dst <ip-dst>"
+ " eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_vxlan_set,
+ (void *)&cmd_set_vxlan_vxlan,
+ (void *)&cmd_set_vxlan_ip_version,
+ (void *)&cmd_set_vxlan_ip_version_value,
+ (void *)&cmd_set_vxlan_vni,
+ (void *)&cmd_set_vxlan_vni_value,
+ (void *)&cmd_set_vxlan_udp_src,
+ (void *)&cmd_set_vxlan_udp_src_value,
+ (void *)&cmd_set_vxlan_udp_dst,
+ (void *)&cmd_set_vxlan_udp_dst_value,
+ (void *)&cmd_set_vxlan_ip_src,
+ (void *)&cmd_set_vxlan_ip_src_value,
+ (void *)&cmd_set_vxlan_ip_dst,
+ (void *)&cmd_set_vxlan_ip_dst_value,
+ (void *)&cmd_set_vxlan_eth_src,
+ (void *)&cmd_set_vxlan_eth_src_value,
+ (void *)&cmd_set_vxlan_eth_dst,
+ (void *)&cmd_set_vxlan_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_vxlan_tos_ttl = {
+ .f = cmd_set_vxlan_parsed,
+ .data = NULL,
+ .help_str = "set vxlan-tos-ttl ip-version ipv4|ipv6 vni <vni> udp-src"
+ " <udp-src> udp-dst <udp-dst> ip-tos <ip-tos> ip-ttl <ip-ttl>"
+ " ip-src <ip-src> ip-dst <ip-dst> eth-src <eth-src>"
+ " eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_vxlan_set,
+ (void *)&cmd_set_vxlan_vxlan_tos_ttl,
+ (void *)&cmd_set_vxlan_ip_version,
+ (void *)&cmd_set_vxlan_ip_version_value,
+ (void *)&cmd_set_vxlan_vni,
+ (void *)&cmd_set_vxlan_vni_value,
+ (void *)&cmd_set_vxlan_udp_src,
+ (void *)&cmd_set_vxlan_udp_src_value,
+ (void *)&cmd_set_vxlan_udp_dst,
+ (void *)&cmd_set_vxlan_udp_dst_value,
+ (void *)&cmd_set_vxlan_ip_tos,
+ (void *)&cmd_set_vxlan_ip_tos_value,
+ (void *)&cmd_set_vxlan_ip_ttl,
+ (void *)&cmd_set_vxlan_ip_ttl_value,
+ (void *)&cmd_set_vxlan_ip_src,
+ (void *)&cmd_set_vxlan_ip_src_value,
+ (void *)&cmd_set_vxlan_ip_dst,
+ (void *)&cmd_set_vxlan_ip_dst_value,
+ (void *)&cmd_set_vxlan_eth_src,
+ (void *)&cmd_set_vxlan_eth_src_value,
+ (void *)&cmd_set_vxlan_eth_dst,
+ (void *)&cmd_set_vxlan_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_vxlan_with_vlan = {
+ .f = cmd_set_vxlan_parsed,
+ .data = NULL,
+ .help_str = "set vxlan-with-vlan ip-version ipv4|ipv6 vni <vni>"
+ " udp-src <udp-src> udp-dst <udp-dst> ip-src <ip-src> ip-dst"
+ " <ip-dst> vlan-tci <vlan-tci> eth-src <eth-src> eth-dst"
+ " <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_vxlan_set,
+ (void *)&cmd_set_vxlan_vxlan_with_vlan,
+ (void *)&cmd_set_vxlan_ip_version,
+ (void *)&cmd_set_vxlan_ip_version_value,
+ (void *)&cmd_set_vxlan_vni,
+ (void *)&cmd_set_vxlan_vni_value,
+ (void *)&cmd_set_vxlan_udp_src,
+ (void *)&cmd_set_vxlan_udp_src_value,
+ (void *)&cmd_set_vxlan_udp_dst,
+ (void *)&cmd_set_vxlan_udp_dst_value,
+ (void *)&cmd_set_vxlan_ip_src,
+ (void *)&cmd_set_vxlan_ip_src_value,
+ (void *)&cmd_set_vxlan_ip_dst,
+ (void *)&cmd_set_vxlan_ip_dst_value,
+ (void *)&cmd_set_vxlan_vlan,
+ (void *)&cmd_set_vxlan_vlan_value,
+ (void *)&cmd_set_vxlan_eth_src,
+ (void *)&cmd_set_vxlan_eth_src_value,
+ (void *)&cmd_set_vxlan_eth_dst,
+ (void *)&cmd_set_vxlan_eth_dst_value,
+ NULL,
+ },
+};
+
+/** Set NVGRE encapsulation details */
+struct cmd_set_nvgre_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t nvgre;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t tni;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t tci;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_nvgre_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, set, "set");
+cmdline_parse_token_string_t cmd_set_nvgre_nvgre =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, nvgre, "nvgre");
+cmdline_parse_token_string_t cmd_set_nvgre_nvgre_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, nvgre,
+ "nvgre-with-vlan");
+cmdline_parse_token_string_t cmd_set_nvgre_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "ip-version");
+cmdline_parse_token_string_t cmd_set_nvgre_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, ip_version,
+ "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_nvgre_tni =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "tni");
+cmdline_parse_token_num_t cmd_set_nvgre_tni_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_nvgre_result, tni, UINT32);
+cmdline_parse_token_string_t cmd_set_nvgre_ip_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "ip-src");
+cmdline_parse_token_num_t cmd_set_nvgre_ip_src_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_nvgre_result, ip_src);
+cmdline_parse_token_string_t cmd_set_nvgre_ip_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "ip-dst");
+cmdline_parse_token_ipaddr_t cmd_set_nvgre_ip_dst_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_nvgre_result, ip_dst);
+cmdline_parse_token_string_t cmd_set_nvgre_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "vlan-tci");
+cmdline_parse_token_num_t cmd_set_nvgre_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_nvgre_result, tci, UINT16);
+cmdline_parse_token_string_t cmd_set_nvgre_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_nvgre_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_nvgre_result, eth_src);
+cmdline_parse_token_string_t cmd_set_nvgre_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_nvgre_result, pos_token,
+ "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_nvgre_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_nvgre_result, eth_dst);
+
+static void cmd_set_nvgre_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_nvgre_result *res = parsed_result;
+ union {
+ uint32_t nvgre_tni;
+ uint8_t tni[4];
+ } id = {
+ .nvgre_tni = rte_cpu_to_be_32(res->tni) & RTE_BE32(0x00ffffff),
+ };
+
+ if (strcmp(res->nvgre, "nvgre") == 0)
+ nvgre_encap_conf.select_vlan = 0;
+ else if (strcmp(res->nvgre, "nvgre-with-vlan") == 0)
+ nvgre_encap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ nvgre_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ nvgre_encap_conf.select_ipv4 = 0;
+ else
+ return;
+ rte_memcpy(nvgre_encap_conf.tni, &id.tni[1], 3);
+ if (nvgre_encap_conf.select_ipv4) {
+ IPV4_ADDR_TO_UINT(res->ip_src, nvgre_encap_conf.ipv4_src);
+ IPV4_ADDR_TO_UINT(res->ip_dst, nvgre_encap_conf.ipv4_dst);
+ } else {
+ IPV6_ADDR_TO_ARRAY(res->ip_src, nvgre_encap_conf.ipv6_src);
+ IPV6_ADDR_TO_ARRAY(res->ip_dst, nvgre_encap_conf.ipv6_dst);
+ }
+ if (nvgre_encap_conf.select_vlan)
+ nvgre_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(nvgre_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(nvgre_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_nvgre = {
+ .f = cmd_set_nvgre_parsed,
+ .data = NULL,
+ .help_str = "set nvgre ip-version <ipv4|ipv6> tni <tni> ip-src"
+ " <ip-src> ip-dst <ip-dst> eth-src <eth-src>"
+ " eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_nvgre_set,
+ (void *)&cmd_set_nvgre_nvgre,
+ (void *)&cmd_set_nvgre_ip_version,
+ (void *)&cmd_set_nvgre_ip_version_value,
+ (void *)&cmd_set_nvgre_tni,
+ (void *)&cmd_set_nvgre_tni_value,
+ (void *)&cmd_set_nvgre_ip_src,
+ (void *)&cmd_set_nvgre_ip_src_value,
+ (void *)&cmd_set_nvgre_ip_dst,
+ (void *)&cmd_set_nvgre_ip_dst_value,
+ (void *)&cmd_set_nvgre_eth_src,
+ (void *)&cmd_set_nvgre_eth_src_value,
+ (void *)&cmd_set_nvgre_eth_dst,
+ (void *)&cmd_set_nvgre_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_nvgre_with_vlan = {
+ .f = cmd_set_nvgre_parsed,
+ .data = NULL,
+ .help_str = "set nvgre-with-vlan ip-version <ipv4|ipv6> tni <tni>"
+ " ip-src <ip-src> ip-dst <ip-dst> vlan-tci <vlan-tci>"
+ " eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_nvgre_set,
+ (void *)&cmd_set_nvgre_nvgre_with_vlan,
+ (void *)&cmd_set_nvgre_ip_version,
+ (void *)&cmd_set_nvgre_ip_version_value,
+ (void *)&cmd_set_nvgre_tni,
+ (void *)&cmd_set_nvgre_tni_value,
+ (void *)&cmd_set_nvgre_ip_src,
+ (void *)&cmd_set_nvgre_ip_src_value,
+ (void *)&cmd_set_nvgre_ip_dst,
+ (void *)&cmd_set_nvgre_ip_dst_value,
+ (void *)&cmd_set_nvgre_vlan,
+ (void *)&cmd_set_nvgre_vlan_value,
+ (void *)&cmd_set_nvgre_eth_src,
+ (void *)&cmd_set_nvgre_eth_src_value,
+ (void *)&cmd_set_nvgre_eth_dst,
+ (void *)&cmd_set_nvgre_eth_dst_value,
+ NULL,
+ },
+};
+
+/** Set L2 encapsulation details */
+struct cmd_set_l2_encap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t l2_encap;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+ uint16_t tci;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_l2_encap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, set, "set");
+cmdline_parse_token_string_t cmd_set_l2_encap_l2_encap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, l2_encap, "l2_encap");
+cmdline_parse_token_string_t cmd_set_l2_encap_l2_encap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, l2_encap,
+ "l2_encap-with-vlan");
+cmdline_parse_token_string_t cmd_set_l2_encap_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, pos_token,
+ "ip-version");
+cmdline_parse_token_string_t cmd_set_l2_encap_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, ip_version,
+ "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_l2_encap_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, pos_token,
+ "vlan-tci");
+cmdline_parse_token_num_t cmd_set_l2_encap_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_l2_encap_result, tci, UINT16);
+cmdline_parse_token_string_t cmd_set_l2_encap_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, pos_token,
+ "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_l2_encap_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2_encap_result, eth_src);
+cmdline_parse_token_string_t cmd_set_l2_encap_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_encap_result, pos_token,
+ "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_l2_encap_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2_encap_result, eth_dst);
+
+static void cmd_set_l2_encap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_l2_encap_result *res = parsed_result;
+
+ if (strcmp(res->l2_encap, "l2_encap") == 0)
+ l2_encap_conf.select_vlan = 0;
+ else if (strcmp(res->l2_encap, "l2_encap-with-vlan") == 0)
+ l2_encap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ l2_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ l2_encap_conf.select_ipv4 = 0;
+ else
+ return;
+ if (l2_encap_conf.select_vlan)
+ l2_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(l2_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(l2_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_l2_encap = {
+ .f = cmd_set_l2_encap_parsed,
+ .data = NULL,
+ .help_str = "set l2_encap ip-version ipv4|ipv6"
+ " eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_l2_encap_set,
+ (void *)&cmd_set_l2_encap_l2_encap,
+ (void *)&cmd_set_l2_encap_ip_version,
+ (void *)&cmd_set_l2_encap_ip_version_value,
+ (void *)&cmd_set_l2_encap_eth_src,
+ (void *)&cmd_set_l2_encap_eth_src_value,
+ (void *)&cmd_set_l2_encap_eth_dst,
+ (void *)&cmd_set_l2_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_l2_encap_with_vlan = {
+ .f = cmd_set_l2_encap_parsed,
+ .data = NULL,
+ .help_str = "set l2_encap-with-vlan ip-version ipv4|ipv6"
+ " vlan-tci <vlan-tci> eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_l2_encap_set,
+ (void *)&cmd_set_l2_encap_l2_encap_with_vlan,
+ (void *)&cmd_set_l2_encap_ip_version,
+ (void *)&cmd_set_l2_encap_ip_version_value,
+ (void *)&cmd_set_l2_encap_vlan,
+ (void *)&cmd_set_l2_encap_vlan_value,
+ (void *)&cmd_set_l2_encap_eth_src,
+ (void *)&cmd_set_l2_encap_eth_src_value,
+ (void *)&cmd_set_l2_encap_eth_dst,
+ (void *)&cmd_set_l2_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+/** Set L2 decapsulation details */
+struct cmd_set_l2_decap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t l2_decap;
+ cmdline_fixed_string_t pos_token;
+ uint32_t vlan_present:1;
+};
+
+cmdline_parse_token_string_t cmd_set_l2_decap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_decap_result, set, "set");
+cmdline_parse_token_string_t cmd_set_l2_decap_l2_decap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_decap_result, l2_decap,
+ "l2_decap");
+cmdline_parse_token_string_t cmd_set_l2_decap_l2_decap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_l2_decap_result, l2_decap,
+ "l2_decap-with-vlan");
+
+static void cmd_set_l2_decap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_l2_decap_result *res = parsed_result;
+
+ if (strcmp(res->l2_decap, "l2_decap") == 0)
+ l2_decap_conf.select_vlan = 0;
+ else if (strcmp(res->l2_decap, "l2_decap-with-vlan") == 0)
+ l2_decap_conf.select_vlan = 1;
+}
+
+cmdline_parse_inst_t cmd_set_l2_decap = {
+ .f = cmd_set_l2_decap_parsed,
+ .data = NULL,
+ .help_str = "set l2_decap",
+ .tokens = {
+ (void *)&cmd_set_l2_decap_set,
+ (void *)&cmd_set_l2_decap_l2_decap,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_l2_decap_with_vlan = {
+ .f = cmd_set_l2_decap_parsed,
+ .data = NULL,
+ .help_str = "set l2_decap-with-vlan",
+ .tokens = {
+ (void *)&cmd_set_l2_decap_set,
+ (void *)&cmd_set_l2_decap_l2_decap_with_vlan,
+ NULL,
+ },
+};
+
+/** Set MPLSoGRE encapsulation details */
+struct cmd_set_mplsogre_encap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mplsogre;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+ uint32_t label;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t tci;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result, set,
+ "set");
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_mplsogre_encap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result, mplsogre,
+ "mplsogre_encap");
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_mplsogre_encap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ mplsogre, "mplsogre_encap-with-vlan");
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "ip-version");
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ ip_version, "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_label =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "label");
+cmdline_parse_token_num_t cmd_set_mplsogre_encap_label_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsogre_encap_result, label,
+ UINT32);
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_ip_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "ip-src");
+cmdline_parse_token_ipaddr_t cmd_set_mplsogre_encap_ip_src_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_mplsogre_encap_result, ip_src);
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_ip_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "ip-dst");
+cmdline_parse_token_ipaddr_t cmd_set_mplsogre_encap_ip_dst_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_mplsogre_encap_result, ip_dst);
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "vlan-tci");
+cmdline_parse_token_num_t cmd_set_mplsogre_encap_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsogre_encap_result, tci,
+ UINT16);
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_mplsogre_encap_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ eth_src);
+cmdline_parse_token_string_t cmd_set_mplsogre_encap_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ pos_token, "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_mplsogre_encap_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_mplsogre_encap_result,
+ eth_dst);
+
+static void cmd_set_mplsogre_encap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_mplsogre_encap_result *res = parsed_result;
+ union {
+ uint32_t mplsogre_label;
+ uint8_t label[4];
+ } id = {
+ .mplsogre_label = rte_cpu_to_be_32(res->label<<12),
+ };
+
+ if (strcmp(res->mplsogre, "mplsogre_encap") == 0)
+ mplsogre_encap_conf.select_vlan = 0;
+ else if (strcmp(res->mplsogre, "mplsogre_encap-with-vlan") == 0)
+ mplsogre_encap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ mplsogre_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ mplsogre_encap_conf.select_ipv4 = 0;
+ else
+ return;
+ rte_memcpy(mplsogre_encap_conf.label, &id.label, 3);
+ if (mplsogre_encap_conf.select_ipv4) {
+ IPV4_ADDR_TO_UINT(res->ip_src, mplsogre_encap_conf.ipv4_src);
+ IPV4_ADDR_TO_UINT(res->ip_dst, mplsogre_encap_conf.ipv4_dst);
+ } else {
+ IPV6_ADDR_TO_ARRAY(res->ip_src, mplsogre_encap_conf.ipv6_src);
+ IPV6_ADDR_TO_ARRAY(res->ip_dst, mplsogre_encap_conf.ipv6_dst);
+ }
+ if (mplsogre_encap_conf.select_vlan)
+ mplsogre_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(mplsogre_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(mplsogre_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_mplsogre_encap = {
+ .f = cmd_set_mplsogre_encap_parsed,
+ .data = NULL,
+ .help_str = "set mplsogre_encap ip-version ipv4|ipv6 label <label>"
+ " ip-src <ip-src> ip-dst <ip-dst> eth-src <eth-src>"
+ " eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_mplsogre_encap_set,
+ (void *)&cmd_set_mplsogre_encap_mplsogre_encap,
+ (void *)&cmd_set_mplsogre_encap_ip_version,
+ (void *)&cmd_set_mplsogre_encap_ip_version_value,
+ (void *)&cmd_set_mplsogre_encap_label,
+ (void *)&cmd_set_mplsogre_encap_label_value,
+ (void *)&cmd_set_mplsogre_encap_ip_src,
+ (void *)&cmd_set_mplsogre_encap_ip_src_value,
+ (void *)&cmd_set_mplsogre_encap_ip_dst,
+ (void *)&cmd_set_mplsogre_encap_ip_dst_value,
+ (void *)&cmd_set_mplsogre_encap_eth_src,
+ (void *)&cmd_set_mplsogre_encap_eth_src_value,
+ (void *)&cmd_set_mplsogre_encap_eth_dst,
+ (void *)&cmd_set_mplsogre_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_mplsogre_encap_with_vlan = {
+ .f = cmd_set_mplsogre_encap_parsed,
+ .data = NULL,
+ .help_str = "set mplsogre_encap-with-vlan ip-version ipv4|ipv6"
+ " label <label> ip-src <ip-src> ip-dst <ip-dst>"
+ " vlan-tci <vlan-tci> eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_mplsogre_encap_set,
+ (void *)&cmd_set_mplsogre_encap_mplsogre_encap_with_vlan,
+ (void *)&cmd_set_mplsogre_encap_ip_version,
+ (void *)&cmd_set_mplsogre_encap_ip_version_value,
+ (void *)&cmd_set_mplsogre_encap_label,
+ (void *)&cmd_set_mplsogre_encap_label_value,
+ (void *)&cmd_set_mplsogre_encap_ip_src,
+ (void *)&cmd_set_mplsogre_encap_ip_src_value,
+ (void *)&cmd_set_mplsogre_encap_ip_dst,
+ (void *)&cmd_set_mplsogre_encap_ip_dst_value,
+ (void *)&cmd_set_mplsogre_encap_vlan,
+ (void *)&cmd_set_mplsogre_encap_vlan_value,
+ (void *)&cmd_set_mplsogre_encap_eth_src,
+ (void *)&cmd_set_mplsogre_encap_eth_src_value,
+ (void *)&cmd_set_mplsogre_encap_eth_dst,
+ (void *)&cmd_set_mplsogre_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+/** Set MPLSoGRE decapsulation details */
+struct cmd_set_mplsogre_decap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mplsogre;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+};
+
+cmdline_parse_token_string_t cmd_set_mplsogre_decap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_decap_result, set,
+ "set");
+cmdline_parse_token_string_t cmd_set_mplsogre_decap_mplsogre_decap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_decap_result, mplsogre,
+ "mplsogre_decap");
+cmdline_parse_token_string_t cmd_set_mplsogre_decap_mplsogre_decap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_decap_result,
+ mplsogre, "mplsogre_decap-with-vlan");
+cmdline_parse_token_string_t cmd_set_mplsogre_decap_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_decap_result,
+ pos_token, "ip-version");
+cmdline_parse_token_string_t cmd_set_mplsogre_decap_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsogre_decap_result,
+ ip_version, "ipv4#ipv6");
+
+static void cmd_set_mplsogre_decap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_mplsogre_decap_result *res = parsed_result;
+
+ if (strcmp(res->mplsogre, "mplsogre_decap") == 0)
+ mplsogre_decap_conf.select_vlan = 0;
+ else if (strcmp(res->mplsogre, "mplsogre_decap-with-vlan") == 0)
+ mplsogre_decap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ mplsogre_decap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ mplsogre_decap_conf.select_ipv4 = 0;
+}
+
+cmdline_parse_inst_t cmd_set_mplsogre_decap = {
+ .f = cmd_set_mplsogre_decap_parsed,
+ .data = NULL,
+ .help_str = "set mplsogre_decap ip-version ipv4|ipv6",
+ .tokens = {
+ (void *)&cmd_set_mplsogre_decap_set,
+ (void *)&cmd_set_mplsogre_decap_mplsogre_decap,
+ (void *)&cmd_set_mplsogre_decap_ip_version,
+ (void *)&cmd_set_mplsogre_decap_ip_version_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_mplsogre_decap_with_vlan = {
+ .f = cmd_set_mplsogre_decap_parsed,
+ .data = NULL,
+ .help_str = "set mplsogre_decap-with-vlan ip-version ipv4|ipv6",
+ .tokens = {
+ (void *)&cmd_set_mplsogre_decap_set,
+ (void *)&cmd_set_mplsogre_decap_mplsogre_decap_with_vlan,
+ (void *)&cmd_set_mplsogre_decap_ip_version,
+ (void *)&cmd_set_mplsogre_decap_ip_version_value,
+ NULL,
+ },
+};
+
+/** Set MPLSoUDP encapsulation details */
+struct cmd_set_mplsoudp_encap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mplsoudp;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+ uint32_t label;
+ uint16_t udp_src;
+ uint16_t udp_dst;
+ cmdline_ipaddr_t ip_src;
+ cmdline_ipaddr_t ip_dst;
+ uint16_t tci;
+ struct rte_ether_addr eth_src;
+ struct rte_ether_addr eth_dst;
+};
+
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result, set,
+ "set");
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_mplsoudp_encap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result, mplsoudp,
+ "mplsoudp_encap");
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_mplsoudp_encap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ mplsoudp, "mplsoudp_encap-with-vlan");
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "ip-version");
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ ip_version, "ipv4#ipv6");
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_label =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "label");
+cmdline_parse_token_num_t cmd_set_mplsoudp_encap_label_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsoudp_encap_result, label,
+ UINT32);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_udp_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "udp-src");
+cmdline_parse_token_num_t cmd_set_mplsoudp_encap_udp_src_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsoudp_encap_result, udp_src,
+ UINT16);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_udp_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "udp-dst");
+cmdline_parse_token_num_t cmd_set_mplsoudp_encap_udp_dst_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsoudp_encap_result, udp_dst,
+ UINT16);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_ip_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "ip-src");
+cmdline_parse_token_ipaddr_t cmd_set_mplsoudp_encap_ip_src_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_mplsoudp_encap_result, ip_src);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_ip_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "ip-dst");
+cmdline_parse_token_ipaddr_t cmd_set_mplsoudp_encap_ip_dst_value =
+ TOKEN_IPADDR_INITIALIZER(struct cmd_set_mplsoudp_encap_result, ip_dst);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "vlan-tci");
+cmdline_parse_token_num_t cmd_set_mplsoudp_encap_vlan_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_mplsoudp_encap_result, tci,
+ UINT16);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_eth_src =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "eth-src");
+cmdline_parse_token_etheraddr_t cmd_set_mplsoudp_encap_eth_src_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ eth_src);
+cmdline_parse_token_string_t cmd_set_mplsoudp_encap_eth_dst =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ pos_token, "eth-dst");
+cmdline_parse_token_etheraddr_t cmd_set_mplsoudp_encap_eth_dst_value =
+ TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_mplsoudp_encap_result,
+ eth_dst);
+
+static void cmd_set_mplsoudp_encap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_mplsoudp_encap_result *res = parsed_result;
+ union {
+ uint32_t mplsoudp_label;
+ uint8_t label[4];
+ } id = {
+ .mplsoudp_label = rte_cpu_to_be_32(res->label<<12),
+ };
+
+ if (strcmp(res->mplsoudp, "mplsoudp_encap") == 0)
+ mplsoudp_encap_conf.select_vlan = 0;
+ else if (strcmp(res->mplsoudp, "mplsoudp_encap-with-vlan") == 0)
+ mplsoudp_encap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ mplsoudp_encap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ mplsoudp_encap_conf.select_ipv4 = 0;
+ else
+ return;
+ rte_memcpy(mplsoudp_encap_conf.label, &id.label, 3);
+ mplsoudp_encap_conf.udp_src = rte_cpu_to_be_16(res->udp_src);
+ mplsoudp_encap_conf.udp_dst = rte_cpu_to_be_16(res->udp_dst);
+ if (mplsoudp_encap_conf.select_ipv4) {
+ IPV4_ADDR_TO_UINT(res->ip_src, mplsoudp_encap_conf.ipv4_src);
+ IPV4_ADDR_TO_UINT(res->ip_dst, mplsoudp_encap_conf.ipv4_dst);
+ } else {
+ IPV6_ADDR_TO_ARRAY(res->ip_src, mplsoudp_encap_conf.ipv6_src);
+ IPV6_ADDR_TO_ARRAY(res->ip_dst, mplsoudp_encap_conf.ipv6_dst);
+ }
+ if (mplsoudp_encap_conf.select_vlan)
+ mplsoudp_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci);
+ rte_memcpy(mplsoudp_encap_conf.eth_src, res->eth_src.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ rte_memcpy(mplsoudp_encap_conf.eth_dst, res->eth_dst.addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+}
+
+cmdline_parse_inst_t cmd_set_mplsoudp_encap = {
+ .f = cmd_set_mplsoudp_encap_parsed,
+ .data = NULL,
+ .help_str = "set mplsoudp_encap ip-version ipv4|ipv6 label <label>"
+ " udp-src <udp-src> udp-dst <udp-dst> ip-src <ip-src>"
+ " ip-dst <ip-dst> eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_mplsoudp_encap_set,
+ (void *)&cmd_set_mplsoudp_encap_mplsoudp_encap,
+ (void *)&cmd_set_mplsoudp_encap_ip_version,
+ (void *)&cmd_set_mplsoudp_encap_ip_version_value,
+ (void *)&cmd_set_mplsoudp_encap_label,
+ (void *)&cmd_set_mplsoudp_encap_label_value,
+ (void *)&cmd_set_mplsoudp_encap_udp_src,
+ (void *)&cmd_set_mplsoudp_encap_udp_src_value,
+ (void *)&cmd_set_mplsoudp_encap_udp_dst,
+ (void *)&cmd_set_mplsoudp_encap_udp_dst_value,
+ (void *)&cmd_set_mplsoudp_encap_ip_src,
+ (void *)&cmd_set_mplsoudp_encap_ip_src_value,
+ (void *)&cmd_set_mplsoudp_encap_ip_dst,
+ (void *)&cmd_set_mplsoudp_encap_ip_dst_value,
+ (void *)&cmd_set_mplsoudp_encap_eth_src,
+ (void *)&cmd_set_mplsoudp_encap_eth_src_value,
+ (void *)&cmd_set_mplsoudp_encap_eth_dst,
+ (void *)&cmd_set_mplsoudp_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_mplsoudp_encap_with_vlan = {
+ .f = cmd_set_mplsoudp_encap_parsed,
+ .data = NULL,
+ .help_str = "set mplsoudp_encap-with-vlan ip-version ipv4|ipv6"
+ " label <label> udp-src <udp-src> udp-dst <udp-dst>"
+ " ip-src <ip-src> ip-dst <ip-dst> vlan-tci <vlan-tci>"
+ " eth-src <eth-src> eth-dst <eth-dst>",
+ .tokens = {
+ (void *)&cmd_set_mplsoudp_encap_set,
+ (void *)&cmd_set_mplsoudp_encap_mplsoudp_encap_with_vlan,
+ (void *)&cmd_set_mplsoudp_encap_ip_version,
+ (void *)&cmd_set_mplsoudp_encap_ip_version_value,
+ (void *)&cmd_set_mplsoudp_encap_label,
+ (void *)&cmd_set_mplsoudp_encap_label_value,
+ (void *)&cmd_set_mplsoudp_encap_udp_src,
+ (void *)&cmd_set_mplsoudp_encap_udp_src_value,
+ (void *)&cmd_set_mplsoudp_encap_udp_dst,
+ (void *)&cmd_set_mplsoudp_encap_udp_dst_value,
+ (void *)&cmd_set_mplsoudp_encap_ip_src,
+ (void *)&cmd_set_mplsoudp_encap_ip_src_value,
+ (void *)&cmd_set_mplsoudp_encap_ip_dst,
+ (void *)&cmd_set_mplsoudp_encap_ip_dst_value,
+ (void *)&cmd_set_mplsoudp_encap_vlan,
+ (void *)&cmd_set_mplsoudp_encap_vlan_value,
+ (void *)&cmd_set_mplsoudp_encap_eth_src,
+ (void *)&cmd_set_mplsoudp_encap_eth_src_value,
+ (void *)&cmd_set_mplsoudp_encap_eth_dst,
+ (void *)&cmd_set_mplsoudp_encap_eth_dst_value,
+ NULL,
+ },
+};
+
+/** Set MPLSoUDP decapsulation details */
+struct cmd_set_mplsoudp_decap_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mplsoudp;
+ cmdline_fixed_string_t pos_token;
+ cmdline_fixed_string_t ip_version;
+ uint32_t vlan_present:1;
+};
+
+cmdline_parse_token_string_t cmd_set_mplsoudp_decap_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_decap_result, set,
+ "set");
+cmdline_parse_token_string_t cmd_set_mplsoudp_decap_mplsoudp_decap =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_decap_result, mplsoudp,
+ "mplsoudp_decap");
+cmdline_parse_token_string_t cmd_set_mplsoudp_decap_mplsoudp_decap_with_vlan =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_decap_result,
+ mplsoudp, "mplsoudp_decap-with-vlan");
+cmdline_parse_token_string_t cmd_set_mplsoudp_decap_ip_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_decap_result,
+ pos_token, "ip-version");
+cmdline_parse_token_string_t cmd_set_mplsoudp_decap_ip_version_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_mplsoudp_decap_result,
+ ip_version, "ipv4#ipv6");
+
+static void cmd_set_mplsoudp_decap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_mplsoudp_decap_result *res = parsed_result;
+
+ if (strcmp(res->mplsoudp, "mplsoudp_decap") == 0)
+ mplsoudp_decap_conf.select_vlan = 0;
+ else if (strcmp(res->mplsoudp, "mplsoudp_decap-with-vlan") == 0)
+ mplsoudp_decap_conf.select_vlan = 1;
+ if (strcmp(res->ip_version, "ipv4") == 0)
+ mplsoudp_decap_conf.select_ipv4 = 1;
+ else if (strcmp(res->ip_version, "ipv6") == 0)
+ mplsoudp_decap_conf.select_ipv4 = 0;
+}
+
+cmdline_parse_inst_t cmd_set_mplsoudp_decap = {
+ .f = cmd_set_mplsoudp_decap_parsed,
+ .data = NULL,
+ .help_str = "set mplsoudp_decap ip-version ipv4|ipv6",
+ .tokens = {
+ (void *)&cmd_set_mplsoudp_decap_set,
+ (void *)&cmd_set_mplsoudp_decap_mplsoudp_decap,
+ (void *)&cmd_set_mplsoudp_decap_ip_version,
+ (void *)&cmd_set_mplsoudp_decap_ip_version_value,
+ NULL,
+ },
+};
+
+cmdline_parse_inst_t cmd_set_mplsoudp_decap_with_vlan = {
+ .f = cmd_set_mplsoudp_decap_parsed,
+ .data = NULL,
+ .help_str = "set mplsoudp_decap-with-vlan ip-version ipv4|ipv6",
+ .tokens = {
+ (void *)&cmd_set_mplsoudp_decap_set,
+ (void *)&cmd_set_mplsoudp_decap_mplsoudp_decap_with_vlan,
+ (void *)&cmd_set_mplsoudp_decap_ip_version,
+ (void *)&cmd_set_mplsoudp_decap_ip_version_value,
+ NULL,
+ },
+};
+
+/* Strict link priority scheduling mode setting */
+static void
+cmd_strict_link_prio_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_set_tc_strict_prio(res->port_id, res->tc_map);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid tc_bitmap 0x%x\n", res->tc_map);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_strict_link_prio = {
+ .f = cmd_strict_link_prio_parsed,
+ .data = NULL,
+ .help_str = "set tx strict-link-priority <port_id> <tc_bitmap>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_strict_link_prio,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_tc_map,
+ NULL,
+ },
+};
+
+/* Load dynamic device personalization*/
+struct cmd_ddp_add_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t add;
+ portid_t port_id;
+ char filepath[];
+};
+
+cmdline_parse_token_string_t cmd_ddp_add_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_add_add =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, add, "add");
+cmdline_parse_token_num_t cmd_ddp_add_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ddp_add_result, port_id, UINT16);
+cmdline_parse_token_string_t cmd_ddp_add_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_add_result, filepath, NULL);
+
+static void
+cmd_ddp_add_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ddp_add_result *res = parsed_result;
+ uint8_t *buff;
+ uint32_t size;
+ char *filepath;
+ char *file_fld[2];
+ int file_num;
+ int ret = -ENOTSUP;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ filepath = strdup(res->filepath);
+ if (filepath == NULL) {
+ printf("Failed to allocate memory\n");
+ return;
+ }
+ file_num = rte_strsplit(filepath, strlen(filepath), file_fld, 2, ',');
+
+ buff = open_file(file_fld[0], &size);
+ if (!buff) {
+ free((void *)filepath);
+ return;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_process_ddp_package(res->port_id,
+ buff, size,
+ RTE_PMD_I40E_PKG_OP_WR_ADD);
+#endif
+
+ if (ret == -EEXIST)
+ printf("Profile has already existed.\n");
+ else if (ret < 0)
+ printf("Failed to load profile.\n");
+ else if (file_num == 2)
+ save_file(file_fld[1], buff, size);
+
+ close_file(buff);
+ free((void *)filepath);
+}
+
+cmdline_parse_inst_t cmd_ddp_add = {
+ .f = cmd_ddp_add_parsed,
+ .data = NULL,
+ .help_str = "ddp add <port_id> <profile_path[,backup_profile_path]>",
+ .tokens = {
+ (void *)&cmd_ddp_add_ddp,
+ (void *)&cmd_ddp_add_add,
+ (void *)&cmd_ddp_add_port_id,
+ (void *)&cmd_ddp_add_filepath,
+ NULL,
+ },
+};
+
+/* Delete dynamic device personalization*/
+struct cmd_ddp_del_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t del;
+ portid_t port_id;
+ char filepath[];
+};
+
+cmdline_parse_token_string_t cmd_ddp_del_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_del_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_del_del =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_del_result, del, "del");
+cmdline_parse_token_num_t cmd_ddp_del_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ddp_del_result, port_id, UINT16);
+cmdline_parse_token_string_t cmd_ddp_del_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_del_result, filepath, NULL);
+
+static void
+cmd_ddp_del_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ddp_del_result *res = parsed_result;
+ uint8_t *buff;
+ uint32_t size;
+ int ret = -ENOTSUP;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+ buff = open_file(res->filepath, &size);
+ if (!buff)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_process_ddp_package(res->port_id,
+ buff, size,
+ RTE_PMD_I40E_PKG_OP_WR_DEL);
+#endif
+
+ if (ret == -EACCES)
+ printf("Profile does not exist.\n");
+ else if (ret < 0)
+ printf("Failed to delete profile.\n");
+
+ close_file(buff);
+}
+
+cmdline_parse_inst_t cmd_ddp_del = {
+ .f = cmd_ddp_del_parsed,
+ .data = NULL,
+ .help_str = "ddp del <port_id> <backup_profile_path>",
+ .tokens = {
+ (void *)&cmd_ddp_del_ddp,
+ (void *)&cmd_ddp_del_del,
+ (void *)&cmd_ddp_del_port_id,
+ (void *)&cmd_ddp_del_filepath,
+ NULL,
+ },
+};
+
+/* Get dynamic device personalization profile info */
+struct cmd_ddp_info_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t get;
+ cmdline_fixed_string_t info;
+ char filepath[];
+};
+
+cmdline_parse_token_string_t cmd_ddp_info_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_info_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_info_get =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_info_result, get, "get");
+cmdline_parse_token_string_t cmd_ddp_info_info =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_info_result, info, "info");
+cmdline_parse_token_string_t cmd_ddp_info_filepath =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_info_result, filepath, NULL);
+
+static void
+cmd_ddp_info_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ddp_info_result *res = parsed_result;
+ uint8_t *pkg;
+ uint32_t pkg_size;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ uint32_t i, j, n;
+ uint8_t *buff;
+ uint32_t buff_size = 0;
+ struct rte_pmd_i40e_profile_info info;
+ uint32_t dev_num = 0;
+ struct rte_pmd_i40e_ddp_device_id *devs;
+ uint32_t proto_num = 0;
+ struct rte_pmd_i40e_proto_info *proto = NULL;
+ uint32_t pctype_num = 0;
+ struct rte_pmd_i40e_ptype_info *pctype;
+ uint32_t ptype_num = 0;
+ struct rte_pmd_i40e_ptype_info *ptype;
+ uint8_t proto_id;
+
+#endif
+
+ pkg = open_file(res->filepath, &pkg_size);
+ if (!pkg)
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&info, sizeof(info),
+ RTE_PMD_I40E_PKG_INFO_GLOBAL_HEADER);
+ if (!ret) {
+ printf("Global Track id: 0x%x\n", info.track_id);
+ printf("Global Version: %d.%d.%d.%d\n",
+ info.version.major,
+ info.version.minor,
+ info.version.update,
+ info.version.draft);
+ printf("Global Package name: %s\n\n", info.name);
+ }
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&info, sizeof(info),
+ RTE_PMD_I40E_PKG_INFO_HEADER);
+ if (!ret) {
+ printf("i40e Profile Track id: 0x%x\n", info.track_id);
+ printf("i40e Profile Version: %d.%d.%d.%d\n",
+ info.version.major,
+ info.version.minor,
+ info.version.update,
+ info.version.draft);
+ printf("i40e Profile name: %s\n\n", info.name);
+ }
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&buff_size, sizeof(buff_size),
+ RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES_SIZE);
+ if (!ret && buff_size) {
+ buff = (uint8_t *)malloc(buff_size);
+ if (buff) {
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ buff, buff_size,
+ RTE_PMD_I40E_PKG_INFO_GLOBAL_NOTES);
+ if (!ret)
+ printf("Package Notes:\n%s\n\n", buff);
+ free(buff);
+ }
+ }
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&dev_num, sizeof(dev_num),
+ RTE_PMD_I40E_PKG_INFO_DEVID_NUM);
+ if (!ret && dev_num) {
+ buff_size = dev_num * sizeof(struct rte_pmd_i40e_ddp_device_id);
+ devs = (struct rte_pmd_i40e_ddp_device_id *)malloc(buff_size);
+ if (devs) {
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)devs, buff_size,
+ RTE_PMD_I40E_PKG_INFO_DEVID_LIST);
+ if (!ret) {
+ printf("List of supported devices:\n");
+ for (i = 0; i < dev_num; i++) {
+ printf(" %04X:%04X %04X:%04X\n",
+ devs[i].vendor_dev_id >> 16,
+ devs[i].vendor_dev_id & 0xFFFF,
+ devs[i].sub_vendor_dev_id >> 16,
+ devs[i].sub_vendor_dev_id & 0xFFFF);
+ }
+ printf("\n");
+ }
+ free(devs);
+ }
+ }
+
+ /* get information about protocols and packet types */
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&proto_num, sizeof(proto_num),
+ RTE_PMD_I40E_PKG_INFO_PROTOCOL_NUM);
+ if (ret || !proto_num)
+ goto no_print_return;
+
+ buff_size = proto_num * sizeof(struct rte_pmd_i40e_proto_info);
+ proto = (struct rte_pmd_i40e_proto_info *)malloc(buff_size);
+ if (!proto)
+ goto no_print_return;
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size, (uint8_t *)proto,
+ buff_size,
+ RTE_PMD_I40E_PKG_INFO_PROTOCOL_LIST);
+ if (!ret) {
+ printf("List of used protocols:\n");
+ for (i = 0; i < proto_num; i++)
+ printf(" %2u: %s\n", proto[i].proto_id,
+ proto[i].name);
+ printf("\n");
+ }
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size,
+ (uint8_t *)&pctype_num, sizeof(pctype_num),
+ RTE_PMD_I40E_PKG_INFO_PCTYPE_NUM);
+ if (ret || !pctype_num)
+ goto no_print_pctypes;
+
+ buff_size = pctype_num * sizeof(struct rte_pmd_i40e_ptype_info);
+ pctype = (struct rte_pmd_i40e_ptype_info *)malloc(buff_size);
+ if (!pctype)
+ goto no_print_pctypes;
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size, (uint8_t *)pctype,
+ buff_size,
+ RTE_PMD_I40E_PKG_INFO_PCTYPE_LIST);
+ if (ret) {
+ free(pctype);
+ goto no_print_pctypes;
+ }
+
+ printf("List of defined packet classification types:\n");
+ for (i = 0; i < pctype_num; i++) {
+ printf(" %2u:", pctype[i].ptype_id);
+ for (j = 0; j < RTE_PMD_I40E_PROTO_NUM; j++) {
+ proto_id = pctype[i].protocols[j];
+ if (proto_id != RTE_PMD_I40E_PROTO_UNUSED) {
+ for (n = 0; n < proto_num; n++) {
+ if (proto[n].proto_id == proto_id) {
+ printf(" %s", proto[n].name);
+ break;
+ }
+ }
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+ free(pctype);
+
+no_print_pctypes:
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size, (uint8_t *)&ptype_num,
+ sizeof(ptype_num),
+ RTE_PMD_I40E_PKG_INFO_PTYPE_NUM);
+ if (ret || !ptype_num)
+ goto no_print_return;
+
+ buff_size = ptype_num * sizeof(struct rte_pmd_i40e_ptype_info);
+ ptype = (struct rte_pmd_i40e_ptype_info *)malloc(buff_size);
+ if (!ptype)
+ goto no_print_return;
+
+ ret = rte_pmd_i40e_get_ddp_info(pkg, pkg_size, (uint8_t *)ptype,
+ buff_size,
+ RTE_PMD_I40E_PKG_INFO_PTYPE_LIST);
+ if (ret) {
+ free(ptype);
+ goto no_print_return;
+ }
+ printf("List of defined packet types:\n");
+ for (i = 0; i < ptype_num; i++) {
+ printf(" %2u:", ptype[i].ptype_id);
+ for (j = 0; j < RTE_PMD_I40E_PROTO_NUM; j++) {
+ proto_id = ptype[i].protocols[j];
+ if (proto_id != RTE_PMD_I40E_PROTO_UNUSED) {
+ for (n = 0; n < proto_num; n++) {
+ if (proto[n].proto_id == proto_id) {
+ printf(" %s", proto[n].name);
+ break;
+ }
+ }
+ }
+ }
+ printf("\n");
+ }
+ free(ptype);
+ printf("\n");
+
+ ret = 0;
+no_print_return:
+ if (proto)
+ free(proto);
+#endif
+ if (ret == -ENOTSUP)
+ printf("Function not supported in PMD driver\n");
+ close_file(pkg);
+}
+
+cmdline_parse_inst_t cmd_ddp_get_info = {
+ .f = cmd_ddp_info_parsed,
+ .data = NULL,
+ .help_str = "ddp get info <profile_path>",
+ .tokens = {
+ (void *)&cmd_ddp_info_ddp,
+ (void *)&cmd_ddp_info_get,
+ (void *)&cmd_ddp_info_info,
+ (void *)&cmd_ddp_info_filepath,
+ NULL,
+ },
+};
+
+/* Get dynamic device personalization profile info list*/
+#define PROFILE_INFO_SIZE 48
+#define MAX_PROFILE_NUM 16
+
+struct cmd_ddp_get_list_result {
+ cmdline_fixed_string_t ddp;
+ cmdline_fixed_string_t get;
+ cmdline_fixed_string_t list;
+ portid_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_ddp_get_list_ddp =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, ddp, "ddp");
+cmdline_parse_token_string_t cmd_ddp_get_list_get =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, get, "get");
+cmdline_parse_token_string_t cmd_ddp_get_list_list =
+ TOKEN_STRING_INITIALIZER(struct cmd_ddp_get_list_result, list, "list");
+cmdline_parse_token_num_t cmd_ddp_get_list_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_ddp_get_list_result, port_id, UINT16);
+
+static void
+cmd_ddp_get_list_parsed(
+ __rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct cmd_ddp_get_list_result *res = parsed_result;
+ struct rte_pmd_i40e_profile_list *p_list;
+ struct rte_pmd_i40e_profile_info *p_info;
+ uint32_t p_num;
+ uint32_t size;
+ uint32_t i;
+#endif
+ int ret = -ENOTSUP;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ size = PROFILE_INFO_SIZE * MAX_PROFILE_NUM + 4;
+ p_list = (struct rte_pmd_i40e_profile_list *)malloc(size);
+ if (!p_list) {
+ printf("%s: Failed to malloc buffer\n", __func__);
+ return;
+ }
+
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_get_ddp_list(res->port_id,
+ (uint8_t *)p_list, size);
+
+ if (!ret) {
+ p_num = p_list->p_count;
+ printf("Profile number is: %d\n\n", p_num);
+
+ for (i = 0; i < p_num; i++) {
+ p_info = &p_list->p_info[i];
+ printf("Profile %d:\n", i);
+ printf("Track id: 0x%x\n", p_info->track_id);
+ printf("Version: %d.%d.%d.%d\n",
+ p_info->version.major,
+ p_info->version.minor,
+ p_info->version.update,
+ p_info->version.draft);
+ printf("Profile name: %s\n\n", p_info->name);
+ }
+ }
+
+ free(p_list);
+#endif
+
+ if (ret < 0)
+ printf("Failed to get ddp list\n");
+}
+
+cmdline_parse_inst_t cmd_ddp_get_list = {
+ .f = cmd_ddp_get_list_parsed,
+ .data = NULL,
+ .help_str = "ddp get list <port_id>",
+ .tokens = {
+ (void *)&cmd_ddp_get_list_ddp,
+ (void *)&cmd_ddp_get_list_get,
+ (void *)&cmd_ddp_get_list_list,
+ (void *)&cmd_ddp_get_list_port_id,
+ NULL,
+ },
+};
+
+/* Configure input set */
+struct cmd_cfg_input_set_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t cfg;
+ portid_t port_id;
+ cmdline_fixed_string_t pctype;
+ uint8_t pctype_id;
+ cmdline_fixed_string_t inset_type;
+ cmdline_fixed_string_t opt;
+ cmdline_fixed_string_t field;
+ uint8_t field_idx;
+};
+
+static void
+cmd_cfg_input_set_parsed(
+ __rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct cmd_cfg_input_set_result *res = parsed_result;
+ enum rte_pmd_i40e_inset_type inset_type = INSET_NONE;
+ struct rte_pmd_i40e_inset inset;
+#endif
+ int ret = -ENOTSUP;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (!strcmp(res->inset_type, "hash_inset"))
+ inset_type = INSET_HASH;
+ else if (!strcmp(res->inset_type, "fdir_inset"))
+ inset_type = INSET_FDIR;
+ else if (!strcmp(res->inset_type, "fdir_flx_inset"))
+ inset_type = INSET_FDIR_FLX;
+ ret = rte_pmd_i40e_inset_get(res->port_id, res->pctype_id,
+ &inset, inset_type);
+ if (ret) {
+ printf("Failed to get input set.\n");
+ return;
+ }
+
+ if (!strcmp(res->opt, "get")) {
+ ret = rte_pmd_i40e_inset_field_get(inset.inset,
+ res->field_idx);
+ if (ret)
+ printf("Field index %d is enabled.\n", res->field_idx);
+ else
+ printf("Field index %d is disabled.\n", res->field_idx);
+ return;
+ } else if (!strcmp(res->opt, "set"))
+ ret = rte_pmd_i40e_inset_field_set(&inset.inset,
+ res->field_idx);
+ else if (!strcmp(res->opt, "clear"))
+ ret = rte_pmd_i40e_inset_field_clear(&inset.inset,
+ res->field_idx);
+ if (ret) {
+ printf("Failed to configure input set field.\n");
+ return;
+ }
+
+ ret = rte_pmd_i40e_inset_set(res->port_id, res->pctype_id,
+ &inset, inset_type);
+ if (ret) {
+ printf("Failed to set input set.\n");
+ return;
+ }
+#endif
+
+ if (ret == -ENOTSUP)
+ printf("Function not supported\n");
+}
+
+cmdline_parse_token_string_t cmd_cfg_input_set_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_cfg_input_set_cfg =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ cfg, "config");
+cmdline_parse_token_num_t cmd_cfg_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_cfg_input_set_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_cfg_input_set_pctype =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ pctype, "pctype");
+cmdline_parse_token_num_t cmd_cfg_input_set_pctype_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_cfg_input_set_result,
+ pctype_id, UINT8);
+cmdline_parse_token_string_t cmd_cfg_input_set_inset_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ inset_type,
+ "hash_inset#fdir_inset#fdir_flx_inset");
+cmdline_parse_token_string_t cmd_cfg_input_set_opt =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ opt, "get#set#clear");
+cmdline_parse_token_string_t cmd_cfg_input_set_field =
+ TOKEN_STRING_INITIALIZER(struct cmd_cfg_input_set_result,
+ field, "field");
+cmdline_parse_token_num_t cmd_cfg_input_set_field_idx =
+ TOKEN_NUM_INITIALIZER(struct cmd_cfg_input_set_result,
+ field_idx, UINT8);
+
+cmdline_parse_inst_t cmd_cfg_input_set = {
+ .f = cmd_cfg_input_set_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> pctype <pctype_id> hash_inset|"
+ "fdir_inset|fdir_flx_inset get|set|clear field <field_idx>",
+ .tokens = {
+ (void *)&cmd_cfg_input_set_port,
+ (void *)&cmd_cfg_input_set_cfg,
+ (void *)&cmd_cfg_input_set_port_id,
+ (void *)&cmd_cfg_input_set_pctype,
+ (void *)&cmd_cfg_input_set_pctype_id,
+ (void *)&cmd_cfg_input_set_inset_type,
+ (void *)&cmd_cfg_input_set_opt,
+ (void *)&cmd_cfg_input_set_field,
+ (void *)&cmd_cfg_input_set_field_idx,
+ NULL,
+ },
+};
+
+/* Clear input set */
+struct cmd_clear_input_set_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t cfg;
+ portid_t port_id;
+ cmdline_fixed_string_t pctype;
+ uint8_t pctype_id;
+ cmdline_fixed_string_t inset_type;
+ cmdline_fixed_string_t clear;
+ cmdline_fixed_string_t all;
+};
+
+static void
+cmd_clear_input_set_parsed(
+ __rte_unused void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct cmd_clear_input_set_result *res = parsed_result;
+ enum rte_pmd_i40e_inset_type inset_type = INSET_NONE;
+ struct rte_pmd_i40e_inset inset;
+#endif
+ int ret = -ENOTSUP;
+
+ if (!all_ports_stopped()) {
+ printf("Please stop all ports first\n");
+ return;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (!strcmp(res->inset_type, "hash_inset"))
+ inset_type = INSET_HASH;
+ else if (!strcmp(res->inset_type, "fdir_inset"))
+ inset_type = INSET_FDIR;
+ else if (!strcmp(res->inset_type, "fdir_flx_inset"))
+ inset_type = INSET_FDIR_FLX;
+
+ memset(&inset, 0, sizeof(inset));
+
+ ret = rte_pmd_i40e_inset_set(res->port_id, res->pctype_id,
+ &inset, inset_type);
+ if (ret) {
+ printf("Failed to clear input set.\n");
+ return;
+ }
+
+#endif
+
+ if (ret == -ENOTSUP)
+ printf("Function not supported\n");
+}
+
+cmdline_parse_token_string_t cmd_clear_input_set_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_clear_input_set_cfg =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ cfg, "config");
+cmdline_parse_token_num_t cmd_clear_input_set_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_clear_input_set_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_clear_input_set_pctype =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ pctype, "pctype");
+cmdline_parse_token_num_t cmd_clear_input_set_pctype_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_clear_input_set_result,
+ pctype_id, UINT8);
+cmdline_parse_token_string_t cmd_clear_input_set_inset_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ inset_type,
+ "hash_inset#fdir_inset#fdir_flx_inset");
+cmdline_parse_token_string_t cmd_clear_input_set_clear =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ clear, "clear");
+cmdline_parse_token_string_t cmd_clear_input_set_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_clear_input_set_result,
+ all, "all");
+
+cmdline_parse_inst_t cmd_clear_input_set = {
+ .f = cmd_clear_input_set_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> pctype <pctype_id> hash_inset|"
+ "fdir_inset|fdir_flx_inset clear all",
+ .tokens = {
+ (void *)&cmd_clear_input_set_port,
+ (void *)&cmd_clear_input_set_cfg,
+ (void *)&cmd_clear_input_set_port_id,
+ (void *)&cmd_clear_input_set_pctype,
+ (void *)&cmd_clear_input_set_pctype_id,
+ (void *)&cmd_clear_input_set_inset_type,
+ (void *)&cmd_clear_input_set_clear,
+ (void *)&cmd_clear_input_set_all,
+ NULL,
+ },
+};
+
+/* show vf stats */
+
+/* Common result structure for show vf stats */
+struct cmd_show_vf_stats_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t stats;
+ portid_t port_id;
+ uint16_t vf_id;
+};
+
+/* Common CLI fields show vf stats*/
+cmdline_parse_token_string_t cmd_show_vf_stats_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_vf_stats_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_show_vf_stats_stats =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ stats, "stats");
+cmdline_parse_token_num_t cmd_show_vf_stats_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_vf_stats_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_show_vf_stats_result,
+ vf_id, UINT16);
+
+static void
+cmd_show_vf_stats_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_vf_stats_result *res = parsed_result;
+ struct rte_eth_stats stats;
+ int ret = -ENOTSUP;
+ static const char *nic_stats_border = "########################";
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ memset(&stats, 0, sizeof(stats));
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_get_vf_stats(res->port_id,
+ res->vf_id,
+ &stats);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_get_vf_stats(res->port_id,
+ res->vf_id,
+ &stats);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+
+ printf("\n %s NIC statistics for port %-2d vf %-2d %s\n",
+ nic_stats_border, res->port_id, res->vf_id, nic_stats_border);
+
+ printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: "
+ "%-"PRIu64"\n",
+ stats.ipackets, stats.imissed, stats.ibytes);
+ printf(" RX-errors: %-"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %-10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: "
+ "%-"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+cmdline_parse_inst_t cmd_show_vf_stats = {
+ .f = cmd_show_vf_stats_parsed,
+ .data = NULL,
+ .help_str = "show vf stats <port_id> <vf_id>",
+ .tokens = {
+ (void *)&cmd_show_vf_stats_show,
+ (void *)&cmd_show_vf_stats_vf,
+ (void *)&cmd_show_vf_stats_stats,
+ (void *)&cmd_show_vf_stats_port_id,
+ (void *)&cmd_show_vf_stats_vf_id,
+ NULL,
+ },
+};
+
+/* clear vf stats */
+
+/* Common result structure for clear vf stats */
+struct cmd_clear_vf_stats_result {
+ cmdline_fixed_string_t clear;
+ cmdline_fixed_string_t vf;
+ cmdline_fixed_string_t stats;
+ portid_t port_id;
+ uint16_t vf_id;
+};
+
+/* Common CLI fields clear vf stats*/
+cmdline_parse_token_string_t cmd_clear_vf_stats_clear =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ clear, "clear");
+cmdline_parse_token_string_t cmd_clear_vf_stats_vf =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ vf, "vf");
+cmdline_parse_token_string_t cmd_clear_vf_stats_stats =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ stats, "stats");
+cmdline_parse_token_num_t cmd_clear_vf_stats_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_clear_vf_stats_vf_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_clear_vf_stats_result,
+ vf_id, UINT16);
+
+static void
+cmd_clear_vf_stats_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_clear_vf_stats_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_i40e_reset_vf_stats(res->port_id,
+ res->vf_id);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (ret == -ENOTSUP)
+ ret = rte_pmd_bnxt_reset_vf_stats(res->port_id,
+ res->vf_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid vf_id %d\n", res->vf_id);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_clear_vf_stats = {
+ .f = cmd_clear_vf_stats_parsed,
+ .data = NULL,
+ .help_str = "clear vf stats <port_id> <vf_id>",
+ .tokens = {
+ (void *)&cmd_clear_vf_stats_clear,
+ (void *)&cmd_clear_vf_stats_vf,
+ (void *)&cmd_clear_vf_stats_stats,
+ (void *)&cmd_clear_vf_stats_port_id,
+ (void *)&cmd_clear_vf_stats_vf_id,
+ NULL,
+ },
+};
+
+/* port config pctype mapping reset */
+
+/* Common result structure for port config pctype mapping reset */
+struct cmd_pctype_mapping_reset_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t pctype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t reset;
+};
+
+/* Common CLI fields for port config pctype mapping reset*/
+cmdline_parse_token_string_t cmd_pctype_mapping_reset_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_pctype_mapping_reset_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_pctype_mapping_reset_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_pctype_mapping_reset_pctype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ pctype, "pctype");
+cmdline_parse_token_string_t cmd_pctype_mapping_reset_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_pctype_mapping_reset_reset =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_reset_result,
+ reset, "reset");
+
+static void
+cmd_pctype_mapping_reset_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_pctype_mapping_reset_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_flow_type_mapping_reset(res->port_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_pctype_mapping_reset = {
+ .f = cmd_pctype_mapping_reset_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> pctype mapping reset",
+ .tokens = {
+ (void *)&cmd_pctype_mapping_reset_port,
+ (void *)&cmd_pctype_mapping_reset_config,
+ (void *)&cmd_pctype_mapping_reset_port_id,
+ (void *)&cmd_pctype_mapping_reset_pctype,
+ (void *)&cmd_pctype_mapping_reset_mapping,
+ (void *)&cmd_pctype_mapping_reset_reset,
+ NULL,
+ },
+};
+
+/* show port pctype mapping */
+
+/* Common result structure for show port pctype mapping */
+struct cmd_pctype_mapping_get_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t pctype;
+ cmdline_fixed_string_t mapping;
+};
+
+/* Common CLI fields for pctype mapping get */
+cmdline_parse_token_string_t cmd_pctype_mapping_get_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_get_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_pctype_mapping_get_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_get_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_pctype_mapping_get_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_pctype_mapping_get_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_pctype_mapping_get_pctype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_get_result,
+ pctype, "pctype");
+cmdline_parse_token_string_t cmd_pctype_mapping_get_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_get_result,
+ mapping, "mapping");
+
+static void
+cmd_pctype_mapping_get_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_pctype_mapping_get_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_flow_type_mapping
+ mapping[RTE_PMD_I40E_FLOW_TYPE_MAX];
+ int i, j, first_pctype;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_flow_type_mapping_get(res->port_id, mapping);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ return;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ return;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ return;
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ for (i = 0; i < RTE_PMD_I40E_FLOW_TYPE_MAX; i++) {
+ if (mapping[i].pctype != 0ULL) {
+ first_pctype = 1;
+
+ printf("pctype: ");
+ for (j = 0; j < RTE_PMD_I40E_PCTYPE_MAX; j++) {
+ if (mapping[i].pctype & (1ULL << j)) {
+ printf(first_pctype ?
+ "%02d" : ",%02d", j);
+ first_pctype = 0;
+ }
+ }
+ printf(" -> flowtype: %02d\n", mapping[i].flow_type);
+ }
+ }
+#endif
+}
+
+cmdline_parse_inst_t cmd_pctype_mapping_get = {
+ .f = cmd_pctype_mapping_get_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> pctype mapping",
+ .tokens = {
+ (void *)&cmd_pctype_mapping_get_show,
+ (void *)&cmd_pctype_mapping_get_port,
+ (void *)&cmd_pctype_mapping_get_port_id,
+ (void *)&cmd_pctype_mapping_get_pctype,
+ (void *)&cmd_pctype_mapping_get_mapping,
+ NULL,
+ },
+};
+
+/* port config pctype mapping update */
+
+/* Common result structure for port config pctype mapping update */
+struct cmd_pctype_mapping_update_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t pctype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t update;
+ cmdline_fixed_string_t pctype_list;
+ uint16_t flow_type;
+};
+
+/* Common CLI fields for pctype mapping update*/
+cmdline_parse_token_string_t cmd_pctype_mapping_update_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_pctype_mapping_update_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_pctype_mapping_update_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_pctype_mapping_update_pctype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ pctype, "pctype");
+cmdline_parse_token_string_t cmd_pctype_mapping_update_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_pctype_mapping_update_update =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ update, "update");
+cmdline_parse_token_string_t cmd_pctype_mapping_update_pc_type =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ pctype_list, NULL);
+cmdline_parse_token_num_t cmd_pctype_mapping_update_flow_type =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_pctype_mapping_update_result,
+ flow_type, UINT16);
+
+static void
+cmd_pctype_mapping_update_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_pctype_mapping_update_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_flow_type_mapping mapping;
+ unsigned int i;
+ unsigned int nb_item;
+ unsigned int pctype_list[RTE_PMD_I40E_PCTYPE_MAX];
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ nb_item = parse_item_list(res->pctype_list, "pctypes",
+ RTE_PMD_I40E_PCTYPE_MAX, pctype_list, 1);
+ mapping.flow_type = res->flow_type;
+ for (i = 0, mapping.pctype = 0ULL; i < nb_item; i++)
+ mapping.pctype |= (1ULL << pctype_list[i]);
+ ret = rte_pmd_i40e_flow_type_mapping_update(res->port_id,
+ &mapping,
+ 1,
+ 0);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid pctype or flow type\n");
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_pctype_mapping_update = {
+ .f = cmd_pctype_mapping_update_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> pctype mapping update"
+ " <pctype_id_0,[pctype_id_1]*> <flowtype_id>",
+ .tokens = {
+ (void *)&cmd_pctype_mapping_update_port,
+ (void *)&cmd_pctype_mapping_update_config,
+ (void *)&cmd_pctype_mapping_update_port_id,
+ (void *)&cmd_pctype_mapping_update_pctype,
+ (void *)&cmd_pctype_mapping_update_mapping,
+ (void *)&cmd_pctype_mapping_update_update,
+ (void *)&cmd_pctype_mapping_update_pc_type,
+ (void *)&cmd_pctype_mapping_update_flow_type,
+ NULL,
+ },
+};
+
+/* ptype mapping get */
+
+/* Common result structure for ptype mapping get */
+struct cmd_ptype_mapping_get_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t get;
+ portid_t port_id;
+ uint8_t valid_only;
+};
+
+/* Common CLI fields for ptype mapping get */
+cmdline_parse_token_string_t cmd_ptype_mapping_get_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_get_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_get_get =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ get, "get");
+cmdline_parse_token_num_t cmd_ptype_mapping_get_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_ptype_mapping_get_valid_only =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_get_result,
+ valid_only, UINT8);
+
+static void
+cmd_ptype_mapping_get_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ptype_mapping_get_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ int max_ptype_num = 256;
+ struct rte_pmd_i40e_ptype_mapping mapping[max_ptype_num];
+ uint16_t count;
+ int i;
+#endif
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_get(res->port_id,
+ mapping,
+ max_ptype_num,
+ &count,
+ res->valid_only);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ if (!ret) {
+ for (i = 0; i < count; i++)
+ printf("%3d\t0x%08x\n",
+ mapping[i].hw_ptype, mapping[i].sw_ptype);
+ }
+#endif
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_get = {
+ .f = cmd_ptype_mapping_get_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping get <port_id> <valid_only>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_get_ptype,
+ (void *)&cmd_ptype_mapping_get_mapping,
+ (void *)&cmd_ptype_mapping_get_get,
+ (void *)&cmd_ptype_mapping_get_port_id,
+ (void *)&cmd_ptype_mapping_get_valid_only,
+ NULL,
+ },
+};
+
+/* ptype mapping replace */
+
+/* Common result structure for ptype mapping replace */
+struct cmd_ptype_mapping_replace_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t replace;
+ portid_t port_id;
+ uint32_t target;
+ uint8_t mask;
+ uint32_t pkt_type;
+};
+
+/* Common CLI fields for ptype mapping replace */
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_replace_replace =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ replace, "replace");
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_target =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ target, UINT32);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_mask =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ mask, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_replace_pkt_type =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_replace_result,
+ pkt_type, UINT32);
+
+static void
+cmd_ptype_mapping_replace_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ptype_mapping_replace_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_replace(res->port_id,
+ res->target,
+ res->mask,
+ res->pkt_type);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid ptype 0x%8x or 0x%8x\n",
+ res->target, res->pkt_type);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_replace = {
+ .f = cmd_ptype_mapping_replace_parsed,
+ .data = NULL,
+ .help_str =
+ "ptype mapping replace <port_id> <target> <mask> <pkt_type>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_replace_ptype,
+ (void *)&cmd_ptype_mapping_replace_mapping,
+ (void *)&cmd_ptype_mapping_replace_replace,
+ (void *)&cmd_ptype_mapping_replace_port_id,
+ (void *)&cmd_ptype_mapping_replace_target,
+ (void *)&cmd_ptype_mapping_replace_mask,
+ (void *)&cmd_ptype_mapping_replace_pkt_type,
+ NULL,
+ },
+};
+
+/* ptype mapping reset */
+
+/* Common result structure for ptype mapping reset */
+struct cmd_ptype_mapping_reset_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t reset;
+ portid_t port_id;
+};
+
+/* Common CLI fields for ptype mapping reset*/
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_reset_reset =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ reset, "reset");
+cmdline_parse_token_num_t cmd_ptype_mapping_reset_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_reset_result,
+ port_id, UINT16);
+
+static void
+cmd_ptype_mapping_reset_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ptype_mapping_reset_result *res = parsed_result;
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ ret = rte_pmd_i40e_ptype_mapping_reset(res->port_id);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_reset = {
+ .f = cmd_ptype_mapping_reset_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping reset <port_id>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_reset_ptype,
+ (void *)&cmd_ptype_mapping_reset_mapping,
+ (void *)&cmd_ptype_mapping_reset_reset,
+ (void *)&cmd_ptype_mapping_reset_port_id,
+ NULL,
+ },
+};
+
+/* ptype mapping update */
+
+/* Common result structure for ptype mapping update */
+struct cmd_ptype_mapping_update_result {
+ cmdline_fixed_string_t ptype;
+ cmdline_fixed_string_t mapping;
+ cmdline_fixed_string_t reset;
+ portid_t port_id;
+ uint8_t hw_ptype;
+ uint32_t sw_ptype;
+};
+
+/* Common CLI fields for ptype mapping update*/
+cmdline_parse_token_string_t cmd_ptype_mapping_update_ptype =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ ptype, "ptype");
+cmdline_parse_token_string_t cmd_ptype_mapping_update_mapping =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ mapping, "mapping");
+cmdline_parse_token_string_t cmd_ptype_mapping_update_update =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ reset, "update");
+cmdline_parse_token_num_t cmd_ptype_mapping_update_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_ptype_mapping_update_hw_ptype =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ hw_ptype, UINT8);
+cmdline_parse_token_num_t cmd_ptype_mapping_update_sw_ptype =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_ptype_mapping_update_result,
+ sw_ptype, UINT32);
+
+static void
+cmd_ptype_mapping_update_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_ptype_mapping_update_result *res = parsed_result;
+ int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+ struct rte_pmd_i40e_ptype_mapping mapping;
+#endif
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+#ifdef RTE_LIBRTE_I40E_PMD
+ mapping.hw_ptype = res->hw_ptype;
+ mapping.sw_ptype = res->sw_ptype;
+ ret = rte_pmd_i40e_ptype_mapping_update(res->port_id,
+ &mapping,
+ 1,
+ 0);
+#endif
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ printf("invalid ptype 0x%8x\n", res->sw_ptype);
+ break;
+ case -ENODEV:
+ printf("invalid port_id %d\n", res->port_id);
+ break;
+ case -ENOTSUP:
+ printf("function not implemented\n");
+ break;
+ default:
+ printf("programming error: (%s)\n", strerror(-ret));
+ }
+}
+
+cmdline_parse_inst_t cmd_ptype_mapping_update = {
+ .f = cmd_ptype_mapping_update_parsed,
+ .data = NULL,
+ .help_str = "ptype mapping update <port_id> <hw_ptype> <sw_ptype>",
+ .tokens = {
+ (void *)&cmd_ptype_mapping_update_ptype,
+ (void *)&cmd_ptype_mapping_update_mapping,
+ (void *)&cmd_ptype_mapping_update_update,
+ (void *)&cmd_ptype_mapping_update_port_id,
+ (void *)&cmd_ptype_mapping_update_hw_ptype,
+ (void *)&cmd_ptype_mapping_update_sw_ptype,
+ NULL,
+ },
+};
+
+/* Common result structure for file commands */
+struct cmd_cmdfile_result {
+ cmdline_fixed_string_t load;
+ cmdline_fixed_string_t filename;
+};
+
+/* Common CLI fields for file commands */
+cmdline_parse_token_string_t cmd_load_cmdfile =
+ TOKEN_STRING_INITIALIZER(struct cmd_cmdfile_result, load, "load");
+cmdline_parse_token_string_t cmd_load_cmdfile_filename =
+ TOKEN_STRING_INITIALIZER(struct cmd_cmdfile_result, filename, NULL);
+
+static void
+cmd_load_from_file_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_cmdfile_result *res = parsed_result;
+
+ cmdline_read_from_file(res->filename);
+}
+
+cmdline_parse_inst_t cmd_load_from_file = {
+ .f = cmd_load_from_file_parsed,
+ .data = NULL,
+ .help_str = "load <filename>",
+ .tokens = {
+ (void *)&cmd_load_cmdfile,
+ (void *)&cmd_load_cmdfile_filename,
+ NULL,
+ },
+};
+
+/* Get Rx offloads capabilities */
+struct cmd_rx_offload_get_capa_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rx_offload;
+ cmdline_fixed_string_t capabilities;
+};
+
+cmdline_parse_token_string_t cmd_rx_offload_get_capa_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_capa_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_rx_offload_get_capa_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_capa_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_rx_offload_get_capa_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_rx_offload_get_capa_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_rx_offload_get_capa_rx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_capa_result,
+ rx_offload, "rx_offload");
+cmdline_parse_token_string_t cmd_rx_offload_get_capa_capabilities =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_capa_result,
+ capabilities, "capabilities");
+
+static void
+print_rx_offloads(uint64_t offloads)
+{
+ uint64_t single_offload;
+ int begin;
+ int end;
+ int bit;
+
+ if (offloads == 0)
+ return;
+
+ begin = __builtin_ctzll(offloads);
+ end = sizeof(offloads) * CHAR_BIT - __builtin_clzll(offloads);
+
+ single_offload = 1ULL << begin;
+ for (bit = begin; bit < end; bit++) {
+ if (offloads & single_offload)
+ printf(" %s",
+ rte_eth_dev_rx_offload_name(single_offload));
+ single_offload <<= 1;
+ }
+}
+
+static void
+cmd_rx_offload_get_capa_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_rx_offload_get_capa_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ uint64_t queue_offloads;
+ uint64_t port_offloads;
+ int ret;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ queue_offloads = dev_info.rx_queue_offload_capa;
+ port_offloads = dev_info.rx_offload_capa ^ queue_offloads;
+
+ printf("Rx Offloading Capabilities of port %d :\n", port_id);
+ printf(" Per Queue :");
+ print_rx_offloads(queue_offloads);
+
+ printf("\n");
+ printf(" Per Port :");
+ print_rx_offloads(port_offloads);
+ printf("\n\n");
+}
+
+cmdline_parse_inst_t cmd_rx_offload_get_capa = {
+ .f = cmd_rx_offload_get_capa_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rx_offload capabilities",
+ .tokens = {
+ (void *)&cmd_rx_offload_get_capa_show,
+ (void *)&cmd_rx_offload_get_capa_port,
+ (void *)&cmd_rx_offload_get_capa_port_id,
+ (void *)&cmd_rx_offload_get_capa_rx_offload,
+ (void *)&cmd_rx_offload_get_capa_capabilities,
+ NULL,
+ }
+};
+
+/* Get Rx offloads configuration */
+struct cmd_rx_offload_get_configuration_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rx_offload;
+ cmdline_fixed_string_t configuration;
+};
+
+cmdline_parse_token_string_t cmd_rx_offload_get_configuration_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_configuration_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_rx_offload_get_configuration_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_configuration_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_rx_offload_get_configuration_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_rx_offload_get_configuration_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_rx_offload_get_configuration_rx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_configuration_result,
+ rx_offload, "rx_offload");
+cmdline_parse_token_string_t cmd_rx_offload_get_configuration_configuration =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_rx_offload_get_configuration_result,
+ configuration, "configuration");
+
+static void
+cmd_rx_offload_get_configuration_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_rx_offload_get_configuration_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ struct rte_port *port = &ports[port_id];
+ uint64_t port_offloads;
+ uint64_t queue_offloads;
+ uint16_t nb_rx_queues;
+ int q;
+ int ret;
+
+ printf("Rx Offloading Configuration of port %d :\n", port_id);
+
+ port_offloads = port->dev_conf.rxmode.offloads;
+ printf(" Port :");
+ print_rx_offloads(port_offloads);
+ printf("\n");
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ nb_rx_queues = dev_info.nb_rx_queues;
+ for (q = 0; q < nb_rx_queues; q++) {
+ queue_offloads = port->rx_conf[q].offloads;
+ printf(" Queue[%2d] :", q);
+ print_rx_offloads(queue_offloads);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+cmdline_parse_inst_t cmd_rx_offload_get_configuration = {
+ .f = cmd_rx_offload_get_configuration_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rx_offload configuration",
+ .tokens = {
+ (void *)&cmd_rx_offload_get_configuration_show,
+ (void *)&cmd_rx_offload_get_configuration_port,
+ (void *)&cmd_rx_offload_get_configuration_port_id,
+ (void *)&cmd_rx_offload_get_configuration_rx_offload,
+ (void *)&cmd_rx_offload_get_configuration_configuration,
+ NULL,
+ }
+};
+
+/* Enable/Disable a per port offloading */
+struct cmd_config_per_port_rx_offload_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t rx_offload;
+ cmdline_fixed_string_t offload;
+ cmdline_fixed_string_t on_off;
+};
+
+cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_config_per_port_rx_offload_result_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_rx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ rx_offload, "rx_offload");
+cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ offload, "vlan_strip#ipv4_cksum#udp_cksum#tcp_cksum#tcp_lro#"
+ "qinq_strip#outer_ipv4_cksum#macsec_strip#"
+ "header_split#vlan_filter#vlan_extend#jumbo_frame#"
+ "scatter#timestamp#security#keep_crc#rss_hash");
+cmdline_parse_token_string_t cmd_config_per_port_rx_offload_result_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_rx_offload_result,
+ on_off, "on#off");
+
+static uint64_t
+search_rx_offload(const char *name)
+{
+ uint64_t single_offload;
+ const char *single_name;
+ int found = 0;
+ unsigned int bit;
+
+ single_offload = 1;
+ for (bit = 0; bit < sizeof(single_offload) * CHAR_BIT; bit++) {
+ single_name = rte_eth_dev_rx_offload_name(single_offload);
+ if (!strcasecmp(single_name, name)) {
+ found = 1;
+ break;
+ }
+ single_offload <<= 1;
+ }
+
+ if (found)
+ return single_offload;
+
+ return 0;
+}
+
+static void
+cmd_config_per_port_rx_offload_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_per_port_rx_offload_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ struct rte_eth_dev_info dev_info;
+ struct rte_port *port = &ports[port_id];
+ uint64_t single_offload;
+ uint16_t nb_rx_queues;
+ int q;
+ int ret;
+
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Error: Can't config offload when Port %d "
+ "is not stopped\n", port_id);
+ return;
+ }
+
+ single_offload = search_rx_offload(res->offload);
+ if (single_offload == 0) {
+ printf("Unknown offload name: %s\n", res->offload);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ nb_rx_queues = dev_info.nb_rx_queues;
+ if (!strcmp(res->on_off, "on")) {
+ port->dev_conf.rxmode.offloads |= single_offload;
+ for (q = 0; q < nb_rx_queues; q++)
+ port->rx_conf[q].offloads |= single_offload;
+ } else {
+ port->dev_conf.rxmode.offloads &= ~single_offload;
+ for (q = 0; q < nb_rx_queues; q++)
+ port->rx_conf[q].offloads &= ~single_offload;
+ }
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_inst_t cmd_config_per_port_rx_offload = {
+ .f = cmd_config_per_port_rx_offload_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> rx_offload vlan_strip|ipv4_cksum|"
+ "udp_cksum|tcp_cksum|tcp_lro|qinq_strip|outer_ipv4_cksum|"
+ "macsec_strip|header_split|vlan_filter|vlan_extend|"
+ "jumbo_frame|scatter|timestamp|security|keep_crc|rss_hash "
+ "on|off",
+ .tokens = {
+ (void *)&cmd_config_per_port_rx_offload_result_port,
+ (void *)&cmd_config_per_port_rx_offload_result_config,
+ (void *)&cmd_config_per_port_rx_offload_result_port_id,
+ (void *)&cmd_config_per_port_rx_offload_result_rx_offload,
+ (void *)&cmd_config_per_port_rx_offload_result_offload,
+ (void *)&cmd_config_per_port_rx_offload_result_on_off,
+ NULL,
+ }
+};
+
+/* Enable/Disable a per queue offloading */
+struct cmd_config_per_queue_rx_offload_result {
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t rxq;
+ uint16_t queue_id;
+ cmdline_fixed_string_t rx_offload;
+ cmdline_fixed_string_t offload;
+ cmdline_fixed_string_t on_off;
+};
+
+cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_config_per_queue_rx_offload_result_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_rxq =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ rxq, "rxq");
+cmdline_parse_token_num_t cmd_config_per_queue_rx_offload_result_queue_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_rxoffload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ rx_offload, "rx_offload");
+cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ offload, "vlan_strip#ipv4_cksum#udp_cksum#tcp_cksum#tcp_lro#"
+ "qinq_strip#outer_ipv4_cksum#macsec_strip#"
+ "header_split#vlan_filter#vlan_extend#jumbo_frame#"
+ "scatter#timestamp#security#keep_crc");
+cmdline_parse_token_string_t cmd_config_per_queue_rx_offload_result_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_rx_offload_result,
+ on_off, "on#off");
+
+static void
+cmd_config_per_queue_rx_offload_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_per_queue_rx_offload_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ uint16_t queue_id = res->queue_id;
+ struct rte_port *port = &ports[port_id];
+ uint64_t single_offload;
+ int ret;
+
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Error: Can't config offload when Port %d "
+ "is not stopped\n", port_id);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (queue_id >= dev_info.nb_rx_queues) {
+ printf("Error: input queue_id should be 0 ... "
+ "%d\n", dev_info.nb_rx_queues - 1);
+ return;
+ }
+
+ single_offload = search_rx_offload(res->offload);
+ if (single_offload == 0) {
+ printf("Unknown offload name: %s\n", res->offload);
+ return;
+ }
+
+ if (!strcmp(res->on_off, "on"))
+ port->rx_conf[queue_id].offloads |= single_offload;
+ else
+ port->rx_conf[queue_id].offloads &= ~single_offload;
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_inst_t cmd_config_per_queue_rx_offload = {
+ .f = cmd_config_per_queue_rx_offload_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> rxq <queue_id> rx_offload "
+ "vlan_strip|ipv4_cksum|"
+ "udp_cksum|tcp_cksum|tcp_lro|qinq_strip|outer_ipv4_cksum|"
+ "macsec_strip|header_split|vlan_filter|vlan_extend|"
+ "jumbo_frame|scatter|timestamp|security|keep_crc "
+ "on|off",
+ .tokens = {
+ (void *)&cmd_config_per_queue_rx_offload_result_port,
+ (void *)&cmd_config_per_queue_rx_offload_result_port_id,
+ (void *)&cmd_config_per_queue_rx_offload_result_rxq,
+ (void *)&cmd_config_per_queue_rx_offload_result_queue_id,
+ (void *)&cmd_config_per_queue_rx_offload_result_rxoffload,
+ (void *)&cmd_config_per_queue_rx_offload_result_offload,
+ (void *)&cmd_config_per_queue_rx_offload_result_on_off,
+ NULL,
+ }
+};
+
+/* Get Tx offloads capabilities */
+struct cmd_tx_offload_get_capa_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t tx_offload;
+ cmdline_fixed_string_t capabilities;
+};
+
+cmdline_parse_token_string_t cmd_tx_offload_get_capa_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_capa_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_tx_offload_get_capa_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_capa_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_tx_offload_get_capa_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_tx_offload_get_capa_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_tx_offload_get_capa_tx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_capa_result,
+ tx_offload, "tx_offload");
+cmdline_parse_token_string_t cmd_tx_offload_get_capa_capabilities =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_capa_result,
+ capabilities, "capabilities");
+
+static void
+print_tx_offloads(uint64_t offloads)
+{
+ uint64_t single_offload;
+ int begin;
+ int end;
+ int bit;
+
+ if (offloads == 0)
+ return;
+
+ begin = __builtin_ctzll(offloads);
+ end = sizeof(offloads) * CHAR_BIT - __builtin_clzll(offloads);
+
+ single_offload = 1ULL << begin;
+ for (bit = begin; bit < end; bit++) {
+ if (offloads & single_offload)
+ printf(" %s",
+ rte_eth_dev_tx_offload_name(single_offload));
+ single_offload <<= 1;
+ }
+}
+
+static void
+cmd_tx_offload_get_capa_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_offload_get_capa_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ uint64_t queue_offloads;
+ uint64_t port_offloads;
+ int ret;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ queue_offloads = dev_info.tx_queue_offload_capa;
+ port_offloads = dev_info.tx_offload_capa ^ queue_offloads;
+
+ printf("Tx Offloading Capabilities of port %d :\n", port_id);
+ printf(" Per Queue :");
+ print_tx_offloads(queue_offloads);
+
+ printf("\n");
+ printf(" Per Port :");
+ print_tx_offloads(port_offloads);
+ printf("\n\n");
+}
+
+cmdline_parse_inst_t cmd_tx_offload_get_capa = {
+ .f = cmd_tx_offload_get_capa_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> tx_offload capabilities",
+ .tokens = {
+ (void *)&cmd_tx_offload_get_capa_show,
+ (void *)&cmd_tx_offload_get_capa_port,
+ (void *)&cmd_tx_offload_get_capa_port_id,
+ (void *)&cmd_tx_offload_get_capa_tx_offload,
+ (void *)&cmd_tx_offload_get_capa_capabilities,
+ NULL,
+ }
+};
+
+/* Get Tx offloads configuration */
+struct cmd_tx_offload_get_configuration_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t tx_offload;
+ cmdline_fixed_string_t configuration;
+};
+
+cmdline_parse_token_string_t cmd_tx_offload_get_configuration_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_configuration_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_tx_offload_get_configuration_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_configuration_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_tx_offload_get_configuration_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_tx_offload_get_configuration_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_tx_offload_get_configuration_tx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_configuration_result,
+ tx_offload, "tx_offload");
+cmdline_parse_token_string_t cmd_tx_offload_get_configuration_configuration =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_tx_offload_get_configuration_result,
+ configuration, "configuration");
+
+static void
+cmd_tx_offload_get_configuration_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_tx_offload_get_configuration_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ struct rte_port *port = &ports[port_id];
+ uint64_t port_offloads;
+ uint64_t queue_offloads;
+ uint16_t nb_tx_queues;
+ int q;
+ int ret;
+
+ printf("Tx Offloading Configuration of port %d :\n", port_id);
+
+ port_offloads = port->dev_conf.txmode.offloads;
+ printf(" Port :");
+ print_tx_offloads(port_offloads);
+ printf("\n");
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ nb_tx_queues = dev_info.nb_tx_queues;
+ for (q = 0; q < nb_tx_queues; q++) {
+ queue_offloads = port->tx_conf[q].offloads;
+ printf(" Queue[%2d] :", q);
+ print_tx_offloads(queue_offloads);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+cmdline_parse_inst_t cmd_tx_offload_get_configuration = {
+ .f = cmd_tx_offload_get_configuration_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> tx_offload configuration",
+ .tokens = {
+ (void *)&cmd_tx_offload_get_configuration_show,
+ (void *)&cmd_tx_offload_get_configuration_port,
+ (void *)&cmd_tx_offload_get_configuration_port_id,
+ (void *)&cmd_tx_offload_get_configuration_tx_offload,
+ (void *)&cmd_tx_offload_get_configuration_configuration,
+ NULL,
+ }
+};
+
+/* Enable/Disable a per port offloading */
+struct cmd_config_per_port_tx_offload_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t config;
+ portid_t port_id;
+ cmdline_fixed_string_t tx_offload;
+ cmdline_fixed_string_t offload;
+ cmdline_fixed_string_t on_off;
+};
+
+cmdline_parse_token_string_t cmd_config_per_port_tx_offload_result_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_per_port_tx_offload_result_config =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ config, "config");
+cmdline_parse_token_num_t cmd_config_per_port_tx_offload_result_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_port_tx_offload_result_tx_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ tx_offload, "tx_offload");
+cmdline_parse_token_string_t cmd_config_per_port_tx_offload_result_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ offload, "vlan_insert#ipv4_cksum#udp_cksum#tcp_cksum#"
+ "sctp_cksum#tcp_tso#udp_tso#outer_ipv4_cksum#"
+ "qinq_insert#vxlan_tnl_tso#gre_tnl_tso#"
+ "ipip_tnl_tso#geneve_tnl_tso#macsec_insert#"
+ "mt_lockfree#multi_segs#mbuf_fast_free#security");
+cmdline_parse_token_string_t cmd_config_per_port_tx_offload_result_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_port_tx_offload_result,
+ on_off, "on#off");
+
+static uint64_t
+search_tx_offload(const char *name)
+{
+ uint64_t single_offload;
+ const char *single_name;
+ int found = 0;
+ unsigned int bit;
+
+ single_offload = 1;
+ for (bit = 0; bit < sizeof(single_offload) * CHAR_BIT; bit++) {
+ single_name = rte_eth_dev_tx_offload_name(single_offload);
+ if (single_name == NULL)
+ break;
+ if (!strcasecmp(single_name, name)) {
+ found = 1;
+ break;
+ } else if (!strcasecmp(single_name, "UNKNOWN"))
+ break;
+ single_offload <<= 1;
+ }
+
+ if (found)
+ return single_offload;
+
+ return 0;
+}
+
+static void
+cmd_config_per_port_tx_offload_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_per_port_tx_offload_result *res = parsed_result;
+ portid_t port_id = res->port_id;
+ struct rte_eth_dev_info dev_info;
+ struct rte_port *port = &ports[port_id];
+ uint64_t single_offload;
+ uint16_t nb_tx_queues;
+ int q;
+ int ret;
+
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Error: Can't config offload when Port %d "
+ "is not stopped\n", port_id);
+ return;
+ }
+
+ single_offload = search_tx_offload(res->offload);
+ if (single_offload == 0) {
+ printf("Unknown offload name: %s\n", res->offload);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ nb_tx_queues = dev_info.nb_tx_queues;
+ if (!strcmp(res->on_off, "on")) {
+ port->dev_conf.txmode.offloads |= single_offload;
+ for (q = 0; q < nb_tx_queues; q++)
+ port->tx_conf[q].offloads |= single_offload;
+ } else {
+ port->dev_conf.txmode.offloads &= ~single_offload;
+ for (q = 0; q < nb_tx_queues; q++)
+ port->tx_conf[q].offloads &= ~single_offload;
+ }
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_inst_t cmd_config_per_port_tx_offload = {
+ .f = cmd_config_per_port_tx_offload_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> tx_offload "
+ "vlan_insert|ipv4_cksum|udp_cksum|tcp_cksum|"
+ "sctp_cksum|tcp_tso|udp_tso|outer_ipv4_cksum|"
+ "qinq_insert|vxlan_tnl_tso|gre_tnl_tso|"
+ "ipip_tnl_tso|geneve_tnl_tso|macsec_insert|"
+ "mt_lockfree|multi_segs|mbuf_fast_free|security on|off",
+ .tokens = {
+ (void *)&cmd_config_per_port_tx_offload_result_port,
+ (void *)&cmd_config_per_port_tx_offload_result_config,
+ (void *)&cmd_config_per_port_tx_offload_result_port_id,
+ (void *)&cmd_config_per_port_tx_offload_result_tx_offload,
+ (void *)&cmd_config_per_port_tx_offload_result_offload,
+ (void *)&cmd_config_per_port_tx_offload_result_on_off,
+ NULL,
+ }
+};
+
+/* Enable/Disable a per queue offloading */
+struct cmd_config_per_queue_tx_offload_result {
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t txq;
+ uint16_t queue_id;
+ cmdline_fixed_string_t tx_offload;
+ cmdline_fixed_string_t offload;
+ cmdline_fixed_string_t on_off;
+};
+
+cmdline_parse_token_string_t cmd_config_per_queue_tx_offload_result_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_config_per_queue_tx_offload_result_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_queue_tx_offload_result_txq =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ txq, "txq");
+cmdline_parse_token_num_t cmd_config_per_queue_tx_offload_result_queue_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ queue_id, UINT16);
+cmdline_parse_token_string_t cmd_config_per_queue_tx_offload_result_txoffload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ tx_offload, "tx_offload");
+cmdline_parse_token_string_t cmd_config_per_queue_tx_offload_result_offload =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ offload, "vlan_insert#ipv4_cksum#udp_cksum#tcp_cksum#"
+ "sctp_cksum#tcp_tso#udp_tso#outer_ipv4_cksum#"
+ "qinq_insert#vxlan_tnl_tso#gre_tnl_tso#"
+ "ipip_tnl_tso#geneve_tnl_tso#macsec_insert#"
+ "mt_lockfree#multi_segs#mbuf_fast_free#security");
+cmdline_parse_token_string_t cmd_config_per_queue_tx_offload_result_on_off =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_config_per_queue_tx_offload_result,
+ on_off, "on#off");
+
+static void
+cmd_config_per_queue_tx_offload_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_per_queue_tx_offload_result *res = parsed_result;
+ struct rte_eth_dev_info dev_info;
+ portid_t port_id = res->port_id;
+ uint16_t queue_id = res->queue_id;
+ struct rte_port *port = &ports[port_id];
+ uint64_t single_offload;
+ int ret;
+
+ if (port->port_status != RTE_PORT_STOPPED) {
+ printf("Error: Can't config offload when Port %d "
+ "is not stopped\n", port_id);
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (queue_id >= dev_info.nb_tx_queues) {
+ printf("Error: input queue_id should be 0 ... "
+ "%d\n", dev_info.nb_tx_queues - 1);
+ return;
+ }
+
+ single_offload = search_tx_offload(res->offload);
+ if (single_offload == 0) {
+ printf("Unknown offload name: %s\n", res->offload);
+ return;
+ }
+
+ if (!strcmp(res->on_off, "on"))
+ port->tx_conf[queue_id].offloads |= single_offload;
+ else
+ port->tx_conf[queue_id].offloads &= ~single_offload;
+
+ cmd_reconfig_device_queue(port_id, 1, 1);
+}
+
+cmdline_parse_inst_t cmd_config_per_queue_tx_offload = {
+ .f = cmd_config_per_queue_tx_offload_parsed,
+ .data = NULL,
+ .help_str = "port <port_id> txq <queue_id> tx_offload "
+ "vlan_insert|ipv4_cksum|udp_cksum|tcp_cksum|"
+ "sctp_cksum|tcp_tso|udp_tso|outer_ipv4_cksum|"
+ "qinq_insert|vxlan_tnl_tso|gre_tnl_tso|"
+ "ipip_tnl_tso|geneve_tnl_tso|macsec_insert|"
+ "mt_lockfree|multi_segs|mbuf_fast_free|security "
+ "on|off",
+ .tokens = {
+ (void *)&cmd_config_per_queue_tx_offload_result_port,
+ (void *)&cmd_config_per_queue_tx_offload_result_port_id,
+ (void *)&cmd_config_per_queue_tx_offload_result_txq,
+ (void *)&cmd_config_per_queue_tx_offload_result_queue_id,
+ (void *)&cmd_config_per_queue_tx_offload_result_txoffload,
+ (void *)&cmd_config_per_queue_tx_offload_result_offload,
+ (void *)&cmd_config_per_queue_tx_offload_result_on_off,
+ NULL,
+ }
+};
+
+/* *** configure tx_metadata for specific port *** */
+struct cmd_config_tx_metadata_specific_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint16_t port_id;
+ cmdline_fixed_string_t item;
+ uint32_t value;
+};
+
+static void
+cmd_config_tx_metadata_specific_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_tx_metadata_specific_result *res = parsed_result;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+ ports[res->port_id].tx_metadata = res->value;
+ /* Add/remove callback to insert valid metadata in every Tx packet. */
+ if (ports[res->port_id].tx_metadata)
+ add_tx_md_callback(res->port_id);
+ else
+ remove_tx_md_callback(res->port_id);
+ rte_flow_dynf_metadata_register();
+}
+
+cmdline_parse_token_string_t cmd_config_tx_metadata_specific_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_metadata_specific_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_config_tx_metadata_specific_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_metadata_specific_result,
+ keyword, "config");
+cmdline_parse_token_num_t cmd_config_tx_metadata_specific_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_tx_metadata_specific_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_tx_metadata_specific_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_metadata_specific_result,
+ item, "tx_metadata");
+cmdline_parse_token_num_t cmd_config_tx_metadata_specific_value =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_tx_metadata_specific_result,
+ value, UINT32);
+
+cmdline_parse_inst_t cmd_config_tx_metadata_specific = {
+ .f = cmd_config_tx_metadata_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port_id> tx_metadata <value>",
+ .tokens = {
+ (void *)&cmd_config_tx_metadata_specific_port,
+ (void *)&cmd_config_tx_metadata_specific_keyword,
+ (void *)&cmd_config_tx_metadata_specific_id,
+ (void *)&cmd_config_tx_metadata_specific_item,
+ (void *)&cmd_config_tx_metadata_specific_value,
+ NULL,
+ },
+};
+
+/* *** set dynf *** */
+struct cmd_config_tx_dynf_specific_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t keyword;
+ uint16_t port_id;
+ cmdline_fixed_string_t item;
+ cmdline_fixed_string_t name;
+ cmdline_fixed_string_t value;
+};
+
+static void
+cmd_config_dynf_specific_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_config_tx_dynf_specific_result *res = parsed_result;
+ struct rte_mbuf_dynflag desc_flag;
+ int flag;
+ uint64_t old_port_flags;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+ flag = rte_mbuf_dynflag_lookup(res->name, NULL);
+ if (flag <= 0) {
+ if (strlcpy(desc_flag.name, res->name,
+ RTE_MBUF_DYN_NAMESIZE) >= RTE_MBUF_DYN_NAMESIZE) {
+ printf("Flag name too long\n");
+ return;
+ }
+ desc_flag.flags = 0;
+ flag = rte_mbuf_dynflag_register(&desc_flag);
+ if (flag < 0) {
+ printf("Can't register flag\n");
+ return;
+ }
+ strcpy(dynf_names[flag], desc_flag.name);
+ }
+ old_port_flags = ports[res->port_id].mbuf_dynf;
+ if (!strcmp(res->value, "set")) {
+ ports[res->port_id].mbuf_dynf |= 1UL << flag;
+ if (old_port_flags == 0)
+ add_tx_dynf_callback(res->port_id);
+ } else {
+ ports[res->port_id].mbuf_dynf &= ~(1UL << flag);
+ if (ports[res->port_id].mbuf_dynf == 0)
+ remove_tx_dynf_callback(res->port_id);
+ }
+}
+
+cmdline_parse_token_string_t cmd_config_tx_dynf_specific_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ keyword, "port");
+cmdline_parse_token_string_t cmd_config_tx_dynf_specific_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ keyword, "config");
+cmdline_parse_token_num_t cmd_config_tx_dynf_specific_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_config_tx_dynf_specific_item =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ item, "dynf");
+cmdline_parse_token_string_t cmd_config_tx_dynf_specific_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ name, NULL);
+cmdline_parse_token_string_t cmd_config_tx_dynf_specific_value =
+ TOKEN_STRING_INITIALIZER(struct cmd_config_tx_dynf_specific_result,
+ value, "set#clear");
+
+cmdline_parse_inst_t cmd_config_tx_dynf_specific = {
+ .f = cmd_config_dynf_specific_parsed,
+ .data = NULL,
+ .help_str = "port config <port id> dynf <name> set|clear",
+ .tokens = {
+ (void *)&cmd_config_tx_dynf_specific_port,
+ (void *)&cmd_config_tx_dynf_specific_keyword,
+ (void *)&cmd_config_tx_dynf_specific_port_id,
+ (void *)&cmd_config_tx_dynf_specific_item,
+ (void *)&cmd_config_tx_dynf_specific_name,
+ (void *)&cmd_config_tx_dynf_specific_value,
+ NULL,
+ },
+};
+
+/* *** display tx_metadata per port configuration *** */
+struct cmd_show_tx_metadata_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_show_tx_metadata_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_tx_metadata_result *res = parsed_result;
+
+ if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+ printf("invalid port id %u\n", res->cmd_pid);
+ return;
+ }
+ if (!strcmp(res->cmd_keyword, "tx_metadata")) {
+ printf("Port %u tx_metadata: %u\n", res->cmd_pid,
+ ports[res->cmd_pid].tx_metadata);
+ }
+}
+
+cmdline_parse_token_string_t cmd_show_tx_metadata_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_tx_metadata_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_tx_metadata_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_tx_metadata_result,
+ cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_tx_metadata_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_tx_metadata_result,
+ cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_tx_metadata_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_tx_metadata_result,
+ cmd_keyword, "tx_metadata");
+
+cmdline_parse_inst_t cmd_show_tx_metadata = {
+ .f = cmd_show_tx_metadata_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> tx_metadata",
+ .tokens = {
+ (void *)&cmd_show_tx_metadata_show,
+ (void *)&cmd_show_tx_metadata_port,
+ (void *)&cmd_show_tx_metadata_pid,
+ (void *)&cmd_show_tx_metadata_keyword,
+ NULL,
+ },
+};
+
+/* show port supported ptypes */
+
+/* Common result structure for show port ptypes */
+struct cmd_show_port_supported_ptypes_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t ptypes;
+};
+
+/* Common CLI fields for show port ptypes */
+cmdline_parse_token_string_t cmd_show_port_supported_ptypes_show =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_port_supported_ptypes_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_port_supported_ptypes_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_port_supported_ptypes_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_show_port_supported_ptypes_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_show_port_supported_ptypes_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_show_port_supported_ptypes_ptypes =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_show_port_supported_ptypes_result,
+ ptypes, "ptypes");
+
+static void
+cmd_show_port_supported_ptypes_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+#define RSVD_PTYPE_MASK 0xf0000000
+#define MAX_PTYPES_PER_LAYER 16
+#define LTYPE_NAMESIZE 32
+#define PTYPE_NAMESIZE 256
+ struct cmd_show_port_supported_ptypes_result *res = parsed_result;
+ char buf[PTYPE_NAMESIZE], ltype[LTYPE_NAMESIZE];
+ uint32_t ptype_mask = RTE_PTYPE_L2_MASK;
+ uint32_t ptypes[MAX_PTYPES_PER_LAYER];
+ uint16_t port_id = res->port_id;
+ int ret, i;
+
+ ret = rte_eth_dev_get_supported_ptypes(port_id, ptype_mask, NULL, 0);
+ if (ret < 0)
+ return;
+
+ while (ptype_mask != RSVD_PTYPE_MASK) {
+
+ switch (ptype_mask) {
+ case RTE_PTYPE_L2_MASK:
+ strlcpy(ltype, "L2", sizeof(ltype));
+ break;
+ case RTE_PTYPE_L3_MASK:
+ strlcpy(ltype, "L3", sizeof(ltype));
+ break;
+ case RTE_PTYPE_L4_MASK:
+ strlcpy(ltype, "L4", sizeof(ltype));
+ break;
+ case RTE_PTYPE_TUNNEL_MASK:
+ strlcpy(ltype, "Tunnel", sizeof(ltype));
+ break;
+ case RTE_PTYPE_INNER_L2_MASK:
+ strlcpy(ltype, "Inner L2", sizeof(ltype));
+ break;
+ case RTE_PTYPE_INNER_L3_MASK:
+ strlcpy(ltype, "Inner L3", sizeof(ltype));
+ break;
+ case RTE_PTYPE_INNER_L4_MASK:
+ strlcpy(ltype, "Inner L4", sizeof(ltype));
+ break;
+ default:
+ return;
+ }
+
+ ret = rte_eth_dev_get_supported_ptypes(res->port_id,
+ ptype_mask, ptypes,
+ MAX_PTYPES_PER_LAYER);
+
+ if (ret > 0)
+ printf("Supported %s ptypes:\n", ltype);
+ else
+ printf("%s ptypes unsupported\n", ltype);
+
+ for (i = 0; i < ret; ++i) {
+ rte_get_ptype_name(ptypes[i], buf, sizeof(buf));
+ printf("%s\n", buf);
+ }
+
+ ptype_mask <<= 4;
+ }
+}
+
+cmdline_parse_inst_t cmd_show_port_supported_ptypes = {
+ .f = cmd_show_port_supported_ptypes_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> ptypes",
+ .tokens = {
+ (void *)&cmd_show_port_supported_ptypes_show,
+ (void *)&cmd_show_port_supported_ptypes_port,
+ (void *)&cmd_show_port_supported_ptypes_port_id,
+ (void *)&cmd_show_port_supported_ptypes_ptypes,
+ NULL,
+ },
+};
+
+/* *** display rx/tx descriptor status *** */
+struct cmd_show_rx_tx_desc_status_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ cmdline_fixed_string_t cmd_desc;
+ cmdline_fixed_string_t cmd_status;
+ portid_t cmd_pid;
+ portid_t cmd_qid;
+ portid_t cmd_did;
+};
+
+static void
+cmd_show_rx_tx_desc_status_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_rx_tx_desc_status_result *res = parsed_result;
+ int rc;
+
+ if (!rte_eth_dev_is_valid_port(res->cmd_pid)) {
+ printf("invalid port id %u\n", res->cmd_pid);
+ return;
+ }
+
+ if (!strcmp(res->cmd_keyword, "rxq")) {
+ rc = rte_eth_rx_descriptor_status(res->cmd_pid, res->cmd_qid,
+ res->cmd_did);
+ if (rc < 0) {
+ printf("Invalid queueid = %d\n", res->cmd_qid);
+ return;
+ }
+ if (rc == RTE_ETH_RX_DESC_AVAIL)
+ printf("Desc status = AVAILABLE\n");
+ else if (rc == RTE_ETH_RX_DESC_DONE)
+ printf("Desc status = DONE\n");
+ else
+ printf("Desc status = UNAVAILABLE\n");
+ } else if (!strcmp(res->cmd_keyword, "txq")) {
+ rc = rte_eth_tx_descriptor_status(res->cmd_pid, res->cmd_qid,
+ res->cmd_did);
+ if (rc < 0) {
+ printf("Invalid queueid = %d\n", res->cmd_qid);
+ return;
+ }
+ if (rc == RTE_ETH_TX_DESC_FULL)
+ printf("Desc status = FULL\n");
+ else if (rc == RTE_ETH_TX_DESC_DONE)
+ printf("Desc status = DONE\n");
+ else
+ printf("Desc status = UNAVAILABLE\n");
+ }
+}
+
+cmdline_parse_token_string_t cmd_show_rx_tx_desc_status_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_rx_tx_desc_status_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_port, "port");
+cmdline_parse_token_num_t cmd_show_rx_tx_desc_status_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_show_rx_tx_desc_status_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_keyword, "rxq#txq");
+cmdline_parse_token_num_t cmd_show_rx_tx_desc_status_qid =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_qid, UINT16);
+cmdline_parse_token_string_t cmd_show_rx_tx_desc_status_desc =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_desc, "desc");
+cmdline_parse_token_num_t cmd_show_rx_tx_desc_status_did =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_did, UINT16);
+cmdline_parse_token_string_t cmd_show_rx_tx_desc_status_status =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_rx_tx_desc_status_result,
+ cmd_status, "status");
+cmdline_parse_inst_t cmd_show_rx_tx_desc_status = {
+ .f = cmd_show_rx_tx_desc_status_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> rxq|txq <queue_id> desc <desc_id> "
+ "status",
+ .tokens = {
+ (void *)&cmd_show_rx_tx_desc_status_show,
+ (void *)&cmd_show_rx_tx_desc_status_port,
+ (void *)&cmd_show_rx_tx_desc_status_pid,
+ (void *)&cmd_show_rx_tx_desc_status_keyword,
+ (void *)&cmd_show_rx_tx_desc_status_qid,
+ (void *)&cmd_show_rx_tx_desc_status_desc,
+ (void *)&cmd_show_rx_tx_desc_status_did,
+ (void *)&cmd_show_rx_tx_desc_status_status,
+ NULL,
+ },
+};
+
+/* Common result structure for set port ptypes */
+struct cmd_set_port_ptypes_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ portid_t port_id;
+ cmdline_fixed_string_t ptype_mask;
+ uint32_t mask;
+};
+
+/* Common CLI fields for set port ptypes */
+cmdline_parse_token_string_t cmd_set_port_ptypes_set =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_port_ptypes_result,
+ set, "set");
+cmdline_parse_token_string_t cmd_set_port_ptypes_port =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_port_ptypes_result,
+ port, "port");
+cmdline_parse_token_num_t cmd_set_port_ptypes_port_id =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_port_ptypes_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_set_port_ptypes_mask_str =
+ TOKEN_STRING_INITIALIZER
+ (struct cmd_set_port_ptypes_result,
+ ptype_mask, "ptype_mask");
+cmdline_parse_token_num_t cmd_set_port_ptypes_mask_u32 =
+ TOKEN_NUM_INITIALIZER
+ (struct cmd_set_port_ptypes_result,
+ mask, UINT32);
+
+static void
+cmd_set_port_ptypes_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_ptypes_result *res = parsed_result;
+#define PTYPE_NAMESIZE 256
+ char ptype_name[PTYPE_NAMESIZE];
+ uint16_t port_id = res->port_id;
+ uint32_t ptype_mask = res->mask;
+ int ret, i;
+
+ ret = rte_eth_dev_get_supported_ptypes(port_id, RTE_PTYPE_ALL_MASK,
+ NULL, 0);
+ if (ret <= 0) {
+ printf("Port %d doesn't support any ptypes.\n", port_id);
+ return;
+ }
+
+ uint32_t ptypes[ret];
+
+ ret = rte_eth_dev_set_ptypes(port_id, ptype_mask, ptypes, ret);
+ if (ret < 0) {
+ printf("Unable to set requested ptypes for Port %d\n", port_id);
+ return;
+ }
+
+ printf("Successfully set following ptypes for Port %d\n", port_id);
+ for (i = 0; i < ret && ptypes[i] != RTE_PTYPE_UNKNOWN; i++) {
+ rte_get_ptype_name(ptypes[i], ptype_name, sizeof(ptype_name));
+ printf("%s\n", ptype_name);
+ }
+
+ clear_ptypes = false;
+}
+
+cmdline_parse_inst_t cmd_set_port_ptypes = {
+ .f = cmd_set_port_ptypes_parsed,
+ .data = NULL,
+ .help_str = "set port <port_id> ptype_mask <mask>",
+ .tokens = {
+ (void *)&cmd_set_port_ptypes_set,
+ (void *)&cmd_set_port_ptypes_port,
+ (void *)&cmd_set_port_ptypes_port_id,
+ (void *)&cmd_set_port_ptypes_mask_str,
+ (void *)&cmd_set_port_ptypes_mask_u32,
+ NULL,
+ },
+};
+
+/* *** display mac addresses added to a port *** */
+struct cmd_showport_macs_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_port;
+ cmdline_fixed_string_t cmd_keyword;
+ portid_t cmd_pid;
+};
+
+static void
+cmd_showport_macs_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_showport_macs_result *res = parsed_result;
+
+ if (port_id_is_invalid(res->cmd_pid, ENABLED_WARN))
+ return;
+
+ if (!strcmp(res->cmd_keyword, "macs"))
+ show_macs(res->cmd_pid);
+ else if (!strcmp(res->cmd_keyword, "mcast_macs"))
+ show_mcast_macs(res->cmd_pid);
+}
+
+cmdline_parse_token_string_t cmd_showport_macs_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_macs_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_showport_macs_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_macs_result,
+ cmd_port, "port");
+cmdline_parse_token_num_t cmd_showport_macs_pid =
+ TOKEN_NUM_INITIALIZER(struct cmd_showport_macs_result,
+ cmd_pid, UINT16);
+cmdline_parse_token_string_t cmd_showport_macs_keyword =
+ TOKEN_STRING_INITIALIZER(struct cmd_showport_macs_result,
+ cmd_keyword, "macs#mcast_macs");
+
+cmdline_parse_inst_t cmd_showport_macs = {
+ .f = cmd_showport_macs_parsed,
+ .data = NULL,
+ .help_str = "show port <port_id> macs|mcast_macs",
+ .tokens = {
+ (void *)&cmd_showport_macs_show,
+ (void *)&cmd_showport_macs_port,
+ (void *)&cmd_showport_macs_pid,
+ (void *)&cmd_showport_macs_keyword,
+ NULL,
+ },
+};
+
+/* ******************************************************************************** */
+
+/* list of instructions */
+cmdline_parse_ctx_t main_ctx[] = {
+ (cmdline_parse_inst_t *)&cmd_help_brief,
+ (cmdline_parse_inst_t *)&cmd_help_long,
+ (cmdline_parse_inst_t *)&cmd_quit,
+ (cmdline_parse_inst_t *)&cmd_load_from_file,
+ (cmdline_parse_inst_t *)&cmd_showport,
+ (cmdline_parse_inst_t *)&cmd_showqueue,
+ (cmdline_parse_inst_t *)&cmd_showportall,
+ (cmdline_parse_inst_t *)&cmd_showdevice,
+ (cmdline_parse_inst_t *)&cmd_showcfg,
+ (cmdline_parse_inst_t *)&cmd_showfwdall,
+ (cmdline_parse_inst_t *)&cmd_start,
+ (cmdline_parse_inst_t *)&cmd_start_tx_first,
+ (cmdline_parse_inst_t *)&cmd_start_tx_first_n,
+ (cmdline_parse_inst_t *)&cmd_set_link_up,
+ (cmdline_parse_inst_t *)&cmd_set_link_down,
+ (cmdline_parse_inst_t *)&cmd_reset,
+ (cmdline_parse_inst_t *)&cmd_set_numbers,
+ (cmdline_parse_inst_t *)&cmd_set_log,
+ (cmdline_parse_inst_t *)&cmd_set_txpkts,
+ (cmdline_parse_inst_t *)&cmd_set_txsplit,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_list,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_mask,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_mode,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_retry_mode,
+ (cmdline_parse_inst_t *)&cmd_set_burst_tx_retry,
+ (cmdline_parse_inst_t *)&cmd_set_promisc_mode_one,
+ (cmdline_parse_inst_t *)&cmd_set_promisc_mode_all,
+ (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_one,
+ (cmdline_parse_inst_t *)&cmd_set_allmulti_mode_all,
+ (cmdline_parse_inst_t *)&cmd_set_flush_rx,
+ (cmdline_parse_inst_t *)&cmd_set_link_check,
+ (cmdline_parse_inst_t *)&cmd_set_bypass_mode,
+ (cmdline_parse_inst_t *)&cmd_set_bypass_event,
+ (cmdline_parse_inst_t *)&cmd_set_bypass_timeout,
+ (cmdline_parse_inst_t *)&cmd_show_bypass_config,
+#ifdef RTE_LIBRTE_PMD_BOND
+ (cmdline_parse_inst_t *) &cmd_set_bonding_mode,
+ (cmdline_parse_inst_t *) &cmd_show_bonding_config,
+ (cmdline_parse_inst_t *) &cmd_set_bonding_primary,
+ (cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+ (cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
+ (cmdline_parse_inst_t *) &cmd_create_bonded_device,
+ (cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
+ (cmdline_parse_inst_t *) &cmd_set_balance_xmit_policy,
+ (cmdline_parse_inst_t *) &cmd_set_bond_mon_period,
+ (cmdline_parse_inst_t *) &cmd_set_lacp_dedicated_queues,
+ (cmdline_parse_inst_t *) &cmd_set_bonding_agg_mode_policy,
+#endif
+ (cmdline_parse_inst_t *)&cmd_vlan_offload,
+ (cmdline_parse_inst_t *)&cmd_vlan_tpid,
+ (cmdline_parse_inst_t *)&cmd_rx_vlan_filter_all,
+ (cmdline_parse_inst_t *)&cmd_rx_vlan_filter,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set_qinq,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_reset,
+ (cmdline_parse_inst_t *)&cmd_tx_vlan_set_pvid,
+ (cmdline_parse_inst_t *)&cmd_csum_set,
+ (cmdline_parse_inst_t *)&cmd_csum_show,
+ (cmdline_parse_inst_t *)&cmd_csum_tunnel,
+ (cmdline_parse_inst_t *)&cmd_tso_set,
+ (cmdline_parse_inst_t *)&cmd_tso_show,
+ (cmdline_parse_inst_t *)&cmd_tunnel_tso_set,
+ (cmdline_parse_inst_t *)&cmd_tunnel_tso_show,
+ (cmdline_parse_inst_t *)&cmd_gro_enable,
+ (cmdline_parse_inst_t *)&cmd_gro_flush,
+ (cmdline_parse_inst_t *)&cmd_gro_show,
+ (cmdline_parse_inst_t *)&cmd_gso_enable,
+ (cmdline_parse_inst_t *)&cmd_gso_size,
+ (cmdline_parse_inst_t *)&cmd_gso_show,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_rx,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_tx,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_hw,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_lw,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_pt,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_xon,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_macfwd,
+ (cmdline_parse_inst_t *)&cmd_link_flow_control_set_autoneg,
+ (cmdline_parse_inst_t *)&cmd_priority_flow_control_set,
+ (cmdline_parse_inst_t *)&cmd_config_dcb,
+ (cmdline_parse_inst_t *)&cmd_read_reg,
+ (cmdline_parse_inst_t *)&cmd_read_reg_bit_field,
+ (cmdline_parse_inst_t *)&cmd_read_reg_bit,
+ (cmdline_parse_inst_t *)&cmd_write_reg,
+ (cmdline_parse_inst_t *)&cmd_write_reg_bit_field,
+ (cmdline_parse_inst_t *)&cmd_write_reg_bit,
+ (cmdline_parse_inst_t *)&cmd_read_rxd_txd,
+ (cmdline_parse_inst_t *)&cmd_stop,
+ (cmdline_parse_inst_t *)&cmd_mac_addr,
+ (cmdline_parse_inst_t *)&cmd_set_fwd_eth_peer,
+ (cmdline_parse_inst_t *)&cmd_set_qmap,
+ (cmdline_parse_inst_t *)&cmd_set_xstats_hide_zero,
+ (cmdline_parse_inst_t *)&cmd_operate_port,
+ (cmdline_parse_inst_t *)&cmd_operate_specific_port,
+ (cmdline_parse_inst_t *)&cmd_operate_attach_port,
+ (cmdline_parse_inst_t *)&cmd_operate_detach_port,
+ (cmdline_parse_inst_t *)&cmd_operate_detach_device,
+ (cmdline_parse_inst_t *)&cmd_set_port_setup_on,
+ (cmdline_parse_inst_t *)&cmd_config_speed_all,
+ (cmdline_parse_inst_t *)&cmd_config_speed_specific,
+ (cmdline_parse_inst_t *)&cmd_config_loopback_all,
+ (cmdline_parse_inst_t *)&cmd_config_loopback_specific,
+ (cmdline_parse_inst_t *)&cmd_config_rx_tx,
+ (cmdline_parse_inst_t *)&cmd_config_mtu,
+ (cmdline_parse_inst_t *)&cmd_config_max_pkt_len,
+ (cmdline_parse_inst_t *)&cmd_config_max_lro_pkt_size,
+ (cmdline_parse_inst_t *)&cmd_config_rx_mode_flag,
+ (cmdline_parse_inst_t *)&cmd_config_rss,
+ (cmdline_parse_inst_t *)&cmd_config_rxtx_ring_size,
+ (cmdline_parse_inst_t *)&cmd_config_rxtx_queue,
+ (cmdline_parse_inst_t *)&cmd_config_deferred_start_rxtx_queue,
+ (cmdline_parse_inst_t *)&cmd_setup_rxtx_queue,
+ (cmdline_parse_inst_t *)&cmd_config_rss_reta,
+ (cmdline_parse_inst_t *)&cmd_showport_reta,
+ (cmdline_parse_inst_t *)&cmd_showport_macs,
+ (cmdline_parse_inst_t *)&cmd_config_burst,
+ (cmdline_parse_inst_t *)&cmd_config_thresh,
+ (cmdline_parse_inst_t *)&cmd_config_threshold,
+ (cmdline_parse_inst_t *)&cmd_set_uc_hash_filter,
+ (cmdline_parse_inst_t *)&cmd_set_uc_all_hash_filter,
+ (cmdline_parse_inst_t *)&cmd_vf_mac_addr_filter,
+ (cmdline_parse_inst_t *)&cmd_set_vf_macvlan_filter,
+ (cmdline_parse_inst_t *)&cmd_queue_rate_limit,
+ (cmdline_parse_inst_t *)&cmd_tunnel_filter,
+ (cmdline_parse_inst_t *)&cmd_tunnel_udp_config,
+ (cmdline_parse_inst_t *)&cmd_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_mirror_mask,
+ (cmdline_parse_inst_t *)&cmd_set_mirror_link,
+ (cmdline_parse_inst_t *)&cmd_reset_mirror_rule,
+ (cmdline_parse_inst_t *)&cmd_showport_rss_hash,
+ (cmdline_parse_inst_t *)&cmd_showport_rss_hash_key,
+ (cmdline_parse_inst_t *)&cmd_config_rss_hash_key,
+ (cmdline_parse_inst_t *)&cmd_dump,
+ (cmdline_parse_inst_t *)&cmd_dump_one,
+ (cmdline_parse_inst_t *)&cmd_ethertype_filter,
+ (cmdline_parse_inst_t *)&cmd_syn_filter,
+ (cmdline_parse_inst_t *)&cmd_2tuple_filter,
+ (cmdline_parse_inst_t *)&cmd_5tuple_filter,
+ (cmdline_parse_inst_t *)&cmd_flex_filter,
+ (cmdline_parse_inst_t *)&cmd_add_del_ip_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_l2_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_mac_vlan_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_tunnel_flow_director,
+ (cmdline_parse_inst_t *)&cmd_add_del_raw_flow_director,
+ (cmdline_parse_inst_t *)&cmd_flush_flow_director,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_ip_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_mac_vlan_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_tunnel_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_mask,
+ (cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
+ (cmdline_parse_inst_t *)&cmd_get_sym_hash_ena_per_port,
+ (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port,
+ (cmdline_parse_inst_t *)&cmd_get_hash_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_hash_global_config,
+ (cmdline_parse_inst_t *)&cmd_set_hash_input_set,
+ (cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
+ (cmdline_parse_inst_t *)&cmd_flow,
+ (cmdline_parse_inst_t *)&cmd_show_port_meter_cap,
+ (cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
+ (cmdline_parse_inst_t *)&cmd_add_port_meter_profile_trtcm,
+ (cmdline_parse_inst_t *)&cmd_del_port_meter_profile,
+ (cmdline_parse_inst_t *)&cmd_create_port_meter,
+ (cmdline_parse_inst_t *)&cmd_enable_port_meter,
+ (cmdline_parse_inst_t *)&cmd_disable_port_meter,
+ (cmdline_parse_inst_t *)&cmd_del_port_meter,
+ (cmdline_parse_inst_t *)&cmd_set_port_meter_profile,
+ (cmdline_parse_inst_t *)&cmd_set_port_meter_dscp_table,
+ (cmdline_parse_inst_t *)&cmd_set_port_meter_policer_action,
+ (cmdline_parse_inst_t *)&cmd_set_port_meter_stats_mask,
+ (cmdline_parse_inst_t *)&cmd_show_port_meter_stats,
+ (cmdline_parse_inst_t *)&cmd_mcast_addr,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_all,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_eth_type_specific,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_all,
+ (cmdline_parse_inst_t *)&cmd_config_l2_tunnel_en_dis_specific,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_en,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_insertion_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_stripping_en_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_forwarding_en_dis,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_filter_add,
+ (cmdline_parse_inst_t *)&cmd_config_e_tag_filter_del,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_anti_spoof,
+ (cmdline_parse_inst_t *)&cmd_set_vf_mac_anti_spoof,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_stripq,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_insert,
+ (cmdline_parse_inst_t *)&cmd_set_tx_loopback,
+ (cmdline_parse_inst_t *)&cmd_set_all_queues_drop_en,
+ (cmdline_parse_inst_t *)&cmd_set_vf_split_drop_en,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_offload_on,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_offload_off,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_sc,
+ (cmdline_parse_inst_t *)&cmd_set_macsec_sa,
+ (cmdline_parse_inst_t *)&cmd_set_vf_traffic,
+ (cmdline_parse_inst_t *)&cmd_set_vf_rxmode,
+ (cmdline_parse_inst_t *)&cmd_vf_rate_limit,
+ (cmdline_parse_inst_t *)&cmd_vf_rxvlan_filter,
+ (cmdline_parse_inst_t *)&cmd_set_vf_mac_addr,
+ (cmdline_parse_inst_t *)&cmd_set_vf_promisc,
+ (cmdline_parse_inst_t *)&cmd_set_vf_allmulti,
+ (cmdline_parse_inst_t *)&cmd_set_vf_broadcast,
+ (cmdline_parse_inst_t *)&cmd_set_vf_vlan_tag,
+ (cmdline_parse_inst_t *)&cmd_vf_max_bw,
+ (cmdline_parse_inst_t *)&cmd_vf_tc_min_bw,
+ (cmdline_parse_inst_t *)&cmd_vf_tc_max_bw,
+ (cmdline_parse_inst_t *)&cmd_strict_link_prio,
+ (cmdline_parse_inst_t *)&cmd_tc_min_bw,
+#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
+ (cmdline_parse_inst_t *)&cmd_set_port_tm_hierarchy_default,
+#endif
+ (cmdline_parse_inst_t *)&cmd_set_vxlan,
+ (cmdline_parse_inst_t *)&cmd_set_vxlan_tos_ttl,
+ (cmdline_parse_inst_t *)&cmd_set_vxlan_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_nvgre,
+ (cmdline_parse_inst_t *)&cmd_set_nvgre_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_l2_encap,
+ (cmdline_parse_inst_t *)&cmd_set_l2_encap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_l2_decap,
+ (cmdline_parse_inst_t *)&cmd_set_l2_decap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_mplsogre_encap,
+ (cmdline_parse_inst_t *)&cmd_set_mplsogre_encap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_mplsogre_decap,
+ (cmdline_parse_inst_t *)&cmd_set_mplsogre_decap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_mplsoudp_encap,
+ (cmdline_parse_inst_t *)&cmd_set_mplsoudp_encap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_set_mplsoudp_decap,
+ (cmdline_parse_inst_t *)&cmd_set_mplsoudp_decap_with_vlan,
+ (cmdline_parse_inst_t *)&cmd_ddp_add,
+ (cmdline_parse_inst_t *)&cmd_ddp_del,
+ (cmdline_parse_inst_t *)&cmd_ddp_get_list,
+ (cmdline_parse_inst_t *)&cmd_ddp_get_info,
+ (cmdline_parse_inst_t *)&cmd_cfg_input_set,
+ (cmdline_parse_inst_t *)&cmd_clear_input_set,
+ (cmdline_parse_inst_t *)&cmd_show_vf_stats,
+ (cmdline_parse_inst_t *)&cmd_clear_vf_stats,
+ (cmdline_parse_inst_t *)&cmd_show_port_supported_ptypes,
+ (cmdline_parse_inst_t *)&cmd_set_port_ptypes,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_get,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
+ (cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+
+ (cmdline_parse_inst_t *)&cmd_pctype_mapping_get,
+ (cmdline_parse_inst_t *)&cmd_pctype_mapping_reset,
+ (cmdline_parse_inst_t *)&cmd_pctype_mapping_update,
+ (cmdline_parse_inst_t *)&cmd_queue_region,
+ (cmdline_parse_inst_t *)&cmd_region_flowtype,
+ (cmdline_parse_inst_t *)&cmd_user_priority_region,
+ (cmdline_parse_inst_t *)&cmd_flush_queue_region,
+ (cmdline_parse_inst_t *)&cmd_show_queue_region_info_all,
+ (cmdline_parse_inst_t *)&cmd_show_port_tm_cap,
+ (cmdline_parse_inst_t *)&cmd_show_port_tm_level_cap,
+ (cmdline_parse_inst_t *)&cmd_show_port_tm_node_cap,
+ (cmdline_parse_inst_t *)&cmd_show_port_tm_node_type,
+ (cmdline_parse_inst_t *)&cmd_show_port_tm_node_stats,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_node_shaper_profile,
+ (cmdline_parse_inst_t *)&cmd_del_port_tm_node_shaper_profile,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_node_shared_shaper,
+ (cmdline_parse_inst_t *)&cmd_del_port_tm_node_shared_shaper,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_node_wred_profile,
+ (cmdline_parse_inst_t *)&cmd_del_port_tm_node_wred_profile,
+ (cmdline_parse_inst_t *)&cmd_set_port_tm_node_shaper_profile,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_nonleaf_node,
+ (cmdline_parse_inst_t *)&cmd_add_port_tm_leaf_node,
+ (cmdline_parse_inst_t *)&cmd_del_port_tm_node,
+ (cmdline_parse_inst_t *)&cmd_set_port_tm_node_parent,
+ (cmdline_parse_inst_t *)&cmd_suspend_port_tm_node,
+ (cmdline_parse_inst_t *)&cmd_resume_port_tm_node,
+ (cmdline_parse_inst_t *)&cmd_port_tm_hierarchy_commit,
+ (cmdline_parse_inst_t *)&cmd_port_tm_mark_ip_ecn,
+ (cmdline_parse_inst_t *)&cmd_port_tm_mark_ip_dscp,
+ (cmdline_parse_inst_t *)&cmd_port_tm_mark_vlan_dei,
+ (cmdline_parse_inst_t *)&cmd_cfg_tunnel_udp_port,
+ (cmdline_parse_inst_t *)&cmd_rx_offload_get_capa,
+ (cmdline_parse_inst_t *)&cmd_rx_offload_get_configuration,
+ (cmdline_parse_inst_t *)&cmd_config_per_port_rx_offload,
+ (cmdline_parse_inst_t *)&cmd_config_per_queue_rx_offload,
+ (cmdline_parse_inst_t *)&cmd_tx_offload_get_capa,
+ (cmdline_parse_inst_t *)&cmd_tx_offload_get_configuration,
+ (cmdline_parse_inst_t *)&cmd_config_per_port_tx_offload,
+ (cmdline_parse_inst_t *)&cmd_config_per_queue_tx_offload,
+#ifdef RTE_LIBRTE_BPF
+ (cmdline_parse_inst_t *)&cmd_operate_bpf_ld_parse,
+ (cmdline_parse_inst_t *)&cmd_operate_bpf_unld_parse,
+#endif
+ (cmdline_parse_inst_t *)&cmd_config_tx_metadata_specific,
+ (cmdline_parse_inst_t *)&cmd_show_tx_metadata,
+ (cmdline_parse_inst_t *)&cmd_show_rx_tx_desc_status,
+ (cmdline_parse_inst_t *)&cmd_set_raw,
+ (cmdline_parse_inst_t *)&cmd_show_set_raw,
+ (cmdline_parse_inst_t *)&cmd_show_set_raw_all,
+ (cmdline_parse_inst_t *)&cmd_config_tx_dynf_specific,
+ NULL,
+};
+
+/* read cmdline commands from file */
+void
+cmdline_read_from_file(const char *filename)
+{
+ struct cmdline *cl;
+
+ cl = cmdline_file_new(main_ctx, "testpmd> ", filename);
+ if (cl == NULL) {
+ printf("Failed to create file based cmdline context: %s\n",
+ filename);
+ return;
+ }
+
+ cmdline_interact(cl);
+ cmdline_quit(cl);
+
+ cmdline_free(cl);
+
+ printf("Read CLI commands from %s\n", filename);
+}
+
+/* prompt function, called from main on MASTER lcore */
+void
+prompt(void)
+{
+ /* initialize non-constant commands */
+ cmd_set_fwd_mode_init();
+ cmd_set_fwd_retry_mode_init();
+
+ testpmd_cl = cmdline_stdin_new(main_ctx, "testpmd> ");
+ if (testpmd_cl == NULL)
+ return;
+ cmdline_interact(testpmd_cl);
+ cmdline_stdin_exit(testpmd_cl);
+}
+
+void
+prompt_exit(void)
+{
+ if (testpmd_cl != NULL)
+ cmdline_quit(testpmd_cl);
+}
+
+static void
+cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue)
+{
+ if (id == (portid_t)RTE_PORT_ALL) {
+ portid_t pid;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[pid].need_reconfig == 0)
+ ports[pid].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[pid].need_reconfig_queues == 0)
+ ports[pid].need_reconfig_queues = queue;
+ }
+ } else if (!port_id_is_invalid(id, DISABLED_WARN)) {
+ /* check if need_reconfig has been set to 1 */
+ if (ports[id].need_reconfig == 0)
+ ports[id].need_reconfig = dev;
+ /* check if need_reconfig_queues has been set to 1 */
+ if (ports[id].need_reconfig_queues == 0)
+ ports[id].need_reconfig_queues = queue;
+ }
+}
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline_flow.c b/src/spdk/dpdk/app/test-pmd/cmdline_flow.c
new file mode 100644
index 000000000..4e2006c54
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline_flow.c
@@ -0,0 +1,6888 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016 6WIND S.A.
+ * Copyright 2016 Mellanox Technologies, Ltd
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <rte_string_fns.h>
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_byteorder.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_etheraddr.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_num.h>
+#include <rte_flow.h>
+#include <rte_hexdump.h>
+
+#include "testpmd.h"
+
+/** Parser token indices. */
+enum index {
+ /* Special tokens. */
+ ZERO = 0,
+ END,
+ START_SET,
+ END_SET,
+
+ /* Common tokens. */
+ INTEGER,
+ UNSIGNED,
+ PREFIX,
+ BOOLEAN,
+ STRING,
+ HEX,
+ FILE_PATH,
+ MAC_ADDR,
+ IPV4_ADDR,
+ IPV6_ADDR,
+ RULE_ID,
+ PORT_ID,
+ GROUP_ID,
+ PRIORITY_LEVEL,
+
+ /* Top-level command. */
+ SET,
+ /* Sub-leve commands. */
+ SET_RAW_ENCAP,
+ SET_RAW_DECAP,
+ SET_RAW_INDEX,
+
+ /* Top-level command. */
+ FLOW,
+ /* Sub-level commands. */
+ VALIDATE,
+ CREATE,
+ DESTROY,
+ FLUSH,
+ DUMP,
+ QUERY,
+ LIST,
+ AGED,
+ ISOLATE,
+
+ /* Destroy arguments. */
+ DESTROY_RULE,
+
+ /* Query arguments. */
+ QUERY_ACTION,
+
+ /* List arguments. */
+ LIST_GROUP,
+
+ /* Destroy aged flow arguments. */
+ AGED_DESTROY,
+
+ /* Validate/create arguments. */
+ GROUP,
+ PRIORITY,
+ INGRESS,
+ EGRESS,
+ TRANSFER,
+
+ /* Validate/create pattern. */
+ PATTERN,
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
+ ITEM_PARAM_PREFIX,
+ ITEM_NEXT,
+ ITEM_END,
+ ITEM_VOID,
+ ITEM_INVERT,
+ ITEM_ANY,
+ ITEM_ANY_NUM,
+ ITEM_PF,
+ ITEM_VF,
+ ITEM_VF_ID,
+ ITEM_PHY_PORT,
+ ITEM_PHY_PORT_INDEX,
+ ITEM_PORT_ID,
+ ITEM_PORT_ID_ID,
+ ITEM_MARK,
+ ITEM_MARK_ID,
+ ITEM_RAW,
+ ITEM_RAW_RELATIVE,
+ ITEM_RAW_SEARCH,
+ ITEM_RAW_OFFSET,
+ ITEM_RAW_LIMIT,
+ ITEM_RAW_PATTERN,
+ ITEM_ETH,
+ ITEM_ETH_DST,
+ ITEM_ETH_SRC,
+ ITEM_ETH_TYPE,
+ ITEM_VLAN,
+ ITEM_VLAN_TCI,
+ ITEM_VLAN_PCP,
+ ITEM_VLAN_DEI,
+ ITEM_VLAN_VID,
+ ITEM_VLAN_INNER_TYPE,
+ ITEM_IPV4,
+ ITEM_IPV4_TOS,
+ ITEM_IPV4_TTL,
+ ITEM_IPV4_PROTO,
+ ITEM_IPV4_SRC,
+ ITEM_IPV4_DST,
+ ITEM_IPV6,
+ ITEM_IPV6_TC,
+ ITEM_IPV6_FLOW,
+ ITEM_IPV6_PROTO,
+ ITEM_IPV6_HOP,
+ ITEM_IPV6_SRC,
+ ITEM_IPV6_DST,
+ ITEM_ICMP,
+ ITEM_ICMP_TYPE,
+ ITEM_ICMP_CODE,
+ ITEM_UDP,
+ ITEM_UDP_SRC,
+ ITEM_UDP_DST,
+ ITEM_TCP,
+ ITEM_TCP_SRC,
+ ITEM_TCP_DST,
+ ITEM_TCP_FLAGS,
+ ITEM_SCTP,
+ ITEM_SCTP_SRC,
+ ITEM_SCTP_DST,
+ ITEM_SCTP_TAG,
+ ITEM_SCTP_CKSUM,
+ ITEM_VXLAN,
+ ITEM_VXLAN_VNI,
+ ITEM_E_TAG,
+ ITEM_E_TAG_GRP_ECID_B,
+ ITEM_NVGRE,
+ ITEM_NVGRE_TNI,
+ ITEM_MPLS,
+ ITEM_MPLS_LABEL,
+ ITEM_MPLS_TC,
+ ITEM_MPLS_S,
+ ITEM_GRE,
+ ITEM_GRE_PROTO,
+ ITEM_GRE_C_RSVD0_VER,
+ ITEM_GRE_C_BIT,
+ ITEM_GRE_K_BIT,
+ ITEM_GRE_S_BIT,
+ ITEM_FUZZY,
+ ITEM_FUZZY_THRESH,
+ ITEM_GTP,
+ ITEM_GTP_FLAGS,
+ ITEM_GTP_MSG_TYPE,
+ ITEM_GTP_TEID,
+ ITEM_GTPC,
+ ITEM_GTPU,
+ ITEM_GENEVE,
+ ITEM_GENEVE_VNI,
+ ITEM_GENEVE_PROTO,
+ ITEM_VXLAN_GPE,
+ ITEM_VXLAN_GPE_VNI,
+ ITEM_ARP_ETH_IPV4,
+ ITEM_ARP_ETH_IPV4_SHA,
+ ITEM_ARP_ETH_IPV4_SPA,
+ ITEM_ARP_ETH_IPV4_THA,
+ ITEM_ARP_ETH_IPV4_TPA,
+ ITEM_IPV6_EXT,
+ ITEM_IPV6_EXT_NEXT_HDR,
+ ITEM_ICMP6,
+ ITEM_ICMP6_TYPE,
+ ITEM_ICMP6_CODE,
+ ITEM_ICMP6_ND_NS,
+ ITEM_ICMP6_ND_NS_TARGET_ADDR,
+ ITEM_ICMP6_ND_NA,
+ ITEM_ICMP6_ND_NA_TARGET_ADDR,
+ ITEM_ICMP6_ND_OPT,
+ ITEM_ICMP6_ND_OPT_TYPE,
+ ITEM_ICMP6_ND_OPT_SLA_ETH,
+ ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
+ ITEM_ICMP6_ND_OPT_TLA_ETH,
+ ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
+ ITEM_META,
+ ITEM_META_DATA,
+ ITEM_GRE_KEY,
+ ITEM_GRE_KEY_VALUE,
+ ITEM_GTP_PSC,
+ ITEM_GTP_PSC_QFI,
+ ITEM_GTP_PSC_PDU_T,
+ ITEM_PPPOES,
+ ITEM_PPPOED,
+ ITEM_PPPOE_SEID,
+ ITEM_PPPOE_PROTO_ID,
+ ITEM_HIGIG2,
+ ITEM_HIGIG2_CLASSIFICATION,
+ ITEM_HIGIG2_VID,
+ ITEM_TAG,
+ ITEM_TAG_DATA,
+ ITEM_TAG_INDEX,
+ ITEM_L2TPV3OIP,
+ ITEM_L2TPV3OIP_SESSION_ID,
+ ITEM_ESP,
+ ITEM_ESP_SPI,
+ ITEM_AH,
+ ITEM_AH_SPI,
+ ITEM_PFCP,
+ ITEM_PFCP_S_FIELD,
+ ITEM_PFCP_SEID,
+
+ /* Validate/create actions. */
+ ACTIONS,
+ ACTION_NEXT,
+ ACTION_END,
+ ACTION_VOID,
+ ACTION_PASSTHRU,
+ ACTION_JUMP,
+ ACTION_JUMP_GROUP,
+ ACTION_MARK,
+ ACTION_MARK_ID,
+ ACTION_FLAG,
+ ACTION_QUEUE,
+ ACTION_QUEUE_INDEX,
+ ACTION_DROP,
+ ACTION_COUNT,
+ ACTION_COUNT_SHARED,
+ ACTION_COUNT_ID,
+ ACTION_RSS,
+ ACTION_RSS_FUNC,
+ ACTION_RSS_LEVEL,
+ ACTION_RSS_FUNC_DEFAULT,
+ ACTION_RSS_FUNC_TOEPLITZ,
+ ACTION_RSS_FUNC_SIMPLE_XOR,
+ ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ,
+ ACTION_RSS_TYPES,
+ ACTION_RSS_TYPE,
+ ACTION_RSS_KEY,
+ ACTION_RSS_KEY_LEN,
+ ACTION_RSS_QUEUES,
+ ACTION_RSS_QUEUE,
+ ACTION_PF,
+ ACTION_VF,
+ ACTION_VF_ORIGINAL,
+ ACTION_VF_ID,
+ ACTION_PHY_PORT,
+ ACTION_PHY_PORT_ORIGINAL,
+ ACTION_PHY_PORT_INDEX,
+ ACTION_PORT_ID,
+ ACTION_PORT_ID_ORIGINAL,
+ ACTION_PORT_ID_ID,
+ ACTION_METER,
+ ACTION_METER_ID,
+ ACTION_OF_SET_MPLS_TTL,
+ ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
+ ACTION_OF_DEC_MPLS_TTL,
+ ACTION_OF_SET_NW_TTL,
+ ACTION_OF_SET_NW_TTL_NW_TTL,
+ ACTION_OF_DEC_NW_TTL,
+ ACTION_OF_COPY_TTL_OUT,
+ ACTION_OF_COPY_TTL_IN,
+ ACTION_OF_POP_VLAN,
+ ACTION_OF_PUSH_VLAN,
+ ACTION_OF_PUSH_VLAN_ETHERTYPE,
+ ACTION_OF_SET_VLAN_VID,
+ ACTION_OF_SET_VLAN_VID_VLAN_VID,
+ ACTION_OF_SET_VLAN_PCP,
+ ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
+ ACTION_OF_POP_MPLS,
+ ACTION_OF_POP_MPLS_ETHERTYPE,
+ ACTION_OF_PUSH_MPLS,
+ ACTION_OF_PUSH_MPLS_ETHERTYPE,
+ ACTION_VXLAN_ENCAP,
+ ACTION_VXLAN_DECAP,
+ ACTION_NVGRE_ENCAP,
+ ACTION_NVGRE_DECAP,
+ ACTION_L2_ENCAP,
+ ACTION_L2_DECAP,
+ ACTION_MPLSOGRE_ENCAP,
+ ACTION_MPLSOGRE_DECAP,
+ ACTION_MPLSOUDP_ENCAP,
+ ACTION_MPLSOUDP_DECAP,
+ ACTION_SET_IPV4_SRC,
+ ACTION_SET_IPV4_SRC_IPV4_SRC,
+ ACTION_SET_IPV4_DST,
+ ACTION_SET_IPV4_DST_IPV4_DST,
+ ACTION_SET_IPV6_SRC,
+ ACTION_SET_IPV6_SRC_IPV6_SRC,
+ ACTION_SET_IPV6_DST,
+ ACTION_SET_IPV6_DST_IPV6_DST,
+ ACTION_SET_TP_SRC,
+ ACTION_SET_TP_SRC_TP_SRC,
+ ACTION_SET_TP_DST,
+ ACTION_SET_TP_DST_TP_DST,
+ ACTION_MAC_SWAP,
+ ACTION_DEC_TTL,
+ ACTION_SET_TTL,
+ ACTION_SET_TTL_TTL,
+ ACTION_SET_MAC_SRC,
+ ACTION_SET_MAC_SRC_MAC_SRC,
+ ACTION_SET_MAC_DST,
+ ACTION_SET_MAC_DST_MAC_DST,
+ ACTION_INC_TCP_SEQ,
+ ACTION_INC_TCP_SEQ_VALUE,
+ ACTION_DEC_TCP_SEQ,
+ ACTION_DEC_TCP_SEQ_VALUE,
+ ACTION_INC_TCP_ACK,
+ ACTION_INC_TCP_ACK_VALUE,
+ ACTION_DEC_TCP_ACK,
+ ACTION_DEC_TCP_ACK_VALUE,
+ ACTION_RAW_ENCAP,
+ ACTION_RAW_DECAP,
+ ACTION_RAW_ENCAP_INDEX,
+ ACTION_RAW_ENCAP_INDEX_VALUE,
+ ACTION_RAW_DECAP_INDEX,
+ ACTION_RAW_DECAP_INDEX_VALUE,
+ ACTION_SET_TAG,
+ ACTION_SET_TAG_DATA,
+ ACTION_SET_TAG_INDEX,
+ ACTION_SET_TAG_MASK,
+ ACTION_SET_META,
+ ACTION_SET_META_DATA,
+ ACTION_SET_META_MASK,
+ ACTION_SET_IPV4_DSCP,
+ ACTION_SET_IPV4_DSCP_VALUE,
+ ACTION_SET_IPV6_DSCP,
+ ACTION_SET_IPV6_DSCP_VALUE,
+ ACTION_AGE,
+ ACTION_AGE_TIMEOUT,
+};
+
+/** Maximum size for pattern in struct rte_flow_item_raw. */
+#define ITEM_RAW_PATTERN_SIZE 40
+
+/** Storage size for struct rte_flow_item_raw including pattern. */
+#define ITEM_RAW_SIZE \
+ (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
+
+/** Maximum number of queue indices in struct rte_flow_action_rss. */
+#define ACTION_RSS_QUEUE_NUM 128
+
+/** Storage for struct rte_flow_action_rss including external data. */
+struct action_rss_data {
+ struct rte_flow_action_rss conf;
+ uint8_t key[RSS_HASH_KEY_LENGTH];
+ uint16_t queue[ACTION_RSS_QUEUE_NUM];
+};
+
+/** Maximum data size in struct rte_flow_action_raw_encap. */
+#define ACTION_RAW_ENCAP_MAX_DATA 128
+#define RAW_ENCAP_CONFS_MAX_NUM 8
+
+/** Storage for struct rte_flow_action_raw_encap. */
+struct raw_encap_conf {
+ uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
+ uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
+ size_t size;
+};
+
+struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM];
+
+/** Storage for struct rte_flow_action_raw_encap including external data. */
+struct action_raw_encap_data {
+ struct rte_flow_action_raw_encap conf;
+ uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
+ uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
+ uint16_t idx;
+};
+
+/** Storage for struct rte_flow_action_raw_decap. */
+struct raw_decap_conf {
+ uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
+ size_t size;
+};
+
+struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM];
+
+/** Storage for struct rte_flow_action_raw_decap including external data. */
+struct action_raw_decap_data {
+ struct rte_flow_action_raw_decap conf;
+ uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
+ uint16_t idx;
+};
+
+struct vxlan_encap_conf vxlan_encap_conf = {
+ .select_ipv4 = 1,
+ .select_vlan = 0,
+ .select_tos_ttl = 0,
+ .vni = "\x00\x00\x00",
+ .udp_src = 0,
+ .udp_dst = RTE_BE16(4789),
+ .ipv4_src = RTE_IPV4(127, 0, 0, 1),
+ .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
+ .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x01",
+ .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x11\x11",
+ .vlan_tci = 0,
+ .ip_tos = 0,
+ .ip_ttl = 255,
+ .eth_src = "\x00\x00\x00\x00\x00\x00",
+ .eth_dst = "\xff\xff\xff\xff\xff\xff",
+};
+
+/** Maximum number of items in struct rte_flow_action_vxlan_encap. */
+#define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
+
+/** Storage for struct rte_flow_action_vxlan_encap including external data. */
+struct action_vxlan_encap_data {
+ struct rte_flow_action_vxlan_encap conf;
+ struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
+ struct rte_flow_item_eth item_eth;
+ struct rte_flow_item_vlan item_vlan;
+ union {
+ struct rte_flow_item_ipv4 item_ipv4;
+ struct rte_flow_item_ipv6 item_ipv6;
+ };
+ struct rte_flow_item_udp item_udp;
+ struct rte_flow_item_vxlan item_vxlan;
+};
+
+struct nvgre_encap_conf nvgre_encap_conf = {
+ .select_ipv4 = 1,
+ .select_vlan = 0,
+ .tni = "\x00\x00\x00",
+ .ipv4_src = RTE_IPV4(127, 0, 0, 1),
+ .ipv4_dst = RTE_IPV4(255, 255, 255, 255),
+ .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x01",
+ .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x11\x11",
+ .vlan_tci = 0,
+ .eth_src = "\x00\x00\x00\x00\x00\x00",
+ .eth_dst = "\xff\xff\xff\xff\xff\xff",
+};
+
+/** Maximum number of items in struct rte_flow_action_nvgre_encap. */
+#define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
+
+/** Storage for struct rte_flow_action_nvgre_encap including external data. */
+struct action_nvgre_encap_data {
+ struct rte_flow_action_nvgre_encap conf;
+ struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
+ struct rte_flow_item_eth item_eth;
+ struct rte_flow_item_vlan item_vlan;
+ union {
+ struct rte_flow_item_ipv4 item_ipv4;
+ struct rte_flow_item_ipv6 item_ipv6;
+ };
+ struct rte_flow_item_nvgre item_nvgre;
+};
+
+struct l2_encap_conf l2_encap_conf;
+
+struct l2_decap_conf l2_decap_conf;
+
+struct mplsogre_encap_conf mplsogre_encap_conf;
+
+struct mplsogre_decap_conf mplsogre_decap_conf;
+
+struct mplsoudp_encap_conf mplsoudp_encap_conf;
+
+struct mplsoudp_decap_conf mplsoudp_decap_conf;
+
+/** Maximum number of subsequent tokens and arguments on the stack. */
+#define CTX_STACK_SIZE 16
+
+/** Parser context. */
+struct context {
+ /** Stack of subsequent token lists to process. */
+ const enum index *next[CTX_STACK_SIZE];
+ /** Arguments for stacked tokens. */
+ const void *args[CTX_STACK_SIZE];
+ enum index curr; /**< Current token index. */
+ enum index prev; /**< Index of the last token seen. */
+ int next_num; /**< Number of entries in next[]. */
+ int args_num; /**< Number of entries in args[]. */
+ uint32_t eol:1; /**< EOL has been detected. */
+ uint32_t last:1; /**< No more arguments. */
+ portid_t port; /**< Current port ID (for completions). */
+ uint32_t objdata; /**< Object-specific data. */
+ void *object; /**< Address of current object for relative offsets. */
+ void *objmask; /**< Object a full mask must be written to. */
+};
+
+/** Token argument. */
+struct arg {
+ uint32_t hton:1; /**< Use network byte ordering. */
+ uint32_t sign:1; /**< Value is signed. */
+ uint32_t bounded:1; /**< Value is bounded. */
+ uintmax_t min; /**< Minimum value if bounded. */
+ uintmax_t max; /**< Maximum value if bounded. */
+ uint32_t offset; /**< Relative offset from ctx->object. */
+ uint32_t size; /**< Field size. */
+ const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
+};
+
+/** Parser token definition. */
+struct token {
+ /** Type displayed during completion (defaults to "TOKEN"). */
+ const char *type;
+ /** Help displayed during completion (defaults to token name). */
+ const char *help;
+ /** Private data used by parser functions. */
+ const void *priv;
+ /**
+ * Lists of subsequent tokens to push on the stack. Each call to the
+ * parser consumes the last entry of that stack.
+ */
+ const enum index *const *next;
+ /** Arguments stack for subsequent tokens that need them. */
+ const struct arg *const *args;
+ /**
+ * Token-processing callback, returns -1 in case of error, the
+ * length of the matched string otherwise. If NULL, attempts to
+ * match the token name.
+ *
+ * If buf is not NULL, the result should be stored in it according
+ * to context. An error is returned if not large enough.
+ */
+ int (*call)(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size);
+ /**
+ * Callback that provides possible values for this token, used for
+ * completion. Returns -1 in case of error, the number of possible
+ * values otherwise. If NULL, the token name is used.
+ *
+ * If buf is not NULL, entry index ent is written to buf and the
+ * full length of the entry is returned (same behavior as
+ * snprintf()).
+ */
+ int (*comp)(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size);
+ /** Mandatory token name, no default value. */
+ const char *name;
+};
+
+/** Static initializer for the next field. */
+#define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
+
+/** Static initializer for a NEXT() entry. */
+#define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
+
+/** Static initializer for the args field. */
+#define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
+
+/** Static initializer for ARGS() to target a field. */
+#define ARGS_ENTRY(s, f) \
+ (&(const struct arg){ \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ })
+
+/** Static initializer for ARGS() to target a bit-field. */
+#define ARGS_ENTRY_BF(s, f, b) \
+ (&(const struct arg){ \
+ .size = sizeof(s), \
+ .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
+ })
+
+/** Static initializer for ARGS() to target an arbitrary bit-mask. */
+#define ARGS_ENTRY_MASK(s, f, m) \
+ (&(const struct arg){ \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ .mask = (const void *)(m), \
+ })
+
+/** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
+#define ARGS_ENTRY_MASK_HTON(s, f, m) \
+ (&(const struct arg){ \
+ .hton = 1, \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ .mask = (const void *)(m), \
+ })
+
+/** Static initializer for ARGS() to target a pointer. */
+#define ARGS_ENTRY_PTR(s, f) \
+ (&(const struct arg){ \
+ .size = sizeof(*((s *)0)->f), \
+ })
+
+/** Static initializer for ARGS() with arbitrary offset and size. */
+#define ARGS_ENTRY_ARB(o, s) \
+ (&(const struct arg){ \
+ .offset = (o), \
+ .size = (s), \
+ })
+
+/** Same as ARGS_ENTRY_ARB() with bounded values. */
+#define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
+ (&(const struct arg){ \
+ .bounded = 1, \
+ .min = (i), \
+ .max = (a), \
+ .offset = (o), \
+ .size = (s), \
+ })
+
+/** Same as ARGS_ENTRY() using network byte ordering. */
+#define ARGS_ENTRY_HTON(s, f) \
+ (&(const struct arg){ \
+ .hton = 1, \
+ .offset = offsetof(s, f), \
+ .size = sizeof(((s *)0)->f), \
+ })
+
+/** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */
+#define ARG_ENTRY_HTON(s) \
+ (&(const struct arg){ \
+ .hton = 1, \
+ .offset = 0, \
+ .size = sizeof(s), \
+ })
+
+/** Parser output buffer layout expected by cmd_flow_parsed(). */
+struct buffer {
+ enum index command; /**< Flow command. */
+ portid_t port; /**< Affected port ID. */
+ union {
+ struct {
+ struct rte_flow_attr attr;
+ struct rte_flow_item *pattern;
+ struct rte_flow_action *actions;
+ uint32_t pattern_n;
+ uint32_t actions_n;
+ uint8_t *data;
+ } vc; /**< Validate/create arguments. */
+ struct {
+ uint32_t *rule;
+ uint32_t rule_n;
+ } destroy; /**< Destroy arguments. */
+ struct {
+ char file[128];
+ } dump; /**< Dump arguments. */
+ struct {
+ uint32_t rule;
+ struct rte_flow_action action;
+ } query; /**< Query arguments. */
+ struct {
+ uint32_t *group;
+ uint32_t group_n;
+ } list; /**< List arguments. */
+ struct {
+ int set;
+ } isolate; /**< Isolated mode arguments. */
+ struct {
+ int destroy;
+ } aged; /**< Aged arguments. */
+ } args; /**< Command arguments. */
+};
+
+/** Private data for pattern items. */
+struct parse_item_priv {
+ enum rte_flow_item_type type; /**< Item type. */
+ uint32_t size; /**< Size of item specification structure. */
+};
+
+#define PRIV_ITEM(t, s) \
+ (&(const struct parse_item_priv){ \
+ .type = RTE_FLOW_ITEM_TYPE_ ## t, \
+ .size = s, \
+ })
+
+/** Private data for actions. */
+struct parse_action_priv {
+ enum rte_flow_action_type type; /**< Action type. */
+ uint32_t size; /**< Size of action configuration structure. */
+};
+
+#define PRIV_ACTION(t, s) \
+ (&(const struct parse_action_priv){ \
+ .type = RTE_FLOW_ACTION_TYPE_ ## t, \
+ .size = s, \
+ })
+
+static const enum index next_vc_attr[] = {
+ GROUP,
+ PRIORITY,
+ INGRESS,
+ EGRESS,
+ TRANSFER,
+ PATTERN,
+ ZERO,
+};
+
+static const enum index next_destroy_attr[] = {
+ DESTROY_RULE,
+ END,
+ ZERO,
+};
+
+static const enum index next_dump_attr[] = {
+ FILE_PATH,
+ END,
+ ZERO,
+};
+
+static const enum index next_list_attr[] = {
+ LIST_GROUP,
+ END,
+ ZERO,
+};
+
+static const enum index next_aged_attr[] = {
+ AGED_DESTROY,
+ END,
+ ZERO,
+};
+
+static const enum index item_param[] = {
+ ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_LAST,
+ ITEM_PARAM_MASK,
+ ITEM_PARAM_PREFIX,
+ ZERO,
+};
+
+static const enum index next_item[] = {
+ ITEM_END,
+ ITEM_VOID,
+ ITEM_INVERT,
+ ITEM_ANY,
+ ITEM_PF,
+ ITEM_VF,
+ ITEM_PHY_PORT,
+ ITEM_PORT_ID,
+ ITEM_MARK,
+ ITEM_RAW,
+ ITEM_ETH,
+ ITEM_VLAN,
+ ITEM_IPV4,
+ ITEM_IPV6,
+ ITEM_ICMP,
+ ITEM_UDP,
+ ITEM_TCP,
+ ITEM_SCTP,
+ ITEM_VXLAN,
+ ITEM_E_TAG,
+ ITEM_NVGRE,
+ ITEM_MPLS,
+ ITEM_GRE,
+ ITEM_FUZZY,
+ ITEM_GTP,
+ ITEM_GTPC,
+ ITEM_GTPU,
+ ITEM_GENEVE,
+ ITEM_VXLAN_GPE,
+ ITEM_ARP_ETH_IPV4,
+ ITEM_IPV6_EXT,
+ ITEM_ICMP6,
+ ITEM_ICMP6_ND_NS,
+ ITEM_ICMP6_ND_NA,
+ ITEM_ICMP6_ND_OPT,
+ ITEM_ICMP6_ND_OPT_SLA_ETH,
+ ITEM_ICMP6_ND_OPT_TLA_ETH,
+ ITEM_META,
+ ITEM_GRE_KEY,
+ ITEM_GTP_PSC,
+ ITEM_PPPOES,
+ ITEM_PPPOED,
+ ITEM_PPPOE_PROTO_ID,
+ ITEM_HIGIG2,
+ ITEM_TAG,
+ ITEM_L2TPV3OIP,
+ ITEM_ESP,
+ ITEM_AH,
+ ITEM_PFCP,
+ END_SET,
+ ZERO,
+};
+
+static const enum index item_fuzzy[] = {
+ ITEM_FUZZY_THRESH,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_any[] = {
+ ITEM_ANY_NUM,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vf[] = {
+ ITEM_VF_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_phy_port[] = {
+ ITEM_PHY_PORT_INDEX,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_port_id[] = {
+ ITEM_PORT_ID_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_mark[] = {
+ ITEM_MARK_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_raw[] = {
+ ITEM_RAW_RELATIVE,
+ ITEM_RAW_SEARCH,
+ ITEM_RAW_OFFSET,
+ ITEM_RAW_LIMIT,
+ ITEM_RAW_PATTERN,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_eth[] = {
+ ITEM_ETH_DST,
+ ITEM_ETH_SRC,
+ ITEM_ETH_TYPE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vlan[] = {
+ ITEM_VLAN_TCI,
+ ITEM_VLAN_PCP,
+ ITEM_VLAN_DEI,
+ ITEM_VLAN_VID,
+ ITEM_VLAN_INNER_TYPE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ipv4[] = {
+ ITEM_IPV4_TOS,
+ ITEM_IPV4_TTL,
+ ITEM_IPV4_PROTO,
+ ITEM_IPV4_SRC,
+ ITEM_IPV4_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ipv6[] = {
+ ITEM_IPV6_TC,
+ ITEM_IPV6_FLOW,
+ ITEM_IPV6_PROTO,
+ ITEM_IPV6_HOP,
+ ITEM_IPV6_SRC,
+ ITEM_IPV6_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp[] = {
+ ITEM_ICMP_TYPE,
+ ITEM_ICMP_CODE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_udp[] = {
+ ITEM_UDP_SRC,
+ ITEM_UDP_DST,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_tcp[] = {
+ ITEM_TCP_SRC,
+ ITEM_TCP_DST,
+ ITEM_TCP_FLAGS,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_sctp[] = {
+ ITEM_SCTP_SRC,
+ ITEM_SCTP_DST,
+ ITEM_SCTP_TAG,
+ ITEM_SCTP_CKSUM,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vxlan[] = {
+ ITEM_VXLAN_VNI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_e_tag[] = {
+ ITEM_E_TAG_GRP_ECID_B,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_nvgre[] = {
+ ITEM_NVGRE_TNI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_mpls[] = {
+ ITEM_MPLS_LABEL,
+ ITEM_MPLS_TC,
+ ITEM_MPLS_S,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_gre[] = {
+ ITEM_GRE_PROTO,
+ ITEM_GRE_C_RSVD0_VER,
+ ITEM_GRE_C_BIT,
+ ITEM_GRE_K_BIT,
+ ITEM_GRE_S_BIT,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_gre_key[] = {
+ ITEM_GRE_KEY_VALUE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_gtp[] = {
+ ITEM_GTP_FLAGS,
+ ITEM_GTP_MSG_TYPE,
+ ITEM_GTP_TEID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_geneve[] = {
+ ITEM_GENEVE_VNI,
+ ITEM_GENEVE_PROTO,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_vxlan_gpe[] = {
+ ITEM_VXLAN_GPE_VNI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_arp_eth_ipv4[] = {
+ ITEM_ARP_ETH_IPV4_SHA,
+ ITEM_ARP_ETH_IPV4_SPA,
+ ITEM_ARP_ETH_IPV4_THA,
+ ITEM_ARP_ETH_IPV4_TPA,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ipv6_ext[] = {
+ ITEM_IPV6_EXT_NEXT_HDR,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6[] = {
+ ITEM_ICMP6_TYPE,
+ ITEM_ICMP6_CODE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6_nd_ns[] = {
+ ITEM_ICMP6_ND_NS_TARGET_ADDR,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6_nd_na[] = {
+ ITEM_ICMP6_ND_NA_TARGET_ADDR,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6_nd_opt[] = {
+ ITEM_ICMP6_ND_OPT_TYPE,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_sla_eth[] = {
+ ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_tla_eth[] = {
+ ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_meta[] = {
+ ITEM_META_DATA,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_gtp_psc[] = {
+ ITEM_GTP_PSC_QFI,
+ ITEM_GTP_PSC_PDU_T,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_pppoed[] = {
+ ITEM_PPPOE_SEID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_pppoes[] = {
+ ITEM_PPPOE_SEID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_pppoe_proto_id[] = {
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_higig2[] = {
+ ITEM_HIGIG2_CLASSIFICATION,
+ ITEM_HIGIG2_VID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_esp[] = {
+ ITEM_ESP_SPI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_ah[] = {
+ ITEM_AH_SPI,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_pfcp[] = {
+ ITEM_PFCP_S_FIELD,
+ ITEM_PFCP_SEID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index next_set_raw[] = {
+ SET_RAW_INDEX,
+ ITEM_ETH,
+ ZERO,
+};
+
+static const enum index item_tag[] = {
+ ITEM_TAG_DATA,
+ ITEM_TAG_INDEX,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index item_l2tpv3oip[] = {
+ ITEM_L2TPV3OIP_SESSION_ID,
+ ITEM_NEXT,
+ ZERO,
+};
+
+static const enum index next_action[] = {
+ ACTION_END,
+ ACTION_VOID,
+ ACTION_PASSTHRU,
+ ACTION_JUMP,
+ ACTION_MARK,
+ ACTION_FLAG,
+ ACTION_QUEUE,
+ ACTION_DROP,
+ ACTION_COUNT,
+ ACTION_RSS,
+ ACTION_PF,
+ ACTION_VF,
+ ACTION_PHY_PORT,
+ ACTION_PORT_ID,
+ ACTION_METER,
+ ACTION_OF_SET_MPLS_TTL,
+ ACTION_OF_DEC_MPLS_TTL,
+ ACTION_OF_SET_NW_TTL,
+ ACTION_OF_DEC_NW_TTL,
+ ACTION_OF_COPY_TTL_OUT,
+ ACTION_OF_COPY_TTL_IN,
+ ACTION_OF_POP_VLAN,
+ ACTION_OF_PUSH_VLAN,
+ ACTION_OF_SET_VLAN_VID,
+ ACTION_OF_SET_VLAN_PCP,
+ ACTION_OF_POP_MPLS,
+ ACTION_OF_PUSH_MPLS,
+ ACTION_VXLAN_ENCAP,
+ ACTION_VXLAN_DECAP,
+ ACTION_NVGRE_ENCAP,
+ ACTION_NVGRE_DECAP,
+ ACTION_L2_ENCAP,
+ ACTION_L2_DECAP,
+ ACTION_MPLSOGRE_ENCAP,
+ ACTION_MPLSOGRE_DECAP,
+ ACTION_MPLSOUDP_ENCAP,
+ ACTION_MPLSOUDP_DECAP,
+ ACTION_SET_IPV4_SRC,
+ ACTION_SET_IPV4_DST,
+ ACTION_SET_IPV6_SRC,
+ ACTION_SET_IPV6_DST,
+ ACTION_SET_TP_SRC,
+ ACTION_SET_TP_DST,
+ ACTION_MAC_SWAP,
+ ACTION_DEC_TTL,
+ ACTION_SET_TTL,
+ ACTION_SET_MAC_SRC,
+ ACTION_SET_MAC_DST,
+ ACTION_INC_TCP_SEQ,
+ ACTION_DEC_TCP_SEQ,
+ ACTION_INC_TCP_ACK,
+ ACTION_DEC_TCP_ACK,
+ ACTION_RAW_ENCAP,
+ ACTION_RAW_DECAP,
+ ACTION_SET_TAG,
+ ACTION_SET_META,
+ ACTION_SET_IPV4_DSCP,
+ ACTION_SET_IPV6_DSCP,
+ ACTION_AGE,
+ ZERO,
+};
+
+static const enum index action_mark[] = {
+ ACTION_MARK_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_queue[] = {
+ ACTION_QUEUE_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_count[] = {
+ ACTION_COUNT_ID,
+ ACTION_COUNT_SHARED,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_rss[] = {
+ ACTION_RSS_FUNC,
+ ACTION_RSS_LEVEL,
+ ACTION_RSS_TYPES,
+ ACTION_RSS_KEY,
+ ACTION_RSS_KEY_LEN,
+ ACTION_RSS_QUEUES,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_vf[] = {
+ ACTION_VF_ORIGINAL,
+ ACTION_VF_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_phy_port[] = {
+ ACTION_PHY_PORT_ORIGINAL,
+ ACTION_PHY_PORT_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_port_id[] = {
+ ACTION_PORT_ID_ORIGINAL,
+ ACTION_PORT_ID_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_meter[] = {
+ ACTION_METER_ID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_set_mpls_ttl[] = {
+ ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_set_nw_ttl[] = {
+ ACTION_OF_SET_NW_TTL_NW_TTL,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_push_vlan[] = {
+ ACTION_OF_PUSH_VLAN_ETHERTYPE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_set_vlan_vid[] = {
+ ACTION_OF_SET_VLAN_VID_VLAN_VID,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_set_vlan_pcp[] = {
+ ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_pop_mpls[] = {
+ ACTION_OF_POP_MPLS_ETHERTYPE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_of_push_mpls[] = {
+ ACTION_OF_PUSH_MPLS_ETHERTYPE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv4_src[] = {
+ ACTION_SET_IPV4_SRC_IPV4_SRC,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_mac_src[] = {
+ ACTION_SET_MAC_SRC_MAC_SRC,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv4_dst[] = {
+ ACTION_SET_IPV4_DST_IPV4_DST,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv6_src[] = {
+ ACTION_SET_IPV6_SRC_IPV6_SRC,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv6_dst[] = {
+ ACTION_SET_IPV6_DST_IPV6_DST,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_tp_src[] = {
+ ACTION_SET_TP_SRC_TP_SRC,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_tp_dst[] = {
+ ACTION_SET_TP_DST_TP_DST,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ttl[] = {
+ ACTION_SET_TTL_TTL,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_jump[] = {
+ ACTION_JUMP_GROUP,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_mac_dst[] = {
+ ACTION_SET_MAC_DST_MAC_DST,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_inc_tcp_seq[] = {
+ ACTION_INC_TCP_SEQ_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_dec_tcp_seq[] = {
+ ACTION_DEC_TCP_SEQ_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_inc_tcp_ack[] = {
+ ACTION_INC_TCP_ACK_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_dec_tcp_ack[] = {
+ ACTION_DEC_TCP_ACK_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_raw_encap[] = {
+ ACTION_RAW_ENCAP_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_raw_decap[] = {
+ ACTION_RAW_DECAP_INDEX,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_tag[] = {
+ ACTION_SET_TAG_DATA,
+ ACTION_SET_TAG_INDEX,
+ ACTION_SET_TAG_MASK,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_meta[] = {
+ ACTION_SET_META_DATA,
+ ACTION_SET_META_MASK,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv4_dscp[] = {
+ ACTION_SET_IPV4_DSCP_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_set_ipv6_dscp[] = {
+ ACTION_SET_IPV6_DSCP_VALUE,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static const enum index action_age[] = {
+ ACTION_AGE,
+ ACTION_AGE_TIMEOUT,
+ ACTION_NEXT,
+ ZERO,
+};
+
+static int parse_set_raw_encap_decap(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_set_init(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_init(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_vc(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_vc_spec(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
+static int parse_vc_conf(struct context *, const struct token *,
+ const char *, unsigned int, void *, unsigned int);
+static int parse_vc_action_rss(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_rss_func(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_rss_type(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_rss_queue(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_l2_encap(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_l2_decap(struct context *, const struct token *,
+ const char *, unsigned int, void *,
+ unsigned int);
+static int parse_vc_action_mplsogre_encap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_mplsogre_decap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_mplsoudp_encap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_mplsoudp_decap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_raw_encap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_raw_decap(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_raw_encap_index(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_raw_decap_index(struct context *,
+ const struct token *, const char *,
+ unsigned int, void *, unsigned int);
+static int parse_vc_action_set_meta(struct context *ctx,
+ const struct token *token, const char *str,
+ unsigned int len, void *buf,
+ unsigned int size);
+static int parse_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_flush(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_dump(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_query(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_action(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_list(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_aged(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_isolate(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_int(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_prefix(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_boolean(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_string(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_hex(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size);
+static int parse_string0(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_mac_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_ipv4_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_ipv6_addr(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_port(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int comp_none(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_boolean(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_action(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_port(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_rule_id(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_vc_action_rss_type(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_vc_action_rss_queue(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+static int comp_set_raw_index(struct context *, const struct token *,
+ unsigned int, char *, unsigned int);
+
+/** Token definitions. */
+static const struct token token_list[] = {
+ /* Special tokens. */
+ [ZERO] = {
+ .name = "ZERO",
+ .help = "null entry, abused as the entry point",
+ .next = NEXT(NEXT_ENTRY(FLOW)),
+ },
+ [END] = {
+ .name = "",
+ .type = "RETURN",
+ .help = "command may end here",
+ },
+ [START_SET] = {
+ .name = "START_SET",
+ .help = "null entry, abused as the entry point for set",
+ .next = NEXT(NEXT_ENTRY(SET)),
+ },
+ [END_SET] = {
+ .name = "end_set",
+ .type = "RETURN",
+ .help = "set command may end here",
+ },
+ /* Common tokens. */
+ [INTEGER] = {
+ .name = "{int}",
+ .type = "INTEGER",
+ .help = "integer value",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [UNSIGNED] = {
+ .name = "{unsigned}",
+ .type = "UNSIGNED",
+ .help = "unsigned integer value",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [PREFIX] = {
+ .name = "{prefix}",
+ .type = "PREFIX",
+ .help = "prefix length for bit-mask",
+ .call = parse_prefix,
+ .comp = comp_none,
+ },
+ [BOOLEAN] = {
+ .name = "{boolean}",
+ .type = "BOOLEAN",
+ .help = "any boolean value",
+ .call = parse_boolean,
+ .comp = comp_boolean,
+ },
+ [STRING] = {
+ .name = "{string}",
+ .type = "STRING",
+ .help = "fixed string",
+ .call = parse_string,
+ .comp = comp_none,
+ },
+ [HEX] = {
+ .name = "{hex}",
+ .type = "HEX",
+ .help = "fixed string",
+ .call = parse_hex,
+ },
+ [FILE_PATH] = {
+ .name = "{file path}",
+ .type = "STRING",
+ .help = "file path",
+ .call = parse_string0,
+ .comp = comp_none,
+ },
+ [MAC_ADDR] = {
+ .name = "{MAC address}",
+ .type = "MAC-48",
+ .help = "standard MAC address notation",
+ .call = parse_mac_addr,
+ .comp = comp_none,
+ },
+ [IPV4_ADDR] = {
+ .name = "{IPv4 address}",
+ .type = "IPV4 ADDRESS",
+ .help = "standard IPv4 address notation",
+ .call = parse_ipv4_addr,
+ .comp = comp_none,
+ },
+ [IPV6_ADDR] = {
+ .name = "{IPv6 address}",
+ .type = "IPV6 ADDRESS",
+ .help = "standard IPv6 address notation",
+ .call = parse_ipv6_addr,
+ .comp = comp_none,
+ },
+ [RULE_ID] = {
+ .name = "{rule id}",
+ .type = "RULE ID",
+ .help = "rule identifier",
+ .call = parse_int,
+ .comp = comp_rule_id,
+ },
+ [PORT_ID] = {
+ .name = "{port_id}",
+ .type = "PORT ID",
+ .help = "port identifier",
+ .call = parse_port,
+ .comp = comp_port,
+ },
+ [GROUP_ID] = {
+ .name = "{group_id}",
+ .type = "GROUP ID",
+ .help = "group identifier",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ [PRIORITY_LEVEL] = {
+ .name = "{level}",
+ .type = "PRIORITY",
+ .help = "priority level",
+ .call = parse_int,
+ .comp = comp_none,
+ },
+ /* Top-level command. */
+ [FLOW] = {
+ .name = "flow",
+ .type = "{command} {port_id} [{arg} [...]]",
+ .help = "manage ingress/egress flow rules",
+ .next = NEXT(NEXT_ENTRY
+ (VALIDATE,
+ CREATE,
+ DESTROY,
+ FLUSH,
+ DUMP,
+ LIST,
+ AGED,
+ QUERY,
+ ISOLATE)),
+ .call = parse_init,
+ },
+ /* Sub-level commands. */
+ [VALIDATE] = {
+ .name = "validate",
+ .help = "check whether a flow rule can be created",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [CREATE] = {
+ .name = "create",
+ .help = "create a flow rule",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_vc,
+ },
+ [DESTROY] = {
+ .name = "destroy",
+ .help = "destroy specific flow rules",
+ .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_destroy,
+ },
+ [FLUSH] = {
+ .name = "flush",
+ .help = "destroy all flow rules",
+ .next = NEXT(NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_flush,
+ },
+ [DUMP] = {
+ .name = "dump",
+ .help = "dump all flow rules to file",
+ .next = NEXT(next_dump_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_dump,
+ },
+ [QUERY] = {
+ .name = "query",
+ .help = "query an existing flow rule",
+ .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
+ NEXT_ENTRY(RULE_ID),
+ NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
+ ARGS_ENTRY(struct buffer, args.query.rule),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_query,
+ },
+ [LIST] = {
+ .name = "list",
+ .help = "list existing flow rules",
+ .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_list,
+ },
+ [AGED] = {
+ .name = "aged",
+ .help = "list and destroy aged flows",
+ .next = NEXT(next_aged_attr, NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+ .call = parse_aged,
+ },
+ [ISOLATE] = {
+ .name = "isolate",
+ .help = "restrict ingress traffic to the defined flow rules",
+ .next = NEXT(NEXT_ENTRY(BOOLEAN),
+ NEXT_ENTRY(PORT_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
+ ARGS_ENTRY(struct buffer, port)),
+ .call = parse_isolate,
+ },
+ /* Destroy arguments. */
+ [DESTROY_RULE] = {
+ .name = "rule",
+ .help = "specify a rule identifier",
+ .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
+ .call = parse_destroy,
+ },
+ /* Query arguments. */
+ [QUERY_ACTION] = {
+ .name = "{action}",
+ .type = "ACTION",
+ .help = "action to query, must be part of the rule",
+ .call = parse_action,
+ .comp = comp_action,
+ },
+ /* List arguments. */
+ [LIST_GROUP] = {
+ .name = "group",
+ .help = "specify a group",
+ .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
+ .call = parse_list,
+ },
+ [AGED_DESTROY] = {
+ .name = "destroy",
+ .help = "specify aged flows need be destroyed",
+ .call = parse_aged,
+ .comp = comp_none,
+ },
+ /* Validate/create attributes. */
+ [GROUP] = {
+ .name = "group",
+ .help = "specify a group",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
+ .call = parse_vc,
+ },
+ [PRIORITY] = {
+ .name = "priority",
+ .help = "specify a priority level",
+ .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
+ .call = parse_vc,
+ },
+ [INGRESS] = {
+ .name = "ingress",
+ .help = "affect rule to ingress",
+ .next = NEXT(next_vc_attr),
+ .call = parse_vc,
+ },
+ [EGRESS] = {
+ .name = "egress",
+ .help = "affect rule to egress",
+ .next = NEXT(next_vc_attr),
+ .call = parse_vc,
+ },
+ [TRANSFER] = {
+ .name = "transfer",
+ .help = "apply rule directly to endpoints found in pattern",
+ .next = NEXT(next_vc_attr),
+ .call = parse_vc,
+ },
+ /* Validate/create pattern. */
+ [PATTERN] = {
+ .name = "pattern",
+ .help = "submit a list of pattern items",
+ .next = NEXT(next_item),
+ .call = parse_vc,
+ },
+ [ITEM_PARAM_IS] = {
+ .name = "is",
+ .help = "match value perfectly (with full bit-mask)",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_SPEC] = {
+ .name = "spec",
+ .help = "match value according to configured bit-mask",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_LAST] = {
+ .name = "last",
+ .help = "specify upper bound to establish a range",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_MASK] = {
+ .name = "mask",
+ .help = "specify bit-mask with relevant bits set to one",
+ .call = parse_vc_spec,
+ },
+ [ITEM_PARAM_PREFIX] = {
+ .name = "prefix",
+ .help = "generate bit-mask from a prefix length",
+ .call = parse_vc_spec,
+ },
+ [ITEM_NEXT] = {
+ .name = "/",
+ .help = "specify next pattern item",
+ .next = NEXT(next_item),
+ },
+ [ITEM_END] = {
+ .name = "end",
+ .help = "end list of pattern items",
+ .priv = PRIV_ITEM(END, 0),
+ .next = NEXT(NEXT_ENTRY(ACTIONS)),
+ .call = parse_vc,
+ },
+ [ITEM_VOID] = {
+ .name = "void",
+ .help = "no-op pattern item",
+ .priv = PRIV_ITEM(VOID, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_INVERT] = {
+ .name = "invert",
+ .help = "perform actions when pattern does not match",
+ .priv = PRIV_ITEM(INVERT, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_ANY] = {
+ .name = "any",
+ .help = "match any protocol for the current layer",
+ .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
+ .next = NEXT(item_any),
+ .call = parse_vc,
+ },
+ [ITEM_ANY_NUM] = {
+ .name = "num",
+ .help = "number of layers covered",
+ .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
+ },
+ [ITEM_PF] = {
+ .name = "pf",
+ .help = "match traffic from/to the physical function",
+ .priv = PRIV_ITEM(PF, 0),
+ .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
+ .call = parse_vc,
+ },
+ [ITEM_VF] = {
+ .name = "vf",
+ .help = "match traffic from/to a virtual function ID",
+ .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
+ .next = NEXT(item_vf),
+ .call = parse_vc,
+ },
+ [ITEM_VF_ID] = {
+ .name = "id",
+ .help = "VF ID",
+ .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
+ },
+ [ITEM_PHY_PORT] = {
+ .name = "phy_port",
+ .help = "match traffic from/to a specific physical port",
+ .priv = PRIV_ITEM(PHY_PORT,
+ sizeof(struct rte_flow_item_phy_port)),
+ .next = NEXT(item_phy_port),
+ .call = parse_vc,
+ },
+ [ITEM_PHY_PORT_INDEX] = {
+ .name = "index",
+ .help = "physical port index",
+ .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
+ },
+ [ITEM_PORT_ID] = {
+ .name = "port_id",
+ .help = "match traffic from/to a given DPDK port ID",
+ .priv = PRIV_ITEM(PORT_ID,
+ sizeof(struct rte_flow_item_port_id)),
+ .next = NEXT(item_port_id),
+ .call = parse_vc,
+ },
+ [ITEM_PORT_ID_ID] = {
+ .name = "id",
+ .help = "DPDK port ID",
+ .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
+ },
+ [ITEM_MARK] = {
+ .name = "mark",
+ .help = "match traffic against value set in previously matched rule",
+ .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
+ .next = NEXT(item_mark),
+ .call = parse_vc,
+ },
+ [ITEM_MARK_ID] = {
+ .name = "id",
+ .help = "Integer value to match against",
+ .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
+ },
+ [ITEM_RAW] = {
+ .name = "raw",
+ .help = "match an arbitrary byte string",
+ .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
+ .next = NEXT(item_raw),
+ .call = parse_vc,
+ },
+ [ITEM_RAW_RELATIVE] = {
+ .name = "relative",
+ .help = "look for pattern after the previous item",
+ .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
+ relative, 1)),
+ },
+ [ITEM_RAW_SEARCH] = {
+ .name = "search",
+ .help = "search pattern from offset (see also limit)",
+ .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
+ search, 1)),
+ },
+ [ITEM_RAW_OFFSET] = {
+ .name = "offset",
+ .help = "absolute or relative offset for pattern",
+ .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
+ },
+ [ITEM_RAW_LIMIT] = {
+ .name = "limit",
+ .help = "search area limit for start of pattern",
+ .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
+ },
+ [ITEM_RAW_PATTERN] = {
+ .name = "pattern",
+ .help = "byte string to look for",
+ .next = NEXT(item_raw,
+ NEXT_ENTRY(STRING),
+ NEXT_ENTRY(ITEM_PARAM_IS,
+ ITEM_PARAM_SPEC,
+ ITEM_PARAM_MASK)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
+ ARGS_ENTRY(struct rte_flow_item_raw, length),
+ ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
+ ITEM_RAW_PATTERN_SIZE)),
+ },
+ [ITEM_ETH] = {
+ .name = "eth",
+ .help = "match Ethernet header",
+ .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
+ .next = NEXT(item_eth),
+ .call = parse_vc,
+ },
+ [ITEM_ETH_DST] = {
+ .name = "dst",
+ .help = "destination MAC",
+ .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
+ },
+ [ITEM_ETH_SRC] = {
+ .name = "src",
+ .help = "source MAC",
+ .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
+ },
+ [ITEM_ETH_TYPE] = {
+ .name = "type",
+ .help = "EtherType",
+ .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
+ },
+ [ITEM_VLAN] = {
+ .name = "vlan",
+ .help = "match 802.1Q/ad VLAN tag",
+ .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
+ .next = NEXT(item_vlan),
+ .call = parse_vc,
+ },
+ [ITEM_VLAN_TCI] = {
+ .name = "tci",
+ .help = "tag control information",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
+ },
+ [ITEM_VLAN_PCP] = {
+ .name = "pcp",
+ .help = "priority code point",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\xe0\x00")),
+ },
+ [ITEM_VLAN_DEI] = {
+ .name = "dei",
+ .help = "drop eligible indicator",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\x10\x00")),
+ },
+ [ITEM_VLAN_VID] = {
+ .name = "vid",
+ .help = "VLAN identifier",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
+ tci, "\x0f\xff")),
+ },
+ [ITEM_VLAN_INNER_TYPE] = {
+ .name = "inner_type",
+ .help = "inner EtherType",
+ .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
+ inner_type)),
+ },
+ [ITEM_IPV4] = {
+ .name = "ipv4",
+ .help = "match IPv4 header",
+ .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
+ .next = NEXT(item_ipv4),
+ .call = parse_vc,
+ },
+ [ITEM_IPV4_TOS] = {
+ .name = "tos",
+ .help = "type of service",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.type_of_service)),
+ },
+ [ITEM_IPV4_TTL] = {
+ .name = "ttl",
+ .help = "time to live",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.time_to_live)),
+ },
+ [ITEM_IPV4_PROTO] = {
+ .name = "proto",
+ .help = "next protocol ID",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.next_proto_id)),
+ },
+ [ITEM_IPV4_SRC] = {
+ .name = "src",
+ .help = "source address",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.src_addr)),
+ },
+ [ITEM_IPV4_DST] = {
+ .name = "dst",
+ .help = "destination address",
+ .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
+ hdr.dst_addr)),
+ },
+ [ITEM_IPV6] = {
+ .name = "ipv6",
+ .help = "match IPv6 header",
+ .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
+ .next = NEXT(item_ipv6),
+ .call = parse_vc,
+ },
+ [ITEM_IPV6_TC] = {
+ .name = "tc",
+ .help = "traffic class",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
+ hdr.vtc_flow,
+ "\x0f\xf0\x00\x00")),
+ },
+ [ITEM_IPV6_FLOW] = {
+ .name = "flow",
+ .help = "flow label",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
+ hdr.vtc_flow,
+ "\x00\x0f\xff\xff")),
+ },
+ [ITEM_IPV6_PROTO] = {
+ .name = "proto",
+ .help = "protocol (next header)",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.proto)),
+ },
+ [ITEM_IPV6_HOP] = {
+ .name = "hop",
+ .help = "hop limit",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.hop_limits)),
+ },
+ [ITEM_IPV6_SRC] = {
+ .name = "src",
+ .help = "source address",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.src_addr)),
+ },
+ [ITEM_IPV6_DST] = {
+ .name = "dst",
+ .help = "destination address",
+ .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
+ hdr.dst_addr)),
+ },
+ [ITEM_ICMP] = {
+ .name = "icmp",
+ .help = "match ICMP header",
+ .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
+ .next = NEXT(item_icmp),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP_TYPE] = {
+ .name = "type",
+ .help = "ICMP packet type",
+ .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
+ hdr.icmp_type)),
+ },
+ [ITEM_ICMP_CODE] = {
+ .name = "code",
+ .help = "ICMP packet code",
+ .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
+ hdr.icmp_code)),
+ },
+ [ITEM_UDP] = {
+ .name = "udp",
+ .help = "match UDP header",
+ .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
+ .next = NEXT(item_udp),
+ .call = parse_vc,
+ },
+ [ITEM_UDP_SRC] = {
+ .name = "src",
+ .help = "UDP source port",
+ .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
+ hdr.src_port)),
+ },
+ [ITEM_UDP_DST] = {
+ .name = "dst",
+ .help = "UDP destination port",
+ .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
+ hdr.dst_port)),
+ },
+ [ITEM_TCP] = {
+ .name = "tcp",
+ .help = "match TCP header",
+ .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
+ .next = NEXT(item_tcp),
+ .call = parse_vc,
+ },
+ [ITEM_TCP_SRC] = {
+ .name = "src",
+ .help = "TCP source port",
+ .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
+ hdr.src_port)),
+ },
+ [ITEM_TCP_DST] = {
+ .name = "dst",
+ .help = "TCP destination port",
+ .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
+ hdr.dst_port)),
+ },
+ [ITEM_TCP_FLAGS] = {
+ .name = "flags",
+ .help = "TCP flags",
+ .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
+ hdr.tcp_flags)),
+ },
+ [ITEM_SCTP] = {
+ .name = "sctp",
+ .help = "match SCTP header",
+ .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
+ .next = NEXT(item_sctp),
+ .call = parse_vc,
+ },
+ [ITEM_SCTP_SRC] = {
+ .name = "src",
+ .help = "SCTP source port",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.src_port)),
+ },
+ [ITEM_SCTP_DST] = {
+ .name = "dst",
+ .help = "SCTP destination port",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.dst_port)),
+ },
+ [ITEM_SCTP_TAG] = {
+ .name = "tag",
+ .help = "validation tag",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.tag)),
+ },
+ [ITEM_SCTP_CKSUM] = {
+ .name = "cksum",
+ .help = "checksum",
+ .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
+ hdr.cksum)),
+ },
+ [ITEM_VXLAN] = {
+ .name = "vxlan",
+ .help = "match VXLAN header",
+ .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
+ .next = NEXT(item_vxlan),
+ .call = parse_vc,
+ },
+ [ITEM_VXLAN_VNI] = {
+ .name = "vni",
+ .help = "VXLAN identifier",
+ .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
+ },
+ [ITEM_E_TAG] = {
+ .name = "e_tag",
+ .help = "match E-Tag header",
+ .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
+ .next = NEXT(item_e_tag),
+ .call = parse_vc,
+ },
+ [ITEM_E_TAG_GRP_ECID_B] = {
+ .name = "grp_ecid_b",
+ .help = "GRP and E-CID base",
+ .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
+ rsvd_grp_ecid_b,
+ "\x3f\xff")),
+ },
+ [ITEM_NVGRE] = {
+ .name = "nvgre",
+ .help = "match NVGRE header",
+ .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
+ .next = NEXT(item_nvgre),
+ .call = parse_vc,
+ },
+ [ITEM_NVGRE_TNI] = {
+ .name = "tni",
+ .help = "virtual subnet ID",
+ .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
+ },
+ [ITEM_MPLS] = {
+ .name = "mpls",
+ .help = "match MPLS header",
+ .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
+ .next = NEXT(item_mpls),
+ .call = parse_vc,
+ },
+ [ITEM_MPLS_LABEL] = {
+ .name = "label",
+ .help = "MPLS label",
+ .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+ label_tc_s,
+ "\xff\xff\xf0")),
+ },
+ [ITEM_MPLS_TC] = {
+ .name = "tc",
+ .help = "MPLS Traffic Class",
+ .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+ label_tc_s,
+ "\x00\x00\x0e")),
+ },
+ [ITEM_MPLS_S] = {
+ .name = "s",
+ .help = "MPLS Bottom-of-Stack",
+ .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
+ label_tc_s,
+ "\x00\x00\x01")),
+ },
+ [ITEM_GRE] = {
+ .name = "gre",
+ .help = "match GRE header",
+ .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
+ .next = NEXT(item_gre),
+ .call = parse_vc,
+ },
+ [ITEM_GRE_PROTO] = {
+ .name = "protocol",
+ .help = "GRE protocol type",
+ .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+ protocol)),
+ },
+ [ITEM_GRE_C_RSVD0_VER] = {
+ .name = "c_rsvd0_ver",
+ .help =
+ "checksum (1b), undefined (1b), key bit (1b),"
+ " sequence number (1b), reserved 0 (9b),"
+ " version (3b)",
+ .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
+ c_rsvd0_ver)),
+ },
+ [ITEM_GRE_C_BIT] = {
+ .name = "c_bit",
+ .help = "checksum bit (C)",
+ .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
+ c_rsvd0_ver,
+ "\x80\x00\x00\x00")),
+ },
+ [ITEM_GRE_S_BIT] = {
+ .name = "s_bit",
+ .help = "sequence number bit (S)",
+ .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
+ c_rsvd0_ver,
+ "\x10\x00\x00\x00")),
+ },
+ [ITEM_GRE_K_BIT] = {
+ .name = "k_bit",
+ .help = "key bit (K)",
+ .next = NEXT(item_gre, NEXT_ENTRY(BOOLEAN), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre,
+ c_rsvd0_ver,
+ "\x20\x00\x00\x00")),
+ },
+ [ITEM_FUZZY] = {
+ .name = "fuzzy",
+ .help = "fuzzy pattern match, expect faster than default",
+ .priv = PRIV_ITEM(FUZZY,
+ sizeof(struct rte_flow_item_fuzzy)),
+ .next = NEXT(item_fuzzy),
+ .call = parse_vc,
+ },
+ [ITEM_FUZZY_THRESH] = {
+ .name = "thresh",
+ .help = "match accuracy threshold",
+ .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
+ thresh)),
+ },
+ [ITEM_GTP] = {
+ .name = "gtp",
+ .help = "match GTP header",
+ .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
+ .next = NEXT(item_gtp),
+ .call = parse_vc,
+ },
+ [ITEM_GTP_FLAGS] = {
+ .name = "v_pt_rsv_flags",
+ .help = "GTP flags",
+ .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
+ v_pt_rsv_flags)),
+ },
+ [ITEM_GTP_MSG_TYPE] = {
+ .name = "msg_type",
+ .help = "GTP message type",
+ .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
+ },
+ [ITEM_GTP_TEID] = {
+ .name = "teid",
+ .help = "tunnel endpoint identifier",
+ .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
+ },
+ [ITEM_GTPC] = {
+ .name = "gtpc",
+ .help = "match GTP header",
+ .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
+ .next = NEXT(item_gtp),
+ .call = parse_vc,
+ },
+ [ITEM_GTPU] = {
+ .name = "gtpu",
+ .help = "match GTP header",
+ .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
+ .next = NEXT(item_gtp),
+ .call = parse_vc,
+ },
+ [ITEM_GENEVE] = {
+ .name = "geneve",
+ .help = "match GENEVE header",
+ .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+ .next = NEXT(item_geneve),
+ .call = parse_vc,
+ },
+ [ITEM_GENEVE_VNI] = {
+ .name = "vni",
+ .help = "virtual network identifier",
+ .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
+ },
+ [ITEM_GENEVE_PROTO] = {
+ .name = "protocol",
+ .help = "GENEVE protocol type",
+ .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
+ protocol)),
+ },
+ [ITEM_VXLAN_GPE] = {
+ .name = "vxlan-gpe",
+ .help = "match VXLAN-GPE header",
+ .priv = PRIV_ITEM(VXLAN_GPE,
+ sizeof(struct rte_flow_item_vxlan_gpe)),
+ .next = NEXT(item_vxlan_gpe),
+ .call = parse_vc,
+ },
+ [ITEM_VXLAN_GPE_VNI] = {
+ .name = "vni",
+ .help = "VXLAN-GPE identifier",
+ .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
+ vni)),
+ },
+ [ITEM_ARP_ETH_IPV4] = {
+ .name = "arp_eth_ipv4",
+ .help = "match ARP header for Ethernet/IPv4",
+ .priv = PRIV_ITEM(ARP_ETH_IPV4,
+ sizeof(struct rte_flow_item_arp_eth_ipv4)),
+ .next = NEXT(item_arp_eth_ipv4),
+ .call = parse_vc,
+ },
+ [ITEM_ARP_ETH_IPV4_SHA] = {
+ .name = "sha",
+ .help = "sender hardware address",
+ .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+ sha)),
+ },
+ [ITEM_ARP_ETH_IPV4_SPA] = {
+ .name = "spa",
+ .help = "sender IPv4 address",
+ .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+ spa)),
+ },
+ [ITEM_ARP_ETH_IPV4_THA] = {
+ .name = "tha",
+ .help = "target hardware address",
+ .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+ tha)),
+ },
+ [ITEM_ARP_ETH_IPV4_TPA] = {
+ .name = "tpa",
+ .help = "target IPv4 address",
+ .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+ tpa)),
+ },
+ [ITEM_IPV6_EXT] = {
+ .name = "ipv6_ext",
+ .help = "match presence of any IPv6 extension header",
+ .priv = PRIV_ITEM(IPV6_EXT,
+ sizeof(struct rte_flow_item_ipv6_ext)),
+ .next = NEXT(item_ipv6_ext),
+ .call = parse_vc,
+ },
+ [ITEM_IPV6_EXT_NEXT_HDR] = {
+ .name = "next_hdr",
+ .help = "next header",
+ .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+ next_hdr)),
+ },
+ [ITEM_ICMP6] = {
+ .name = "icmp6",
+ .help = "match any ICMPv6 header",
+ .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+ .next = NEXT(item_icmp6),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_TYPE] = {
+ .name = "type",
+ .help = "ICMPv6 type",
+ .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+ type)),
+ },
+ [ITEM_ICMP6_CODE] = {
+ .name = "code",
+ .help = "ICMPv6 code",
+ .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+ code)),
+ },
+ [ITEM_ICMP6_ND_NS] = {
+ .name = "icmp6_nd_ns",
+ .help = "match ICMPv6 neighbor discovery solicitation",
+ .priv = PRIV_ITEM(ICMP6_ND_NS,
+ sizeof(struct rte_flow_item_icmp6_nd_ns)),
+ .next = NEXT(item_icmp6_nd_ns),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
+ .name = "target_addr",
+ .help = "target address",
+ .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
+ target_addr)),
+ },
+ [ITEM_ICMP6_ND_NA] = {
+ .name = "icmp6_nd_na",
+ .help = "match ICMPv6 neighbor discovery advertisement",
+ .priv = PRIV_ITEM(ICMP6_ND_NA,
+ sizeof(struct rte_flow_item_icmp6_nd_na)),
+ .next = NEXT(item_icmp6_nd_na),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
+ .name = "target_addr",
+ .help = "target address",
+ .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
+ target_addr)),
+ },
+ [ITEM_ICMP6_ND_OPT] = {
+ .name = "icmp6_nd_opt",
+ .help = "match presence of any ICMPv6 neighbor discovery"
+ " option",
+ .priv = PRIV_ITEM(ICMP6_ND_OPT,
+ sizeof(struct rte_flow_item_icmp6_nd_opt)),
+ .next = NEXT(item_icmp6_nd_opt),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_ND_OPT_TYPE] = {
+ .name = "type",
+ .help = "ND option type",
+ .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
+ type)),
+ },
+ [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
+ .name = "icmp6_nd_opt_sla_eth",
+ .help = "match ICMPv6 neighbor discovery source Ethernet"
+ " link-layer address option",
+ .priv = PRIV_ITEM
+ (ICMP6_ND_OPT_SLA_ETH,
+ sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+ .next = NEXT(item_icmp6_nd_opt_sla_eth),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
+ .name = "sla",
+ .help = "source Ethernet LLA",
+ .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
+ },
+ [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
+ .name = "icmp6_nd_opt_tla_eth",
+ .help = "match ICMPv6 neighbor discovery target Ethernet"
+ " link-layer address option",
+ .priv = PRIV_ITEM
+ (ICMP6_ND_OPT_TLA_ETH,
+ sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
+ .next = NEXT(item_icmp6_nd_opt_tla_eth),
+ .call = parse_vc,
+ },
+ [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
+ .name = "tla",
+ .help = "target Ethernet LLA",
+ .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
+ },
+ [ITEM_META] = {
+ .name = "meta",
+ .help = "match metadata header",
+ .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
+ .next = NEXT(item_meta),
+ .call = parse_vc,
+ },
+ [ITEM_META_DATA] = {
+ .name = "data",
+ .help = "metadata value",
+ .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta,
+ data, "\xff\xff\xff\xff")),
+ },
+ [ITEM_GRE_KEY] = {
+ .name = "gre_key",
+ .help = "match GRE key",
+ .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)),
+ .next = NEXT(item_gre_key),
+ .call = parse_vc,
+ },
+ [ITEM_GRE_KEY_VALUE] = {
+ .name = "value",
+ .help = "key value",
+ .next = NEXT(item_gre_key, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
+ },
+ [ITEM_GTP_PSC] = {
+ .name = "gtp_psc",
+ .help = "match GTP extension header with type 0x85",
+ .priv = PRIV_ITEM(GTP_PSC,
+ sizeof(struct rte_flow_item_gtp_psc)),
+ .next = NEXT(item_gtp_psc),
+ .call = parse_vc,
+ },
+ [ITEM_GTP_PSC_QFI] = {
+ .name = "qfi",
+ .help = "QoS flow identifier",
+ .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
+ qfi)),
+ },
+ [ITEM_GTP_PSC_PDU_T] = {
+ .name = "pdu_t",
+ .help = "PDU type",
+ .next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
+ pdu_type)),
+ },
+ [ITEM_PPPOES] = {
+ .name = "pppoes",
+ .help = "match PPPoE session header",
+ .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
+ .next = NEXT(item_pppoes),
+ .call = parse_vc,
+ },
+ [ITEM_PPPOED] = {
+ .name = "pppoed",
+ .help = "match PPPoE discovery header",
+ .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
+ .next = NEXT(item_pppoed),
+ .call = parse_vc,
+ },
+ [ITEM_PPPOE_SEID] = {
+ .name = "seid",
+ .help = "session identifier",
+ .next = NEXT(item_pppoes, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
+ session_id)),
+ },
+ [ITEM_PPPOE_PROTO_ID] = {
+ .name = "pppoe_proto_id",
+ .help = "match PPPoE session protocol identifier",
+ .priv = PRIV_ITEM(PPPOE_PROTO_ID,
+ sizeof(struct rte_flow_item_pppoe_proto_id)),
+ .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(UNSIGNED),
+ item_param),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_item_pppoe_proto_id, proto_id)),
+ .call = parse_vc,
+ },
+ [ITEM_HIGIG2] = {
+ .name = "higig2",
+ .help = "matches higig2 header",
+ .priv = PRIV_ITEM(HIGIG2,
+ sizeof(struct rte_flow_item_higig2_hdr)),
+ .next = NEXT(item_higig2),
+ .call = parse_vc,
+ },
+ [ITEM_HIGIG2_CLASSIFICATION] = {
+ .name = "classification",
+ .help = "matches classification of higig2 header",
+ .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
+ hdr.ppt1.classification)),
+ },
+ [ITEM_HIGIG2_VID] = {
+ .name = "vid",
+ .help = "matches vid of higig2 header",
+ .next = NEXT(item_higig2, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr,
+ hdr.ppt1.vid)),
+ },
+ [ITEM_TAG] = {
+ .name = "tag",
+ .help = "match tag value",
+ .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)),
+ .next = NEXT(item_tag),
+ .call = parse_vc,
+ },
+ [ITEM_TAG_DATA] = {
+ .name = "data",
+ .help = "tag value to match",
+ .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)),
+ },
+ [ITEM_TAG_INDEX] = {
+ .name = "index",
+ .help = "index of tag array to match",
+ .next = NEXT(item_tag, NEXT_ENTRY(UNSIGNED),
+ NEXT_ENTRY(ITEM_PARAM_IS)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)),
+ },
+ [ITEM_L2TPV3OIP] = {
+ .name = "l2tpv3oip",
+ .help = "match L2TPv3 over IP header",
+ .priv = PRIV_ITEM(L2TPV3OIP,
+ sizeof(struct rte_flow_item_l2tpv3oip)),
+ .next = NEXT(item_l2tpv3oip),
+ .call = parse_vc,
+ },
+ [ITEM_L2TPV3OIP_SESSION_ID] = {
+ .name = "session_id",
+ .help = "session identifier",
+ .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip,
+ session_id)),
+ },
+ [ITEM_ESP] = {
+ .name = "esp",
+ .help = "match ESP header",
+ .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
+ .next = NEXT(item_esp),
+ .call = parse_vc,
+ },
+ [ITEM_ESP_SPI] = {
+ .name = "spi",
+ .help = "security policy index",
+ .next = NEXT(item_esp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp,
+ hdr.spi)),
+ },
+ [ITEM_AH] = {
+ .name = "ah",
+ .help = "match AH header",
+ .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)),
+ .next = NEXT(item_ah),
+ .call = parse_vc,
+ },
+ [ITEM_AH_SPI] = {
+ .name = "spi",
+ .help = "security parameters index",
+ .next = NEXT(item_ah, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)),
+ },
+ [ITEM_PFCP] = {
+ .name = "pfcp",
+ .help = "match pfcp header",
+ .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)),
+ .next = NEXT(item_pfcp),
+ .call = parse_vc,
+ },
+ [ITEM_PFCP_S_FIELD] = {
+ .name = "s_field",
+ .help = "S field",
+ .next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp,
+ s_field)),
+ },
+ [ITEM_PFCP_SEID] = {
+ .name = "seid",
+ .help = "session endpoint identifier",
+ .next = NEXT(item_pfcp, NEXT_ENTRY(UNSIGNED), item_param),
+ .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)),
+ },
+ /* Validate/create actions. */
+ [ACTIONS] = {
+ .name = "actions",
+ .help = "submit a list of associated actions",
+ .next = NEXT(next_action),
+ .call = parse_vc,
+ },
+ [ACTION_NEXT] = {
+ .name = "/",
+ .help = "specify next action",
+ .next = NEXT(next_action),
+ },
+ [ACTION_END] = {
+ .name = "end",
+ .help = "end list of actions",
+ .priv = PRIV_ACTION(END, 0),
+ .call = parse_vc,
+ },
+ [ACTION_VOID] = {
+ .name = "void",
+ .help = "no-op action",
+ .priv = PRIV_ACTION(VOID, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_PASSTHRU] = {
+ .name = "passthru",
+ .help = "let subsequent rule process matched packets",
+ .priv = PRIV_ACTION(PASSTHRU, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_JUMP] = {
+ .name = "jump",
+ .help = "redirect traffic to a given group",
+ .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
+ .next = NEXT(action_jump),
+ .call = parse_vc,
+ },
+ [ACTION_JUMP_GROUP] = {
+ .name = "group",
+ .help = "group to redirect traffic to",
+ .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MARK] = {
+ .name = "mark",
+ .help = "attach 32 bit value to packets",
+ .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
+ .next = NEXT(action_mark),
+ .call = parse_vc,
+ },
+ [ACTION_MARK_ID] = {
+ .name = "id",
+ .help = "32 bit value to return with packets",
+ .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_FLAG] = {
+ .name = "flag",
+ .help = "flag packets",
+ .priv = PRIV_ACTION(FLAG, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_QUEUE] = {
+ .name = "queue",
+ .help = "assign packets to a given queue index",
+ .priv = PRIV_ACTION(QUEUE,
+ sizeof(struct rte_flow_action_queue)),
+ .next = NEXT(action_queue),
+ .call = parse_vc,
+ },
+ [ACTION_QUEUE_INDEX] = {
+ .name = "index",
+ .help = "queue index to use",
+ .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_DROP] = {
+ .name = "drop",
+ .help = "drop packets (note: passthru has priority)",
+ .priv = PRIV_ACTION(DROP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_COUNT] = {
+ .name = "count",
+ .help = "enable counters for this rule",
+ .priv = PRIV_ACTION(COUNT,
+ sizeof(struct rte_flow_action_count)),
+ .next = NEXT(action_count),
+ .call = parse_vc,
+ },
+ [ACTION_COUNT_ID] = {
+ .name = "identifier",
+ .help = "counter identifier to use",
+ .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_COUNT_SHARED] = {
+ .name = "shared",
+ .help = "shared counter",
+ .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
+ shared, 1)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_RSS] = {
+ .name = "rss",
+ .help = "spread packets among several queues",
+ .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
+ .next = NEXT(action_rss),
+ .call = parse_vc_action_rss,
+ },
+ [ACTION_RSS_FUNC] = {
+ .name = "func",
+ .help = "RSS hash function to apply",
+ .next = NEXT(action_rss,
+ NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
+ ACTION_RSS_FUNC_TOEPLITZ,
+ ACTION_RSS_FUNC_SIMPLE_XOR,
+ ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)),
+ },
+ [ACTION_RSS_FUNC_DEFAULT] = {
+ .name = "default",
+ .help = "default hash function",
+ .call = parse_vc_action_rss_func,
+ },
+ [ACTION_RSS_FUNC_TOEPLITZ] = {
+ .name = "toeplitz",
+ .help = "Toeplitz hash function",
+ .call = parse_vc_action_rss_func,
+ },
+ [ACTION_RSS_FUNC_SIMPLE_XOR] = {
+ .name = "simple_xor",
+ .help = "simple XOR hash function",
+ .call = parse_vc_action_rss_func,
+ },
+ [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = {
+ .name = "symmetric_toeplitz",
+ .help = "Symmetric Toeplitz hash function",
+ .call = parse_vc_action_rss_func,
+ },
+ [ACTION_RSS_LEVEL] = {
+ .name = "level",
+ .help = "encapsulation level for \"types\"",
+ .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_ARB
+ (offsetof(struct action_rss_data, conf) +
+ offsetof(struct rte_flow_action_rss, level),
+ sizeof(((struct rte_flow_action_rss *)0)->
+ level))),
+ },
+ [ACTION_RSS_TYPES] = {
+ .name = "types",
+ .help = "specific RSS hash types",
+ .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
+ },
+ [ACTION_RSS_TYPE] = {
+ .name = "{type}",
+ .help = "RSS hash type",
+ .call = parse_vc_action_rss_type,
+ .comp = comp_vc_action_rss_type,
+ },
+ [ACTION_RSS_KEY] = {
+ .name = "key",
+ .help = "RSS hash key",
+ .next = NEXT(action_rss, NEXT_ENTRY(HEX)),
+ .args = ARGS(ARGS_ENTRY_ARB(0, 0),
+ ARGS_ENTRY_ARB
+ (offsetof(struct action_rss_data, conf) +
+ offsetof(struct rte_flow_action_rss, key_len),
+ sizeof(((struct rte_flow_action_rss *)0)->
+ key_len)),
+ ARGS_ENTRY(struct action_rss_data, key)),
+ },
+ [ACTION_RSS_KEY_LEN] = {
+ .name = "key_len",
+ .help = "RSS hash key length in bytes",
+ .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_rss_data, conf) +
+ offsetof(struct rte_flow_action_rss, key_len),
+ sizeof(((struct rte_flow_action_rss *)0)->
+ key_len),
+ 0,
+ RSS_HASH_KEY_LENGTH)),
+ },
+ [ACTION_RSS_QUEUES] = {
+ .name = "queues",
+ .help = "queue indices to use",
+ .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_RSS_QUEUE] = {
+ .name = "{queue}",
+ .help = "queue index",
+ .call = parse_vc_action_rss_queue,
+ .comp = comp_vc_action_rss_queue,
+ },
+ [ACTION_PF] = {
+ .name = "pf",
+ .help = "direct traffic to physical function",
+ .priv = PRIV_ACTION(PF, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_VF] = {
+ .name = "vf",
+ .help = "direct traffic to a virtual function ID",
+ .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
+ .next = NEXT(action_vf),
+ .call = parse_vc,
+ },
+ [ACTION_VF_ORIGINAL] = {
+ .name = "original",
+ .help = "use original VF ID if possible",
+ .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
+ original, 1)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_VF_ID] = {
+ .name = "id",
+ .help = "VF ID",
+ .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_PHY_PORT] = {
+ .name = "phy_port",
+ .help = "direct packets to physical port index",
+ .priv = PRIV_ACTION(PHY_PORT,
+ sizeof(struct rte_flow_action_phy_port)),
+ .next = NEXT(action_phy_port),
+ .call = parse_vc,
+ },
+ [ACTION_PHY_PORT_ORIGINAL] = {
+ .name = "original",
+ .help = "use original port index if possible",
+ .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
+ original, 1)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_PHY_PORT_INDEX] = {
+ .name = "index",
+ .help = "physical port index",
+ .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
+ index)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_PORT_ID] = {
+ .name = "port_id",
+ .help = "direct matching traffic to a given DPDK port ID",
+ .priv = PRIV_ACTION(PORT_ID,
+ sizeof(struct rte_flow_action_port_id)),
+ .next = NEXT(action_port_id),
+ .call = parse_vc,
+ },
+ [ACTION_PORT_ID_ORIGINAL] = {
+ .name = "original",
+ .help = "use original DPDK port ID if possible",
+ .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
+ original, 1)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_PORT_ID_ID] = {
+ .name = "id",
+ .help = "DPDK port ID",
+ .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_METER] = {
+ .name = "meter",
+ .help = "meter the directed packets at given id",
+ .priv = PRIV_ACTION(METER,
+ sizeof(struct rte_flow_action_meter)),
+ .next = NEXT(action_meter),
+ .call = parse_vc,
+ },
+ [ACTION_METER_ID] = {
+ .name = "mtr_id",
+ .help = "meter id to use",
+ .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_SET_MPLS_TTL] = {
+ .name = "of_set_mpls_ttl",
+ .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
+ .priv = PRIV_ACTION
+ (OF_SET_MPLS_TTL,
+ sizeof(struct rte_flow_action_of_set_mpls_ttl)),
+ .next = NEXT(action_of_set_mpls_ttl),
+ .call = parse_vc,
+ },
+ [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
+ .name = "mpls_ttl",
+ .help = "MPLS TTL",
+ .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
+ mpls_ttl)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_DEC_MPLS_TTL] = {
+ .name = "of_dec_mpls_ttl",
+ .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
+ .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_OF_SET_NW_TTL] = {
+ .name = "of_set_nw_ttl",
+ .help = "OpenFlow's OFPAT_SET_NW_TTL",
+ .priv = PRIV_ACTION
+ (OF_SET_NW_TTL,
+ sizeof(struct rte_flow_action_of_set_nw_ttl)),
+ .next = NEXT(action_of_set_nw_ttl),
+ .call = parse_vc,
+ },
+ [ACTION_OF_SET_NW_TTL_NW_TTL] = {
+ .name = "nw_ttl",
+ .help = "IP TTL",
+ .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
+ nw_ttl)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_DEC_NW_TTL] = {
+ .name = "of_dec_nw_ttl",
+ .help = "OpenFlow's OFPAT_DEC_NW_TTL",
+ .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_OF_COPY_TTL_OUT] = {
+ .name = "of_copy_ttl_out",
+ .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
+ .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_OF_COPY_TTL_IN] = {
+ .name = "of_copy_ttl_in",
+ .help = "OpenFlow's OFPAT_COPY_TTL_IN",
+ .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_OF_POP_VLAN] = {
+ .name = "of_pop_vlan",
+ .help = "OpenFlow's OFPAT_POP_VLAN",
+ .priv = PRIV_ACTION(OF_POP_VLAN, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_OF_PUSH_VLAN] = {
+ .name = "of_push_vlan",
+ .help = "OpenFlow's OFPAT_PUSH_VLAN",
+ .priv = PRIV_ACTION
+ (OF_PUSH_VLAN,
+ sizeof(struct rte_flow_action_of_push_vlan)),
+ .next = NEXT(action_of_push_vlan),
+ .call = parse_vc,
+ },
+ [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
+ .name = "ethertype",
+ .help = "EtherType",
+ .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_of_push_vlan,
+ ethertype)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_SET_VLAN_VID] = {
+ .name = "of_set_vlan_vid",
+ .help = "OpenFlow's OFPAT_SET_VLAN_VID",
+ .priv = PRIV_ACTION
+ (OF_SET_VLAN_VID,
+ sizeof(struct rte_flow_action_of_set_vlan_vid)),
+ .next = NEXT(action_of_set_vlan_vid),
+ .call = parse_vc,
+ },
+ [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
+ .name = "vlan_vid",
+ .help = "VLAN id",
+ .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_of_set_vlan_vid,
+ vlan_vid)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_SET_VLAN_PCP] = {
+ .name = "of_set_vlan_pcp",
+ .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
+ .priv = PRIV_ACTION
+ (OF_SET_VLAN_PCP,
+ sizeof(struct rte_flow_action_of_set_vlan_pcp)),
+ .next = NEXT(action_of_set_vlan_pcp),
+ .call = parse_vc,
+ },
+ [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
+ .name = "vlan_pcp",
+ .help = "VLAN priority",
+ .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_of_set_vlan_pcp,
+ vlan_pcp)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_POP_MPLS] = {
+ .name = "of_pop_mpls",
+ .help = "OpenFlow's OFPAT_POP_MPLS",
+ .priv = PRIV_ACTION(OF_POP_MPLS,
+ sizeof(struct rte_flow_action_of_pop_mpls)),
+ .next = NEXT(action_of_pop_mpls),
+ .call = parse_vc,
+ },
+ [ACTION_OF_POP_MPLS_ETHERTYPE] = {
+ .name = "ethertype",
+ .help = "EtherType",
+ .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_of_pop_mpls,
+ ethertype)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_OF_PUSH_MPLS] = {
+ .name = "of_push_mpls",
+ .help = "OpenFlow's OFPAT_PUSH_MPLS",
+ .priv = PRIV_ACTION
+ (OF_PUSH_MPLS,
+ sizeof(struct rte_flow_action_of_push_mpls)),
+ .next = NEXT(action_of_push_mpls),
+ .call = parse_vc,
+ },
+ [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
+ .name = "ethertype",
+ .help = "EtherType",
+ .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_of_push_mpls,
+ ethertype)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_VXLAN_ENCAP] = {
+ .name = "vxlan_encap",
+ .help = "VXLAN encapsulation, uses configuration set by \"set"
+ " vxlan\"",
+ .priv = PRIV_ACTION(VXLAN_ENCAP,
+ sizeof(struct action_vxlan_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_vxlan_encap,
+ },
+ [ACTION_VXLAN_DECAP] = {
+ .name = "vxlan_decap",
+ .help = "Performs a decapsulation action by stripping all"
+ " headers of the VXLAN tunnel network overlay from the"
+ " matched flow.",
+ .priv = PRIV_ACTION(VXLAN_DECAP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_NVGRE_ENCAP] = {
+ .name = "nvgre_encap",
+ .help = "NVGRE encapsulation, uses configuration set by \"set"
+ " nvgre\"",
+ .priv = PRIV_ACTION(NVGRE_ENCAP,
+ sizeof(struct action_nvgre_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_nvgre_encap,
+ },
+ [ACTION_NVGRE_DECAP] = {
+ .name = "nvgre_decap",
+ .help = "Performs a decapsulation action by stripping all"
+ " headers of the NVGRE tunnel network overlay from the"
+ " matched flow.",
+ .priv = PRIV_ACTION(NVGRE_DECAP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_L2_ENCAP] = {
+ .name = "l2_encap",
+ .help = "l2 encap, uses configuration set by"
+ " \"set l2_encap\"",
+ .priv = PRIV_ACTION(RAW_ENCAP,
+ sizeof(struct action_raw_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_l2_encap,
+ },
+ [ACTION_L2_DECAP] = {
+ .name = "l2_decap",
+ .help = "l2 decap, uses configuration set by"
+ " \"set l2_decap\"",
+ .priv = PRIV_ACTION(RAW_DECAP,
+ sizeof(struct action_raw_decap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_l2_decap,
+ },
+ [ACTION_MPLSOGRE_ENCAP] = {
+ .name = "mplsogre_encap",
+ .help = "mplsogre encapsulation, uses configuration set by"
+ " \"set mplsogre_encap\"",
+ .priv = PRIV_ACTION(RAW_ENCAP,
+ sizeof(struct action_raw_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_mplsogre_encap,
+ },
+ [ACTION_MPLSOGRE_DECAP] = {
+ .name = "mplsogre_decap",
+ .help = "mplsogre decapsulation, uses configuration set by"
+ " \"set mplsogre_decap\"",
+ .priv = PRIV_ACTION(RAW_DECAP,
+ sizeof(struct action_raw_decap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_mplsogre_decap,
+ },
+ [ACTION_MPLSOUDP_ENCAP] = {
+ .name = "mplsoudp_encap",
+ .help = "mplsoudp encapsulation, uses configuration set by"
+ " \"set mplsoudp_encap\"",
+ .priv = PRIV_ACTION(RAW_ENCAP,
+ sizeof(struct action_raw_encap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_mplsoudp_encap,
+ },
+ [ACTION_MPLSOUDP_DECAP] = {
+ .name = "mplsoudp_decap",
+ .help = "mplsoudp decapsulation, uses configuration set by"
+ " \"set mplsoudp_decap\"",
+ .priv = PRIV_ACTION(RAW_DECAP,
+ sizeof(struct action_raw_decap_data)),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_mplsoudp_decap,
+ },
+ [ACTION_SET_IPV4_SRC] = {
+ .name = "set_ipv4_src",
+ .help = "Set a new IPv4 source address in the outermost"
+ " IPv4 header",
+ .priv = PRIV_ACTION(SET_IPV4_SRC,
+ sizeof(struct rte_flow_action_set_ipv4)),
+ .next = NEXT(action_set_ipv4_src),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
+ .name = "ipv4_addr",
+ .help = "new IPv4 source address to set",
+ .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_ipv4, ipv4_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_IPV4_DST] = {
+ .name = "set_ipv4_dst",
+ .help = "Set a new IPv4 destination address in the outermost"
+ " IPv4 header",
+ .priv = PRIV_ACTION(SET_IPV4_DST,
+ sizeof(struct rte_flow_action_set_ipv4)),
+ .next = NEXT(action_set_ipv4_dst),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV4_DST_IPV4_DST] = {
+ .name = "ipv4_addr",
+ .help = "new IPv4 destination address to set",
+ .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_ipv4, ipv4_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_IPV6_SRC] = {
+ .name = "set_ipv6_src",
+ .help = "Set a new IPv6 source address in the outermost"
+ " IPv6 header",
+ .priv = PRIV_ACTION(SET_IPV6_SRC,
+ sizeof(struct rte_flow_action_set_ipv6)),
+ .next = NEXT(action_set_ipv6_src),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
+ .name = "ipv6_addr",
+ .help = "new IPv6 source address to set",
+ .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_ipv6, ipv6_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_IPV6_DST] = {
+ .name = "set_ipv6_dst",
+ .help = "Set a new IPv6 destination address in the outermost"
+ " IPv6 header",
+ .priv = PRIV_ACTION(SET_IPV6_DST,
+ sizeof(struct rte_flow_action_set_ipv6)),
+ .next = NEXT(action_set_ipv6_dst),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV6_DST_IPV6_DST] = {
+ .name = "ipv6_addr",
+ .help = "new IPv6 destination address to set",
+ .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_ipv6, ipv6_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_TP_SRC] = {
+ .name = "set_tp_src",
+ .help = "set a new source port number in the outermost"
+ " TCP/UDP header",
+ .priv = PRIV_ACTION(SET_TP_SRC,
+ sizeof(struct rte_flow_action_set_tp)),
+ .next = NEXT(action_set_tp_src),
+ .call = parse_vc,
+ },
+ [ACTION_SET_TP_SRC_TP_SRC] = {
+ .name = "port",
+ .help = "new source port number to set",
+ .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_tp, port)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_TP_DST] = {
+ .name = "set_tp_dst",
+ .help = "set a new destination port number in the outermost"
+ " TCP/UDP header",
+ .priv = PRIV_ACTION(SET_TP_DST,
+ sizeof(struct rte_flow_action_set_tp)),
+ .next = NEXT(action_set_tp_dst),
+ .call = parse_vc,
+ },
+ [ACTION_SET_TP_DST_TP_DST] = {
+ .name = "port",
+ .help = "new destination port number to set",
+ .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_tp, port)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_MAC_SWAP] = {
+ .name = "mac_swap",
+ .help = "Swap the source and destination MAC addresses"
+ " in the outermost Ethernet header",
+ .priv = PRIV_ACTION(MAC_SWAP, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_DEC_TTL] = {
+ .name = "dec_ttl",
+ .help = "decrease network TTL if available",
+ .priv = PRIV_ACTION(DEC_TTL, 0),
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc,
+ },
+ [ACTION_SET_TTL] = {
+ .name = "set_ttl",
+ .help = "set ttl value",
+ .priv = PRIV_ACTION(SET_TTL,
+ sizeof(struct rte_flow_action_set_ttl)),
+ .next = NEXT(action_set_ttl),
+ .call = parse_vc,
+ },
+ [ACTION_SET_TTL_TTL] = {
+ .name = "ttl_value",
+ .help = "new ttl value to set",
+ .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_ttl, ttl_value)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_MAC_SRC] = {
+ .name = "set_mac_src",
+ .help = "set source mac address",
+ .priv = PRIV_ACTION(SET_MAC_SRC,
+ sizeof(struct rte_flow_action_set_mac)),
+ .next = NEXT(action_set_mac_src),
+ .call = parse_vc,
+ },
+ [ACTION_SET_MAC_SRC_MAC_SRC] = {
+ .name = "mac_addr",
+ .help = "new source mac address",
+ .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_mac, mac_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_MAC_DST] = {
+ .name = "set_mac_dst",
+ .help = "set destination mac address",
+ .priv = PRIV_ACTION(SET_MAC_DST,
+ sizeof(struct rte_flow_action_set_mac)),
+ .next = NEXT(action_set_mac_dst),
+ .call = parse_vc,
+ },
+ [ACTION_SET_MAC_DST_MAC_DST] = {
+ .name = "mac_addr",
+ .help = "new destination mac address to set",
+ .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
+ .args = ARGS(ARGS_ENTRY_HTON
+ (struct rte_flow_action_set_mac, mac_addr)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_INC_TCP_SEQ] = {
+ .name = "inc_tcp_seq",
+ .help = "increase TCP sequence number",
+ .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
+ .next = NEXT(action_inc_tcp_seq),
+ .call = parse_vc,
+ },
+ [ACTION_INC_TCP_SEQ_VALUE] = {
+ .name = "value",
+ .help = "the value to increase TCP sequence number by",
+ .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_DEC_TCP_SEQ] = {
+ .name = "dec_tcp_seq",
+ .help = "decrease TCP sequence number",
+ .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
+ .next = NEXT(action_dec_tcp_seq),
+ .call = parse_vc,
+ },
+ [ACTION_DEC_TCP_SEQ_VALUE] = {
+ .name = "value",
+ .help = "the value to decrease TCP sequence number by",
+ .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_INC_TCP_ACK] = {
+ .name = "inc_tcp_ack",
+ .help = "increase TCP acknowledgment number",
+ .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
+ .next = NEXT(action_inc_tcp_ack),
+ .call = parse_vc,
+ },
+ [ACTION_INC_TCP_ACK_VALUE] = {
+ .name = "value",
+ .help = "the value to increase TCP acknowledgment number by",
+ .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_DEC_TCP_ACK] = {
+ .name = "dec_tcp_ack",
+ .help = "decrease TCP acknowledgment number",
+ .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
+ .next = NEXT(action_dec_tcp_ack),
+ .call = parse_vc,
+ },
+ [ACTION_DEC_TCP_ACK_VALUE] = {
+ .name = "value",
+ .help = "the value to decrease TCP acknowledgment number by",
+ .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_RAW_ENCAP] = {
+ .name = "raw_encap",
+ .help = "encapsulation data, defined by set raw_encap",
+ .priv = PRIV_ACTION(RAW_ENCAP,
+ sizeof(struct action_raw_encap_data)),
+ .next = NEXT(action_raw_encap),
+ .call = parse_vc_action_raw_encap,
+ },
+ [ACTION_RAW_ENCAP_INDEX] = {
+ .name = "index",
+ .help = "the index of raw_encap_confs",
+ .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)),
+ },
+ [ACTION_RAW_ENCAP_INDEX_VALUE] = {
+ .name = "{index}",
+ .type = "UNSIGNED",
+ .help = "unsigned integer value",
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_raw_encap_index,
+ .comp = comp_set_raw_index,
+ },
+ [ACTION_RAW_DECAP] = {
+ .name = "raw_decap",
+ .help = "decapsulation data, defined by set raw_encap",
+ .priv = PRIV_ACTION(RAW_DECAP,
+ sizeof(struct action_raw_decap_data)),
+ .next = NEXT(action_raw_decap),
+ .call = parse_vc_action_raw_decap,
+ },
+ [ACTION_RAW_DECAP_INDEX] = {
+ .name = "index",
+ .help = "the index of raw_encap_confs",
+ .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)),
+ },
+ [ACTION_RAW_DECAP_INDEX_VALUE] = {
+ .name = "{index}",
+ .type = "UNSIGNED",
+ .help = "unsigned integer value",
+ .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+ .call = parse_vc_action_raw_decap_index,
+ .comp = comp_set_raw_index,
+ },
+ /* Top level command. */
+ [SET] = {
+ .name = "set",
+ .help = "set raw encap/decap data",
+ .type = "set raw_encap|raw_decap <index> <pattern>",
+ .next = NEXT(NEXT_ENTRY
+ (SET_RAW_ENCAP,
+ SET_RAW_DECAP)),
+ .call = parse_set_init,
+ },
+ /* Sub-level commands. */
+ [SET_RAW_ENCAP] = {
+ .name = "raw_encap",
+ .help = "set raw encap data",
+ .next = NEXT(next_set_raw),
+ .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct buffer, port),
+ sizeof(((struct buffer *)0)->port),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
+ .call = parse_set_raw_encap_decap,
+ },
+ [SET_RAW_DECAP] = {
+ .name = "raw_decap",
+ .help = "set raw decap data",
+ .next = NEXT(next_set_raw),
+ .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct buffer, port),
+ sizeof(((struct buffer *)0)->port),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1)),
+ .call = parse_set_raw_encap_decap,
+ },
+ [SET_RAW_INDEX] = {
+ .name = "{index}",
+ .type = "UNSIGNED",
+ .help = "index of raw_encap/raw_decap data",
+ .next = NEXT(next_item),
+ .call = parse_port,
+ },
+ [ACTION_SET_TAG] = {
+ .name = "set_tag",
+ .help = "set tag",
+ .priv = PRIV_ACTION(SET_TAG,
+ sizeof(struct rte_flow_action_set_tag)),
+ .next = NEXT(action_set_tag),
+ .call = parse_vc,
+ },
+ [ACTION_SET_TAG_INDEX] = {
+ .name = "index",
+ .help = "index of tag array",
+ .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_TAG_DATA] = {
+ .name = "data",
+ .help = "tag value",
+ .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_tag, data)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_TAG_MASK] = {
+ .name = "mask",
+ .help = "mask for tag value",
+ .next = NEXT(action_set_tag, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_tag, mask)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_META] = {
+ .name = "set_meta",
+ .help = "set metadata",
+ .priv = PRIV_ACTION(SET_META,
+ sizeof(struct rte_flow_action_set_meta)),
+ .next = NEXT(action_set_meta),
+ .call = parse_vc_action_set_meta,
+ },
+ [ACTION_SET_META_DATA] = {
+ .name = "data",
+ .help = "metadata value",
+ .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_meta, data)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_META_MASK] = {
+ .name = "mask",
+ .help = "mask for metadata value",
+ .next = NEXT(action_set_meta, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_meta, mask)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_IPV4_DSCP] = {
+ .name = "set_ipv4_dscp",
+ .help = "set DSCP value",
+ .priv = PRIV_ACTION(SET_IPV4_DSCP,
+ sizeof(struct rte_flow_action_set_dscp)),
+ .next = NEXT(action_set_ipv4_dscp),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV4_DSCP_VALUE] = {
+ .name = "dscp_value",
+ .help = "new IPv4 DSCP value to set",
+ .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_dscp, dscp)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_SET_IPV6_DSCP] = {
+ .name = "set_ipv6_dscp",
+ .help = "set DSCP value",
+ .priv = PRIV_ACTION(SET_IPV6_DSCP,
+ sizeof(struct rte_flow_action_set_dscp)),
+ .next = NEXT(action_set_ipv6_dscp),
+ .call = parse_vc,
+ },
+ [ACTION_SET_IPV6_DSCP_VALUE] = {
+ .name = "dscp_value",
+ .help = "new IPv6 DSCP value to set",
+ .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(UNSIGNED)),
+ .args = ARGS(ARGS_ENTRY
+ (struct rte_flow_action_set_dscp, dscp)),
+ .call = parse_vc_conf,
+ },
+ [ACTION_AGE] = {
+ .name = "age",
+ .help = "set a specific metadata header",
+ .next = NEXT(action_age),
+ .priv = PRIV_ACTION(AGE,
+ sizeof(struct rte_flow_action_age)),
+ .call = parse_vc,
+ },
+ [ACTION_AGE_TIMEOUT] = {
+ .name = "timeout",
+ .help = "flow age timeout value",
+ .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age,
+ timeout, 24)),
+ .next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
+ .call = parse_vc_conf,
+ },
+};
+
+/** Remove and return last entry from argument stack. */
+static const struct arg *
+pop_args(struct context *ctx)
+{
+ return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
+}
+
+/** Add entry on top of the argument stack. */
+static int
+push_args(struct context *ctx, const struct arg *arg)
+{
+ if (ctx->args_num == CTX_STACK_SIZE)
+ return -1;
+ ctx->args[ctx->args_num++] = arg;
+ return 0;
+}
+
+/** Spread value into buffer according to bit-mask. */
+static size_t
+arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
+{
+ uint32_t i = arg->size;
+ uint32_t end = 0;
+ int sub = 1;
+ int add = 0;
+ size_t len = 0;
+
+ if (!arg->mask)
+ return 0;
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ i = 0;
+ end = arg->size;
+ sub = 0;
+ add = 1;
+ }
+#endif
+ while (i != end) {
+ unsigned int shift = 0;
+ uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
+
+ for (shift = 0; arg->mask[i] >> shift; ++shift) {
+ if (!(arg->mask[i] & (1 << shift)))
+ continue;
+ ++len;
+ if (!dst)
+ continue;
+ *buf &= ~(1 << shift);
+ *buf |= (val & 1) << shift;
+ val >>= 1;
+ }
+ i += add;
+ }
+ return len;
+}
+
+/** Compare a string with a partial one of a given length. */
+static int
+strcmp_partial(const char *full, const char *partial, size_t partial_len)
+{
+ int r = strncmp(full, partial, partial_len);
+
+ if (r)
+ return r;
+ if (strlen(full) <= partial_len)
+ return 0;
+ return full[partial_len];
+}
+
+/**
+ * Parse a prefix length and generate a bit-mask.
+ *
+ * Last argument (ctx->args) is retrieved to determine mask size, storage
+ * location and whether the result must use network byte ordering.
+ */
+static int
+parse_prefix(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
+ char *end;
+ uintmax_t u;
+ unsigned int bytes;
+ unsigned int extra;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ errno = 0;
+ u = strtoumax(str, &end, 0);
+ if (errno || (size_t)(end - str) != len)
+ goto error;
+ if (arg->mask) {
+ uintmax_t v = 0;
+
+ extra = arg_entry_bf_fill(NULL, 0, arg);
+ if (u > extra)
+ goto error;
+ if (!ctx->object)
+ return len;
+ extra -= u;
+ while (u--)
+ (v <<= 1, v |= 1);
+ v <<= extra;
+ if (!arg_entry_bf_fill(ctx->object, v, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
+ bytes = u / 8;
+ extra = u % 8;
+ size = arg->size;
+ if (bytes > size || bytes + !!extra > size)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ memset((uint8_t *)buf + size - bytes, 0xff, bytes);
+ memset(buf, 0x00, size - bytes);
+ if (extra)
+ ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
+ } else
+#endif
+ {
+ memset(buf, 0xff, bytes);
+ memset((uint8_t *)buf + bytes, 0x00, size - bytes);
+ if (extra)
+ ((uint8_t *)buf)[bytes] = conv[extra];
+ }
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Default parsing function for token name matching. */
+static int
+parse_default(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ (void)ctx;
+ (void)buf;
+ (void)size;
+ if (strcmp_partial(token->name, str, len))
+ return -1;
+ return len;
+}
+
+/** Parse flow command, initialize output buffer for subsequent tokens. */
+static int
+parse_init(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Make sure buffer is large enough. */
+ if (size < sizeof(*out))
+ return -1;
+ /* Initialize buffer. */
+ memset(out, 0x00, sizeof(*out));
+ memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for validate/create commands. */
+static int
+parse_vc(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint8_t *data;
+ uint32_t data_size;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != VALIDATE && ctx->curr != CREATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.vc.data = (uint8_t *)out + size;
+ return len;
+ }
+ ctx->objdata = 0;
+ ctx->object = &out->args.vc.attr;
+ ctx->objmask = NULL;
+ switch (ctx->curr) {
+ case GROUP:
+ case PRIORITY:
+ return len;
+ case INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case PATTERN:
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.pattern;
+ ctx->objmask = NULL;
+ return len;
+ case ACTIONS:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)
+ (out->args.vc.pattern +
+ out->args.vc.pattern_n),
+ sizeof(double));
+ ctx->object = out->args.vc.actions;
+ ctx->objmask = NULL;
+ return len;
+ default:
+ if (!token->priv)
+ return -1;
+ break;
+ }
+ if (!out->args.vc.actions) {
+ const struct parse_item_priv *priv = token->priv;
+ struct rte_flow_item *item =
+ out->args.vc.pattern + out->args.vc.pattern_n;
+
+ data_size = priv->size * 3; /* spec, last, mask */
+ data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
+ (out->args.vc.data - data_size),
+ sizeof(double));
+ if ((uint8_t *)item + sizeof(*item) > data)
+ return -1;
+ *item = (struct rte_flow_item){
+ .type = priv->type,
+ };
+ ++out->args.vc.pattern_n;
+ ctx->object = item;
+ ctx->objmask = NULL;
+ } else {
+ const struct parse_action_priv *priv = token->priv;
+ struct rte_flow_action *action =
+ out->args.vc.actions + out->args.vc.actions_n;
+
+ data_size = priv->size; /* configuration */
+ data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
+ (out->args.vc.data - data_size),
+ sizeof(double));
+ if ((uint8_t *)action + sizeof(*action) > data)
+ return -1;
+ *action = (struct rte_flow_action){
+ .type = priv->type,
+ .conf = data_size ? data : NULL,
+ };
+ ++out->args.vc.actions_n;
+ ctx->object = action;
+ ctx->objmask = NULL;
+ }
+ memset(data, 0, data_size);
+ out->args.vc.data = data;
+ ctx->objdata = data_size;
+ return len;
+}
+
+/** Parse pattern item parameter type. */
+static int
+parse_vc_spec(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_item *item;
+ uint32_t data_size;
+ int index;
+ int objmask = 0;
+
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Parse parameter types. */
+ switch (ctx->curr) {
+ static const enum index prefix[] = NEXT_ENTRY(PREFIX);
+
+ case ITEM_PARAM_IS:
+ index = 0;
+ objmask = 1;
+ break;
+ case ITEM_PARAM_SPEC:
+ index = 0;
+ break;
+ case ITEM_PARAM_LAST:
+ index = 1;
+ break;
+ case ITEM_PARAM_PREFIX:
+ /* Modify next token to expect a prefix. */
+ if (ctx->next_num < 2)
+ return -1;
+ ctx->next[ctx->next_num - 2] = prefix;
+ /* Fall through. */
+ case ITEM_PARAM_MASK:
+ index = 2;
+ break;
+ default:
+ return -1;
+ }
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->args.vc.pattern_n)
+ return -1;
+ item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
+ data_size = ctx->objdata / 3; /* spec, last, mask */
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data + (data_size * index);
+ if (objmask) {
+ ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
+ item->mask = ctx->objmask;
+ } else
+ ctx->objmask = NULL;
+ /* Update relevant item pointer. */
+ *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
+ ctx->object;
+ return len;
+}
+
+/** Parse action configuration field. */
+static int
+parse_vc_conf(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse RSS action. */
+static int
+parse_vc_action_rss(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_rss_data *action_rss_data;
+ unsigned int i;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Set up default configuration. */
+ action_rss_data = ctx->object;
+ *action_rss_data = (struct action_rss_data){
+ .conf = (struct rte_flow_action_rss){
+ .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
+ .level = 0,
+ .types = rss_hf,
+ .key_len = sizeof(action_rss_data->key),
+ .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
+ .key = action_rss_data->key,
+ .queue = action_rss_data->queue,
+ },
+ .key = "testpmd's default RSS hash key, "
+ "override it for better balancing",
+ .queue = { 0 },
+ };
+ for (i = 0; i < action_rss_data->conf.queue_num; ++i)
+ action_rss_data->queue[i] = i;
+ if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
+ ctx->port != (portid_t)RTE_PORT_ALL) {
+ struct rte_eth_dev_info info;
+ int ret2;
+
+ ret2 = rte_eth_dev_info_get(ctx->port, &info);
+ if (ret2 != 0)
+ return ret2;
+
+ action_rss_data->conf.key_len =
+ RTE_MIN(sizeof(action_rss_data->key),
+ info.hash_key_size);
+ }
+ action->conf = &action_rss_data->conf;
+ return ret;
+}
+
+/**
+ * Parse func field for RSS action.
+ *
+ * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
+ * ACTION_RSS_FUNC_* index that called this function.
+ */
+static int
+parse_vc_action_rss_func(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct action_rss_data *action_rss_data;
+ enum rte_eth_hash_function func;
+
+ (void)buf;
+ (void)size;
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ switch (ctx->curr) {
+ case ACTION_RSS_FUNC_DEFAULT:
+ func = RTE_ETH_HASH_FUNCTION_DEFAULT;
+ break;
+ case ACTION_RSS_FUNC_TOEPLITZ:
+ func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+ break;
+ case ACTION_RSS_FUNC_SIMPLE_XOR:
+ func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+ break;
+ case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ:
+ func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
+ break;
+ default:
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action_rss_data = ctx->object;
+ action_rss_data->conf.func = func;
+ return len;
+}
+
+/**
+ * Parse type field for RSS action.
+ *
+ * Valid tokens are type field names and the "end" token.
+ */
+static int
+parse_vc_action_rss_type(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
+ struct action_rss_data *action_rss_data;
+ unsigned int i;
+
+ (void)token;
+ (void)buf;
+ (void)size;
+ if (ctx->curr != ACTION_RSS_TYPE)
+ return -1;
+ if (!(ctx->objdata >> 16) && ctx->object) {
+ action_rss_data = ctx->object;
+ action_rss_data->conf.types = 0;
+ }
+ if (!strcmp_partial("end", str, len)) {
+ ctx->objdata &= 0xffff;
+ return len;
+ }
+ for (i = 0; rss_type_table[i].str; ++i)
+ if (!strcmp_partial(rss_type_table[i].str, str, len))
+ break;
+ if (!rss_type_table[i].str)
+ return -1;
+ ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
+ /* Repeat token. */
+ if (ctx->next_num == RTE_DIM(ctx->next))
+ return -1;
+ ctx->next[ctx->next_num++] = next;
+ if (!ctx->object)
+ return len;
+ action_rss_data = ctx->object;
+ action_rss_data->conf.types |= rss_type_table[i].rss_type;
+ return len;
+}
+
+/**
+ * Parse queue field for RSS action.
+ *
+ * Valid tokens are queue indices and the "end" token.
+ */
+static int
+parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
+ struct action_rss_data *action_rss_data;
+ const struct arg *arg;
+ int ret;
+ int i;
+
+ (void)token;
+ (void)buf;
+ (void)size;
+ if (ctx->curr != ACTION_RSS_QUEUE)
+ return -1;
+ i = ctx->objdata >> 16;
+ if (!strcmp_partial("end", str, len)) {
+ ctx->objdata &= 0xffff;
+ goto end;
+ }
+ if (i >= ACTION_RSS_QUEUE_NUM)
+ return -1;
+ arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
+ i * sizeof(action_rss_data->queue[i]),
+ sizeof(action_rss_data->queue[i]));
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ ++i;
+ ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
+ /* Repeat token. */
+ if (ctx->next_num == RTE_DIM(ctx->next))
+ return -1;
+ ctx->next[ctx->next_num++] = next;
+end:
+ if (!ctx->object)
+ return len;
+ action_rss_data = ctx->object;
+ action_rss_data->conf.queue_num = i;
+ action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
+ return len;
+}
+
+/** Parse VXLAN encap action. */
+static int
+parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_vxlan_encap_data *action_vxlan_encap_data;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Set up default configuration. */
+ action_vxlan_encap_data = ctx->object;
+ *action_vxlan_encap_data = (struct action_vxlan_encap_data){
+ .conf = (struct rte_flow_action_vxlan_encap){
+ .definition = action_vxlan_encap_data->items,
+ },
+ .items = {
+ {
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .spec = &action_vxlan_encap_data->item_eth,
+ .mask = &rte_flow_item_eth_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_VLAN,
+ .spec = &action_vxlan_encap_data->item_vlan,
+ .mask = &rte_flow_item_vlan_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_IPV4,
+ .spec = &action_vxlan_encap_data->item_ipv4,
+ .mask = &rte_flow_item_ipv4_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_UDP,
+ .spec = &action_vxlan_encap_data->item_udp,
+ .mask = &rte_flow_item_udp_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_VXLAN,
+ .spec = &action_vxlan_encap_data->item_vxlan,
+ .mask = &rte_flow_item_vxlan_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_END,
+ },
+ },
+ .item_eth.type = 0,
+ .item_vlan = {
+ .tci = vxlan_encap_conf.vlan_tci,
+ .inner_type = 0,
+ },
+ .item_ipv4.hdr = {
+ .src_addr = vxlan_encap_conf.ipv4_src,
+ .dst_addr = vxlan_encap_conf.ipv4_dst,
+ },
+ .item_udp.hdr = {
+ .src_port = vxlan_encap_conf.udp_src,
+ .dst_port = vxlan_encap_conf.udp_dst,
+ },
+ .item_vxlan.flags = 0,
+ };
+ memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
+ vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
+ vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ if (!vxlan_encap_conf.select_ipv4) {
+ memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
+ &vxlan_encap_conf.ipv6_src,
+ sizeof(vxlan_encap_conf.ipv6_src));
+ memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
+ &vxlan_encap_conf.ipv6_dst,
+ sizeof(vxlan_encap_conf.ipv6_dst));
+ action_vxlan_encap_data->items[2] = (struct rte_flow_item){
+ .type = RTE_FLOW_ITEM_TYPE_IPV6,
+ .spec = &action_vxlan_encap_data->item_ipv6,
+ .mask = &rte_flow_item_ipv6_mask,
+ };
+ }
+ if (!vxlan_encap_conf.select_vlan)
+ action_vxlan_encap_data->items[1].type =
+ RTE_FLOW_ITEM_TYPE_VOID;
+ if (vxlan_encap_conf.select_tos_ttl) {
+ if (vxlan_encap_conf.select_ipv4) {
+ static struct rte_flow_item_ipv4 ipv4_mask_tos;
+
+ memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask,
+ sizeof(ipv4_mask_tos));
+ ipv4_mask_tos.hdr.type_of_service = 0xff;
+ ipv4_mask_tos.hdr.time_to_live = 0xff;
+ action_vxlan_encap_data->item_ipv4.hdr.type_of_service =
+ vxlan_encap_conf.ip_tos;
+ action_vxlan_encap_data->item_ipv4.hdr.time_to_live =
+ vxlan_encap_conf.ip_ttl;
+ action_vxlan_encap_data->items[2].mask =
+ &ipv4_mask_tos;
+ } else {
+ static struct rte_flow_item_ipv6 ipv6_mask_tos;
+
+ memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask,
+ sizeof(ipv6_mask_tos));
+ ipv6_mask_tos.hdr.vtc_flow |=
+ RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT);
+ ipv6_mask_tos.hdr.hop_limits = 0xff;
+ action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |=
+ rte_cpu_to_be_32
+ ((uint32_t)vxlan_encap_conf.ip_tos <<
+ RTE_IPV6_HDR_TC_SHIFT);
+ action_vxlan_encap_data->item_ipv6.hdr.hop_limits =
+ vxlan_encap_conf.ip_ttl;
+ action_vxlan_encap_data->items[2].mask =
+ &ipv6_mask_tos;
+ }
+ }
+ memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
+ RTE_DIM(vxlan_encap_conf.vni));
+ action->conf = &action_vxlan_encap_data->conf;
+ return ret;
+}
+
+/** Parse NVGRE encap action. */
+static int
+parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_nvgre_encap_data *action_nvgre_encap_data;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Set up default configuration. */
+ action_nvgre_encap_data = ctx->object;
+ *action_nvgre_encap_data = (struct action_nvgre_encap_data){
+ .conf = (struct rte_flow_action_nvgre_encap){
+ .definition = action_nvgre_encap_data->items,
+ },
+ .items = {
+ {
+ .type = RTE_FLOW_ITEM_TYPE_ETH,
+ .spec = &action_nvgre_encap_data->item_eth,
+ .mask = &rte_flow_item_eth_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_VLAN,
+ .spec = &action_nvgre_encap_data->item_vlan,
+ .mask = &rte_flow_item_vlan_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_IPV4,
+ .spec = &action_nvgre_encap_data->item_ipv4,
+ .mask = &rte_flow_item_ipv4_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_NVGRE,
+ .spec = &action_nvgre_encap_data->item_nvgre,
+ .mask = &rte_flow_item_nvgre_mask,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_END,
+ },
+ },
+ .item_eth.type = 0,
+ .item_vlan = {
+ .tci = nvgre_encap_conf.vlan_tci,
+ .inner_type = 0,
+ },
+ .item_ipv4.hdr = {
+ .src_addr = nvgre_encap_conf.ipv4_src,
+ .dst_addr = nvgre_encap_conf.ipv4_dst,
+ },
+ .item_nvgre.flow_id = 0,
+ };
+ memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
+ nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
+ nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ if (!nvgre_encap_conf.select_ipv4) {
+ memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
+ &nvgre_encap_conf.ipv6_src,
+ sizeof(nvgre_encap_conf.ipv6_src));
+ memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
+ &nvgre_encap_conf.ipv6_dst,
+ sizeof(nvgre_encap_conf.ipv6_dst));
+ action_nvgre_encap_data->items[2] = (struct rte_flow_item){
+ .type = RTE_FLOW_ITEM_TYPE_IPV6,
+ .spec = &action_nvgre_encap_data->item_ipv6,
+ .mask = &rte_flow_item_ipv6_mask,
+ };
+ }
+ if (!nvgre_encap_conf.select_vlan)
+ action_nvgre_encap_data->items[1].type =
+ RTE_FLOW_ITEM_TYPE_VOID;
+ memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
+ RTE_DIM(nvgre_encap_conf.tni));
+ action->conf = &action_nvgre_encap_data->conf;
+ return ret;
+}
+
+/** Parse l2 encap action. */
+static int
+parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_encap_data *action_encap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {
+ .tci = mplsoudp_encap_conf.vlan_tci,
+ .inner_type = 0,
+ };
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_encap_data = ctx->object;
+ *action_encap_data = (struct action_raw_encap_data) {
+ .conf = (struct rte_flow_action_raw_encap){
+ .data = action_encap_data->data,
+ },
+ .data = {},
+ };
+ header = action_encap_data->data;
+ if (l2_encap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ else if (l2_encap_conf.select_ipv4)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(eth.dst.addr_bytes,
+ l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(eth.src.addr_bytes,
+ l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (l2_encap_conf.select_vlan) {
+ if (l2_encap_conf.select_ipv4)
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ action_encap_data->conf.size = header -
+ action_encap_data->data;
+ action->conf = &action_encap_data->conf;
+ return ret;
+}
+
+/** Parse l2 decap action. */
+static int
+parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_decap_data *action_decap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {
+ .tci = mplsoudp_encap_conf.vlan_tci,
+ .inner_type = 0,
+ };
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_decap_data = ctx->object;
+ *action_decap_data = (struct action_raw_decap_data) {
+ .conf = (struct rte_flow_action_raw_decap){
+ .data = action_decap_data->data,
+ },
+ .data = {},
+ };
+ header = action_decap_data->data;
+ if (l2_decap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (l2_decap_conf.select_vlan) {
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ action_decap_data->conf.size = header -
+ action_decap_data->data;
+ action->conf = &action_decap_data->conf;
+ return ret;
+}
+
+#define ETHER_TYPE_MPLS_UNICAST 0x8847
+
+/** Parse MPLSOGRE encap action. */
+static int
+parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_encap_data *action_encap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {
+ .tci = mplsogre_encap_conf.vlan_tci,
+ .inner_type = 0,
+ };
+ struct rte_flow_item_ipv4 ipv4 = {
+ .hdr = {
+ .src_addr = mplsogre_encap_conf.ipv4_src,
+ .dst_addr = mplsogre_encap_conf.ipv4_dst,
+ .next_proto_id = IPPROTO_GRE,
+ .version_ihl = RTE_IPV4_VHL_DEF,
+ .time_to_live = IPDEFTTL,
+ },
+ };
+ struct rte_flow_item_ipv6 ipv6 = {
+ .hdr = {
+ .proto = IPPROTO_GRE,
+ .hop_limits = IPDEFTTL,
+ },
+ };
+ struct rte_flow_item_gre gre = {
+ .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
+ };
+ struct rte_flow_item_mpls mpls = {
+ .ttl = 0,
+ };
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_encap_data = ctx->object;
+ *action_encap_data = (struct action_raw_encap_data) {
+ .conf = (struct rte_flow_action_raw_encap){
+ .data = action_encap_data->data,
+ },
+ .data = {},
+ .preserve = {},
+ };
+ header = action_encap_data->data;
+ if (mplsogre_encap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ else if (mplsogre_encap_conf.select_ipv4)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(eth.dst.addr_bytes,
+ mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(eth.src.addr_bytes,
+ mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (mplsogre_encap_conf.select_vlan) {
+ if (mplsogre_encap_conf.select_ipv4)
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ if (mplsogre_encap_conf.select_ipv4) {
+ memcpy(header, &ipv4, sizeof(ipv4));
+ header += sizeof(ipv4);
+ } else {
+ memcpy(&ipv6.hdr.src_addr,
+ &mplsogre_encap_conf.ipv6_src,
+ sizeof(mplsogre_encap_conf.ipv6_src));
+ memcpy(&ipv6.hdr.dst_addr,
+ &mplsogre_encap_conf.ipv6_dst,
+ sizeof(mplsogre_encap_conf.ipv6_dst));
+ memcpy(header, &ipv6, sizeof(ipv6));
+ header += sizeof(ipv6);
+ }
+ memcpy(header, &gre, sizeof(gre));
+ header += sizeof(gre);
+ memcpy(mpls.label_tc_s, mplsogre_encap_conf.label,
+ RTE_DIM(mplsogre_encap_conf.label));
+ mpls.label_tc_s[2] |= 0x1;
+ memcpy(header, &mpls, sizeof(mpls));
+ header += sizeof(mpls);
+ action_encap_data->conf.size = header -
+ action_encap_data->data;
+ action->conf = &action_encap_data->conf;
+ return ret;
+}
+
+/** Parse MPLSOGRE decap action. */
+static int
+parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_decap_data *action_decap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {.tci = 0};
+ struct rte_flow_item_ipv4 ipv4 = {
+ .hdr = {
+ .next_proto_id = IPPROTO_GRE,
+ },
+ };
+ struct rte_flow_item_ipv6 ipv6 = {
+ .hdr = {
+ .proto = IPPROTO_GRE,
+ },
+ };
+ struct rte_flow_item_gre gre = {
+ .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
+ };
+ struct rte_flow_item_mpls mpls;
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_decap_data = ctx->object;
+ *action_decap_data = (struct action_raw_decap_data) {
+ .conf = (struct rte_flow_action_raw_decap){
+ .data = action_decap_data->data,
+ },
+ .data = {},
+ };
+ header = action_decap_data->data;
+ if (mplsogre_decap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ else if (mplsogre_encap_conf.select_ipv4)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(eth.dst.addr_bytes,
+ mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(eth.src.addr_bytes,
+ mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (mplsogre_encap_conf.select_vlan) {
+ if (mplsogre_encap_conf.select_ipv4)
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ if (mplsogre_encap_conf.select_ipv4) {
+ memcpy(header, &ipv4, sizeof(ipv4));
+ header += sizeof(ipv4);
+ } else {
+ memcpy(header, &ipv6, sizeof(ipv6));
+ header += sizeof(ipv6);
+ }
+ memcpy(header, &gre, sizeof(gre));
+ header += sizeof(gre);
+ memset(&mpls, 0, sizeof(mpls));
+ memcpy(header, &mpls, sizeof(mpls));
+ header += sizeof(mpls);
+ action_decap_data->conf.size = header -
+ action_decap_data->data;
+ action->conf = &action_decap_data->conf;
+ return ret;
+}
+
+/** Parse MPLSOUDP encap action. */
+static int
+parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_encap_data *action_encap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {
+ .tci = mplsoudp_encap_conf.vlan_tci,
+ .inner_type = 0,
+ };
+ struct rte_flow_item_ipv4 ipv4 = {
+ .hdr = {
+ .src_addr = mplsoudp_encap_conf.ipv4_src,
+ .dst_addr = mplsoudp_encap_conf.ipv4_dst,
+ .next_proto_id = IPPROTO_UDP,
+ .version_ihl = RTE_IPV4_VHL_DEF,
+ .time_to_live = IPDEFTTL,
+ },
+ };
+ struct rte_flow_item_ipv6 ipv6 = {
+ .hdr = {
+ .proto = IPPROTO_UDP,
+ .hop_limits = IPDEFTTL,
+ },
+ };
+ struct rte_flow_item_udp udp = {
+ .hdr = {
+ .src_port = mplsoudp_encap_conf.udp_src,
+ .dst_port = mplsoudp_encap_conf.udp_dst,
+ },
+ };
+ struct rte_flow_item_mpls mpls;
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_encap_data = ctx->object;
+ *action_encap_data = (struct action_raw_encap_data) {
+ .conf = (struct rte_flow_action_raw_encap){
+ .data = action_encap_data->data,
+ },
+ .data = {},
+ .preserve = {},
+ };
+ header = action_encap_data->data;
+ if (mplsoudp_encap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ else if (mplsoudp_encap_conf.select_ipv4)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(eth.dst.addr_bytes,
+ mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(eth.src.addr_bytes,
+ mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (mplsoudp_encap_conf.select_vlan) {
+ if (mplsoudp_encap_conf.select_ipv4)
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ if (mplsoudp_encap_conf.select_ipv4) {
+ memcpy(header, &ipv4, sizeof(ipv4));
+ header += sizeof(ipv4);
+ } else {
+ memcpy(&ipv6.hdr.src_addr,
+ &mplsoudp_encap_conf.ipv6_src,
+ sizeof(mplsoudp_encap_conf.ipv6_src));
+ memcpy(&ipv6.hdr.dst_addr,
+ &mplsoudp_encap_conf.ipv6_dst,
+ sizeof(mplsoudp_encap_conf.ipv6_dst));
+ memcpy(header, &ipv6, sizeof(ipv6));
+ header += sizeof(ipv6);
+ }
+ memcpy(header, &udp, sizeof(udp));
+ header += sizeof(udp);
+ memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
+ RTE_DIM(mplsoudp_encap_conf.label));
+ mpls.label_tc_s[2] |= 0x1;
+ memcpy(header, &mpls, sizeof(mpls));
+ header += sizeof(mpls);
+ action_encap_data->conf.size = header -
+ action_encap_data->data;
+ action->conf = &action_encap_data->conf;
+ return ret;
+}
+
+/** Parse MPLSOUDP decap action. */
+static int
+parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_decap_data *action_decap_data;
+ struct rte_flow_item_eth eth = { .type = 0, };
+ struct rte_flow_item_vlan vlan = {.tci = 0};
+ struct rte_flow_item_ipv4 ipv4 = {
+ .hdr = {
+ .next_proto_id = IPPROTO_UDP,
+ },
+ };
+ struct rte_flow_item_ipv6 ipv6 = {
+ .hdr = {
+ .proto = IPPROTO_UDP,
+ },
+ };
+ struct rte_flow_item_udp udp = {
+ .hdr = {
+ .dst_port = rte_cpu_to_be_16(6635),
+ },
+ };
+ struct rte_flow_item_mpls mpls;
+ uint8_t *header;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_decap_data = ctx->object;
+ *action_decap_data = (struct action_raw_decap_data) {
+ .conf = (struct rte_flow_action_raw_decap){
+ .data = action_decap_data->data,
+ },
+ .data = {},
+ };
+ header = action_decap_data->data;
+ if (mplsoudp_decap_conf.select_vlan)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ else if (mplsoudp_encap_conf.select_ipv4)
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(eth.dst.addr_bytes,
+ mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN);
+ memcpy(eth.src.addr_bytes,
+ mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN);
+ memcpy(header, &eth, sizeof(eth));
+ header += sizeof(eth);
+ if (mplsoudp_encap_conf.select_vlan) {
+ if (mplsoudp_encap_conf.select_ipv4)
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ else
+ vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
+ memcpy(header, &vlan, sizeof(vlan));
+ header += sizeof(vlan);
+ }
+ if (mplsoudp_encap_conf.select_ipv4) {
+ memcpy(header, &ipv4, sizeof(ipv4));
+ header += sizeof(ipv4);
+ } else {
+ memcpy(header, &ipv6, sizeof(ipv6));
+ header += sizeof(ipv6);
+ }
+ memcpy(header, &udp, sizeof(udp));
+ header += sizeof(udp);
+ memset(&mpls, 0, sizeof(mpls));
+ memcpy(header, &mpls, sizeof(mpls));
+ header += sizeof(mpls);
+ action_decap_data->conf.size = header -
+ action_decap_data->data;
+ action->conf = &action_decap_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_raw_decap_data *action_raw_decap_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_raw_decap_data, idx),
+ sizeof(((struct action_raw_decap_data *)0)->idx),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_raw_decap_data = ctx->object;
+ idx = action_raw_decap_data->idx;
+ action_raw_decap_data->conf.data = raw_decap_confs[idx].data;
+ action_raw_decap_data->conf.size = raw_decap_confs[idx].size;
+ action->conf = &action_raw_decap_data->conf;
+ return len;
+}
+
+
+static int
+parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct action_raw_encap_data *action_raw_encap_data;
+ struct rte_flow_action *action;
+ const struct arg *arg;
+ struct buffer *out = buf;
+ int ret;
+ uint16_t idx;
+
+ RTE_SET_USED(token);
+ RTE_SET_USED(buf);
+ RTE_SET_USED(size);
+ if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE)
+ return -1;
+ arg = ARGS_ENTRY_ARB_BOUNDED
+ (offsetof(struct action_raw_encap_data, idx),
+ sizeof(((struct action_raw_encap_data *)0)->idx),
+ 0, RAW_ENCAP_CONFS_MAX_NUM - 1);
+ if (push_args(ctx, arg))
+ return -1;
+ ret = parse_int(ctx, token, str, len, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ return -1;
+ }
+ if (!ctx->object)
+ return len;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ action_raw_encap_data = ctx->object;
+ idx = action_raw_encap_data->idx;
+ action_raw_encap_data->conf.data = raw_encap_confs[idx].data;
+ action_raw_encap_data->conf.size = raw_encap_confs[idx].size;
+ action_raw_encap_data->conf.preserve = NULL;
+ action->conf = &action_raw_encap_data->conf;
+ return len;
+}
+
+static int
+parse_vc_action_raw_encap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_encap_data *action_raw_encap_data = NULL;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_raw_encap_data = ctx->object;
+ action_raw_encap_data->conf.data = raw_encap_confs[0].data;
+ action_raw_encap_data->conf.preserve = NULL;
+ action_raw_encap_data->conf.size = raw_encap_confs[0].size;
+ action->conf = &action_raw_encap_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_raw_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ struct buffer *out = buf;
+ struct rte_flow_action *action;
+ struct action_raw_decap_data *action_raw_decap_data = NULL;
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return ret;
+ if (!out->args.vc.actions_n)
+ return -1;
+ action = &out->args.vc.actions[out->args.vc.actions_n - 1];
+ /* Point to selected object. */
+ ctx->object = out->args.vc.data;
+ ctx->objmask = NULL;
+ /* Copy the headers to the buffer. */
+ action_raw_decap_data = ctx->object;
+ action_raw_decap_data->conf.data = raw_decap_confs[0].data;
+ action_raw_decap_data->conf.size = raw_decap_confs[0].size;
+ action->conf = &action_raw_decap_data->conf;
+ return ret;
+}
+
+static int
+parse_vc_action_set_meta(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len, void *buf,
+ unsigned int size)
+{
+ int ret;
+
+ ret = parse_vc(ctx, token, str, len, buf, size);
+ if (ret < 0)
+ return ret;
+ ret = rte_flow_dynf_metadata_register();
+ if (ret < 0)
+ return -1;
+ return len;
+}
+
+/** Parse tokens for destroy command. */
+static int
+parse_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.destroy.rule =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
+ sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for flush command. */
+static int
+parse_flush(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != FLUSH)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for dump command. */
+static int
+parse_dump(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != DUMP)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse tokens for query command. */
+static int
+parse_query(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != QUERY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/** Parse action names. */
+static int
+parse_action(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+
+ (void)size;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ /* Parse action name. */
+ for (i = 0; next_action[i]; ++i) {
+ const struct parse_action_priv *priv;
+
+ token = &token_list[next_action[i]];
+ if (strcmp_partial(token->name, str, len))
+ continue;
+ priv = token->priv;
+ if (!priv)
+ goto error;
+ if (out)
+ memcpy((uint8_t *)ctx->object + arg->offset,
+ &priv->type,
+ arg->size);
+ return len;
+ }
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Parse tokens for list command. */
+static int
+parse_list(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != LIST)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.list.group =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
+ sizeof(*out->args.list.group)) > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = out->args.list.group + out->args.list.group_n++;
+ ctx->objmask = NULL;
+ return len;
+}
+
+/** Parse tokens for list all aged flows command. */
+static int
+parse_aged(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != AGED)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ if (ctx->curr == AGED_DESTROY)
+ out->args.aged.destroy = 1;
+ return len;
+}
+
+/** Parse tokens for isolate command. */
+static int
+parse_isolate(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != ISOLATE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ }
+ return len;
+}
+
+/**
+ * Parse signed/unsigned integers 8 to 64-bit long.
+ *
+ * Last argument (ctx->args) is retrieved to determine integer type and
+ * storage location.
+ */
+static int
+parse_int(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ uintmax_t u;
+ char *end;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ errno = 0;
+ u = arg->sign ?
+ (uintmax_t)strtoimax(str, &end, 0) :
+ strtoumax(str, &end, 0);
+ if (errno || (size_t)(end - str) != len)
+ goto error;
+ if (arg->bounded &&
+ ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
+ (intmax_t)u > (intmax_t)arg->max)) ||
+ (!arg->sign && (u < arg->min || u > arg->max))))
+ goto error;
+ if (!ctx->object)
+ return len;
+ if (arg->mask) {
+ if (!arg_entry_bf_fill(ctx->object, u, arg) ||
+ !arg_entry_bf_fill(ctx->objmask, -1, arg))
+ goto error;
+ return len;
+ }
+ buf = (uint8_t *)ctx->object + arg->offset;
+ size = arg->size;
+ if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t))
+ return -1;
+objmask:
+ switch (size) {
+ case sizeof(uint8_t):
+ *(uint8_t *)buf = u;
+ break;
+ case sizeof(uint16_t):
+ *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
+ break;
+ case sizeof(uint8_t [3]):
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ if (!arg->hton) {
+ ((uint8_t *)buf)[0] = u;
+ ((uint8_t *)buf)[1] = u >> 8;
+ ((uint8_t *)buf)[2] = u >> 16;
+ break;
+ }
+#endif
+ ((uint8_t *)buf)[0] = u >> 16;
+ ((uint8_t *)buf)[1] = u >> 8;
+ ((uint8_t *)buf)[2] = u;
+ break;
+ case sizeof(uint32_t):
+ *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
+ break;
+ case sizeof(uint64_t):
+ *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
+ break;
+ default:
+ goto error;
+ }
+ if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
+ u = -1;
+ buf = (uint8_t *)ctx->objmask + arg->offset;
+ goto objmask;
+ }
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse a string.
+ *
+ * Three arguments (ctx->args) are retrieved from the stack to store data,
+ * its actual length and address (in that order).
+ */
+static int
+parse_string(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg_data = pop_args(ctx);
+ const struct arg *arg_len = pop_args(ctx);
+ const struct arg *arg_addr = pop_args(ctx);
+ char tmp[16]; /* Ought to be enough. */
+ int ret;
+
+ /* Arguments are expected. */
+ if (!arg_data)
+ return -1;
+ if (!arg_len) {
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ if (!arg_addr) {
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ size = arg_data->size;
+ /* Bit-mask fill is not supported. */
+ if (arg_data->mask || size < len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ /* Let parse_int() fill length information first. */
+ ret = snprintf(tmp, sizeof(tmp), "%u", len);
+ if (ret < 0)
+ goto error;
+ push_args(ctx, arg_len);
+ ret = parse_int(ctx, token, tmp, ret, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ goto error;
+ }
+ buf = (uint8_t *)ctx->object + arg_data->offset;
+ /* Output buffer is not necessarily NUL-terminated. */
+ memcpy(buf, str, len);
+ memset((uint8_t *)buf + len, 0x00, size - len);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
+ /* Save address if requested. */
+ if (arg_addr->size) {
+ memcpy((uint8_t *)ctx->object + arg_addr->offset,
+ (void *[]){
+ (uint8_t *)ctx->object + arg_data->offset
+ },
+ arg_addr->size);
+ if (ctx->objmask)
+ memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
+ (void *[]){
+ (uint8_t *)ctx->objmask + arg_data->offset
+ },
+ arg_addr->size);
+ }
+ return len;
+error:
+ push_args(ctx, arg_addr);
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+}
+
+static int
+parse_hex_string(const char *src, uint8_t *dst, uint32_t *size)
+{
+ char *c = NULL;
+ uint32_t i, len;
+ char tmp[3];
+
+ /* Check input parameters */
+ if ((src == NULL) ||
+ (dst == NULL) ||
+ (size == NULL) ||
+ (*size == 0))
+ return -1;
+
+ /* Convert chars to bytes */
+ for (i = 0, len = 0; i < *size; i += 2) {
+ snprintf(tmp, 3, "%s", src + i);
+ dst[len++] = strtoul(tmp, &c, 16);
+ if (*c != 0) {
+ len--;
+ dst[len] = 0;
+ *size = len;
+ return -1;
+ }
+ }
+ dst[len] = 0;
+ *size = len;
+
+ return 0;
+}
+
+static int
+parse_hex(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg_data = pop_args(ctx);
+ const struct arg *arg_len = pop_args(ctx);
+ const struct arg *arg_addr = pop_args(ctx);
+ char tmp[16]; /* Ought to be enough. */
+ int ret;
+ unsigned int hexlen = len;
+ unsigned int length = 256;
+ uint8_t hex_tmp[length];
+
+ /* Arguments are expected. */
+ if (!arg_data)
+ return -1;
+ if (!arg_len) {
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ if (!arg_addr) {
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+ }
+ size = arg_data->size;
+ /* Bit-mask fill is not supported. */
+ if (arg_data->mask)
+ goto error;
+ if (!ctx->object)
+ return len;
+
+ /* translate bytes string to array. */
+ if (str[0] == '0' && ((str[1] == 'x') ||
+ (str[1] == 'X'))) {
+ str += 2;
+ hexlen -= 2;
+ }
+ if (hexlen > length)
+ return -1;
+ ret = parse_hex_string(str, hex_tmp, &hexlen);
+ if (ret < 0)
+ goto error;
+ /* Let parse_int() fill length information first. */
+ ret = snprintf(tmp, sizeof(tmp), "%u", hexlen);
+ if (ret < 0)
+ goto error;
+ push_args(ctx, arg_len);
+ ret = parse_int(ctx, token, tmp, ret, NULL, 0);
+ if (ret < 0) {
+ pop_args(ctx);
+ goto error;
+ }
+ buf = (uint8_t *)ctx->object + arg_data->offset;
+ /* Output buffer is not necessarily NUL-terminated. */
+ memcpy(buf, hex_tmp, hexlen);
+ memset((uint8_t *)buf + hexlen, 0x00, size - hexlen);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg_data->offset,
+ 0xff, hexlen);
+ /* Save address if requested. */
+ if (arg_addr->size) {
+ memcpy((uint8_t *)ctx->object + arg_addr->offset,
+ (void *[]){
+ (uint8_t *)ctx->object + arg_data->offset
+ },
+ arg_addr->size);
+ if (ctx->objmask)
+ memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
+ (void *[]){
+ (uint8_t *)ctx->objmask + arg_data->offset
+ },
+ arg_addr->size);
+ }
+ return len;
+error:
+ push_args(ctx, arg_addr);
+ push_args(ctx, arg_len);
+ push_args(ctx, arg_data);
+ return -1;
+
+}
+
+/**
+ * Parse a zero-ended string.
+ */
+static int
+parse_string0(struct context *ctx, const struct token *token __rte_unused,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg_data = pop_args(ctx);
+
+ /* Arguments are expected. */
+ if (!arg_data)
+ return -1;
+ size = arg_data->size;
+ /* Bit-mask fill is not supported. */
+ if (arg_data->mask || size < len + 1)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg_data->offset;
+ strncpy(buf, str, len);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
+ return len;
+error:
+ push_args(ctx, arg_data);
+ return -1;
+}
+
+/**
+ * Parse a MAC address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_mac_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ struct rte_ether_addr tmp;
+ int ret;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
+ if (ret < 0 || (unsigned int)ret != len)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse an IPv4 address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_ipv4_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ char str2[len + 1];
+ struct in_addr tmp;
+ int ret;
+
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ memcpy(str2, str, len);
+ str2[len] = '\0';
+ ret = inet_pton(AF_INET, str2, &tmp);
+ if (ret != 1) {
+ /* Attempt integer parsing. */
+ push_args(ctx, arg);
+ return parse_int(ctx, token, str, len, buf, size);
+ }
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/**
+ * Parse an IPv6 address.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_ipv6_addr(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ char str2[len + 1];
+ struct in6_addr tmp;
+ int ret;
+
+ (void)token;
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ size = arg->size;
+ /* Bit-mask fill is not supported. */
+ if (arg->mask || size != sizeof(tmp))
+ goto error;
+ /* Only network endian is supported. */
+ if (!arg->hton)
+ goto error;
+ memcpy(str2, str, len);
+ str2[len] = '\0';
+ ret = inet_pton(AF_INET6, str2, &tmp);
+ if (ret != 1)
+ goto error;
+ if (!ctx->object)
+ return len;
+ buf = (uint8_t *)ctx->object + arg->offset;
+ memcpy(buf, &tmp, size);
+ if (ctx->objmask)
+ memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
+ return len;
+error:
+ push_args(ctx, arg);
+ return -1;
+}
+
+/** Boolean values (even indices stand for false). */
+static const char *const boolean_name[] = {
+ "0", "1",
+ "false", "true",
+ "no", "yes",
+ "N", "Y",
+ "off", "on",
+ NULL,
+};
+
+/**
+ * Parse a boolean value.
+ *
+ * Last argument (ctx->args) is retrieved to determine storage size and
+ * location.
+ */
+static int
+parse_boolean(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ const struct arg *arg = pop_args(ctx);
+ unsigned int i;
+ int ret;
+
+ /* Argument is expected. */
+ if (!arg)
+ return -1;
+ for (i = 0; boolean_name[i]; ++i)
+ if (!strcmp_partial(boolean_name[i], str, len))
+ break;
+ /* Process token as integer. */
+ if (boolean_name[i])
+ str = i & 1 ? "1" : "0";
+ push_args(ctx, arg);
+ ret = parse_int(ctx, token, str, strlen(str), buf, size);
+ return ret > 0 ? (int)len : ret;
+}
+
+/** Parse port and update context. */
+static int
+parse_port(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = &(struct buffer){ .port = 0 };
+ int ret;
+
+ if (buf)
+ out = buf;
+ else {
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ size = sizeof(*out);
+ }
+ ret = parse_int(ctx, token, str, len, out, size);
+ if (ret >= 0)
+ ctx->port = out->port;
+ if (!buf)
+ ctx->object = NULL;
+ return ret;
+}
+
+/** Parse set command, initialize output buffer for subsequent tokens. */
+static int
+parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Make sure buffer is large enough. */
+ if (size < sizeof(*out))
+ return -1;
+ ctx->objdata = 0;
+ ctx->objmask = NULL;
+ ctx->object = out;
+ if (!out->command)
+ return -1;
+ out->command = ctx->curr;
+ return len;
+}
+
+/**
+ * Parse set raw_encap/raw_decap command,
+ * initialize output buffer for subsequent tokens.
+ */
+static int
+parse_set_init(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ /* Make sure buffer is large enough. */
+ if (size < sizeof(*out))
+ return -1;
+ /* Initialize buffer. */
+ memset(out, 0x00, sizeof(*out));
+ memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ if (!out->command) {
+ if (ctx->curr != SET)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ out->args.vc.data = (uint8_t *)out + size;
+ /* All we need is pattern */
+ out->args.vc.pattern =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ ctx->object = out->args.vc.pattern;
+ }
+ return len;
+}
+
+/** No completion. */
+static int
+comp_none(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ (void)ctx;
+ (void)token;
+ (void)ent;
+ (void)buf;
+ (void)size;
+ return 0;
+}
+
+/** Complete boolean values. */
+static int
+comp_boolean(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; boolean_name[i]; ++i)
+ if (buf && i == ent)
+ return strlcpy(buf, boolean_name[i], size);
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete action names. */
+static int
+comp_action(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; next_action[i]; ++i)
+ if (buf && i == ent)
+ return strlcpy(buf, token_list[next_action[i]].name,
+ size);
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available ports. */
+static int
+comp_port(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ portid_t p;
+
+ (void)ctx;
+ (void)token;
+ RTE_ETH_FOREACH_DEV(p) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", p);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete available rule IDs. */
+static int
+comp_rule_id(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i = 0;
+ struct rte_port *port;
+ struct port_flow *pf;
+
+ (void)token;
+ if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+ ctx->port == (portid_t)RTE_PORT_ALL)
+ return -1;
+ port = &ports[ctx->port];
+ for (pf = port->flow_list; pf != NULL; pf = pf->next) {
+ if (buf && i == ent)
+ return snprintf(buf, size, "%u", pf->id);
+ ++i;
+ }
+ if (buf)
+ return -1;
+ return i;
+}
+
+/** Complete type field for RSS action. */
+static int
+comp_vc_action_rss_type(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ unsigned int i;
+
+ (void)ctx;
+ (void)token;
+ for (i = 0; rss_type_table[i].str; ++i)
+ ;
+ if (!buf)
+ return i + 1;
+ if (ent < i)
+ return strlcpy(buf, rss_type_table[ent].str, size);
+ if (ent == i)
+ return snprintf(buf, size, "end");
+ return -1;
+}
+
+/** Complete queue field for RSS action. */
+static int
+comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ (void)ctx;
+ (void)token;
+ if (!buf)
+ return nb_rxq + 1;
+ if (ent < nb_rxq)
+ return snprintf(buf, size, "%u", ent);
+ if (ent == nb_rxq)
+ return snprintf(buf, size, "end");
+ return -1;
+}
+
+/** Complete index number for set raw_encap/raw_decap commands. */
+static int
+comp_set_raw_index(struct context *ctx, const struct token *token,
+ unsigned int ent, char *buf, unsigned int size)
+{
+ uint16_t idx = 0;
+ uint16_t nb = 0;
+
+ RTE_SET_USED(ctx);
+ RTE_SET_USED(token);
+ for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) {
+ if (buf && idx == ent)
+ return snprintf(buf, size, "%u", idx);
+ ++nb;
+ }
+ return nb;
+}
+
+/** Internal context. */
+static struct context cmd_flow_context;
+
+/** Global parser instance (cmdline API). */
+cmdline_parse_inst_t cmd_flow;
+cmdline_parse_inst_t cmd_set_raw;
+
+/** Initialize context. */
+static void
+cmd_flow_context_init(struct context *ctx)
+{
+ /* A full memset() is not necessary. */
+ ctx->curr = ZERO;
+ ctx->prev = ZERO;
+ ctx->next_num = 0;
+ ctx->args_num = 0;
+ ctx->eol = 0;
+ ctx->last = 0;
+ ctx->port = 0;
+ ctx->objdata = 0;
+ ctx->object = NULL;
+ ctx->objmask = NULL;
+}
+
+/** Parse a token (cmdline API). */
+static int
+cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
+ unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token;
+ const enum index *list;
+ int len;
+ int i;
+
+ (void)hdr;
+ token = &token_list[ctx->curr];
+ /* Check argument length. */
+ ctx->eol = 0;
+ ctx->last = 1;
+ for (len = 0; src[len]; ++len)
+ if (src[len] == '#' || isspace(src[len]))
+ break;
+ if (!len)
+ return -1;
+ /* Last argument and EOL detection. */
+ for (i = len; src[i]; ++i)
+ if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
+ break;
+ else if (!isspace(src[i])) {
+ ctx->last = 0;
+ break;
+ }
+ for (; src[i]; ++i)
+ if (src[i] == '\r' || src[i] == '\n') {
+ ctx->eol = 1;
+ break;
+ }
+ /* Initialize context if necessary. */
+ if (!ctx->next_num) {
+ if (!token->next)
+ return 0;
+ ctx->next[ctx->next_num++] = token->next[0];
+ }
+ /* Process argument through candidates. */
+ ctx->prev = ctx->curr;
+ list = ctx->next[ctx->next_num - 1];
+ for (i = 0; list[i]; ++i) {
+ const struct token *next = &token_list[list[i]];
+ int tmp;
+
+ ctx->curr = list[i];
+ if (next->call)
+ tmp = next->call(ctx, next, src, len, result, size);
+ else
+ tmp = parse_default(ctx, next, src, len, result, size);
+ if (tmp == -1 || tmp != len)
+ continue;
+ token = next;
+ break;
+ }
+ if (!list[i])
+ return -1;
+ --ctx->next_num;
+ /* Push subsequent tokens if any. */
+ if (token->next)
+ for (i = 0; token->next[i]; ++i) {
+ if (ctx->next_num == RTE_DIM(ctx->next))
+ return -1;
+ ctx->next[ctx->next_num++] = token->next[i];
+ }
+ /* Push arguments if any. */
+ if (token->args)
+ for (i = 0; token->args[i]; ++i) {
+ if (ctx->args_num == RTE_DIM(ctx->args))
+ return -1;
+ ctx->args[ctx->args_num++] = token->args[i];
+ }
+ return len;
+}
+
+/** Return number of completion entries (cmdline API). */
+static int
+cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->curr];
+ const enum index *list;
+ int i;
+
+ (void)hdr;
+ /* Count number of tokens in current list. */
+ if (ctx->next_num)
+ list = ctx->next[ctx->next_num - 1];
+ else
+ list = token->next[0];
+ for (i = 0; list[i]; ++i)
+ ;
+ if (!i)
+ return 0;
+ /*
+ * If there is a single token, use its completion callback, otherwise
+ * return the number of entries.
+ */
+ token = &token_list[list[0]];
+ if (i == 1 && token->comp) {
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[0];
+ return token->comp(ctx, token, 0, NULL, 0);
+ }
+ return i;
+}
+
+/** Return a completion entry (cmdline API). */
+static int
+cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
+ char *dst, unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->curr];
+ const enum index *list;
+ int i;
+
+ (void)hdr;
+ /* Count number of tokens in current list. */
+ if (ctx->next_num)
+ list = ctx->next[ctx->next_num - 1];
+ else
+ list = token->next[0];
+ for (i = 0; list[i]; ++i)
+ ;
+ if (!i)
+ return -1;
+ /* If there is a single token, use its completion callback. */
+ token = &token_list[list[0]];
+ if (i == 1 && token->comp) {
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[0];
+ return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
+ }
+ /* Otherwise make sure the index is valid and use defaults. */
+ if (index >= i)
+ return -1;
+ token = &token_list[list[index]];
+ strlcpy(dst, token->name, size);
+ /* Save index for cmd_flow_get_help(). */
+ ctx->prev = list[index];
+ return 0;
+}
+
+/** Populate help strings for current token (cmdline API). */
+static int
+cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->prev];
+
+ (void)hdr;
+ if (!size)
+ return -1;
+ /* Set token type and update global help with details. */
+ strlcpy(dst, (token->type ? token->type : "TOKEN"), size);
+ if (token->help)
+ cmd_flow.help_str = token->help;
+ else
+ cmd_flow.help_str = token->name;
+ return 0;
+}
+
+/** Token definition template (cmdline API). */
+static struct cmdline_token_hdr cmd_flow_token_hdr = {
+ .ops = &(struct cmdline_token_ops){
+ .parse = cmd_flow_parse,
+ .complete_get_nb = cmd_flow_complete_get_nb,
+ .complete_get_elt = cmd_flow_complete_get_elt,
+ .get_help = cmd_flow_get_help,
+ },
+ .offset = 0,
+};
+
+/** Populate the next dynamic token. */
+static void
+cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
+ cmdline_parse_token_hdr_t **hdr_inst)
+{
+ struct context *ctx = &cmd_flow_context;
+
+ /* Always reinitialize context before requesting the first token. */
+ if (!(hdr_inst - cmd_flow.tokens))
+ cmd_flow_context_init(ctx);
+ /* Return NULL when no more tokens are expected. */
+ if (!ctx->next_num && ctx->curr) {
+ *hdr = NULL;
+ return;
+ }
+ /* Determine if command should end here. */
+ if (ctx->eol && ctx->last && ctx->next_num) {
+ const enum index *list = ctx->next[ctx->next_num - 1];
+ int i;
+
+ for (i = 0; list[i]; ++i) {
+ if (list[i] != END)
+ continue;
+ *hdr = NULL;
+ return;
+ }
+ }
+ *hdr = &cmd_flow_token_hdr;
+}
+
+/** Dispatch parsed buffer to function calls. */
+static void
+cmd_flow_parsed(const struct buffer *in)
+{
+ switch (in->command) {
+ case VALIDATE:
+ port_flow_validate(in->port, &in->args.vc.attr,
+ in->args.vc.pattern, in->args.vc.actions);
+ break;
+ case CREATE:
+ port_flow_create(in->port, &in->args.vc.attr,
+ in->args.vc.pattern, in->args.vc.actions);
+ break;
+ case DESTROY:
+ port_flow_destroy(in->port, in->args.destroy.rule_n,
+ in->args.destroy.rule);
+ break;
+ case FLUSH:
+ port_flow_flush(in->port);
+ break;
+ case DUMP:
+ port_flow_dump(in->port, in->args.dump.file);
+ break;
+ case QUERY:
+ port_flow_query(in->port, in->args.query.rule,
+ &in->args.query.action);
+ break;
+ case LIST:
+ port_flow_list(in->port, in->args.list.group_n,
+ in->args.list.group);
+ break;
+ case ISOLATE:
+ port_flow_isolate(in->port, in->args.isolate.set);
+ break;
+ case AGED:
+ port_flow_aged(in->port, in->args.aged.destroy);
+ break;
+ default:
+ break;
+ }
+}
+
+/** Token generator and output processing callback (cmdline API). */
+static void
+cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
+{
+ if (cl == NULL)
+ cmd_flow_tok(arg0, arg2);
+ else
+ cmd_flow_parsed(arg0);
+}
+
+/** Global parser instance (cmdline API). */
+cmdline_parse_inst_t cmd_flow = {
+ .f = cmd_flow_cb,
+ .data = NULL, /**< Unused. */
+ .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
+ .tokens = {
+ NULL,
+ }, /**< Tokens are returned by cmd_flow_tok(). */
+};
+
+/** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */
+
+static void
+update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto)
+{
+ struct rte_flow_item_ipv4 *ipv4;
+ struct rte_flow_item_eth *eth;
+ struct rte_flow_item_ipv6 *ipv6;
+ struct rte_flow_item_vxlan *vxlan;
+ struct rte_flow_item_vxlan_gpe *gpe;
+ struct rte_flow_item_nvgre *nvgre;
+ uint32_t ipv6_vtc_flow;
+
+ switch (item->type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ eth = (struct rte_flow_item_eth *)buf;
+ if (next_proto)
+ eth->type = rte_cpu_to_be_16(next_proto);
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ ipv4 = (struct rte_flow_item_ipv4 *)buf;
+ ipv4->hdr.version_ihl = 0x45;
+ if (next_proto && ipv4->hdr.next_proto_id == 0)
+ ipv4->hdr.next_proto_id = (uint8_t)next_proto;
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ ipv6 = (struct rte_flow_item_ipv6 *)buf;
+ if (next_proto && ipv6->hdr.proto == 0)
+ ipv6->hdr.proto = (uint8_t)next_proto;
+ ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow);
+ ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */
+ ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */
+ ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow);
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ vxlan = (struct rte_flow_item_vxlan *)buf;
+ vxlan->flags = 0x08;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ gpe = (struct rte_flow_item_vxlan_gpe *)buf;
+ gpe->flags = 0x0C;
+ break;
+ case RTE_FLOW_ITEM_TYPE_NVGRE:
+ nvgre = (struct rte_flow_item_nvgre *)buf;
+ nvgre->protocol = rte_cpu_to_be_16(0x6558);
+ nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000);
+ break;
+ default:
+ break;
+ }
+}
+
+/** Helper of get item's default mask. */
+static const void *
+flow_item_default_mask(const struct rte_flow_item *item)
+{
+ const void *mask = NULL;
+ static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
+
+ switch (item->type) {
+ case RTE_FLOW_ITEM_TYPE_ANY:
+ mask = &rte_flow_item_any_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VF:
+ mask = &rte_flow_item_vf_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_PORT_ID:
+ mask = &rte_flow_item_port_id_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_RAW:
+ mask = &rte_flow_item_raw_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ mask = &rte_flow_item_eth_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VLAN:
+ mask = &rte_flow_item_vlan_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ mask = &rte_flow_item_ipv4_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ mask = &rte_flow_item_ipv6_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_ICMP:
+ mask = &rte_flow_item_icmp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ mask = &rte_flow_item_udp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ mask = &rte_flow_item_tcp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_SCTP:
+ mask = &rte_flow_item_sctp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ mask = &rte_flow_item_vxlan_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ mask = &rte_flow_item_vxlan_gpe_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_E_TAG:
+ mask = &rte_flow_item_e_tag_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_NVGRE:
+ mask = &rte_flow_item_nvgre_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_MPLS:
+ mask = &rte_flow_item_mpls_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GRE:
+ mask = &rte_flow_item_gre_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+ mask = &gre_key_default_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_META:
+ mask = &rte_flow_item_meta_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_FUZZY:
+ mask = &rte_flow_item_fuzzy_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GTP:
+ mask = &rte_flow_item_gtp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GTP_PSC:
+ mask = &rte_flow_item_gtp_psc_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ mask = &rte_flow_item_geneve_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
+ mask = &rte_flow_item_pppoe_proto_id_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
+ mask = &rte_flow_item_l2tpv3oip_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_ESP:
+ mask = &rte_flow_item_esp_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_AH:
+ mask = &rte_flow_item_ah_mask;
+ break;
+ case RTE_FLOW_ITEM_TYPE_PFCP:
+ mask = &rte_flow_item_pfcp_mask;
+ break;
+ default:
+ break;
+ }
+ return mask;
+}
+
+
+
+/** Dispatch parsed buffer to function calls. */
+static void
+cmd_set_raw_parsed(const struct buffer *in)
+{
+ uint32_t n = in->args.vc.pattern_n;
+ int i = 0;
+ struct rte_flow_item *item = NULL;
+ size_t size = 0;
+ uint8_t *data = NULL;
+ uint8_t *data_tail = NULL;
+ size_t *total_size = NULL;
+ uint16_t upper_layer = 0;
+ uint16_t proto = 0;
+ uint16_t idx = in->port; /* We borrow port field as index */
+
+ RTE_ASSERT(in->command == SET_RAW_ENCAP ||
+ in->command == SET_RAW_DECAP);
+ if (in->command == SET_RAW_ENCAP) {
+ total_size = &raw_encap_confs[idx].size;
+ data = (uint8_t *)&raw_encap_confs[idx].data;
+ } else {
+ total_size = &raw_decap_confs[idx].size;
+ data = (uint8_t *)&raw_decap_confs[idx].data;
+ }
+ *total_size = 0;
+ memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
+ /* process hdr from upper layer to low layer (L3/L4 -> L2). */
+ data_tail = data + ACTION_RAW_ENCAP_MAX_DATA;
+ for (i = n - 1 ; i >= 0; --i) {
+ item = in->args.vc.pattern + i;
+ if (item->spec == NULL)
+ item->spec = flow_item_default_mask(item);
+ switch (item->type) {
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ size = sizeof(struct rte_flow_item_eth);
+ break;
+ case RTE_FLOW_ITEM_TYPE_VLAN:
+ size = sizeof(struct rte_flow_item_vlan);
+ proto = RTE_ETHER_TYPE_VLAN;
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ size = sizeof(struct rte_flow_item_ipv4);
+ proto = RTE_ETHER_TYPE_IPV4;
+ break;
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ size = sizeof(struct rte_flow_item_ipv6);
+ proto = RTE_ETHER_TYPE_IPV6;
+ break;
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ size = sizeof(struct rte_flow_item_udp);
+ proto = 0x11;
+ break;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ size = sizeof(struct rte_flow_item_tcp);
+ proto = 0x06;
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ size = sizeof(struct rte_flow_item_vxlan);
+ break;
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ size = sizeof(struct rte_flow_item_vxlan_gpe);
+ break;
+ case RTE_FLOW_ITEM_TYPE_GRE:
+ size = sizeof(struct rte_flow_item_gre);
+ proto = 0x2F;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+ size = sizeof(rte_be32_t);
+ proto = 0x0;
+ break;
+ case RTE_FLOW_ITEM_TYPE_MPLS:
+ size = sizeof(struct rte_flow_item_mpls);
+ proto = 0x0;
+ break;
+ case RTE_FLOW_ITEM_TYPE_NVGRE:
+ size = sizeof(struct rte_flow_item_nvgre);
+ proto = 0x2F;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ size = sizeof(struct rte_flow_item_geneve);
+ break;
+ case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
+ size = sizeof(struct rte_flow_item_l2tpv3oip);
+ proto = 0x73;
+ break;
+ case RTE_FLOW_ITEM_TYPE_ESP:
+ size = sizeof(struct rte_flow_item_esp);
+ proto = 0x32;
+ break;
+ case RTE_FLOW_ITEM_TYPE_AH:
+ size = sizeof(struct rte_flow_item_ah);
+ proto = 0x33;
+ break;
+ case RTE_FLOW_ITEM_TYPE_GTP:
+ size = sizeof(struct rte_flow_item_gtp);
+ break;
+ case RTE_FLOW_ITEM_TYPE_PFCP:
+ size = sizeof(struct rte_flow_item_pfcp);
+ break;
+ default:
+ printf("Error - Not supported item\n");
+ *total_size = 0;
+ memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA);
+ return;
+ }
+ *total_size += size;
+ rte_memcpy(data_tail - (*total_size), item->spec, size);
+ /* update some fields which cannot be set by cmdline */
+ update_fields((data_tail - (*total_size)), item,
+ upper_layer);
+ upper_layer = proto;
+ }
+ if (verbose_level & 0x1)
+ printf("total data size is %zu\n", (*total_size));
+ RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA);
+ memmove(data, (data_tail - (*total_size)), *total_size);
+}
+
+/** Populate help strings for current token (cmdline API). */
+static int
+cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst,
+ unsigned int size)
+{
+ struct context *ctx = &cmd_flow_context;
+ const struct token *token = &token_list[ctx->prev];
+
+ (void)hdr;
+ if (!size)
+ return -1;
+ /* Set token type and update global help with details. */
+ snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
+ if (token->help)
+ cmd_set_raw.help_str = token->help;
+ else
+ cmd_set_raw.help_str = token->name;
+ return 0;
+}
+
+/** Token definition template (cmdline API). */
+static struct cmdline_token_hdr cmd_set_raw_token_hdr = {
+ .ops = &(struct cmdline_token_ops){
+ .parse = cmd_flow_parse,
+ .complete_get_nb = cmd_flow_complete_get_nb,
+ .complete_get_elt = cmd_flow_complete_get_elt,
+ .get_help = cmd_set_raw_get_help,
+ },
+ .offset = 0,
+};
+
+/** Populate the next dynamic token. */
+static void
+cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr,
+ cmdline_parse_token_hdr_t **hdr_inst)
+{
+ struct context *ctx = &cmd_flow_context;
+
+ /* Always reinitialize context before requesting the first token. */
+ if (!(hdr_inst - cmd_set_raw.tokens)) {
+ cmd_flow_context_init(ctx);
+ ctx->curr = START_SET;
+ }
+ /* Return NULL when no more tokens are expected. */
+ if (!ctx->next_num && (ctx->curr != START_SET)) {
+ *hdr = NULL;
+ return;
+ }
+ /* Determine if command should end here. */
+ if (ctx->eol && ctx->last && ctx->next_num) {
+ const enum index *list = ctx->next[ctx->next_num - 1];
+ int i;
+
+ for (i = 0; list[i]; ++i) {
+ if (list[i] != END)
+ continue;
+ *hdr = NULL;
+ return;
+ }
+ }
+ *hdr = &cmd_set_raw_token_hdr;
+}
+
+/** Token generator and output processing callback (cmdline API). */
+static void
+cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2)
+{
+ if (cl == NULL)
+ cmd_set_raw_tok(arg0, arg2);
+ else
+ cmd_set_raw_parsed(arg0);
+}
+
+/** Global parser instance (cmdline API). */
+cmdline_parse_inst_t cmd_set_raw = {
+ .f = cmd_set_raw_cb,
+ .data = NULL, /**< Unused. */
+ .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
+ .tokens = {
+ NULL,
+ }, /**< Tokens are returned by cmd_flow_tok(). */
+};
+
+/* *** display raw_encap/raw_decap buf */
+struct cmd_show_set_raw_result {
+ cmdline_fixed_string_t cmd_show;
+ cmdline_fixed_string_t cmd_what;
+ cmdline_fixed_string_t cmd_all;
+ uint16_t cmd_index;
+};
+
+static void
+cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_show_set_raw_result *res = parsed_result;
+ uint16_t index = res->cmd_index;
+ uint8_t all = 0;
+ uint8_t *raw_data = NULL;
+ size_t raw_size = 0;
+ char title[16] = {0};
+
+ RTE_SET_USED(cl);
+ RTE_SET_USED(data);
+ if (!strcmp(res->cmd_all, "all")) {
+ all = 1;
+ index = 0;
+ } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) {
+ printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1);
+ return;
+ }
+ do {
+ if (!strcmp(res->cmd_what, "raw_encap")) {
+ raw_data = (uint8_t *)&raw_encap_confs[index].data;
+ raw_size = raw_encap_confs[index].size;
+ snprintf(title, 16, "\nindex: %u", index);
+ rte_hexdump(stdout, title, raw_data, raw_size);
+ } else {
+ raw_data = (uint8_t *)&raw_decap_confs[index].data;
+ raw_size = raw_decap_confs[index].size;
+ snprintf(title, 16, "\nindex: %u", index);
+ rte_hexdump(stdout, title, raw_data, raw_size);
+ }
+ } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM);
+}
+
+cmdline_parse_token_string_t cmd_show_set_raw_cmd_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
+ cmd_show, "show");
+cmdline_parse_token_string_t cmd_show_set_raw_cmd_what =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
+ cmd_what, "raw_encap#raw_decap");
+cmdline_parse_token_num_t cmd_show_set_raw_cmd_index =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result,
+ cmd_index, UINT16);
+cmdline_parse_token_string_t cmd_show_set_raw_cmd_all =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result,
+ cmd_all, "all");
+cmdline_parse_inst_t cmd_show_set_raw = {
+ .f = cmd_show_set_raw_parsed,
+ .data = NULL,
+ .help_str = "show <raw_encap|raw_decap> <index>",
+ .tokens = {
+ (void *)&cmd_show_set_raw_cmd_show,
+ (void *)&cmd_show_set_raw_cmd_what,
+ (void *)&cmd_show_set_raw_cmd_index,
+ NULL,
+ },
+};
+cmdline_parse_inst_t cmd_show_set_raw_all = {
+ .f = cmd_show_set_raw_parsed,
+ .data = NULL,
+ .help_str = "show <raw_encap|raw_decap> all",
+ .tokens = {
+ (void *)&cmd_show_set_raw_cmd_show,
+ (void *)&cmd_show_set_raw_cmd_what,
+ (void *)&cmd_show_set_raw_cmd_all,
+ NULL,
+ },
+};
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline_mtr.c b/src/spdk/dpdk/app/test-pmd/cmdline_mtr.c
new file mode 100644
index 000000000..caa7e9864
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline_mtr.c
@@ -0,0 +1,1467 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_mtr.h>
+
+#include "testpmd.h"
+#include "cmdline_mtr.h"
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+#define MAX_DSCP_TABLE_ENTRIES 64
+
+/** Display Meter Error Message */
+static void
+print_err_msg(struct rte_mtr_error *error)
+{
+ static const char *const errstrlist[] = {
+ [RTE_MTR_ERROR_TYPE_NONE] = "no error",
+ [RTE_MTR_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+ [RTE_MTR_ERROR_TYPE_METER_PROFILE_ID] = "meter profile id",
+ [RTE_MTR_ERROR_TYPE_METER_PROFILE] = "meter profile null",
+ [RTE_MTR_ERROR_TYPE_MTR_ID] = "meter id",
+ [RTE_MTR_ERROR_TYPE_MTR_PARAMS] = "meter params null",
+ [RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN]
+ = "policer action(green)",
+ [RTE_MTR_ERROR_TYPE_POLICER_ACTION_YELLOW]
+ = "policer action(yellow)",
+ [RTE_MTR_ERROR_TYPE_POLICER_ACTION_RED]
+ = "policer action(red)",
+ [RTE_MTR_ERROR_TYPE_STATS_MASK] = "stats mask",
+ [RTE_MTR_ERROR_TYPE_STATS] = "stats",
+ [RTE_MTR_ERROR_TYPE_SHARED]
+ = "shared meter",
+ };
+
+ const char *errstr;
+ char buf[64];
+
+ if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+ !errstrlist[error->type])
+ errstr = "unknown type";
+ else
+ errstr = errstrlist[error->type];
+
+ if (error->cause)
+ snprintf(buf, sizeof(buf), "cause: %p, ", error->cause);
+
+ printf("%s: %s%s (error %d)\n", errstr, error->cause ? buf : "",
+ error->message ? error->message : "(no stated reason)",
+ error->type);
+}
+
+static int
+parse_uint(uint64_t *value, const char *str)
+{
+ char *next = NULL;
+ uint64_t n;
+
+ errno = 0;
+ /* Parse number string */
+ n = strtol(str, &next, 10);
+ if (errno != 0 || str == next || *next != '\0')
+ return -1;
+
+ *value = n;
+
+ return 0;
+}
+
+static int
+parse_dscp_table_entries(char *str, enum rte_color **dscp_table)
+{
+ char *token;
+ int i = 0;
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL)
+ return 0;
+
+ /* Allocate memory for dscp table */
+ *dscp_table = (enum rte_color *)malloc(MAX_DSCP_TABLE_ENTRIES *
+ sizeof(enum rte_color));
+ if (*dscp_table == NULL)
+ return -1;
+
+ while (1) {
+ if (strcmp(token, "G") == 0 ||
+ strcmp(token, "g") == 0)
+ *dscp_table[i++] = RTE_COLOR_GREEN;
+ else if (strcmp(token, "Y") == 0 ||
+ strcmp(token, "y") == 0)
+ *dscp_table[i++] = RTE_COLOR_YELLOW;
+ else if (strcmp(token, "R") == 0 ||
+ strcmp(token, "r") == 0)
+ *dscp_table[i++] = RTE_COLOR_RED;
+ else {
+ free(*dscp_table);
+ return -1;
+ }
+ if (i == MAX_DSCP_TABLE_ENTRIES)
+ break;
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ free(*dscp_table);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+parse_meter_color_str(char *c_str, uint32_t *use_prev_meter_color,
+ enum rte_color **dscp_table)
+{
+ char *token;
+ uint64_t previous_mtr_color = 0;
+ int ret;
+
+ /* First token: use previous meter color */
+ token = strtok_r(c_str, PARSE_DELIMITER, &c_str);
+ if (token == NULL)
+ return -1;
+
+ ret = parse_uint(&previous_mtr_color, token);
+ if (ret != 0)
+ return -1;
+
+ /* Check if previous meter color to be used */
+ if (previous_mtr_color) {
+ *use_prev_meter_color = previous_mtr_color;
+ return 0;
+ }
+
+ /* Parse dscp table entries */
+ ret = parse_dscp_table_entries(c_str, dscp_table);
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+string_to_policer_action(char *s)
+{
+ if ((strcmp(s, "G") == 0) || (strcmp(s, "g") == 0))
+ return MTR_POLICER_ACTION_COLOR_GREEN;
+
+ if ((strcmp(s, "Y") == 0) || (strcmp(s, "y") == 0))
+ return MTR_POLICER_ACTION_COLOR_YELLOW;
+
+ if ((strcmp(s, "R") == 0) || (strcmp(s, "r") == 0))
+ return MTR_POLICER_ACTION_COLOR_RED;
+
+ if ((strcmp(s, "D") == 0) || (strcmp(s, "d") == 0))
+ return MTR_POLICER_ACTION_DROP;
+
+ return -1;
+}
+
+static int
+parse_policer_action_string(char *p_str, uint32_t action_mask,
+ enum rte_mtr_policer_action actions[])
+{
+ char *token;
+ int count = __builtin_popcount(action_mask);
+ int g_color = 0, y_color = 0, action, i;
+
+ for (i = 0; i < count; i++) {
+ token = strtok_r(p_str, PARSE_DELIMITER, &p_str);
+ if (token == NULL)
+ return -1;
+
+ action = string_to_policer_action(token);
+ if (action == -1)
+ return -1;
+
+ if (g_color == 0 && (action_mask & 0x1)) {
+ actions[RTE_COLOR_GREEN] = action;
+ g_color = 1;
+ } else if (y_color == 0 && (action_mask & 0x2)) {
+ actions[RTE_COLOR_YELLOW] = action;
+ y_color = 1;
+ } else
+ actions[RTE_COLOR_RED] = action;
+ }
+ return 0;
+}
+
+static int
+parse_multi_token_string(char *t_str, uint16_t *port_id,
+ uint32_t *mtr_id, enum rte_color **dscp_table)
+{
+ char *token;
+ uint64_t val;
+ int ret;
+
+ /* First token: port id */
+ token = strtok_r(t_str, PARSE_DELIMITER, &t_str);
+ if (token == NULL)
+ return -1;
+
+ ret = parse_uint(&val, token);
+ if (ret != 0 || val > UINT16_MAX)
+ return -1;
+
+ *port_id = val;
+
+ /* Second token: meter id */
+ token = strtok_r(t_str, PARSE_DELIMITER, &t_str);
+ if (token == NULL)
+ return 0;
+
+ ret = parse_uint(&val, token);
+ if (ret != 0 || val > UINT32_MAX)
+ return -1;
+
+ *mtr_id = val;
+
+ ret = parse_dscp_table_entries(t_str, dscp_table);
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+/* *** Show Port Meter Capabilities *** */
+struct cmd_show_port_meter_cap_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t cap;
+ uint16_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_show_port_meter_cap_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_cap_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_meter_cap_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_cap_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_meter_cap_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_cap_result, meter, "meter");
+cmdline_parse_token_string_t cmd_show_port_meter_cap_cap =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_cap_result, cap, "cap");
+cmdline_parse_token_num_t cmd_show_port_meter_cap_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_meter_cap_result, port_id, UINT16);
+
+static void cmd_show_port_meter_cap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_meter_cap_result *res = parsed_result;
+ struct rte_mtr_capabilities cap;
+ struct rte_mtr_error error;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&cap, 0, sizeof(struct rte_mtr_capabilities));
+ ret = rte_mtr_capabilities_get(port_id, &cap, &error);
+ if (ret) {
+ print_err_msg(&error);
+ return;
+ }
+
+ printf("\n**** Port Meter Object Capabilities ****\n\n");
+ printf("cap.n_max %" PRIu32 "\n", cap.n_max);
+ printf("cap.n_shared_max %" PRIu32 "\n", cap.n_shared_max);
+ printf("cap.identical %" PRId32 "\n", cap.identical);
+ printf("cap.shared_identical %" PRId32 "\n",
+ cap.shared_identical);
+ printf("cap.shared_n_flows_per_mtr_max %" PRIu32 "\n",
+ cap.shared_n_flows_per_mtr_max);
+ printf("cap.chaining_n_mtrs_per_flow_max %" PRIu32 "\n",
+ cap.chaining_n_mtrs_per_flow_max);
+ printf("cap.chaining_use_prev_mtr_color_supported %" PRId32 "\n",
+ cap.chaining_use_prev_mtr_color_supported);
+ printf("cap.chaining_use_prev_mtr_color_enforced %" PRId32 "\n",
+ cap.chaining_use_prev_mtr_color_enforced);
+ printf("cap.meter_srtcm_rfc2697_n_max %" PRIu32 "\n",
+ cap.meter_srtcm_rfc2697_n_max);
+ printf("cap.meter_trtcm_rfc2698_n_max %" PRIu32 "\n",
+ cap.meter_trtcm_rfc2698_n_max);
+ printf("cap.meter_trtcm_rfc4115_n_max %" PRIu32 "\n",
+ cap.meter_trtcm_rfc4115_n_max);
+ printf("cap.meter_rate_max %" PRIu64 "\n", cap.meter_rate_max);
+ printf("cap.color_aware_srtcm_rfc2697_supported %" PRId32 "\n",
+ cap.color_aware_srtcm_rfc2697_supported);
+ printf("cap.color_aware_trtcm_rfc2698_supported %" PRId32 "\n",
+ cap.color_aware_trtcm_rfc2698_supported);
+ printf("cap.color_aware_trtcm_rfc4115_supported %" PRId32 "\n",
+ cap.color_aware_trtcm_rfc4115_supported);
+ printf("cap.policer_action_recolor_supported %" PRId32 "\n",
+ cap.policer_action_recolor_supported);
+ printf("cap.policer_action_drop_supported %" PRId32 "\n",
+ cap.policer_action_drop_supported);
+ printf("cap.stats_mask %" PRIx64 "\n", cap.stats_mask);
+}
+
+cmdline_parse_inst_t cmd_show_port_meter_cap = {
+ .f = cmd_show_port_meter_cap_parsed,
+ .data = NULL,
+ .help_str = "Show port meter cap",
+ .tokens = {
+ (void *)&cmd_show_port_meter_cap_show,
+ (void *)&cmd_show_port_meter_cap_port,
+ (void *)&cmd_show_port_meter_cap_meter,
+ (void *)&cmd_show_port_meter_cap_cap,
+ (void *)&cmd_show_port_meter_cap_port_id,
+ NULL,
+ },
+};
+
+/* *** Add Port Meter Profile srtcm_rfc2697 *** */
+struct cmd_add_port_meter_profile_srtcm_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t profile;
+ cmdline_fixed_string_t srtcm_rfc2697;
+ uint16_t port_id;
+ uint32_t profile_id;
+ uint64_t cir;
+ uint64_t cbs;
+ uint64_t ebs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_srtcm_srtcm_rfc2697 =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ srtcm_rfc2697, "srtcm_rfc2697");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cir =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_cbs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_srtcm_ebs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_srtcm_result,
+ ebs, UINT64);
+
+static void cmd_add_port_meter_profile_srtcm_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_meter_profile_srtcm_result *res = parsed_result;
+ struct rte_mtr_meter_profile mp;
+ struct rte_mtr_error error;
+ uint32_t profile_id = res->profile_id;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Private shaper profile params */
+ memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+ mp.alg = RTE_MTR_SRTCM_RFC2697;
+ mp.srtcm_rfc2697.cir = res->cir;
+ mp.srtcm_rfc2697.cbs = res->cbs;
+ mp.srtcm_rfc2697.ebs = res->ebs;
+
+ ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm = {
+ .f = cmd_add_port_meter_profile_srtcm_parsed,
+ .data = NULL,
+ .help_str = "Add port meter profile srtcm (rfc2697)",
+ .tokens = {
+ (void *)&cmd_add_port_meter_profile_srtcm_add,
+ (void *)&cmd_add_port_meter_profile_srtcm_port,
+ (void *)&cmd_add_port_meter_profile_srtcm_meter,
+ (void *)&cmd_add_port_meter_profile_srtcm_profile,
+ (void *)&cmd_add_port_meter_profile_srtcm_srtcm_rfc2697,
+ (void *)&cmd_add_port_meter_profile_srtcm_port_id,
+ (void *)&cmd_add_port_meter_profile_srtcm_profile_id,
+ (void *)&cmd_add_port_meter_profile_srtcm_cir,
+ (void *)&cmd_add_port_meter_profile_srtcm_cbs,
+ (void *)&cmd_add_port_meter_profile_srtcm_ebs,
+ NULL,
+ },
+};
+
+/* *** Add Port Meter Profile trtcm_rfc2698 *** */
+struct cmd_add_port_meter_profile_trtcm_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t profile;
+ cmdline_fixed_string_t trtcm_rfc2698;
+ uint16_t port_id;
+ uint32_t profile_id;
+ uint64_t cir;
+ uint64_t pir;
+ uint64_t cbs;
+ uint64_t pbs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ profile, "profile");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_trtcm_rfc2698 =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ trtcm_rfc2698, "trtcm_rfc2698");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cir =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pir =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ pir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_cbs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_pbs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_result,
+ pbs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_meter_profile_trtcm_result *res = parsed_result;
+ struct rte_mtr_meter_profile mp;
+ struct rte_mtr_error error;
+ uint32_t profile_id = res->profile_id;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Private shaper profile params */
+ memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+ mp.alg = RTE_MTR_TRTCM_RFC2698;
+ mp.trtcm_rfc2698.cir = res->cir;
+ mp.trtcm_rfc2698.pir = res->pir;
+ mp.trtcm_rfc2698.cbs = res->cbs;
+ mp.trtcm_rfc2698.pbs = res->pbs;
+
+ ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm = {
+ .f = cmd_add_port_meter_profile_trtcm_parsed,
+ .data = NULL,
+ .help_str = "Add port meter profile trtcm (rfc2698)",
+ .tokens = {
+ (void *)&cmd_add_port_meter_profile_trtcm_add,
+ (void *)&cmd_add_port_meter_profile_trtcm_port,
+ (void *)&cmd_add_port_meter_profile_trtcm_meter,
+ (void *)&cmd_add_port_meter_profile_trtcm_profile,
+ (void *)&cmd_add_port_meter_profile_trtcm_trtcm_rfc2698,
+ (void *)&cmd_add_port_meter_profile_trtcm_port_id,
+ (void *)&cmd_add_port_meter_profile_trtcm_profile_id,
+ (void *)&cmd_add_port_meter_profile_trtcm_cir,
+ (void *)&cmd_add_port_meter_profile_trtcm_pir,
+ (void *)&cmd_add_port_meter_profile_trtcm_cbs,
+ (void *)&cmd_add_port_meter_profile_trtcm_pbs,
+ NULL,
+ },
+};
+
+/* *** Add Port Meter Profile trtcm_rfc4115 *** */
+struct cmd_add_port_meter_profile_trtcm_rfc4115_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t profile;
+ cmdline_fixed_string_t trtcm_rfc4115;
+ uint16_t port_id;
+ uint32_t profile_id;
+ uint64_t cir;
+ uint64_t eir;
+ uint64_t cbs;
+ uint64_t ebs;
+};
+
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result, add,
+ "add");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ meter, "meter");
+cmdline_parse_token_string_t cmd_add_port_meter_profile_trtcm_rfc4115_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ profile, "profile");
+cmdline_parse_token_string_t
+ cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115 =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ trtcm_rfc4115, "trtcm_rfc4115");
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cir =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ cir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_eir =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ eir, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_cbs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ cbs, UINT64);
+cmdline_parse_token_num_t cmd_add_port_meter_profile_trtcm_rfc4115_ebs =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result,
+ ebs, UINT64);
+
+static void cmd_add_port_meter_profile_trtcm_rfc4115_parsed(
+ void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_meter_profile_trtcm_rfc4115_result *res =
+ parsed_result;
+ struct rte_mtr_meter_profile mp;
+ struct rte_mtr_error error;
+ uint32_t profile_id = res->profile_id;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Private shaper profile params */
+ memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+ mp.alg = RTE_MTR_TRTCM_RFC4115;
+ mp.trtcm_rfc4115.cir = res->cir;
+ mp.trtcm_rfc4115.eir = res->eir;
+ mp.trtcm_rfc4115.cbs = res->cbs;
+ mp.trtcm_rfc4115.ebs = res->ebs;
+
+ ret = rte_mtr_meter_profile_add(port_id, profile_id, &mp, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115 = {
+ .f = cmd_add_port_meter_profile_trtcm_rfc4115_parsed,
+ .data = NULL,
+ .help_str = "Add port meter profile trtcm (rfc4115)",
+ .tokens = {
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_add,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_meter,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_trtcm_rfc4115,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port_id,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_profile_id,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cir,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_eir,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_cbs,
+ (void *)&cmd_add_port_meter_profile_trtcm_rfc4115_ebs,
+ NULL,
+ },
+};
+
+/* *** Delete Port Meter Profile *** */
+struct cmd_del_port_meter_profile_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_profile_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_profile_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_profile_result,
+ meter, "meter");
+cmdline_parse_token_string_t cmd_del_port_meter_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_meter_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_meter_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_profile_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_meter_profile_result,
+ profile_id, UINT32);
+
+static void cmd_del_port_meter_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_meter_profile_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint32_t profile_id = res->profile_id;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Delete meter profile */
+ ret = rte_mtr_meter_profile_delete(port_id, profile_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_meter_profile = {
+ .f = cmd_del_port_meter_profile_parsed,
+ .data = NULL,
+ .help_str = "Delete port meter profile",
+ .tokens = {
+ (void *)&cmd_del_port_meter_profile_del,
+ (void *)&cmd_del_port_meter_profile_port,
+ (void *)&cmd_del_port_meter_profile_meter,
+ (void *)&cmd_del_port_meter_profile_profile,
+ (void *)&cmd_del_port_meter_profile_port_id,
+ (void *)&cmd_del_port_meter_profile_profile_id,
+ NULL,
+ },
+};
+
+/* *** Create Port Meter Object *** */
+struct cmd_create_port_meter_result {
+ cmdline_fixed_string_t create;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ uint16_t port_id;
+ uint32_t mtr_id;
+ uint32_t profile_id;
+ cmdline_fixed_string_t meter_enable;
+ cmdline_fixed_string_t g_action;
+ cmdline_fixed_string_t y_action;
+ cmdline_fixed_string_t r_action;
+ uint64_t statistics_mask;
+ uint32_t shared;
+ cmdline_multi_string_t meter_input_color;
+};
+
+cmdline_parse_token_string_t cmd_create_port_meter_create =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_create_port_meter_result, create, "create");
+cmdline_parse_token_string_t cmd_create_port_meter_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_create_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_create_port_meter_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_create_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_create_port_meter_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_create_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_create_port_meter_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_create_port_meter_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_create_port_meter_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_create_port_meter_result, profile_id, UINT32);
+cmdline_parse_token_string_t cmd_create_port_meter_meter_enable =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
+ meter_enable, "yes#no");
+cmdline_parse_token_string_t cmd_create_port_meter_g_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
+ g_action, "R#Y#G#D#r#y#g#d");
+cmdline_parse_token_string_t cmd_create_port_meter_y_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
+ y_action, "R#Y#G#D#r#y#g#d");
+cmdline_parse_token_string_t cmd_create_port_meter_r_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
+ r_action, "R#Y#G#D#r#y#g#d");
+cmdline_parse_token_num_t cmd_create_port_meter_statistics_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_port_meter_result,
+ statistics_mask, UINT64);
+cmdline_parse_token_num_t cmd_create_port_meter_shared =
+ TOKEN_NUM_INITIALIZER(struct cmd_create_port_meter_result,
+ shared, UINT32);
+cmdline_parse_token_string_t cmd_create_port_meter_input_color =
+ TOKEN_STRING_INITIALIZER(struct cmd_create_port_meter_result,
+ meter_input_color, TOKEN_STRING_MULTI);
+
+static void cmd_create_port_meter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_create_port_meter_result *res = parsed_result;
+ struct rte_mtr_error error;
+ struct rte_mtr_params params;
+ uint32_t mtr_id = res->mtr_id;
+ uint32_t shared = res->shared;
+ uint32_t use_prev_meter_color = 0;
+ uint16_t port_id = res->port_id;
+ enum rte_color *dscp_table = NULL;
+ char *c_str = res->meter_input_color;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Meter params */
+ memset(&params, 0, sizeof(struct rte_mtr_params));
+ params.meter_profile_id = res->profile_id;
+
+ /* Parse meter input color string params */
+ ret = parse_meter_color_str(c_str, &use_prev_meter_color, &dscp_table);
+ if (ret) {
+ printf(" Meter input color params string parse error\n");
+ return;
+ }
+
+ params.use_prev_mtr_color = use_prev_meter_color;
+ params.dscp_table = dscp_table;
+
+ if (strcmp(res->meter_enable, "yes") == 0)
+ params.meter_enable = 1;
+ else
+ params.meter_enable = 0;
+
+ params.action[RTE_COLOR_GREEN] =
+ string_to_policer_action(res->g_action);
+ params.action[RTE_COLOR_YELLOW] =
+ string_to_policer_action(res->y_action);
+ params.action[RTE_COLOR_RED] =
+ string_to_policer_action(res->r_action);
+ params.stats_mask = res->statistics_mask;
+
+ ret = rte_mtr_create(port_id, mtr_id, &params, shared, &error);
+ if (ret != 0) {
+ free(dscp_table);
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_create_port_meter = {
+ .f = cmd_create_port_meter_parsed,
+ .data = NULL,
+ .help_str = "Create port meter",
+ .tokens = {
+ (void *)&cmd_create_port_meter_create,
+ (void *)&cmd_create_port_meter_port,
+ (void *)&cmd_create_port_meter_meter,
+ (void *)&cmd_create_port_meter_port_id,
+ (void *)&cmd_create_port_meter_mtr_id,
+ (void *)&cmd_create_port_meter_profile_id,
+ (void *)&cmd_create_port_meter_meter_enable,
+ (void *)&cmd_create_port_meter_g_action,
+ (void *)&cmd_create_port_meter_y_action,
+ (void *)&cmd_create_port_meter_r_action,
+ (void *)&cmd_create_port_meter_statistics_mask,
+ (void *)&cmd_create_port_meter_shared,
+ (void *)&cmd_create_port_meter_input_color,
+ NULL,
+ },
+};
+
+/* *** Enable Meter of MTR Object *** */
+struct cmd_enable_port_meter_result {
+ cmdline_fixed_string_t enable;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ uint16_t port_id;
+ uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_enable_port_meter_enable =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_enable_port_meter_result, enable, "enable");
+cmdline_parse_token_string_t cmd_enable_port_meter_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_enable_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_enable_port_meter_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_enable_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_enable_port_meter_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_enable_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_enable_port_meter_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_enable_port_meter_result, mtr_id, UINT32);
+
+static void cmd_enable_port_meter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_enable_port_meter_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint16_t port_id = res->port_id;
+
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Enable Meter */
+ ret = rte_mtr_meter_enable(port_id, mtr_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_enable_port_meter = {
+ .f = cmd_enable_port_meter_parsed,
+ .data = NULL,
+ .help_str = "Enable port meter",
+ .tokens = {
+ (void *)&cmd_enable_port_meter_enable,
+ (void *)&cmd_enable_port_meter_port,
+ (void *)&cmd_enable_port_meter_meter,
+ (void *)&cmd_enable_port_meter_port_id,
+ (void *)&cmd_enable_port_meter_mtr_id,
+ NULL,
+ },
+};
+
+/* *** Disable Meter of MTR Object *** */
+struct cmd_disable_port_meter_result {
+ cmdline_fixed_string_t disable;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ uint16_t port_id;
+ uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_disable_port_meter_disable =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_disable_port_meter_result, disable, "disable");
+cmdline_parse_token_string_t cmd_disable_port_meter_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_disable_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_disable_port_meter_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_disable_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_disable_port_meter_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_disable_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_disable_port_meter_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_disable_port_meter_result, mtr_id, UINT32);
+
+static void cmd_disable_port_meter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_disable_port_meter_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint16_t port_id = res->port_id;
+
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Disable Meter */
+ ret = rte_mtr_meter_disable(port_id, mtr_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_disable_port_meter = {
+ .f = cmd_disable_port_meter_parsed,
+ .data = NULL,
+ .help_str = "Disable port meter",
+ .tokens = {
+ (void *)&cmd_disable_port_meter_disable,
+ (void *)&cmd_disable_port_meter_port,
+ (void *)&cmd_disable_port_meter_meter,
+ (void *)&cmd_disable_port_meter_port_id,
+ (void *)&cmd_disable_port_meter_mtr_id,
+ NULL,
+ },
+};
+
+/* *** Delete Port Meter Object *** */
+struct cmd_del_port_meter_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ uint16_t port_id;
+ uint32_t mtr_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_meter_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_meter_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_meter_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_meter_result, meter, "meter");
+cmdline_parse_token_num_t cmd_del_port_meter_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_meter_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_meter_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_meter_result, mtr_id, UINT32);
+
+static void cmd_del_port_meter_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_meter_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint16_t port_id = res->port_id;
+
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Destroy Meter */
+ ret = rte_mtr_destroy(port_id, mtr_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_meter = {
+ .f = cmd_del_port_meter_parsed,
+ .data = NULL,
+ .help_str = "Delete port meter",
+ .tokens = {
+ (void *)&cmd_del_port_meter_del,
+ (void *)&cmd_del_port_meter_port,
+ (void *)&cmd_del_port_meter_meter,
+ (void *)&cmd_del_port_meter_port_id,
+ (void *)&cmd_del_port_meter_mtr_id,
+ NULL,
+ },
+};
+
+/* *** Set Port Meter Profile *** */
+struct cmd_set_port_meter_profile_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t mtr_id;
+ uint32_t profile_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_profile_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, profile, "profile");
+cmdline_parse_token_num_t cmd_set_port_meter_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_profile_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_profile_result, profile_id, UINT32);
+
+static void cmd_set_port_meter_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_meter_profile_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint32_t profile_id = res->profile_id;
+ uint16_t port_id = res->port_id;
+
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Set meter profile */
+ ret = rte_mtr_meter_profile_update(port_id, mtr_id,
+ profile_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_profile = {
+ .f = cmd_set_port_meter_profile_parsed,
+ .data = NULL,
+ .help_str = "Set port meter profile",
+ .tokens = {
+ (void *)&cmd_set_port_meter_profile_set,
+ (void *)&cmd_set_port_meter_profile_port,
+ (void *)&cmd_set_port_meter_profile_meter,
+ (void *)&cmd_set_port_meter_profile_profile,
+ (void *)&cmd_set_port_meter_profile_port_id,
+ (void *)&cmd_set_port_meter_profile_mtr_id,
+ (void *)&cmd_set_port_meter_profile_profile_id,
+ NULL,
+ },
+};
+
+/* *** Set Port Meter DSCP Table *** */
+struct cmd_set_port_meter_dscp_table_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t dscp_table;
+ cmdline_multi_string_t token_string;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_dscp_table_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_dscp_table_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_dscp_table_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_dscp_table_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_dscp_table_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_dscp_table_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_dscp_table_dscp_table =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_dscp_table_result,
+ dscp_table, "dscp table");
+cmdline_parse_token_string_t cmd_set_port_meter_dscp_table_token_string =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_meter_dscp_table_result,
+ token_string, TOKEN_STRING_MULTI);
+
+static void cmd_set_port_meter_dscp_table_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_meter_dscp_table_result *res = parsed_result;
+ struct rte_mtr_error error;
+ enum rte_color *dscp_table = NULL;
+ char *t_str = res->token_string;
+ uint32_t mtr_id = 0;
+ uint16_t port_id;
+ int ret;
+
+ /* Parse string */
+ ret = parse_multi_token_string(t_str, &port_id, &mtr_id, &dscp_table);
+ if (ret) {
+ printf(" Multi token string parse error\n");
+ return;
+ }
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ goto free_table;
+
+ /* Update Meter DSCP Table*/
+ ret = rte_mtr_meter_dscp_table_update(port_id, mtr_id,
+ dscp_table, &error);
+ if (ret != 0)
+ print_err_msg(&error);
+
+free_table:
+ free(dscp_table);
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {
+ .f = cmd_set_port_meter_dscp_table_parsed,
+ .data = NULL,
+ .help_str = "Update port meter dscp table",
+ .tokens = {
+ (void *)&cmd_set_port_meter_dscp_table_set,
+ (void *)&cmd_set_port_meter_dscp_table_port,
+ (void *)&cmd_set_port_meter_dscp_table_meter,
+ (void *)&cmd_set_port_meter_dscp_table_dscp_table,
+ (void *)&cmd_set_port_meter_dscp_table_token_string,
+ NULL,
+ },
+};
+
+/* *** Set Port Meter Policer Action *** */
+struct cmd_set_port_meter_policer_action_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t policer;
+ cmdline_fixed_string_t action;
+ uint16_t port_id;
+ uint32_t mtr_id;
+ uint32_t action_mask;
+ cmdline_multi_string_t policer_action;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, meter,
+ "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, policer,
+ "policer");
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_action =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, action,
+ "action");
+cmdline_parse_token_num_t cmd_set_port_meter_policer_action_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, port_id,
+ UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_policer_action_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, mtr_id,
+ UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_policer_action_action_mask =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result, action_mask,
+ UINT32);
+cmdline_parse_token_string_t cmd_set_port_meter_policer_action_policer_action =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_policer_action_result,
+ policer_action, TOKEN_STRING_MULTI);
+
+static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_meter_policer_action_result *res = parsed_result;
+ enum rte_mtr_policer_action *actions;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint32_t action_mask = res->action_mask;
+ uint16_t port_id = res->port_id;
+ char *p_str = res->policer_action;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Check: action mask */
+ if (action_mask == 0 || (action_mask & (~0x7UL))) {
+ printf(" Policer action mask not correct (error)\n");
+ return;
+ }
+
+ /* Allocate memory for policer actions */
+ actions = (enum rte_mtr_policer_action *)malloc(RTE_COLORS *
+ sizeof(enum rte_mtr_policer_action));
+ if (actions == NULL) {
+ printf("Memory for policer actions not allocated (error)\n");
+ return;
+ }
+ /* Parse policer action string */
+ ret = parse_policer_action_string(p_str, action_mask, actions);
+ if (ret) {
+ printf(" Policer action string parse error\n");
+ free(actions);
+ return;
+ }
+
+ ret = rte_mtr_policer_actions_update(port_id, mtr_id,
+ action_mask, actions, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+
+ free(actions);
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
+ .f = cmd_set_port_meter_policer_action_parsed,
+ .data = NULL,
+ .help_str = "Set port meter policer action",
+ .tokens = {
+ (void *)&cmd_set_port_meter_policer_action_set,
+ (void *)&cmd_set_port_meter_policer_action_port,
+ (void *)&cmd_set_port_meter_policer_action_meter,
+ (void *)&cmd_set_port_meter_policer_action_policer,
+ (void *)&cmd_set_port_meter_policer_action_action,
+ (void *)&cmd_set_port_meter_policer_action_port_id,
+ (void *)&cmd_set_port_meter_policer_action_mtr_id,
+ (void *)&cmd_set_port_meter_policer_action_action_mask,
+ (void *)&cmd_set_port_meter_policer_action_policer_action,
+ NULL,
+ },
+};
+
+/* *** Set Port Meter Stats Mask *** */
+struct cmd_set_port_meter_stats_mask_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t stats;
+ cmdline_fixed_string_t mask;
+ uint16_t port_id;
+ uint32_t mtr_id;
+ uint64_t stats_mask;
+};
+
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, meter, "meter");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_stats =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, stats, "stats");
+cmdline_parse_token_string_t cmd_set_port_meter_stats_mask_mask =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, mask, "mask");
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, mtr_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_meter_stats_mask_stats_mask =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_meter_stats_mask_result, stats_mask,
+ UINT64);
+
+static void cmd_set_port_meter_stats_mask_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_meter_stats_mask_result *res = parsed_result;
+ struct rte_mtr_error error;
+ uint64_t stats_mask = res->stats_mask;
+ uint32_t mtr_id = res->mtr_id;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_mtr_stats_update(port_id, mtr_id, stats_mask, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_set_port_meter_stats_mask = {
+ .f = cmd_set_port_meter_stats_mask_parsed,
+ .data = NULL,
+ .help_str = "Set port meter stats mask",
+ .tokens = {
+ (void *)&cmd_set_port_meter_stats_mask_set,
+ (void *)&cmd_set_port_meter_stats_mask_port,
+ (void *)&cmd_set_port_meter_stats_mask_meter,
+ (void *)&cmd_set_port_meter_stats_mask_stats,
+ (void *)&cmd_set_port_meter_stats_mask_mask,
+ (void *)&cmd_set_port_meter_stats_mask_port_id,
+ (void *)&cmd_set_port_meter_stats_mask_mtr_id,
+ (void *)&cmd_set_port_meter_stats_mask_stats_mask,
+ NULL,
+ },
+};
+
+/* *** Show Port Meter Stats *** */
+struct cmd_show_port_meter_stats_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t meter;
+ cmdline_fixed_string_t stats;
+ uint16_t port_id;
+ uint32_t mtr_id;
+ cmdline_fixed_string_t clear;
+};
+
+cmdline_parse_token_string_t cmd_show_port_meter_stats_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_meter =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, meter, "meter");
+cmdline_parse_token_string_t cmd_show_port_meter_stats_stats =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, stats, "stats");
+cmdline_parse_token_num_t cmd_show_port_meter_stats_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_meter_stats_mtr_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, mtr_id, UINT32);
+cmdline_parse_token_string_t cmd_show_port_meter_stats_clear =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_meter_stats_result, clear, "yes#no");
+
+static void cmd_show_port_meter_stats_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_meter_stats_result *res = parsed_result;
+ struct rte_mtr_stats stats;
+ uint64_t stats_mask = 0;
+ struct rte_mtr_error error;
+ uint32_t mtr_id = res->mtr_id;
+ uint32_t clear = 0;
+ uint16_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ if (strcmp(res->clear, "yes") == 0)
+ clear = 1;
+
+ memset(&stats, 0, sizeof(struct rte_mtr_stats));
+ ret = rte_mtr_stats_read(port_id, mtr_id, &stats,
+ &stats_mask, clear, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+
+ /* Display stats */
+ if (stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
+ printf("\tPkts G: %" PRIu64 "\n",
+ stats.n_pkts[RTE_COLOR_GREEN]);
+ if (stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
+ printf("\tBytes G: %" PRIu64 "\n",
+ stats.n_bytes[RTE_COLOR_GREEN]);
+ if (stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
+ printf("\tPkts Y: %" PRIu64 "\n",
+ stats.n_pkts[RTE_COLOR_YELLOW]);
+ if (stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
+ printf("\tBytes Y: %" PRIu64 "\n",
+ stats.n_bytes[RTE_COLOR_YELLOW]);
+ if (stats_mask & RTE_MTR_STATS_N_PKTS_RED)
+ printf("\tPkts R: %" PRIu64 "\n",
+ stats.n_pkts[RTE_COLOR_RED]);
+ if (stats_mask & RTE_MTR_STATS_N_BYTES_RED)
+ printf("\tBytes R: %" PRIu64 "\n",
+ stats.n_bytes[RTE_COLOR_RED]);
+ if (stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
+ printf("\tPkts DROPPED: %" PRIu64 "\n",
+ stats.n_pkts_dropped);
+ if (stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
+ printf("\tBytes DROPPED: %" PRIu64 "\n",
+ stats.n_bytes_dropped);
+}
+
+cmdline_parse_inst_t cmd_show_port_meter_stats = {
+ .f = cmd_show_port_meter_stats_parsed,
+ .data = NULL,
+ .help_str = "Show port meter stats",
+ .tokens = {
+ (void *)&cmd_show_port_meter_stats_show,
+ (void *)&cmd_show_port_meter_stats_port,
+ (void *)&cmd_show_port_meter_stats_meter,
+ (void *)&cmd_show_port_meter_stats_stats,
+ (void *)&cmd_show_port_meter_stats_port_id,
+ (void *)&cmd_show_port_meter_stats_mtr_id,
+ (void *)&cmd_show_port_meter_stats_clear,
+ NULL,
+ },
+};
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline_mtr.h b/src/spdk/dpdk/app/test-pmd/cmdline_mtr.h
new file mode 100644
index 000000000..e69d6da02
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline_mtr.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _CMDLINE_MTR_H_
+#define _CMDLINE_MTR_H_
+
+/* Traffic Metering and Policing */
+extern cmdline_parse_inst_t cmd_show_port_meter_cap;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm;
+extern cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115;
+extern cmdline_parse_inst_t cmd_del_port_meter_profile;
+extern cmdline_parse_inst_t cmd_create_port_meter;
+extern cmdline_parse_inst_t cmd_enable_port_meter;
+extern cmdline_parse_inst_t cmd_disable_port_meter;
+extern cmdline_parse_inst_t cmd_del_port_meter;
+extern cmdline_parse_inst_t cmd_set_port_meter_profile;
+extern cmdline_parse_inst_t cmd_set_port_meter_dscp_table;
+extern cmdline_parse_inst_t cmd_set_port_meter_policer_action;
+extern cmdline_parse_inst_t cmd_set_port_meter_stats_mask;
+extern cmdline_parse_inst_t cmd_show_port_meter_stats;
+
+#endif /* _CMDLINE_MTR_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline_tm.c b/src/spdk/dpdk/app/test-pmd/cmdline_tm.c
new file mode 100644
index 000000000..6951beb58
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline_tm.c
@@ -0,0 +1,2463 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_tm.h>
+
+#include "testpmd.h"
+#include "cmdline_tm.h"
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+#define MAX_NUM_SHARED_SHAPERS 256
+
+#define skip_white_spaces(pos) \
+({ \
+ __typeof__(pos) _p = (pos); \
+ for ( ; isspace(*_p); _p++) \
+ ; \
+ _p; \
+})
+
+/** Display TM Error Message */
+static void
+print_err_msg(struct rte_tm_error *error)
+{
+ static const char *const errstrlist[] = {
+ [RTE_TM_ERROR_TYPE_NONE] = "no error",
+ [RTE_TM_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+ [RTE_TM_ERROR_TYPE_CAPABILITIES]
+ = "capability parameter null",
+ [RTE_TM_ERROR_TYPE_LEVEL_ID] = "level id",
+ [RTE_TM_ERROR_TYPE_WRED_PROFILE]
+ = "wred profile null",
+ [RTE_TM_ERROR_TYPE_WRED_PROFILE_GREEN] = "wred profile(green)",
+ [RTE_TM_ERROR_TYPE_WRED_PROFILE_YELLOW]
+ = "wred profile(yellow)",
+ [RTE_TM_ERROR_TYPE_WRED_PROFILE_RED] = "wred profile(red)",
+ [RTE_TM_ERROR_TYPE_WRED_PROFILE_ID] = "wred profile id",
+ [RTE_TM_ERROR_TYPE_SHARED_WRED_CONTEXT_ID]
+ = "shared wred context id",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE] = "shaper profile null",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE]
+ = "committed rate field (shaper profile)",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE]
+ = "committed size field (shaper profile)",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE]
+ = "peak rate field (shaper profile)",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE]
+ = "peak size field (shaper profile)",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN]
+ = "packet adjust length field (shaper profile)",
+ [RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID] = "shaper profile id",
+ [RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID] = "shared shaper id",
+ [RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID] = "parent node id",
+ [RTE_TM_ERROR_TYPE_NODE_PRIORITY] = "node priority",
+ [RTE_TM_ERROR_TYPE_NODE_WEIGHT] = "node weight",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS] = "node parameter null",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID]
+ = "shaper profile id field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID]
+ = "shared shaper id field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS]
+ = "num shared shapers field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE]
+ = "wfq weght mode field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES]
+ = "num strict priorities field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN]
+ = "congestion management mode field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID] =
+ "wred profile id field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID]
+ = "shared wred context id field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS]
+ = "num shared wred contexts field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS]
+ = "stats field (node params)",
+ [RTE_TM_ERROR_TYPE_NODE_ID] = "node id",
+ };
+
+ const char *errstr;
+ char buf[64];
+
+ if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+ !errstrlist[error->type])
+ errstr = "unknown type";
+ else
+ errstr = errstrlist[error->type];
+
+ if (error->cause)
+ snprintf(buf, sizeof(buf), "cause: %p, ", error->cause);
+
+ printf("%s: %s%s (error %d)\n", errstr, error->cause ? buf : "",
+ error->message ? error->message : "(no stated reason)",
+ error->type);
+}
+
+static int
+read_uint64(uint64_t *value, const char *p)
+{
+ char *next;
+ uint64_t val;
+
+ p = skip_white_spaces(p);
+ if (!isdigit(*p))
+ return -EINVAL;
+
+ val = strtoul(p, &next, 10);
+ if (p == next)
+ return -EINVAL;
+
+ p = next;
+ switch (*p) {
+ case 'T':
+ val *= 1024ULL;
+ /* fall through */
+ case 'G':
+ val *= 1024ULL;
+ /* fall through */
+ case 'M':
+ val *= 1024ULL;
+ /* fall through */
+ case 'k':
+ case 'K':
+ val *= 1024ULL;
+ p++;
+ break;
+ }
+
+ p = skip_white_spaces(p);
+ if (*p != '\0')
+ return -EINVAL;
+
+ *value = val;
+ return 0;
+}
+
+static int
+read_uint32(uint32_t *value, const char *p)
+{
+ uint64_t val = 0;
+ int ret = read_uint64(&val, p);
+
+ if (ret < 0)
+ return ret;
+
+ if (val > UINT32_MAX)
+ return -ERANGE;
+
+ *value = val;
+ return 0;
+}
+
+static int
+parse_multi_ss_id_str(char *s_str, uint32_t *n_ssp, uint32_t shaper_id[])
+{
+ uint32_t n_shared_shapers = 0, i = 0;
+ char *token;
+
+ /* First token: num of shared shapers */
+ token = strtok_r(s_str, PARSE_DELIMITER, &s_str);
+ if (token == NULL)
+ return -1;
+
+ if (read_uint32(&n_shared_shapers, token))
+ return -1;
+
+ /* Check: num of shared shaper */
+ if (n_shared_shapers >= MAX_NUM_SHARED_SHAPERS) {
+ printf(" Number of shared shapers exceed the max (error)\n");
+ return -1;
+ }
+
+ /* Parse shared shaper ids */
+ while (1) {
+ token = strtok_r(s_str, PARSE_DELIMITER, &s_str);
+ if ((token != NULL && n_shared_shapers == 0) ||
+ (token == NULL && i < n_shared_shapers))
+ return -1;
+
+ if (token == NULL)
+ break;
+
+ if (read_uint32(&shaper_id[i], token))
+ return -1;
+ i++;
+ }
+ *n_ssp = n_shared_shapers;
+
+ return 0;
+}
+/* *** Port TM Capability *** */
+struct cmd_show_port_tm_cap_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t cap;
+ uint16_t port_id;
+};
+
+cmdline_parse_token_string_t cmd_show_port_tm_cap_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_cap_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_port_tm_cap_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_cap_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_show_port_tm_cap_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_cap_result,
+ tm, "tm");
+cmdline_parse_token_string_t cmd_show_port_tm_cap_cap =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_cap_result,
+ cap, "cap");
+cmdline_parse_token_num_t cmd_show_port_tm_cap_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_cap_result,
+ port_id, UINT16);
+
+static void cmd_show_port_tm_cap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_tm_cap_result *res = parsed_result;
+ struct rte_tm_capabilities cap;
+ struct rte_tm_error error;
+ portid_t port_id = res->port_id;
+ uint32_t i;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&cap, 0, sizeof(struct rte_tm_capabilities));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_capabilities_get(port_id, &cap, &error);
+ if (ret) {
+ print_err_msg(&error);
+ return;
+ }
+
+ printf("\n**** Port TM Capabilities ****\n\n");
+ printf("cap.n_nodes_max %" PRIu32 "\n", cap.n_nodes_max);
+ printf("cap.n_levels_max %" PRIu32 "\n", cap.n_levels_max);
+ printf("cap.non_leaf_nodes_identical %" PRId32 "\n",
+ cap.non_leaf_nodes_identical);
+ printf("cap.leaf_nodes_identical %" PRId32 "\n",
+ cap.leaf_nodes_identical);
+ printf("cap.shaper_n_max %u\n", cap.shaper_n_max);
+ printf("cap.shaper_private_n_max %" PRIu32 "\n",
+ cap.shaper_private_n_max);
+ printf("cap.shaper_private_dual_rate_n_max %" PRId32 "\n",
+ cap.shaper_private_dual_rate_n_max);
+ printf("cap.shaper_private_rate_min %" PRIu64 "\n",
+ cap.shaper_private_rate_min);
+ printf("cap.shaper_private_rate_max %" PRIu64 "\n",
+ cap.shaper_private_rate_max);
+ printf("cap.shaper_shared_n_max %" PRIu32 "\n",
+ cap.shaper_shared_n_max);
+ printf("cap.shaper_shared_n_nodes_per_shaper_max %" PRIu32 "\n",
+ cap.shaper_shared_n_nodes_per_shaper_max);
+ printf("cap.shaper_shared_n_shapers_per_node_max %" PRIu32 "\n",
+ cap.shaper_shared_n_shapers_per_node_max);
+ printf("cap.shaper_shared_dual_rate_n_max %" PRIu32 "\n",
+ cap.shaper_shared_dual_rate_n_max);
+ printf("cap.shaper_shared_rate_min %" PRIu64 "\n",
+ cap.shaper_shared_rate_min);
+ printf("cap.shaper_shared_rate_max %" PRIu64 "\n",
+ cap.shaper_shared_rate_max);
+ printf("cap.shaper_pkt_length_adjust_min %" PRId32 "\n",
+ cap.shaper_pkt_length_adjust_min);
+ printf("cap.shaper_pkt_length_adjust_max %" PRId32 "\n",
+ cap.shaper_pkt_length_adjust_max);
+ printf("cap.sched_n_children_max %" PRIu32 "\n",
+ cap.sched_n_children_max);
+ printf("cap.sched_sp_n_priorities_max %" PRIu32 "\n",
+ cap.sched_sp_n_priorities_max);
+ printf("cap.sched_wfq_n_children_per_group_max %" PRIu32 "\n",
+ cap.sched_wfq_n_children_per_group_max);
+ printf("cap.sched_wfq_n_groups_max %" PRIu32 "\n",
+ cap.sched_wfq_n_groups_max);
+ printf("cap.sched_wfq_weight_max %" PRIu32 "\n",
+ cap.sched_wfq_weight_max);
+ printf("cap.cman_head_drop_supported %" PRId32 "\n",
+ cap.cman_head_drop_supported);
+ printf("cap.cman_wred_context_n_max %" PRIu32 "\n",
+ cap.cman_wred_context_n_max);
+ printf("cap.cman_wred_context_private_n_max %" PRIu32 "\n",
+ cap.cman_wred_context_private_n_max);
+ printf("cap.cman_wred_context_shared_n_max %" PRIu32 "\n",
+ cap.cman_wred_context_shared_n_max);
+ printf("cap.cman_wred_context_shared_n_nodes_per_context_max %" PRIu32
+ "\n", cap.cman_wred_context_shared_n_nodes_per_context_max);
+ printf("cap.cman_wred_context_shared_n_contexts_per_node_max %" PRIu32
+ "\n", cap.cman_wred_context_shared_n_contexts_per_node_max);
+
+ for (i = 0; i < RTE_COLORS; i++) {
+ printf("cap.mark_vlan_dei_supported %" PRId32 "\n",
+ cap.mark_vlan_dei_supported[i]);
+ printf("cap.mark_ip_ecn_tcp_supported %" PRId32 "\n",
+ cap.mark_ip_ecn_tcp_supported[i]);
+ printf("cap.mark_ip_ecn_sctp_supported %" PRId32 "\n",
+ cap.mark_ip_ecn_sctp_supported[i]);
+ printf("cap.mark_ip_dscp_supported %" PRId32 "\n",
+ cap.mark_ip_dscp_supported[i]);
+ }
+
+ printf("cap.dynamic_update_mask %" PRIx64 "\n",
+ cap.dynamic_update_mask);
+ printf("cap.stats_mask %" PRIx64 "\n", cap.stats_mask);
+}
+
+cmdline_parse_inst_t cmd_show_port_tm_cap = {
+ .f = cmd_show_port_tm_cap_parsed,
+ .data = NULL,
+ .help_str = "Show Port TM Capabilities",
+ .tokens = {
+ (void *)&cmd_show_port_tm_cap_show,
+ (void *)&cmd_show_port_tm_cap_port,
+ (void *)&cmd_show_port_tm_cap_tm,
+ (void *)&cmd_show_port_tm_cap_cap,
+ (void *)&cmd_show_port_tm_cap_port_id,
+ NULL,
+ },
+};
+
+/* *** Port TM Hierarchical Level Capability *** */
+struct cmd_show_port_tm_level_cap_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t level;
+ cmdline_fixed_string_t cap;
+ uint16_t port_id;
+ uint32_t level_id;
+};
+
+cmdline_parse_token_string_t cmd_show_port_tm_level_cap_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_port_tm_level_cap_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_show_port_tm_level_cap_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ tm, "tm");
+cmdline_parse_token_string_t cmd_show_port_tm_level_cap_level =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ level, "level");
+cmdline_parse_token_string_t cmd_show_port_tm_level_cap_cap =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ cap, "cap");
+cmdline_parse_token_num_t cmd_show_port_tm_level_cap_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_tm_level_cap_level_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_level_cap_result,
+ level_id, UINT32);
+
+
+static void cmd_show_port_tm_level_cap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_tm_level_cap_result *res = parsed_result;
+ struct rte_tm_level_capabilities lcap;
+ struct rte_tm_error error;
+ portid_t port_id = res->port_id;
+ uint32_t level_id = res->level_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&lcap, 0, sizeof(struct rte_tm_level_capabilities));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_level_capabilities_get(port_id, level_id, &lcap, &error);
+ if (ret) {
+ print_err_msg(&error);
+ return;
+ }
+ printf("\n** Port TM Hierarchy level %" PRIu32 " Capability **\n\n",
+ level_id);
+
+ printf("cap.n_nodes_max %" PRIu32 "\n", lcap.n_nodes_max);
+ printf("cap.n_nodes_nonleaf_max %" PRIu32 "\n",
+ lcap.n_nodes_nonleaf_max);
+ printf("cap.n_nodes_leaf_max %" PRIu32 "\n", lcap.n_nodes_leaf_max);
+ printf("cap.non_leaf_nodes_identical %" PRId32 "\n",
+ lcap.non_leaf_nodes_identical);
+ printf("cap.leaf_nodes_identical %" PRId32 "\n",
+ lcap.leaf_nodes_identical);
+ if (level_id <= 3) {
+ printf("cap.nonleaf.shaper_private_supported %" PRId32 "\n",
+ lcap.nonleaf.shaper_private_supported);
+ printf("cap.nonleaf.shaper_private_dual_rate_supported %" PRId32
+ "\n", lcap.nonleaf.shaper_private_dual_rate_supported);
+ printf("cap.nonleaf.shaper_private_rate_min %" PRIu64 "\n",
+ lcap.nonleaf.shaper_private_rate_min);
+ printf("cap.nonleaf.shaper_private_rate_max %" PRIu64 "\n",
+ lcap.nonleaf.shaper_private_rate_max);
+ printf("cap.nonleaf.shaper_shared_n_max %" PRIu32 "\n",
+ lcap.nonleaf.shaper_shared_n_max);
+ printf("cap.nonleaf.sched_n_children_max %" PRIu32 "\n",
+ lcap.nonleaf.sched_n_children_max);
+ printf("cap.nonleaf.sched_sp_n_priorities_max %" PRIu32 "\n",
+ lcap.nonleaf.sched_sp_n_priorities_max);
+ printf("cap.nonleaf.sched_wfq_n_children_per_group_max %" PRIu32
+ "\n", lcap.nonleaf.sched_wfq_n_children_per_group_max);
+ printf("cap.nonleaf.sched_wfq_n_groups_max %" PRIu32 "\n",
+ lcap.nonleaf.sched_wfq_n_groups_max);
+ printf("cap.nonleaf.sched_wfq_weight_max %" PRIu32 "\n",
+ lcap.nonleaf.sched_wfq_weight_max);
+ printf("cap.nonleaf.stats_mask %" PRIx64 "\n",
+ lcap.nonleaf.stats_mask);
+ } else {
+ printf("cap.leaf.shaper_private_supported %" PRId32 "\n",
+ lcap.leaf.shaper_private_supported);
+ printf("cap.leaf.shaper_private_dual_rate_supported %" PRId32
+ "\n", lcap.leaf.shaper_private_dual_rate_supported);
+ printf("cap.leaf.shaper_private_rate_min %" PRIu64 "\n",
+ lcap.leaf.shaper_private_rate_min);
+ printf("cap.leaf.shaper_private_rate_max %" PRIu64 "\n",
+ lcap.leaf.shaper_private_rate_max);
+ printf("cap.leaf.shaper_shared_n_max %" PRIu32 "\n",
+ lcap.leaf.shaper_shared_n_max);
+ printf("cap.leaf.cman_head_drop_supported %" PRId32 "\n",
+ lcap.leaf.cman_head_drop_supported);
+ printf("cap.leaf.cman_wred_context_private_supported %" PRId32
+ "\n", lcap.leaf.cman_wred_context_private_supported);
+ printf("cap.leaf.cman_wred_context_shared_n_max %" PRIu32 "\n",
+ lcap.leaf.cman_wred_context_shared_n_max);
+ printf("cap.leaf.stats_mask %" PRIx64 "\n",
+ lcap.leaf.stats_mask);
+ }
+}
+
+cmdline_parse_inst_t cmd_show_port_tm_level_cap = {
+ .f = cmd_show_port_tm_level_cap_parsed,
+ .data = NULL,
+ .help_str = "Show Port TM Hierarhical level Capabilities",
+ .tokens = {
+ (void *)&cmd_show_port_tm_level_cap_show,
+ (void *)&cmd_show_port_tm_level_cap_port,
+ (void *)&cmd_show_port_tm_level_cap_tm,
+ (void *)&cmd_show_port_tm_level_cap_level,
+ (void *)&cmd_show_port_tm_level_cap_cap,
+ (void *)&cmd_show_port_tm_level_cap_port_id,
+ (void *)&cmd_show_port_tm_level_cap_level_id,
+ NULL,
+ },
+};
+
+/* *** Port TM Hierarchy Node Capability *** */
+struct cmd_show_port_tm_node_cap_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t cap;
+ uint16_t port_id;
+ uint32_t node_id;
+};
+
+cmdline_parse_token_string_t cmd_show_port_tm_node_cap_show =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ show, "show");
+cmdline_parse_token_string_t cmd_show_port_tm_node_cap_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_show_port_tm_node_cap_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ tm, "tm");
+cmdline_parse_token_string_t cmd_show_port_tm_node_cap_node =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ node, "node");
+cmdline_parse_token_string_t cmd_show_port_tm_node_cap_cap =
+ TOKEN_STRING_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ cap, "cap");
+cmdline_parse_token_num_t cmd_show_port_tm_node_cap_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_tm_node_cap_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_node_cap_result,
+ node_id, UINT32);
+
+static void cmd_show_port_tm_node_cap_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_tm_node_cap_result *res = parsed_result;
+ struct rte_tm_node_capabilities ncap;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ portid_t port_id = res->port_id;
+ int ret, is_leaf = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Node id must be valid */
+ ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+
+ memset(&ncap, 0, sizeof(struct rte_tm_node_capabilities));
+ ret = rte_tm_node_capabilities_get(port_id, node_id, &ncap, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+ printf("\n** Port TM Hierarchy node %" PRIu32 " Capability **\n\n",
+ node_id);
+ printf("cap.shaper_private_supported %" PRId32 "\n",
+ ncap.shaper_private_supported);
+ printf("cap.shaper_private_dual_rate_supported %" PRId32 "\n",
+ ncap.shaper_private_dual_rate_supported);
+ printf("cap.shaper_private_rate_min %" PRIu64 "\n",
+ ncap.shaper_private_rate_min);
+ printf("cap.shaper_private_rate_max %" PRIu64 "\n",
+ ncap.shaper_private_rate_max);
+ printf("cap.shaper_shared_n_max %" PRIu32 "\n",
+ ncap.shaper_shared_n_max);
+ if (!is_leaf) {
+ printf("cap.nonleaf.sched_n_children_max %" PRIu32 "\n",
+ ncap.nonleaf.sched_n_children_max);
+ printf("cap.nonleaf.sched_sp_n_priorities_max %" PRIu32 "\n",
+ ncap.nonleaf.sched_sp_n_priorities_max);
+ printf("cap.nonleaf.sched_wfq_n_children_per_group_max %" PRIu32
+ "\n", ncap.nonleaf.sched_wfq_n_children_per_group_max);
+ printf("cap.nonleaf.sched_wfq_n_groups_max %" PRIu32 "\n",
+ ncap.nonleaf.sched_wfq_n_groups_max);
+ printf("cap.nonleaf.sched_wfq_weight_max %" PRIu32 "\n",
+ ncap.nonleaf.sched_wfq_weight_max);
+ } else {
+ printf("cap.leaf.cman_head_drop_supported %" PRId32 "\n",
+ ncap.leaf.cman_head_drop_supported);
+ printf("cap.leaf.cman_wred_context_private_supported %" PRId32
+ "\n", ncap.leaf.cman_wred_context_private_supported);
+ printf("cap.leaf.cman_wred_context_shared_n_max %" PRIu32 "\n",
+ ncap.leaf.cman_wred_context_shared_n_max);
+ }
+ printf("cap.stats_mask %" PRIx64 "\n", ncap.stats_mask);
+}
+
+cmdline_parse_inst_t cmd_show_port_tm_node_cap = {
+ .f = cmd_show_port_tm_node_cap_parsed,
+ .data = NULL,
+ .help_str = "Show Port TM Hierarchy node capabilities",
+ .tokens = {
+ (void *)&cmd_show_port_tm_node_cap_show,
+ (void *)&cmd_show_port_tm_node_cap_port,
+ (void *)&cmd_show_port_tm_node_cap_tm,
+ (void *)&cmd_show_port_tm_node_cap_node,
+ (void *)&cmd_show_port_tm_node_cap_cap,
+ (void *)&cmd_show_port_tm_node_cap_port_id,
+ (void *)&cmd_show_port_tm_node_cap_node_id,
+ NULL,
+ },
+};
+
+/* *** Show Port TM Node Statistics *** */
+struct cmd_show_port_tm_node_stats_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t stats;
+ uint16_t port_id;
+ uint32_t node_id;
+ uint32_t clear;
+};
+
+cmdline_parse_token_string_t cmd_show_port_tm_node_stats_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_tm_node_stats_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_tm_node_stats_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, tm, "tm");
+cmdline_parse_token_string_t cmd_show_port_tm_node_stats_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, node, "node");
+cmdline_parse_token_string_t cmd_show_port_tm_node_stats_stats =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, stats, "stats");
+cmdline_parse_token_num_t cmd_show_port_tm_node_stats_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_show_port_tm_node_stats_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_tm_node_stats_node_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result,
+ node_id, UINT32);
+cmdline_parse_token_num_t cmd_show_port_tm_node_stats_clear =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_tm_node_stats_result, clear, UINT32);
+
+static void cmd_show_port_tm_node_stats_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_tm_node_stats_result *res = parsed_result;
+ struct rte_tm_node_stats stats;
+ struct rte_tm_error error;
+ uint64_t stats_mask = 0;
+ uint32_t node_id = res->node_id;
+ uint32_t clear = res->clear;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Port status */
+ if (!port_is_started(port_id)) {
+ printf(" Port %u not started (error)\n", port_id);
+ return;
+ }
+
+ memset(&stats, 0, sizeof(struct rte_tm_node_stats));
+ ret = rte_tm_node_stats_read(port_id, node_id, &stats,
+ &stats_mask, clear, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+
+ /* Display stats */
+ if (stats_mask & RTE_TM_STATS_N_PKTS)
+ printf("\tPkts scheduled from node: %" PRIu64 "\n",
+ stats.n_pkts);
+ if (stats_mask & RTE_TM_STATS_N_BYTES)
+ printf("\tBytes scheduled from node: %" PRIu64 "\n",
+ stats.n_bytes);
+ if (stats_mask & RTE_TM_STATS_N_PKTS_GREEN_DROPPED)
+ printf("\tPkts dropped (green): %" PRIu64 "\n",
+ stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN]);
+ if (stats_mask & RTE_TM_STATS_N_PKTS_YELLOW_DROPPED)
+ printf("\tPkts dropped (yellow): %" PRIu64 "\n",
+ stats.leaf.n_pkts_dropped[RTE_COLOR_YELLOW]);
+ if (stats_mask & RTE_TM_STATS_N_PKTS_RED_DROPPED)
+ printf("\tPkts dropped (red): %" PRIu64 "\n",
+ stats.leaf.n_pkts_dropped[RTE_COLOR_RED]);
+ if (stats_mask & RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
+ printf("\tBytes dropped (green): %" PRIu64 "\n",
+ stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN]);
+ if (stats_mask & RTE_TM_STATS_N_BYTES_YELLOW_DROPPED)
+ printf("\tBytes dropped (yellow): %" PRIu64 "\n",
+ stats.leaf.n_bytes_dropped[RTE_COLOR_YELLOW]);
+ if (stats_mask & RTE_TM_STATS_N_BYTES_RED_DROPPED)
+ printf("\tBytes dropped (red): %" PRIu64 "\n",
+ stats.leaf.n_bytes_dropped[RTE_COLOR_RED]);
+ if (stats_mask & RTE_TM_STATS_N_PKTS_QUEUED)
+ printf("\tPkts queued: %" PRIu64 "\n",
+ stats.leaf.n_pkts_queued);
+ if (stats_mask & RTE_TM_STATS_N_BYTES_QUEUED)
+ printf("\tBytes queued: %" PRIu64 "\n",
+ stats.leaf.n_bytes_queued);
+}
+
+cmdline_parse_inst_t cmd_show_port_tm_node_stats = {
+ .f = cmd_show_port_tm_node_stats_parsed,
+ .data = NULL,
+ .help_str = "Show port tm node stats",
+ .tokens = {
+ (void *)&cmd_show_port_tm_node_stats_show,
+ (void *)&cmd_show_port_tm_node_stats_port,
+ (void *)&cmd_show_port_tm_node_stats_tm,
+ (void *)&cmd_show_port_tm_node_stats_node,
+ (void *)&cmd_show_port_tm_node_stats_stats,
+ (void *)&cmd_show_port_tm_node_stats_port_id,
+ (void *)&cmd_show_port_tm_node_stats_node_id,
+ (void *)&cmd_show_port_tm_node_stats_clear,
+ NULL,
+ },
+};
+
+/* *** Show Port TM Node Type *** */
+struct cmd_show_port_tm_node_type_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t type;
+ uint16_t port_id;
+ uint32_t node_id;
+};
+
+cmdline_parse_token_string_t cmd_show_port_tm_node_type_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result, show, "show");
+cmdline_parse_token_string_t cmd_show_port_tm_node_type_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result, port, "port");
+cmdline_parse_token_string_t cmd_show_port_tm_node_type_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result, tm, "tm");
+cmdline_parse_token_string_t cmd_show_port_tm_node_type_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result, node, "node");
+cmdline_parse_token_string_t cmd_show_port_tm_node_type_type =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result, type, "type");
+cmdline_parse_token_num_t cmd_show_port_tm_node_type_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_show_port_tm_node_type_node_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_tm_node_type_result,
+ node_id, UINT32);
+
+static void cmd_show_port_tm_node_type_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_tm_node_type_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ portid_t port_id = res->port_id;
+ int ret, is_leaf = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+
+ if (is_leaf == 1)
+ printf("leaf node\n");
+ else
+ printf("nonleaf node\n");
+
+}
+
+cmdline_parse_inst_t cmd_show_port_tm_node_type = {
+ .f = cmd_show_port_tm_node_type_parsed,
+ .data = NULL,
+ .help_str = "Show port tm node type",
+ .tokens = {
+ (void *)&cmd_show_port_tm_node_type_show,
+ (void *)&cmd_show_port_tm_node_type_port,
+ (void *)&cmd_show_port_tm_node_type_tm,
+ (void *)&cmd_show_port_tm_node_type_node,
+ (void *)&cmd_show_port_tm_node_type_type,
+ (void *)&cmd_show_port_tm_node_type_port_id,
+ (void *)&cmd_show_port_tm_node_type_node_id,
+ NULL,
+ },
+};
+
+/* *** Add Port TM Private Shaper Profile *** */
+struct cmd_add_port_tm_node_shaper_profile_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t shaper;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t shaper_id;
+ uint64_t cmit_tb_rate;
+ uint64_t cmit_tb_size;
+ uint64_t peak_tb_rate;
+ uint64_t peak_tb_size;
+ uint32_t pktlen_adjust;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ node, "node");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_shaper =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ shaper, "shaper");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shaper_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_shaper_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ shaper_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_cmit_tb_rate =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ cmit_tb_rate, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_cmit_tb_size =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ cmit_tb_size, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_peak_tb_rate =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ peak_tb_rate, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_peak_tb_size =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ peak_tb_size, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shaper_profile_pktlen_adjust =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shaper_profile_result,
+ pktlen_adjust, UINT32);
+
+static void cmd_add_port_tm_node_shaper_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_tm_node_shaper_profile_result *res = parsed_result;
+ struct rte_tm_shaper_params sp;
+ struct rte_tm_error error;
+ uint32_t shaper_id = res->shaper_id;
+ uint32_t pkt_len_adjust = res->pktlen_adjust;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ /* Private shaper profile params */
+ memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ sp.committed.rate = res->cmit_tb_rate;
+ sp.committed.size = res->cmit_tb_size;
+ sp.peak.rate = res->peak_tb_rate;
+ sp.peak.size = res->peak_tb_size;
+ sp.pkt_length_adjust = pkt_len_adjust;
+
+ ret = rte_tm_shaper_profile_add(port_id, shaper_id, &sp, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_node_shaper_profile = {
+ .f = cmd_add_port_tm_node_shaper_profile_parsed,
+ .data = NULL,
+ .help_str = "Add port tm node private shaper profile",
+ .tokens = {
+ (void *)&cmd_add_port_tm_node_shaper_profile_add,
+ (void *)&cmd_add_port_tm_node_shaper_profile_port,
+ (void *)&cmd_add_port_tm_node_shaper_profile_tm,
+ (void *)&cmd_add_port_tm_node_shaper_profile_node,
+ (void *)&cmd_add_port_tm_node_shaper_profile_shaper,
+ (void *)&cmd_add_port_tm_node_shaper_profile_profile,
+ (void *)&cmd_add_port_tm_node_shaper_profile_port_id,
+ (void *)&cmd_add_port_tm_node_shaper_profile_shaper_id,
+ (void *)&cmd_add_port_tm_node_shaper_profile_cmit_tb_rate,
+ (void *)&cmd_add_port_tm_node_shaper_profile_cmit_tb_size,
+ (void *)&cmd_add_port_tm_node_shaper_profile_peak_tb_rate,
+ (void *)&cmd_add_port_tm_node_shaper_profile_peak_tb_size,
+ (void *)&cmd_add_port_tm_node_shaper_profile_pktlen_adjust,
+ NULL,
+ },
+};
+
+/* *** Delete Port TM Private Shaper Profile *** */
+struct cmd_del_port_tm_node_shaper_profile_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t shaper;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t shaper_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result, tm, "tm");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ node, "node");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_shaper =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ shaper, "shaper");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shaper_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_tm_node_shaper_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_tm_node_shaper_profile_shaper_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_shaper_profile_result,
+ shaper_id, UINT32);
+
+static void cmd_del_port_tm_node_shaper_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_tm_node_shaper_profile_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t shaper_id = res->shaper_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_shaper_profile_delete(port_id, shaper_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_tm_node_shaper_profile = {
+ .f = cmd_del_port_tm_node_shaper_profile_parsed,
+ .data = NULL,
+ .help_str = "Delete port tm node private shaper profile",
+ .tokens = {
+ (void *)&cmd_del_port_tm_node_shaper_profile_del,
+ (void *)&cmd_del_port_tm_node_shaper_profile_port,
+ (void *)&cmd_del_port_tm_node_shaper_profile_tm,
+ (void *)&cmd_del_port_tm_node_shaper_profile_node,
+ (void *)&cmd_del_port_tm_node_shaper_profile_shaper,
+ (void *)&cmd_del_port_tm_node_shaper_profile_profile,
+ (void *)&cmd_del_port_tm_node_shaper_profile_port_id,
+ (void *)&cmd_del_port_tm_node_shaper_profile_shaper_id,
+ NULL,
+ },
+};
+
+/* *** Add/Update Port TM shared Shaper *** */
+struct cmd_add_port_tm_node_shared_shaper_result {
+ cmdline_fixed_string_t cmd_type;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t shared;
+ cmdline_fixed_string_t shaper;
+ uint16_t port_id;
+ uint32_t shared_shaper_id;
+ uint32_t shaper_profile_id;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_cmd_type =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ cmd_type, "add#set");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result, port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result, tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result, node, "node");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_shared =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ shared, "shared");
+cmdline_parse_token_string_t cmd_add_port_tm_node_shared_shaper_shaper =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ shaper, "shaper");
+cmdline_parse_token_num_t cmd_add_port_tm_node_shared_shaper_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shared_shaper_shared_shaper_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ shared_shaper_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_node_shared_shaper_shaper_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_shared_shaper_result,
+ shaper_profile_id, UINT32);
+
+static void cmd_add_port_tm_node_shared_shaper_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_tm_node_shared_shaper_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t shared_shaper_id = res->shared_shaper_id;
+ uint32_t shaper_profile_id = res->shaper_profile_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Command type: add */
+ if ((strcmp(res->cmd_type, "add") == 0) &&
+ (port_is_started(port_id))) {
+ printf(" Port %u not stopped (error)\n", port_id);
+ return;
+ }
+
+ /* Command type: set (update) */
+ if ((strcmp(res->cmd_type, "set") == 0) &&
+ (!port_is_started(port_id))) {
+ printf(" Port %u not started (error)\n", port_id);
+ return;
+ }
+
+ ret = rte_tm_shared_shaper_add_update(port_id, shared_shaper_id,
+ shaper_profile_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_node_shared_shaper = {
+ .f = cmd_add_port_tm_node_shared_shaper_parsed,
+ .data = NULL,
+ .help_str = "add/update port tm node shared shaper",
+ .tokens = {
+ (void *)&cmd_add_port_tm_node_shared_shaper_cmd_type,
+ (void *)&cmd_add_port_tm_node_shared_shaper_port,
+ (void *)&cmd_add_port_tm_node_shared_shaper_tm,
+ (void *)&cmd_add_port_tm_node_shared_shaper_node,
+ (void *)&cmd_add_port_tm_node_shared_shaper_shared,
+ (void *)&cmd_add_port_tm_node_shared_shaper_shaper,
+ (void *)&cmd_add_port_tm_node_shared_shaper_port_id,
+ (void *)&cmd_add_port_tm_node_shared_shaper_shared_shaper_id,
+ (void *)&cmd_add_port_tm_node_shared_shaper_shaper_profile_id,
+ NULL,
+ },
+};
+
+/* *** Delete Port TM shared Shaper *** */
+struct cmd_del_port_tm_node_shared_shaper_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t shared;
+ cmdline_fixed_string_t shaper;
+ uint16_t port_id;
+ uint32_t shared_shaper_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result, tm, "tm");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result, node, "node");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_shared =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result,
+ shared, "shared");
+cmdline_parse_token_string_t cmd_del_port_tm_node_shared_shaper_shaper =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result,
+ shaper, "shaper");
+cmdline_parse_token_num_t cmd_del_port_tm_node_shared_shaper_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_tm_node_shared_shaper_shared_shaper_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_shared_shaper_result,
+ shared_shaper_id, UINT32);
+
+static void cmd_del_port_tm_node_shared_shaper_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_tm_node_shared_shaper_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t shared_shaper_id = res->shared_shaper_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_shared_shaper_delete(port_id, shared_shaper_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_tm_node_shared_shaper = {
+ .f = cmd_del_port_tm_node_shared_shaper_parsed,
+ .data = NULL,
+ .help_str = "delete port tm node shared shaper",
+ .tokens = {
+ (void *)&cmd_del_port_tm_node_shared_shaper_del,
+ (void *)&cmd_del_port_tm_node_shared_shaper_port,
+ (void *)&cmd_del_port_tm_node_shared_shaper_tm,
+ (void *)&cmd_del_port_tm_node_shared_shaper_node,
+ (void *)&cmd_del_port_tm_node_shared_shaper_shared,
+ (void *)&cmd_del_port_tm_node_shared_shaper_shaper,
+ (void *)&cmd_del_port_tm_node_shared_shaper_port_id,
+ (void *)&cmd_del_port_tm_node_shared_shaper_shared_shaper_id,
+ NULL,
+ },
+};
+
+/* *** Add Port TM Node WRED Profile *** */
+struct cmd_add_port_tm_node_wred_profile_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t wred;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t wred_profile_id;
+ cmdline_fixed_string_t color_g;
+ uint64_t min_th_g;
+ uint64_t max_th_g;
+ uint16_t maxp_inv_g;
+ uint16_t wq_log2_g;
+ cmdline_fixed_string_t color_y;
+ uint64_t min_th_y;
+ uint64_t max_th_y;
+ uint16_t maxp_inv_y;
+ uint16_t wq_log2_y;
+ cmdline_fixed_string_t color_r;
+ uint64_t min_th_r;
+ uint64_t max_th_r;
+ uint16_t maxp_inv_r;
+ uint16_t wq_log2_r;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result, tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result, node, "node");
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_wred =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result, wred, "wred");
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_wred_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ wred_profile_id, UINT32);
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_color_g =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ color_g, "G#g");
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_min_th_g =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ min_th_g, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_max_th_g =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ max_th_g, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_maxp_inv_g =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ maxp_inv_g, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_wq_log2_g =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ wq_log2_g, UINT16);
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_color_y =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ color_y, "Y#y");
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_min_th_y =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ min_th_y, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_max_th_y =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ max_th_y, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_maxp_inv_y =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ maxp_inv_y, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_wq_log2_y =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ wq_log2_y, UINT16);
+cmdline_parse_token_string_t cmd_add_port_tm_node_wred_profile_color_r =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ color_r, "R#r");
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_min_th_r =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ min_th_r, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_max_th_r =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ max_th_r, UINT64);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_maxp_inv_r =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ maxp_inv_r, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_node_wred_profile_wq_log2_r =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_node_wred_profile_result,
+ wq_log2_r, UINT16);
+
+
+static void cmd_add_port_tm_node_wred_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_tm_node_wred_profile_result *res = parsed_result;
+ struct rte_tm_wred_params wp;
+ enum rte_color color;
+ struct rte_tm_error error;
+ uint32_t wred_profile_id = res->wred_profile_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&wp, 0, sizeof(struct rte_tm_wred_params));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+
+ /* WRED Params (Green Color)*/
+ color = RTE_COLOR_GREEN;
+ wp.red_params[color].min_th = res->min_th_g;
+ wp.red_params[color].max_th = res->max_th_g;
+ wp.red_params[color].maxp_inv = res->maxp_inv_g;
+ wp.red_params[color].wq_log2 = res->wq_log2_g;
+
+
+ /* WRED Params (Yellow Color)*/
+ color = RTE_COLOR_YELLOW;
+ wp.red_params[color].min_th = res->min_th_y;
+ wp.red_params[color].max_th = res->max_th_y;
+ wp.red_params[color].maxp_inv = res->maxp_inv_y;
+ wp.red_params[color].wq_log2 = res->wq_log2_y;
+
+ /* WRED Params (Red Color)*/
+ color = RTE_COLOR_RED;
+ wp.red_params[color].min_th = res->min_th_r;
+ wp.red_params[color].max_th = res->max_th_r;
+ wp.red_params[color].maxp_inv = res->maxp_inv_r;
+ wp.red_params[color].wq_log2 = res->wq_log2_r;
+
+ ret = rte_tm_wred_profile_add(port_id, wred_profile_id, &wp, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_node_wred_profile = {
+ .f = cmd_add_port_tm_node_wred_profile_parsed,
+ .data = NULL,
+ .help_str = "Add port tm node wred profile",
+ .tokens = {
+ (void *)&cmd_add_port_tm_node_wred_profile_add,
+ (void *)&cmd_add_port_tm_node_wred_profile_port,
+ (void *)&cmd_add_port_tm_node_wred_profile_tm,
+ (void *)&cmd_add_port_tm_node_wred_profile_node,
+ (void *)&cmd_add_port_tm_node_wred_profile_wred,
+ (void *)&cmd_add_port_tm_node_wred_profile_profile,
+ (void *)&cmd_add_port_tm_node_wred_profile_port_id,
+ (void *)&cmd_add_port_tm_node_wred_profile_wred_profile_id,
+ (void *)&cmd_add_port_tm_node_wred_profile_color_g,
+ (void *)&cmd_add_port_tm_node_wred_profile_min_th_g,
+ (void *)&cmd_add_port_tm_node_wred_profile_max_th_g,
+ (void *)&cmd_add_port_tm_node_wred_profile_maxp_inv_g,
+ (void *)&cmd_add_port_tm_node_wred_profile_wq_log2_g,
+ (void *)&cmd_add_port_tm_node_wred_profile_color_y,
+ (void *)&cmd_add_port_tm_node_wred_profile_min_th_y,
+ (void *)&cmd_add_port_tm_node_wred_profile_max_th_y,
+ (void *)&cmd_add_port_tm_node_wred_profile_maxp_inv_y,
+ (void *)&cmd_add_port_tm_node_wred_profile_wq_log2_y,
+ (void *)&cmd_add_port_tm_node_wred_profile_color_r,
+ (void *)&cmd_add_port_tm_node_wred_profile_min_th_r,
+ (void *)&cmd_add_port_tm_node_wred_profile_max_th_r,
+ (void *)&cmd_add_port_tm_node_wred_profile_maxp_inv_r,
+ (void *)&cmd_add_port_tm_node_wred_profile_wq_log2_r,
+ NULL,
+ },
+};
+
+/* *** Delete Port TM node WRED Profile *** */
+struct cmd_del_port_tm_node_wred_profile_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t wred;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t wred_profile_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result, tm, "tm");
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result, node, "node");
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_wred =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result, wred, "wred");
+cmdline_parse_token_string_t cmd_del_port_tm_node_wred_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_del_port_tm_node_wred_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_tm_node_wred_profile_wred_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_del_port_tm_node_wred_profile_result,
+ wred_profile_id, UINT32);
+
+static void cmd_del_port_tm_node_wred_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_tm_node_wred_profile_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t wred_profile_id = res->wred_profile_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_wred_profile_delete(port_id, wred_profile_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_tm_node_wred_profile = {
+ .f = cmd_del_port_tm_node_wred_profile_parsed,
+ .data = NULL,
+ .help_str = "Delete port tm node wred profile",
+ .tokens = {
+ (void *)&cmd_del_port_tm_node_wred_profile_del,
+ (void *)&cmd_del_port_tm_node_wred_profile_port,
+ (void *)&cmd_del_port_tm_node_wred_profile_tm,
+ (void *)&cmd_del_port_tm_node_wred_profile_node,
+ (void *)&cmd_del_port_tm_node_wred_profile_wred,
+ (void *)&cmd_del_port_tm_node_wred_profile_profile,
+ (void *)&cmd_del_port_tm_node_wred_profile_port_id,
+ (void *)&cmd_del_port_tm_node_wred_profile_wred_profile_id,
+ NULL,
+ },
+};
+
+/* *** Update Port TM Node Shaper profile *** */
+struct cmd_set_port_tm_node_shaper_profile_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t shaper;
+ cmdline_fixed_string_t profile;
+ uint16_t port_id;
+ uint32_t node_id;
+ uint32_t shaper_profile_id;
+};
+
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ port, "port");
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result, tm, "tm");
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ node, "node");
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_shaper =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ shaper, "shaper");
+cmdline_parse_token_string_t cmd_set_port_tm_node_shaper_profile_profile =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ profile, "profile");
+cmdline_parse_token_num_t cmd_set_port_tm_node_shaper_profile_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_tm_node_shaper_profile_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_port_tm_node_shaper_profile_result,
+ node_id, UINT32);
+cmdline_parse_token_num_t
+ cmd_set_port_tm_node_shaper_shaper_profile_profile_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_tm_node_shaper_profile_result,
+ shaper_profile_id, UINT32);
+
+static void cmd_set_port_tm_node_shaper_profile_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_tm_node_shaper_profile_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ uint32_t shaper_profile_id = res->shaper_profile_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Port status */
+ if (!port_is_started(port_id)) {
+ printf(" Port %u not started (error)\n", port_id);
+ return;
+ }
+
+ ret = rte_tm_node_shaper_update(port_id, node_id,
+ shaper_profile_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_set_port_tm_node_shaper_profile = {
+ .f = cmd_set_port_tm_node_shaper_profile_parsed,
+ .data = NULL,
+ .help_str = "Set port tm node shaper profile",
+ .tokens = {
+ (void *)&cmd_set_port_tm_node_shaper_profile_set,
+ (void *)&cmd_set_port_tm_node_shaper_profile_port,
+ (void *)&cmd_set_port_tm_node_shaper_profile_tm,
+ (void *)&cmd_set_port_tm_node_shaper_profile_node,
+ (void *)&cmd_set_port_tm_node_shaper_profile_shaper,
+ (void *)&cmd_set_port_tm_node_shaper_profile_profile,
+ (void *)&cmd_set_port_tm_node_shaper_profile_port_id,
+ (void *)&cmd_set_port_tm_node_shaper_profile_node_id,
+ (void *)&cmd_set_port_tm_node_shaper_shaper_profile_profile_id,
+ NULL,
+ },
+};
+
+/* *** Add Port TM nonleaf node *** */
+struct cmd_add_port_tm_nonleaf_node_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t nonleaf;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+ int32_t parent_node_id;
+ uint32_t priority;
+ uint32_t weight;
+ uint32_t level_id;
+ int32_t shaper_profile_id;
+ uint32_t n_sp_priorities;
+ uint64_t stats_mask;
+ cmdline_multi_string_t multi_shared_shaper_id;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result, port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result, tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_nonleaf =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result, nonleaf, "nonleaf");
+cmdline_parse_token_string_t cmd_add_port_tm_nonleaf_node_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result, node, "node");
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_add_port_tm_nonleaf_node_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ node_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_parent_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ parent_node_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ priority, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_weight =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ weight, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_level_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ level_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_shaper_profile_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ shaper_profile_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_n_sp_priorities =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ n_sp_priorities, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_nonleaf_node_stats_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ stats_mask, UINT64);
+cmdline_parse_token_string_t
+ cmd_add_port_tm_nonleaf_node_multi_shared_shaper_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_add_port_tm_nonleaf_node_result,
+ multi_shared_shaper_id, TOKEN_STRING_MULTI);
+
+static void cmd_add_port_tm_nonleaf_node_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_tm_nonleaf_node_result *res = parsed_result;
+ struct rte_tm_error error;
+ struct rte_tm_node_params np;
+ uint32_t *shared_shaper_id;
+ uint32_t parent_node_id, n_shared_shapers = 0;
+ char *s_str = res->multi_shared_shaper_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&np, 0, sizeof(struct rte_tm_node_params));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+
+ /* Node parameters */
+ if (res->parent_node_id < 0)
+ parent_node_id = UINT32_MAX;
+ else
+ parent_node_id = res->parent_node_id;
+
+ shared_shaper_id = (uint32_t *)malloc(MAX_NUM_SHARED_SHAPERS *
+ sizeof(uint32_t));
+ if (shared_shaper_id == NULL) {
+ printf(" Memory not allocated for shared shapers (error)\n");
+ return;
+ }
+
+ /* Parse multi shared shaper id string */
+ ret = parse_multi_ss_id_str(s_str, &n_shared_shapers, shared_shaper_id);
+ if (ret) {
+ printf(" Shared shapers params string parse error\n");
+ free(shared_shaper_id);
+ return;
+ }
+
+ if (res->shaper_profile_id < 0)
+ np.shaper_profile_id = UINT32_MAX;
+ else
+ np.shaper_profile_id = res->shaper_profile_id;
+
+ np.n_shared_shapers = n_shared_shapers;
+ if (np.n_shared_shapers) {
+ np.shared_shaper_id = &shared_shaper_id[0];
+ } else {
+ free(shared_shaper_id);
+ shared_shaper_id = NULL;
+ }
+
+ np.nonleaf.n_sp_priorities = res->n_sp_priorities;
+ np.stats_mask = res->stats_mask;
+ np.nonleaf.wfq_weight_mode = NULL;
+
+ ret = rte_tm_node_add(port_id, res->node_id, parent_node_id,
+ res->priority, res->weight, res->level_id,
+ &np, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ free(shared_shaper_id);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node = {
+ .f = cmd_add_port_tm_nonleaf_node_parsed,
+ .data = NULL,
+ .help_str = "Add port tm nonleaf node",
+ .tokens = {
+ (void *)&cmd_add_port_tm_nonleaf_node_add,
+ (void *)&cmd_add_port_tm_nonleaf_node_port,
+ (void *)&cmd_add_port_tm_nonleaf_node_tm,
+ (void *)&cmd_add_port_tm_nonleaf_node_nonleaf,
+ (void *)&cmd_add_port_tm_nonleaf_node_node,
+ (void *)&cmd_add_port_tm_nonleaf_node_port_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_node_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_parent_node_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_priority,
+ (void *)&cmd_add_port_tm_nonleaf_node_weight,
+ (void *)&cmd_add_port_tm_nonleaf_node_level_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_shaper_profile_id,
+ (void *)&cmd_add_port_tm_nonleaf_node_n_sp_priorities,
+ (void *)&cmd_add_port_tm_nonleaf_node_stats_mask,
+ (void *)&cmd_add_port_tm_nonleaf_node_multi_shared_shaper_id,
+ NULL,
+ },
+};
+
+/* *** Add Port TM leaf node *** */
+struct cmd_add_port_tm_leaf_node_result {
+ cmdline_fixed_string_t add;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t leaf;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+ int32_t parent_node_id;
+ uint32_t priority;
+ uint32_t weight;
+ uint32_t level_id;
+ int32_t shaper_profile_id;
+ uint32_t cman_mode;
+ uint32_t wred_profile_id;
+ uint64_t stats_mask;
+ cmdline_multi_string_t multi_shared_shaper_id;
+};
+
+cmdline_parse_token_string_t cmd_add_port_tm_leaf_node_add =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_leaf_node_result, add, "add");
+cmdline_parse_token_string_t cmd_add_port_tm_leaf_node_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_leaf_node_result, port, "port");
+cmdline_parse_token_string_t cmd_add_port_tm_leaf_node_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_leaf_node_result, tm, "tm");
+cmdline_parse_token_string_t cmd_add_port_tm_leaf_node_nonleaf =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_leaf_node_result, leaf, "leaf");
+cmdline_parse_token_string_t cmd_add_port_tm_leaf_node_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_add_port_tm_leaf_node_result, node, "node");
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ node_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_parent_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ parent_node_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ priority, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_weight =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ weight, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_level_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ level_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_shaper_profile_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ shaper_profile_id, INT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_cman_mode =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ cman_mode, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_wred_profile_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ wred_profile_id, UINT32);
+cmdline_parse_token_num_t cmd_add_port_tm_leaf_node_stats_mask =
+ TOKEN_NUM_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ stats_mask, UINT64);
+cmdline_parse_token_string_t
+ cmd_add_port_tm_leaf_node_multi_shared_shaper_id =
+ TOKEN_STRING_INITIALIZER(struct cmd_add_port_tm_leaf_node_result,
+ multi_shared_shaper_id, TOKEN_STRING_MULTI);
+
+static void cmd_add_port_tm_leaf_node_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_add_port_tm_leaf_node_result *res = parsed_result;
+ struct rte_tm_error error;
+ struct rte_tm_node_params np;
+ uint32_t *shared_shaper_id;
+ uint32_t parent_node_id, n_shared_shapers = 0;
+ portid_t port_id = res->port_id;
+ char *s_str = res->multi_shared_shaper_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&np, 0, sizeof(struct rte_tm_node_params));
+ memset(&error, 0, sizeof(struct rte_tm_error));
+
+ /* Node parameters */
+ if (res->parent_node_id < 0)
+ parent_node_id = UINT32_MAX;
+ else
+ parent_node_id = res->parent_node_id;
+
+ shared_shaper_id = (uint32_t *)malloc(MAX_NUM_SHARED_SHAPERS *
+ sizeof(uint32_t));
+ if (shared_shaper_id == NULL) {
+ printf(" Memory not allocated for shared shapers (error)\n");
+ return;
+ }
+
+ /* Parse multi shared shaper id string */
+ ret = parse_multi_ss_id_str(s_str, &n_shared_shapers, shared_shaper_id);
+ if (ret) {
+ printf(" Shared shapers params string parse error\n");
+ free(shared_shaper_id);
+ return;
+ }
+
+ if (res->shaper_profile_id < 0)
+ np.shaper_profile_id = UINT32_MAX;
+ else
+ np.shaper_profile_id = res->shaper_profile_id;
+
+ np.n_shared_shapers = n_shared_shapers;
+
+ if (np.n_shared_shapers) {
+ np.shared_shaper_id = &shared_shaper_id[0];
+ } else {
+ free(shared_shaper_id);
+ shared_shaper_id = NULL;
+ }
+
+ np.leaf.cman = res->cman_mode;
+ np.leaf.wred.wred_profile_id = res->wred_profile_id;
+ np.stats_mask = res->stats_mask;
+
+ ret = rte_tm_node_add(port_id, res->node_id, parent_node_id,
+ res->priority, res->weight, res->level_id,
+ &np, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ free(shared_shaper_id);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_add_port_tm_leaf_node = {
+ .f = cmd_add_port_tm_leaf_node_parsed,
+ .data = NULL,
+ .help_str = "Add port tm leaf node",
+ .tokens = {
+ (void *)&cmd_add_port_tm_leaf_node_add,
+ (void *)&cmd_add_port_tm_leaf_node_port,
+ (void *)&cmd_add_port_tm_leaf_node_tm,
+ (void *)&cmd_add_port_tm_leaf_node_nonleaf,
+ (void *)&cmd_add_port_tm_leaf_node_node,
+ (void *)&cmd_add_port_tm_leaf_node_port_id,
+ (void *)&cmd_add_port_tm_leaf_node_node_id,
+ (void *)&cmd_add_port_tm_leaf_node_parent_node_id,
+ (void *)&cmd_add_port_tm_leaf_node_priority,
+ (void *)&cmd_add_port_tm_leaf_node_weight,
+ (void *)&cmd_add_port_tm_leaf_node_level_id,
+ (void *)&cmd_add_port_tm_leaf_node_shaper_profile_id,
+ (void *)&cmd_add_port_tm_leaf_node_cman_mode,
+ (void *)&cmd_add_port_tm_leaf_node_wred_profile_id,
+ (void *)&cmd_add_port_tm_leaf_node_stats_mask,
+ (void *)&cmd_add_port_tm_leaf_node_multi_shared_shaper_id,
+ NULL,
+ },
+};
+
+/* *** Delete Port TM Node *** */
+struct cmd_del_port_tm_node_result {
+ cmdline_fixed_string_t del;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+};
+
+cmdline_parse_token_string_t cmd_del_port_tm_node_del =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_result, del, "del");
+cmdline_parse_token_string_t cmd_del_port_tm_node_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_result, port, "port");
+cmdline_parse_token_string_t cmd_del_port_tm_node_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_result, tm, "tm");
+cmdline_parse_token_string_t cmd_del_port_tm_node_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_del_port_tm_node_result, node, "node");
+cmdline_parse_token_num_t cmd_del_port_tm_node_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_del_port_tm_node_result,
+ port_id, UINT16);
+cmdline_parse_token_num_t cmd_del_port_tm_node_node_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_del_port_tm_node_result,
+ node_id, UINT32);
+
+static void cmd_del_port_tm_node_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_del_port_tm_node_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Port status */
+ if (port_is_started(port_id)) {
+ printf(" Port %u not stopped (error)\n", port_id);
+ return;
+ }
+
+ ret = rte_tm_node_delete(port_id, node_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_del_port_tm_node = {
+ .f = cmd_del_port_tm_node_parsed,
+ .data = NULL,
+ .help_str = "Delete port tm node",
+ .tokens = {
+ (void *)&cmd_del_port_tm_node_del,
+ (void *)&cmd_del_port_tm_node_port,
+ (void *)&cmd_del_port_tm_node_tm,
+ (void *)&cmd_del_port_tm_node_node,
+ (void *)&cmd_del_port_tm_node_port_id,
+ (void *)&cmd_del_port_tm_node_node_id,
+ NULL,
+ },
+};
+
+/* *** Update Port TM Node Parent *** */
+struct cmd_set_port_tm_node_parent_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ cmdline_fixed_string_t parent;
+ uint16_t port_id;
+ uint32_t node_id;
+ uint32_t parent_id;
+ uint32_t priority;
+ uint32_t weight;
+};
+
+cmdline_parse_token_string_t cmd_set_port_tm_node_parent_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, set, "set");
+cmdline_parse_token_string_t cmd_set_port_tm_node_parent_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, port, "port");
+cmdline_parse_token_string_t cmd_set_port_tm_node_parent_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, tm, "tm");
+cmdline_parse_token_string_t cmd_set_port_tm_node_parent_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, node, "node");
+cmdline_parse_token_string_t cmd_set_port_tm_node_parent_parent =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, parent, "parent");
+cmdline_parse_token_num_t cmd_set_port_tm_node_parent_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_set_port_tm_node_parent_node_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_tm_node_parent_result, node_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_tm_node_parent_parent_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_port_tm_node_parent_result,
+ parent_id, UINT32);
+cmdline_parse_token_num_t cmd_set_port_tm_node_parent_priority =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_port_tm_node_parent_result,
+ priority, UINT32);
+cmdline_parse_token_num_t cmd_set_port_tm_node_parent_weight =
+ TOKEN_NUM_INITIALIZER(struct cmd_set_port_tm_node_parent_result,
+ weight, UINT32);
+
+static void cmd_set_port_tm_node_parent_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_tm_node_parent_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ uint32_t parent_id = res->parent_id;
+ uint32_t priority = res->priority;
+ uint32_t weight = res->weight;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ /* Port status */
+ if (!port_is_started(port_id)) {
+ printf(" Port %u not started (error)\n", port_id);
+ return;
+ }
+
+ ret = rte_tm_node_parent_update(port_id, node_id,
+ parent_id, priority, weight, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_set_port_tm_node_parent = {
+ .f = cmd_set_port_tm_node_parent_parsed,
+ .data = NULL,
+ .help_str = "Set port tm node parent",
+ .tokens = {
+ (void *)&cmd_set_port_tm_node_parent_set,
+ (void *)&cmd_set_port_tm_node_parent_port,
+ (void *)&cmd_set_port_tm_node_parent_tm,
+ (void *)&cmd_set_port_tm_node_parent_node,
+ (void *)&cmd_set_port_tm_node_parent_parent,
+ (void *)&cmd_set_port_tm_node_parent_port_id,
+ (void *)&cmd_set_port_tm_node_parent_node_id,
+ (void *)&cmd_set_port_tm_node_parent_parent_id,
+ (void *)&cmd_set_port_tm_node_parent_priority,
+ (void *)&cmd_set_port_tm_node_parent_weight,
+ NULL,
+ },
+};
+
+/* *** Suspend Port TM Node *** */
+struct cmd_suspend_port_tm_node_result {
+ cmdline_fixed_string_t suspend;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+};
+
+cmdline_parse_token_string_t cmd_suspend_port_tm_node_suspend =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, suspend, "suspend");
+cmdline_parse_token_string_t cmd_suspend_port_tm_node_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, port, "port");
+cmdline_parse_token_string_t cmd_suspend_port_tm_node_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, tm, "tm");
+cmdline_parse_token_string_t cmd_suspend_port_tm_node_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, node, "node");
+cmdline_parse_token_num_t cmd_suspend_port_tm_node_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_suspend_port_tm_node_node_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_suspend_port_tm_node_result, node_id, UINT32);
+
+static void cmd_suspend_port_tm_node_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_suspend_port_tm_node_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_node_suspend(port_id, node_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_suspend_port_tm_node = {
+ .f = cmd_suspend_port_tm_node_parsed,
+ .data = NULL,
+ .help_str = "Suspend port tm node",
+ .tokens = {
+ (void *)&cmd_suspend_port_tm_node_suspend,
+ (void *)&cmd_suspend_port_tm_node_port,
+ (void *)&cmd_suspend_port_tm_node_tm,
+ (void *)&cmd_suspend_port_tm_node_node,
+ (void *)&cmd_suspend_port_tm_node_port_id,
+ (void *)&cmd_suspend_port_tm_node_node_id,
+ NULL,
+ },
+};
+
+/* *** Resume Port TM Node *** */
+struct cmd_resume_port_tm_node_result {
+ cmdline_fixed_string_t resume;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t node;
+ uint16_t port_id;
+ uint32_t node_id;
+};
+
+cmdline_parse_token_string_t cmd_resume_port_tm_node_resume =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, resume, "resume");
+cmdline_parse_token_string_t cmd_resume_port_tm_node_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, port, "port");
+cmdline_parse_token_string_t cmd_resume_port_tm_node_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, tm, "tm");
+cmdline_parse_token_string_t cmd_resume_port_tm_node_node =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, node, "node");
+cmdline_parse_token_num_t cmd_resume_port_tm_node_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, port_id, UINT16);
+cmdline_parse_token_num_t cmd_resume_port_tm_node_node_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_resume_port_tm_node_result, node_id, UINT32);
+
+static void cmd_resume_port_tm_node_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_resume_port_tm_node_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t node_id = res->node_id;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_node_resume(port_id, node_id, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_resume_port_tm_node = {
+ .f = cmd_resume_port_tm_node_parsed,
+ .data = NULL,
+ .help_str = "Resume port tm node",
+ .tokens = {
+ (void *)&cmd_resume_port_tm_node_resume,
+ (void *)&cmd_resume_port_tm_node_port,
+ (void *)&cmd_resume_port_tm_node_tm,
+ (void *)&cmd_resume_port_tm_node_node,
+ (void *)&cmd_resume_port_tm_node_port_id,
+ (void *)&cmd_resume_port_tm_node_node_id,
+ NULL,
+ },
+};
+
+/* *** Port TM Hierarchy Commit *** */
+struct cmd_port_tm_hierarchy_commit_result {
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t hierarchy;
+ cmdline_fixed_string_t commit;
+ uint16_t port_id;
+ cmdline_fixed_string_t clean_on_fail;
+};
+
+cmdline_parse_token_string_t cmd_port_tm_hierarchy_commit_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_port_tm_hierarchy_commit_result, port, "port");
+cmdline_parse_token_string_t cmd_port_tm_hierarchy_commit_tm =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_port_tm_hierarchy_commit_result, tm, "tm");
+cmdline_parse_token_string_t cmd_port_tm_hierarchy_commit_hierarchy =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_port_tm_hierarchy_commit_result,
+ hierarchy, "hierarchy");
+cmdline_parse_token_string_t cmd_port_tm_hierarchy_commit_commit =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_port_tm_hierarchy_commit_result, commit, "commit");
+cmdline_parse_token_num_t cmd_port_tm_hierarchy_commit_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_port_tm_hierarchy_commit_result,
+ port_id, UINT16);
+cmdline_parse_token_string_t cmd_port_tm_hierarchy_commit_clean_on_fail =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_hierarchy_commit_result,
+ clean_on_fail, "yes#no");
+
+static void cmd_port_tm_hierarchy_commit_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_port_tm_hierarchy_commit_result *res = parsed_result;
+ struct rte_tm_error error;
+ uint32_t clean_on_fail;
+ portid_t port_id = res->port_id;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ if (strcmp(res->clean_on_fail, "yes") == 0)
+ clean_on_fail = 1;
+ else
+ clean_on_fail = 0;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_hierarchy_commit(port_id, clean_on_fail, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_port_tm_hierarchy_commit = {
+ .f = cmd_port_tm_hierarchy_commit_parsed,
+ .data = NULL,
+ .help_str = "Commit port tm hierarchy",
+ .tokens = {
+ (void *)&cmd_port_tm_hierarchy_commit_port,
+ (void *)&cmd_port_tm_hierarchy_commit_tm,
+ (void *)&cmd_port_tm_hierarchy_commit_hierarchy,
+ (void *)&cmd_port_tm_hierarchy_commit_commit,
+ (void *)&cmd_port_tm_hierarchy_commit_port_id,
+ (void *)&cmd_port_tm_hierarchy_commit_clean_on_fail,
+ NULL,
+ },
+};
+
+/* *** Port TM Mark IP ECN *** */
+struct cmd_port_tm_mark_ip_ecn_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t mark;
+ cmdline_fixed_string_t ip_ecn;
+ uint16_t port_id;
+ uint16_t green;
+ uint16_t yellow;
+ uint16_t red;
+};
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_ecn_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ set, "set");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_ecn_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ port, "port");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_ecn_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result, tm,
+ "tm");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_ecn_mark =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ mark, "mark");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_ecn_ip_ecn =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ ip_ecn, "ip_ecn");
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_ecn_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ port_id, UINT16);
+
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_ecn_green =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ green, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_ecn_yellow =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ yellow, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_ecn_red =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_ecn_result,
+ red, UINT16);
+
+static void cmd_port_tm_mark_ip_ecn_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_port_tm_mark_ip_ecn_result *res = parsed_result;
+ struct rte_tm_error error;
+ portid_t port_id = res->port_id;
+ int green = res->green;
+ int yellow = res->yellow;
+ int red = res->red;
+ int ret;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_mark_ip_ecn(port_id, green, yellow, red, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_port_tm_mark_ip_ecn = {
+ .f = cmd_port_tm_mark_ip_ecn_parsed,
+ .data = NULL,
+ .help_str = "set port tm mark ip_ecn <port> <green> <yellow> <red>",
+ .tokens = {
+ (void *)&cmd_port_tm_mark_ip_ecn_set,
+ (void *)&cmd_port_tm_mark_ip_ecn_port,
+ (void *)&cmd_port_tm_mark_ip_ecn_tm,
+ (void *)&cmd_port_tm_mark_ip_ecn_mark,
+ (void *)&cmd_port_tm_mark_ip_ecn_ip_ecn,
+ (void *)&cmd_port_tm_mark_ip_ecn_port_id,
+ (void *)&cmd_port_tm_mark_ip_ecn_green,
+ (void *)&cmd_port_tm_mark_ip_ecn_yellow,
+ (void *)&cmd_port_tm_mark_ip_ecn_red,
+ NULL,
+ },
+};
+
+
+/* *** Port TM Mark IP DSCP *** */
+struct cmd_port_tm_mark_ip_dscp_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t mark;
+ cmdline_fixed_string_t ip_dscp;
+ uint16_t port_id;
+ uint16_t green;
+ uint16_t yellow;
+ uint16_t red;
+};
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_dscp_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ set, "set");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_dscp_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ port, "port");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_dscp_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result, tm,
+ "tm");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_dscp_mark =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ mark, "mark");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_ip_dscp_ip_dscp =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ ip_dscp, "ip_dscp");
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_dscp_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ port_id, UINT16);
+
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_dscp_green =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ green, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_dscp_yellow =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ yellow, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_ip_dscp_red =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_ip_dscp_result,
+ red, UINT16);
+
+static void cmd_port_tm_mark_ip_dscp_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_port_tm_mark_ip_dscp_result *res = parsed_result;
+ struct rte_tm_error error;
+ portid_t port_id = res->port_id;
+ int green = res->green;
+ int yellow = res->yellow;
+ int red = res->red;
+ int ret;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_mark_ip_dscp(port_id, green, yellow, red, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_port_tm_mark_ip_dscp = {
+ .f = cmd_port_tm_mark_ip_dscp_parsed,
+ .data = NULL,
+ .help_str = "set port tm mark ip_dscp <port> <green> <yellow> <red>",
+ .tokens = {
+ (void *)&cmd_port_tm_mark_ip_dscp_set,
+ (void *)&cmd_port_tm_mark_ip_dscp_port,
+ (void *)&cmd_port_tm_mark_ip_dscp_tm,
+ (void *)&cmd_port_tm_mark_ip_dscp_mark,
+ (void *)&cmd_port_tm_mark_ip_dscp_ip_dscp,
+ (void *)&cmd_port_tm_mark_ip_dscp_port_id,
+ (void *)&cmd_port_tm_mark_ip_dscp_green,
+ (void *)&cmd_port_tm_mark_ip_dscp_yellow,
+ (void *)&cmd_port_tm_mark_ip_dscp_red,
+ NULL,
+ },
+};
+
+
+/* *** Port TM Mark VLAN_DEI *** */
+struct cmd_port_tm_mark_vlan_dei_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t tm;
+ cmdline_fixed_string_t mark;
+ cmdline_fixed_string_t vlan_dei;
+ uint16_t port_id;
+ uint16_t green;
+ uint16_t yellow;
+ uint16_t red;
+};
+
+cmdline_parse_token_string_t cmd_port_tm_mark_vlan_dei_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ set, "set");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_vlan_dei_port =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ port, "port");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_vlan_dei_tm =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result, tm,
+ "tm");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_vlan_dei_mark =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ mark, "mark");
+
+cmdline_parse_token_string_t cmd_port_tm_mark_vlan_dei_vlan_dei =
+ TOKEN_STRING_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ vlan_dei, "vlan_dei");
+cmdline_parse_token_num_t cmd_port_tm_mark_vlan_dei_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ port_id, UINT16);
+
+cmdline_parse_token_num_t cmd_port_tm_mark_vlan_dei_green =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ green, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_vlan_dei_yellow =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ yellow, UINT16);
+cmdline_parse_token_num_t cmd_port_tm_mark_vlan_dei_red =
+ TOKEN_NUM_INITIALIZER(struct cmd_port_tm_mark_vlan_dei_result,
+ red, UINT16);
+
+static void cmd_port_tm_mark_vlan_dei_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_port_tm_mark_vlan_dei_result *res = parsed_result;
+ struct rte_tm_error error;
+ portid_t port_id = res->port_id;
+ int green = res->green;
+ int yellow = res->yellow;
+ int red = res->red;
+ int ret;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ memset(&error, 0, sizeof(struct rte_tm_error));
+ ret = rte_tm_mark_vlan_dei(port_id, green, yellow, red, &error);
+ if (ret != 0) {
+ print_err_msg(&error);
+ return;
+ }
+}
+
+cmdline_parse_inst_t cmd_port_tm_mark_vlan_dei = {
+ .f = cmd_port_tm_mark_vlan_dei_parsed,
+ .data = NULL,
+ .help_str = "set port tm mark vlan_dei <port> <green> <yellow> <red>",
+ .tokens = {
+ (void *)&cmd_port_tm_mark_vlan_dei_set,
+ (void *)&cmd_port_tm_mark_vlan_dei_port,
+ (void *)&cmd_port_tm_mark_vlan_dei_tm,
+ (void *)&cmd_port_tm_mark_vlan_dei_mark,
+ (void *)&cmd_port_tm_mark_vlan_dei_vlan_dei,
+ (void *)&cmd_port_tm_mark_vlan_dei_port_id,
+ (void *)&cmd_port_tm_mark_vlan_dei_green,
+ (void *)&cmd_port_tm_mark_vlan_dei_yellow,
+ (void *)&cmd_port_tm_mark_vlan_dei_red,
+ NULL,
+ },
+};
diff --git a/src/spdk/dpdk/app/test-pmd/cmdline_tm.h b/src/spdk/dpdk/app/test-pmd/cmdline_tm.h
new file mode 100644
index 000000000..950cb7538
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/cmdline_tm.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _CMDLINE_TM_H_
+#define _CMDLINE_TM_H_
+
+ /* Traffic Management CLI */
+extern cmdline_parse_inst_t cmd_show_port_tm_cap;
+extern cmdline_parse_inst_t cmd_show_port_tm_level_cap;
+extern cmdline_parse_inst_t cmd_show_port_tm_node_cap;
+extern cmdline_parse_inst_t cmd_show_port_tm_node_type;
+extern cmdline_parse_inst_t cmd_show_port_tm_node_stats;
+extern cmdline_parse_inst_t cmd_add_port_tm_node_shaper_profile;
+extern cmdline_parse_inst_t cmd_del_port_tm_node_shaper_profile;
+extern cmdline_parse_inst_t cmd_add_port_tm_node_shared_shaper;
+extern cmdline_parse_inst_t cmd_del_port_tm_node_shared_shaper;
+extern cmdline_parse_inst_t cmd_add_port_tm_node_wred_profile;
+extern cmdline_parse_inst_t cmd_del_port_tm_node_wred_profile;
+extern cmdline_parse_inst_t cmd_set_port_tm_node_shaper_profile;
+extern cmdline_parse_inst_t cmd_add_port_tm_nonleaf_node;
+extern cmdline_parse_inst_t cmd_add_port_tm_leaf_node;
+extern cmdline_parse_inst_t cmd_del_port_tm_node;
+extern cmdline_parse_inst_t cmd_set_port_tm_node_parent;
+extern cmdline_parse_inst_t cmd_suspend_port_tm_node;
+extern cmdline_parse_inst_t cmd_resume_port_tm_node;
+extern cmdline_parse_inst_t cmd_port_tm_hierarchy_commit;
+extern cmdline_parse_inst_t cmd_port_tm_mark_vlan_dei;
+extern cmdline_parse_inst_t cmd_port_tm_mark_ip_ecn;
+extern cmdline_parse_inst_t cmd_port_tm_mark_ip_dscp;
+
+#endif /* _CMDLINE_TM_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/config.c b/src/spdk/dpdk/app/test-pmd/config.c
new file mode 100644
index 000000000..5381207cc
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/config.c
@@ -0,0 +1,4318 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation.
+ * Copyright 2013-2014 6WIND S.A.
+ */
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_cycles.h>
+#include <rte_flow.h>
+#include <rte_errno.h>
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+#include <rte_pmd_bnxt.h>
+#endif
+#include <rte_gro.h>
+
+#include "testpmd.h"
+
+#define ETHDEV_FWVERS_LEN 32
+
+static char *flowtype_to_str(uint16_t flow_type);
+
+static const struct {
+ enum tx_pkt_split split;
+ const char *name;
+} tx_split_name[] = {
+ {
+ .split = TX_PKT_SPLIT_OFF,
+ .name = "off",
+ },
+ {
+ .split = TX_PKT_SPLIT_ON,
+ .name = "on",
+ },
+ {
+ .split = TX_PKT_SPLIT_RND,
+ .name = "rand",
+ },
+};
+
+const struct rss_type_info rss_type_table[] = {
+ { "all", ETH_RSS_ETH | ETH_RSS_VLAN | ETH_RSS_IP | ETH_RSS_TCP |
+ ETH_RSS_UDP | ETH_RSS_SCTP | ETH_RSS_L2_PAYLOAD |
+ ETH_RSS_L2TPV3 | ETH_RSS_ESP | ETH_RSS_AH | ETH_RSS_PFCP},
+ { "none", 0 },
+ { "eth", ETH_RSS_ETH },
+ { "l2-src-only", ETH_RSS_L2_SRC_ONLY },
+ { "l2-dst-only", ETH_RSS_L2_DST_ONLY },
+ { "vlan", ETH_RSS_VLAN },
+ { "s-vlan", ETH_RSS_S_VLAN },
+ { "c-vlan", ETH_RSS_C_VLAN },
+ { "ipv4", ETH_RSS_IPV4 },
+ { "ipv4-frag", ETH_RSS_FRAG_IPV4 },
+ { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
+ { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP },
+ { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP },
+ { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER },
+ { "ipv6", ETH_RSS_IPV6 },
+ { "ipv6-frag", ETH_RSS_FRAG_IPV6 },
+ { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP },
+ { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP },
+ { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP },
+ { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER },
+ { "l2-payload", ETH_RSS_L2_PAYLOAD },
+ { "ipv6-ex", ETH_RSS_IPV6_EX },
+ { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX },
+ { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX },
+ { "port", ETH_RSS_PORT },
+ { "vxlan", ETH_RSS_VXLAN },
+ { "geneve", ETH_RSS_GENEVE },
+ { "nvgre", ETH_RSS_NVGRE },
+ { "ip", ETH_RSS_IP },
+ { "udp", ETH_RSS_UDP },
+ { "tcp", ETH_RSS_TCP },
+ { "sctp", ETH_RSS_SCTP },
+ { "tunnel", ETH_RSS_TUNNEL },
+ { "l3-src-only", ETH_RSS_L3_SRC_ONLY },
+ { "l3-dst-only", ETH_RSS_L3_DST_ONLY },
+ { "l4-src-only", ETH_RSS_L4_SRC_ONLY },
+ { "l4-dst-only", ETH_RSS_L4_DST_ONLY },
+ { "esp", ETH_RSS_ESP },
+ { "ah", ETH_RSS_AH },
+ { "l2tpv3", ETH_RSS_L2TPV3 },
+ { "pfcp", ETH_RSS_PFCP },
+ { NULL, 0 },
+};
+
+static void
+print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", name, buf);
+}
+
+void
+nic_stats_display(portid_t port_id)
+{
+ static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
+ static uint64_t prev_cycles[RTE_MAX_ETHPORTS];
+ uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx,
+ diff_cycles;
+ uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
+ struct rte_eth_stats stats;
+ struct rte_port *port = &ports[port_id];
+ uint8_t i;
+
+ static const char *nic_stats_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+ rte_eth_stats_get(port_id, &stats);
+ printf("\n %s NIC statistics for port %-2d %s\n",
+ nic_stats_border, port_id, nic_stats_border);
+
+ if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
+ printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: "
+ "%-"PRIu64"\n",
+ stats.ipackets, stats.imissed, stats.ibytes);
+ printf(" RX-errors: %-"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %-10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: "
+ "%-"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+ }
+ else {
+ printf(" RX-packets: %10"PRIu64" RX-errors: %10"PRIu64
+ " RX-bytes: %10"PRIu64"\n",
+ stats.ipackets, stats.ierrors, stats.ibytes);
+ printf(" RX-errors: %10"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombuf: %10"PRIu64"\n",
+ stats.rx_nombuf);
+ printf(" TX-packets: %10"PRIu64" TX-errors: %10"PRIu64
+ " TX-bytes: %10"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+ }
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d RX-packets: %10"PRIu64
+ " RX-errors: %10"PRIu64
+ " RX-bytes: %10"PRIu64"\n",
+ i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
+ }
+ }
+ if (port->tx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
+ printf(" Stats reg %2d TX-packets: %10"PRIu64
+ " TX-bytes: %10"PRIu64"\n",
+ i, stats.q_opackets[i], stats.q_obytes[i]);
+ }
+ }
+
+ diff_cycles = prev_cycles[port_id];
+ prev_cycles[port_id] = rte_rdtsc();
+ if (diff_cycles > 0)
+ diff_cycles = prev_cycles[port_id] - diff_cycles;
+
+ diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
+ (stats.ipackets - prev_pkts_rx[port_id]) : 0;
+ diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ?
+ (stats.opackets - prev_pkts_tx[port_id]) : 0;
+ prev_pkts_rx[port_id] = stats.ipackets;
+ prev_pkts_tx[port_id] = stats.opackets;
+ mpps_rx = diff_cycles > 0 ?
+ diff_pkts_rx * rte_get_tsc_hz() / diff_cycles : 0;
+ mpps_tx = diff_cycles > 0 ?
+ diff_pkts_tx * rte_get_tsc_hz() / diff_cycles : 0;
+
+ diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?
+ (stats.ibytes - prev_bytes_rx[port_id]) : 0;
+ diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ?
+ (stats.obytes - prev_bytes_tx[port_id]) : 0;
+ prev_bytes_rx[port_id] = stats.ibytes;
+ prev_bytes_tx[port_id] = stats.obytes;
+ mbps_rx = diff_cycles > 0 ?
+ diff_bytes_rx * rte_get_tsc_hz() / diff_cycles : 0;
+ mbps_tx = diff_cycles > 0 ?
+ diff_bytes_tx * rte_get_tsc_hz() / diff_cycles : 0;
+
+ printf("\n Throughput (since last show)\n");
+ printf(" Rx-pps: %12"PRIu64" Rx-bps: %12"PRIu64"\n Tx-pps: %12"
+ PRIu64" Tx-bps: %12"PRIu64"\n", mpps_rx, mbps_rx * 8,
+ mpps_tx, mbps_tx * 8);
+
+ printf(" %s############################%s\n",
+ nic_stats_border, nic_stats_border);
+}
+
+void
+nic_stats_clear(portid_t port_id)
+{
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+
+ ret = rte_eth_stats_reset(port_id);
+ if (ret != 0) {
+ printf("%s: Error: failed to reset stats (port %u): %s",
+ __func__, port_id, strerror(ret));
+ return;
+ }
+
+ ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+ if (ret != 0) {
+ printf("%s: Error: failed to get stats (port %u): %s",
+ __func__, port_id, strerror(ret));
+ return;
+ }
+ printf("\n NIC statistics for port %d cleared\n", port_id);
+}
+
+void
+nic_xstats_display(portid_t port_id)
+{
+ struct rte_eth_xstat *xstats;
+ int cnt_xstats, idx_xstat;
+ struct rte_eth_xstat_name *xstats_names;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+ printf("###### NIC extended statistics for port %-2d\n", port_id);
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("Error: Invalid port number %i\n", port_id);
+ return;
+ }
+
+ /* Get count */
+ cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0);
+ if (cnt_xstats < 0) {
+ printf("Error: Cannot get count of xstats\n");
+ return;
+ }
+
+ /* Get id-name lookup table */
+ xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats);
+ if (xstats_names == NULL) {
+ printf("Cannot allocate memory for xstats lookup\n");
+ return;
+ }
+ if (cnt_xstats != rte_eth_xstats_get_names(
+ port_id, xstats_names, cnt_xstats)) {
+ printf("Error: Cannot get xstats lookup\n");
+ free(xstats_names);
+ return;
+ }
+
+ /* Get stats themselves */
+ xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats);
+ if (xstats == NULL) {
+ printf("Cannot allocate memory for xstats\n");
+ free(xstats_names);
+ return;
+ }
+ if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+ printf("Error: Unable to get xstats\n");
+ free(xstats_names);
+ free(xstats);
+ return;
+ }
+
+ /* Display xstats */
+ for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) {
+ if (xstats_hide_zero && !xstats[idx_xstat].value)
+ continue;
+ printf("%s: %"PRIu64"\n",
+ xstats_names[idx_xstat].name,
+ xstats[idx_xstat].value);
+ }
+ free(xstats_names);
+ free(xstats);
+}
+
+void
+nic_xstats_clear(portid_t port_id)
+{
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+
+ ret = rte_eth_xstats_reset(port_id);
+ if (ret != 0) {
+ printf("%s: Error: failed to reset xstats (port %u): %s",
+ __func__, port_id, strerror(ret));
+ return;
+ }
+
+ ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+ if (ret != 0) {
+ printf("%s: Error: failed to get stats (port %u): %s",
+ __func__, port_id, strerror(ret));
+ return;
+ }
+}
+
+void
+nic_stats_mapping_display(portid_t port_id)
+{
+ struct rte_port *port = &ports[port_id];
+ uint16_t i;
+
+ static const char *nic_stats_mapping_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+
+ if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
+ printf("Port id %d - either does not support queue statistic mapping or"
+ " no queue statistic mapping set\n", port_id);
+ return;
+ }
+
+ printf("\n %s NIC statistics mapping for port %-2d %s\n",
+ nic_stats_mapping_border, port_id, nic_stats_mapping_border);
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if (rx_queue_stats_mappings[i].port_id == port_id) {
+ printf(" RX-queue %2d mapped to Stats Reg %2d\n",
+ rx_queue_stats_mappings[i].queue_id,
+ rx_queue_stats_mappings[i].stats_counter_id);
+ }
+ }
+ printf("\n");
+ }
+
+
+ if (port->tx_queue_stats_mapping_enabled) {
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if (tx_queue_stats_mappings[i].port_id == port_id) {
+ printf(" TX-queue %2d mapped to Stats Reg %2d\n",
+ tx_queue_stats_mappings[i].queue_id,
+ tx_queue_stats_mappings[i].stats_counter_id);
+ }
+ }
+ }
+
+ printf(" %s####################################%s\n",
+ nic_stats_mapping_border, nic_stats_mapping_border);
+}
+
+void
+rx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+ struct rte_eth_burst_mode mode;
+ struct rte_eth_rxq_info qinfo;
+ int32_t rc;
+ static const char *info_border = "*********************";
+
+ rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
+ if (rc != 0) {
+ printf("Failed to retrieve information for port: %u, "
+ "RX queue: %hu\nerror desc: %s(%d)\n",
+ port_id, queue_id, strerror(-rc), rc);
+ return;
+ }
+
+ printf("\n%s Infos for port %-2u, RX queue %-2u %s",
+ info_border, port_id, queue_id, info_border);
+
+ printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name);
+ printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh);
+ printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh);
+ printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh);
+ printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh);
+ printf("\nRX drop packets: %s",
+ (qinfo.conf.rx_drop_en != 0) ? "on" : "off");
+ printf("\nRX deferred start: %s",
+ (qinfo.conf.rx_deferred_start != 0) ? "on" : "off");
+ printf("\nRX scattered packets: %s",
+ (qinfo.scattered_rx != 0) ? "on" : "off");
+ printf("\nNumber of RXDs: %hu", qinfo.nb_desc);
+
+ if (rte_eth_rx_burst_mode_get(port_id, queue_id, &mode) == 0)
+ printf("\nBurst mode: %s%s",
+ mode.info,
+ mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ?
+ " (per queue)" : "");
+
+ printf("\n");
+}
+
+void
+tx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+ struct rte_eth_burst_mode mode;
+ struct rte_eth_txq_info qinfo;
+ int32_t rc;
+ static const char *info_border = "*********************";
+
+ rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
+ if (rc != 0) {
+ printf("Failed to retrieve information for port: %u, "
+ "TX queue: %hu\nerror desc: %s(%d)\n",
+ port_id, queue_id, strerror(-rc), rc);
+ return;
+ }
+
+ printf("\n%s Infos for port %-2u, TX queue %-2u %s",
+ info_border, port_id, queue_id, info_border);
+
+ printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh);
+ printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh);
+ printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh);
+ printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh);
+ printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh);
+ printf("\nTX deferred start: %s",
+ (qinfo.conf.tx_deferred_start != 0) ? "on" : "off");
+ printf("\nNumber of TXDs: %hu", qinfo.nb_desc);
+
+ if (rte_eth_tx_burst_mode_get(port_id, queue_id, &mode) == 0)
+ printf("\nBurst mode: %s%s",
+ mode.info,
+ mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ?
+ " (per queue)" : "");
+
+ printf("\n");
+}
+
+static int bus_match_all(const struct rte_bus *bus, const void *data)
+{
+ RTE_SET_USED(bus);
+ RTE_SET_USED(data);
+ return 0;
+}
+
+void
+device_infos_display(const char *identifier)
+{
+ static const char *info_border = "*********************";
+ struct rte_bus *start = NULL, *next;
+ struct rte_dev_iterator dev_iter;
+ char name[RTE_ETH_NAME_MAX_LEN];
+ struct rte_ether_addr mac_addr;
+ struct rte_device *dev;
+ struct rte_devargs da;
+ portid_t port_id;
+ char devstr[128];
+
+ memset(&da, 0, sizeof(da));
+ if (!identifier)
+ goto skip_parse;
+
+ if (rte_devargs_parsef(&da, "%s", identifier)) {
+ printf("cannot parse identifier\n");
+ if (da.args)
+ free(da.args);
+ return;
+ }
+
+skip_parse:
+ while ((next = rte_bus_find(start, bus_match_all, NULL)) != NULL) {
+
+ start = next;
+ if (identifier && da.bus != next)
+ continue;
+
+ /* Skip buses that don't have iterate method */
+ if (!next->dev_iterate)
+ continue;
+
+ snprintf(devstr, sizeof(devstr), "bus=%s", next->name);
+ RTE_DEV_FOREACH(dev, devstr, &dev_iter) {
+
+ if (!dev->driver)
+ continue;
+ /* Check for matching device if identifier is present */
+ if (identifier &&
+ strncmp(da.name, dev->name, strlen(dev->name)))
+ continue;
+ printf("\n%s Infos for device %s %s\n",
+ info_border, dev->name, info_border);
+ printf("Bus name: %s", dev->bus->name);
+ printf("\nDriver name: %s", dev->driver->name);
+ printf("\nDevargs: %s",
+ dev->devargs ? dev->devargs->args : "");
+ printf("\nConnect to socket: %d", dev->numa_node);
+ printf("\n");
+
+ /* List ports with matching device name */
+ RTE_ETH_FOREACH_DEV_OF(port_id, dev) {
+ printf("\n\tPort id: %-2d", port_id);
+ if (eth_macaddr_get_print_err(port_id,
+ &mac_addr) == 0)
+ print_ethaddr("\n\tMAC address: ",
+ &mac_addr);
+ rte_eth_dev_get_name_by_port(port_id, name);
+ printf("\n\tDevice name: %s", name);
+ printf("\n");
+ }
+ }
+ };
+}
+
+void
+port_infos_display(portid_t port_id)
+{
+ struct rte_port *port;
+ struct rte_ether_addr mac_addr;
+ struct rte_eth_link link;
+ struct rte_eth_dev_info dev_info;
+ int vlan_offload;
+ struct rte_mempool * mp;
+ static const char *info_border = "*********************";
+ uint16_t mtu;
+ char name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+ char fw_version[ETHDEV_FWVERS_LEN];
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+ port = &ports[port_id];
+ ret = eth_link_get_nowait_print_err(port_id, &link);
+ if (ret < 0)
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ printf("\n%s Infos for port %-2d %s\n",
+ info_border, port_id, info_border);
+ if (eth_macaddr_get_print_err(port_id, &mac_addr) == 0)
+ print_ethaddr("MAC address: ", &mac_addr);
+ rte_eth_dev_get_name_by_port(port_id, name);
+ printf("\nDevice name: %s", name);
+ printf("\nDriver name: %s", dev_info.driver_name);
+
+ if (rte_eth_dev_fw_version_get(port_id, fw_version,
+ ETHDEV_FWVERS_LEN) == 0)
+ printf("\nFirmware-version: %s", fw_version);
+ else
+ printf("\nFirmware-version: %s", "not available");
+
+ if (dev_info.device->devargs && dev_info.device->devargs->args)
+ printf("\nDevargs: %s", dev_info.device->devargs->args);
+ printf("\nConnect to socket: %u", port->socket_id);
+
+ if (port_numa[port_id] != NUMA_NO_CONFIG) {
+ mp = mbuf_pool_find(port_numa[port_id]);
+ if (mp)
+ printf("\nmemory allocation on the socket: %d",
+ port_numa[port_id]);
+ } else
+ printf("\nmemory allocation on the socket: %u",port->socket_id);
+
+ printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
+ printf("Link speed: %u Mbps\n", (unsigned) link.link_speed);
+ printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex"));
+
+ if (!rte_eth_dev_get_mtu(port_id, &mtu))
+ printf("MTU: %u\n", mtu);
+
+ printf("Promiscuous mode: %s\n",
+ rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled");
+ printf("Allmulticast mode: %s\n",
+ rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled");
+ printf("Maximum number of MAC addresses: %u\n",
+ (unsigned int)(port->dev_info.max_mac_addrs));
+ printf("Maximum number of MAC addresses of hash filtering: %u\n",
+ (unsigned int)(port->dev_info.max_hash_mac_addrs));
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+ if (vlan_offload >= 0){
+ printf("VLAN offload: \n");
+ if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD)
+ printf(" strip on, ");
+ else
+ printf(" strip off, ");
+
+ if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD)
+ printf("filter on, ");
+ else
+ printf("filter off, ");
+
+ if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)
+ printf("extend on, ");
+ else
+ printf("extend off, ");
+
+ if (vlan_offload & ETH_QINQ_STRIP_OFFLOAD)
+ printf("qinq strip on\n");
+ else
+ printf("qinq strip off\n");
+ }
+
+ if (dev_info.hash_key_size > 0)
+ printf("Hash key size in bytes: %u\n", dev_info.hash_key_size);
+ if (dev_info.reta_size > 0)
+ printf("Redirection table size: %u\n", dev_info.reta_size);
+ if (!dev_info.flow_type_rss_offloads)
+ printf("No RSS offload flow type is supported.\n");
+ else {
+ uint16_t i;
+ char *p;
+
+ printf("Supported RSS offload flow types:\n");
+ for (i = RTE_ETH_FLOW_UNKNOWN + 1;
+ i < sizeof(dev_info.flow_type_rss_offloads) * CHAR_BIT; i++) {
+ if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
+ continue;
+ p = flowtype_to_str(i);
+ if (p)
+ printf(" %s\n", p);
+ else
+ printf(" user defined %d\n", i);
+ }
+ }
+
+ printf("Minimum size of RX buffer: %u\n", dev_info.min_rx_bufsize);
+ printf("Maximum configurable length of RX packet: %u\n",
+ dev_info.max_rx_pktlen);
+ printf("Maximum configurable size of LRO aggregated packet: %u\n",
+ dev_info.max_lro_pkt_size);
+ if (dev_info.max_vfs)
+ printf("Maximum number of VFs: %u\n", dev_info.max_vfs);
+ if (dev_info.max_vmdq_pools)
+ printf("Maximum number of VMDq pools: %u\n",
+ dev_info.max_vmdq_pools);
+
+ printf("Current number of RX queues: %u\n", dev_info.nb_rx_queues);
+ printf("Max possible RX queues: %u\n", dev_info.max_rx_queues);
+ printf("Max possible number of RXDs per queue: %hu\n",
+ dev_info.rx_desc_lim.nb_max);
+ printf("Min possible number of RXDs per queue: %hu\n",
+ dev_info.rx_desc_lim.nb_min);
+ printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align);
+
+ printf("Current number of TX queues: %u\n", dev_info.nb_tx_queues);
+ printf("Max possible TX queues: %u\n", dev_info.max_tx_queues);
+ printf("Max possible number of TXDs per queue: %hu\n",
+ dev_info.tx_desc_lim.nb_max);
+ printf("Min possible number of TXDs per queue: %hu\n",
+ dev_info.tx_desc_lim.nb_min);
+ printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
+ printf("Max segment number per packet: %hu\n",
+ dev_info.tx_desc_lim.nb_seg_max);
+ printf("Max segment number per MTU/TSO: %hu\n",
+ dev_info.tx_desc_lim.nb_mtu_seg_max);
+
+ /* Show switch info only if valid switch domain and port id is set */
+ if (dev_info.switch_info.domain_id !=
+ RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
+ if (dev_info.switch_info.name)
+ printf("Switch name: %s\n", dev_info.switch_info.name);
+
+ printf("Switch domain Id: %u\n",
+ dev_info.switch_info.domain_id);
+ printf("Switch Port Id: %u\n",
+ dev_info.switch_info.port_id);
+ }
+}
+
+void
+port_summary_header_display(void)
+{
+ uint16_t port_number;
+
+ port_number = rte_eth_dev_count_avail();
+ printf("Number of available ports: %i\n", port_number);
+ printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
+ "Driver", "Status", "Link");
+}
+
+void
+port_summary_display(portid_t port_id)
+{
+ struct rte_ether_addr mac_addr;
+ struct rte_eth_link link;
+ struct rte_eth_dev_info dev_info;
+ char name[RTE_ETH_NAME_MAX_LEN];
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ print_valid_ports();
+ return;
+ }
+
+ ret = eth_link_get_nowait_print_err(port_id, &link);
+ if (ret < 0)
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ rte_eth_dev_get_name_by_port(port_id, name);
+ ret = eth_macaddr_get_print_err(port_id, &mac_addr);
+ if (ret != 0)
+ return;
+
+ printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %uMbps\n",
+ port_id, mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
+ mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
+ mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], name,
+ dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
+ (unsigned int) link.link_speed);
+}
+
+void
+port_offload_cap_display(portid_t port_id)
+{
+ struct rte_eth_dev_info dev_info;
+ static const char *info_border = "************";
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ printf("\n%s Port %d supported offload features: %s\n",
+ info_border, port_id, info_border);
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
+ printf("VLAN stripped: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_VLAN_STRIP)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) {
+ printf("Double VLANs stripped: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_QINQ_STRIP)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) {
+ printf("RX IPv4 checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_IPV4_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) {
+ printf("RX UDP checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) {
+ printf("RX TCP checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_TCP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCTP_CKSUM) {
+ printf("RX SCTP checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_SCTP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM) {
+ printf("RX Outer IPv4 checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_UDP_CKSUM) {
+ printf("RX Outer UDP checksum: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_OUTER_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
+ printf("Large receive offload: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_TCP_LRO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP) {
+ printf("HW timestamp: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_TIMESTAMP)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC) {
+ printf("Rx Keep CRC: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_KEEP_CRC)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY) {
+ printf("RX offload security: ");
+ if (ports[port_id].dev_conf.rxmode.offloads &
+ DEV_RX_OFFLOAD_SECURITY)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) {
+ printf("VLAN insert: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_VLAN_INSERT)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
+ printf("Double VLANs insert: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_QINQ_INSERT)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) {
+ printf("TX IPv4 checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_IPV4_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) {
+ printf("TX UDP checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) {
+ printf("TX TCP checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_TCP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
+ printf("TX SCTP checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_SCTP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) {
+ printf("TX Outer IPv4 checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
+ printf("TX TCP segmentation: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_TCP_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO) {
+ printf("TX UDP segmentation: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_UDP_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO) {
+ printf("TSO for VXLAN tunnel packet: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_VXLAN_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO) {
+ printf("TSO for GRE tunnel packet: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_GRE_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO) {
+ printf("TSO for IPIP tunnel packet: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_IPIP_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO) {
+ printf("TSO for GENEVE tunnel packet: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO) {
+ printf("IP tunnel TSO: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_IP_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO) {
+ printf("UDP tunnel TSO: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_UDP_TNL_TSO)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+ if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) {
+ printf("TX Outer UDP checksum: ");
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
+ printf("on\n");
+ else
+ printf("off\n");
+ }
+
+}
+
+int
+port_id_is_invalid(portid_t port_id, enum print_warning warning)
+{
+ uint16_t pid;
+
+ if (port_id == (portid_t)RTE_PORT_ALL)
+ return 0;
+
+ RTE_ETH_FOREACH_DEV(pid)
+ if (port_id == pid)
+ return 0;
+
+ if (warning == ENABLED_WARN)
+ printf("Invalid port %d\n", port_id);
+
+ return 1;
+}
+
+void print_valid_ports(void)
+{
+ portid_t pid;
+
+ printf("The valid ports array is [");
+ RTE_ETH_FOREACH_DEV(pid) {
+ printf(" %d", pid);
+ }
+ printf(" ]\n");
+}
+
+static int
+vlan_id_is_invalid(uint16_t vlan_id)
+{
+ if (vlan_id < 4096)
+ return 0;
+ printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id);
+ return 1;
+}
+
+static int
+port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off)
+{
+ const struct rte_pci_device *pci_dev;
+ const struct rte_bus *bus;
+ uint64_t pci_len;
+
+ if (reg_off & 0x3) {
+ printf("Port register offset 0x%X not aligned on a 4-byte "
+ "boundary\n",
+ (unsigned)reg_off);
+ return 1;
+ }
+
+ if (!ports[port_id].dev_info.device) {
+ printf("Invalid device\n");
+ return 0;
+ }
+
+ bus = rte_bus_find_by_device(ports[port_id].dev_info.device);
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(ports[port_id].dev_info.device);
+ } else {
+ printf("Not a PCI device\n");
+ return 1;
+ }
+
+ pci_len = pci_dev->mem_resource[0].len;
+ if (reg_off >= pci_len) {
+ printf("Port %d: register offset %u (0x%X) out of port PCI "
+ "resource (length=%"PRIu64")\n",
+ port_id, (unsigned)reg_off, (unsigned)reg_off, pci_len);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+reg_bit_pos_is_invalid(uint8_t bit_pos)
+{
+ if (bit_pos <= 31)
+ return 0;
+ printf("Invalid bit position %d (must be <= 31)\n", bit_pos);
+ return 1;
+}
+
+#define display_port_and_reg_off(port_id, reg_off) \
+ printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off))
+
+static inline void
+display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
+{
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v);
+}
+
+void
+port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x)
+{
+ uint32_t reg_v;
+
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit_x))
+ return;
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x));
+}
+
+void
+port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos)
+{
+ uint32_t reg_v;
+ uint8_t l_bit;
+ uint8_t h_bit;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit1_pos))
+ return;
+ if (reg_bit_pos_is_invalid(bit2_pos))
+ return;
+ if (bit1_pos > bit2_pos)
+ l_bit = bit2_pos, h_bit = bit1_pos;
+ else
+ l_bit = bit1_pos, h_bit = bit2_pos;
+
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ reg_v >>= l_bit;
+ if (h_bit < 31)
+ reg_v &= ((1 << (h_bit - l_bit + 1)) - 1);
+ display_port_and_reg_off(port_id, (unsigned)reg_off);
+ printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit,
+ ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v);
+}
+
+void
+port_reg_display(portid_t port_id, uint32_t reg_off)
+{
+ uint32_t reg_v;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
+ uint8_t bit_v)
+{
+ uint32_t reg_v;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit_pos))
+ return;
+ if (bit_v > 1) {
+ printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v);
+ return;
+ }
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ if (bit_v == 0)
+ reg_v &= ~(1 << bit_pos);
+ else
+ reg_v |= (1 << bit_pos);
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value)
+{
+ uint32_t max_v;
+ uint32_t reg_v;
+ uint8_t l_bit;
+ uint8_t h_bit;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ if (reg_bit_pos_is_invalid(bit1_pos))
+ return;
+ if (reg_bit_pos_is_invalid(bit2_pos))
+ return;
+ if (bit1_pos > bit2_pos)
+ l_bit = bit2_pos, h_bit = bit1_pos;
+ else
+ l_bit = bit1_pos, h_bit = bit2_pos;
+
+ if ((h_bit - l_bit) < 31)
+ max_v = (1 << (h_bit - l_bit + 1)) - 1;
+ else
+ max_v = 0xFFFFFFFF;
+
+ if (value > max_v) {
+ printf("Invalid value %u (0x%x) must be < %u (0x%x)\n",
+ (unsigned)value, (unsigned)value,
+ (unsigned)max_v, (unsigned)max_v);
+ return;
+ }
+ reg_v = port_id_pci_reg_read(port_id, reg_off);
+ reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */
+ reg_v |= (value << l_bit); /* Set changed bits */
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (port_reg_off_is_invalid(port_id, reg_off))
+ return;
+ port_id_pci_reg_write(port_id, reg_off, reg_v);
+ display_port_reg_value(port_id, reg_off, reg_v);
+}
+
+void
+port_mtu_set(portid_t port_id, uint16_t mtu)
+{
+ int diag;
+ struct rte_port *rte_port = &ports[port_id];
+ struct rte_eth_dev_info dev_info;
+ uint16_t eth_overhead;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (mtu > dev_info.max_mtu || mtu < dev_info.min_mtu) {
+ printf("Set MTU failed. MTU:%u is not in valid range, min:%u - max:%u\n",
+ mtu, dev_info.min_mtu, dev_info.max_mtu);
+ return;
+ }
+ diag = rte_eth_dev_set_mtu(port_id, mtu);
+ if (diag == 0 &&
+ dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) {
+ /*
+ * Ether overhead in driver is equal to the difference of
+ * max_rx_pktlen and max_mtu in rte_eth_dev_info when the
+ * device supports jumbo frame.
+ */
+ eth_overhead = dev_info.max_rx_pktlen - dev_info.max_mtu;
+ if (mtu > RTE_ETHER_MAX_LEN - eth_overhead) {
+ rte_port->dev_conf.rxmode.offloads |=
+ DEV_RX_OFFLOAD_JUMBO_FRAME;
+ rte_port->dev_conf.rxmode.max_rx_pkt_len =
+ mtu + eth_overhead;
+ } else
+ rte_port->dev_conf.rxmode.offloads &=
+ ~DEV_RX_OFFLOAD_JUMBO_FRAME;
+
+ return;
+ }
+ printf("Set MTU failed. diag=%d\n", diag);
+}
+
+/* Generic flow management functions. */
+
+/** Generate a port_flow entry from attributes/pattern/actions. */
+static struct port_flow *
+port_flow_new(const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_conv_rule rule = {
+ .attr_ro = attr,
+ .pattern_ro = pattern,
+ .actions_ro = actions,
+ };
+ struct port_flow *pf;
+ int ret;
+
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, error);
+ if (ret < 0)
+ return NULL;
+ pf = calloc(1, offsetof(struct port_flow, rule) + ret);
+ if (!pf) {
+ rte_flow_error_set
+ (error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "calloc() failed");
+ return NULL;
+ }
+ if (rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &pf->rule, ret, &rule,
+ error) >= 0)
+ return pf;
+ free(pf);
+ return NULL;
+}
+
+/** Print a message out of a flow error. */
+static int
+port_flow_complain(struct rte_flow_error *error)
+{
+ static const char *const errstrlist[] = {
+ [RTE_FLOW_ERROR_TYPE_NONE] = "no error",
+ [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
+ [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)",
+ [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field",
+ [RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER] = "transfer field",
+ [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure",
+ [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length",
+ [RTE_FLOW_ERROR_TYPE_ITEM_SPEC] = "item specification",
+ [RTE_FLOW_ERROR_TYPE_ITEM_LAST] = "item specification range",
+ [RTE_FLOW_ERROR_TYPE_ITEM_MASK] = "item specification mask",
+ [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item",
+ [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions",
+ [RTE_FLOW_ERROR_TYPE_ACTION_CONF] = "action configuration",
+ [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action",
+ };
+ const char *errstr;
+ char buf[32];
+ int err = rte_errno;
+
+ if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
+ !errstrlist[error->type])
+ errstr = "unknown type";
+ else
+ errstr = errstrlist[error->type];
+ printf("%s(): Caught PMD error type %d (%s): %s%s: %s\n", __func__,
+ error->type, errstr,
+ error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ",
+ error->cause), buf) : "",
+ error->message ? error->message : "(no stated reason)",
+ rte_strerror(err));
+ return -err;
+}
+
+/** Validate flow rule. */
+int
+port_flow_validate(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions)
+{
+ struct rte_flow_error error;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x11, sizeof(error));
+ if (rte_flow_validate(port_id, attr, pattern, actions, &error))
+ return port_flow_complain(&error);
+ printf("Flow rule validated\n");
+ return 0;
+}
+
+/** Update age action context by port_flow pointer. */
+void
+update_age_action_context(const struct rte_flow_action *actions,
+ struct port_flow *pf)
+{
+ struct rte_flow_action_age *age = NULL;
+
+ for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+ switch (actions->type) {
+ case RTE_FLOW_ACTION_TYPE_AGE:
+ age = (struct rte_flow_action_age *)
+ (uintptr_t)actions->conf;
+ age->context = pf;
+ return;
+ default:
+ break;
+ }
+ }
+}
+
+/** Create flow rule. */
+int
+port_flow_create(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions)
+{
+ struct rte_flow *flow;
+ struct rte_port *port;
+ struct port_flow *pf;
+ uint32_t id = 0;
+ struct rte_flow_error error;
+
+ port = &ports[port_id];
+ if (port->flow_list) {
+ if (port->flow_list->id == UINT32_MAX) {
+ printf("Highest rule ID is already assigned, delete"
+ " it first");
+ return -ENOMEM;
+ }
+ id = port->flow_list->id + 1;
+ }
+ pf = port_flow_new(attr, pattern, actions, &error);
+ if (!pf)
+ return port_flow_complain(&error);
+ update_age_action_context(actions, pf);
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x22, sizeof(error));
+ flow = rte_flow_create(port_id, attr, pattern, actions, &error);
+ if (!flow) {
+ free(pf);
+ return port_flow_complain(&error);
+ }
+ pf->next = port->flow_list;
+ pf->id = id;
+ pf->flow = flow;
+ port->flow_list = pf;
+ printf("Flow rule #%u created\n", pf->id);
+ return 0;
+}
+
+/** Destroy a number of flow rules. */
+int
+port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule)
+{
+ struct rte_port *port;
+ struct port_flow **tmp;
+ uint32_t c = 0;
+ int ret = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+ port = &ports[port_id];
+ tmp = &port->flow_list;
+ while (*tmp) {
+ uint32_t i;
+
+ for (i = 0; i != n; ++i) {
+ struct rte_flow_error error;
+ struct port_flow *pf = *tmp;
+
+ if (rule[i] != pf->id)
+ continue;
+ /*
+ * Poisoning to make sure PMDs update it in case
+ * of error.
+ */
+ memset(&error, 0x33, sizeof(error));
+ if (rte_flow_destroy(port_id, pf->flow, &error)) {
+ ret = port_flow_complain(&error);
+ continue;
+ }
+ printf("Flow rule #%u destroyed\n", pf->id);
+ *tmp = pf->next;
+ free(pf);
+ break;
+ }
+ if (i == n)
+ tmp = &(*tmp)->next;
+ ++c;
+ }
+ return ret;
+}
+
+/** Remove all flow rules. */
+int
+port_flow_flush(portid_t port_id)
+{
+ struct rte_flow_error error;
+ struct rte_port *port;
+ int ret = 0;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x44, sizeof(error));
+ if (rte_flow_flush(port_id, &error)) {
+ ret = port_flow_complain(&error);
+ if (port_id_is_invalid(port_id, DISABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return ret;
+ }
+ port = &ports[port_id];
+ while (port->flow_list) {
+ struct port_flow *pf = port->flow_list->next;
+
+ free(port->flow_list);
+ port->flow_list = pf;
+ }
+ return ret;
+}
+
+/** Dump all flow rules. */
+int
+port_flow_dump(portid_t port_id, const char *file_name)
+{
+ int ret = 0;
+ FILE *file = stdout;
+ struct rte_flow_error error;
+
+ if (file_name && strlen(file_name)) {
+ file = fopen(file_name, "w");
+ if (!file) {
+ printf("Failed to create file %s: %s\n", file_name,
+ strerror(errno));
+ return -errno;
+ }
+ }
+ ret = rte_flow_dev_dump(port_id, file, &error);
+ if (ret) {
+ port_flow_complain(&error);
+ printf("Failed to dump flow: %s\n", strerror(-ret));
+ } else
+ printf("Flow dump finished\n");
+ if (file_name && strlen(file_name))
+ fclose(file);
+ return ret;
+}
+
+/** Query a flow rule. */
+int
+port_flow_query(portid_t port_id, uint32_t rule,
+ const struct rte_flow_action *action)
+{
+ struct rte_flow_error error;
+ struct rte_port *port;
+ struct port_flow *pf;
+ const char *name;
+ union {
+ struct rte_flow_query_count count;
+ } query;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+ port = &ports[port_id];
+ for (pf = port->flow_list; pf; pf = pf->next)
+ if (pf->id == rule)
+ break;
+ if (!pf) {
+ printf("Flow rule #%u not found\n", rule);
+ return -ENOENT;
+ }
+ ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+ &name, sizeof(name),
+ (void *)(uintptr_t)action->type, &error);
+ if (ret < 0)
+ return port_flow_complain(&error);
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ break;
+ default:
+ printf("Cannot query action type %d (%s)\n",
+ action->type, name);
+ return -ENOTSUP;
+ }
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x55, sizeof(error));
+ memset(&query, 0, sizeof(query));
+ if (rte_flow_query(port_id, pf->flow, action, &query, &error))
+ return port_flow_complain(&error);
+ switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_COUNT:
+ printf("%s:\n"
+ " hits_set: %u\n"
+ " bytes_set: %u\n"
+ " hits: %" PRIu64 "\n"
+ " bytes: %" PRIu64 "\n",
+ name,
+ query.count.hits_set,
+ query.count.bytes_set,
+ query.count.hits,
+ query.count.bytes);
+ break;
+ default:
+ printf("Cannot display result for action type %d (%s)\n",
+ action->type, name);
+ break;
+ }
+ return 0;
+}
+
+/** List simply and destroy all aged flows. */
+void
+port_flow_aged(portid_t port_id, uint8_t destroy)
+{
+ void **contexts;
+ int nb_context, total = 0, idx;
+ struct rte_flow_error error;
+ struct port_flow *pf;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return;
+ total = rte_flow_get_aged_flows(port_id, NULL, 0, &error);
+ printf("Port %u total aged flows: %d\n", port_id, total);
+ if (total < 0) {
+ port_flow_complain(&error);
+ return;
+ }
+ if (total == 0)
+ return;
+ contexts = malloc(sizeof(void *) * total);
+ if (contexts == NULL) {
+ printf("Cannot allocate contexts for aged flow\n");
+ return;
+ }
+ printf("ID\tGroup\tPrio\tAttr\n");
+ nb_context = rte_flow_get_aged_flows(port_id, contexts, total, &error);
+ if (nb_context != total) {
+ printf("Port:%d get aged flows count(%d) != total(%d)\n",
+ port_id, nb_context, total);
+ free(contexts);
+ return;
+ }
+ for (idx = 0; idx < nb_context; idx++) {
+ pf = (struct port_flow *)contexts[idx];
+ if (!pf) {
+ printf("Error: get Null context in port %u\n", port_id);
+ continue;
+ }
+ printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t\n",
+ pf->id,
+ pf->rule.attr->group,
+ pf->rule.attr->priority,
+ pf->rule.attr->ingress ? 'i' : '-',
+ pf->rule.attr->egress ? 'e' : '-',
+ pf->rule.attr->transfer ? 't' : '-');
+ }
+ if (destroy) {
+ int ret;
+ uint32_t flow_id;
+
+ total = 0;
+ printf("\n");
+ for (idx = 0; idx < nb_context; idx++) {
+ pf = (struct port_flow *)contexts[idx];
+ if (!pf)
+ continue;
+ flow_id = pf->id;
+ ret = port_flow_destroy(port_id, 1, &flow_id);
+ if (!ret)
+ total++;
+ }
+ printf("%d flows be destroyed\n", total);
+ }
+ free(contexts);
+}
+
+/** List flow rules. */
+void
+port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n])
+{
+ struct rte_port *port;
+ struct port_flow *pf;
+ struct port_flow *list = NULL;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return;
+ port = &ports[port_id];
+ if (!port->flow_list)
+ return;
+ /* Sort flows by group, priority and ID. */
+ for (pf = port->flow_list; pf != NULL; pf = pf->next) {
+ struct port_flow **tmp;
+ const struct rte_flow_attr *curr = pf->rule.attr;
+
+ if (n) {
+ /* Filter out unwanted groups. */
+ for (i = 0; i != n; ++i)
+ if (curr->group == group[i])
+ break;
+ if (i == n)
+ continue;
+ }
+ for (tmp = &list; *tmp; tmp = &(*tmp)->tmp) {
+ const struct rte_flow_attr *comp = (*tmp)->rule.attr;
+
+ if (curr->group > comp->group ||
+ (curr->group == comp->group &&
+ curr->priority > comp->priority) ||
+ (curr->group == comp->group &&
+ curr->priority == comp->priority &&
+ pf->id > (*tmp)->id))
+ continue;
+ break;
+ }
+ pf->tmp = *tmp;
+ *tmp = pf;
+ }
+ printf("ID\tGroup\tPrio\tAttr\tRule\n");
+ for (pf = list; pf != NULL; pf = pf->tmp) {
+ const struct rte_flow_item *item = pf->rule.pattern;
+ const struct rte_flow_action *action = pf->rule.actions;
+ const char *name;
+
+ printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t",
+ pf->id,
+ pf->rule.attr->group,
+ pf->rule.attr->priority,
+ pf->rule.attr->ingress ? 'i' : '-',
+ pf->rule.attr->egress ? 'e' : '-',
+ pf->rule.attr->transfer ? 't' : '-');
+ while (item->type != RTE_FLOW_ITEM_TYPE_END) {
+ if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR,
+ &name, sizeof(name),
+ (void *)(uintptr_t)item->type,
+ NULL) <= 0)
+ name = "[UNKNOWN]";
+ if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
+ printf("%s ", name);
+ ++item;
+ }
+ printf("=>");
+ while (action->type != RTE_FLOW_ACTION_TYPE_END) {
+ if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
+ &name, sizeof(name),
+ (void *)(uintptr_t)action->type,
+ NULL) <= 0)
+ name = "[UNKNOWN]";
+ if (action->type != RTE_FLOW_ACTION_TYPE_VOID)
+ printf(" %s", name);
+ ++action;
+ }
+ printf("\n");
+ }
+}
+
+/** Restrict ingress traffic to the defined flow rules. */
+int
+port_flow_isolate(portid_t port_id, int set)
+{
+ struct rte_flow_error error;
+
+ /* Poisoning to make sure PMDs update it in case of error. */
+ memset(&error, 0x66, sizeof(error));
+ if (rte_flow_isolate(port_id, set, &error))
+ return port_flow_complain(&error);
+ printf("Ingress traffic on port %u is %s to the defined flow rules\n",
+ port_id,
+ set ? "now restricted" : "not restricted anymore");
+ return 0;
+}
+
+/*
+ * RX/TX ring descriptors display functions.
+ */
+int
+rx_queue_id_is_invalid(queueid_t rxq_id)
+{
+ if (rxq_id < nb_rxq)
+ return 0;
+ printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq);
+ return 1;
+}
+
+int
+tx_queue_id_is_invalid(queueid_t txq_id)
+{
+ if (txq_id < nb_txq)
+ return 0;
+ printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq);
+ return 1;
+}
+
+static int
+rx_desc_id_is_invalid(uint16_t rxdesc_id)
+{
+ if (rxdesc_id < nb_rxd)
+ return 0;
+ printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n",
+ rxdesc_id, nb_rxd);
+ return 1;
+}
+
+static int
+tx_desc_id_is_invalid(uint16_t txdesc_id)
+{
+ if (txdesc_id < nb_txd)
+ return 0;
+ printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n",
+ txdesc_id, nb_txd);
+ return 1;
+}
+
+static const struct rte_memzone *
+ring_dma_zone_lookup(const char *ring_name, portid_t port_id, uint16_t q_id)
+{
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+ const struct rte_memzone *mz;
+
+ snprintf(mz_name, sizeof(mz_name), "eth_p%d_q%d_%s",
+ port_id, q_id, ring_name);
+ mz = rte_memzone_lookup(mz_name);
+ if (mz == NULL)
+ printf("%s ring memory zoneof (port %d, queue %d) not"
+ "found (zone name = %s\n",
+ ring_name, port_id, q_id, mz_name);
+ return mz;
+}
+
+union igb_ring_dword {
+ uint64_t dword;
+ struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint32_t lo;
+ uint32_t hi;
+#else
+ uint32_t hi;
+ uint32_t lo;
+#endif
+ } words;
+};
+
+struct igb_ring_desc_32_bytes {
+ union igb_ring_dword lo_dword;
+ union igb_ring_dword hi_dword;
+ union igb_ring_dword resv1;
+ union igb_ring_dword resv2;
+};
+
+struct igb_ring_desc_16_bytes {
+ union igb_ring_dword lo_dword;
+ union igb_ring_dword hi_dword;
+};
+
+static void
+ring_rxd_display_dword(union igb_ring_dword dword)
+{
+ printf(" 0x%08X - 0x%08X\n", (unsigned)dword.words.lo,
+ (unsigned)dword.words.hi);
+}
+
+static void
+ring_rx_descriptor_display(const struct rte_memzone *ring_mz,
+#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
+ portid_t port_id,
+#else
+ __rte_unused portid_t port_id,
+#endif
+ uint16_t desc_id)
+{
+ struct igb_ring_desc_16_bytes *ring =
+ (struct igb_ring_desc_16_bytes *)ring_mz->addr;
+#ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
+ int ret;
+ struct rte_eth_dev_info dev_info;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (strstr(dev_info.driver_name, "i40e") != NULL) {
+ /* 32 bytes RX descriptor, i40e only */
+ struct igb_ring_desc_32_bytes *ring =
+ (struct igb_ring_desc_32_bytes *)ring_mz->addr;
+ ring[desc_id].lo_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].lo_dword);
+ ring[desc_id].hi_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].hi_dword);
+ ring[desc_id].resv1.dword =
+ rte_le_to_cpu_64(ring[desc_id].resv1.dword);
+ ring_rxd_display_dword(ring[desc_id].resv1);
+ ring[desc_id].resv2.dword =
+ rte_le_to_cpu_64(ring[desc_id].resv2.dword);
+ ring_rxd_display_dword(ring[desc_id].resv2);
+
+ return;
+ }
+#endif
+ /* 16 bytes RX descriptor */
+ ring[desc_id].lo_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].lo_dword);
+ ring[desc_id].hi_dword.dword =
+ rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ ring_rxd_display_dword(ring[desc_id].hi_dword);
+}
+
+static void
+ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id)
+{
+ struct igb_ring_desc_16_bytes *ring;
+ struct igb_ring_desc_16_bytes txd;
+
+ ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr;
+ txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
+ txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
+ printf(" 0x%08X - 0x%08X / 0x%08X - 0x%08X\n",
+ (unsigned)txd.lo_dword.words.lo,
+ (unsigned)txd.lo_dword.words.hi,
+ (unsigned)txd.hi_dword.words.lo,
+ (unsigned)txd.hi_dword.words.hi);
+}
+
+void
+rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
+{
+ const struct rte_memzone *rx_mz;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (rx_queue_id_is_invalid(rxq_id))
+ return;
+ if (rx_desc_id_is_invalid(rxd_id))
+ return;
+ rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id);
+ if (rx_mz == NULL)
+ return;
+ ring_rx_descriptor_display(rx_mz, port_id, rxd_id);
+}
+
+void
+tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
+{
+ const struct rte_memzone *tx_mz;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (tx_queue_id_is_invalid(txq_id))
+ return;
+ if (tx_desc_id_is_invalid(txd_id))
+ return;
+ tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id);
+ if (tx_mz == NULL)
+ return;
+ ring_tx_descriptor_display(tx_mz, txd_id);
+}
+
+void
+fwd_lcores_config_display(void)
+{
+ lcoreid_t lc_id;
+
+ printf("List of forwarding lcores:");
+ for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++)
+ printf(" %2u", fwd_lcores_cpuids[lc_id]);
+ printf("\n");
+}
+void
+rxtx_config_display(void)
+{
+ portid_t pid;
+ queueid_t qid;
+
+ printf(" %s packet forwarding%s packets/burst=%d\n",
+ cur_fwd_eng->fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry",
+ nb_pkt_per_burst);
+
+ if (cur_fwd_eng == &tx_only_engine || cur_fwd_eng == &flow_gen_engine)
+ printf(" packet len=%u - nb packet segments=%d\n",
+ (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs);
+
+ printf(" nb forwarding cores=%d - nb forwarding ports=%d\n",
+ nb_fwd_lcores, nb_fwd_ports);
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ struct rte_eth_rxconf *rx_conf = &ports[pid].rx_conf[0];
+ struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0];
+ uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0];
+ uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0];
+ uint16_t nb_rx_desc_tmp;
+ uint16_t nb_tx_desc_tmp;
+ struct rte_eth_rxq_info rx_qinfo;
+ struct rte_eth_txq_info tx_qinfo;
+ int32_t rc;
+
+ /* per port config */
+ printf(" port %d: RX queue number: %d Tx queue number: %d\n",
+ (unsigned int)pid, nb_rxq, nb_txq);
+
+ printf(" Rx offloads=0x%"PRIx64" Tx offloads=0x%"PRIx64"\n",
+ ports[pid].dev_conf.rxmode.offloads,
+ ports[pid].dev_conf.txmode.offloads);
+
+ /* per rx queue config only for first queue to be less verbose */
+ for (qid = 0; qid < 1; qid++) {
+ rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo);
+ if (rc)
+ nb_rx_desc_tmp = nb_rx_desc[qid];
+ else
+ nb_rx_desc_tmp = rx_qinfo.nb_desc;
+
+ printf(" RX queue: %d\n", qid);
+ printf(" RX desc=%d - RX free threshold=%d\n",
+ nb_rx_desc_tmp, rx_conf[qid].rx_free_thresh);
+ printf(" RX threshold registers: pthresh=%d hthresh=%d "
+ " wthresh=%d\n",
+ rx_conf[qid].rx_thresh.pthresh,
+ rx_conf[qid].rx_thresh.hthresh,
+ rx_conf[qid].rx_thresh.wthresh);
+ printf(" RX Offloads=0x%"PRIx64"\n",
+ rx_conf[qid].offloads);
+ }
+
+ /* per tx queue config only for first queue to be less verbose */
+ for (qid = 0; qid < 1; qid++) {
+ rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo);
+ if (rc)
+ nb_tx_desc_tmp = nb_tx_desc[qid];
+ else
+ nb_tx_desc_tmp = tx_qinfo.nb_desc;
+
+ printf(" TX queue: %d\n", qid);
+ printf(" TX desc=%d - TX free threshold=%d\n",
+ nb_tx_desc_tmp, tx_conf[qid].tx_free_thresh);
+ printf(" TX threshold registers: pthresh=%d hthresh=%d "
+ " wthresh=%d\n",
+ tx_conf[qid].tx_thresh.pthresh,
+ tx_conf[qid].tx_thresh.hthresh,
+ tx_conf[qid].tx_thresh.wthresh);
+ printf(" TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n",
+ tx_conf[qid].offloads, tx_conf->tx_rs_thresh);
+ }
+ }
+}
+
+void
+port_rss_reta_info(portid_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries)
+{
+ uint16_t i, idx, shift;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
+ if (ret != 0) {
+ printf("Failed to get RSS RETA info, return code = %d\n", ret);
+ return;
+ }
+
+ for (i = 0; i < nb_entries; i++) {
+ idx = i / RTE_RETA_GROUP_SIZE;
+ shift = i % RTE_RETA_GROUP_SIZE;
+ if (!(reta_conf[idx].mask & (1ULL << shift)))
+ continue;
+ printf("RSS RETA configuration: hash index=%u, queue=%u\n",
+ i, reta_conf[idx].reta[shift]);
+ }
+}
+
+/*
+ * Displays the RSS hash functions of a port, and, optionaly, the RSS hash
+ * key of the port.
+ */
+void
+port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
+{
+ struct rte_eth_rss_conf rss_conf = {0};
+ uint8_t rss_key[RSS_HASH_KEY_LENGTH];
+ uint64_t rss_hf;
+ uint8_t i;
+ int diag;
+ struct rte_eth_dev_info dev_info;
+ uint8_t hash_key_size;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if (dev_info.hash_key_size > 0 &&
+ dev_info.hash_key_size <= sizeof(rss_key))
+ hash_key_size = dev_info.hash_key_size;
+ else {
+ printf("dev_info did not provide a valid hash key size\n");
+ return;
+ }
+
+ /* Get RSS hash key if asked to display it */
+ rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
+ rss_conf.rss_key_len = hash_key_size;
+ diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
+ if (diag != 0) {
+ switch (diag) {
+ case -ENODEV:
+ printf("port index %d invalid\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("operation not supported by device\n");
+ break;
+ default:
+ printf("operation failed - diag=%d\n", diag);
+ break;
+ }
+ return;
+ }
+ rss_hf = rss_conf.rss_hf;
+ if (rss_hf == 0) {
+ printf("RSS disabled\n");
+ return;
+ }
+ printf("RSS functions:\n ");
+ for (i = 0; rss_type_table[i].str; i++) {
+ if (rss_hf & rss_type_table[i].rss_type)
+ printf("%s ", rss_type_table[i].str);
+ }
+ printf("\n");
+ if (!show_rss_key)
+ return;
+ printf("RSS key:\n");
+ for (i = 0; i < hash_key_size; i++)
+ printf("%02X", rss_key[i]);
+ printf("\n");
+}
+
+void
+port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key,
+ uint hash_key_len)
+{
+ struct rte_eth_rss_conf rss_conf;
+ int diag;
+ unsigned int i;
+
+ rss_conf.rss_key = NULL;
+ rss_conf.rss_key_len = hash_key_len;
+ rss_conf.rss_hf = 0;
+ for (i = 0; rss_type_table[i].str; i++) {
+ if (!strcmp(rss_type_table[i].str, rss_type))
+ rss_conf.rss_hf = rss_type_table[i].rss_type;
+ }
+ diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
+ if (diag == 0) {
+ rss_conf.rss_key = hash_key;
+ diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf);
+ }
+ if (diag == 0)
+ return;
+
+ switch (diag) {
+ case -ENODEV:
+ printf("port index %d invalid\n", port_id);
+ break;
+ case -ENOTSUP:
+ printf("operation not supported by device\n");
+ break;
+ default:
+ printf("operation failed - diag=%d\n", diag);
+ break;
+ }
+}
+
+/*
+ * Setup forwarding configuration for each logical core.
+ */
+static void
+setup_fwd_config_of_each_lcore(struct fwd_config *cfg)
+{
+ streamid_t nb_fs_per_lcore;
+ streamid_t nb_fs;
+ streamid_t sm_id;
+ lcoreid_t nb_extra;
+ lcoreid_t nb_fc;
+ lcoreid_t nb_lc;
+ lcoreid_t lc_id;
+
+ nb_fs = cfg->nb_fwd_streams;
+ nb_fc = cfg->nb_fwd_lcores;
+ if (nb_fs <= nb_fc) {
+ nb_fs_per_lcore = 1;
+ nb_extra = 0;
+ } else {
+ nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc);
+ nb_extra = (lcoreid_t) (nb_fs % nb_fc);
+ }
+
+ nb_lc = (lcoreid_t) (nb_fc - nb_extra);
+ sm_id = 0;
+ for (lc_id = 0; lc_id < nb_lc; lc_id++) {
+ fwd_lcores[lc_id]->stream_idx = sm_id;
+ fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore;
+ sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
+ }
+
+ /*
+ * Assign extra remaining streams, if any.
+ */
+ nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1);
+ for (lc_id = 0; lc_id < nb_extra; lc_id++) {
+ fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id;
+ fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore;
+ sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
+ }
+}
+
+static portid_t
+fwd_topology_tx_port_get(portid_t rxp)
+{
+ static int warning_once = 1;
+
+ RTE_ASSERT(rxp < cur_fwd_config.nb_fwd_ports);
+
+ switch (port_topology) {
+ default:
+ case PORT_TOPOLOGY_PAIRED:
+ if ((rxp & 0x1) == 0) {
+ if (rxp + 1 < cur_fwd_config.nb_fwd_ports)
+ return rxp + 1;
+ if (warning_once) {
+ printf("\nWarning! port-topology=paired"
+ " and odd forward ports number,"
+ " the last port will pair with"
+ " itself.\n\n");
+ warning_once = 0;
+ }
+ return rxp;
+ }
+ return rxp - 1;
+ case PORT_TOPOLOGY_CHAINED:
+ return (rxp + 1) % cur_fwd_config.nb_fwd_ports;
+ case PORT_TOPOLOGY_LOOP:
+ return rxp;
+ }
+}
+
+static void
+simple_fwd_config_setup(void)
+{
+ portid_t i;
+
+ cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) cur_fwd_config.nb_fwd_ports;
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+
+ /*
+ * In the simple forwarding test, the number of forwarding cores
+ * must be lower or equal to the number of forwarding ports.
+ */
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t) cur_fwd_config.nb_fwd_ports;
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ fwd_streams[i]->rx_port = fwd_ports_ids[i];
+ fwd_streams[i]->rx_queue = 0;
+ fwd_streams[i]->tx_port =
+ fwd_ports_ids[fwd_topology_tx_port_get(i)];
+ fwd_streams[i]->tx_queue = 0;
+ fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port;
+ fwd_streams[i]->retry_enabled = retry_enabled;
+ }
+}
+
+/**
+ * For the RSS forwarding test all streams distributed over lcores. Each stream
+ * being composed of a RX queue to poll on a RX port for input messages,
+ * associated with a TX queue of a TX port where to send forwarded packets.
+ */
+static void
+rss_fwd_config_setup(void)
+{
+ portid_t rxp;
+ portid_t txp;
+ queueid_t rxq;
+ queueid_t nb_q;
+ streamid_t sm_id;
+
+ nb_q = nb_rxq;
+ if (nb_q > nb_txq)
+ nb_q = nb_txq;
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports);
+
+ if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t)cur_fwd_config.nb_fwd_streams;
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+ rxp = 0; rxq = 0;
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ struct fwd_stream *fs;
+
+ fs = fwd_streams[sm_id];
+ txp = fwd_topology_tx_port_get(rxp);
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq;
+ fs->tx_port = fwd_ports_ids[txp];
+ fs->tx_queue = rxq;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ rxp++;
+ if (rxp < nb_fwd_ports)
+ continue;
+ rxp = 0;
+ rxq++;
+ }
+}
+
+/**
+ * For the DCB forwarding test, each core is assigned on each traffic class.
+ *
+ * Each core is assigned a multi-stream, each stream being composed of
+ * a RX queue to poll on a RX port for input messages, associated with
+ * a TX queue of a TX port where to send forwarded packets. All RX and
+ * TX queues are mapping to the same traffic class.
+ * If VMDQ and DCB co-exist, each traffic class on different POOLs share
+ * the same core
+ */
+static void
+dcb_fwd_config_setup(void)
+{
+ struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
+ portid_t txp, rxp = 0;
+ queueid_t txq, rxq = 0;
+ lcoreid_t lc_id;
+ uint16_t nb_rx_queue, nb_tx_queue;
+ uint16_t i, j, k, sm_id = 0;
+ uint8_t tc = 0;
+
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+ sm_id = 0;
+ txp = 1;
+ /* get the dcb info on the first RX and TX ports */
+ (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+ (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
+
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
+ fwd_lcores[lc_id]->stream_nb = 0;
+ fwd_lcores[lc_id]->stream_idx = sm_id;
+ for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
+ /* if the nb_queue is zero, means this tc is
+ * not enabled on the POOL
+ */
+ if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
+ break;
+ k = fwd_lcores[lc_id]->stream_nb +
+ fwd_lcores[lc_id]->stream_idx;
+ rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
+ txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
+ nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
+ nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
+ for (j = 0; j < nb_rx_queue; j++) {
+ struct fwd_stream *fs;
+
+ fs = fwd_streams[k + j];
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq + j;
+ fs->tx_port = fwd_ports_ids[txp];
+ fs->tx_queue = txq + j % nb_tx_queue;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ }
+ fwd_lcores[lc_id]->stream_nb +=
+ rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
+ }
+ sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb);
+
+ tc++;
+ if (tc < rxp_dcb_info.nb_tcs)
+ continue;
+ /* Restart from TC 0 on next RX port */
+ tc = 0;
+ if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
+ rxp = (portid_t)
+ (rxp + ((nb_ports >> 1) / nb_fwd_ports));
+ else
+ rxp++;
+ if (rxp >= nb_fwd_ports)
+ return;
+ /* get the dcb information on next RX and TX ports */
+ if ((rxp & 0x1) == 0)
+ txp = (portid_t) (rxp + 1);
+ else
+ txp = (portid_t) (rxp - 1);
+ rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+ rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
+ }
+}
+
+static void
+icmp_echo_config_setup(void)
+{
+ portid_t rxp;
+ queueid_t rxq;
+ lcoreid_t lc_id;
+ uint16_t sm_id;
+
+ if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t)
+ (nb_txq * nb_fwd_ports);
+ else
+ cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
+ cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
+ cur_fwd_config.nb_fwd_streams =
+ (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
+ if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
+ cur_fwd_config.nb_fwd_lcores =
+ (lcoreid_t)cur_fwd_config.nb_fwd_streams;
+ if (verbose_level > 0) {
+ printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n",
+ __FUNCTION__,
+ cur_fwd_config.nb_fwd_lcores,
+ cur_fwd_config.nb_fwd_ports,
+ cur_fwd_config.nb_fwd_streams);
+ }
+
+ /* reinitialize forwarding streams */
+ init_fwd_streams();
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+ rxp = 0; rxq = 0;
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
+ if (verbose_level > 0)
+ printf(" core=%d: \n", lc_id);
+ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
+ struct fwd_stream *fs;
+ fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
+ fs->rx_port = fwd_ports_ids[rxp];
+ fs->rx_queue = rxq;
+ fs->tx_port = fs->rx_port;
+ fs->tx_queue = rxq;
+ fs->peer_addr = fs->tx_port;
+ fs->retry_enabled = retry_enabled;
+ if (verbose_level > 0)
+ printf(" stream=%d port=%d rxq=%d txq=%d\n",
+ sm_id, fs->rx_port, fs->rx_queue,
+ fs->tx_queue);
+ rxq = (queueid_t) (rxq + 1);
+ if (rxq == nb_rxq) {
+ rxq = 0;
+ rxp = (portid_t) (rxp + 1);
+ }
+ }
+ }
+}
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+static void
+softnic_fwd_config_setup(void)
+{
+ struct rte_port *port;
+ portid_t pid, softnic_portid;
+ queueid_t i;
+ uint8_t softnic_enable = 0;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ const char *driver = port->dev_info.driver_name;
+
+ if (strcmp(driver, "net_softnic") == 0) {
+ softnic_portid = pid;
+ softnic_enable = 1;
+ break;
+ }
+ }
+
+ if (softnic_enable == 0) {
+ printf("Softnic mode not configured(%s)!\n", __func__);
+ return;
+ }
+
+ cur_fwd_config.nb_fwd_ports = 1;
+ cur_fwd_config.nb_fwd_streams = (streamid_t) nb_rxq;
+
+ /* Re-initialize forwarding streams */
+ init_fwd_streams();
+
+ /*
+ * In the softnic forwarding test, the number of forwarding cores
+ * is set to one and remaining are used for softnic packet processing.
+ */
+ cur_fwd_config.nb_fwd_lcores = 1;
+ setup_fwd_config_of_each_lcore(&cur_fwd_config);
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_streams; i++) {
+ fwd_streams[i]->rx_port = softnic_portid;
+ fwd_streams[i]->rx_queue = i;
+ fwd_streams[i]->tx_port = softnic_portid;
+ fwd_streams[i]->tx_queue = i;
+ fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port;
+ fwd_streams[i]->retry_enabled = retry_enabled;
+ }
+}
+#endif
+
+void
+fwd_config_setup(void)
+{
+ cur_fwd_config.fwd_eng = cur_fwd_eng;
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) {
+ icmp_echo_config_setup();
+ return;
+ }
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) {
+ softnic_fwd_config_setup();
+ return;
+ }
+#endif
+
+ if ((nb_rxq > 1) && (nb_txq > 1)){
+ if (dcb_config)
+ dcb_fwd_config_setup();
+ else
+ rss_fwd_config_setup();
+ }
+ else
+ simple_fwd_config_setup();
+}
+
+static const char *
+mp_alloc_to_str(uint8_t mode)
+{
+ switch (mode) {
+ case MP_ALLOC_NATIVE:
+ return "native";
+ case MP_ALLOC_ANON:
+ return "anon";
+ case MP_ALLOC_XMEM:
+ return "xmem";
+ case MP_ALLOC_XMEM_HUGE:
+ return "xmemhuge";
+ case MP_ALLOC_XBUF:
+ return "xbuf";
+ default:
+ return "invalid";
+ }
+}
+
+void
+pkt_fwd_config_display(struct fwd_config *cfg)
+{
+ struct fwd_stream *fs;
+ lcoreid_t lc_id;
+ streamid_t sm_id;
+
+ printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
+ "NUMA support %s, MP allocation mode: %s\n",
+ cfg->fwd_eng->fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry",
+ cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
+ numa_support == 1 ? "enabled" : "disabled",
+ mp_alloc_to_str(mp_alloc_type));
+
+ if (retry_enabled)
+ printf("TX retry num: %u, delay between TX retries: %uus\n",
+ burst_tx_retry_num, burst_tx_delay_time);
+ for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) {
+ printf("Logical Core %u (socket %u) forwards packets on "
+ "%d streams:",
+ fwd_lcores_cpuids[lc_id],
+ rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]),
+ fwd_lcores[lc_id]->stream_nb);
+ for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
+ fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
+ printf("\n RX P=%d/Q=%d (socket %u) -> TX "
+ "P=%d/Q=%d (socket %u) ",
+ fs->rx_port, fs->rx_queue,
+ ports[fs->rx_port].socket_id,
+ fs->tx_port, fs->tx_queue,
+ ports[fs->tx_port].socket_id);
+ print_ethaddr("peer=",
+ &peer_eth_addrs[fs->peer_addr]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+}
+
+void
+set_fwd_eth_peer(portid_t port_id, char *peer_addr)
+{
+ struct rte_ether_addr new_peer_addr;
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("Error: Invalid port number %i\n", port_id);
+ return;
+ }
+ if (rte_ether_unformat_addr(peer_addr, &new_peer_addr) < 0) {
+ printf("Error: Invalid ethernet address: %s\n", peer_addr);
+ return;
+ }
+ peer_eth_addrs[port_id] = new_peer_addr;
+}
+
+int
+set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc)
+{
+ unsigned int i;
+ unsigned int lcore_cpuid;
+ int record_now;
+
+ record_now = 0;
+ again:
+ for (i = 0; i < nb_lc; i++) {
+ lcore_cpuid = lcorelist[i];
+ if (! rte_lcore_is_enabled(lcore_cpuid)) {
+ printf("lcore %u not enabled\n", lcore_cpuid);
+ return -1;
+ }
+ if (lcore_cpuid == rte_get_master_lcore()) {
+ printf("lcore %u cannot be masked on for running "
+ "packet forwarding, which is the master lcore "
+ "and reserved for command line parsing only\n",
+ lcore_cpuid);
+ return -1;
+ }
+ if (record_now)
+ fwd_lcores_cpuids[i] = lcore_cpuid;
+ }
+ if (record_now == 0) {
+ record_now = 1;
+ goto again;
+ }
+ nb_cfg_lcores = (lcoreid_t) nb_lc;
+ if (nb_fwd_lcores != (lcoreid_t) nb_lc) {
+ printf("previous number of forwarding cores %u - changed to "
+ "number of configured cores %u\n",
+ (unsigned int) nb_fwd_lcores, nb_lc);
+ nb_fwd_lcores = (lcoreid_t) nb_lc;
+ }
+
+ return 0;
+}
+
+int
+set_fwd_lcores_mask(uint64_t lcoremask)
+{
+ unsigned int lcorelist[64];
+ unsigned int nb_lc;
+ unsigned int i;
+
+ if (lcoremask == 0) {
+ printf("Invalid NULL mask of cores\n");
+ return -1;
+ }
+ nb_lc = 0;
+ for (i = 0; i < 64; i++) {
+ if (! ((uint64_t)(1ULL << i) & lcoremask))
+ continue;
+ lcorelist[nb_lc++] = i;
+ }
+ return set_fwd_lcores_list(lcorelist, nb_lc);
+}
+
+void
+set_fwd_lcores_number(uint16_t nb_lc)
+{
+ if (nb_lc > nb_cfg_lcores) {
+ printf("nb fwd cores %u > %u (max. number of configured "
+ "lcores) - ignored\n",
+ (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores);
+ return;
+ }
+ nb_fwd_lcores = (lcoreid_t) nb_lc;
+ printf("Number of forwarding cores set to %u\n",
+ (unsigned int) nb_fwd_lcores);
+}
+
+void
+set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
+{
+ unsigned int i;
+ portid_t port_id;
+ int record_now;
+
+ record_now = 0;
+ again:
+ for (i = 0; i < nb_pt; i++) {
+ port_id = (portid_t) portlist[i];
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (record_now)
+ fwd_ports_ids[i] = port_id;
+ }
+ if (record_now == 0) {
+ record_now = 1;
+ goto again;
+ }
+ nb_cfg_ports = (portid_t) nb_pt;
+ if (nb_fwd_ports != (portid_t) nb_pt) {
+ printf("previous number of forwarding ports %u - changed to "
+ "number of configured ports %u\n",
+ (unsigned int) nb_fwd_ports, nb_pt);
+ nb_fwd_ports = (portid_t) nb_pt;
+ }
+}
+
+/**
+ * Parse the user input and obtain the list of forwarding ports
+ *
+ * @param[in] list
+ * String containing the user input. User can specify
+ * in these formats 1,3,5 or 1-3 or 1-2,5 or 3,5-6.
+ * For example, if the user wants to use all the available
+ * 4 ports in his system, then the input can be 0-3 or 0,1,2,3.
+ * If the user wants to use only the ports 1,2 then the input
+ * is 1,2.
+ * valid characters are '-' and ','
+ * @param[out] values
+ * This array will be filled with a list of port IDs
+ * based on the user input
+ * Note that duplicate entries are discarded and only the first
+ * count entries in this array are port IDs and all the rest
+ * will contain default values
+ * @param[in] maxsize
+ * This parameter denotes 2 things
+ * 1) Number of elements in the values array
+ * 2) Maximum value of each element in the values array
+ * @return
+ * On success, returns total count of parsed port IDs
+ * On failure, returns 0
+ */
+static unsigned int
+parse_port_list(const char *list, unsigned int *values, unsigned int maxsize)
+{
+ unsigned int count = 0;
+ char *end = NULL;
+ int min, max;
+ int value, i;
+ unsigned int marked[maxsize];
+
+ if (list == NULL || values == NULL)
+ return 0;
+
+ for (i = 0; i < (int)maxsize; i++)
+ marked[i] = 0;
+
+ min = INT_MAX;
+
+ do {
+ /*Remove the blank spaces if any*/
+ while (isblank(*list))
+ list++;
+ if (*list == '\0')
+ break;
+ errno = 0;
+ value = strtol(list, &end, 10);
+ if (errno || end == NULL)
+ return 0;
+ if (value < 0 || value >= (int)maxsize)
+ return 0;
+ while (isblank(*end))
+ end++;
+ if (*end == '-' && min == INT_MAX) {
+ min = value;
+ } else if ((*end == ',') || (*end == '\0')) {
+ max = value;
+ if (min == INT_MAX)
+ min = value;
+ for (i = min; i <= max; i++) {
+ if (count < maxsize) {
+ if (marked[i])
+ continue;
+ values[count] = i;
+ marked[i] = 1;
+ count++;
+ }
+ }
+ min = INT_MAX;
+ } else
+ return 0;
+ list = end + 1;
+ } while (*end != '\0');
+
+ return count;
+}
+
+void
+parse_fwd_portlist(const char *portlist)
+{
+ unsigned int portcount;
+ unsigned int portindex[RTE_MAX_ETHPORTS];
+ unsigned int i, valid_port_count = 0;
+
+ portcount = parse_port_list(portlist, portindex, RTE_MAX_ETHPORTS);
+ if (!portcount)
+ rte_exit(EXIT_FAILURE, "Invalid fwd port list\n");
+
+ /*
+ * Here we verify the validity of the ports
+ * and thereby calculate the total number of
+ * valid ports
+ */
+ for (i = 0; i < portcount && i < RTE_DIM(portindex); i++) {
+ if (rte_eth_dev_is_valid_port(portindex[i])) {
+ portindex[valid_port_count] = portindex[i];
+ valid_port_count++;
+ }
+ }
+
+ set_fwd_ports_list(portindex, valid_port_count);
+}
+
+void
+set_fwd_ports_mask(uint64_t portmask)
+{
+ unsigned int portlist[64];
+ unsigned int nb_pt;
+ unsigned int i;
+
+ if (portmask == 0) {
+ printf("Invalid NULL mask of ports\n");
+ return;
+ }
+ nb_pt = 0;
+ RTE_ETH_FOREACH_DEV(i) {
+ if (! ((uint64_t)(1ULL << i) & portmask))
+ continue;
+ portlist[nb_pt++] = i;
+ }
+ set_fwd_ports_list(portlist, nb_pt);
+}
+
+void
+set_fwd_ports_number(uint16_t nb_pt)
+{
+ if (nb_pt > nb_cfg_ports) {
+ printf("nb fwd ports %u > %u (number of configured "
+ "ports) - ignored\n",
+ (unsigned int) nb_pt, (unsigned int) nb_cfg_ports);
+ return;
+ }
+ nb_fwd_ports = (portid_t) nb_pt;
+ printf("Number of forwarding ports set to %u\n",
+ (unsigned int) nb_fwd_ports);
+}
+
+int
+port_is_forwarding(portid_t port_id)
+{
+ unsigned int i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return -1;
+
+ for (i = 0; i < nb_fwd_ports; i++) {
+ if (fwd_ports_ids[i] == port_id)
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+set_nb_pkt_per_burst(uint16_t nb)
+{
+ if (nb > MAX_PKT_BURST) {
+ printf("nb pkt per burst: %u > %u (maximum packet per burst) "
+ " ignored\n",
+ (unsigned int) nb, (unsigned int) MAX_PKT_BURST);
+ return;
+ }
+ nb_pkt_per_burst = nb;
+ printf("Number of packets per burst set to %u\n",
+ (unsigned int) nb_pkt_per_burst);
+}
+
+static const char *
+tx_split_get_name(enum tx_pkt_split split)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+ if (tx_split_name[i].split == split)
+ return tx_split_name[i].name;
+ }
+ return NULL;
+}
+
+void
+set_tx_pkt_split(const char *name)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+ if (strcmp(tx_split_name[i].name, name) == 0) {
+ tx_pkt_split = tx_split_name[i].split;
+ return;
+ }
+ }
+ printf("unknown value: \"%s\"\n", name);
+}
+
+void
+show_tx_pkt_segments(void)
+{
+ uint32_t i, n;
+ const char *split;
+
+ n = tx_pkt_nb_segs;
+ split = tx_split_get_name(tx_pkt_split);
+
+ printf("Number of segments: %u\n", n);
+ printf("Segment sizes: ");
+ for (i = 0; i != n - 1; i++)
+ printf("%hu,", tx_pkt_seg_lengths[i]);
+ printf("%hu\n", tx_pkt_seg_lengths[i]);
+ printf("Split packet: %s\n", split);
+}
+
+void
+set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs)
+{
+ uint16_t tx_pkt_len;
+ unsigned i;
+
+ if (nb_segs >= (unsigned) nb_txd) {
+ printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n",
+ nb_segs, (unsigned int) nb_txd);
+ return;
+ }
+
+ /*
+ * Check that each segment length is greater or equal than
+ * the mbuf data sise.
+ * Check also that the total packet length is greater or equal than the
+ * size of an empty UDP/IP packet (sizeof(struct rte_ether_hdr) +
+ * 20 + 8).
+ */
+ tx_pkt_len = 0;
+ for (i = 0; i < nb_segs; i++) {
+ if (seg_lengths[i] > (unsigned) mbuf_data_size) {
+ printf("length[%u]=%u > mbuf_data_size=%u - give up\n",
+ i, seg_lengths[i], (unsigned) mbuf_data_size);
+ return;
+ }
+ tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]);
+ }
+ if (tx_pkt_len < (sizeof(struct rte_ether_hdr) + 20 + 8)) {
+ printf("total packet length=%u < %d - give up\n",
+ (unsigned) tx_pkt_len,
+ (int)(sizeof(struct rte_ether_hdr) + 20 + 8));
+ return;
+ }
+
+ for (i = 0; i < nb_segs; i++)
+ tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i];
+
+ tx_pkt_length = tx_pkt_len;
+ tx_pkt_nb_segs = (uint8_t) nb_segs;
+}
+
+void
+setup_gro(const char *onoff, portid_t port_id)
+{
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("invalid port id %u\n", port_id);
+ return;
+ }
+ if (test_done == 0) {
+ printf("Before enable/disable GRO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ if (strcmp(onoff, "on") == 0) {
+ if (gro_ports[port_id].enable != 0) {
+ printf("Port %u has enabled GRO. Please"
+ " disable GRO first\n", port_id);
+ return;
+ }
+ if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
+ gro_ports[port_id].param.gro_types = RTE_GRO_TCP_IPV4;
+ gro_ports[port_id].param.max_flow_num =
+ GRO_DEFAULT_FLOW_NUM;
+ gro_ports[port_id].param.max_item_per_flow =
+ GRO_DEFAULT_ITEM_NUM_PER_FLOW;
+ }
+ gro_ports[port_id].enable = 1;
+ } else {
+ if (gro_ports[port_id].enable == 0) {
+ printf("Port %u has disabled GRO\n", port_id);
+ return;
+ }
+ gro_ports[port_id].enable = 0;
+ }
+}
+
+void
+setup_gro_flush_cycles(uint8_t cycles)
+{
+ if (test_done == 0) {
+ printf("Before change flush interval for GRO,"
+ " please stop forwarding first.\n");
+ return;
+ }
+
+ if (cycles > GRO_MAX_FLUSH_CYCLES || cycles <
+ GRO_DEFAULT_FLUSH_CYCLES) {
+ printf("The flushing cycle be in the range"
+ " of 1 to %u. Revert to the default"
+ " value %u.\n",
+ GRO_MAX_FLUSH_CYCLES,
+ GRO_DEFAULT_FLUSH_CYCLES);
+ cycles = GRO_DEFAULT_FLUSH_CYCLES;
+ }
+
+ gro_flush_cycles = cycles;
+}
+
+void
+show_gro(portid_t port_id)
+{
+ struct rte_gro_param *param;
+ uint32_t max_pkts_num;
+
+ param = &gro_ports[port_id].param;
+
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("Invalid port id %u.\n", port_id);
+ return;
+ }
+ if (gro_ports[port_id].enable) {
+ printf("GRO type: TCP/IPv4\n");
+ if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
+ max_pkts_num = param->max_flow_num *
+ param->max_item_per_flow;
+ } else
+ max_pkts_num = MAX_PKT_BURST * GRO_MAX_FLUSH_CYCLES;
+ printf("Max number of packets to perform GRO: %u\n",
+ max_pkts_num);
+ printf("Flushing cycles: %u\n", gro_flush_cycles);
+ } else
+ printf("Port %u doesn't enable GRO.\n", port_id);
+}
+
+void
+setup_gso(const char *mode, portid_t port_id)
+{
+ if (!rte_eth_dev_is_valid_port(port_id)) {
+ printf("invalid port id %u\n", port_id);
+ return;
+ }
+ if (strcmp(mode, "on") == 0) {
+ if (test_done == 0) {
+ printf("before enabling GSO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ gso_ports[port_id].enable = 1;
+ } else if (strcmp(mode, "off") == 0) {
+ if (test_done == 0) {
+ printf("before disabling GSO,"
+ " please stop forwarding first\n");
+ return;
+ }
+ gso_ports[port_id].enable = 0;
+ }
+}
+
+char*
+list_pkt_forwarding_modes(void)
+{
+ static char fwd_modes[128] = "";
+ const char *separator = "|";
+ struct fwd_engine *fwd_eng;
+ unsigned i = 0;
+
+ if (strlen (fwd_modes) == 0) {
+ while ((fwd_eng = fwd_engines[i++]) != NULL) {
+ strncat(fwd_modes, fwd_eng->fwd_mode_name,
+ sizeof(fwd_modes) - strlen(fwd_modes) - 1);
+ strncat(fwd_modes, separator,
+ sizeof(fwd_modes) - strlen(fwd_modes) - 1);
+ }
+ fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
+ }
+
+ return fwd_modes;
+}
+
+char*
+list_pkt_forwarding_retry_modes(void)
+{
+ static char fwd_modes[128] = "";
+ const char *separator = "|";
+ struct fwd_engine *fwd_eng;
+ unsigned i = 0;
+
+ if (strlen(fwd_modes) == 0) {
+ while ((fwd_eng = fwd_engines[i++]) != NULL) {
+ if (fwd_eng == &rx_only_engine)
+ continue;
+ strncat(fwd_modes, fwd_eng->fwd_mode_name,
+ sizeof(fwd_modes) -
+ strlen(fwd_modes) - 1);
+ strncat(fwd_modes, separator,
+ sizeof(fwd_modes) -
+ strlen(fwd_modes) - 1);
+ }
+ fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
+ }
+
+ return fwd_modes;
+}
+
+void
+set_pkt_forwarding_mode(const char *fwd_mode_name)
+{
+ struct fwd_engine *fwd_eng;
+ unsigned i;
+
+ i = 0;
+ while ((fwd_eng = fwd_engines[i]) != NULL) {
+ if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) {
+ printf("Set %s packet forwarding mode%s\n",
+ fwd_mode_name,
+ retry_enabled == 0 ? "" : " with retry");
+ cur_fwd_eng = fwd_eng;
+ return;
+ }
+ i++;
+ }
+ printf("Invalid %s packet forwarding mode\n", fwd_mode_name);
+}
+
+void
+add_rx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
+ if (!ports[portid].rx_dump_cb[queue])
+ ports[portid].rx_dump_cb[queue] =
+ rte_eth_add_rx_callback(portid, queue,
+ dump_rx_pkts, NULL);
+}
+
+void
+add_tx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (!ports[portid].tx_dump_cb[queue])
+ ports[portid].tx_dump_cb[queue] =
+ rte_eth_add_tx_callback(portid, queue,
+ dump_tx_pkts, NULL);
+}
+
+void
+remove_rx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
+ if (ports[portid].rx_dump_cb[queue]) {
+ rte_eth_remove_rx_callback(portid, queue,
+ ports[portid].rx_dump_cb[queue]);
+ ports[portid].rx_dump_cb[queue] = NULL;
+ }
+}
+
+void
+remove_tx_dump_callbacks(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (ports[portid].tx_dump_cb[queue]) {
+ rte_eth_remove_tx_callback(portid, queue,
+ ports[portid].tx_dump_cb[queue]);
+ ports[portid].tx_dump_cb[queue] = NULL;
+ }
+}
+
+void
+configure_rxtx_dump_callbacks(uint16_t verbose)
+{
+ portid_t portid;
+
+#ifndef RTE_ETHDEV_RXTX_CALLBACKS
+ TESTPMD_LOG(ERR, "setting rxtx callbacks is not enabled\n");
+ return;
+#endif
+
+ RTE_ETH_FOREACH_DEV(portid)
+ {
+ if (verbose == 1 || verbose > 2)
+ add_rx_dump_callbacks(portid);
+ else
+ remove_rx_dump_callbacks(portid);
+ if (verbose >= 2)
+ add_tx_dump_callbacks(portid);
+ else
+ remove_tx_dump_callbacks(portid);
+ }
+}
+
+void
+set_verbose_level(uint16_t vb_level)
+{
+ printf("Change verbose level from %u to %u\n",
+ (unsigned int) verbose_level, (unsigned int) vb_level);
+ verbose_level = vb_level;
+ configure_rxtx_dump_callbacks(verbose_level);
+}
+
+void
+vlan_extend_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+ uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on) {
+ vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD;
+ port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
+ } else {
+ vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD;
+ port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_EXTEND;
+ }
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+ ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
+}
+
+void
+rx_vlan_strip_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+ uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on) {
+ vlan_offload |= ETH_VLAN_STRIP_OFFLOAD;
+ port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
+ } else {
+ vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD;
+ port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
+ }
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+ ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
+}
+
+void
+rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
+ if (diag < 0)
+ printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed "
+ "diag=%d\n", port_id, queue_id, on, diag);
+}
+
+void
+rx_vlan_filter_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+ uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on) {
+ vlan_offload |= ETH_VLAN_FILTER_OFFLOAD;
+ port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+ } else {
+ vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD;
+ port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
+ }
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed "
+ "diag=%d\n", port_id, on, diag);
+ ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
+}
+
+void
+rx_vlan_qinq_strip_set(portid_t port_id, int on)
+{
+ int diag;
+ int vlan_offload;
+ uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
+
+ if (on) {
+ vlan_offload |= ETH_QINQ_STRIP_OFFLOAD;
+ port_rx_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
+ } else {
+ vlan_offload &= ~ETH_QINQ_STRIP_OFFLOAD;
+ port_rx_offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
+ }
+
+ diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
+ if (diag < 0)
+ printf("%s(port_pi=%d, on=%d) failed "
+ "diag=%d\n", __func__, port_id, on, diag);
+ ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
+}
+
+int
+rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 1;
+ if (vlan_id_is_invalid(vlan_id))
+ return 1;
+ diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
+ if (diag == 0)
+ return 0;
+ printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed "
+ "diag=%d\n",
+ port_id, vlan_id, on, diag);
+ return -1;
+}
+
+void
+rx_vlan_all_filter_set(portid_t port_id, int on)
+{
+ uint16_t vlan_id;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ for (vlan_id = 0; vlan_id < 4096; vlan_id++) {
+ if (rx_vft_set(port_id, vlan_id, on))
+ break;
+ }
+}
+
+void
+vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id)
+{
+ int diag;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id);
+ if (diag == 0)
+ return;
+
+ printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed "
+ "diag=%d\n",
+ port_id, vlan_type, tp_id, diag);
+}
+
+void
+tx_vlan_set(portid_t port_id, uint16_t vlan_id)
+{
+ struct rte_eth_dev_info dev_info;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (vlan_id_is_invalid(vlan_id))
+ return;
+
+ if (ports[port_id].dev_conf.txmode.offloads &
+ DEV_TX_OFFLOAD_QINQ_INSERT) {
+ printf("Error, as QinQ has been enabled.\n");
+ return;
+ }
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) == 0) {
+ printf("Error: vlan insert is not supported by port %d\n",
+ port_id);
+ return;
+ }
+
+ tx_vlan_reset(port_id);
+ ports[port_id].dev_conf.txmode.offloads |= DEV_TX_OFFLOAD_VLAN_INSERT;
+ ports[port_id].tx_vlan_id = vlan_id;
+}
+
+void
+tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
+{
+ struct rte_eth_dev_info dev_info;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (vlan_id_is_invalid(vlan_id))
+ return;
+ if (vlan_id_is_invalid(vlan_id_outer))
+ return;
+
+ ret = eth_dev_info_get_print_err(port_id, &dev_info);
+ if (ret != 0)
+ return;
+
+ if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) == 0) {
+ printf("Error: qinq insert not supported by port %d\n",
+ port_id);
+ return;
+ }
+
+ tx_vlan_reset(port_id);
+ ports[port_id].dev_conf.txmode.offloads |= (DEV_TX_OFFLOAD_VLAN_INSERT |
+ DEV_TX_OFFLOAD_QINQ_INSERT);
+ ports[port_id].tx_vlan_id = vlan_id;
+ ports[port_id].tx_vlan_id_outer = vlan_id_outer;
+}
+
+void
+tx_vlan_reset(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ ports[port_id].dev_conf.txmode.offloads &=
+ ~(DEV_TX_OFFLOAD_VLAN_INSERT |
+ DEV_TX_OFFLOAD_QINQ_INSERT);
+ ports[port_id].tx_vlan_id = 0;
+ ports[port_id].tx_vlan_id_outer = 0;
+}
+
+void
+tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
+}
+
+void
+set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
+{
+ uint16_t i;
+ uint8_t existing_mapping_found = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
+ return;
+
+ if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ printf("map_value not in required range 0..%d\n",
+ RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ return;
+ }
+
+ if (!is_rx) { /*then tx*/
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if ((tx_queue_stats_mappings[i].port_id == port_id) &&
+ (tx_queue_stats_mappings[i].queue_id == queue_id)) {
+ tx_queue_stats_mappings[i].stats_counter_id = map_value;
+ existing_mapping_found = 1;
+ break;
+ }
+ }
+ if (!existing_mapping_found) { /* A new additional mapping... */
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id;
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id;
+ tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value;
+ nb_tx_queue_stats_mappings++;
+ }
+ }
+ else { /*rx*/
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if ((rx_queue_stats_mappings[i].port_id == port_id) &&
+ (rx_queue_stats_mappings[i].queue_id == queue_id)) {
+ rx_queue_stats_mappings[i].stats_counter_id = map_value;
+ existing_mapping_found = 1;
+ break;
+ }
+ }
+ if (!existing_mapping_found) { /* A new additional mapping... */
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id;
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id;
+ rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value;
+ nb_rx_queue_stats_mappings++;
+ }
+ }
+}
+
+void
+set_xstats_hide_zero(uint8_t on_off)
+{
+ xstats_hide_zero = on_off;
+}
+
+static inline void
+print_fdir_mask(struct rte_eth_fdir_masks *mask)
+{
+ printf("\n vlan_tci: 0x%04x", rte_be_to_cpu_16(mask->vlan_tci_mask));
+
+ if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+ printf(", mac_addr: 0x%02x, tunnel_type: 0x%01x,"
+ " tunnel_id: 0x%08x",
+ mask->mac_addr_byte_mask, mask->tunnel_type_mask,
+ rte_be_to_cpu_32(mask->tunnel_id_mask));
+ else if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
+ printf(", src_ipv4: 0x%08x, dst_ipv4: 0x%08x",
+ rte_be_to_cpu_32(mask->ipv4_mask.src_ip),
+ rte_be_to_cpu_32(mask->ipv4_mask.dst_ip));
+
+ printf("\n src_port: 0x%04x, dst_port: 0x%04x",
+ rte_be_to_cpu_16(mask->src_port_mask),
+ rte_be_to_cpu_16(mask->dst_port_mask));
+
+ printf("\n src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[0]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[1]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[2]),
+ rte_be_to_cpu_32(mask->ipv6_mask.src_ip[3]));
+
+ printf("\n dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[0]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[1]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[2]),
+ rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[3]));
+ }
+
+ printf("\n");
+}
+
+static inline void
+print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
+{
+ struct rte_eth_flex_payload_cfg *cfg;
+ uint32_t i, j;
+
+ for (i = 0; i < flex_conf->nb_payloads; i++) {
+ cfg = &flex_conf->flex_set[i];
+ if (cfg->type == RTE_ETH_RAW_PAYLOAD)
+ printf("\n RAW: ");
+ else if (cfg->type == RTE_ETH_L2_PAYLOAD)
+ printf("\n L2_PAYLOAD: ");
+ else if (cfg->type == RTE_ETH_L3_PAYLOAD)
+ printf("\n L3_PAYLOAD: ");
+ else if (cfg->type == RTE_ETH_L4_PAYLOAD)
+ printf("\n L4_PAYLOAD: ");
+ else
+ printf("\n UNKNOWN PAYLOAD(%u): ", cfg->type);
+ for (j = 0; j < num; j++)
+ printf(" %-5u", cfg->src_offset[j]);
+ }
+ printf("\n");
+}
+
+static char *
+flowtype_to_str(uint16_t flow_type)
+{
+ struct flow_type_info {
+ char str[32];
+ uint16_t ftype;
+ };
+
+ uint8_t i;
+ static struct flow_type_info flowtype_str_table[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ {"port", RTE_ETH_FLOW_PORT},
+ {"vxlan", RTE_ETH_FLOW_VXLAN},
+ {"geneve", RTE_ETH_FLOW_GENEVE},
+ {"nvgre", RTE_ETH_FLOW_NVGRE},
+ {"vxlan-gpe", RTE_ETH_FLOW_VXLAN_GPE},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str_table); i++) {
+ if (flowtype_str_table[i].ftype == flow_type)
+ return flowtype_str_table[i].str;
+ }
+
+ return NULL;
+}
+
+static inline void
+print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
+{
+ struct rte_eth_fdir_flex_mask *mask;
+ uint32_t i, j;
+ char *p;
+
+ for (i = 0; i < flex_conf->nb_flexmasks; i++) {
+ mask = &flex_conf->flex_mask[i];
+ p = flowtype_to_str(mask->flow_type);
+ printf("\n %s:\t", p ? p : "unknown");
+ for (j = 0; j < num; j++)
+ printf(" %02x", mask->mask[j]);
+ }
+ printf("\n");
+}
+
+static inline void
+print_fdir_flow_type(uint32_t flow_types_mask)
+{
+ int i;
+ char *p;
+
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+ if (!(flow_types_mask & (1 << i)))
+ continue;
+ p = flowtype_to_str(i);
+ if (p)
+ printf(" %s", p);
+ else
+ printf(" unknown");
+ }
+ printf("\n");
+}
+
+void
+fdir_get_infos(portid_t port_id)
+{
+ struct rte_eth_fdir_stats fdir_stat;
+ struct rte_eth_fdir_info fdir_info;
+ int ret;
+
+ static const char *fdir_stats_border = "########################";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
+ if (ret < 0) {
+ printf("\n FDIR is not supported on port %-2d\n",
+ port_id);
+ return;
+ }
+
+ memset(&fdir_info, 0, sizeof(fdir_info));
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_INFO, &fdir_info);
+ memset(&fdir_stat, 0, sizeof(fdir_stat));
+ rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
+ RTE_ETH_FILTER_STATS, &fdir_stat);
+ printf("\n %s FDIR infos for port %-2d %s\n",
+ fdir_stats_border, port_id, fdir_stats_border);
+ printf(" MODE: ");
+ if (fdir_info.mode == RTE_FDIR_MODE_PERFECT)
+ printf(" PERFECT\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+ printf(" PERFECT-MAC-VLAN\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+ printf(" PERFECT-TUNNEL\n");
+ else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE)
+ printf(" SIGNATURE\n");
+ else
+ printf(" DISABLE\n");
+ if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN
+ && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+ printf(" SUPPORTED FLOW TYPE: ");
+ print_fdir_flow_type(fdir_info.flow_types_mask[0]);
+ }
+ printf(" FLEX PAYLOAD INFO:\n");
+ printf(" max_len: %-10"PRIu32" payload_limit: %-10"PRIu32"\n"
+ " payload_unit: %-10"PRIu32" payload_seg: %-10"PRIu32"\n"
+ " bitmask_unit: %-10"PRIu32" bitmask_num: %-10"PRIu32"\n",
+ fdir_info.max_flexpayload, fdir_info.flex_payload_limit,
+ fdir_info.flex_payload_unit,
+ fdir_info.max_flex_payload_segment_num,
+ fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num);
+ printf(" MASK: ");
+ print_fdir_mask(&fdir_info.mask);
+ if (fdir_info.flex_conf.nb_payloads > 0) {
+ printf(" FLEX PAYLOAD SRC OFFSET:");
+ print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload);
+ }
+ if (fdir_info.flex_conf.nb_flexmasks > 0) {
+ printf(" FLEX MASK CFG:");
+ print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload);
+ }
+ printf(" guarant_count: %-10"PRIu32" best_count: %"PRIu32"\n",
+ fdir_stat.guarant_cnt, fdir_stat.best_cnt);
+ printf(" guarant_space: %-10"PRIu32" best_space: %"PRIu32"\n",
+ fdir_info.guarant_spc, fdir_info.best_spc);
+ printf(" collision: %-10"PRIu32" free: %"PRIu32"\n"
+ " maxhash: %-10"PRIu32" maxlen: %"PRIu32"\n"
+ " add: %-10"PRIu64" remove: %"PRIu64"\n"
+ " f_add: %-10"PRIu64" f_remove: %"PRIu64"\n",
+ fdir_stat.collision, fdir_stat.free,
+ fdir_stat.maxhash, fdir_stat.maxlen,
+ fdir_stat.add, fdir_stat.remove,
+ fdir_stat.f_add, fdir_stat.f_remove);
+ printf(" %s############################%s\n",
+ fdir_stats_border, fdir_stats_border);
+}
+
+void
+fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
+{
+ struct rte_port *port;
+ struct rte_eth_fdir_flex_conf *flex_conf;
+ int i, idx = 0;
+
+ port = &ports[port_id];
+ flex_conf = &port->dev_conf.fdir_conf.flex_conf;
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
+ if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) {
+ idx = i;
+ break;
+ }
+ }
+ if (i >= RTE_ETH_FLOW_MAX) {
+ if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) {
+ idx = flex_conf->nb_flexmasks;
+ flex_conf->nb_flexmasks++;
+ } else {
+ printf("The flex mask table is full. Can not set flex"
+ " mask for flow_type(%u).", cfg->flow_type);
+ return;
+ }
+ }
+ rte_memcpy(&flex_conf->flex_mask[idx],
+ cfg,
+ sizeof(struct rte_eth_fdir_flex_mask));
+}
+
+void
+fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg)
+{
+ struct rte_port *port;
+ struct rte_eth_fdir_flex_conf *flex_conf;
+ int i, idx = 0;
+
+ port = &ports[port_id];
+ flex_conf = &port->dev_conf.fdir_conf.flex_conf;
+ for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) {
+ if (cfg->type == flex_conf->flex_set[i].type) {
+ idx = i;
+ break;
+ }
+ }
+ if (i >= RTE_ETH_PAYLOAD_MAX) {
+ if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) {
+ idx = flex_conf->nb_payloads;
+ flex_conf->nb_payloads++;
+ } else {
+ printf("The flex payload table is full. Can not set"
+ " flex payload for type(%u).", cfg->type);
+ return;
+ }
+ }
+ rte_memcpy(&flex_conf->flex_set[idx],
+ cfg,
+ sizeof(struct rte_eth_flex_payload_cfg));
+
+}
+
+void
+set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
+{
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ int diag;
+
+ if (is_rx)
+ diag = rte_pmd_ixgbe_set_vf_rx(port_id, vf, on);
+ else
+ diag = rte_pmd_ixgbe_set_vf_tx(port_id, vf, on);
+
+ if (diag == 0)
+ return;
+ printf("rte_pmd_ixgbe_set_vf_%s for port_id=%d failed diag=%d\n",
+ is_rx ? "rx" : "tx", port_id, diag);
+ return;
+#endif
+ printf("VF %s setting not supported for port %d\n",
+ is_rx ? "Rx" : "Tx", port_id);
+ RTE_SET_USED(vf);
+ RTE_SET_USED(on);
+}
+
+int
+set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
+{
+ int diag;
+ struct rte_eth_link link;
+ int ret;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 1;
+ ret = eth_link_get_nowait_print_err(port_id, &link);
+ if (ret < 0)
+ return 1;
+ if (rate > link.link_speed) {
+ printf("Invalid rate value:%u bigger than link speed: %u\n",
+ rate, link.link_speed);
+ return 1;
+ }
+ diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate);
+ if (diag == 0)
+ return diag;
+ printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n",
+ port_id, diag);
+ return diag;
+}
+
+int
+set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
+{
+ int diag = -ENOTSUP;
+
+ RTE_SET_USED(vf);
+ RTE_SET_USED(rate);
+ RTE_SET_USED(q_msk);
+
+#ifdef RTE_LIBRTE_IXGBE_PMD
+ if (diag == -ENOTSUP)
+ diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate,
+ q_msk);
+#endif
+#ifdef RTE_LIBRTE_BNXT_PMD
+ if (diag == -ENOTSUP)
+ diag = rte_pmd_bnxt_set_vf_rate_limit(port_id, vf, rate, q_msk);
+#endif
+ if (diag == 0)
+ return diag;
+
+ printf("set_vf_rate_limit for port_id=%d failed diag=%d\n",
+ port_id, diag);
+ return diag;
+}
+
+/*
+ * Functions to manage the set of filtered Multicast MAC addresses.
+ *
+ * A pool of filtered multicast MAC addresses is associated with each port.
+ * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses.
+ * The address of the pool and the number of valid multicast MAC addresses
+ * recorded in the pool are stored in the fields "mc_addr_pool" and
+ * "mc_addr_nb" of the "rte_port" data structure.
+ *
+ * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes
+ * to be supplied a contiguous array of multicast MAC addresses.
+ * To comply with this constraint, the set of multicast addresses recorded
+ * into the pool are systematically compacted at the beginning of the pool.
+ * Hence, when a multicast address is removed from the pool, all following
+ * addresses, if any, are copied back to keep the set contiguous.
+ */
+#define MCAST_POOL_INC 32
+
+static int
+mcast_addr_pool_extend(struct rte_port *port)
+{
+ struct rte_ether_addr *mc_pool;
+ size_t mc_pool_size;
+
+ /*
+ * If a free entry is available at the end of the pool, just
+ * increment the number of recorded multicast addresses.
+ */
+ if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) {
+ port->mc_addr_nb++;
+ return 0;
+ }
+
+ /*
+ * [re]allocate a pool with MCAST_POOL_INC more entries.
+ * The previous test guarantees that port->mc_addr_nb is a multiple
+ * of MCAST_POOL_INC.
+ */
+ mc_pool_size = sizeof(struct rte_ether_addr) * (port->mc_addr_nb +
+ MCAST_POOL_INC);
+ mc_pool = (struct rte_ether_addr *) realloc(port->mc_addr_pool,
+ mc_pool_size);
+ if (mc_pool == NULL) {
+ printf("allocation of pool of %u multicast addresses failed\n",
+ port->mc_addr_nb + MCAST_POOL_INC);
+ return -ENOMEM;
+ }
+
+ port->mc_addr_pool = mc_pool;
+ port->mc_addr_nb++;
+ return 0;
+
+}
+
+static void
+mcast_addr_pool_append(struct rte_port *port, struct rte_ether_addr *mc_addr)
+{
+ if (mcast_addr_pool_extend(port) != 0)
+ return;
+ rte_ether_addr_copy(mc_addr, &port->mc_addr_pool[port->mc_addr_nb - 1]);
+}
+
+static void
+mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
+{
+ port->mc_addr_nb--;
+ if (addr_idx == port->mc_addr_nb) {
+ /* No need to recompact the set of multicast addressses. */
+ if (port->mc_addr_nb == 0) {
+ /* free the pool of multicast addresses. */
+ free(port->mc_addr_pool);
+ port->mc_addr_pool = NULL;
+ }
+ return;
+ }
+ memmove(&port->mc_addr_pool[addr_idx],
+ &port->mc_addr_pool[addr_idx + 1],
+ sizeof(struct rte_ether_addr) * (port->mc_addr_nb - addr_idx));
+}
+
+static int
+eth_port_multicast_addr_list_set(portid_t port_id)
+{
+ struct rte_port *port;
+ int diag;
+
+ port = &ports[port_id];
+ diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool,
+ port->mc_addr_nb);
+ if (diag < 0)
+ printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
+ port_id, port->mc_addr_nb, diag);
+
+ return diag;
+}
+
+void
+mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr)
+{
+ struct rte_port *port;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[port_id];
+
+ /*
+ * Check that the added multicast MAC address is not already recorded
+ * in the pool of multicast addresses.
+ */
+ for (i = 0; i < port->mc_addr_nb; i++) {
+ if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) {
+ printf("multicast address already filtered by port\n");
+ return;
+ }
+ }
+
+ mcast_addr_pool_append(port, mc_addr);
+ if (eth_port_multicast_addr_list_set(port_id) < 0)
+ /* Rollback on failure, remove the address from the pool */
+ mcast_addr_pool_remove(port, i);
+}
+
+void
+mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr)
+{
+ struct rte_port *port;
+ uint32_t i;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[port_id];
+
+ /*
+ * Search the pool of multicast MAC addresses for the removed address.
+ */
+ for (i = 0; i < port->mc_addr_nb; i++) {
+ if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i]))
+ break;
+ }
+ if (i == port->mc_addr_nb) {
+ printf("multicast address not filtered by port %d\n", port_id);
+ return;
+ }
+
+ mcast_addr_pool_remove(port, i);
+ if (eth_port_multicast_addr_list_set(port_id) < 0)
+ /* Rollback on failure, add the address back into the pool */
+ mcast_addr_pool_append(port, mc_addr);
+}
+
+void
+port_dcb_info_display(portid_t port_id)
+{
+ struct rte_eth_dcb_info dcb_info;
+ uint16_t i;
+ int ret;
+ static const char *border = "================";
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
+ if (ret) {
+ printf("\n Failed to get dcb infos on port %-2d\n",
+ port_id);
+ return;
+ }
+ printf("\n %s DCB infos for port %-2d %s\n", border, port_id, border);
+ printf(" TC NUMBER: %d\n", dcb_info.nb_tcs);
+ printf("\n TC : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", i);
+ printf("\n Priority : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.prio_tc[i]);
+ printf("\n BW percent :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d%%", dcb_info.tc_bws[i]);
+ printf("\n RXQ base : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base);
+ printf("\n RXQ number :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue);
+ printf("\n TXQ base : ");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base);
+ printf("\n TXQ number :");
+ for (i = 0; i < dcb_info.nb_tcs; i++)
+ printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue);
+ printf("\n");
+}
+
+uint8_t *
+open_file(const char *file_path, uint32_t *size)
+{
+ int fd = open(file_path, O_RDONLY);
+ off_t pkg_size;
+ uint8_t *buf = NULL;
+ int ret = 0;
+ struct stat st_buf;
+
+ if (size)
+ *size = 0;
+
+ if (fd == -1) {
+ printf("%s: Failed to open %s\n", __func__, file_path);
+ return buf;
+ }
+
+ if ((fstat(fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
+ close(fd);
+ printf("%s: File operations failed\n", __func__);
+ return buf;
+ }
+
+ pkg_size = st_buf.st_size;
+ if (pkg_size < 0) {
+ close(fd);
+ printf("%s: File operations failed\n", __func__);
+ return buf;
+ }
+
+ buf = (uint8_t *)malloc(pkg_size);
+ if (!buf) {
+ close(fd);
+ printf("%s: Failed to malloc memory\n", __func__);
+ return buf;
+ }
+
+ ret = read(fd, buf, pkg_size);
+ if (ret < 0) {
+ close(fd);
+ printf("%s: File read operation failed\n", __func__);
+ close_file(buf);
+ return NULL;
+ }
+
+ if (size)
+ *size = pkg_size;
+
+ close(fd);
+
+ return buf;
+}
+
+int
+save_file(const char *file_path, uint8_t *buf, uint32_t size)
+{
+ FILE *fh = fopen(file_path, "wb");
+
+ if (fh == NULL) {
+ printf("%s: Failed to open %s\n", __func__, file_path);
+ return -1;
+ }
+
+ if (fwrite(buf, 1, size, fh) != size) {
+ fclose(fh);
+ printf("%s: File write operation failed\n", __func__);
+ return -1;
+ }
+
+ fclose(fh);
+
+ return 0;
+}
+
+int
+close_file(uint8_t *buf)
+{
+ if (buf) {
+ free((void *)buf);
+ return 0;
+ }
+
+ return -1;
+}
+
+void
+port_queue_region_info_display(portid_t port_id, void *buf)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+ uint16_t i, j;
+ struct rte_pmd_i40e_queue_regions *info =
+ (struct rte_pmd_i40e_queue_regions *)buf;
+ static const char *queue_region_info_stats_border = "-------";
+
+ if (!info->queue_region_number)
+ printf("there is no region has been set before");
+
+ printf("\n %s All queue region info for port=%2d %s",
+ queue_region_info_stats_border, port_id,
+ queue_region_info_stats_border);
+ printf("\n queue_region_number: %-14u \n",
+ info->queue_region_number);
+
+ for (i = 0; i < info->queue_region_number; i++) {
+ printf("\n region_id: %-14u queue_number: %-14u "
+ "queue_start_index: %-14u \n",
+ info->region[i].region_id,
+ info->region[i].queue_num,
+ info->region[i].queue_start_index);
+
+ printf(" user_priority_num is %-14u :",
+ info->region[i].user_priority_num);
+ for (j = 0; j < info->region[i].user_priority_num; j++)
+ printf(" %-14u ", info->region[i].user_priority[j]);
+
+ printf("\n flowtype_num is %-14u :",
+ info->region[i].flowtype_num);
+ for (j = 0; j < info->region[i].flowtype_num; j++)
+ printf(" %-14u ", info->region[i].hw_flowtype[j]);
+ }
+#else
+ RTE_SET_USED(port_id);
+ RTE_SET_USED(buf);
+#endif
+
+ printf("\n\n");
+}
+
+void
+show_macs(portid_t port_id)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+ struct rte_eth_dev_info dev_info;
+ struct rte_ether_addr *addr;
+ uint32_t i, num_macs = 0;
+ struct rte_eth_dev *dev;
+
+ dev = &rte_eth_devices[port_id];
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+
+ for (i = 0; i < dev_info.max_mac_addrs; i++) {
+ addr = &dev->data->mac_addrs[i];
+
+ /* skip zero address */
+ if (rte_is_zero_ether_addr(addr))
+ continue;
+
+ num_macs++;
+ }
+
+ printf("Number of MAC address added: %d\n", num_macs);
+
+ for (i = 0; i < dev_info.max_mac_addrs; i++) {
+ addr = &dev->data->mac_addrs[i];
+
+ /* skip zero address */
+ if (rte_is_zero_ether_addr(addr))
+ continue;
+
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr);
+ printf(" %s\n", buf);
+ }
+}
+
+void
+show_mcast_macs(portid_t port_id)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+ struct rte_ether_addr *addr;
+ struct rte_port *port;
+ uint32_t i;
+
+ port = &ports[port_id];
+
+ printf("Number of Multicast MAC address added: %d\n", port->mc_addr_nb);
+
+ for (i = 0; i < port->mc_addr_nb; i++) {
+ addr = &port->mc_addr_pool[i];
+
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr);
+ printf(" %s\n", buf);
+ }
+}
diff --git a/src/spdk/dpdk/app/test-pmd/csumonly.c b/src/spdk/dpdk/app/test-pmd/csumonly.c
new file mode 100644
index 000000000..862622379
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/csumonly.c
@@ -0,0 +1,1112 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright 2014 6WIND S.A.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_vxlan.h>
+#include <rte_sctp.h>
+#include <rte_gtp.h>
+#include <rte_prefetch.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+#include <rte_gro.h>
+#include <rte_gso.h>
+
+#include "testpmd.h"
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+
+#define GRE_CHECKSUM_PRESENT 0x8000
+#define GRE_KEY_PRESENT 0x2000
+#define GRE_SEQUENCE_PRESENT 0x1000
+#define GRE_EXT_LEN 4
+#define GRE_SUPPORTED_FIELDS (GRE_CHECKSUM_PRESENT | GRE_KEY_PRESENT |\
+ GRE_SEQUENCE_PRESENT)
+
+/* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+#define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8)))
+#else
+#define _htons(x) (x)
+#endif
+
+uint16_t vxlan_gpe_udp_port = 4790;
+
+/* structure that caches offload info for the current packet */
+struct testpmd_offload_info {
+ uint16_t ethertype;
+ uint8_t gso_enable;
+ uint16_t l2_len;
+ uint16_t l3_len;
+ uint16_t l4_len;
+ uint8_t l4_proto;
+ uint8_t is_tunnel;
+ uint16_t outer_ethertype;
+ uint16_t outer_l2_len;
+ uint16_t outer_l3_len;
+ uint8_t outer_l4_proto;
+ uint16_t tso_segsz;
+ uint16_t tunnel_tso_segsz;
+ uint32_t pkt_len;
+};
+
+/* simplified GRE header */
+struct simple_gre_hdr {
+ uint16_t flags;
+ uint16_t proto;
+} __rte_packed;
+
+static uint16_t
+get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype)
+{
+ if (ethertype == _htons(RTE_ETHER_TYPE_IPV4))
+ return rte_ipv4_udptcp_cksum(l3_hdr, l4_hdr);
+ else /* assume ethertype == RTE_ETHER_TYPE_IPV6 */
+ return rte_ipv6_udptcp_cksum(l3_hdr, l4_hdr);
+}
+
+/* Parse an IPv4 header to fill l3_len, l4_len, and l4_proto */
+static void
+parse_ipv4(struct rte_ipv4_hdr *ipv4_hdr, struct testpmd_offload_info *info)
+{
+ struct rte_tcp_hdr *tcp_hdr;
+
+ info->l3_len = (ipv4_hdr->version_ihl & 0x0f) * 4;
+ info->l4_proto = ipv4_hdr->next_proto_id;
+
+ /* only fill l4_len for TCP, it's useful for TSO */
+ if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct rte_tcp_hdr *)
+ ((char *)ipv4_hdr + info->l3_len);
+ info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
+ } else if (info->l4_proto == IPPROTO_UDP)
+ info->l4_len = sizeof(struct rte_udp_hdr);
+ else
+ info->l4_len = 0;
+}
+
+/* Parse an IPv6 header to fill l3_len, l4_len, and l4_proto */
+static void
+parse_ipv6(struct rte_ipv6_hdr *ipv6_hdr, struct testpmd_offload_info *info)
+{
+ struct rte_tcp_hdr *tcp_hdr;
+
+ info->l3_len = sizeof(struct rte_ipv6_hdr);
+ info->l4_proto = ipv6_hdr->proto;
+
+ /* only fill l4_len for TCP, it's useful for TSO */
+ if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct rte_tcp_hdr *)
+ ((char *)ipv6_hdr + info->l3_len);
+ info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2;
+ } else if (info->l4_proto == IPPROTO_UDP)
+ info->l4_len = sizeof(struct rte_udp_hdr);
+ else
+ info->l4_len = 0;
+}
+
+/*
+ * Parse an ethernet header to fill the ethertype, l2_len, l3_len and
+ * ipproto. This function is able to recognize IPv4/IPv6 with optional VLAN
+ * headers. The l4_len argument is only set in case of TCP (useful for TSO).
+ */
+static void
+parse_ethernet(struct rte_ether_hdr *eth_hdr, struct testpmd_offload_info *info)
+{
+ struct rte_ipv4_hdr *ipv4_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ struct rte_vlan_hdr *vlan_hdr;
+
+ info->l2_len = sizeof(struct rte_ether_hdr);
+ info->ethertype = eth_hdr->ether_type;
+
+ while (info->ethertype == _htons(RTE_ETHER_TYPE_VLAN) ||
+ info->ethertype == _htons(RTE_ETHER_TYPE_QINQ)) {
+ vlan_hdr = (struct rte_vlan_hdr *)
+ ((char *)eth_hdr + info->l2_len);
+ info->l2_len += sizeof(struct rte_vlan_hdr);
+ info->ethertype = vlan_hdr->eth_proto;
+ }
+
+ switch (info->ethertype) {
+ case _htons(RTE_ETHER_TYPE_IPV4):
+ ipv4_hdr = (struct rte_ipv4_hdr *)
+ ((char *)eth_hdr + info->l2_len);
+ parse_ipv4(ipv4_hdr, info);
+ break;
+ case _htons(RTE_ETHER_TYPE_IPV6):
+ ipv6_hdr = (struct rte_ipv6_hdr *)
+ ((char *)eth_hdr + info->l2_len);
+ parse_ipv6(ipv6_hdr, info);
+ break;
+ default:
+ info->l4_len = 0;
+ info->l3_len = 0;
+ info->l4_proto = 0;
+ break;
+ }
+}
+
+/*
+ * Parse a GTP protocol header.
+ * No optional fields and next extension header type.
+ */
+static void
+parse_gtp(struct rte_udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info)
+{
+ struct rte_ipv4_hdr *ipv4_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ struct rte_gtp_hdr *gtp_hdr;
+ uint8_t gtp_len = sizeof(*gtp_hdr);
+ uint8_t ip_ver;
+
+ /* Check udp destination port. */
+ if (udp_hdr->dst_port != _htons(RTE_GTPC_UDP_PORT) &&
+ udp_hdr->src_port != _htons(RTE_GTPC_UDP_PORT) &&
+ udp_hdr->dst_port != _htons(RTE_GTPU_UDP_PORT))
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+ info->l2_len = 0;
+
+ gtp_hdr = (struct rte_gtp_hdr *)((char *)udp_hdr +
+ sizeof(struct rte_udp_hdr));
+
+ /*
+ * Check message type. If message type is 0xff, it is
+ * a GTP data packet. If not, it is a GTP control packet
+ */
+ if (gtp_hdr->msg_type == 0xff) {
+ ip_ver = *(uint8_t *)((char *)udp_hdr +
+ sizeof(struct rte_udp_hdr) +
+ sizeof(struct rte_gtp_hdr));
+ ip_ver = (ip_ver) & 0xf0;
+
+ if (ip_ver == RTE_GTP_TYPE_IPV4) {
+ ipv4_hdr = (struct rte_ipv4_hdr *)((char *)gtp_hdr +
+ gtp_len);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV4);
+ parse_ipv4(ipv4_hdr, info);
+ } else if (ip_ver == RTE_GTP_TYPE_IPV6) {
+ ipv6_hdr = (struct rte_ipv6_hdr *)((char *)gtp_hdr +
+ gtp_len);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV6);
+ parse_ipv6(ipv6_hdr, info);
+ }
+ } else {
+ info->ethertype = 0;
+ info->l4_len = 0;
+ info->l3_len = 0;
+ info->l4_proto = 0;
+ }
+
+ info->l2_len += RTE_ETHER_GTP_HLEN;
+}
+
+/* Parse a vxlan header */
+static void
+parse_vxlan(struct rte_udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info,
+ uint32_t pkt_type)
+{
+ struct rte_ether_hdr *eth_hdr;
+
+ /* check udp destination port, 4789 is the default vxlan port
+ * (rfc7348) or that the rx offload flag is set (i40e only
+ * currently) */
+ if (udp_hdr->dst_port != _htons(4789) &&
+ RTE_ETH_IS_TUNNEL_PKT(pkt_type) == 0)
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct rte_ether_hdr *)((char *)udp_hdr +
+ sizeof(struct rte_udp_hdr) +
+ sizeof(struct rte_vxlan_hdr));
+
+ parse_ethernet(eth_hdr, info);
+ info->l2_len += RTE_ETHER_VXLAN_HLEN; /* add udp + vxlan */
+}
+
+/* Parse a vxlan-gpe header */
+static void
+parse_vxlan_gpe(struct rte_udp_hdr *udp_hdr,
+ struct testpmd_offload_info *info)
+{
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_ipv4_hdr *ipv4_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ struct rte_vxlan_gpe_hdr *vxlan_gpe_hdr;
+ uint8_t vxlan_gpe_len = sizeof(*vxlan_gpe_hdr);
+
+ /* Check udp destination port. */
+ if (udp_hdr->dst_port != _htons(vxlan_gpe_udp_port))
+ return;
+
+ vxlan_gpe_hdr = (struct rte_vxlan_gpe_hdr *)((char *)udp_hdr +
+ sizeof(struct rte_udp_hdr));
+
+ if (!vxlan_gpe_hdr->proto || vxlan_gpe_hdr->proto ==
+ RTE_VXLAN_GPE_TYPE_IPV4) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv4_hdr = (struct rte_ipv4_hdr *)((char *)vxlan_gpe_hdr +
+ vxlan_gpe_len);
+
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV4);
+ info->l2_len = 0;
+
+ } else if (vxlan_gpe_hdr->proto == RTE_VXLAN_GPE_TYPE_IPV6) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv6_hdr = (struct rte_ipv6_hdr *)((char *)vxlan_gpe_hdr +
+ vxlan_gpe_len);
+
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV6);
+ parse_ipv6(ipv6_hdr, info);
+ info->l2_len = 0;
+
+ } else if (vxlan_gpe_hdr->proto == RTE_VXLAN_GPE_TYPE_ETH) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct rte_ether_hdr *)((char *)vxlan_gpe_hdr +
+ vxlan_gpe_len);
+
+ parse_ethernet(eth_hdr, info);
+ } else
+ return;
+
+ info->l2_len += RTE_ETHER_VXLAN_GPE_HLEN;
+}
+
+/* Parse a gre header */
+static void
+parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info)
+{
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_ipv4_hdr *ipv4_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ uint8_t gre_len = 0;
+
+ gre_len += sizeof(struct simple_gre_hdr);
+
+ if (gre_hdr->flags & _htons(GRE_KEY_PRESENT))
+ gre_len += GRE_EXT_LEN;
+ if (gre_hdr->flags & _htons(GRE_SEQUENCE_PRESENT))
+ gre_len += GRE_EXT_LEN;
+ if (gre_hdr->flags & _htons(GRE_CHECKSUM_PRESENT))
+ gre_len += GRE_EXT_LEN;
+
+ if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_IPV4)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv4_hdr = (struct rte_ipv4_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV4);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_IPV6)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ ipv6_hdr = (struct rte_ipv6_hdr *)((char *)gre_hdr + gre_len);
+
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV6);
+ parse_ipv6(ipv6_hdr, info);
+ info->l2_len = 0;
+
+ } else if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_TEB)) {
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+ info->outer_l4_proto = info->l4_proto;
+
+ eth_hdr = (struct rte_ether_hdr *)((char *)gre_hdr + gre_len);
+
+ parse_ethernet(eth_hdr, info);
+ } else
+ return;
+
+ info->l2_len += gre_len;
+}
+
+
+/* Parse an encapsulated ip or ipv6 header */
+static void
+parse_encap_ip(void *encap_ip, struct testpmd_offload_info *info)
+{
+ struct rte_ipv4_hdr *ipv4_hdr = encap_ip;
+ struct rte_ipv6_hdr *ipv6_hdr = encap_ip;
+ uint8_t ip_version;
+
+ ip_version = (ipv4_hdr->version_ihl & 0xf0) >> 4;
+
+ if (ip_version != 4 && ip_version != 6)
+ return;
+
+ info->is_tunnel = 1;
+ info->outer_ethertype = info->ethertype;
+ info->outer_l2_len = info->l2_len;
+ info->outer_l3_len = info->l3_len;
+
+ if (ip_version == 4) {
+ parse_ipv4(ipv4_hdr, info);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV4);
+ } else {
+ parse_ipv6(ipv6_hdr, info);
+ info->ethertype = _htons(RTE_ETHER_TYPE_IPV6);
+ }
+ info->l2_len = 0;
+}
+
+/* if possible, calculate the checksum of a packet in hw or sw,
+ * depending on the testpmd command line configuration */
+static uint64_t
+process_inner_cksums(void *l3_hdr, const struct testpmd_offload_info *info,
+ uint64_t tx_offloads)
+{
+ struct rte_ipv4_hdr *ipv4_hdr = l3_hdr;
+ struct rte_udp_hdr *udp_hdr;
+ struct rte_tcp_hdr *tcp_hdr;
+ struct rte_sctp_hdr *sctp_hdr;
+ uint64_t ol_flags = 0;
+ uint32_t max_pkt_len, tso_segsz = 0;
+
+ /* ensure packet is large enough to require tso */
+ if (!info->is_tunnel) {
+ max_pkt_len = info->l2_len + info->l3_len + info->l4_len +
+ info->tso_segsz;
+ if (info->tso_segsz != 0 && info->pkt_len > max_pkt_len)
+ tso_segsz = info->tso_segsz;
+ } else {
+ max_pkt_len = info->outer_l2_len + info->outer_l3_len +
+ info->l2_len + info->l3_len + info->l4_len +
+ info->tunnel_tso_segsz;
+ if (info->tunnel_tso_segsz != 0 && info->pkt_len > max_pkt_len)
+ tso_segsz = info->tunnel_tso_segsz;
+ }
+
+ if (info->ethertype == _htons(RTE_ETHER_TYPE_IPV4)) {
+ ipv4_hdr = l3_hdr;
+ ipv4_hdr->hdr_checksum = 0;
+
+ ol_flags |= PKT_TX_IPV4;
+ if (info->l4_proto == IPPROTO_TCP && tso_segsz) {
+ ol_flags |= PKT_TX_IP_CKSUM;
+ } else {
+ if (tx_offloads & DEV_TX_OFFLOAD_IPV4_CKSUM)
+ ol_flags |= PKT_TX_IP_CKSUM;
+ else
+ ipv4_hdr->hdr_checksum =
+ rte_ipv4_cksum(ipv4_hdr);
+ }
+ } else if (info->ethertype == _htons(RTE_ETHER_TYPE_IPV6))
+ ol_flags |= PKT_TX_IPV6;
+ else
+ return 0; /* packet type not supported, nothing to do */
+
+ if (info->l4_proto == IPPROTO_UDP) {
+ udp_hdr = (struct rte_udp_hdr *)((char *)l3_hdr + info->l3_len);
+ /* do not recalculate udp cksum if it was 0 */
+ if (udp_hdr->dgram_cksum != 0) {
+ udp_hdr->dgram_cksum = 0;
+ if (tx_offloads & DEV_TX_OFFLOAD_UDP_CKSUM)
+ ol_flags |= PKT_TX_UDP_CKSUM;
+ else {
+ udp_hdr->dgram_cksum =
+ get_udptcp_checksum(l3_hdr, udp_hdr,
+ info->ethertype);
+ }
+ }
+ if (info->gso_enable)
+ ol_flags |= PKT_TX_UDP_SEG;
+ } else if (info->l4_proto == IPPROTO_TCP) {
+ tcp_hdr = (struct rte_tcp_hdr *)((char *)l3_hdr + info->l3_len);
+ tcp_hdr->cksum = 0;
+ if (tso_segsz)
+ ol_flags |= PKT_TX_TCP_SEG;
+ else if (tx_offloads & DEV_TX_OFFLOAD_TCP_CKSUM)
+ ol_flags |= PKT_TX_TCP_CKSUM;
+ else {
+ tcp_hdr->cksum =
+ get_udptcp_checksum(l3_hdr, tcp_hdr,
+ info->ethertype);
+ }
+ if (info->gso_enable)
+ ol_flags |= PKT_TX_TCP_SEG;
+ } else if (info->l4_proto == IPPROTO_SCTP) {
+ sctp_hdr = (struct rte_sctp_hdr *)
+ ((char *)l3_hdr + info->l3_len);
+ sctp_hdr->cksum = 0;
+ /* sctp payload must be a multiple of 4 to be
+ * offloaded */
+ if ((tx_offloads & DEV_TX_OFFLOAD_SCTP_CKSUM) &&
+ ((ipv4_hdr->total_length & 0x3) == 0)) {
+ ol_flags |= PKT_TX_SCTP_CKSUM;
+ } else {
+ /* XXX implement CRC32c, example available in
+ * RFC3309 */
+ }
+ }
+
+ return ol_flags;
+}
+
+/* Calculate the checksum of outer header */
+static uint64_t
+process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info,
+ uint64_t tx_offloads, int tso_enabled)
+{
+ struct rte_ipv4_hdr *ipv4_hdr = outer_l3_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr = outer_l3_hdr;
+ struct rte_udp_hdr *udp_hdr;
+ uint64_t ol_flags = 0;
+
+ if (info->outer_ethertype == _htons(RTE_ETHER_TYPE_IPV4)) {
+ ipv4_hdr->hdr_checksum = 0;
+ ol_flags |= PKT_TX_OUTER_IPV4;
+
+ if (tx_offloads & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ else
+ ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr);
+ } else
+ ol_flags |= PKT_TX_OUTER_IPV6;
+
+ if (info->outer_l4_proto != IPPROTO_UDP)
+ return ol_flags;
+
+ udp_hdr = (struct rte_udp_hdr *)
+ ((char *)outer_l3_hdr + info->outer_l3_len);
+
+ if (tso_enabled)
+ ol_flags |= PKT_TX_TCP_SEG;
+
+ /* Skip SW outer UDP checksum generation if HW supports it */
+ if (tx_offloads & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) {
+ if (info->outer_ethertype == _htons(RTE_ETHER_TYPE_IPV4))
+ udp_hdr->dgram_cksum
+ = rte_ipv4_phdr_cksum(ipv4_hdr, ol_flags);
+ else
+ udp_hdr->dgram_cksum
+ = rte_ipv6_phdr_cksum(ipv6_hdr, ol_flags);
+
+ ol_flags |= PKT_TX_OUTER_UDP_CKSUM;
+ return ol_flags;
+ }
+
+ /* outer UDP checksum is done in software. In the other side, for
+ * UDP tunneling, like VXLAN or Geneve, outer UDP checksum can be
+ * set to zero.
+ *
+ * If a packet will be TSOed into small packets by NIC, we cannot
+ * set/calculate a non-zero checksum, because it will be a wrong
+ * value after the packet be split into several small packets.
+ */
+ if (tso_enabled)
+ udp_hdr->dgram_cksum = 0;
+
+ /* do not recalculate udp cksum if it was 0 */
+ if (udp_hdr->dgram_cksum != 0) {
+ udp_hdr->dgram_cksum = 0;
+ if (info->outer_ethertype == _htons(RTE_ETHER_TYPE_IPV4))
+ udp_hdr->dgram_cksum =
+ rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr);
+ else
+ udp_hdr->dgram_cksum =
+ rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr);
+ }
+
+ return ol_flags;
+}
+
+/*
+ * Helper function.
+ * Performs actual copying.
+ * Returns number of segments in the destination mbuf on success,
+ * or negative error code on failure.
+ */
+static int
+mbuf_copy_split(const struct rte_mbuf *ms, struct rte_mbuf *md[],
+ uint16_t seglen[], uint8_t nb_seg)
+{
+ uint32_t dlen, slen, tlen;
+ uint32_t i, len;
+ const struct rte_mbuf *m;
+ const uint8_t *src;
+ uint8_t *dst;
+
+ dlen = 0;
+ slen = 0;
+ tlen = 0;
+
+ dst = NULL;
+ src = NULL;
+
+ m = ms;
+ i = 0;
+ while (ms != NULL && i != nb_seg) {
+
+ if (slen == 0) {
+ slen = rte_pktmbuf_data_len(ms);
+ src = rte_pktmbuf_mtod(ms, const uint8_t *);
+ }
+
+ if (dlen == 0) {
+ dlen = RTE_MIN(seglen[i], slen);
+ md[i]->data_len = dlen;
+ md[i]->next = (i + 1 == nb_seg) ? NULL : md[i + 1];
+ dst = rte_pktmbuf_mtod(md[i], uint8_t *);
+ }
+
+ len = RTE_MIN(slen, dlen);
+ memcpy(dst, src, len);
+ tlen += len;
+ slen -= len;
+ dlen -= len;
+ src += len;
+ dst += len;
+
+ if (slen == 0)
+ ms = ms->next;
+ if (dlen == 0)
+ i++;
+ }
+
+ if (ms != NULL)
+ return -ENOBUFS;
+ else if (tlen != m->pkt_len)
+ return -EINVAL;
+
+ md[0]->nb_segs = nb_seg;
+ md[0]->pkt_len = tlen;
+ md[0]->vlan_tci = m->vlan_tci;
+ md[0]->vlan_tci_outer = m->vlan_tci_outer;
+ md[0]->ol_flags = m->ol_flags;
+ md[0]->tx_offload = m->tx_offload;
+
+ return nb_seg;
+}
+
+/*
+ * Allocate a new mbuf with up to tx_pkt_nb_segs segments.
+ * Copy packet contents and offload information into the new segmented mbuf.
+ */
+static struct rte_mbuf *
+pkt_copy_split(const struct rte_mbuf *pkt)
+{
+ int32_t n, rc;
+ uint32_t i, len, nb_seg;
+ struct rte_mempool *mp;
+ uint16_t seglen[RTE_MAX_SEGS_PER_PKT];
+ struct rte_mbuf *p, *md[RTE_MAX_SEGS_PER_PKT];
+
+ mp = current_fwd_lcore()->mbp;
+
+ if (tx_pkt_split == TX_PKT_SPLIT_RND)
+ nb_seg = random() % tx_pkt_nb_segs + 1;
+ else
+ nb_seg = tx_pkt_nb_segs;
+
+ memcpy(seglen, tx_pkt_seg_lengths, nb_seg * sizeof(seglen[0]));
+
+ /* calculate number of segments to use and their length. */
+ len = 0;
+ for (i = 0; i != nb_seg && len < pkt->pkt_len; i++) {
+ len += seglen[i];
+ md[i] = NULL;
+ }
+
+ n = pkt->pkt_len - len;
+
+ /* update size of the last segment to fit rest of the packet */
+ if (n >= 0) {
+ seglen[i - 1] += n;
+ len += n;
+ }
+
+ nb_seg = i;
+ while (i != 0) {
+ p = rte_pktmbuf_alloc(mp);
+ if (p == NULL) {
+ TESTPMD_LOG(ERR,
+ "failed to allocate %u-th of %u mbuf "
+ "from mempool: %s\n",
+ nb_seg - i, nb_seg, mp->name);
+ break;
+ }
+
+ md[--i] = p;
+ if (rte_pktmbuf_tailroom(md[i]) < seglen[i]) {
+ TESTPMD_LOG(ERR, "mempool %s, %u-th segment: "
+ "expected seglen: %u, "
+ "actual mbuf tailroom: %u\n",
+ mp->name, i, seglen[i],
+ rte_pktmbuf_tailroom(md[i]));
+ break;
+ }
+ }
+
+ /* all mbufs successfully allocated, do copy */
+ if (i == 0) {
+ rc = mbuf_copy_split(pkt, md, seglen, nb_seg);
+ if (rc < 0)
+ TESTPMD_LOG(ERR,
+ "mbuf_copy_split for %p(len=%u, nb_seg=%u) "
+ "into %u segments failed with error code: %d\n",
+ pkt, pkt->pkt_len, pkt->nb_segs, nb_seg, rc);
+
+ /* figure out how many mbufs to free. */
+ i = RTE_MAX(rc, 0);
+ }
+
+ /* free unused mbufs */
+ for (; i != nb_seg; i++) {
+ rte_pktmbuf_free_seg(md[i]);
+ md[i] = NULL;
+ }
+
+ return md[0];
+}
+
+/*
+ * Receive a burst of packets, and for each packet:
+ * - parse packet, and try to recognize a supported packet type (1)
+ * - if it's not a supported packet type, don't touch the packet, else:
+ * - reprocess the checksum of all supported layers. This is done in SW
+ * or HW, depending on testpmd command line configuration
+ * - if TSO is enabled in testpmd command line, also flag the mbuf for TCP
+ * segmentation offload (this implies HW TCP checksum)
+ * Then transmit packets on the output port.
+ *
+ * (1) Supported packets are:
+ * Ether / (vlan) / IP|IP6 / UDP|TCP|SCTP .
+ * Ether / (vlan) / outer IP|IP6 / outer UDP / VxLAN / Ether / IP|IP6 /
+ * UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / outer UDP / VXLAN-GPE / Ether / IP|IP6 /
+ * UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / outer UDP / VXLAN-GPE / IP|IP6 /
+ * UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP / outer UDP / GTP / IP|IP6 / UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / GRE / Ether / IP|IP6 / UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / GRE / IP|IP6 / UDP|TCP|SCTP
+ * Ether / (vlan) / outer IP|IP6 / IP|IP6 / UDP|TCP|SCTP
+ *
+ * The testpmd command line for this forward engine sets the flags
+ * TESTPMD_TX_OFFLOAD_* in ports[tx_port].tx_ol_flags. They control
+ * wether a checksum must be calculated in software or in hardware. The
+ * IP, UDP, TCP and SCTP flags always concern the inner layer. The
+ * OUTER_IP is only useful for tunnel packets.
+ */
+static void
+pkt_burst_checksum_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *gso_segments[GSO_MAX_PKT_BURST];
+ struct rte_gso_ctx *gso_ctx;
+ struct rte_mbuf **tx_pkts_burst;
+ struct rte_port *txp;
+ struct rte_mbuf *m, *p;
+ struct rte_ether_hdr *eth_hdr;
+ void *l3_hdr = NULL, *outer_l3_hdr = NULL; /* can be IPv4 or IPv6 */
+ void **gro_ctx;
+ uint16_t gro_pkts_num;
+ uint8_t gro_enable;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_prep;
+ uint16_t i;
+ uint64_t rx_ol_flags, tx_ol_flags;
+ uint64_t tx_offloads;
+ uint32_t retry;
+ uint32_t rx_bad_ip_csum;
+ uint32_t rx_bad_l4_csum;
+ uint32_t rx_bad_outer_l4_csum;
+ struct testpmd_offload_info info;
+ uint16_t nb_segments = 0;
+ int ret;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /* receive a burst of packet */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ rx_bad_ip_csum = 0;
+ rx_bad_l4_csum = 0;
+ rx_bad_outer_l4_csum = 0;
+ gro_enable = gro_ports[fs->rx_port].enable;
+
+ txp = &ports[fs->tx_port];
+ tx_offloads = txp->dev_conf.txmode.offloads;
+ memset(&info, 0, sizeof(info));
+ info.tso_segsz = txp->tso_segsz;
+ info.tunnel_tso_segsz = txp->tunnel_tso_segsz;
+ if (gso_ports[fs->tx_port].enable)
+ info.gso_enable = 1;
+
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+
+ m = pkts_burst[i];
+ info.is_tunnel = 0;
+ info.pkt_len = rte_pktmbuf_pkt_len(m);
+ tx_ol_flags = m->ol_flags &
+ (IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF);
+ rx_ol_flags = m->ol_flags;
+
+ /* Update the L3/L4 checksum error packet statistics */
+ if ((rx_ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD)
+ rx_bad_ip_csum += 1;
+ if ((rx_ol_flags & PKT_RX_L4_CKSUM_MASK) == PKT_RX_L4_CKSUM_BAD)
+ rx_bad_l4_csum += 1;
+ if (rx_ol_flags & PKT_RX_OUTER_L4_CKSUM_BAD)
+ rx_bad_outer_l4_csum += 1;
+
+ /* step 1: dissect packet, parsing optional vlan, ip4/ip6, vxlan
+ * and inner headers */
+
+ eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
+ rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+ &eth_hdr->d_addr);
+ rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_hdr->s_addr);
+ parse_ethernet(eth_hdr, &info);
+ l3_hdr = (char *)eth_hdr + info.l2_len;
+
+ /* check if it's a supported tunnel */
+ if (txp->parse_tunnel) {
+ if (info.l4_proto == IPPROTO_UDP) {
+ struct rte_udp_hdr *udp_hdr;
+
+ udp_hdr = (struct rte_udp_hdr *)
+ ((char *)l3_hdr + info.l3_len);
+ parse_gtp(udp_hdr, &info);
+ if (info.is_tunnel) {
+ tx_ol_flags |= PKT_TX_TUNNEL_GTP;
+ goto tunnel_update;
+ }
+ parse_vxlan_gpe(udp_hdr, &info);
+ if (info.is_tunnel) {
+ tx_ol_flags |=
+ PKT_TX_TUNNEL_VXLAN_GPE;
+ goto tunnel_update;
+ }
+ parse_vxlan(udp_hdr, &info,
+ m->packet_type);
+ if (info.is_tunnel)
+ tx_ol_flags |=
+ PKT_TX_TUNNEL_VXLAN;
+ } else if (info.l4_proto == IPPROTO_GRE) {
+ struct simple_gre_hdr *gre_hdr;
+
+ gre_hdr = (struct simple_gre_hdr *)
+ ((char *)l3_hdr + info.l3_len);
+ parse_gre(gre_hdr, &info);
+ if (info.is_tunnel)
+ tx_ol_flags |= PKT_TX_TUNNEL_GRE;
+ } else if (info.l4_proto == IPPROTO_IPIP) {
+ void *encap_ip_hdr;
+
+ encap_ip_hdr = (char *)l3_hdr + info.l3_len;
+ parse_encap_ip(encap_ip_hdr, &info);
+ if (info.is_tunnel)
+ tx_ol_flags |= PKT_TX_TUNNEL_IPIP;
+ }
+ }
+
+tunnel_update:
+ /* update l3_hdr and outer_l3_hdr if a tunnel was parsed */
+ if (info.is_tunnel) {
+ outer_l3_hdr = l3_hdr;
+ l3_hdr = (char *)l3_hdr + info.outer_l3_len + info.l2_len;
+ }
+
+ /* step 2: depending on user command line configuration,
+ * recompute checksum either in software or flag the
+ * mbuf to offload the calculation to the NIC. If TSO
+ * is configured, prepare the mbuf for TCP segmentation. */
+
+ /* process checksums of inner headers first */
+ tx_ol_flags |= process_inner_cksums(l3_hdr, &info,
+ tx_offloads);
+
+ /* Then process outer headers if any. Note that the software
+ * checksum will be wrong if one of the inner checksums is
+ * processed in hardware. */
+ if (info.is_tunnel == 1) {
+ tx_ol_flags |= process_outer_cksums(outer_l3_hdr, &info,
+ tx_offloads,
+ !!(tx_ol_flags & PKT_TX_TCP_SEG));
+ }
+
+ /* step 3: fill the mbuf meta data (flags and header lengths) */
+
+ m->tx_offload = 0;
+ if (info.is_tunnel == 1) {
+ if (info.tunnel_tso_segsz ||
+ (tx_offloads &
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) ||
+ (tx_offloads &
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) ||
+ (tx_ol_flags & PKT_TX_OUTER_IPV6)) {
+ m->outer_l2_len = info.outer_l2_len;
+ m->outer_l3_len = info.outer_l3_len;
+ m->l2_len = info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ m->tso_segsz = info.tunnel_tso_segsz;
+ }
+ else {
+ /* if there is a outer UDP cksum
+ processed in sw and the inner in hw,
+ the outer checksum will be wrong as
+ the payload will be modified by the
+ hardware */
+ m->l2_len = info.outer_l2_len +
+ info.outer_l3_len + info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ }
+ } else {
+ /* this is only useful if an offload flag is
+ * set, but it does not hurt to fill it in any
+ * case */
+ m->l2_len = info.l2_len;
+ m->l3_len = info.l3_len;
+ m->l4_len = info.l4_len;
+ m->tso_segsz = info.tso_segsz;
+ }
+ m->ol_flags = tx_ol_flags;
+
+ /* Do split & copy for the packet. */
+ if (tx_pkt_split != TX_PKT_SPLIT_OFF) {
+ p = pkt_copy_split(m);
+ if (p != NULL) {
+ rte_pktmbuf_free(m);
+ m = p;
+ pkts_burst[i] = m;
+ }
+ }
+
+ /* if verbose mode is enabled, dump debug info */
+ if (verbose_level > 0) {
+ char buf[256];
+
+ printf("-----------------\n");
+ printf("port=%u, mbuf=%p, pkt_len=%u, nb_segs=%u:\n",
+ fs->rx_port, m, m->pkt_len, m->nb_segs);
+ /* dump rx parsed packet info */
+ rte_get_rx_ol_flag_list(rx_ol_flags, buf, sizeof(buf));
+ printf("rx: l2_len=%d ethertype=%x l3_len=%d "
+ "l4_proto=%d l4_len=%d flags=%s\n",
+ info.l2_len, rte_be_to_cpu_16(info.ethertype),
+ info.l3_len, info.l4_proto, info.l4_len, buf);
+ if (rx_ol_flags & PKT_RX_LRO)
+ printf("rx: m->lro_segsz=%u\n", m->tso_segsz);
+ if (info.is_tunnel == 1)
+ printf("rx: outer_l2_len=%d outer_ethertype=%x "
+ "outer_l3_len=%d\n", info.outer_l2_len,
+ rte_be_to_cpu_16(info.outer_ethertype),
+ info.outer_l3_len);
+ /* dump tx packet info */
+ if ((tx_offloads & (DEV_TX_OFFLOAD_IPV4_CKSUM |
+ DEV_TX_OFFLOAD_UDP_CKSUM |
+ DEV_TX_OFFLOAD_TCP_CKSUM |
+ DEV_TX_OFFLOAD_SCTP_CKSUM)) ||
+ info.tso_segsz != 0)
+ printf("tx: m->l2_len=%d m->l3_len=%d "
+ "m->l4_len=%d\n",
+ m->l2_len, m->l3_len, m->l4_len);
+ if (info.is_tunnel == 1) {
+ if ((tx_offloads &
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) ||
+ (tx_offloads &
+ DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) ||
+ (tx_ol_flags & PKT_TX_OUTER_IPV6))
+ printf("tx: m->outer_l2_len=%d "
+ "m->outer_l3_len=%d\n",
+ m->outer_l2_len,
+ m->outer_l3_len);
+ if (info.tunnel_tso_segsz != 0 &&
+ (m->ol_flags & PKT_TX_TCP_SEG))
+ printf("tx: m->tso_segsz=%d\n",
+ m->tso_segsz);
+ } else if (info.tso_segsz != 0 &&
+ (m->ol_flags & PKT_TX_TCP_SEG))
+ printf("tx: m->tso_segsz=%d\n", m->tso_segsz);
+ rte_get_tx_ol_flag_list(m->ol_flags, buf, sizeof(buf));
+ printf("tx: flags=%s", buf);
+ printf("\n");
+ }
+ }
+
+ if (unlikely(gro_enable)) {
+ if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
+ nb_rx = rte_gro_reassemble_burst(pkts_burst, nb_rx,
+ &(gro_ports[fs->rx_port].param));
+ } else {
+ gro_ctx = current_fwd_lcore()->gro_ctx;
+ nb_rx = rte_gro_reassemble(pkts_burst, nb_rx, gro_ctx);
+
+ if (++fs->gro_times >= gro_flush_cycles) {
+ gro_pkts_num = rte_gro_get_pkt_count(gro_ctx);
+ if (gro_pkts_num > MAX_PKT_BURST - nb_rx)
+ gro_pkts_num = MAX_PKT_BURST - nb_rx;
+
+ nb_rx += rte_gro_timeout_flush(gro_ctx, 0,
+ RTE_GRO_TCP_IPV4,
+ &pkts_burst[nb_rx],
+ gro_pkts_num);
+ fs->gro_times = 0;
+ }
+ }
+ }
+
+ if (gso_ports[fs->tx_port].enable == 0)
+ tx_pkts_burst = pkts_burst;
+ else {
+ gso_ctx = &(current_fwd_lcore()->gso_ctx);
+ gso_ctx->gso_size = gso_max_segment_size;
+ for (i = 0; i < nb_rx; i++) {
+ ret = rte_gso_segment(pkts_burst[i], gso_ctx,
+ &gso_segments[nb_segments],
+ GSO_MAX_PKT_BURST - nb_segments);
+ if (ret >= 0)
+ nb_segments += ret;
+ else {
+ TESTPMD_LOG(DEBUG, "Unable to segment packet");
+ rte_pktmbuf_free(pkts_burst[i]);
+ }
+ }
+
+ tx_pkts_burst = gso_segments;
+ nb_rx = nb_segments;
+ }
+
+ nb_prep = rte_eth_tx_prepare(fs->tx_port, fs->tx_queue,
+ tx_pkts_burst, nb_rx);
+ if (nb_prep != nb_rx)
+ printf("Preparing packet burst to transmit failed: %s\n",
+ rte_strerror(rte_errno));
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, tx_pkts_burst,
+ nb_prep);
+
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &tx_pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+ fs->rx_bad_ip_csum += rx_bad_ip_csum;
+ fs->rx_bad_l4_csum += rx_bad_l4_csum;
+ fs->rx_bad_outer_l4_csum += rx_bad_outer_l4_csum;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(tx_pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine csum_fwd_engine = {
+ .fwd_mode_name = "csum",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_checksum_forward,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/flowgen.c b/src/spdk/dpdk/app/test-pmd/flowgen.c
new file mode 100644
index 000000000..4bd351e67
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/flowgen.c
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/* hardcoded configuration (for now) */
+static unsigned cfg_n_flows = 1024;
+static uint32_t cfg_ip_src = RTE_IPV4(10, 254, 0, 0);
+static uint32_t cfg_ip_dst = RTE_IPV4(10, 253, 0, 0);
+static uint16_t cfg_udp_src = 1000;
+static uint16_t cfg_udp_dst = 1001;
+static struct rte_ether_addr cfg_ether_src =
+ {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x00 }};
+static struct rte_ether_addr cfg_ether_dst =
+ {{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x01 }};
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+
+static inline uint16_t
+ip_sum(const unaligned_uint16_t *hdr, int hdr_len)
+{
+ uint32_t sum = 0;
+
+ while (hdr_len > 1)
+ {
+ sum += *hdr++;
+ if (sum & 0x80000000)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ hdr_len -= 2;
+ }
+
+ while (sum >> 16)
+ sum = (sum & 0xFFFF) + (sum >> 16);
+
+ return ~sum;
+}
+
+/*
+ * Multi-flow generation mode.
+ *
+ * We originate a bunch of flows (varying destination IP addresses), and
+ * terminate receive traffic. Received traffic is simply discarded, but we
+ * still do so in order to maintain traffic statistics.
+ */
+static void
+pkt_burst_flow_gen(struct fwd_stream *fs)
+{
+ unsigned pkt_size = tx_pkt_length - 4; /* Adjust FCS */
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mempool *mbp;
+ struct rte_mbuf *pkt;
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_ipv4_hdr *ip_hdr;
+ struct rte_udp_hdr *udp_hdr;
+ uint16_t vlan_tci, vlan_tci_outer;
+ uint64_t ol_flags = 0;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_pkt;
+ uint16_t i;
+ uint32_t retry;
+ uint64_t tx_offloads;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+ static int next_flow = 0;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /* Receive a burst of packets and discard them. */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ fs->rx_packets += nb_rx;
+
+ for (i = 0; i < nb_rx; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+ mbp = current_fwd_lcore()->mbp;
+ vlan_tci = ports[fs->tx_port].tx_vlan_id;
+ vlan_tci_outer = ports[fs->tx_port].tx_vlan_id_outer;
+
+ tx_offloads = ports[fs->tx_port].dev_conf.txmode.offloads;
+ if (tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
+ ol_flags |= PKT_TX_VLAN_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_QINQ_INSERT)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_MACSEC_INSERT)
+ ol_flags |= PKT_TX_MACSEC;
+
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_mbuf_raw_alloc(mbp);
+ if (!pkt)
+ break;
+
+ pkt->data_len = pkt_size;
+ pkt->next = NULL;
+
+ /* Initialize Ethernet header. */
+ eth_hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ rte_ether_addr_copy(&cfg_ether_dst, &eth_hdr->d_addr);
+ rte_ether_addr_copy(&cfg_ether_src, &eth_hdr->s_addr);
+ eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+ /* Initialize IP header. */
+ ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);
+ memset(ip_hdr, 0, sizeof(*ip_hdr));
+ ip_hdr->version_ihl = RTE_IPV4_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = IPPROTO_UDP;
+ ip_hdr->packet_id = 0;
+ ip_hdr->src_addr = rte_cpu_to_be_32(cfg_ip_src);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(cfg_ip_dst +
+ next_flow);
+ ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_size -
+ sizeof(*eth_hdr));
+ ip_hdr->hdr_checksum = ip_sum((unaligned_uint16_t *)ip_hdr,
+ sizeof(*ip_hdr));
+
+ /* Initialize UDP header. */
+ udp_hdr = (struct rte_udp_hdr *)(ip_hdr + 1);
+ udp_hdr->src_port = rte_cpu_to_be_16(cfg_udp_src);
+ udp_hdr->dst_port = rte_cpu_to_be_16(cfg_udp_dst);
+ udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+ udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_size -
+ sizeof(*eth_hdr) -
+ sizeof(*ip_hdr));
+ pkt->nb_segs = 1;
+ pkt->pkt_len = pkt_size;
+ pkt->ol_flags &= EXT_ATTACHED_MBUF;
+ pkt->ol_flags |= ol_flags;
+ pkt->vlan_tci = vlan_tci;
+ pkt->vlan_tci_outer = vlan_tci_outer;
+ pkt->l2_len = sizeof(struct rte_ether_hdr);
+ pkt->l3_len = sizeof(struct rte_ipv4_hdr);
+ pkts_burst[nb_pkt] = pkt;
+
+ next_flow = (next_flow + 1) % cfg_n_flows;
+ }
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_pkt)) {
+ /* Back out the flow counter. */
+ next_flow -= (nb_pkt - nb_tx);
+ while (next_flow < 0)
+ next_flow += cfg_n_flows;
+
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_pkt);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine flow_gen_engine = {
+ .fwd_mode_name = "flowgen",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_flow_gen,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/icmpecho.c b/src/spdk/dpdk/app/test-pmd/icmpecho.c
new file mode 100644
index 000000000..65aece16c
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/icmpecho.c
@@ -0,0 +1,535 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2013 6WIND S.A.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_arp.h>
+#include <rte_ip.h>
+#include <rte_icmp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static const char *
+arp_op_name(uint16_t arp_op)
+{
+ switch (arp_op) {
+ case RTE_ARP_OP_REQUEST:
+ return "ARP Request";
+ case RTE_ARP_OP_REPLY:
+ return "ARP Reply";
+ case RTE_ARP_OP_REVREQUEST:
+ return "Reverse ARP Request";
+ case RTE_ARP_OP_REVREPLY:
+ return "Reverse ARP Reply";
+ case RTE_ARP_OP_INVREQUEST:
+ return "Peer Identify Request";
+ case RTE_ARP_OP_INVREPLY:
+ return "Peer Identify Reply";
+ default:
+ break;
+ }
+ return "Unkwown ARP op";
+}
+
+static const char *
+ip_proto_name(uint16_t ip_proto)
+{
+ static const char * ip_proto_names[] = {
+ "IP6HOPOPTS", /**< IP6 hop-by-hop options */
+ "ICMP", /**< control message protocol */
+ "IGMP", /**< group mgmt protocol */
+ "GGP", /**< gateway^2 (deprecated) */
+ "IPv4", /**< IPv4 encapsulation */
+
+ "UNASSIGNED",
+ "TCP", /**< transport control protocol */
+ "ST", /**< Stream protocol II */
+ "EGP", /**< exterior gateway protocol */
+ "PIGP", /**< private interior gateway */
+
+ "RCC_MON", /**< BBN RCC Monitoring */
+ "NVPII", /**< network voice protocol*/
+ "PUP", /**< pup */
+ "ARGUS", /**< Argus */
+ "EMCON", /**< EMCON */
+
+ "XNET", /**< Cross Net Debugger */
+ "CHAOS", /**< Chaos*/
+ "UDP", /**< user datagram protocol */
+ "MUX", /**< Multiplexing */
+ "DCN_MEAS", /**< DCN Measurement Subsystems */
+
+ "HMP", /**< Host Monitoring */
+ "PRM", /**< Packet Radio Measurement */
+ "XNS_IDP", /**< xns idp */
+ "TRUNK1", /**< Trunk-1 */
+ "TRUNK2", /**< Trunk-2 */
+
+ "LEAF1", /**< Leaf-1 */
+ "LEAF2", /**< Leaf-2 */
+ "RDP", /**< Reliable Data */
+ "IRTP", /**< Reliable Transaction */
+ "TP4", /**< tp-4 w/ class negotiation */
+
+ "BLT", /**< Bulk Data Transfer */
+ "NSP", /**< Network Services */
+ "INP", /**< Merit Internodal */
+ "SEP", /**< Sequential Exchange */
+ "3PC", /**< Third Party Connect */
+
+ "IDPR", /**< InterDomain Policy Routing */
+ "XTP", /**< XTP */
+ "DDP", /**< Datagram Delivery */
+ "CMTP", /**< Control Message Transport */
+ "TPXX", /**< TP++ Transport */
+
+ "ILTP", /**< IL transport protocol */
+ "IPv6_HDR", /**< IP6 header */
+ "SDRP", /**< Source Demand Routing */
+ "IPv6_RTG", /**< IP6 routing header */
+ "IPv6_FRAG", /**< IP6 fragmentation header */
+
+ "IDRP", /**< InterDomain Routing*/
+ "RSVP", /**< resource reservation */
+ "GRE", /**< General Routing Encap. */
+ "MHRP", /**< Mobile Host Routing */
+ "BHA", /**< BHA */
+
+ "ESP", /**< IP6 Encap Sec. Payload */
+ "AH", /**< IP6 Auth Header */
+ "INLSP", /**< Integ. Net Layer Security */
+ "SWIPE", /**< IP with encryption */
+ "NHRP", /**< Next Hop Resolution */
+
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "ICMPv6", /**< ICMP6 */
+ "IPv6NONEXT", /**< IP6 no next header */
+
+ "Ipv6DSTOPTS",/**< IP6 destination option */
+ "AHIP", /**< any host internal protocol */
+ "CFTP", /**< CFTP */
+ "HELLO", /**< "hello" routing protocol */
+ "SATEXPAK", /**< SATNET/Backroom EXPAK */
+
+ "KRYPTOLAN", /**< Kryptolan */
+ "RVD", /**< Remote Virtual Disk */
+ "IPPC", /**< Pluribus Packet Core */
+ "ADFS", /**< Any distributed FS */
+ "SATMON", /**< Satnet Monitoring */
+
+ "VISA", /**< VISA Protocol */
+ "IPCV", /**< Packet Core Utility */
+ "CPNX", /**< Comp. Prot. Net. Executive */
+ "CPHB", /**< Comp. Prot. HeartBeat */
+ "WSN", /**< Wang Span Network */
+
+ "PVP", /**< Packet Video Protocol */
+ "BRSATMON", /**< BackRoom SATNET Monitoring */
+ "ND", /**< Sun net disk proto (temp.) */
+ "WBMON", /**< WIDEBAND Monitoring */
+ "WBEXPAK", /**< WIDEBAND EXPAK */
+
+ "EON", /**< ISO cnlp */
+ "VMTP", /**< VMTP */
+ "SVMTP", /**< Secure VMTP */
+ "VINES", /**< Banyon VINES */
+ "TTP", /**< TTP */
+
+ "IGP", /**< NSFNET-IGP */
+ "DGP", /**< dissimilar gateway prot. */
+ "TCF", /**< TCF */
+ "IGRP", /**< Cisco/GXS IGRP */
+ "OSPFIGP", /**< OSPFIGP */
+
+ "SRPC", /**< Strite RPC protocol */
+ "LARP", /**< Locus Address Resolution */
+ "MTP", /**< Multicast Transport */
+ "AX25", /**< AX.25 Frames */
+ "4IN4", /**< IP encapsulated in IP */
+
+ "MICP", /**< Mobile Int.ing control */
+ "SCCSP", /**< Semaphore Comm. security */
+ "ETHERIP", /**< Ethernet IP encapsulation */
+ "ENCAP", /**< encapsulation header */
+ "AES", /**< any private encr. scheme */
+
+ "GMTP", /**< GMTP */
+ "IPCOMP", /**< payload compression (IPComp) */
+ "UNASSIGNED",
+ "UNASSIGNED",
+ "PIM", /**< Protocol Independent Mcast */
+ };
+
+ if (ip_proto < RTE_DIM(ip_proto_names))
+ return ip_proto_names[ip_proto];
+ switch (ip_proto) {
+#ifdef IPPROTO_PGM
+ case IPPROTO_PGM: /**< PGM */
+ return "PGM";
+#endif
+ case IPPROTO_SCTP: /**< Stream Control Transport Protocol */
+ return "SCTP";
+#ifdef IPPROTO_DIVERT
+ case IPPROTO_DIVERT: /**< divert pseudo-protocol */
+ return "DIVERT";
+#endif
+ case IPPROTO_RAW: /**< raw IP packet */
+ return "RAW";
+ default:
+ break;
+ }
+ return "UNASSIGNED";
+}
+
+static void
+ipv4_addr_to_dot(uint32_t be_ipv4_addr, char *buf)
+{
+ uint32_t ipv4_addr;
+
+ ipv4_addr = rte_be_to_cpu_32(be_ipv4_addr);
+ sprintf(buf, "%d.%d.%d.%d", (ipv4_addr >> 24) & 0xFF,
+ (ipv4_addr >> 16) & 0xFF, (ipv4_addr >> 8) & 0xFF,
+ ipv4_addr & 0xFF);
+}
+
+static void
+ether_addr_dump(const char *what, const struct rte_ether_addr *ea)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, ea);
+ if (what)
+ printf("%s", what);
+ printf("%s", buf);
+}
+
+static void
+ipv4_addr_dump(const char *what, uint32_t be_ipv4_addr)
+{
+ char buf[16];
+
+ ipv4_addr_to_dot(be_ipv4_addr, buf);
+ if (what)
+ printf("%s", what);
+ printf("%s", buf);
+}
+
+static uint16_t
+ipv4_hdr_cksum(struct rte_ipv4_hdr *ip_h)
+{
+ uint16_t *v16_h;
+ uint32_t ip_cksum;
+
+ /*
+ * Compute the sum of successive 16-bit words of the IPv4 header,
+ * skipping the checksum field of the header.
+ */
+ v16_h = (unaligned_uint16_t *) ip_h;
+ ip_cksum = v16_h[0] + v16_h[1] + v16_h[2] + v16_h[3] +
+ v16_h[4] + v16_h[6] + v16_h[7] + v16_h[8] + v16_h[9];
+
+ /* reduce 32 bit checksum to 16 bits and complement it */
+ ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+ ip_cksum = (ip_cksum & 0xffff) + (ip_cksum >> 16);
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ return (ip_cksum == 0) ? 0xFFFF : (uint16_t) ip_cksum;
+}
+
+#define is_multicast_ipv4_addr(ipv4_addr) \
+ (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
+
+/*
+ * Receive a burst of packets, lookup for ICMP echo requests, and, if any,
+ * send back ICMP echo replies.
+ */
+static void
+reply_to_icmp_echo_rqsts(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *pkt;
+ struct rte_ether_hdr *eth_h;
+ struct rte_vlan_hdr *vlan_h;
+ struct rte_arp_hdr *arp_h;
+ struct rte_ipv4_hdr *ip_h;
+ struct rte_icmp_hdr *icmp_h;
+ struct rte_ether_addr eth_addr;
+ uint32_t retry;
+ uint32_t ip_addr;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t nb_replies;
+ uint16_t eth_type;
+ uint16_t vlan_id;
+ uint16_t arp_op;
+ uint16_t arp_pro;
+ uint32_t cksum;
+ uint8_t i;
+ int l2_len;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * First, receive a burst of packets.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ nb_replies = 0;
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+ pkt = pkts_burst[i];
+ eth_h = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ eth_type = RTE_BE_TO_CPU_16(eth_h->ether_type);
+ l2_len = sizeof(struct rte_ether_hdr);
+ if (verbose_level > 0) {
+ printf("\nPort %d pkt-len=%u nb-segs=%u\n",
+ fs->rx_port, pkt->pkt_len, pkt->nb_segs);
+ ether_addr_dump(" ETH: src=", &eth_h->s_addr);
+ ether_addr_dump(" dst=", &eth_h->d_addr);
+ }
+ if (eth_type == RTE_ETHER_TYPE_VLAN) {
+ vlan_h = (struct rte_vlan_hdr *)
+ ((char *)eth_h + sizeof(struct rte_ether_hdr));
+ l2_len += sizeof(struct rte_vlan_hdr);
+ eth_type = rte_be_to_cpu_16(vlan_h->eth_proto);
+ if (verbose_level > 0) {
+ vlan_id = rte_be_to_cpu_16(vlan_h->vlan_tci)
+ & 0xFFF;
+ printf(" [vlan id=%u]", vlan_id);
+ }
+ }
+ if (verbose_level > 0) {
+ printf(" type=0x%04x\n", eth_type);
+ }
+
+ /* Reply to ARP requests */
+ if (eth_type == RTE_ETHER_TYPE_ARP) {
+ arp_h = (struct rte_arp_hdr *) ((char *)eth_h + l2_len);
+ arp_op = RTE_BE_TO_CPU_16(arp_h->arp_opcode);
+ arp_pro = RTE_BE_TO_CPU_16(arp_h->arp_protocol);
+ if (verbose_level > 0) {
+ printf(" ARP: hrd=%d proto=0x%04x hln=%d "
+ "pln=%d op=%u (%s)\n",
+ RTE_BE_TO_CPU_16(arp_h->arp_hardware),
+ arp_pro, arp_h->arp_hlen,
+ arp_h->arp_plen, arp_op,
+ arp_op_name(arp_op));
+ }
+ if ((RTE_BE_TO_CPU_16(arp_h->arp_hardware) !=
+ RTE_ARP_HRD_ETHER) ||
+ (arp_pro != RTE_ETHER_TYPE_IPV4) ||
+ (arp_h->arp_hlen != 6) ||
+ (arp_h->arp_plen != 4)
+ ) {
+ rte_pktmbuf_free(pkt);
+ if (verbose_level > 0)
+ printf("\n");
+ continue;
+ }
+ if (verbose_level > 0) {
+ rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
+ &eth_addr);
+ ether_addr_dump(" sha=", &eth_addr);
+ ip_addr = arp_h->arp_data.arp_sip;
+ ipv4_addr_dump(" sip=", ip_addr);
+ printf("\n");
+ rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
+ &eth_addr);
+ ether_addr_dump(" tha=", &eth_addr);
+ ip_addr = arp_h->arp_data.arp_tip;
+ ipv4_addr_dump(" tip=", ip_addr);
+ printf("\n");
+ }
+ if (arp_op != RTE_ARP_OP_REQUEST) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+
+ /*
+ * Build ARP reply.
+ */
+
+ /* Use source MAC address as destination MAC address. */
+ rte_ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
+ /* Set source MAC address with MAC address of TX port */
+ rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_h->s_addr);
+
+ arp_h->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY);
+ rte_ether_addr_copy(&arp_h->arp_data.arp_tha,
+ &eth_addr);
+ rte_ether_addr_copy(&arp_h->arp_data.arp_sha,
+ &arp_h->arp_data.arp_tha);
+ rte_ether_addr_copy(&eth_h->s_addr,
+ &arp_h->arp_data.arp_sha);
+
+ /* Swap IP addresses in ARP payload */
+ ip_addr = arp_h->arp_data.arp_sip;
+ arp_h->arp_data.arp_sip = arp_h->arp_data.arp_tip;
+ arp_h->arp_data.arp_tip = ip_addr;
+ pkts_burst[nb_replies++] = pkt;
+ continue;
+ }
+
+ if (eth_type != RTE_ETHER_TYPE_IPV4) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+ ip_h = (struct rte_ipv4_hdr *) ((char *)eth_h + l2_len);
+ if (verbose_level > 0) {
+ ipv4_addr_dump(" IPV4: src=", ip_h->src_addr);
+ ipv4_addr_dump(" dst=", ip_h->dst_addr);
+ printf(" proto=%d (%s)\n",
+ ip_h->next_proto_id,
+ ip_proto_name(ip_h->next_proto_id));
+ }
+
+ /*
+ * Check if packet is a ICMP echo request.
+ */
+ icmp_h = (struct rte_icmp_hdr *) ((char *)ip_h +
+ sizeof(struct rte_ipv4_hdr));
+ if (! ((ip_h->next_proto_id == IPPROTO_ICMP) &&
+ (icmp_h->icmp_type == RTE_IP_ICMP_ECHO_REQUEST) &&
+ (icmp_h->icmp_code == 0))) {
+ rte_pktmbuf_free(pkt);
+ continue;
+ }
+
+ if (verbose_level > 0)
+ printf(" ICMP: echo request seq id=%d\n",
+ rte_be_to_cpu_16(icmp_h->icmp_seq_nb));
+
+ /*
+ * Prepare ICMP echo reply to be sent back.
+ * - switch ethernet source and destinations addresses,
+ * - use the request IP source address as the reply IP
+ * destination address,
+ * - if the request IP destination address is a multicast
+ * address:
+ * - choose a reply IP source address different from the
+ * request IP source address,
+ * - re-compute the IP header checksum.
+ * Otherwise:
+ * - switch the request IP source and destination
+ * addresses in the reply IP header,
+ * - keep the IP header checksum unchanged.
+ * - set RTE_IP_ICMP_ECHO_REPLY in ICMP header.
+ * ICMP checksum is computed by assuming it is valid in the
+ * echo request and not verified.
+ */
+ rte_ether_addr_copy(&eth_h->s_addr, &eth_addr);
+ rte_ether_addr_copy(&eth_h->d_addr, &eth_h->s_addr);
+ rte_ether_addr_copy(&eth_addr, &eth_h->d_addr);
+ ip_addr = ip_h->src_addr;
+ if (is_multicast_ipv4_addr(ip_h->dst_addr)) {
+ uint32_t ip_src;
+
+ ip_src = rte_be_to_cpu_32(ip_addr);
+ if ((ip_src & 0x00000003) == 1)
+ ip_src = (ip_src & 0xFFFFFFFC) | 0x00000002;
+ else
+ ip_src = (ip_src & 0xFFFFFFFC) | 0x00000001;
+ ip_h->src_addr = rte_cpu_to_be_32(ip_src);
+ ip_h->dst_addr = ip_addr;
+ ip_h->hdr_checksum = ipv4_hdr_cksum(ip_h);
+ } else {
+ ip_h->src_addr = ip_h->dst_addr;
+ ip_h->dst_addr = ip_addr;
+ }
+ icmp_h->icmp_type = RTE_IP_ICMP_ECHO_REPLY;
+ cksum = ~icmp_h->icmp_cksum & 0xffff;
+ cksum += ~htons(RTE_IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
+ cksum += htons(RTE_IP_ICMP_ECHO_REPLY << 8);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ icmp_h->icmp_cksum = ~cksum;
+ pkts_burst[nb_replies++] = pkt;
+ }
+
+ /* Send back ICMP echo replies, if any. */
+ if (nb_replies > 0) {
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst,
+ nb_replies);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_replies) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_replies &&
+ retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port,
+ fs->tx_queue,
+ &pkts_burst[nb_tx],
+ nb_replies - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_replies)) {
+ fs->fwd_dropped += (nb_replies - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_replies);
+ }
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine icmp_echo_engine = {
+ .fwd_mode_name = "icmpecho",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = reply_to_icmp_echo_rqsts,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/ieee1588fwd.c b/src/spdk/dpdk/app/test-pmd/ieee1588fwd.c
new file mode 100644
index 000000000..e3b98e3e0
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/ieee1588fwd.c
@@ -0,0 +1,218 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2015 Intel Corporation
+ */
+
+
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/**
+ * The structure of a PTP V2 packet.
+ *
+ * Only the minimum fields used by the ieee1588 test are represented.
+ */
+struct ptpv2_msg {
+ uint8_t msg_id;
+ uint8_t version; /**< must be 0x02 */
+ uint8_t unused[34];
+};
+
+#define PTP_SYNC_MESSAGE 0x0
+#define PTP_DELAY_REQ_MESSAGE 0x1
+#define PTP_PATH_DELAY_REQ_MESSAGE 0x2
+#define PTP_PATH_DELAY_RESP_MESSAGE 0x3
+#define PTP_FOLLOWUP_MESSAGE 0x8
+#define PTP_DELAY_RESP_MESSAGE 0x9
+#define PTP_PATH_DELAY_FOLLOWUP_MESSAGE 0xA
+#define PTP_ANNOUNCE_MESSAGE 0xB
+#define PTP_SIGNALLING_MESSAGE 0xC
+#define PTP_MANAGEMENT_MESSAGE 0xD
+
+/*
+ * Forwarding of IEEE1588 Precise Time Protocol (PTP) packets.
+ *
+ * In this mode, packets are received one by one and are expected to be
+ * PTP V2 L2 Ethernet frames (with the specific Ethernet type "0x88F7")
+ * containing PTP "sync" messages (version 2 at offset 1, and message ID
+ * 0 at offset 0).
+ *
+ * Check that each received packet is a IEEE1588 PTP V2 packet of type
+ * PTP_SYNC_MESSAGE, and that it has been identified and timestamped
+ * by the hardware.
+ * Check that the value of the last RX timestamp recorded by the controller
+ * is greater than the previous one.
+ *
+ * If everything is OK, send the received packet back on the same port,
+ * requesting for it to be timestamped by the hardware.
+ * Check that the value of the last TX timestamp recorded by the controller
+ * is greater than the previous one.
+ */
+
+static void
+port_ieee1588_rx_timestamp_check(portid_t pi, uint32_t index)
+{
+ struct timespec timestamp = {0, 0};
+
+ if (rte_eth_timesync_read_rx_timestamp(pi, &timestamp, index) < 0) {
+ printf("Port %u RX timestamp registers not valid\n", pi);
+ return;
+ }
+ printf("Port %u RX timestamp value %lu s %lu ns\n",
+ pi, timestamp.tv_sec, timestamp.tv_nsec);
+}
+
+#define MAX_TX_TMST_WAIT_MICROSECS 1000 /**< 1 milli-second */
+
+static void
+port_ieee1588_tx_timestamp_check(portid_t pi)
+{
+ struct timespec timestamp = {0, 0};
+ unsigned wait_us = 0;
+
+ while ((rte_eth_timesync_read_tx_timestamp(pi, &timestamp) < 0) &&
+ (wait_us < MAX_TX_TMST_WAIT_MICROSECS)) {
+ rte_delay_us(1);
+ wait_us++;
+ }
+ if (wait_us >= MAX_TX_TMST_WAIT_MICROSECS) {
+ printf("Port %u TX timestamp registers not valid after "
+ "%u micro-seconds\n",
+ pi, MAX_TX_TMST_WAIT_MICROSECS);
+ return;
+ }
+ printf("Port %u TX timestamp value %lu s %lu ns validated after "
+ "%u micro-second%s\n",
+ pi, timestamp.tv_sec, timestamp.tv_nsec, wait_us,
+ (wait_us == 1) ? "" : "s");
+}
+
+static void
+ieee1588_packet_fwd(struct fwd_stream *fs)
+{
+ struct rte_mbuf *mb;
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_ether_addr addr;
+ struct ptpv2_msg *ptp_hdr;
+ uint16_t eth_type;
+ uint32_t timesync_index;
+
+ /*
+ * Receive 1 packet at a time.
+ */
+ if (rte_eth_rx_burst(fs->rx_port, fs->rx_queue, &mb, 1) == 0)
+ return;
+
+ fs->rx_packets += 1;
+
+ /*
+ * Check that the received packet is a PTP packet that was detected
+ * by the hardware.
+ */
+ eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+ eth_type = rte_be_to_cpu_16(eth_hdr->ether_type);
+
+ if (! (mb->ol_flags & PKT_RX_IEEE1588_PTP)) {
+ if (eth_type == RTE_ETHER_TYPE_1588) {
+ printf("Port %u Received PTP packet not filtered"
+ " by hardware\n",
+ fs->rx_port);
+ } else {
+ printf("Port %u Received non PTP packet type=0x%4x "
+ "len=%u\n",
+ fs->rx_port, eth_type,
+ (unsigned) mb->pkt_len);
+ }
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ if (eth_type != RTE_ETHER_TYPE_1588) {
+ printf("Port %u Received NON PTP packet incorrectly"
+ " detected by hardware\n",
+ fs->rx_port);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /*
+ * Check that the received PTP packet is a PTP V2 packet of type
+ * PTP_SYNC_MESSAGE.
+ */
+ ptp_hdr = (struct ptpv2_msg *) (rte_pktmbuf_mtod(mb, char *) +
+ sizeof(struct rte_ether_hdr));
+ if (ptp_hdr->version != 0x02) {
+ printf("Port %u Received PTP V2 Ethernet frame with wrong PTP"
+ " protocol version 0x%x (should be 0x02)\n",
+ fs->rx_port, ptp_hdr->version);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ if (ptp_hdr->msg_id != PTP_SYNC_MESSAGE) {
+ printf("Port %u Received PTP V2 Ethernet frame with unexpected"
+ " message ID 0x%x (expected 0x0 - PTP_SYNC_MESSAGE)\n",
+ fs->rx_port, ptp_hdr->msg_id);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+ printf("Port %u IEEE1588 PTP V2 SYNC Message filtered by hardware\n",
+ fs->rx_port);
+
+ /*
+ * Check that the received PTP packet has been timestamped by the
+ * hardware.
+ */
+ if (! (mb->ol_flags & PKT_RX_IEEE1588_TMST)) {
+ printf("Port %u Received PTP packet not timestamped"
+ " by hardware\n",
+ fs->rx_port);
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /* For i40e we need the timesync register index. It is ignored for the
+ * other PMDs. */
+ timesync_index = mb->timesync & 0x3;
+ /* Read and check the RX timestamp. */
+ port_ieee1588_rx_timestamp_check(fs->rx_port, timesync_index);
+
+ /* Swap dest and src mac addresses. */
+ rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
+ rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
+
+ /* Forward PTP packet with hardware TX timestamp */
+ mb->ol_flags |= PKT_TX_IEEE1588_TMST;
+ fs->tx_packets += 1;
+ if (rte_eth_tx_burst(fs->rx_port, fs->tx_queue, &mb, 1) == 0) {
+ printf("Port %u sent PTP packet dropped\n", fs->rx_port);
+ fs->fwd_dropped += 1;
+ rte_pktmbuf_free(mb);
+ return;
+ }
+
+ /*
+ * Check the TX timestamp.
+ */
+ port_ieee1588_tx_timestamp_check(fs->rx_port);
+}
+
+static void
+port_ieee1588_fwd_begin(portid_t pi)
+{
+ rte_eth_timesync_enable(pi);
+}
+
+static void
+port_ieee1588_fwd_end(portid_t pi)
+{
+ rte_eth_timesync_disable(pi);
+}
+
+struct fwd_engine ieee1588_fwd_engine = {
+ .fwd_mode_name = "ieee1588",
+ .port_fwd_begin = port_ieee1588_fwd_begin,
+ .port_fwd_end = port_ieee1588_fwd_end,
+ .packet_fwd = ieee1588_packet_fwd,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/iofwd.c b/src/spdk/dpdk/app/test-pmd/iofwd.c
new file mode 100644
index 000000000..9dce76efe
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/iofwd.c
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_memcpy.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * Forwarding of packets in I/O mode.
+ * Forward packets "as-is".
+ * This is the fastest possible forwarding operation, as it does not access
+ * to packets data.
+ */
+static void
+pkt_burst_io_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint32_t retry;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
+ pkts_burst, nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+ fs->rx_packets += nb_rx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine io_fwd_engine = {
+ .fwd_mode_name = "io",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_io_forward,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/macfwd.c b/src/spdk/dpdk/app/test-pmd/macfwd.c
new file mode 100644
index 000000000..d2ebb1105
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macfwd.c
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * Forwarding of packets in MAC mode.
+ * Change the source and the destination Ethernet addressed of packets
+ * before forwarding them.
+ */
+static void
+pkt_burst_mac_forward(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *mb;
+ struct rte_ether_hdr *eth_hdr;
+ uint32_t retry;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint16_t i;
+ uint64_t ol_flags = 0;
+ uint64_t tx_offloads;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ txp = &ports[fs->tx_port];
+ tx_offloads = txp->dev_conf.txmode.offloads;
+ if (tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
+ ol_flags = PKT_TX_VLAN_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_QINQ_INSERT)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_MACSEC_INSERT)
+ ol_flags |= PKT_TX_MACSEC;
+ for (i = 0; i < nb_rx; i++) {
+ if (likely(i < nb_rx - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1],
+ void *));
+ mb = pkts_burst[i];
+ eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+ rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr],
+ &eth_hdr->d_addr);
+ rte_ether_addr_copy(&ports[fs->tx_port].eth_addr,
+ &eth_hdr->s_addr);
+ mb->ol_flags &= IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF;
+ mb->ol_flags |= ol_flags;
+ mb->l2_len = sizeof(struct rte_ether_hdr);
+ mb->l3_len = sizeof(struct rte_ipv4_hdr);
+ mb->vlan_tci = txp->tx_vlan_id;
+ mb->vlan_tci_outer = txp->tx_vlan_id_outer;
+ }
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine mac_fwd_engine = {
+ .fwd_mode_name = "mac",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_mac_forward,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/macswap.c b/src/spdk/dpdk/app/test-pmd/macswap.c
new file mode 100644
index 000000000..8428c26d8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macswap.c
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+#if defined(RTE_ARCH_X86)
+#include "macswap_sse.h"
+#elif defined(RTE_MACHINE_CPUFLAG_NEON)
+#include "macswap_neon.h"
+#else
+#include "macswap.h"
+#endif
+
+/*
+ * MAC swap forwarding mode: Swap the source and the destination Ethernet
+ * addresses of packets before forwarding them.
+ */
+static void
+pkt_burst_mac_swap(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint32_t retry;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets and forward them.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ txp = &ports[fs->tx_port];
+
+ do_macswap(pkts_burst, nb_rx, txp);
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_rx);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine mac_swap_engine = {
+ .fwd_mode_name = "macswap",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_mac_swap,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/macswap.h b/src/spdk/dpdk/app/test-pmd/macswap.h
new file mode 100644
index 000000000..013844156
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macswap.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _MACSWAP_H_
+#define _MACSWAP_H_
+
+#include "macswap_common.h"
+
+static inline void
+do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
+ struct rte_port *txp)
+{
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_mbuf *mb;
+ struct rte_ether_addr addr;
+ uint64_t ol_flags;
+ int i;
+
+ ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+ vlan_qinq_set(pkts, nb, ol_flags,
+ txp->tx_vlan_id, txp->tx_vlan_id_outer);
+
+ for (i = 0; i < nb; i++) {
+ if (likely(i < nb - 1))
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i+1], void *));
+ mb = pkts[i];
+
+ eth_hdr = rte_pktmbuf_mtod(mb, struct rte_ether_hdr *);
+
+ /* Swap dest and src mac addresses. */
+ rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
+ rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
+ rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
+
+ mbuf_field_set(mb, ol_flags);
+ }
+}
+
+#endif /* _MACSWAP_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/macswap_common.h b/src/spdk/dpdk/app/test-pmd/macswap_common.h
new file mode 100644
index 000000000..7e9a3590a
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macswap_common.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _MACSWAP_COMMON_H_
+#define _MACSWAP_COMMON_H_
+
+static inline uint64_t
+ol_flags_init(uint64_t tx_offload)
+{
+ uint64_t ol_flags = 0;
+
+ ol_flags |= (tx_offload & DEV_TX_OFFLOAD_VLAN_INSERT) ?
+ PKT_TX_VLAN : 0;
+ ol_flags |= (tx_offload & DEV_TX_OFFLOAD_QINQ_INSERT) ?
+ PKT_TX_QINQ : 0;
+ ol_flags |= (tx_offload & DEV_TX_OFFLOAD_MACSEC_INSERT) ?
+ PKT_TX_MACSEC : 0;
+
+ return ol_flags;
+}
+
+static inline void
+vlan_qinq_set(struct rte_mbuf *pkts[], uint16_t nb,
+ uint64_t ol_flags, uint16_t vlan, uint16_t outer_vlan)
+{
+ int i;
+
+ if (ol_flags & PKT_TX_VLAN)
+ for (i = 0; i < nb; i++)
+ pkts[i]->vlan_tci = vlan;
+ if (ol_flags & PKT_TX_QINQ)
+ for (i = 0; i < nb; i++)
+ pkts[i]->vlan_tci_outer = outer_vlan;
+}
+
+static inline void
+mbuf_field_set(struct rte_mbuf *mb, uint64_t ol_flags)
+{
+ mb->ol_flags &= IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF;
+ mb->ol_flags |= ol_flags;
+ mb->l2_len = sizeof(struct rte_ether_hdr);
+ mb->l3_len = sizeof(struct rte_ipv4_hdr);
+}
+
+#endif /* _MACSWAP_COMMON_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/macswap_neon.h b/src/spdk/dpdk/app/test-pmd/macswap_neon.h
new file mode 100644
index 000000000..df6c260cd
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macswap_neon.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ *
+ * Copyright(c) 2019 Intel Corporation
+ *
+ * Derived do_macswap implementation from app/test-pmd/macswap_sse.h
+ */
+
+#ifndef _MACSWAP_NEON_H_
+#define _MACSWAP_NEON_H_
+
+#include "macswap_common.h"
+#include "rte_vect.h"
+
+static inline void
+do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
+ struct rte_port *txp)
+{
+ struct rte_ether_hdr *eth_hdr[4];
+ struct rte_mbuf *mb[4];
+ uint64_t ol_flags;
+ int i;
+ int r;
+ uint8x16_t v0, v1, v2, v3;
+ /**
+ * Index map be used to shuffle the 16 bytes.
+ * byte 0-5 will be swapped with byte 6-11.
+ * byte 12-15 will keep unchanged.
+ */
+ const uint8x16_t idx_map = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5,
+ 12, 13, 14, 15};
+
+ ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+ vlan_qinq_set(pkts, nb, ol_flags,
+ txp->tx_vlan_id, txp->tx_vlan_id_outer);
+
+ i = 0;
+ r = nb;
+
+ while (r >= 4) {
+ if (r >= 8) {
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 4], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 5], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 6], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 7], void *));
+ }
+
+ mb[0] = pkts[i++];
+ eth_hdr[0] = rte_pktmbuf_mtod(mb[0], struct rte_ether_hdr *);
+
+ mb[1] = pkts[i++];
+ eth_hdr[1] = rte_pktmbuf_mtod(mb[1], struct rte_ether_hdr *);
+
+ mb[2] = pkts[i++];
+ eth_hdr[2] = rte_pktmbuf_mtod(mb[2], struct rte_ether_hdr *);
+
+ mb[3] = pkts[i++];
+ eth_hdr[3] = rte_pktmbuf_mtod(mb[3], struct rte_ether_hdr *);
+
+ v0 = vld1q_u8((uint8_t const *)eth_hdr[0]);
+ v1 = vld1q_u8((uint8_t const *)eth_hdr[1]);
+ v2 = vld1q_u8((uint8_t const *)eth_hdr[2]);
+ v3 = vld1q_u8((uint8_t const *)eth_hdr[3]);
+
+ v0 = vqtbl1q_u8(v0, idx_map);
+ v1 = vqtbl1q_u8(v1, idx_map);
+ v2 = vqtbl1q_u8(v2, idx_map);
+ v3 = vqtbl1q_u8(v3, idx_map);
+
+ vst1q_u8((uint8_t *)eth_hdr[0], v0);
+ vst1q_u8((uint8_t *)eth_hdr[1], v1);
+ vst1q_u8((uint8_t *)eth_hdr[2], v2);
+ vst1q_u8((uint8_t *)eth_hdr[3], v3);
+
+ mbuf_field_set(mb[0], ol_flags);
+ mbuf_field_set(mb[1], ol_flags);
+ mbuf_field_set(mb[2], ol_flags);
+ mbuf_field_set(mb[3], ol_flags);
+ r -= 4;
+ }
+
+ for ( ; i < nb; i++) {
+ if (i < nb - 1)
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i+1], void *));
+ mb[0] = pkts[i];
+ eth_hdr[0] = rte_pktmbuf_mtod(mb[0], struct rte_ether_hdr *);
+
+ /* Swap dest and src mac addresses. */
+ v0 = vld1q_u8((uint8_t const *)eth_hdr[0]);
+ v0 = vqtbl1q_u8(v0, idx_map);
+ vst1q_u8((uint8_t *)eth_hdr[0], v0);
+
+ mbuf_field_set(mb[0], ol_flags);
+ }
+}
+
+#endif /* _MACSWAP_NEON_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/macswap_sse.h b/src/spdk/dpdk/app/test-pmd/macswap_sse.h
new file mode 100644
index 000000000..223f87a53
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/macswap_sse.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _MACSWAP_SSE_H_
+#define _MACSWAP_SSE_H_
+
+#include "macswap_common.h"
+
+static inline void
+do_macswap(struct rte_mbuf *pkts[], uint16_t nb,
+ struct rte_port *txp)
+{
+ struct rte_ether_hdr *eth_hdr[4];
+ struct rte_mbuf *mb[4];
+ uint64_t ol_flags;
+ int i;
+ int r;
+ __m128i addr0, addr1, addr2, addr3;
+ /**
+ * shuffle mask be used to shuffle the 16 bytes.
+ * byte 0-5 wills be swapped with byte 6-11.
+ * byte 12-15 will keep unchanged.
+ */
+ __m128i shfl_msk = _mm_set_epi8(15, 14, 13, 12,
+ 5, 4, 3, 2,
+ 1, 0, 11, 10,
+ 9, 8, 7, 6);
+
+ ol_flags = ol_flags_init(txp->dev_conf.txmode.offloads);
+ vlan_qinq_set(pkts, nb, ol_flags,
+ txp->tx_vlan_id, txp->tx_vlan_id_outer);
+
+ i = 0;
+ r = nb;
+
+ while (r >= 4) {
+ if (r >= 8) {
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 4], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 5], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 6], void *));
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i + 7], void *));
+ }
+
+ mb[0] = pkts[i++];
+ eth_hdr[0] = rte_pktmbuf_mtod(mb[0], struct rte_ether_hdr *);
+ addr0 = _mm_loadu_si128((__m128i *)eth_hdr[0]);
+
+ mb[1] = pkts[i++];
+ eth_hdr[1] = rte_pktmbuf_mtod(mb[1], struct rte_ether_hdr *);
+ addr1 = _mm_loadu_si128((__m128i *)eth_hdr[1]);
+
+
+ mb[2] = pkts[i++];
+ eth_hdr[2] = rte_pktmbuf_mtod(mb[2], struct rte_ether_hdr *);
+ addr2 = _mm_loadu_si128((__m128i *)eth_hdr[2]);
+
+ mb[3] = pkts[i++];
+ eth_hdr[3] = rte_pktmbuf_mtod(mb[3], struct rte_ether_hdr *);
+ addr3 = _mm_loadu_si128((__m128i *)eth_hdr[3]);
+
+ addr0 = _mm_shuffle_epi8(addr0, shfl_msk);
+ addr1 = _mm_shuffle_epi8(addr1, shfl_msk);
+ addr2 = _mm_shuffle_epi8(addr2, shfl_msk);
+ addr3 = _mm_shuffle_epi8(addr3, shfl_msk);
+
+ _mm_storeu_si128((__m128i *)eth_hdr[0], addr0);
+ _mm_storeu_si128((__m128i *)eth_hdr[1], addr1);
+ _mm_storeu_si128((__m128i *)eth_hdr[2], addr2);
+ _mm_storeu_si128((__m128i *)eth_hdr[3], addr3);
+
+ mbuf_field_set(mb[0], ol_flags);
+ mbuf_field_set(mb[1], ol_flags);
+ mbuf_field_set(mb[2], ol_flags);
+ mbuf_field_set(mb[3], ol_flags);
+ r -= 4;
+ }
+
+ for ( ; i < nb; i++) {
+ if (i < nb - 1)
+ rte_prefetch0(rte_pktmbuf_mtod(pkts[i+1], void *));
+ mb[0] = pkts[i];
+ eth_hdr[0] = rte_pktmbuf_mtod(mb[0], struct rte_ether_hdr *);
+
+ /* Swap dest and src mac addresses. */
+ addr0 = _mm_loadu_si128((__m128i *)eth_hdr[0]);
+ addr0 = _mm_shuffle_epi8(addr0, shfl_msk);
+ _mm_storeu_si128((__m128i *)eth_hdr[0], addr0);
+
+ mbuf_field_set(mb[0], ol_flags);
+ }
+}
+
+#endif /* _MACSWAP_SSE_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/meson.build b/src/spdk/dpdk/app/test-pmd/meson.build
new file mode 100644
index 000000000..487288297
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/meson.build
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+# override default name to drop the hyphen
+name = 'testpmd'
+cflags += '-Wno-deprecated-declarations'
+sources = files('cmdline.c',
+ 'cmdline_flow.c',
+ 'cmdline_mtr.c',
+ 'cmdline_tm.c',
+ 'config.c',
+ 'csumonly.c',
+ 'flowgen.c',
+ 'icmpecho.c',
+ 'ieee1588fwd.c',
+ 'iofwd.c',
+ 'macfwd.c',
+ 'macswap.c',
+ 'noisy_vnf.c',
+ 'parameters.c',
+ 'rxonly.c',
+ 'testpmd.c',
+ 'txonly.c',
+ 'util.c')
+
+deps += ['ethdev', 'gro', 'gso', 'cmdline', 'metrics', 'meter', 'bus_pci']
+if dpdk_conf.has('RTE_LIBRTE_PDUMP')
+ deps += 'pdump'
+endif
+if dpdk_conf.has('RTE_LIBRTE_BNXT_PMD')
+ deps += 'pmd_bnxt'
+endif
+if dpdk_conf.has('RTE_LIBRTE_I40E_PMD')
+ deps += 'pmd_i40e'
+endif
+if dpdk_conf.has('RTE_LIBRTE_IXGBE_PMD')
+ deps += 'pmd_ixgbe'
+endif
+if dpdk_conf.has('RTE_LIBRTE_SOFTNIC_PMD')
+ sources += files('softnicfwd.c')
+ deps += 'pmd_softnic'
+endif
+if dpdk_conf.has('RTE_LIBRTE_DPAA_PMD')
+ deps += ['bus_dpaa', 'mempool_dpaa', 'pmd_dpaa']
+endif
+if dpdk_conf.has('RTE_LIBRTE_BPF')
+ sources += files('bpf_cmd.c')
+ deps += 'bpf'
+endif
diff --git a/src/spdk/dpdk/app/test-pmd/noisy_vnf.c b/src/spdk/dpdk/app/test-pmd/noisy_vnf.c
new file mode 100644
index 000000000..58c4ee925
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/noisy_vnf.c
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Red Hat Corp.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_memcpy.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_malloc.h>
+
+#include "testpmd.h"
+
+struct noisy_config {
+ struct rte_ring *f;
+ uint64_t prev_time;
+ char *vnf_mem;
+ bool do_buffering;
+ bool do_flush;
+ bool do_sim;
+};
+
+struct noisy_config *noisy_cfg[RTE_MAX_ETHPORTS];
+
+static inline void
+do_write(char *vnf_mem)
+{
+ uint64_t i = rte_rand();
+ uint64_t w = rte_rand();
+
+ vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
+ RTE_CACHE_LINE_SIZE)] = w;
+}
+
+static inline void
+do_read(char *vnf_mem)
+{
+ uint64_t i = rte_rand();
+ uint64_t r;
+
+ r = vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
+ RTE_CACHE_LINE_SIZE)];
+ r++;
+}
+
+static inline void
+do_readwrite(char *vnf_mem)
+{
+ do_read(vnf_mem);
+ do_write(vnf_mem);
+}
+
+/*
+ * Simulate route lookups as defined by commandline parameters
+ */
+static void
+sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
+{
+ uint16_t i, j;
+
+ if (!ncf->do_sim)
+ return;
+
+ for (i = 0; i < nb_pkts; i++) {
+ for (j = 0; j < noisy_lkup_num_writes; j++)
+ do_write(ncf->vnf_mem);
+ for (j = 0; j < noisy_lkup_num_reads; j++)
+ do_read(ncf->vnf_mem);
+ for (j = 0; j < noisy_lkup_num_reads_writes; j++)
+ do_readwrite(ncf->vnf_mem);
+ }
+}
+
+static uint16_t
+do_retry(uint16_t nb_rx, uint16_t nb_tx, struct rte_mbuf **pkts,
+ struct fwd_stream *fs)
+{
+ uint32_t retry = 0;
+
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts[nb_tx], nb_rx - nb_tx);
+ }
+
+ return nb_tx;
+}
+
+static uint32_t
+drop_pkts(struct rte_mbuf **pkts, uint16_t nb_rx, uint16_t nb_tx)
+{
+ if (nb_tx < nb_rx) {
+ do {
+ rte_pktmbuf_free(pkts[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+
+ return nb_rx - nb_tx;
+}
+
+/*
+ * Forwarding of packets in noisy VNF mode. Forward packets but perform
+ * memory operations first as specified on cmdline.
+ *
+ * Depending on which commandline parameters are specified we have
+ * different cases to handle:
+ *
+ * 1. No FIFO size was given, so we don't do buffering of incoming
+ * packets. This case is pretty much what iofwd does but in this case
+ * we also do simulation of memory accesses (depending on which
+ * parameters were specified for it).
+ * 2. User wants do buffer packets in a FIFO and sent out overflowing
+ * packets.
+ * 3. User wants a FIFO and specifies a time in ms to flush all packets
+ * out of the FIFO
+ * 4. Cases 2 and 3 combined
+ */
+static void
+pkt_burst_noisy_vnf(struct fwd_stream *fs)
+{
+ const uint64_t freq_khz = rte_get_timer_hz() / 1000;
+ struct noisy_config *ncf = noisy_cfg[fs->rx_port];
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
+ uint16_t nb_deqd = 0;
+ uint16_t nb_rx = 0;
+ uint16_t nb_tx = 0;
+ uint16_t nb_enqd;
+ unsigned int fifo_free;
+ uint64_t delta_ms;
+ bool needs_flush = false;
+ uint64_t now;
+
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
+ pkts_burst, nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ goto flush;
+ fs->rx_packets += nb_rx;
+
+ if (!ncf->do_buffering) {
+ sim_memory_lookups(ncf, nb_rx);
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ pkts_burst, nb_rx);
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled)
+ nb_tx += do_retry(nb_rx, nb_tx, pkts_burst, fs);
+ fs->tx_packets += nb_tx;
+ fs->fwd_dropped += drop_pkts(pkts_burst, nb_rx, nb_tx);
+ return;
+ }
+
+ fifo_free = rte_ring_free_count(ncf->f);
+ if (fifo_free >= nb_rx) {
+ nb_enqd = rte_ring_enqueue_burst(ncf->f,
+ (void **) pkts_burst, nb_rx, NULL);
+ if (nb_enqd < nb_rx)
+ fs->fwd_dropped += drop_pkts(pkts_burst,
+ nb_rx, nb_enqd);
+ } else {
+ nb_deqd = rte_ring_dequeue_burst(ncf->f,
+ (void **) tmp_pkts, nb_rx, NULL);
+ nb_enqd = rte_ring_enqueue_burst(ncf->f,
+ (void **) pkts_burst, nb_deqd, NULL);
+ if (nb_deqd > 0) {
+ nb_tx = rte_eth_tx_burst(fs->tx_port,
+ fs->tx_queue, tmp_pkts,
+ nb_deqd);
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled)
+ nb_tx += do_retry(nb_rx, nb_tx, tmp_pkts, fs);
+ fs->fwd_dropped += drop_pkts(tmp_pkts, nb_deqd, nb_tx);
+ }
+ }
+
+ sim_memory_lookups(ncf, nb_enqd);
+
+flush:
+ if (ncf->do_flush) {
+ if (!ncf->prev_time)
+ now = ncf->prev_time = rte_get_timer_cycles();
+ else
+ now = rte_get_timer_cycles();
+ delta_ms = (now - ncf->prev_time) / freq_khz;
+ needs_flush = delta_ms >= noisy_tx_sw_buf_flush_time &&
+ noisy_tx_sw_buf_flush_time > 0 && !nb_tx;
+ }
+ while (needs_flush && !rte_ring_empty(ncf->f)) {
+ unsigned int sent;
+ nb_deqd = rte_ring_dequeue_burst(ncf->f, (void **)tmp_pkts,
+ MAX_PKT_BURST, NULL);
+ sent = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ tmp_pkts, nb_deqd);
+ if (unlikely(sent < nb_deqd) && fs->retry_enabled)
+ nb_tx += do_retry(nb_rx, nb_tx, tmp_pkts, fs);
+ fs->fwd_dropped += drop_pkts(tmp_pkts, nb_deqd, sent);
+ ncf->prev_time = rte_get_timer_cycles();
+ }
+}
+
+#define NOISY_STRSIZE 256
+#define NOISY_RING "noisy_ring_%d\n"
+
+static void
+noisy_fwd_end(portid_t pi)
+{
+ rte_ring_free(noisy_cfg[pi]->f);
+ rte_free(noisy_cfg[pi]->vnf_mem);
+ rte_free(noisy_cfg[pi]);
+}
+
+static void
+noisy_fwd_begin(portid_t pi)
+{
+ struct noisy_config *n;
+ char name[NOISY_STRSIZE];
+
+ noisy_cfg[pi] = rte_zmalloc("testpmd noisy fifo and timers",
+ sizeof(struct noisy_config),
+ RTE_CACHE_LINE_SIZE);
+ if (noisy_cfg[pi] == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "rte_zmalloc(%d) struct noisy_config) failed\n",
+ (int) pi);
+ }
+ n = noisy_cfg[pi];
+ n->do_buffering = noisy_tx_sw_bufsz > 0;
+ n->do_sim = noisy_lkup_num_writes + noisy_lkup_num_reads +
+ noisy_lkup_num_reads_writes;
+ n->do_flush = noisy_tx_sw_buf_flush_time > 0;
+
+ if (n->do_buffering) {
+ snprintf(name, NOISY_STRSIZE, NOISY_RING, pi);
+ n->f = rte_ring_create(name, noisy_tx_sw_bufsz,
+ rte_socket_id(), 0);
+ if (!n->f)
+ rte_exit(EXIT_FAILURE,
+ "rte_ring_create(%d), size %d) failed\n",
+ (int) pi,
+ noisy_tx_sw_bufsz);
+ }
+ if (noisy_lkup_mem_sz > 0) {
+ n->vnf_mem = (char *) rte_zmalloc("vnf sim memory",
+ noisy_lkup_mem_sz * 1024 * 1024,
+ RTE_CACHE_LINE_SIZE);
+ if (!n->vnf_mem)
+ rte_exit(EXIT_FAILURE,
+ "rte_zmalloc(%" PRIu64 ") for vnf memory) failed\n",
+ noisy_lkup_mem_sz);
+ } else if (n->do_sim) {
+ rte_exit(EXIT_FAILURE,
+ "--noisy-lkup-memory-size must be > 0\n");
+ }
+}
+
+struct fwd_engine noisy_vnf_engine = {
+ .fwd_mode_name = "noisy",
+ .port_fwd_begin = noisy_fwd_begin,
+ .port_fwd_end = noisy_fwd_end,
+ .packet_fwd = pkt_burst_noisy_vnf,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/parameters.c b/src/spdk/dpdk/app/test-pmd/parameters.c
new file mode 100644
index 000000000..f761e1470
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/parameters.c
@@ -0,0 +1,1413 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <arpa/inet.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#ifdef RTE_LIBRTE_PMD_BOND
+#include <rte_eth_bond.h>
+#endif
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static void
+usage(char* progname)
+{
+ printf("usage: %s [EAL options] -- "
+#ifdef RTE_LIBRTE_CMDLINE
+ "[--interactive|-i] "
+ "[--cmdline-file=FILENAME] "
+#endif
+ "[--help|-h] | [--auto-start|-a] | ["
+ "--tx-first | --stats-period=PERIOD | "
+ "--coremask=COREMASK --portmask=PORTMASK --numa "
+ "--portlist=PORTLIST "
+ "--mbuf-size= | --total-num-mbufs= | "
+ "--nb-cores= | --nb-ports= | "
+#ifdef RTE_LIBRTE_CMDLINE
+ "--eth-peers-configfile= | "
+ "--eth-peer=X,M:M:M:M:M:M | "
+ "--tx-ip=SRC,DST | --tx-udp=PORT | "
+#endif
+ "--pkt-filter-mode= |"
+ "--rss-ip | --rss-udp | "
+ "--rxpt= | --rxht= | --rxwt= | --rxfreet= | "
+ "--txpt= | --txht= | --txwt= | --txfreet= | "
+ "--txrst= | --tx-offloads= | | --rx-offloads= | "
+ "--vxlan-gpe-port= ]\n",
+ progname);
+#ifdef RTE_LIBRTE_CMDLINE
+ printf(" --interactive: run in interactive mode.\n");
+ printf(" --cmdline-file: execute cli commands before startup.\n");
+#endif
+ printf(" --auto-start: start forwarding on init "
+ "[always when non-interactive].\n");
+ printf(" --help: display this message and quit.\n");
+ printf(" --tx-first: start forwarding sending a burst first "
+ "(only if interactive is disabled).\n");
+ printf(" --stats-period=PERIOD: statistics will be shown "
+ "every PERIOD seconds (only if interactive is disabled).\n");
+ printf(" --nb-cores=N: set the number of forwarding cores "
+ "(1 <= N <= %d).\n", nb_lcores);
+ printf(" --nb-ports=N: set the number of forwarding ports "
+ "(1 <= N <= %d).\n", nb_ports);
+ printf(" --coremask=COREMASK: hexadecimal bitmask of cores running "
+ "the packet forwarding test. The master lcore is reserved for "
+ "command line parsing only, and cannot be masked on for "
+ "packet forwarding.\n");
+ printf(" --portmask=PORTMASK: hexadecimal bitmask of ports used "
+ "by the packet forwarding test.\n");
+ printf(" --portlist=PORTLIST: list of forwarding ports\n");
+ printf(" --numa: enable NUMA-aware allocation of RX/TX rings and of "
+ "RX memory buffers (mbufs).\n");
+ printf(" --port-numa-config=(port,socket)[,(port,socket)]: "
+ "specify the socket on which the memory pool "
+ "used by the port will be allocated.\n");
+ printf(" --ring-numa-config=(port,flag,socket)[,(port,flag,socket)]: "
+ "specify the socket on which the TX/RX rings for "
+ "the port will be allocated "
+ "(flag: 1 for RX; 2 for TX; 3 for RX and TX).\n");
+ printf(" --socket-num=N: set socket from which all memory is allocated "
+ "in NUMA mode.\n");
+ printf(" --mbuf-size=N: set the data size of mbuf to N bytes.\n");
+ printf(" --total-num-mbufs=N: set the number of mbufs to be allocated "
+ "in mbuf pools.\n");
+ printf(" --max-pkt-len=N: set the maximum size of packet to N bytes.\n");
+ printf(" --max-lro-pkt-size=N: set the maximum LRO aggregated packet "
+ "size to N bytes.\n");
+#ifdef RTE_LIBRTE_CMDLINE
+ printf(" --eth-peers-configfile=name: config file with ethernet addresses "
+ "of peer ports.\n");
+ printf(" --eth-peer=X,M:M:M:M:M:M: set the MAC address of the X peer "
+ "port (0 <= X < %d).\n", RTE_MAX_ETHPORTS);
+#endif
+ printf(" --pkt-filter-mode=N: set Flow Director mode "
+ "(N: none (default mode) or signature or perfect).\n");
+ printf(" --pkt-filter-report-hash=N: set Flow Director report mode "
+ "(N: none or match (default) or always).\n");
+ printf(" --pkt-filter-size=N: set Flow Director mode "
+ "(N: 64K (default mode) or 128K or 256K).\n");
+ printf(" --pkt-filter-drop-queue=N: set drop-queue. "
+ "In perfect mode, when you add a rule with queue = -1 "
+ "the packet will be enqueued into the rx drop-queue. "
+ "If the drop-queue doesn't exist, the packet is dropped. "
+ "By default drop-queue=127.\n");
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ printf(" --latencystats=N: enable latency and jitter statistcs "
+ "monitoring on forwarding lcore id N.\n");
+#endif
+ printf(" --disable-crc-strip: disable CRC stripping by hardware.\n");
+ printf(" --enable-lro: enable large receive offload.\n");
+ printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n");
+ printf(" --enable-rx-timestamp: enable rx hardware timestamp offload.\n");
+ printf(" --enable-hw-vlan: enable hardware vlan.\n");
+ printf(" --enable-hw-vlan-filter: enable hardware vlan filter.\n");
+ printf(" --enable-hw-vlan-strip: enable hardware vlan strip.\n");
+ printf(" --enable-hw-vlan-extend: enable hardware vlan extend.\n");
+ printf(" --enable-hw-qinq-strip: enable hardware qinq strip.\n");
+ printf(" --enable-drop-en: enable per queue packet drop.\n");
+ printf(" --disable-rss: disable rss.\n");
+ printf(" --port-topology=<paired|chained|loop>: set port topology (paired "
+ "is default).\n");
+ printf(" --forward-mode=N: set forwarding mode (N: %s).\n",
+ list_pkt_forwarding_modes());
+ printf(" --rss-ip: set RSS functions to IPv4/IPv6 only .\n");
+ printf(" --rss-udp: set RSS functions to IPv4/IPv6 + UDP.\n");
+ printf(" --rxq=N: set the number of RX queues per port to N.\n");
+ printf(" --rxd=N: set the number of descriptors in RX rings to N.\n");
+ printf(" --txq=N: set the number of TX queues per port to N.\n");
+ printf(" --txd=N: set the number of descriptors in TX rings to N.\n");
+ printf(" --hairpinq=N: set the number of hairpin queues per port to "
+ "N.\n");
+ printf(" --burst=N: set the number of packets per burst to N.\n");
+ printf(" --mbcache=N: set the cache of mbuf memory pool to N.\n");
+ printf(" --rxpt=N: set prefetch threshold register of RX rings to N.\n");
+ printf(" --rxht=N: set the host threshold register of RX rings to N.\n");
+ printf(" --rxfreet=N: set the free threshold of RX descriptors to N "
+ "(0 <= N < value of rxd).\n");
+ printf(" --rxwt=N: set the write-back threshold register of RX rings to N.\n");
+ printf(" --txpt=N: set the prefetch threshold register of TX rings to N.\n");
+ printf(" --txht=N: set the nhost threshold register of TX rings to N.\n");
+ printf(" --txwt=N: set the write-back threshold register of TX rings to N.\n");
+ printf(" --txfreet=N: set the transmit free threshold of TX rings to N "
+ "(0 <= N <= value of txd).\n");
+ printf(" --txrst=N: set the transmit RS bit threshold of TX rings to N "
+ "(0 <= N <= value of txd).\n");
+ printf(" --tx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
+ "tx queues statistics counters mapping "
+ "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ printf(" --rx-queue-stats-mapping=(port,queue,mapping)[,(port,queue,mapping]: "
+ "rx queues statistics counters mapping "
+ "(0 <= mapping <= %d).\n", RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ printf(" --no-flush-rx: Don't flush RX streams before forwarding."
+ " Used mainly with PCAP drivers.\n");
+ printf(" --txpkts=X[,Y]*: set TX segment sizes"
+ " or total packet length.\n");
+ printf(" --txonly-multi-flow: generate multiple flows in txonly mode\n");
+ printf(" --disable-link-check: disable check on link status when "
+ "starting/stopping ports.\n");
+ printf(" --disable-device-start: do not automatically start port\n");
+ printf(" --no-lsc-interrupt: disable link status change interrupt.\n");
+ printf(" --no-rmv-interrupt: disable device removal interrupt.\n");
+ printf(" --bitrate-stats=N: set the logical core N to perform "
+ "bit-rate calculation.\n");
+ printf(" --print-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|flow_aged|all>: "
+ "enable print of designated event or all of them.\n");
+ printf(" --mask-event <unknown|intr_lsc|queue_state|intr_reset|vf_mbox|macsec|intr_rmv|flow_aged|all>: "
+ "disable print of designated event or all of them.\n");
+ printf(" --flow-isolate-all: "
+ "requests flow API isolated mode on all ports at initialization time.\n");
+ printf(" --tx-offloads=0xXXXXXXXX: hexadecimal bitmask of TX queue offloads\n");
+ printf(" --rx-offloads=0xXXXXXXXX: hexadecimal bitmask of RX queue offloads\n");
+ printf(" --hot-plug: enable hot plug for device.\n");
+ printf(" --vxlan-gpe-port=N: UPD port of tunnel VXLAN-GPE\n");
+ printf(" --mlockall: lock all memory\n");
+ printf(" --no-mlockall: do not lock all memory\n");
+ printf(" --mp-alloc <native|anon|xmem|xmemhuge>: mempool allocation method.\n"
+ " native: use regular DPDK memory to create and populate mempool\n"
+ " anon: use regular DPDK memory to create and anonymous memory to populate mempool\n"
+ " xmem: use anonymous memory to create and populate mempool\n"
+ " xmemhuge: use anonymous hugepage memory to create and populate mempool\n");
+ printf(" --noisy-tx-sw-buffer-size=N: size of FIFO buffer\n");
+ printf(" --noisy-tx-sw-buffer-flushtime=N: flush FIFO after N ms\n");
+ printf(" --noisy-lkup-memory=N: allocate N MB of VNF memory\n");
+ printf(" --noisy-lkup-num-writes=N: do N random writes per packet\n");
+ printf(" --noisy-lkup-num-reads=N: do N random reads per packet\n");
+ printf(" --noisy-lkup-num-writes=N: do N random reads and writes per packet\n");
+ printf(" --no-iova-contig: mempool memory can be IOVA non contiguous. "
+ "valid only with --mp-alloc=anon\n");
+ printf(" --rx-mq-mode=0xX: hexadecimal bitmask of RX mq mode can be "
+ "enabled\n");
+}
+
+#ifdef RTE_LIBRTE_CMDLINE
+static int
+init_peer_eth_addrs(char *config_filename)
+{
+ FILE *config_file;
+ portid_t i;
+ char buf[50];
+
+ config_file = fopen(config_filename, "r");
+ if (config_file == NULL) {
+ perror("Failed to open eth config file\n");
+ return -1;
+ }
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+
+ if (fgets(buf, sizeof(buf), config_file) == NULL)
+ break;
+
+ if (rte_ether_unformat_addr(buf, &peer_eth_addrs[i]) < 0) {
+ printf("Bad MAC address format on line %d\n", i+1);
+ fclose(config_file);
+ return -1;
+ }
+ }
+ fclose(config_file);
+ nb_peer_eth_addrs = (portid_t) i;
+ return 0;
+}
+#endif
+
+/*
+ * Parse the coremask given as argument (hexadecimal string) and set
+ * the global configuration of forwarding cores.
+ */
+static void
+parse_fwd_coremask(const char *coremask)
+{
+ char *end;
+ unsigned long long int cm;
+
+ /* parse hexadecimal string */
+ end = NULL;
+ cm = strtoull(coremask, &end, 16);
+ if ((coremask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ rte_exit(EXIT_FAILURE, "Invalid fwd core mask\n");
+ else if (set_fwd_lcores_mask((uint64_t) cm) < 0)
+ rte_exit(EXIT_FAILURE, "coremask is not valid\n");
+}
+
+/*
+ * Parse the coremask given as argument (hexadecimal string) and set
+ * the global configuration of forwarding cores.
+ */
+static void
+parse_fwd_portmask(const char *portmask)
+{
+ char *end;
+ unsigned long long int pm;
+
+ /* parse hexadecimal string */
+ end = NULL;
+ pm = strtoull(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ rte_exit(EXIT_FAILURE, "Invalid fwd port mask\n");
+ else
+ set_fwd_ports_mask((uint64_t) pm);
+}
+
+
+static int
+parse_queue_stats_mapping_config(const char *q_arg, int is_rx)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_QUEUE,
+ FLD_STATS_COUNTER,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ int i;
+ unsigned size;
+
+ /* reset from value set at definition */
+ is_rx ? (nb_rx_queue_stats_mappings = 0) : (nb_tx_queue_stats_mappings = 0);
+
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++){
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ /* Check mapping field is in correct range (0..RTE_ETHDEV_QUEUE_STAT_CNTRS-1) */
+ if (int_fld[FLD_STATS_COUNTER] >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
+ printf("Stats counter not in the correct range 0..%d\n",
+ RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
+ return -1;
+ }
+
+ if (!is_rx) {
+ if ((nb_tx_queue_stats_mappings >=
+ MAX_TX_QUEUE_STATS_MAPPINGS)) {
+ printf("exceeded max number of TX queue "
+ "statistics mappings: %hu\n",
+ nb_tx_queue_stats_mappings);
+ return -1;
+ }
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].port_id =
+ (uint8_t)int_fld[FLD_PORT];
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].queue_id =
+ (uint8_t)int_fld[FLD_QUEUE];
+ tx_queue_stats_mappings_array[nb_tx_queue_stats_mappings].stats_counter_id =
+ (uint8_t)int_fld[FLD_STATS_COUNTER];
+ ++nb_tx_queue_stats_mappings;
+ }
+ else {
+ if ((nb_rx_queue_stats_mappings >=
+ MAX_RX_QUEUE_STATS_MAPPINGS)) {
+ printf("exceeded max number of RX queue "
+ "statistics mappings: %hu\n",
+ nb_rx_queue_stats_mappings);
+ return -1;
+ }
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].port_id =
+ (uint8_t)int_fld[FLD_PORT];
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].queue_id =
+ (uint8_t)int_fld[FLD_QUEUE];
+ rx_queue_stats_mappings_array[nb_rx_queue_stats_mappings].stats_counter_id =
+ (uint8_t)int_fld[FLD_STATS_COUNTER];
+ ++nb_rx_queue_stats_mappings;
+ }
+
+ }
+/* Reassign the rx/tx_queue_stats_mappings pointer to point to this newly populated array rather */
+/* than to the default array (that was set at its definition) */
+ is_rx ? (rx_queue_stats_mappings = rx_queue_stats_mappings_array) :
+ (tx_queue_stats_mappings = tx_queue_stats_mappings_array);
+ return 0;
+}
+
+static void
+print_invalid_socket_id_error(void)
+{
+ unsigned int i = 0;
+
+ printf("Invalid socket id, options are: ");
+ for (i = 0; i < num_sockets; i++) {
+ printf("%u%s", socket_ids[i],
+ (i == num_sockets - 1) ? "\n" : ",");
+ }
+}
+
+static int
+parse_portnuma_config(const char *q_arg)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ uint8_t i, socket_id;
+ portid_t port_id;
+ unsigned size;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_SOCKET,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+
+ /* reset from value set at definition */
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ port_id = (portid_t)int_fld[FLD_PORT];
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL) {
+ print_valid_ports();
+ return -1;
+ }
+ socket_id = (uint8_t)int_fld[FLD_SOCKET];
+ if (new_socket_id(socket_id)) {
+ if (num_sockets >= RTE_MAX_NUMA_NODES) {
+ print_invalid_socket_id_error();
+ return -1;
+ }
+ socket_ids[num_sockets++] = socket_id;
+ }
+ port_numa[port_id] = socket_id;
+ }
+
+ return 0;
+}
+
+static int
+parse_ringnuma_config(const char *q_arg)
+{
+ char s[256];
+ const char *p, *p0 = q_arg;
+ char *end;
+ uint8_t i, ring_flag, socket_id;
+ portid_t port_id;
+ unsigned size;
+ enum fieldnames {
+ FLD_PORT = 0,
+ FLD_FLAG,
+ FLD_SOCKET,
+ _NUM_FLD
+ };
+ unsigned long int_fld[_NUM_FLD];
+ char *str_fld[_NUM_FLD];
+ #define RX_RING_ONLY 0x1
+ #define TX_RING_ONLY 0x2
+ #define RXTX_RING 0x3
+
+ /* reset from value set at definition */
+ while ((p = strchr(p0,'(')) != NULL) {
+ ++p;
+ if((p0 = strchr(p,')')) == NULL)
+ return -1;
+
+ size = p0 - p;
+ if(size >= sizeof(s))
+ return -1;
+
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD)
+ return -1;
+ for (i = 0; i < _NUM_FLD; i++) {
+ errno = 0;
+ int_fld[i] = strtoul(str_fld[i], &end, 0);
+ if (errno != 0 || end == str_fld[i] || int_fld[i] > 255)
+ return -1;
+ }
+ port_id = (portid_t)int_fld[FLD_PORT];
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL) {
+ print_valid_ports();
+ return -1;
+ }
+ socket_id = (uint8_t)int_fld[FLD_SOCKET];
+ if (new_socket_id(socket_id)) {
+ if (num_sockets >= RTE_MAX_NUMA_NODES) {
+ print_invalid_socket_id_error();
+ return -1;
+ }
+ socket_ids[num_sockets++] = socket_id;
+ }
+ ring_flag = (uint8_t)int_fld[FLD_FLAG];
+ if ((ring_flag < RX_RING_ONLY) || (ring_flag > RXTX_RING)) {
+ printf("Invalid ring-flag=%d config for port =%d\n",
+ ring_flag,port_id);
+ return -1;
+ }
+
+ switch (ring_flag & RXTX_RING) {
+ case RX_RING_ONLY:
+ rxring_numa[port_id] = socket_id;
+ break;
+ case TX_RING_ONLY:
+ txring_numa[port_id] = socket_id;
+ break;
+ case RXTX_RING:
+ rxring_numa[port_id] = socket_id;
+ txring_numa[port_id] = socket_id;
+ break;
+ default:
+ printf("Invalid ring-flag=%d config for port=%d\n",
+ ring_flag,port_id);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_event_printing_config(const char *optarg, int enable)
+{
+ uint32_t mask = 0;
+
+ if (!strcmp(optarg, "unknown"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN;
+ else if (!strcmp(optarg, "intr_lsc"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC;
+ else if (!strcmp(optarg, "queue_state"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE;
+ else if (!strcmp(optarg, "intr_reset"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET;
+ else if (!strcmp(optarg, "vf_mbox"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_VF_MBOX;
+ else if (!strcmp(optarg, "ipsec"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_IPSEC;
+ else if (!strcmp(optarg, "macsec"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_MACSEC;
+ else if (!strcmp(optarg, "intr_rmv"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV;
+ else if (!strcmp(optarg, "dev_probed"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_NEW;
+ else if (!strcmp(optarg, "dev_released"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_DESTROY;
+ else if (!strcmp(optarg, "flow_aged"))
+ mask = UINT32_C(1) << RTE_ETH_EVENT_FLOW_AGED;
+ else if (!strcmp(optarg, "all"))
+ mask = ~UINT32_C(0);
+ else {
+ fprintf(stderr, "Invalid event: %s\n", optarg);
+ return -1;
+ }
+ if (enable)
+ event_print_mask |= mask;
+ else
+ event_print_mask &= ~mask;
+ return 0;
+}
+
+void
+launch_args_parse(int argc, char** argv)
+{
+ int n, opt;
+ char **argvopt;
+ int opt_idx;
+ portid_t pid;
+ enum { TX, RX };
+ /* Default offloads for all ports. */
+ uint64_t rx_offloads = rx_mode.offloads;
+ uint64_t tx_offloads = tx_mode.offloads;
+ struct rte_eth_dev_info dev_info;
+ uint16_t rec_nb_pkts;
+ int ret;
+
+ static struct option lgopts[] = {
+ { "help", 0, 0, 0 },
+#ifdef RTE_LIBRTE_CMDLINE
+ { "interactive", 0, 0, 0 },
+ { "cmdline-file", 1, 0, 0 },
+ { "auto-start", 0, 0, 0 },
+ { "eth-peers-configfile", 1, 0, 0 },
+ { "eth-peer", 1, 0, 0 },
+#endif
+ { "tx-first", 0, 0, 0 },
+ { "stats-period", 1, 0, 0 },
+ { "ports", 1, 0, 0 },
+ { "nb-cores", 1, 0, 0 },
+ { "nb-ports", 1, 0, 0 },
+ { "coremask", 1, 0, 0 },
+ { "portmask", 1, 0, 0 },
+ { "portlist", 1, 0, 0 },
+ { "numa", 0, 0, 0 },
+ { "no-numa", 0, 0, 0 },
+ { "mp-anon", 0, 0, 0 },
+ { "port-numa-config", 1, 0, 0 },
+ { "ring-numa-config", 1, 0, 0 },
+ { "socket-num", 1, 0, 0 },
+ { "mbuf-size", 1, 0, 0 },
+ { "total-num-mbufs", 1, 0, 0 },
+ { "max-pkt-len", 1, 0, 0 },
+ { "max-lro-pkt-size", 1, 0, 0 },
+ { "pkt-filter-mode", 1, 0, 0 },
+ { "pkt-filter-report-hash", 1, 0, 0 },
+ { "pkt-filter-size", 1, 0, 0 },
+ { "pkt-filter-drop-queue", 1, 0, 0 },
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ { "latencystats", 1, 0, 0 },
+#endif
+#ifdef RTE_LIBRTE_BITRATE
+ { "bitrate-stats", 1, 0, 0 },
+#endif
+ { "disable-crc-strip", 0, 0, 0 },
+ { "enable-lro", 0, 0, 0 },
+ { "enable-rx-cksum", 0, 0, 0 },
+ { "enable-rx-timestamp", 0, 0, 0 },
+ { "enable-scatter", 0, 0, 0 },
+ { "enable-hw-vlan", 0, 0, 0 },
+ { "enable-hw-vlan-filter", 0, 0, 0 },
+ { "enable-hw-vlan-strip", 0, 0, 0 },
+ { "enable-hw-vlan-extend", 0, 0, 0 },
+ { "enable-hw-qinq-strip", 0, 0, 0 },
+ { "enable-drop-en", 0, 0, 0 },
+ { "disable-rss", 0, 0, 0 },
+ { "port-topology", 1, 0, 0 },
+ { "forward-mode", 1, 0, 0 },
+ { "rss-ip", 0, 0, 0 },
+ { "rss-udp", 0, 0, 0 },
+ { "rxq", 1, 0, 0 },
+ { "txq", 1, 0, 0 },
+ { "rxd", 1, 0, 0 },
+ { "txd", 1, 0, 0 },
+ { "hairpinq", 1, 0, 0 },
+ { "burst", 1, 0, 0 },
+ { "mbcache", 1, 0, 0 },
+ { "txpt", 1, 0, 0 },
+ { "txht", 1, 0, 0 },
+ { "txwt", 1, 0, 0 },
+ { "txfreet", 1, 0, 0 },
+ { "txrst", 1, 0, 0 },
+ { "rxpt", 1, 0, 0 },
+ { "rxht", 1, 0, 0 },
+ { "rxwt", 1, 0, 0 },
+ { "rxfreet", 1, 0, 0 },
+ { "tx-queue-stats-mapping", 1, 0, 0 },
+ { "rx-queue-stats-mapping", 1, 0, 0 },
+ { "no-flush-rx", 0, 0, 0 },
+ { "flow-isolate-all", 0, 0, 0 },
+ { "txpkts", 1, 0, 0 },
+ { "txonly-multi-flow", 0, 0, 0 },
+ { "disable-link-check", 0, 0, 0 },
+ { "disable-device-start", 0, 0, 0 },
+ { "no-lsc-interrupt", 0, 0, 0 },
+ { "no-rmv-interrupt", 0, 0, 0 },
+ { "print-event", 1, 0, 0 },
+ { "mask-event", 1, 0, 0 },
+ { "tx-offloads", 1, 0, 0 },
+ { "rx-offloads", 1, 0, 0 },
+ { "hot-plug", 0, 0, 0 },
+ { "vxlan-gpe-port", 1, 0, 0 },
+ { "mlockall", 0, 0, 0 },
+ { "no-mlockall", 0, 0, 0 },
+ { "mp-alloc", 1, 0, 0 },
+ { "tx-ip", 1, 0, 0 },
+ { "tx-udp", 1, 0, 0 },
+ { "noisy-tx-sw-buffer-size", 1, 0, 0 },
+ { "noisy-tx-sw-buffer-flushtime", 1, 0, 0 },
+ { "noisy-lkup-memory", 1, 0, 0 },
+ { "noisy-lkup-num-writes", 1, 0, 0 },
+ { "noisy-lkup-num-reads", 1, 0, 0 },
+ { "noisy-lkup-num-reads-writes", 1, 0, 0 },
+ { "no-iova-contig", 0, 0, 0 },
+ { "rx-mq-mode", 1, 0, 0 },
+ { 0, 0, 0, 0 },
+ };
+
+ argvopt = argv;
+
+#ifdef RTE_LIBRTE_CMDLINE
+#define SHORTOPTS "i"
+#else
+#define SHORTOPTS ""
+#endif
+ while ((opt = getopt_long(argc, argvopt, SHORTOPTS "ah",
+ lgopts, &opt_idx)) != EOF) {
+ switch (opt) {
+#ifdef RTE_LIBRTE_CMDLINE
+ case 'i':
+ printf("Interactive-mode selected\n");
+ interactive = 1;
+ break;
+#endif
+ case 'a':
+ printf("Auto-start selected\n");
+ auto_start = 1;
+ break;
+
+ case 0: /*long options */
+ if (!strcmp(lgopts[opt_idx].name, "help")) {
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ }
+#ifdef RTE_LIBRTE_CMDLINE
+ if (!strcmp(lgopts[opt_idx].name, "interactive")) {
+ printf("Interactive-mode selected\n");
+ interactive = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "cmdline-file")) {
+ printf("CLI commands to be read from %s\n",
+ optarg);
+ strlcpy(cmdline_filename, optarg,
+ sizeof(cmdline_filename));
+ }
+ if (!strcmp(lgopts[opt_idx].name, "auto-start")) {
+ printf("Auto-start selected\n");
+ auto_start = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "tx-first")) {
+ printf("Ports to start sending a burst of "
+ "packets first\n");
+ tx_first = 1;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "stats-period")) {
+ char *end = NULL;
+ unsigned int n;
+
+ n = strtoul(optarg, &end, 10);
+ if ((optarg[0] == '\0') || (end == NULL) ||
+ (*end != '\0'))
+ break;
+
+ stats_period = n;
+ break;
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "eth-peers-configfile")) {
+ if (init_peer_eth_addrs(optarg) != 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot open logfile\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "eth-peer")) {
+ char *port_end;
+
+ errno = 0;
+ n = strtoul(optarg, &port_end, 10);
+ if (errno != 0 || port_end == optarg || *port_end++ != ',')
+ rte_exit(EXIT_FAILURE,
+ "Invalid eth-peer: %s", optarg);
+ if (n >= RTE_MAX_ETHPORTS)
+ rte_exit(EXIT_FAILURE,
+ "eth-peer: port %d >= RTE_MAX_ETHPORTS(%d)\n",
+ n, RTE_MAX_ETHPORTS);
+
+ if (rte_ether_unformat_addr(port_end,
+ &peer_eth_addrs[n]) < 0)
+ rte_exit(EXIT_FAILURE,
+ "Invalid ethernet address: %s\n",
+ port_end);
+ nb_peer_eth_addrs++;
+ }
+#endif
+ if (!strcmp(lgopts[opt_idx].name, "tx-ip")) {
+ struct in_addr in;
+ char *end;
+
+ end = strchr(optarg, ',');
+ if (end == optarg || !end)
+ rte_exit(EXIT_FAILURE,
+ "Invalid tx-ip: %s", optarg);
+
+ *end++ = 0;
+ if (inet_aton(optarg, &in) == 0)
+ rte_exit(EXIT_FAILURE,
+ "Invalid source IP address: %s\n",
+ optarg);
+ tx_ip_src_addr = rte_be_to_cpu_32(in.s_addr);
+
+ if (inet_aton(end, &in) == 0)
+ rte_exit(EXIT_FAILURE,
+ "Invalid destination IP address: %s\n",
+ optarg);
+ tx_ip_dst_addr = rte_be_to_cpu_32(in.s_addr);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "tx-udp")) {
+ char *end = NULL;
+
+ errno = 0;
+ n = strtoul(optarg, &end, 10);
+ if (errno != 0 || end == optarg ||
+ n > UINT16_MAX ||
+ !(*end == '\0' || *end == ','))
+ rte_exit(EXIT_FAILURE,
+ "Invalid UDP port: %s\n",
+ optarg);
+ tx_udp_src_port = n;
+ if (*end == ',') {
+ char *dst = end + 1;
+
+ n = strtoul(dst, &end, 10);
+ if (errno != 0 || end == dst ||
+ n > UINT16_MAX || *end)
+ rte_exit(EXIT_FAILURE,
+ "Invalid destination UDP port: %s\n",
+ dst);
+ tx_udp_dst_port = n;
+ } else {
+ tx_udp_dst_port = n;
+ }
+
+ }
+ if (!strcmp(lgopts[opt_idx].name, "nb-ports")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= nb_ports)
+ nb_fwd_ports = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "Invalid port %d\n", n);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "nb-cores")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= nb_lcores)
+ nb_fwd_lcores = (uint8_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "nb-cores should be > 0 and <= %d\n",
+ nb_lcores);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "coremask"))
+ parse_fwd_coremask(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "portmask"))
+ parse_fwd_portmask(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "portlist"))
+ parse_fwd_portlist(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "no-numa"))
+ numa_support = 0;
+ if (!strcmp(lgopts[opt_idx].name, "numa"))
+ numa_support = 1;
+ if (!strcmp(lgopts[opt_idx].name, "mp-anon")) {
+ mp_alloc_type = MP_ALLOC_ANON;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mp-alloc")) {
+ if (!strcmp(optarg, "native"))
+ mp_alloc_type = MP_ALLOC_NATIVE;
+ else if (!strcmp(optarg, "anon"))
+ mp_alloc_type = MP_ALLOC_ANON;
+ else if (!strcmp(optarg, "xmem"))
+ mp_alloc_type = MP_ALLOC_XMEM;
+ else if (!strcmp(optarg, "xmemhuge"))
+ mp_alloc_type = MP_ALLOC_XMEM_HUGE;
+ else if (!strcmp(optarg, "xbuf"))
+ mp_alloc_type = MP_ALLOC_XBUF;
+ else
+ rte_exit(EXIT_FAILURE,
+ "mp-alloc %s invalid - must be: "
+ "native, anon, xmem or xmemhuge\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "port-numa-config")) {
+ if (parse_portnuma_config(optarg))
+ rte_exit(EXIT_FAILURE,
+ "invalid port-numa configuration\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "ring-numa-config"))
+ if (parse_ringnuma_config(optarg))
+ rte_exit(EXIT_FAILURE,
+ "invalid ring-numa configuration\n");
+ if (!strcmp(lgopts[opt_idx].name, "socket-num")) {
+ n = atoi(optarg);
+ if (!new_socket_id((uint8_t)n)) {
+ socket_num = (uint8_t)n;
+ } else {
+ print_invalid_socket_id_error();
+ rte_exit(EXIT_FAILURE,
+ "Invalid socket id");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mbuf-size")) {
+ n = atoi(optarg);
+ if (n > 0 && n <= 0xFFFF)
+ mbuf_data_size = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "mbuf-size should be > 0 and < 65536\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "total-num-mbufs")) {
+ n = atoi(optarg);
+ if (n > 1024)
+ param_total_num_mbufs = (unsigned)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "total-num-mbufs should be > 1024\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
+ n = atoi(optarg);
+ if (n >= RTE_ETHER_MIN_LEN) {
+ rx_mode.max_rx_pkt_len = (uint32_t) n;
+ if (n > RTE_ETHER_MAX_LEN)
+ rx_offloads |=
+ DEV_RX_OFFLOAD_JUMBO_FRAME;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "Invalid max-pkt-len=%d - should be > %d\n",
+ n, RTE_ETHER_MIN_LEN);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "max-lro-pkt-size")) {
+ n = atoi(optarg);
+ rx_mode.max_lro_pkt_size = (uint32_t) n;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "pkt-filter-mode")) {
+ if (!strcmp(optarg, "signature"))
+ fdir_conf.mode =
+ RTE_FDIR_MODE_SIGNATURE;
+ else if (!strcmp(optarg, "perfect"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
+ else if (!strcmp(optarg, "perfect-mac-vlan"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT_MAC_VLAN;
+ else if (!strcmp(optarg, "perfect-tunnel"))
+ fdir_conf.mode = RTE_FDIR_MODE_PERFECT_TUNNEL;
+ else if (!strcmp(optarg, "none"))
+ fdir_conf.mode = RTE_FDIR_MODE_NONE;
+ else
+ rte_exit(EXIT_FAILURE,
+ "pkt-mode-invalid %s invalid - must be: "
+ "none, signature, perfect, perfect-mac-vlan"
+ " or perfect-tunnel\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "pkt-filter-report-hash")) {
+ if (!strcmp(optarg, "none"))
+ fdir_conf.status =
+ RTE_FDIR_NO_REPORT_STATUS;
+ else if (!strcmp(optarg, "match"))
+ fdir_conf.status =
+ RTE_FDIR_REPORT_STATUS;
+ else if (!strcmp(optarg, "always"))
+ fdir_conf.status =
+ RTE_FDIR_REPORT_STATUS_ALWAYS;
+ else
+ rte_exit(EXIT_FAILURE,
+ "pkt-filter-report-hash %s invalid "
+ "- must be: none or match or always\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "pkt-filter-size")) {
+ if (!strcmp(optarg, "64K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_64K;
+ else if (!strcmp(optarg, "128K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_128K;
+ else if (!strcmp(optarg, "256K"))
+ fdir_conf.pballoc =
+ RTE_FDIR_PBALLOC_256K;
+ else
+ rte_exit(EXIT_FAILURE, "pkt-filter-size %s invalid -"
+ " must be: 64K or 128K or 256K\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "pkt-filter-drop-queue")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ fdir_conf.drop_queue = (uint8_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "drop queue %d invalid - must"
+ "be >= 0 \n", n);
+ }
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (!strcmp(lgopts[opt_idx].name,
+ "latencystats")) {
+ n = atoi(optarg);
+ if (n >= 0) {
+ latencystats_lcore_id = (lcoreid_t) n;
+ latencystats_enabled = 1;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "invalid lcore id %d for latencystats"
+ " must be >= 0\n", n);
+ }
+#endif
+#ifdef RTE_LIBRTE_BITRATE
+ if (!strcmp(lgopts[opt_idx].name, "bitrate-stats")) {
+ n = atoi(optarg);
+ if (n >= 0) {
+ bitrate_lcore_id = (lcoreid_t) n;
+ bitrate_enabled = 1;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "invalid lcore id %d for bitrate stats"
+ " must be >= 0\n", n);
+ }
+#endif
+ if (!strcmp(lgopts[opt_idx].name, "disable-crc-strip"))
+ rx_offloads |= DEV_RX_OFFLOAD_KEEP_CRC;
+ if (!strcmp(lgopts[opt_idx].name, "enable-lro"))
+ rx_offloads |= DEV_RX_OFFLOAD_TCP_LRO;
+ if (!strcmp(lgopts[opt_idx].name, "enable-scatter"))
+ rx_offloads |= DEV_RX_OFFLOAD_SCATTER;
+ if (!strcmp(lgopts[opt_idx].name, "enable-rx-cksum"))
+ rx_offloads |= DEV_RX_OFFLOAD_CHECKSUM;
+ if (!strcmp(lgopts[opt_idx].name,
+ "enable-rx-timestamp"))
+ rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
+ if (!strcmp(lgopts[opt_idx].name, "enable-hw-vlan"))
+ rx_offloads |= DEV_RX_OFFLOAD_VLAN;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "enable-hw-vlan-filter"))
+ rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "enable-hw-vlan-strip"))
+ rx_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "enable-hw-vlan-extend"))
+ rx_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
+
+ if (!strcmp(lgopts[opt_idx].name,
+ "enable-hw-qinq-strip"))
+ rx_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
+
+ if (!strcmp(lgopts[opt_idx].name, "enable-drop-en"))
+ rx_drop_en = 1;
+
+ if (!strcmp(lgopts[opt_idx].name, "disable-rss"))
+ rss_hf = 0;
+ if (!strcmp(lgopts[opt_idx].name, "port-topology")) {
+ if (!strcmp(optarg, "paired"))
+ port_topology = PORT_TOPOLOGY_PAIRED;
+ else if (!strcmp(optarg, "chained"))
+ port_topology = PORT_TOPOLOGY_CHAINED;
+ else if (!strcmp(optarg, "loop"))
+ port_topology = PORT_TOPOLOGY_LOOP;
+ else
+ rte_exit(EXIT_FAILURE, "port-topology %s invalid -"
+ " must be: paired, chained or loop\n",
+ optarg);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "forward-mode"))
+ set_pkt_forwarding_mode(optarg);
+ if (!strcmp(lgopts[opt_idx].name, "rss-ip"))
+ rss_hf = ETH_RSS_IP;
+ if (!strcmp(lgopts[opt_idx].name, "rss-udp"))
+ rss_hf = ETH_RSS_UDP;
+ if (!strcmp(lgopts[opt_idx].name, "rxq")) {
+ n = atoi(optarg);
+ if (n >= 0 && check_nb_rxq((queueid_t)n) == 0)
+ nb_rxq = (queueid_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "rxq %d invalid - must be"
+ " >= 0 && <= %u\n", n,
+ get_allowed_max_nb_rxq(&pid));
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txq")) {
+ n = atoi(optarg);
+ if (n >= 0 && check_nb_txq((queueid_t)n) == 0)
+ nb_txq = (queueid_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+ " >= 0 && <= %u\n", n,
+ get_allowed_max_nb_txq(&pid));
+ }
+ if (!strcmp(lgopts[opt_idx].name, "hairpinq")) {
+ n = atoi(optarg);
+ if (n >= 0 &&
+ check_nb_hairpinq((queueid_t)n) == 0)
+ nb_hairpinq = (queueid_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "txq %d invalid - must be"
+ " >= 0 && <= %u\n", n,
+ get_allowed_max_nb_hairpinq
+ (&pid));
+ if ((n + nb_txq) < 0 ||
+ check_nb_txq((queueid_t)(n + nb_txq)) != 0)
+ rte_exit(EXIT_FAILURE, "txq + hairpinq "
+ "%d invalid - must be"
+ " >= 0 && <= %u\n",
+ n + nb_txq,
+ get_allowed_max_nb_txq(&pid));
+ if ((n + nb_rxq) < 0 ||
+ check_nb_rxq((queueid_t)(n + nb_rxq)) != 0)
+ rte_exit(EXIT_FAILURE, "rxq + hairpinq "
+ "%d invalid - must be"
+ " >= 0 && <= %u\n",
+ n + nb_rxq,
+ get_allowed_max_nb_rxq(&pid));
+ }
+ if (!nb_rxq && !nb_txq) {
+ rte_exit(EXIT_FAILURE, "Either rx or tx queues should "
+ "be non-zero\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "burst")) {
+ n = atoi(optarg);
+ if (n == 0) {
+ /* A burst size of zero means that the
+ * PMD should be queried for
+ * recommended Rx burst size. Since
+ * testpmd uses a single size for all
+ * ports, port 0 is queried for the
+ * value, on the assumption that all
+ * ports are of the same NIC model.
+ */
+ ret = eth_dev_info_get_print_err(
+ 0,
+ &dev_info);
+ if (ret != 0)
+ return;
+
+ rec_nb_pkts = dev_info
+ .default_rxportconf.burst_size;
+
+ if (rec_nb_pkts == 0)
+ rte_exit(EXIT_FAILURE,
+ "PMD does not recommend a burst size. "
+ "Provided value must be between "
+ "1 and %d\n", MAX_PKT_BURST);
+ else if (rec_nb_pkts > MAX_PKT_BURST)
+ rte_exit(EXIT_FAILURE,
+ "PMD recommended burst size of %d"
+ " exceeds maximum value of %d\n",
+ rec_nb_pkts, MAX_PKT_BURST);
+ printf("Using PMD-provided burst value of %d\n",
+ rec_nb_pkts);
+ nb_pkt_per_burst = rec_nb_pkts;
+ } else if (n > MAX_PKT_BURST)
+ rte_exit(EXIT_FAILURE,
+ "burst must be between1 and %d\n",
+ MAX_PKT_BURST);
+ else
+ nb_pkt_per_burst = (uint16_t) n;
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mbcache")) {
+ n = atoi(optarg);
+ if ((n >= 0) &&
+ (n <= RTE_MEMPOOL_CACHE_MAX_SIZE))
+ mb_mempool_cache = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "mbcache must be >= 0 and <= %d\n",
+ RTE_MEMPOOL_CACHE_MAX_SIZE);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txfreet")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_free_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txfreet must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txrst")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_rs_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txrst must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxd")) {
+ n = atoi(optarg);
+ if (n > 0) {
+ if (rx_free_thresh >= n)
+ rte_exit(EXIT_FAILURE,
+ "rxd must be > "
+ "rx_free_thresh(%d)\n",
+ (int)rx_free_thresh);
+ else
+ nb_rxd = (uint16_t) n;
+ } else
+ rte_exit(EXIT_FAILURE,
+ "rxd(%d) invalid - must be > 0\n",
+ n);
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txd")) {
+ n = atoi(optarg);
+ if (n > 0)
+ nb_txd = (uint16_t) n;
+ else
+ rte_exit(EXIT_FAILURE, "txd must be in > 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txpt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_pthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txpt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txht")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_hthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txht must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txwt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ tx_wthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "txwt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxpt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_pthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxpt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxht")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_hthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxht must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxwt")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_wthresh = (int8_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxwt must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rxfreet")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ rx_free_thresh = (int16_t)n;
+ else
+ rte_exit(EXIT_FAILURE, "rxfreet must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "tx-queue-stats-mapping")) {
+ if (parse_queue_stats_mapping_config(optarg, TX)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid TX queue statistics mapping config entered\n");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "rx-queue-stats-mapping")) {
+ if (parse_queue_stats_mapping_config(optarg, RX)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid RX queue statistics mapping config entered\n");
+ }
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txpkts")) {
+ unsigned seg_lengths[RTE_MAX_SEGS_PER_PKT];
+ unsigned int nb_segs;
+
+ nb_segs = parse_item_list(optarg, "txpkt segments",
+ RTE_MAX_SEGS_PER_PKT, seg_lengths, 0);
+ if (nb_segs > 0)
+ set_tx_pkt_segments(seg_lengths, nb_segs);
+ else
+ rte_exit(EXIT_FAILURE, "bad txpkts\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "txonly-multi-flow"))
+ txonly_multi_flow = 1;
+ if (!strcmp(lgopts[opt_idx].name, "no-flush-rx"))
+ no_flush_rx = 1;
+ if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
+ no_link_check = 1;
+ if (!strcmp(lgopts[opt_idx].name, "disable-device-start"))
+ no_device_start = 1;
+ if (!strcmp(lgopts[opt_idx].name, "no-lsc-interrupt"))
+ lsc_interrupt = 0;
+ if (!strcmp(lgopts[opt_idx].name, "no-rmv-interrupt"))
+ rmv_interrupt = 0;
+ if (!strcmp(lgopts[opt_idx].name, "flow-isolate-all"))
+ flow_isolate_all = 1;
+ if (!strcmp(lgopts[opt_idx].name, "tx-offloads")) {
+ char *end = NULL;
+ n = strtoull(optarg, &end, 16);
+ if (n >= 0)
+ tx_offloads = (uint64_t)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "tx-offloads must be >= 0\n");
+ }
+
+ if (!strcmp(lgopts[opt_idx].name, "rx-offloads")) {
+ char *end = NULL;
+ n = strtoull(optarg, &end, 16);
+ if (n >= 0)
+ rx_offloads = (uint64_t)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "rx-offloads must be >= 0\n");
+ }
+
+ if (!strcmp(lgopts[opt_idx].name, "vxlan-gpe-port")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ vxlan_gpe_udp_port = (uint16_t)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "vxlan-gpe-port must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "print-event"))
+ if (parse_event_printing_config(optarg, 1)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid print-event argument\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "mask-event"))
+ if (parse_event_printing_config(optarg, 0)) {
+ rte_exit(EXIT_FAILURE,
+ "invalid mask-event argument\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "hot-plug"))
+ hot_plug = 1;
+ if (!strcmp(lgopts[opt_idx].name, "mlockall"))
+ do_mlockall = 1;
+ if (!strcmp(lgopts[opt_idx].name, "no-mlockall"))
+ do_mlockall = 0;
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-tx-sw-buffer-size")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_tx_sw_bufsz = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-tx-sw-buffer-size must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-tx-sw-buffer-flushtime")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_tx_sw_buf_flush_time = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-tx-sw-buffer-flushtime must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-lkup-memory")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_lkup_mem_sz = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-lkup-memory must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-lkup-num-writes")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_lkup_num_writes = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-lkup-num-writes must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-lkup-num-reads")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_lkup_num_reads = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-lkup-num-reads must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name,
+ "noisy-lkup-num-reads-writes")) {
+ n = atoi(optarg);
+ if (n >= 0)
+ noisy_lkup_num_reads_writes = n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "noisy-lkup-num-reads-writes must be >= 0\n");
+ }
+ if (!strcmp(lgopts[opt_idx].name, "no-iova-contig"))
+ mempool_flags = MEMPOOL_F_NO_IOVA_CONTIG;
+
+ if (!strcmp(lgopts[opt_idx].name, "rx-mq-mode")) {
+ char *end = NULL;
+ n = strtoul(optarg, &end, 16);
+ if (n >= 0 && n <= ETH_MQ_RX_VMDQ_DCB_RSS)
+ rx_mq_mode = (enum rte_eth_rx_mq_mode)n;
+ else
+ rte_exit(EXIT_FAILURE,
+ "rx-mq-mode must be >= 0 and <= %d\n",
+ ETH_MQ_RX_VMDQ_DCB_RSS);
+ }
+ break;
+ case 'h':
+ usage(argv[0]);
+ rte_exit(EXIT_SUCCESS, "Displayed help\n");
+ break;
+ default:
+ usage(argv[0]);
+ printf("Invalid option: %s\n", argv[optind]);
+ rte_exit(EXIT_FAILURE,
+ "Command line is incomplete or incorrect\n");
+ break;
+ }
+ }
+
+ if (optind != argc) {
+ usage(argv[0]);
+ printf("Invalid parameter: %s\n", argv[optind]);
+ rte_exit(EXIT_FAILURE, "Command line is incorrect\n");
+ }
+
+ /* Set offload configuration from command line parameters. */
+ rx_mode.offloads = rx_offloads;
+ tx_mode.offloads = tx_offloads;
+
+ if (mempool_flags & MEMPOOL_F_NO_IOVA_CONTIG &&
+ mp_alloc_type != MP_ALLOC_ANON) {
+ TESTPMD_LOG(WARNING, "cannot use no-iova-contig without "
+ "mp-alloc=anon. mempool no-iova-contig is "
+ "ignored\n");
+ mempool_flags = 0;
+ }
+}
diff --git a/src/spdk/dpdk/app/test-pmd/rxonly.c b/src/spdk/dpdk/app/test-pmd/rxonly.c
new file mode 100644
index 000000000..5c65fc42d
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/rxonly.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_string_fns.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_net.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/*
+ * Received a burst of packets.
+ */
+static void
+pkt_burst_receive(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ uint16_t nb_rx;
+ uint16_t i;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+
+ start_tsc = rte_rdtsc();
+#endif
+
+ /*
+ * Receive a burst of packets.
+ */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue, pkts_burst,
+ nb_pkt_per_burst);
+ if (unlikely(nb_rx == 0))
+ return;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+ fs->rx_packets += nb_rx;
+ for (i = 0; i < nb_rx; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+struct fwd_engine rx_only_engine = {
+ .fwd_mode_name = "rxonly",
+ .port_fwd_begin = NULL,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_receive,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/softnicfwd.c b/src/spdk/dpdk/app/test-pmd/softnicfwd.c
new file mode 100644
index 000000000..e9d437364
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/softnicfwd.c
@@ -0,0 +1,686 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include <rte_cycles.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+#include <rte_meter.h>
+#include <rte_eth_softnic.h>
+#include <rte_tm.h>
+
+#include "testpmd.h"
+
+#define SUBPORT_NODES_PER_PORT 1
+#define PIPE_NODES_PER_SUBPORT 4096
+#define TC_NODES_PER_PIPE 4
+#define QUEUE_NODES_PER_TC 4
+
+#define NUM_PIPE_NODES \
+ (SUBPORT_NODES_PER_PORT * PIPE_NODES_PER_SUBPORT)
+
+#define NUM_TC_NODES \
+ (NUM_PIPE_NODES * TC_NODES_PER_PIPE)
+
+#define ROOT_NODE_ID 1000000
+#define SUBPORT_NODES_START_ID 900000
+#define PIPE_NODES_START_ID 800000
+#define TC_NODES_START_ID 700000
+
+#define STATS_MASK_DEFAULT \
+ (RTE_TM_STATS_N_PKTS | \
+ RTE_TM_STATS_N_BYTES | \
+ RTE_TM_STATS_N_PKTS_GREEN_DROPPED | \
+ RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
+
+#define STATS_MASK_QUEUE \
+ (STATS_MASK_DEFAULT | \
+ RTE_TM_STATS_N_PKTS_QUEUED)
+
+#define BYTES_IN_MBPS (1000 * 1000 / 8)
+#define TOKEN_BUCKET_SIZE 1000000
+
+/* TM Hierarchy Levels */
+enum tm_hierarchy_level {
+ TM_NODE_LEVEL_PORT = 0,
+ TM_NODE_LEVEL_SUBPORT,
+ TM_NODE_LEVEL_PIPE,
+ TM_NODE_LEVEL_TC,
+ TM_NODE_LEVEL_QUEUE,
+ TM_NODE_LEVEL_MAX,
+};
+
+struct tm_hierarchy {
+ /* TM Nodes */
+ uint32_t root_node_id;
+ uint32_t subport_node_id[SUBPORT_NODES_PER_PORT];
+ uint32_t pipe_node_id[SUBPORT_NODES_PER_PORT][PIPE_NODES_PER_SUBPORT];
+ uint32_t tc_node_id[NUM_PIPE_NODES][TC_NODES_PER_PIPE];
+ uint32_t queue_node_id[NUM_TC_NODES][QUEUE_NODES_PER_TC];
+
+ /* TM Hierarchy Nodes Shaper Rates */
+ uint32_t root_node_shaper_rate;
+ uint32_t subport_node_shaper_rate;
+ uint32_t pipe_node_shaper_rate;
+ uint32_t tc_node_shaper_rate;
+ uint32_t tc_node_shared_shaper_rate;
+
+ uint32_t n_shapers;
+};
+
+static struct fwd_lcore *softnic_fwd_lcore;
+static uint16_t softnic_port_id;
+struct fwd_engine softnic_fwd_engine;
+
+/*
+ * Softnic packet forward
+ */
+static void
+softnic_fwd(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ uint16_t nb_rx;
+ uint16_t nb_tx;
+ uint32_t retry;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ /* Packets Receive */
+ nb_rx = rte_eth_rx_burst(fs->rx_port, fs->rx_queue,
+ pkts_burst, nb_pkt_per_burst);
+ fs->rx_packets += nb_rx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->rx_burst_stats.pkt_burst_spread[nb_rx]++;
+#endif
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ pkts_burst, nb_rx);
+
+ /* Retry if necessary */
+ if (unlikely(nb_tx < nb_rx) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_rx && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_rx - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+
+ if (unlikely(nb_tx < nb_rx)) {
+ fs->fwd_dropped += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+static void
+softnic_fwd_run(struct fwd_stream *fs)
+{
+ rte_pmd_softnic_run(softnic_port_id);
+ softnic_fwd(fs);
+}
+
+/**
+ * Softnic init
+ */
+static int
+softnic_begin(void *arg __rte_unused)
+{
+ for (;;) {
+ if (!softnic_fwd_lcore->stopped)
+ break;
+ }
+
+ do {
+ /* Run softnic */
+ rte_pmd_softnic_run(softnic_port_id);
+ } while (!softnic_fwd_lcore->stopped);
+
+ return 0;
+}
+
+static int
+set_tm_hiearchy_nodes_shaper_rate(portid_t port_id,
+ struct tm_hierarchy *h)
+{
+ struct rte_eth_link link_params;
+ uint64_t tm_port_rate;
+ int ret;
+
+ memset(&link_params, 0, sizeof(link_params));
+
+ ret = rte_eth_link_get(port_id, &link_params);
+ if (ret < 0) {
+ printf("Error during getting device (port %u) link info: %s\n",
+ port_id, rte_strerror(-ret));
+ return ret;
+ }
+ tm_port_rate = (uint64_t)ETH_SPEED_NUM_10G * BYTES_IN_MBPS;
+
+ /* Set tm hierarchy shapers rate */
+ h->root_node_shaper_rate = tm_port_rate;
+ h->subport_node_shaper_rate =
+ tm_port_rate / SUBPORT_NODES_PER_PORT;
+ h->pipe_node_shaper_rate
+ = h->subport_node_shaper_rate / PIPE_NODES_PER_SUBPORT;
+ h->tc_node_shaper_rate = h->pipe_node_shaper_rate;
+ h->tc_node_shared_shaper_rate = h->subport_node_shaper_rate;
+
+ return 0;
+}
+
+static int
+softport_tm_root_node_add(portid_t port_id, struct tm_hierarchy *h,
+ struct rte_tm_error *error)
+{
+ struct rte_tm_node_params rnp;
+ struct rte_tm_shaper_params rsp;
+ uint32_t priority, weight, level_id, shaper_profile_id;
+
+ memset(&rsp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&rnp, 0, sizeof(struct rte_tm_node_params));
+
+ /* Shaper profile Parameters */
+ rsp.peak.rate = h->root_node_shaper_rate;
+ rsp.peak.size = TOKEN_BUCKET_SIZE;
+ rsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+ shaper_profile_id = 0;
+
+ if (rte_tm_shaper_profile_add(port_id, shaper_profile_id,
+ &rsp, error)) {
+ printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
+ __func__, error->type, error->message,
+ shaper_profile_id);
+ return -1;
+ }
+
+ /* Root Node Parameters */
+ h->root_node_id = ROOT_NODE_ID;
+ weight = 1;
+ priority = 0;
+ level_id = TM_NODE_LEVEL_PORT;
+ rnp.shaper_profile_id = shaper_profile_id;
+ rnp.nonleaf.n_sp_priorities = 1;
+ rnp.stats_mask = STATS_MASK_DEFAULT;
+
+ /* Add Node to TM Hierarchy */
+ if (rte_tm_node_add(port_id, h->root_node_id, RTE_TM_NODE_ID_NULL,
+ priority, weight, level_id, &rnp, error)) {
+ printf("%s ERROR(%d)-%s!(node_id %u, parent_id %u, level %u)\n",
+ __func__, error->type, error->message,
+ h->root_node_id, RTE_TM_NODE_ID_NULL,
+ level_id);
+ return -1;
+ }
+ /* Update */
+ h->n_shapers++;
+
+ printf(" Root node added (Start id %u, Count %u, level %u)\n",
+ h->root_node_id, 1, level_id);
+
+ return 0;
+}
+
+static int
+softport_tm_subport_node_add(portid_t port_id,
+ struct tm_hierarchy *h,
+ struct rte_tm_error *error)
+{
+ uint32_t subport_parent_node_id, subport_node_id = 0;
+ struct rte_tm_node_params snp;
+ struct rte_tm_shaper_params ssp;
+ uint32_t priority, weight, level_id, shaper_profile_id;
+ uint32_t i;
+
+ memset(&ssp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&snp, 0, sizeof(struct rte_tm_node_params));
+
+ shaper_profile_id = h->n_shapers;
+
+ /* Add Shaper Profile to TM Hierarchy */
+ for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
+ ssp.peak.rate = h->subport_node_shaper_rate;
+ ssp.peak.size = TOKEN_BUCKET_SIZE;
+ ssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+
+ if (rte_tm_shaper_profile_add(port_id, shaper_profile_id,
+ &ssp, error)) {
+ printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
+ __func__, error->type, error->message,
+ shaper_profile_id);
+ return -1;
+ }
+
+ /* Node Parameters */
+ h->subport_node_id[i] = SUBPORT_NODES_START_ID + i;
+ subport_parent_node_id = h->root_node_id;
+ weight = 1;
+ priority = 0;
+ level_id = TM_NODE_LEVEL_SUBPORT;
+ snp.shaper_profile_id = shaper_profile_id;
+ snp.nonleaf.n_sp_priorities = 1;
+ snp.stats_mask = STATS_MASK_DEFAULT;
+
+ /* Add Node to TM Hiearchy */
+ if (rte_tm_node_add(port_id,
+ h->subport_node_id[i],
+ subport_parent_node_id,
+ priority, weight,
+ level_id,
+ &snp,
+ error)) {
+ printf("%s ERROR(%d)-%s!(node %u,parent %u,level %u)\n",
+ __func__,
+ error->type,
+ error->message,
+ h->subport_node_id[i],
+ subport_parent_node_id,
+ level_id);
+ return -1;
+ }
+ shaper_profile_id++;
+ subport_node_id++;
+ }
+ /* Update */
+ h->n_shapers = shaper_profile_id;
+
+ printf(" Subport nodes added (Start id %u, Count %u, level %u)\n",
+ h->subport_node_id[0], SUBPORT_NODES_PER_PORT, level_id);
+
+ return 0;
+}
+
+static int
+softport_tm_pipe_node_add(portid_t port_id,
+ struct tm_hierarchy *h,
+ struct rte_tm_error *error)
+{
+ uint32_t pipe_parent_node_id;
+ struct rte_tm_node_params pnp;
+ struct rte_tm_shaper_params psp;
+ uint32_t priority, weight, level_id, shaper_profile_id;
+ uint32_t i, j;
+
+ memset(&psp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&pnp, 0, sizeof(struct rte_tm_node_params));
+
+ shaper_profile_id = h->n_shapers;
+
+ /* Shaper Profile Parameters */
+ psp.peak.rate = h->pipe_node_shaper_rate;
+ psp.peak.size = TOKEN_BUCKET_SIZE;
+ psp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+
+ /* Pipe Node Parameters */
+ weight = 1;
+ priority = 0;
+ level_id = TM_NODE_LEVEL_PIPE;
+ pnp.nonleaf.n_sp_priorities = 4;
+ pnp.stats_mask = STATS_MASK_DEFAULT;
+
+ /* Add Shaper Profiles and Nodes to TM Hierarchy */
+ for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
+ for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {
+ if (rte_tm_shaper_profile_add(port_id,
+ shaper_profile_id, &psp, error)) {
+ printf("%s ERROR(%d)-%s!(shaper_id %u)\n ",
+ __func__, error->type, error->message,
+ shaper_profile_id);
+ return -1;
+ }
+ pnp.shaper_profile_id = shaper_profile_id;
+ pipe_parent_node_id = h->subport_node_id[i];
+ h->pipe_node_id[i][j] = PIPE_NODES_START_ID +
+ (i * PIPE_NODES_PER_SUBPORT) + j;
+
+ if (rte_tm_node_add(port_id,
+ h->pipe_node_id[i][j],
+ pipe_parent_node_id,
+ priority, weight, level_id,
+ &pnp,
+ error)) {
+ printf("%s ERROR(%d)-%s!(node %u,parent %u )\n",
+ __func__,
+ error->type,
+ error->message,
+ h->pipe_node_id[i][j],
+ pipe_parent_node_id);
+
+ return -1;
+ }
+ shaper_profile_id++;
+ }
+ }
+ /* Update */
+ h->n_shapers = shaper_profile_id;
+
+ printf(" Pipe nodes added (Start id %u, Count %u, level %u)\n",
+ h->pipe_node_id[0][0], NUM_PIPE_NODES, level_id);
+
+ return 0;
+}
+
+static int
+softport_tm_tc_node_add(portid_t port_id,
+ struct tm_hierarchy *h,
+ struct rte_tm_error *error)
+{
+ uint32_t tc_parent_node_id;
+ struct rte_tm_node_params tnp;
+ struct rte_tm_shaper_params tsp, tssp;
+ uint32_t shared_shaper_profile_id[TC_NODES_PER_PIPE];
+ uint32_t priority, weight, level_id, shaper_profile_id;
+ uint32_t pos, n_tc_nodes, i, j, k;
+
+ memset(&tsp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&tssp, 0, sizeof(struct rte_tm_shaper_params));
+ memset(&tnp, 0, sizeof(struct rte_tm_node_params));
+
+ shaper_profile_id = h->n_shapers;
+
+ /* Private Shaper Profile (TC) Parameters */
+ tsp.peak.rate = h->tc_node_shaper_rate;
+ tsp.peak.size = TOKEN_BUCKET_SIZE;
+ tsp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+
+ /* Shared Shaper Profile (TC) Parameters */
+ tssp.peak.rate = h->tc_node_shared_shaper_rate;
+ tssp.peak.size = TOKEN_BUCKET_SIZE;
+ tssp.pkt_length_adjust = RTE_TM_ETH_FRAMING_OVERHEAD_FCS;
+
+ /* TC Node Parameters */
+ weight = 1;
+ level_id = TM_NODE_LEVEL_TC;
+ tnp.n_shared_shapers = 1;
+ tnp.nonleaf.n_sp_priorities = 1;
+ tnp.stats_mask = STATS_MASK_DEFAULT;
+
+ /* Add Shared Shaper Profiles to TM Hierarchy */
+ for (i = 0; i < TC_NODES_PER_PIPE; i++) {
+ shared_shaper_profile_id[i] = shaper_profile_id;
+
+ if (rte_tm_shaper_profile_add(port_id,
+ shared_shaper_profile_id[i], &tssp, error)) {
+ printf("%s ERROR(%d)-%s!(Shared shaper profileid %u)\n",
+ __func__, error->type, error->message,
+ shared_shaper_profile_id[i]);
+
+ return -1;
+ }
+ if (rte_tm_shared_shaper_add_update(port_id, i,
+ shared_shaper_profile_id[i], error)) {
+ printf("%s ERROR(%d)-%s!(Shared shaper id %u)\n",
+ __func__, error->type, error->message, i);
+
+ return -1;
+ }
+ shaper_profile_id++;
+ }
+
+ /* Add Shaper Profiles and Nodes to TM Hierarchy */
+ n_tc_nodes = 0;
+ for (i = 0; i < SUBPORT_NODES_PER_PORT; i++) {
+ for (j = 0; j < PIPE_NODES_PER_SUBPORT; j++) {
+ for (k = 0; k < TC_NODES_PER_PIPE ; k++) {
+ priority = k;
+ tc_parent_node_id = h->pipe_node_id[i][j];
+ tnp.shared_shaper_id =
+ (uint32_t *)calloc(1, sizeof(uint32_t));
+ if (tnp.shared_shaper_id == NULL) {
+ printf("Shared shaper mem alloc err\n");
+ return -1;
+ }
+ tnp.shared_shaper_id[0] = k;
+ pos = j + (i * PIPE_NODES_PER_SUBPORT);
+ h->tc_node_id[pos][k] =
+ TC_NODES_START_ID + n_tc_nodes;
+
+ if (rte_tm_shaper_profile_add(port_id,
+ shaper_profile_id, &tsp, error)) {
+ printf("%s ERROR(%d)-%s!(shaper %u)\n",
+ __func__, error->type,
+ error->message,
+ shaper_profile_id);
+
+ free(tnp.shared_shaper_id);
+ return -1;
+ }
+ tnp.shaper_profile_id = shaper_profile_id;
+ if (rte_tm_node_add(port_id,
+ h->tc_node_id[pos][k],
+ tc_parent_node_id,
+ priority, weight,
+ level_id,
+ &tnp, error)) {
+ printf("%s ERROR(%d)-%s!(node id %u)\n",
+ __func__,
+ error->type,
+ error->message,
+ h->tc_node_id[pos][k]);
+
+ free(tnp.shared_shaper_id);
+ return -1;
+ }
+ shaper_profile_id++;
+ n_tc_nodes++;
+ }
+ }
+ }
+ /* Update */
+ h->n_shapers = shaper_profile_id;
+
+ printf(" TC nodes added (Start id %u, Count %u, level %u)\n",
+ h->tc_node_id[0][0], n_tc_nodes, level_id);
+
+ return 0;
+}
+
+static int
+softport_tm_queue_node_add(portid_t port_id, struct tm_hierarchy *h,
+ struct rte_tm_error *error)
+{
+ uint32_t queue_parent_node_id;
+ struct rte_tm_node_params qnp;
+ uint32_t priority, weight, level_id, pos;
+ uint32_t n_queue_nodes, i, j, k;
+
+ memset(&qnp, 0, sizeof(struct rte_tm_node_params));
+
+ /* Queue Node Parameters */
+ priority = 0;
+ weight = 1;
+ level_id = TM_NODE_LEVEL_QUEUE;
+ qnp.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
+ qnp.leaf.cman = RTE_TM_CMAN_TAIL_DROP;
+ qnp.stats_mask = STATS_MASK_QUEUE;
+
+ /* Add Queue Nodes to TM Hierarchy */
+ n_queue_nodes = 0;
+ for (i = 0; i < NUM_PIPE_NODES; i++) {
+ for (j = 0; j < TC_NODES_PER_PIPE; j++) {
+ queue_parent_node_id = h->tc_node_id[i][j];
+ for (k = 0; k < QUEUE_NODES_PER_TC; k++) {
+ pos = j + (i * TC_NODES_PER_PIPE);
+ h->queue_node_id[pos][k] = n_queue_nodes;
+ if (rte_tm_node_add(port_id,
+ h->queue_node_id[pos][k],
+ queue_parent_node_id,
+ priority,
+ weight,
+ level_id,
+ &qnp, error)) {
+ printf("%s ERROR(%d)-%s!(node %u)\n",
+ __func__,
+ error->type,
+ error->message,
+ h->queue_node_id[pos][k]);
+
+ return -1;
+ }
+ n_queue_nodes++;
+ }
+ }
+ }
+ printf(" Queue nodes added (Start id %u, Count %u, level %u)\n",
+ h->queue_node_id[0][0], n_queue_nodes, level_id);
+
+ return 0;
+}
+
+static int
+softport_tm_hierarchy_specify(portid_t port_id,
+ struct rte_tm_error *error)
+{
+
+ struct tm_hierarchy h;
+ int status;
+
+ memset(&h, 0, sizeof(struct tm_hierarchy));
+
+ /* TM hierarchy shapers rate */
+ status = set_tm_hiearchy_nodes_shaper_rate(port_id, &h);
+ if (status)
+ return status;
+
+ /* Add root node (level 0) */
+ status = softport_tm_root_node_add(port_id, &h, error);
+ if (status)
+ return status;
+
+ /* Add subport node (level 1) */
+ status = softport_tm_subport_node_add(port_id, &h, error);
+ if (status)
+ return status;
+
+ /* Add pipe nodes (level 2) */
+ status = softport_tm_pipe_node_add(port_id, &h, error);
+ if (status)
+ return status;
+
+ /* Add traffic class nodes (level 3) */
+ status = softport_tm_tc_node_add(port_id, &h, error);
+ if (status)
+ return status;
+
+ /* Add queue nodes (level 4) */
+ status = softport_tm_queue_node_add(port_id, &h, error);
+ if (status)
+ return status;
+
+ return 0;
+}
+
+/*
+ * Softnic TM default configuration
+ */
+static void
+softnic_tm_default_config(portid_t pi)
+{
+ struct rte_port *port = &ports[pi];
+ struct rte_tm_error error;
+ int status;
+
+ /* Stop port */
+ rte_eth_dev_stop(pi);
+
+ /* TM hierarchy specification */
+ status = softport_tm_hierarchy_specify(pi, &error);
+ if (status) {
+ printf(" TM Hierarchy built error(%d) - %s\n",
+ error.type, error.message);
+ return;
+ }
+ printf("\n TM Hierarchy Specified!\n");
+
+ /* TM hierarchy commit */
+ status = rte_tm_hierarchy_commit(pi, 0, &error);
+ if (status) {
+ printf(" Hierarchy commit error(%d) - %s\n",
+ error.type, error.message);
+ return;
+ }
+ printf(" Hierarchy Committed (port %u)!\n", pi);
+
+ /* Start port */
+ status = rte_eth_dev_start(pi);
+ if (status) {
+ printf("\n Port %u start error!\n", pi);
+ return;
+ }
+
+ /* Reset the default hierarchy flag */
+ port->softport.default_tm_hierarchy_enable = 0;
+}
+
+/*
+ * Softnic forwarding init
+ */
+static void
+softnic_fwd_begin(portid_t pi)
+{
+ struct rte_port *port = &ports[pi];
+ uint32_t lcore, fwd_core_present = 0, softnic_run_launch = 0;
+ int status;
+
+ softnic_fwd_lcore = port->softport.fwd_lcore_arg[0];
+ softnic_port_id = pi;
+
+ /* Launch softnic_run function on lcores */
+ for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) {
+ if (!rte_lcore_is_enabled(lcore))
+ continue;
+
+ if (lcore == rte_get_master_lcore())
+ continue;
+
+ if (fwd_core_present == 0) {
+ fwd_core_present++;
+ continue;
+ }
+
+ status = rte_eal_remote_launch(softnic_begin, NULL, lcore);
+ if (status)
+ printf("softnic launch on lcore %u failed (%d)\n",
+ lcore, status);
+
+ softnic_run_launch = 1;
+ }
+
+ if (!softnic_run_launch)
+ softnic_fwd_engine.packet_fwd = softnic_fwd_run;
+
+ /* Softnic TM default configuration */
+ if (port->softport.default_tm_hierarchy_enable == 1)
+ softnic_tm_default_config(pi);
+}
+
+struct fwd_engine softnic_fwd_engine = {
+ .fwd_mode_name = "softnic",
+ .port_fwd_begin = softnic_fwd_begin,
+ .port_fwd_end = NULL,
+ .packet_fwd = softnic_fwd,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/testpmd.c b/src/spdk/dpdk/app/test-pmd/testpmd.c
new file mode 100644
index 000000000..4989d22ca
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/testpmd.c
@@ -0,0 +1,3859 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_alarm.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_mbuf_pool_ops.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_dev.h>
+#include <rte_string_fns.h>
+#ifdef RTE_LIBRTE_IXGBE_PMD
+#include <rte_pmd_ixgbe.h>
+#endif
+#ifdef RTE_LIBRTE_PDUMP
+#include <rte_pdump.h>
+#endif
+#include <rte_flow.h>
+#include <rte_metrics.h>
+#ifdef RTE_LIBRTE_BITRATE
+#include <rte_bitrate.h>
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+#include <rte_latencystats.h>
+#endif
+
+#include "testpmd.h"
+
+#ifndef MAP_HUGETLB
+/* FreeBSD may not have MAP_HUGETLB (in fact, it probably doesn't) */
+#define HUGE_FLAG (0x40000)
+#else
+#define HUGE_FLAG MAP_HUGETLB
+#endif
+
+#ifndef MAP_HUGE_SHIFT
+/* older kernels (or FreeBSD) will not have this define */
+#define HUGE_SHIFT (26)
+#else
+#define HUGE_SHIFT MAP_HUGE_SHIFT
+#endif
+
+#define EXTMEM_HEAP_NAME "extmem"
+#define EXTBUF_ZONE_SIZE RTE_PGSIZE_2M
+
+uint16_t verbose_level = 0; /**< Silent by default. */
+int testpmd_logtype; /**< Log type for testpmd logs */
+
+/* use master core for command line ? */
+uint8_t interactive = 0;
+uint8_t auto_start = 0;
+uint8_t tx_first;
+char cmdline_filename[PATH_MAX] = {0};
+
+/*
+ * NUMA support configuration.
+ * When set, the NUMA support attempts to dispatch the allocation of the
+ * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the
+ * probed ports among the CPU sockets 0 and 1.
+ * Otherwise, all memory is allocated from CPU socket 0.
+ */
+uint8_t numa_support = 1; /**< numa enabled by default */
+
+/*
+ * In UMA mode,all memory is allocated from socket 0 if --socket-num is
+ * not configured.
+ */
+uint8_t socket_num = UMA_NO_CONFIG;
+
+/*
+ * Select mempool allocation type:
+ * - native: use regular DPDK memory
+ * - anon: use regular DPDK memory to create mempool, but populate using
+ * anonymous memory (may not be IOVA-contiguous)
+ * - xmem: use externally allocated hugepage memory
+ */
+uint8_t mp_alloc_type = MP_ALLOC_NATIVE;
+
+/*
+ * Store specified sockets on which memory pool to be used by ports
+ * is allocated.
+ */
+uint8_t port_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which RX ring to be used by ports
+ * is allocated.
+ */
+uint8_t rxring_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which TX ring to be used by ports
+ * is allocated.
+ */
+uint8_t txring_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Record the Ethernet address of peer target ports to which packets are
+ * forwarded.
+ * Must be instantiated with the ethernet addresses of peer traffic generator
+ * ports.
+ */
+struct rte_ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
+portid_t nb_peer_eth_addrs = 0;
+
+/*
+ * Probed Target Environment.
+ */
+struct rte_port *ports; /**< For all probed ethernet ports. */
+portid_t nb_ports; /**< Number of probed ethernet ports. */
+struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */
+lcoreid_t nb_lcores; /**< Number of probed logical cores. */
+
+portid_t ports_ids[RTE_MAX_ETHPORTS]; /**< Store all port ids. */
+
+/*
+ * Test Forwarding Configuration.
+ * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
+ * nb_fwd_ports <= nb_cfg_ports <= nb_ports
+ */
+lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
+lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
+portid_t nb_cfg_ports; /**< Number of configured ports. */
+portid_t nb_fwd_ports; /**< Number of forwarding ports. */
+
+unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */
+portid_t fwd_ports_ids[RTE_MAX_ETHPORTS]; /**< Port ids configuration. */
+
+struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */
+streamid_t nb_fwd_streams; /**< Is equal to (nb_ports * nb_rxq). */
+
+/*
+ * Forwarding engines.
+ */
+struct fwd_engine * fwd_engines[] = {
+ &io_fwd_engine,
+ &mac_fwd_engine,
+ &mac_swap_engine,
+ &flow_gen_engine,
+ &rx_only_engine,
+ &tx_only_engine,
+ &csum_fwd_engine,
+ &icmp_echo_engine,
+ &noisy_vnf_engine,
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+ &softnic_fwd_engine,
+#endif
+#ifdef RTE_LIBRTE_IEEE1588
+ &ieee1588_fwd_engine,
+#endif
+ NULL,
+};
+
+struct rte_mempool *mempools[RTE_MAX_NUMA_NODES];
+uint16_t mempool_flags;
+
+struct fwd_config cur_fwd_config;
+struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */
+uint32_t retry_enabled;
+uint32_t burst_tx_delay_time = BURST_TX_WAIT_US;
+uint32_t burst_tx_retry_num = BURST_TX_RETRIES;
+
+uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */
+uint32_t param_total_num_mbufs = 0; /**< number of mbufs in all pools - if
+ * specified on command-line. */
+uint16_t stats_period; /**< Period to show statistics (disabled by default) */
+
+/*
+ * In container, it cannot terminate the process which running with 'stats-period'
+ * option. Set flag to exit stats period loop after received SIGINT/SIGTERM.
+ */
+uint8_t f_quit;
+
+/*
+ * Configuration of packet segments used by the "txonly" processing engine.
+ */
+uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */
+uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = {
+ TXONLY_DEF_PACKET_LEN,
+};
+uint8_t tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */
+
+enum tx_pkt_split tx_pkt_split = TX_PKT_SPLIT_OFF;
+/**< Split policy for packets to TX. */
+
+uint8_t txonly_multi_flow;
+/**< Whether multiple flows are generated in TXONLY mode. */
+
+uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */
+uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */
+
+/* current configuration is in DCB or not,0 means it is not in DCB mode */
+uint8_t dcb_config = 0;
+
+/* Whether the dcb is in testing status */
+uint8_t dcb_test = 0;
+
+/*
+ * Configurable number of RX/TX queues.
+ */
+queueid_t nb_hairpinq; /**< Number of hairpin queues per port. */
+queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
+queueid_t nb_txq = 1; /**< Number of TX queues per port. */
+
+/*
+ * Configurable number of RX/TX ring descriptors.
+ * Defaults are supplied by drivers via ethdev.
+ */
+#define RTE_TEST_RX_DESC_DEFAULT 0
+#define RTE_TEST_TX_DESC_DEFAULT 0
+uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
+uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
+
+#define RTE_PMD_PARAM_UNSET -1
+/*
+ * Configurable values of RX and TX ring threshold registers.
+ */
+
+int8_t rx_pthresh = RTE_PMD_PARAM_UNSET;
+int8_t rx_hthresh = RTE_PMD_PARAM_UNSET;
+int8_t rx_wthresh = RTE_PMD_PARAM_UNSET;
+
+int8_t tx_pthresh = RTE_PMD_PARAM_UNSET;
+int8_t tx_hthresh = RTE_PMD_PARAM_UNSET;
+int8_t tx_wthresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of RX free threshold.
+ */
+int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of RX drop enable.
+ */
+int8_t rx_drop_en = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of TX free threshold.
+ */
+int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of TX RS bit threshold.
+ */
+int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET;
+
+/*
+ * Configurable value of buffered packets before sending.
+ */
+uint16_t noisy_tx_sw_bufsz;
+
+/*
+ * Configurable value of packet buffer timeout.
+ */
+uint16_t noisy_tx_sw_buf_flush_time;
+
+/*
+ * Configurable value for size of VNF internal memory area
+ * used for simulating noisy neighbour behaviour
+ */
+uint64_t noisy_lkup_mem_sz;
+
+/*
+ * Configurable value of number of random writes done in
+ * VNF simulation memory area.
+ */
+uint64_t noisy_lkup_num_writes;
+
+/*
+ * Configurable value of number of random reads done in
+ * VNF simulation memory area.
+ */
+uint64_t noisy_lkup_num_reads;
+
+/*
+ * Configurable value of number of random reads/writes done in
+ * VNF simulation memory area.
+ */
+uint64_t noisy_lkup_num_reads_writes;
+
+/*
+ * Receive Side Scaling (RSS) configuration.
+ */
+uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */
+
+/*
+ * Port topology configuration
+ */
+uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */
+
+/*
+ * Avoids to flush all the RX streams before starts forwarding.
+ */
+uint8_t no_flush_rx = 0; /* flush by default */
+
+/*
+ * Flow API isolated mode.
+ */
+uint8_t flow_isolate_all;
+
+/*
+ * Avoids to check link status when starting/stopping a port.
+ */
+uint8_t no_link_check = 0; /* check by default */
+
+/*
+ * Don't automatically start all ports in interactive mode.
+ */
+uint8_t no_device_start = 0;
+
+/*
+ * Enable link status change notification
+ */
+uint8_t lsc_interrupt = 1; /* enabled by default */
+
+/*
+ * Enable device removal notification.
+ */
+uint8_t rmv_interrupt = 1; /* enabled by default */
+
+uint8_t hot_plug = 0; /**< hotplug disabled by default. */
+
+/* After attach, port setup is called on event or by iterator */
+bool setup_on_probe_event = true;
+
+/* Clear ptypes on port initialization. */
+uint8_t clear_ptypes = true;
+
+/* Pretty printing of ethdev events */
+static const char * const eth_event_desc[] = {
+ [RTE_ETH_EVENT_UNKNOWN] = "unknown",
+ [RTE_ETH_EVENT_INTR_LSC] = "link state change",
+ [RTE_ETH_EVENT_QUEUE_STATE] = "queue state",
+ [RTE_ETH_EVENT_INTR_RESET] = "reset",
+ [RTE_ETH_EVENT_VF_MBOX] = "VF mbox",
+ [RTE_ETH_EVENT_IPSEC] = "IPsec",
+ [RTE_ETH_EVENT_MACSEC] = "MACsec",
+ [RTE_ETH_EVENT_INTR_RMV] = "device removal",
+ [RTE_ETH_EVENT_NEW] = "device probed",
+ [RTE_ETH_EVENT_DESTROY] = "device released",
+ [RTE_ETH_EVENT_FLOW_AGED] = "flow aged",
+ [RTE_ETH_EVENT_MAX] = NULL,
+};
+
+/*
+ * Display or mask ether events
+ * Default to all events except VF_MBOX
+ */
+uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) |
+ (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) |
+ (UINT32_C(1) << RTE_ETH_EVENT_IPSEC) |
+ (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) |
+ (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV) |
+ (UINT32_C(1) << RTE_ETH_EVENT_FLOW_AGED);
+/*
+ * Decide if all memory are locked for performance.
+ */
+int do_mlockall = 0;
+
+/*
+ * NIC bypass mode configuration options.
+ */
+
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+/* The NIC bypass watchdog timeout. */
+uint32_t bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF;
+#endif
+
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+
+/*
+ * Set when latency stats is enabled in the commandline
+ */
+uint8_t latencystats_enabled;
+
+/*
+ * Lcore ID to serive latency statistics.
+ */
+lcoreid_t latencystats_lcore_id = -1;
+
+#endif
+
+/*
+ * Ethernet device configuration.
+ */
+struct rte_eth_rxmode rx_mode = {
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ /**< Default maximum frame length. */
+};
+
+struct rte_eth_txmode tx_mode = {
+ .offloads = DEV_TX_OFFLOAD_MBUF_FAST_FREE,
+};
+
+struct rte_fdir_conf fdir_conf = {
+ .mode = RTE_FDIR_MODE_NONE,
+ .pballoc = RTE_FDIR_PBALLOC_64K,
+ .status = RTE_FDIR_REPORT_STATUS,
+ .mask = {
+ .vlan_tci_mask = 0xFFEF,
+ .ipv4_mask = {
+ .src_ip = 0xFFFFFFFF,
+ .dst_ip = 0xFFFFFFFF,
+ },
+ .ipv6_mask = {
+ .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
+ },
+ .src_port_mask = 0xFFFF,
+ .dst_port_mask = 0xFFFF,
+ .mac_addr_byte_mask = 0xFF,
+ .tunnel_type_mask = 1,
+ .tunnel_id_mask = 0xFFFFFFFF,
+ },
+ .drop_queue = 127,
+};
+
+volatile int test_done = 1; /* stop packet forwarding when set to 1. */
+
+struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS];
+struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS];
+
+struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array;
+struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array;
+
+uint16_t nb_tx_queue_stats_mappings = 0;
+uint16_t nb_rx_queue_stats_mappings = 0;
+
+/*
+ * Display zero values by default for xstats
+ */
+uint8_t xstats_hide_zero;
+
+unsigned int num_sockets = 0;
+unsigned int socket_ids[RTE_MAX_NUMA_NODES];
+
+#ifdef RTE_LIBRTE_BITRATE
+/* Bitrate statistics */
+struct rte_stats_bitrates *bitrate_data;
+lcoreid_t bitrate_lcore_id;
+uint8_t bitrate_enabled;
+#endif
+
+struct gro_status gro_ports[RTE_MAX_ETHPORTS];
+uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES;
+
+/*
+ * hexadecimal bitmask of RX mq mode can be enabled.
+ */
+enum rte_eth_rx_mq_mode rx_mq_mode = ETH_MQ_RX_VMDQ_DCB_RSS;
+
+/* Forward function declarations */
+static void setup_attached_port(portid_t pi);
+static void map_port_queue_stats_mapping_registers(portid_t pi,
+ struct rte_port *port);
+static void check_all_ports_link_status(uint32_t port_mask);
+static int eth_event_callback(portid_t port_id,
+ enum rte_eth_event_type type,
+ void *param, void *ret_param);
+static void dev_event_callback(const char *device_name,
+ enum rte_dev_event_type type,
+ void *param);
+
+/*
+ * Check if all the ports are started.
+ * If yes, return positive value. If not, return zero.
+ */
+static int all_ports_started(void);
+
+struct gso_status gso_ports[RTE_MAX_ETHPORTS];
+uint16_t gso_max_segment_size = RTE_ETHER_MAX_LEN - RTE_ETHER_CRC_LEN;
+
+/* Holds the registered mbuf dynamic flags names. */
+char dynf_names[64][RTE_MBUF_DYN_NAMESIZE];
+
+/*
+ * Helper function to check if socket is already discovered.
+ * If yes, return positive value. If not, return zero.
+ */
+int
+new_socket_id(unsigned int socket_id)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_sockets; i++) {
+ if (socket_ids[i] == socket_id)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Setup default configuration.
+ */
+static void
+set_default_fwd_lcores_config(void)
+{
+ unsigned int i;
+ unsigned int nb_lc;
+ unsigned int sock_num;
+
+ nb_lc = 0;
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ if (!rte_lcore_is_enabled(i))
+ continue;
+ sock_num = rte_lcore_to_socket_id(i);
+ if (new_socket_id(sock_num)) {
+ if (num_sockets >= RTE_MAX_NUMA_NODES) {
+ rte_exit(EXIT_FAILURE,
+ "Total sockets greater than %u\n",
+ RTE_MAX_NUMA_NODES);
+ }
+ socket_ids[num_sockets++] = sock_num;
+ }
+ if (i == rte_get_master_lcore())
+ continue;
+ fwd_lcores_cpuids[nb_lc++] = i;
+ }
+ nb_lcores = (lcoreid_t) nb_lc;
+ nb_cfg_lcores = nb_lcores;
+ nb_fwd_lcores = 1;
+}
+
+static void
+set_def_peer_eth_addrs(void)
+{
+ portid_t i;
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ peer_eth_addrs[i].addr_bytes[0] = RTE_ETHER_LOCAL_ADMIN_ADDR;
+ peer_eth_addrs[i].addr_bytes[5] = i;
+ }
+}
+
+static void
+set_default_fwd_ports_config(void)
+{
+ portid_t pt_id;
+ int i = 0;
+
+ RTE_ETH_FOREACH_DEV(pt_id) {
+ fwd_ports_ids[i++] = pt_id;
+
+ /* Update sockets info according to the attached device */
+ int socket_id = rte_eth_dev_socket_id(pt_id);
+ if (socket_id >= 0 && new_socket_id(socket_id)) {
+ if (num_sockets >= RTE_MAX_NUMA_NODES) {
+ rte_exit(EXIT_FAILURE,
+ "Total sockets greater than %u\n",
+ RTE_MAX_NUMA_NODES);
+ }
+ socket_ids[num_sockets++] = socket_id;
+ }
+ }
+
+ nb_cfg_ports = nb_ports;
+ nb_fwd_ports = nb_ports;
+}
+
+void
+set_def_fwd_config(void)
+{
+ set_default_fwd_lcores_config();
+ set_def_peer_eth_addrs();
+ set_default_fwd_ports_config();
+}
+
+/* extremely pessimistic estimation of memory required to create a mempool */
+static int
+calc_mem_size(uint32_t nb_mbufs, uint32_t mbuf_sz, size_t pgsz, size_t *out)
+{
+ unsigned int n_pages, mbuf_per_pg, leftover;
+ uint64_t total_mem, mbuf_mem, obj_sz;
+
+ /* there is no good way to predict how much space the mempool will
+ * occupy because it will allocate chunks on the fly, and some of those
+ * will come from default DPDK memory while some will come from our
+ * external memory, so just assume 128MB will be enough for everyone.
+ */
+ uint64_t hdr_mem = 128 << 20;
+
+ /* account for possible non-contiguousness */
+ obj_sz = rte_mempool_calc_obj_size(mbuf_sz, 0, NULL);
+ if (obj_sz > pgsz) {
+ TESTPMD_LOG(ERR, "Object size is bigger than page size\n");
+ return -1;
+ }
+
+ mbuf_per_pg = pgsz / obj_sz;
+ leftover = (nb_mbufs % mbuf_per_pg) > 0;
+ n_pages = (nb_mbufs / mbuf_per_pg) + leftover;
+
+ mbuf_mem = n_pages * pgsz;
+
+ total_mem = RTE_ALIGN(hdr_mem + mbuf_mem, pgsz);
+
+ if (total_mem > SIZE_MAX) {
+ TESTPMD_LOG(ERR, "Memory size too big\n");
+ return -1;
+ }
+ *out = (size_t)total_mem;
+
+ return 0;
+}
+
+static int
+pagesz_flags(uint64_t page_sz)
+{
+ /* as per mmap() manpage, all page sizes are log2 of page size
+ * shifted by MAP_HUGE_SHIFT
+ */
+ int log2 = rte_log2_u64(page_sz);
+
+ return (log2 << HUGE_SHIFT);
+}
+
+static void *
+alloc_mem(size_t memsz, size_t pgsz, bool huge)
+{
+ void *addr;
+ int flags;
+
+ /* allocate anonymous hugepages */
+ flags = MAP_ANONYMOUS | MAP_PRIVATE;
+ if (huge)
+ flags |= HUGE_FLAG | pagesz_flags(pgsz);
+
+ addr = mmap(NULL, memsz, PROT_READ | PROT_WRITE, flags, -1, 0);
+ if (addr == MAP_FAILED)
+ return NULL;
+
+ return addr;
+}
+
+struct extmem_param {
+ void *addr;
+ size_t len;
+ size_t pgsz;
+ rte_iova_t *iova_table;
+ unsigned int iova_table_len;
+};
+
+static int
+create_extmem(uint32_t nb_mbufs, uint32_t mbuf_sz, struct extmem_param *param,
+ bool huge)
+{
+ uint64_t pgsizes[] = {RTE_PGSIZE_2M, RTE_PGSIZE_1G, /* x86_64, ARM */
+ RTE_PGSIZE_16M, RTE_PGSIZE_16G}; /* POWER */
+ unsigned int cur_page, n_pages, pgsz_idx;
+ size_t mem_sz, cur_pgsz;
+ rte_iova_t *iovas = NULL;
+ void *addr;
+ int ret;
+
+ for (pgsz_idx = 0; pgsz_idx < RTE_DIM(pgsizes); pgsz_idx++) {
+ /* skip anything that is too big */
+ if (pgsizes[pgsz_idx] > SIZE_MAX)
+ continue;
+
+ cur_pgsz = pgsizes[pgsz_idx];
+
+ /* if we were told not to allocate hugepages, override */
+ if (!huge)
+ cur_pgsz = sysconf(_SC_PAGESIZE);
+
+ ret = calc_mem_size(nb_mbufs, mbuf_sz, cur_pgsz, &mem_sz);
+ if (ret < 0) {
+ TESTPMD_LOG(ERR, "Cannot calculate memory size\n");
+ return -1;
+ }
+
+ /* allocate our memory */
+ addr = alloc_mem(mem_sz, cur_pgsz, huge);
+
+ /* if we couldn't allocate memory with a specified page size,
+ * that doesn't mean we can't do it with other page sizes, so
+ * try another one.
+ */
+ if (addr == NULL)
+ continue;
+
+ /* store IOVA addresses for every page in this memory area */
+ n_pages = mem_sz / cur_pgsz;
+
+ iovas = malloc(sizeof(*iovas) * n_pages);
+
+ if (iovas == NULL) {
+ TESTPMD_LOG(ERR, "Cannot allocate memory for iova addresses\n");
+ goto fail;
+ }
+ /* lock memory if it's not huge pages */
+ if (!huge)
+ mlock(addr, mem_sz);
+
+ /* populate IOVA addresses */
+ for (cur_page = 0; cur_page < n_pages; cur_page++) {
+ rte_iova_t iova;
+ size_t offset;
+ void *cur;
+
+ offset = cur_pgsz * cur_page;
+ cur = RTE_PTR_ADD(addr, offset);
+
+ /* touch the page before getting its IOVA */
+ *(volatile char *)cur = 0;
+
+ iova = rte_mem_virt2iova(cur);
+
+ iovas[cur_page] = iova;
+ }
+
+ break;
+ }
+ /* if we couldn't allocate anything */
+ if (iovas == NULL)
+ return -1;
+
+ param->addr = addr;
+ param->len = mem_sz;
+ param->pgsz = cur_pgsz;
+ param->iova_table = iovas;
+ param->iova_table_len = n_pages;
+
+ return 0;
+fail:
+ if (iovas)
+ free(iovas);
+ if (addr)
+ munmap(addr, mem_sz);
+
+ return -1;
+}
+
+static int
+setup_extmem(uint32_t nb_mbufs, uint32_t mbuf_sz, bool huge)
+{
+ struct extmem_param param;
+ int socket_id, ret;
+
+ memset(&param, 0, sizeof(param));
+
+ /* check if our heap exists */
+ socket_id = rte_malloc_heap_get_socket(EXTMEM_HEAP_NAME);
+ if (socket_id < 0) {
+ /* create our heap */
+ ret = rte_malloc_heap_create(EXTMEM_HEAP_NAME);
+ if (ret < 0) {
+ TESTPMD_LOG(ERR, "Cannot create heap\n");
+ return -1;
+ }
+ }
+
+ ret = create_extmem(nb_mbufs, mbuf_sz, &param, huge);
+ if (ret < 0) {
+ TESTPMD_LOG(ERR, "Cannot create memory area\n");
+ return -1;
+ }
+
+ /* we now have a valid memory area, so add it to heap */
+ ret = rte_malloc_heap_memory_add(EXTMEM_HEAP_NAME,
+ param.addr, param.len, param.iova_table,
+ param.iova_table_len, param.pgsz);
+
+ /* when using VFIO, memory is automatically mapped for DMA by EAL */
+
+ /* not needed any more */
+ free(param.iova_table);
+
+ if (ret < 0) {
+ TESTPMD_LOG(ERR, "Cannot add memory to heap\n");
+ munmap(param.addr, param.len);
+ return -1;
+ }
+
+ /* success */
+
+ TESTPMD_LOG(DEBUG, "Allocated %zuMB of external memory\n",
+ param.len >> 20);
+
+ return 0;
+}
+static void
+dma_unmap_cb(struct rte_mempool *mp __rte_unused, void *opaque __rte_unused,
+ struct rte_mempool_memhdr *memhdr, unsigned mem_idx __rte_unused)
+{
+ uint16_t pid = 0;
+ int ret;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ struct rte_eth_dev *dev =
+ &rte_eth_devices[pid];
+
+ ret = rte_dev_dma_unmap(dev->device, memhdr->addr, 0,
+ memhdr->len);
+ if (ret) {
+ TESTPMD_LOG(DEBUG,
+ "unable to DMA unmap addr 0x%p "
+ "for device %s\n",
+ memhdr->addr, dev->data->name);
+ }
+ }
+ ret = rte_extmem_unregister(memhdr->addr, memhdr->len);
+ if (ret) {
+ TESTPMD_LOG(DEBUG,
+ "unable to un-register addr 0x%p\n", memhdr->addr);
+ }
+}
+
+static void
+dma_map_cb(struct rte_mempool *mp __rte_unused, void *opaque __rte_unused,
+ struct rte_mempool_memhdr *memhdr, unsigned mem_idx __rte_unused)
+{
+ uint16_t pid = 0;
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ int ret;
+
+ ret = rte_extmem_register(memhdr->addr, memhdr->len, NULL, 0,
+ page_size);
+ if (ret) {
+ TESTPMD_LOG(DEBUG,
+ "unable to register addr 0x%p\n", memhdr->addr);
+ return;
+ }
+ RTE_ETH_FOREACH_DEV(pid) {
+ struct rte_eth_dev *dev =
+ &rte_eth_devices[pid];
+
+ ret = rte_dev_dma_map(dev->device, memhdr->addr, 0,
+ memhdr->len);
+ if (ret) {
+ TESTPMD_LOG(DEBUG,
+ "unable to DMA map addr 0x%p "
+ "for device %s\n",
+ memhdr->addr, dev->data->name);
+ }
+ }
+}
+
+static unsigned int
+setup_extbuf(uint32_t nb_mbufs, uint16_t mbuf_sz, unsigned int socket_id,
+ char *pool_name, struct rte_pktmbuf_extmem **ext_mem)
+{
+ struct rte_pktmbuf_extmem *xmem;
+ unsigned int ext_num, zone_num, elt_num;
+ uint16_t elt_size;
+
+ elt_size = RTE_ALIGN_CEIL(mbuf_sz, RTE_CACHE_LINE_SIZE);
+ elt_num = EXTBUF_ZONE_SIZE / elt_size;
+ zone_num = (nb_mbufs + elt_num - 1) / elt_num;
+
+ xmem = malloc(sizeof(struct rte_pktmbuf_extmem) * zone_num);
+ if (xmem == NULL) {
+ TESTPMD_LOG(ERR, "Cannot allocate memory for "
+ "external buffer descriptors\n");
+ *ext_mem = NULL;
+ return 0;
+ }
+ for (ext_num = 0; ext_num < zone_num; ext_num++) {
+ struct rte_pktmbuf_extmem *xseg = xmem + ext_num;
+ const struct rte_memzone *mz;
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+ int ret;
+
+ ret = snprintf(mz_name, sizeof(mz_name),
+ RTE_MEMPOOL_MZ_FORMAT "_xb_%u", pool_name, ext_num);
+ if (ret < 0 || ret >= (int)sizeof(mz_name)) {
+ errno = ENAMETOOLONG;
+ ext_num = 0;
+ break;
+ }
+ mz = rte_memzone_reserve_aligned(mz_name, EXTBUF_ZONE_SIZE,
+ socket_id,
+ RTE_MEMZONE_IOVA_CONTIG |
+ RTE_MEMZONE_1GB |
+ RTE_MEMZONE_SIZE_HINT_ONLY,
+ EXTBUF_ZONE_SIZE);
+ if (mz == NULL) {
+ /*
+ * The caller exits on external buffer creation
+ * error, so there is no need to free memzones.
+ */
+ errno = ENOMEM;
+ ext_num = 0;
+ break;
+ }
+ xseg->buf_ptr = mz->addr;
+ xseg->buf_iova = mz->iova;
+ xseg->buf_len = EXTBUF_ZONE_SIZE;
+ xseg->elt_size = elt_size;
+ }
+ if (ext_num == 0 && xmem != NULL) {
+ free(xmem);
+ xmem = NULL;
+ }
+ *ext_mem = xmem;
+ return ext_num;
+}
+
+/*
+ * Configuration initialisation done once at init time.
+ */
+static struct rte_mempool *
+mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf,
+ unsigned int socket_id)
+{
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+ struct rte_mempool *rte_mp = NULL;
+ uint32_t mb_size;
+
+ mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size;
+ mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name));
+
+ TESTPMD_LOG(INFO,
+ "create a new mbuf pool <%s>: n=%u, size=%u, socket=%u\n",
+ pool_name, nb_mbuf, mbuf_seg_size, socket_id);
+
+ switch (mp_alloc_type) {
+ case MP_ALLOC_NATIVE:
+ {
+ /* wrapper to rte_mempool_create() */
+ TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
+ rte_mbuf_best_mempool_ops());
+ rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
+ mb_mempool_cache, 0, mbuf_seg_size, socket_id);
+ break;
+ }
+ case MP_ALLOC_ANON:
+ {
+ rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf,
+ mb_size, (unsigned int) mb_mempool_cache,
+ sizeof(struct rte_pktmbuf_pool_private),
+ socket_id, mempool_flags);
+ if (rte_mp == NULL)
+ goto err;
+
+ if (rte_mempool_populate_anon(rte_mp) == 0) {
+ rte_mempool_free(rte_mp);
+ rte_mp = NULL;
+ goto err;
+ }
+ rte_pktmbuf_pool_init(rte_mp, NULL);
+ rte_mempool_obj_iter(rte_mp, rte_pktmbuf_init, NULL);
+ rte_mempool_mem_iter(rte_mp, dma_map_cb, NULL);
+ break;
+ }
+ case MP_ALLOC_XMEM:
+ case MP_ALLOC_XMEM_HUGE:
+ {
+ int heap_socket;
+ bool huge = mp_alloc_type == MP_ALLOC_XMEM_HUGE;
+
+ if (setup_extmem(nb_mbuf, mbuf_seg_size, huge) < 0)
+ rte_exit(EXIT_FAILURE, "Could not create external memory\n");
+
+ heap_socket =
+ rte_malloc_heap_get_socket(EXTMEM_HEAP_NAME);
+ if (heap_socket < 0)
+ rte_exit(EXIT_FAILURE, "Could not get external memory socket ID\n");
+
+ TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
+ rte_mbuf_best_mempool_ops());
+ rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf,
+ mb_mempool_cache, 0, mbuf_seg_size,
+ heap_socket);
+ break;
+ }
+ case MP_ALLOC_XBUF:
+ {
+ struct rte_pktmbuf_extmem *ext_mem;
+ unsigned int ext_num;
+
+ ext_num = setup_extbuf(nb_mbuf, mbuf_seg_size,
+ socket_id, pool_name, &ext_mem);
+ if (ext_num == 0)
+ rte_exit(EXIT_FAILURE,
+ "Can't create pinned data buffers\n");
+
+ TESTPMD_LOG(INFO, "preferred mempool ops selected: %s\n",
+ rte_mbuf_best_mempool_ops());
+ rte_mp = rte_pktmbuf_pool_create_extbuf
+ (pool_name, nb_mbuf, mb_mempool_cache,
+ 0, mbuf_seg_size, socket_id,
+ ext_mem, ext_num);
+ free(ext_mem);
+ break;
+ }
+ default:
+ {
+ rte_exit(EXIT_FAILURE, "Invalid mempool creation mode\n");
+ }
+ }
+
+err:
+ if (rte_mp == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "Creation of mbuf pool for socket %u failed: %s\n",
+ socket_id, rte_strerror(rte_errno));
+ } else if (verbose_level > 0) {
+ rte_mempool_dump(stdout, rte_mp);
+ }
+ return rte_mp;
+}
+
+/*
+ * Check given socket id is valid or not with NUMA mode,
+ * if valid, return 0, else return -1
+ */
+static int
+check_socket_id(const unsigned int socket_id)
+{
+ static int warning_once = 0;
+
+ if (new_socket_id(socket_id)) {
+ if (!warning_once && numa_support)
+ printf("Warning: NUMA should be configured manually by"
+ " using --port-numa-config and"
+ " --ring-numa-config parameters along with"
+ " --numa.\n");
+ warning_once = 1;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Get the allowed maximum number of RX queues.
+ * *pid return the port id which has minimal value of
+ * max_rx_queues in all ports.
+ */
+queueid_t
+get_allowed_max_nb_rxq(portid_t *pid)
+{
+ queueid_t allowed_max_rxq = RTE_MAX_QUEUES_PER_PORT;
+ bool max_rxq_valid = false;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ max_rxq_valid = true;
+ if (dev_info.max_rx_queues < allowed_max_rxq) {
+ allowed_max_rxq = dev_info.max_rx_queues;
+ *pid = pi;
+ }
+ }
+ return max_rxq_valid ? allowed_max_rxq : 0;
+}
+
+/*
+ * Check input rxq is valid or not.
+ * If input rxq is not greater than any of maximum number
+ * of RX queues of all ports, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_rxq(queueid_t rxq)
+{
+ queueid_t allowed_max_rxq;
+ portid_t pid = 0;
+
+ allowed_max_rxq = get_allowed_max_nb_rxq(&pid);
+ if (rxq > allowed_max_rxq) {
+ printf("Fail: input rxq (%u) can't be greater "
+ "than max_rx_queues (%u) of port %u\n",
+ rxq,
+ allowed_max_rxq,
+ pid);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Get the allowed maximum number of TX queues.
+ * *pid return the port id which has minimal value of
+ * max_tx_queues in all ports.
+ */
+queueid_t
+get_allowed_max_nb_txq(portid_t *pid)
+{
+ queueid_t allowed_max_txq = RTE_MAX_QUEUES_PER_PORT;
+ bool max_txq_valid = false;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ max_txq_valid = true;
+ if (dev_info.max_tx_queues < allowed_max_txq) {
+ allowed_max_txq = dev_info.max_tx_queues;
+ *pid = pi;
+ }
+ }
+ return max_txq_valid ? allowed_max_txq : 0;
+}
+
+/*
+ * Check input txq is valid or not.
+ * If input txq is not greater than any of maximum number
+ * of TX queues of all ports, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_txq(queueid_t txq)
+{
+ queueid_t allowed_max_txq;
+ portid_t pid = 0;
+
+ allowed_max_txq = get_allowed_max_nb_txq(&pid);
+ if (txq > allowed_max_txq) {
+ printf("Fail: input txq (%u) can't be greater "
+ "than max_tx_queues (%u) of port %u\n",
+ txq,
+ allowed_max_txq,
+ pid);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Get the allowed maximum number of RXDs of every rx queue.
+ * *pid return the port id which has minimal value of
+ * max_rxd in all queues of all ports.
+ */
+static uint16_t
+get_allowed_max_nb_rxd(portid_t *pid)
+{
+ uint16_t allowed_max_rxd = UINT16_MAX;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ if (dev_info.rx_desc_lim.nb_max < allowed_max_rxd) {
+ allowed_max_rxd = dev_info.rx_desc_lim.nb_max;
+ *pid = pi;
+ }
+ }
+ return allowed_max_rxd;
+}
+
+/*
+ * Get the allowed minimal number of RXDs of every rx queue.
+ * *pid return the port id which has minimal value of
+ * min_rxd in all queues of all ports.
+ */
+static uint16_t
+get_allowed_min_nb_rxd(portid_t *pid)
+{
+ uint16_t allowed_min_rxd = 0;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ if (dev_info.rx_desc_lim.nb_min > allowed_min_rxd) {
+ allowed_min_rxd = dev_info.rx_desc_lim.nb_min;
+ *pid = pi;
+ }
+ }
+
+ return allowed_min_rxd;
+}
+
+/*
+ * Check input rxd is valid or not.
+ * If input rxd is not greater than any of maximum number
+ * of RXDs of every Rx queues and is not less than any of
+ * minimal number of RXDs of every Rx queues, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_rxd(queueid_t rxd)
+{
+ uint16_t allowed_max_rxd;
+ uint16_t allowed_min_rxd;
+ portid_t pid = 0;
+
+ allowed_max_rxd = get_allowed_max_nb_rxd(&pid);
+ if (rxd > allowed_max_rxd) {
+ printf("Fail: input rxd (%u) can't be greater "
+ "than max_rxds (%u) of port %u\n",
+ rxd,
+ allowed_max_rxd,
+ pid);
+ return -1;
+ }
+
+ allowed_min_rxd = get_allowed_min_nb_rxd(&pid);
+ if (rxd < allowed_min_rxd) {
+ printf("Fail: input rxd (%u) can't be less "
+ "than min_rxds (%u) of port %u\n",
+ rxd,
+ allowed_min_rxd,
+ pid);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the allowed maximum number of TXDs of every rx queues.
+ * *pid return the port id which has minimal value of
+ * max_txd in every tx queue.
+ */
+static uint16_t
+get_allowed_max_nb_txd(portid_t *pid)
+{
+ uint16_t allowed_max_txd = UINT16_MAX;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ if (dev_info.tx_desc_lim.nb_max < allowed_max_txd) {
+ allowed_max_txd = dev_info.tx_desc_lim.nb_max;
+ *pid = pi;
+ }
+ }
+ return allowed_max_txd;
+}
+
+/*
+ * Get the allowed maximum number of TXDs of every tx queues.
+ * *pid return the port id which has minimal value of
+ * min_txd in every tx queue.
+ */
+static uint16_t
+get_allowed_min_nb_txd(portid_t *pid)
+{
+ uint16_t allowed_min_txd = 0;
+ portid_t pi;
+ struct rte_eth_dev_info dev_info;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+ continue;
+
+ if (dev_info.tx_desc_lim.nb_min > allowed_min_txd) {
+ allowed_min_txd = dev_info.tx_desc_lim.nb_min;
+ *pid = pi;
+ }
+ }
+
+ return allowed_min_txd;
+}
+
+/*
+ * Check input txd is valid or not.
+ * If input txd is not greater than any of maximum number
+ * of TXDs of every Rx queues, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_txd(queueid_t txd)
+{
+ uint16_t allowed_max_txd;
+ uint16_t allowed_min_txd;
+ portid_t pid = 0;
+
+ allowed_max_txd = get_allowed_max_nb_txd(&pid);
+ if (txd > allowed_max_txd) {
+ printf("Fail: input txd (%u) can't be greater "
+ "than max_txds (%u) of port %u\n",
+ txd,
+ allowed_max_txd,
+ pid);
+ return -1;
+ }
+
+ allowed_min_txd = get_allowed_min_nb_txd(&pid);
+ if (txd < allowed_min_txd) {
+ printf("Fail: input txd (%u) can't be less "
+ "than min_txds (%u) of port %u\n",
+ txd,
+ allowed_min_txd,
+ pid);
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * Get the allowed maximum number of hairpin queues.
+ * *pid return the port id which has minimal value of
+ * max_hairpin_queues in all ports.
+ */
+queueid_t
+get_allowed_max_nb_hairpinq(portid_t *pid)
+{
+ queueid_t allowed_max_hairpinq = RTE_MAX_QUEUES_PER_PORT;
+ portid_t pi;
+ struct rte_eth_hairpin_cap cap;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (rte_eth_dev_hairpin_capability_get(pi, &cap) != 0) {
+ *pid = pi;
+ return 0;
+ }
+ if (cap.max_nb_queues < allowed_max_hairpinq) {
+ allowed_max_hairpinq = cap.max_nb_queues;
+ *pid = pi;
+ }
+ }
+ return allowed_max_hairpinq;
+}
+
+/*
+ * Check input hairpin is valid or not.
+ * If input hairpin is not greater than any of maximum number
+ * of hairpin queues of all ports, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_hairpinq(queueid_t hairpinq)
+{
+ queueid_t allowed_max_hairpinq;
+ portid_t pid = 0;
+
+ allowed_max_hairpinq = get_allowed_max_nb_hairpinq(&pid);
+ if (hairpinq > allowed_max_hairpinq) {
+ printf("Fail: input hairpin (%u) can't be greater "
+ "than max_hairpin_queues (%u) of port %u\n",
+ hairpinq, allowed_max_hairpinq, pid);
+ return -1;
+ }
+ return 0;
+}
+
+static void
+init_config(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+ struct rte_mempool *mbp;
+ unsigned int nb_mbuf_per_pool;
+ lcoreid_t lc_id;
+ uint8_t port_per_socket[RTE_MAX_NUMA_NODES];
+ struct rte_gro_param gro_param;
+ uint32_t gso_types;
+ uint16_t data_size;
+ bool warning = 0;
+ int k;
+ int ret;
+
+ memset(port_per_socket,0,RTE_MAX_NUMA_NODES);
+
+ /* Configuration of logical cores. */
+ fwd_lcores = rte_zmalloc("testpmd: fwd_lcores",
+ sizeof(struct fwd_lcore *) * nb_lcores,
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_lcores == NULL) {
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) "
+ "failed\n", nb_lcores);
+ }
+ for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
+ fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore",
+ sizeof(struct fwd_lcore),
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_lcores[lc_id] == NULL) {
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) "
+ "failed\n");
+ }
+ fwd_lcores[lc_id]->cpuid_idx = lc_id;
+ }
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ /* Apply default TxRx configuration for all ports */
+ port->dev_conf.txmode = tx_mode;
+ port->dev_conf.rxmode = rx_mode;
+
+ ret = eth_dev_info_get_print_err(pid, &port->dev_info);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_dev_info_get() failed\n");
+
+ if (!(port->dev_info.tx_offload_capa &
+ DEV_TX_OFFLOAD_MBUF_FAST_FREE))
+ port->dev_conf.txmode.offloads &=
+ ~DEV_TX_OFFLOAD_MBUF_FAST_FREE;
+ if (numa_support) {
+ if (port_numa[pid] != NUMA_NO_CONFIG)
+ port_per_socket[port_numa[pid]]++;
+ else {
+ uint32_t socket_id = rte_eth_dev_socket_id(pid);
+
+ /*
+ * if socket_id is invalid,
+ * set to the first available socket.
+ */
+ if (check_socket_id(socket_id) < 0)
+ socket_id = socket_ids[0];
+ port_per_socket[socket_id]++;
+ }
+ }
+
+ /* Apply Rx offloads configuration */
+ for (k = 0; k < port->dev_info.max_rx_queues; k++)
+ port->rx_conf[k].offloads =
+ port->dev_conf.rxmode.offloads;
+ /* Apply Tx offloads configuration */
+ for (k = 0; k < port->dev_info.max_tx_queues; k++)
+ port->tx_conf[k].offloads =
+ port->dev_conf.txmode.offloads;
+
+ /* set flag to initialize port/queue */
+ port->need_reconfig = 1;
+ port->need_reconfig_queues = 1;
+ port->tx_metadata = 0;
+
+ /* Check for maximum number of segments per MTU. Accordingly
+ * update the mbuf data size.
+ */
+ if (port->dev_info.rx_desc_lim.nb_mtu_seg_max != UINT16_MAX &&
+ port->dev_info.rx_desc_lim.nb_mtu_seg_max != 0) {
+ data_size = rx_mode.max_rx_pkt_len /
+ port->dev_info.rx_desc_lim.nb_mtu_seg_max;
+
+ if ((data_size + RTE_PKTMBUF_HEADROOM) >
+ mbuf_data_size) {
+ mbuf_data_size = data_size +
+ RTE_PKTMBUF_HEADROOM;
+ warning = 1;
+ }
+ }
+ }
+
+ if (warning)
+ TESTPMD_LOG(WARNING, "Configured mbuf size %hu\n",
+ mbuf_data_size);
+
+ /*
+ * Create pools of mbuf.
+ * If NUMA support is disabled, create a single pool of mbuf in
+ * socket 0 memory by default.
+ * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1.
+ *
+ * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and
+ * nb_txd can be configured at run time.
+ */
+ if (param_total_num_mbufs)
+ nb_mbuf_per_pool = param_total_num_mbufs;
+ else {
+ nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX +
+ (nb_lcores * mb_mempool_cache) +
+ RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
+ nb_mbuf_per_pool *= RTE_MAX_ETHPORTS;
+ }
+
+ if (numa_support) {
+ uint8_t i;
+
+ for (i = 0; i < num_sockets; i++)
+ mempools[i] = mbuf_pool_create(mbuf_data_size,
+ nb_mbuf_per_pool,
+ socket_ids[i]);
+ } else {
+ if (socket_num == UMA_NO_CONFIG)
+ mempools[0] = mbuf_pool_create(mbuf_data_size,
+ nb_mbuf_per_pool, 0);
+ else
+ mempools[socket_num] = mbuf_pool_create
+ (mbuf_data_size,
+ nb_mbuf_per_pool,
+ socket_num);
+ }
+
+ init_port_config();
+
+ gso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+ DEV_TX_OFFLOAD_GRE_TNL_TSO | DEV_TX_OFFLOAD_UDP_TSO;
+ /*
+ * Records which Mbuf pool to use by each logical core, if needed.
+ */
+ for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
+ mbp = mbuf_pool_find(
+ rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]));
+
+ if (mbp == NULL)
+ mbp = mbuf_pool_find(0);
+ fwd_lcores[lc_id]->mbp = mbp;
+ /* initialize GSO context */
+ fwd_lcores[lc_id]->gso_ctx.direct_pool = mbp;
+ fwd_lcores[lc_id]->gso_ctx.indirect_pool = mbp;
+ fwd_lcores[lc_id]->gso_ctx.gso_types = gso_types;
+ fwd_lcores[lc_id]->gso_ctx.gso_size = RTE_ETHER_MAX_LEN -
+ RTE_ETHER_CRC_LEN;
+ fwd_lcores[lc_id]->gso_ctx.flag = 0;
+ }
+
+ /* Configuration of packet forwarding streams. */
+ if (init_fwd_streams() < 0)
+ rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n");
+
+ fwd_config_setup();
+
+ /* create a gro context for each lcore */
+ gro_param.gro_types = RTE_GRO_TCP_IPV4;
+ gro_param.max_flow_num = GRO_MAX_FLUSH_CYCLES;
+ gro_param.max_item_per_flow = MAX_PKT_BURST;
+ for (lc_id = 0; lc_id < nb_lcores; lc_id++) {
+ gro_param.socket_id = rte_lcore_to_socket_id(
+ fwd_lcores_cpuids[lc_id]);
+ fwd_lcores[lc_id]->gro_ctx = rte_gro_ctx_create(&gro_param);
+ if (fwd_lcores[lc_id]->gro_ctx == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "rte_gro_ctx_create() failed\n");
+ }
+ }
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) {
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ const char *driver = port->dev_info.driver_name;
+
+ if (strcmp(driver, "net_softnic") == 0)
+ port->softport.fwd_lcore_arg = fwd_lcores;
+ }
+ }
+#endif
+
+}
+
+
+void
+reconfig(portid_t new_port_id, unsigned socket_id)
+{
+ struct rte_port *port;
+ int ret;
+
+ /* Reconfiguration of Ethernet ports. */
+ port = &ports[new_port_id];
+
+ ret = eth_dev_info_get_print_err(new_port_id, &port->dev_info);
+ if (ret != 0)
+ return;
+
+ /* set flag to initialize port/queue */
+ port->need_reconfig = 1;
+ port->need_reconfig_queues = 1;
+ port->socket_id = socket_id;
+
+ init_port_config();
+}
+
+
+int
+init_fwd_streams(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+ streamid_t sm_id, nb_fwd_streams_new;
+ queueid_t q;
+
+ /* set socket id according to numa or not */
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ if (nb_rxq > port->dev_info.max_rx_queues) {
+ printf("Fail: nb_rxq(%d) is greater than "
+ "max_rx_queues(%d)\n", nb_rxq,
+ port->dev_info.max_rx_queues);
+ return -1;
+ }
+ if (nb_txq > port->dev_info.max_tx_queues) {
+ printf("Fail: nb_txq(%d) is greater than "
+ "max_tx_queues(%d)\n", nb_txq,
+ port->dev_info.max_tx_queues);
+ return -1;
+ }
+ if (numa_support) {
+ if (port_numa[pid] != NUMA_NO_CONFIG)
+ port->socket_id = port_numa[pid];
+ else {
+ port->socket_id = rte_eth_dev_socket_id(pid);
+
+ /*
+ * if socket_id is invalid,
+ * set to the first available socket.
+ */
+ if (check_socket_id(port->socket_id) < 0)
+ port->socket_id = socket_ids[0];
+ }
+ }
+ else {
+ if (socket_num == UMA_NO_CONFIG)
+ port->socket_id = 0;
+ else
+ port->socket_id = socket_num;
+ }
+ }
+
+ q = RTE_MAX(nb_rxq, nb_txq);
+ if (q == 0) {
+ printf("Fail: Cannot allocate fwd streams as number of queues is 0\n");
+ return -1;
+ }
+ nb_fwd_streams_new = (streamid_t)(nb_ports * q);
+ if (nb_fwd_streams_new == nb_fwd_streams)
+ return 0;
+ /* clear the old */
+ if (fwd_streams != NULL) {
+ for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
+ if (fwd_streams[sm_id] == NULL)
+ continue;
+ rte_free(fwd_streams[sm_id]);
+ fwd_streams[sm_id] = NULL;
+ }
+ rte_free(fwd_streams);
+ fwd_streams = NULL;
+ }
+
+ /* init new */
+ nb_fwd_streams = nb_fwd_streams_new;
+ if (nb_fwd_streams) {
+ fwd_streams = rte_zmalloc("testpmd: fwd_streams",
+ sizeof(struct fwd_stream *) * nb_fwd_streams,
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_streams == NULL)
+ rte_exit(EXIT_FAILURE, "rte_zmalloc(%d"
+ " (struct fwd_stream *)) failed\n",
+ nb_fwd_streams);
+
+ for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
+ fwd_streams[sm_id] = rte_zmalloc("testpmd:"
+ " struct fwd_stream", sizeof(struct fwd_stream),
+ RTE_CACHE_LINE_SIZE);
+ if (fwd_streams[sm_id] == NULL)
+ rte_exit(EXIT_FAILURE, "rte_zmalloc"
+ "(struct fwd_stream) failed\n");
+ }
+ }
+
+ return 0;
+}
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+static void
+pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
+{
+ unsigned int total_burst;
+ unsigned int nb_burst;
+ unsigned int burst_stats[3];
+ uint16_t pktnb_stats[3];
+ uint16_t nb_pkt;
+ int burst_percent[3];
+
+ /*
+ * First compute the total number of packet bursts and the
+ * two highest numbers of bursts of the same number of packets.
+ */
+ total_burst = 0;
+ burst_stats[0] = burst_stats[1] = burst_stats[2] = 0;
+ pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0;
+ for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) {
+ nb_burst = pbs->pkt_burst_spread[nb_pkt];
+ if (nb_burst == 0)
+ continue;
+ total_burst += nb_burst;
+ if (nb_burst > burst_stats[0]) {
+ burst_stats[1] = burst_stats[0];
+ pktnb_stats[1] = pktnb_stats[0];
+ burst_stats[0] = nb_burst;
+ pktnb_stats[0] = nb_pkt;
+ } else if (nb_burst > burst_stats[1]) {
+ burst_stats[1] = nb_burst;
+ pktnb_stats[1] = nb_pkt;
+ }
+ }
+ if (total_burst == 0)
+ return;
+ burst_percent[0] = (burst_stats[0] * 100) / total_burst;
+ printf(" %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst,
+ burst_percent[0], (int) pktnb_stats[0]);
+ if (burst_stats[0] == total_burst) {
+ printf("]\n");
+ return;
+ }
+ if (burst_stats[0] + burst_stats[1] == total_burst) {
+ printf(" + %d%% of %d pkts]\n",
+ 100 - burst_percent[0], pktnb_stats[1]);
+ return;
+ }
+ burst_percent[1] = (burst_stats[1] * 100) / total_burst;
+ burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]);
+ if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) {
+ printf(" + %d%% of others]\n", 100 - burst_percent[0]);
+ return;
+ }
+ printf(" + %d%% of %d pkts + %d%% of others]\n",
+ burst_percent[1], (int) pktnb_stats[1], burst_percent[2]);
+}
+#endif /* RTE_TEST_PMD_RECORD_BURST_STATS */
+
+static void
+fwd_stream_stats_display(streamid_t stream_id)
+{
+ struct fwd_stream *fs;
+ static const char *fwd_top_stats_border = "-------";
+
+ fs = fwd_streams[stream_id];
+ if ((fs->rx_packets == 0) && (fs->tx_packets == 0) &&
+ (fs->fwd_dropped == 0))
+ return;
+ printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> "
+ "TX Port=%2d/Queue=%2d %s\n",
+ fwd_top_stats_border, fs->rx_port, fs->rx_queue,
+ fs->tx_port, fs->tx_queue, fwd_top_stats_border);
+ printf(" RX-packets: %-14"PRIu64" TX-packets: %-14"PRIu64
+ " TX-dropped: %-14"PRIu64,
+ fs->rx_packets, fs->tx_packets, fs->fwd_dropped);
+
+ /* if checksum mode */
+ if (cur_fwd_eng == &csum_fwd_engine) {
+ printf(" RX- bad IP checksum: %-14"PRIu64
+ " Rx- bad L4 checksum: %-14"PRIu64
+ " Rx- bad outer L4 checksum: %-14"PRIu64"\n",
+ fs->rx_bad_ip_csum, fs->rx_bad_l4_csum,
+ fs->rx_bad_outer_l4_csum);
+ } else {
+ printf("\n");
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ pkt_burst_stats_display("RX", &fs->rx_burst_stats);
+ pkt_burst_stats_display("TX", &fs->tx_burst_stats);
+#endif
+}
+
+void
+fwd_stats_display(void)
+{
+ static const char *fwd_stats_border = "----------------------";
+ static const char *acc_stats_border = "+++++++++++++++";
+ struct {
+ struct fwd_stream *rx_stream;
+ struct fwd_stream *tx_stream;
+ uint64_t tx_dropped;
+ uint64_t rx_bad_ip_csum;
+ uint64_t rx_bad_l4_csum;
+ uint64_t rx_bad_outer_l4_csum;
+ } ports_stats[RTE_MAX_ETHPORTS];
+ uint64_t total_rx_dropped = 0;
+ uint64_t total_tx_dropped = 0;
+ uint64_t total_rx_nombuf = 0;
+ struct rte_eth_stats stats;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t fwd_cycles = 0;
+#endif
+ uint64_t total_recv = 0;
+ uint64_t total_xmit = 0;
+ struct rte_port *port;
+ streamid_t sm_id;
+ portid_t pt_id;
+ int i;
+
+ memset(ports_stats, 0, sizeof(ports_stats));
+
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ struct fwd_stream *fs = fwd_streams[sm_id];
+
+ if (cur_fwd_config.nb_fwd_streams >
+ cur_fwd_config.nb_fwd_ports) {
+ fwd_stream_stats_display(sm_id);
+ } else {
+ ports_stats[fs->tx_port].tx_stream = fs;
+ ports_stats[fs->rx_port].rx_stream = fs;
+ }
+
+ ports_stats[fs->tx_port].tx_dropped += fs->fwd_dropped;
+
+ ports_stats[fs->rx_port].rx_bad_ip_csum += fs->rx_bad_ip_csum;
+ ports_stats[fs->rx_port].rx_bad_l4_csum += fs->rx_bad_l4_csum;
+ ports_stats[fs->rx_port].rx_bad_outer_l4_csum +=
+ fs->rx_bad_outer_l4_csum;
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ fwd_cycles += fs->core_cycles;
+#endif
+ }
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ uint8_t j;
+
+ pt_id = fwd_ports_ids[i];
+ port = &ports[pt_id];
+
+ rte_eth_stats_get(pt_id, &stats);
+ stats.ipackets -= port->stats.ipackets;
+ stats.opackets -= port->stats.opackets;
+ stats.ibytes -= port->stats.ibytes;
+ stats.obytes -= port->stats.obytes;
+ stats.imissed -= port->stats.imissed;
+ stats.oerrors -= port->stats.oerrors;
+ stats.rx_nombuf -= port->stats.rx_nombuf;
+
+ total_recv += stats.ipackets;
+ total_xmit += stats.opackets;
+ total_rx_dropped += stats.imissed;
+ total_tx_dropped += ports_stats[pt_id].tx_dropped;
+ total_tx_dropped += stats.oerrors;
+ total_rx_nombuf += stats.rx_nombuf;
+
+ printf("\n %s Forward statistics for port %-2d %s\n",
+ fwd_stats_border, pt_id, fwd_stats_border);
+
+ if (!port->rx_queue_stats_mapping_enabled &&
+ !port->tx_queue_stats_mapping_enabled) {
+ printf(" RX-packets: %-14"PRIu64
+ " RX-dropped: %-14"PRIu64
+ "RX-total: %-"PRIu64"\n",
+ stats.ipackets, stats.imissed,
+ stats.ipackets + stats.imissed);
+
+ if (cur_fwd_eng == &csum_fwd_engine)
+ printf(" Bad-ipcsum: %-14"PRIu64
+ " Bad-l4csum: %-14"PRIu64
+ "Bad-outer-l4csum: %-14"PRIu64"\n",
+ ports_stats[pt_id].rx_bad_ip_csum,
+ ports_stats[pt_id].rx_bad_l4_csum,
+ ports_stats[pt_id].rx_bad_outer_l4_csum);
+ if (stats.ierrors + stats.rx_nombuf > 0) {
+ printf(" RX-error: %-"PRIu64"\n",
+ stats.ierrors);
+ printf(" RX-nombufs: %-14"PRIu64"\n",
+ stats.rx_nombuf);
+ }
+
+ printf(" TX-packets: %-14"PRIu64
+ " TX-dropped: %-14"PRIu64
+ "TX-total: %-"PRIu64"\n",
+ stats.opackets, ports_stats[pt_id].tx_dropped,
+ stats.opackets + ports_stats[pt_id].tx_dropped);
+ } else {
+ printf(" RX-packets: %14"PRIu64
+ " RX-dropped:%14"PRIu64
+ " RX-total:%14"PRIu64"\n",
+ stats.ipackets, stats.imissed,
+ stats.ipackets + stats.imissed);
+
+ if (cur_fwd_eng == &csum_fwd_engine)
+ printf(" Bad-ipcsum:%14"PRIu64
+ " Bad-l4csum:%14"PRIu64
+ " Bad-outer-l4csum: %-14"PRIu64"\n",
+ ports_stats[pt_id].rx_bad_ip_csum,
+ ports_stats[pt_id].rx_bad_l4_csum,
+ ports_stats[pt_id].rx_bad_outer_l4_csum);
+ if ((stats.ierrors + stats.rx_nombuf) > 0) {
+ printf(" RX-error:%"PRIu64"\n", stats.ierrors);
+ printf(" RX-nombufs: %14"PRIu64"\n",
+ stats.rx_nombuf);
+ }
+
+ printf(" TX-packets: %14"PRIu64
+ " TX-dropped:%14"PRIu64
+ " TX-total:%14"PRIu64"\n",
+ stats.opackets, ports_stats[pt_id].tx_dropped,
+ stats.opackets + ports_stats[pt_id].tx_dropped);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ if (ports_stats[pt_id].rx_stream)
+ pkt_burst_stats_display("RX",
+ &ports_stats[pt_id].rx_stream->rx_burst_stats);
+ if (ports_stats[pt_id].tx_stream)
+ pkt_burst_stats_display("TX",
+ &ports_stats[pt_id].tx_stream->tx_burst_stats);
+#endif
+
+ if (port->rx_queue_stats_mapping_enabled) {
+ printf("\n");
+ for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS; j++) {
+ printf(" Stats reg %2d RX-packets:%14"PRIu64
+ " RX-errors:%14"PRIu64
+ " RX-bytes:%14"PRIu64"\n",
+ j, stats.q_ipackets[j],
+ stats.q_errors[j], stats.q_ibytes[j]);
+ }
+ printf("\n");
+ }
+ if (port->tx_queue_stats_mapping_enabled) {
+ for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS; j++) {
+ printf(" Stats reg %2d TX-packets:%14"PRIu64
+ " TX-bytes:%14"
+ PRIu64"\n",
+ j, stats.q_opackets[j],
+ stats.q_obytes[j]);
+ }
+ }
+
+ printf(" %s--------------------------------%s\n",
+ fwd_stats_border, fwd_stats_border);
+ }
+
+ printf("\n %s Accumulated forward statistics for all ports"
+ "%s\n",
+ acc_stats_border, acc_stats_border);
+ printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: "
+ "%-"PRIu64"\n"
+ " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: "
+ "%-"PRIu64"\n",
+ total_recv, total_rx_dropped, total_recv + total_rx_dropped,
+ total_xmit, total_tx_dropped, total_xmit + total_tx_dropped);
+ if (total_rx_nombuf > 0)
+ printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf);
+ printf(" %s++++++++++++++++++++++++++++++++++++++++++++++"
+ "%s\n",
+ acc_stats_border, acc_stats_border);
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+#define CYC_PER_MHZ 1E6
+ if (total_recv > 0)
+ printf("\n CPU cycles/packet=%.2F (total cycles="
+ "%"PRIu64" / total RX packets=%"PRIu64") at %"PRIu64
+ " MHz Clock\n",
+ (double) fwd_cycles / total_recv,
+ fwd_cycles, total_recv,
+ (uint64_t)(rte_get_tsc_hz() / CYC_PER_MHZ));
+#endif
+}
+
+void
+fwd_stats_reset(void)
+{
+ streamid_t sm_id;
+ portid_t pt_id;
+ int i;
+
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ rte_eth_stats_get(pt_id, &ports[pt_id].stats);
+ }
+ for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
+ struct fwd_stream *fs = fwd_streams[sm_id];
+
+ fs->rx_packets = 0;
+ fs->tx_packets = 0;
+ fs->fwd_dropped = 0;
+ fs->rx_bad_ip_csum = 0;
+ fs->rx_bad_l4_csum = 0;
+ fs->rx_bad_outer_l4_csum = 0;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ memset(&fs->rx_burst_stats, 0, sizeof(fs->rx_burst_stats));
+ memset(&fs->tx_burst_stats, 0, sizeof(fs->tx_burst_stats));
+#endif
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ fs->core_cycles = 0;
+#endif
+ }
+}
+
+static void
+flush_fwd_rx_queues(void)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ portid_t rxp;
+ portid_t port_id;
+ queueid_t rxq;
+ uint16_t nb_rx;
+ uint16_t i;
+ uint8_t j;
+ uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
+ uint64_t timer_period;
+
+ /* convert to number of cycles */
+ timer_period = rte_get_timer_hz(); /* 1 second timeout */
+
+ for (j = 0; j < 2; j++) {
+ for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) {
+ for (rxq = 0; rxq < nb_rxq; rxq++) {
+ port_id = fwd_ports_ids[rxp];
+ /**
+ * testpmd can stuck in the below do while loop
+ * if rte_eth_rx_burst() always returns nonzero
+ * packets. So timer is added to exit this loop
+ * after 1sec timer expiry.
+ */
+ prev_tsc = rte_rdtsc();
+ do {
+ nb_rx = rte_eth_rx_burst(port_id, rxq,
+ pkts_burst, MAX_PKT_BURST);
+ for (i = 0; i < nb_rx; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+ cur_tsc = rte_rdtsc();
+ diff_tsc = cur_tsc - prev_tsc;
+ timer_tsc += diff_tsc;
+ } while ((nb_rx > 0) &&
+ (timer_tsc < timer_period));
+ timer_tsc = 0;
+ }
+ }
+ rte_delay_ms(10); /* wait 10 milli-seconds before retrying */
+ }
+}
+
+static void
+run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
+{
+ struct fwd_stream **fsm;
+ streamid_t nb_fs;
+ streamid_t sm_id;
+#ifdef RTE_LIBRTE_BITRATE
+ uint64_t tics_per_1sec;
+ uint64_t tics_datum;
+ uint64_t tics_current;
+ uint16_t i, cnt_ports;
+
+ cnt_ports = nb_ports;
+ tics_datum = rte_rdtsc();
+ tics_per_1sec = rte_get_timer_hz();
+#endif
+ fsm = &fwd_streams[fc->stream_idx];
+ nb_fs = fc->stream_nb;
+ do {
+ for (sm_id = 0; sm_id < nb_fs; sm_id++)
+ (*pkt_fwd)(fsm[sm_id]);
+#ifdef RTE_LIBRTE_BITRATE
+ if (bitrate_enabled != 0 &&
+ bitrate_lcore_id == rte_lcore_id()) {
+ tics_current = rte_rdtsc();
+ if (tics_current - tics_datum >= tics_per_1sec) {
+ /* Periodic bitrate calculation */
+ for (i = 0; i < cnt_ports; i++)
+ rte_stats_bitrate_calc(bitrate_data,
+ ports_ids[i]);
+ tics_datum = tics_current;
+ }
+ }
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (latencystats_enabled != 0 &&
+ latencystats_lcore_id == rte_lcore_id())
+ rte_latencystats_update();
+#endif
+
+ } while (! fc->stopped);
+}
+
+static int
+start_pkt_forward_on_core(void *fwd_arg)
+{
+ run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg,
+ cur_fwd_config.fwd_eng->packet_fwd);
+ return 0;
+}
+
+/*
+ * Run the TXONLY packet forwarding engine to send a single burst of packets.
+ * Used to start communication flows in network loopback test configurations.
+ */
+static int
+run_one_txonly_burst_on_core(void *fwd_arg)
+{
+ struct fwd_lcore *fwd_lc;
+ struct fwd_lcore tmp_lcore;
+
+ fwd_lc = (struct fwd_lcore *) fwd_arg;
+ tmp_lcore = *fwd_lc;
+ tmp_lcore.stopped = 1;
+ run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd);
+ return 0;
+}
+
+/*
+ * Launch packet forwarding:
+ * - Setup per-port forwarding context.
+ * - launch logical cores with their forwarding configuration.
+ */
+static void
+launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore)
+{
+ port_fwd_begin_t port_fwd_begin;
+ unsigned int i;
+ unsigned int lc_id;
+ int diag;
+
+ port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin;
+ if (port_fwd_begin != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_begin)(fwd_ports_ids[i]);
+ }
+ for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) {
+ lc_id = fwd_lcores_cpuids[i];
+ if ((interactive == 0) || (lc_id != rte_lcore_id())) {
+ fwd_lcores[i]->stopped = 0;
+ diag = rte_eal_remote_launch(pkt_fwd_on_lcore,
+ fwd_lcores[i], lc_id);
+ if (diag != 0)
+ printf("launch lcore %u failed - diag=%d\n",
+ lc_id, diag);
+ }
+ }
+}
+
+/*
+ * Launch packet forwarding configuration.
+ */
+void
+start_packet_forwarding(int with_tx_first)
+{
+ port_fwd_begin_t port_fwd_begin;
+ port_fwd_end_t port_fwd_end;
+ struct rte_port *port;
+ unsigned int i;
+ portid_t pt_id;
+
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") == 0 && !nb_rxq)
+ rte_exit(EXIT_FAILURE, "rxq are 0, cannot use rxonly fwd mode\n");
+
+ if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 && !nb_txq)
+ rte_exit(EXIT_FAILURE, "txq are 0, cannot use txonly fwd mode\n");
+
+ if ((strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") != 0 &&
+ strcmp(cur_fwd_eng->fwd_mode_name, "txonly") != 0) &&
+ (!nb_rxq || !nb_txq))
+ rte_exit(EXIT_FAILURE,
+ "Either rxq or txq are 0, cannot use %s fwd mode\n",
+ cur_fwd_eng->fwd_mode_name);
+
+ if (all_ports_started() == 0) {
+ printf("Not all ports were started\n");
+ return;
+ }
+ if (test_done == 0) {
+ printf("Packet forwarding already started\n");
+ return;
+ }
+
+
+ if(dcb_test) {
+ for (i = 0; i < nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ port = &ports[pt_id];
+ if (!port->dcb_flag) {
+ printf("In DCB mode, all forwarding ports must "
+ "be configured in this mode.\n");
+ return;
+ }
+ }
+ if (nb_fwd_lcores == 1) {
+ printf("In DCB mode,the nb forwarding cores "
+ "should be larger than 1.\n");
+ return;
+ }
+ }
+ test_done = 0;
+
+ fwd_config_setup();
+
+ if(!no_flush_rx)
+ flush_fwd_rx_queues();
+
+ pkt_fwd_config_display(&cur_fwd_config);
+ rxtx_config_display();
+
+ fwd_stats_reset();
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ port = &ports[pt_id];
+ map_port_queue_stats_mapping_registers(pt_id, port);
+ }
+ if (with_tx_first) {
+ port_fwd_begin = tx_only_engine.port_fwd_begin;
+ if (port_fwd_begin != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_begin)(fwd_ports_ids[i]);
+ }
+ while (with_tx_first--) {
+ launch_packet_forwarding(
+ run_one_txonly_burst_on_core);
+ rte_eal_mp_wait_lcore();
+ }
+ port_fwd_end = tx_only_engine.port_fwd_end;
+ if (port_fwd_end != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ (*port_fwd_end)(fwd_ports_ids[i]);
+ }
+ }
+ launch_packet_forwarding(start_pkt_forward_on_core);
+}
+
+void
+stop_packet_forwarding(void)
+{
+ port_fwd_end_t port_fwd_end;
+ lcoreid_t lc_id;
+ portid_t pt_id;
+ int i;
+
+ if (test_done) {
+ printf("Packet forwarding not started\n");
+ return;
+ }
+ printf("Telling cores to stop...");
+ for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++)
+ fwd_lcores[lc_id]->stopped = 1;
+ printf("\nWaiting for lcores to finish...\n");
+ rte_eal_mp_wait_lcore();
+ port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end;
+ if (port_fwd_end != NULL) {
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
+ pt_id = fwd_ports_ids[i];
+ (*port_fwd_end)(pt_id);
+ }
+ }
+
+ fwd_stats_display();
+
+ printf("\nDone.\n");
+ test_done = 1;
+}
+
+void
+dev_set_link_up(portid_t pid)
+{
+ if (rte_eth_dev_set_link_up(pid) < 0)
+ printf("\nSet link up fail.\n");
+}
+
+void
+dev_set_link_down(portid_t pid)
+{
+ if (rte_eth_dev_set_link_down(pid) < 0)
+ printf("\nSet link down fail.\n");
+}
+
+static int
+all_ports_started(void)
+{
+ portid_t pi;
+ struct rte_port *port;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ port = &ports[pi];
+ /* Check if there is a port which is not started */
+ if ((port->port_status != RTE_PORT_STARTED) &&
+ (port->slave_flag == 0))
+ return 0;
+ }
+
+ /* No port is not started */
+ return 1;
+}
+
+int
+port_is_stopped(portid_t port_id)
+{
+ struct rte_port *port = &ports[port_id];
+
+ if ((port->port_status != RTE_PORT_STOPPED) &&
+ (port->slave_flag == 0))
+ return 0;
+ return 1;
+}
+
+int
+all_ports_stopped(void)
+{
+ portid_t pi;
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (!port_is_stopped(pi))
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+port_is_started(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 0;
+
+ if (ports[port_id].port_status != RTE_PORT_STARTED)
+ return 0;
+
+ return 1;
+}
+
+/* Configure the Rx and Tx hairpin queues for the selected port. */
+static int
+setup_hairpin_queues(portid_t pi)
+{
+ queueid_t qi;
+ struct rte_eth_hairpin_conf hairpin_conf = {
+ .peer_count = 1,
+ };
+ int i;
+ int diag;
+ struct rte_port *port = &ports[pi];
+
+ for (qi = nb_txq, i = 0; qi < nb_hairpinq + nb_txq; qi++) {
+ hairpin_conf.peers[0].port = pi;
+ hairpin_conf.peers[0].queue = i + nb_rxq;
+ diag = rte_eth_tx_hairpin_queue_setup
+ (pi, qi, nb_txd, &hairpin_conf);
+ i++;
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d hairpin "
+ "queues\n", pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ for (qi = nb_rxq, i = 0; qi < nb_hairpinq + nb_rxq; qi++) {
+ hairpin_conf.peers[0].port = pi;
+ hairpin_conf.peers[0].queue = i + nb_txq;
+ diag = rte_eth_rx_hairpin_queue_setup
+ (pi, qi, nb_rxd, &hairpin_conf);
+ i++;
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d hairpin "
+ "queues\n", pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ return 0;
+}
+
+int
+start_port(portid_t pid)
+{
+ int diag, need_check_link_status = -1;
+ portid_t pi;
+ queueid_t qi;
+ struct rte_port *port;
+ struct rte_ether_addr mac_addr;
+ struct rte_eth_hairpin_cap cap;
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return 0;
+
+ if(dcb_config)
+ dcb_test = 1;
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ need_check_link_status = 0;
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED,
+ RTE_PORT_HANDLING) == 0) {
+ printf("Port %d is now not stopped\n", pi);
+ continue;
+ }
+
+ if (port->need_reconfig > 0) {
+ port->need_reconfig = 0;
+
+ if (flow_isolate_all) {
+ int ret = port_flow_isolate(pi, 1);
+ if (ret) {
+ printf("Failed to apply isolated"
+ " mode on port %d\n", pi);
+ return -1;
+ }
+ }
+ configure_rxtx_dump_callbacks(0);
+ printf("Configuring Port %d (socket %u)\n", pi,
+ port->socket_id);
+ if (nb_hairpinq > 0 &&
+ rte_eth_dev_hairpin_capability_get(pi, &cap)) {
+ printf("Port %d doesn't support hairpin "
+ "queues\n", pi);
+ return -1;
+ }
+ /* configure port */
+ diag = rte_eth_dev_configure(pi, nb_rxq + nb_hairpinq,
+ nb_txq + nb_hairpinq,
+ &(port->dev_conf));
+ if (diag != 0) {
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d\n", pi);
+ /* try to reconfigure port next time */
+ port->need_reconfig = 1;
+ return -1;
+ }
+ }
+ if (port->need_reconfig_queues > 0) {
+ port->need_reconfig_queues = 0;
+ /* setup tx queues */
+ for (qi = 0; qi < nb_txq; qi++) {
+ if ((numa_support) &&
+ (txring_numa[pi] != NUMA_NO_CONFIG))
+ diag = rte_eth_tx_queue_setup(pi, qi,
+ port->nb_tx_desc[qi],
+ txring_numa[pi],
+ &(port->tx_conf[qi]));
+ else
+ diag = rte_eth_tx_queue_setup(pi, qi,
+ port->nb_tx_desc[qi],
+ port->socket_id,
+ &(port->tx_conf[qi]));
+
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup tx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d tx queues\n",
+ pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ for (qi = 0; qi < nb_rxq; qi++) {
+ /* setup rx queues */
+ if ((numa_support) &&
+ (rxring_numa[pi] != NUMA_NO_CONFIG)) {
+ struct rte_mempool * mp =
+ mbuf_pool_find(rxring_numa[pi]);
+ if (mp == NULL) {
+ printf("Failed to setup RX queue:"
+ "No mempool allocation"
+ " on the socket %d\n",
+ rxring_numa[pi]);
+ return -1;
+ }
+
+ diag = rte_eth_rx_queue_setup(pi, qi,
+ port->nb_rx_desc[qi],
+ rxring_numa[pi],
+ &(port->rx_conf[qi]),
+ mp);
+ } else {
+ struct rte_mempool *mp =
+ mbuf_pool_find(port->socket_id);
+ if (mp == NULL) {
+ printf("Failed to setup RX queue:"
+ "No mempool allocation"
+ " on the socket %d\n",
+ port->socket_id);
+ return -1;
+ }
+ diag = rte_eth_rx_queue_setup(pi, qi,
+ port->nb_rx_desc[qi],
+ port->socket_id,
+ &(port->rx_conf[qi]),
+ mp);
+ }
+ if (diag == 0)
+ continue;
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING,
+ RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back "
+ "to stopped\n", pi);
+ printf("Fail to configure port %d rx queues\n",
+ pi);
+ /* try to reconfigure queues next time */
+ port->need_reconfig_queues = 1;
+ return -1;
+ }
+ /* setup hairpin queues */
+ if (setup_hairpin_queues(pi) != 0)
+ return -1;
+ }
+ configure_rxtx_dump_callbacks(verbose_level);
+ if (clear_ptypes) {
+ diag = rte_eth_dev_set_ptypes(pi, RTE_PTYPE_UNKNOWN,
+ NULL, 0);
+ if (diag < 0)
+ printf(
+ "Port %d: Failed to disable Ptype parsing\n",
+ pi);
+ }
+
+ /* start port */
+ if (rte_eth_dev_start(pi) < 0) {
+ printf("Fail to start port %d\n", pi);
+
+ /* Fail to setup rx queue, return */
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set back to "
+ "stopped\n", pi);
+ continue;
+ }
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0)
+ printf("Port %d can not be set into started\n", pi);
+
+ if (eth_macaddr_get_print_err(pi, &mac_addr) == 0)
+ printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi,
+ mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
+ mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
+ mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]);
+
+ /* at least one port started, need checking link status */
+ need_check_link_status = 1;
+ }
+
+ if (need_check_link_status == 1 && !no_link_check)
+ check_all_ports_link_status(RTE_PORT_ALL);
+ else if (need_check_link_status == 0)
+ printf("Please stop the ports first\n");
+
+ printf("Done\n");
+ return 0;
+}
+
+void
+stop_port(portid_t pid)
+{
+ portid_t pi;
+ struct rte_port *port;
+ int need_check_link_status = 0;
+
+ if (dcb_test) {
+ dcb_test = 0;
+ dcb_config = 0;
+ }
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return;
+
+ printf("Stopping ports...\n");
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ if (port_is_forwarding(pi) != 0 && test_done == 0) {
+ printf("Please remove port %d from forwarding configuration.\n", pi);
+ continue;
+ }
+
+ if (port_is_bonding_slave(pi)) {
+ printf("Please remove port %d from bonded device.\n", pi);
+ continue;
+ }
+
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED,
+ RTE_PORT_HANDLING) == 0)
+ continue;
+
+ rte_eth_dev_stop(pi);
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
+ printf("Port %d can not be set into stopped\n", pi);
+ need_check_link_status = 1;
+ }
+ if (need_check_link_status && !no_link_check)
+ check_all_ports_link_status(RTE_PORT_ALL);
+
+ printf("Done\n");
+}
+
+static void
+remove_invalid_ports_in(portid_t *array, portid_t *total)
+{
+ portid_t i;
+ portid_t new_total = 0;
+
+ for (i = 0; i < *total; i++)
+ if (!port_id_is_invalid(array[i], DISABLED_WARN)) {
+ array[new_total] = array[i];
+ new_total++;
+ }
+ *total = new_total;
+}
+
+static void
+remove_invalid_ports(void)
+{
+ remove_invalid_ports_in(ports_ids, &nb_ports);
+ remove_invalid_ports_in(fwd_ports_ids, &nb_fwd_ports);
+ nb_cfg_ports = nb_fwd_ports;
+}
+
+void
+close_port(portid_t pid)
+{
+ portid_t pi;
+ struct rte_port *port;
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return;
+
+ printf("Closing ports...\n");
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ if (port_is_forwarding(pi) != 0 && test_done == 0) {
+ printf("Please remove port %d from forwarding configuration.\n", pi);
+ continue;
+ }
+
+ if (port_is_bonding_slave(pi)) {
+ printf("Please remove port %d from bonded device.\n", pi);
+ continue;
+ }
+
+ port = &ports[pi];
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) {
+ printf("Port %d is already closed\n", pi);
+ continue;
+ }
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) {
+ printf("Port %d is now not stopped\n", pi);
+ continue;
+ }
+
+ if (port->flow_list)
+ port_flow_flush(pi);
+ rte_eth_dev_close(pi);
+
+ remove_invalid_ports();
+
+ if (rte_atomic16_cmpset(&(port->port_status),
+ RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0)
+ printf("Port %d cannot be set to closed\n", pi);
+ }
+
+ printf("Done\n");
+}
+
+void
+reset_port(portid_t pid)
+{
+ int diag;
+ portid_t pi;
+ struct rte_port *port;
+
+ if (port_id_is_invalid(pid, ENABLED_WARN))
+ return;
+
+ if ((pid == (portid_t)RTE_PORT_ALL && !all_ports_stopped()) ||
+ (pid != (portid_t)RTE_PORT_ALL && !port_is_stopped(pid))) {
+ printf("Can not reset port(s), please stop port(s) first.\n");
+ return;
+ }
+
+ printf("Resetting ports...\n");
+
+ RTE_ETH_FOREACH_DEV(pi) {
+ if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+ continue;
+
+ if (port_is_forwarding(pi) != 0 && test_done == 0) {
+ printf("Please remove port %d from forwarding "
+ "configuration.\n", pi);
+ continue;
+ }
+
+ if (port_is_bonding_slave(pi)) {
+ printf("Please remove port %d from bonded device.\n",
+ pi);
+ continue;
+ }
+
+ diag = rte_eth_dev_reset(pi);
+ if (diag == 0) {
+ port = &ports[pi];
+ port->need_reconfig = 1;
+ port->need_reconfig_queues = 1;
+ } else {
+ printf("Failed to reset port %d. diag=%d\n", pi, diag);
+ }
+ }
+
+ printf("Done\n");
+}
+
+void
+attach_port(char *identifier)
+{
+ portid_t pi;
+ struct rte_dev_iterator iterator;
+
+ printf("Attaching a new port...\n");
+
+ if (identifier == NULL) {
+ printf("Invalid parameters are specified\n");
+ return;
+ }
+
+ if (rte_dev_probe(identifier) < 0) {
+ TESTPMD_LOG(ERR, "Failed to attach port %s\n", identifier);
+ return;
+ }
+
+ /* first attach mode: event */
+ if (setup_on_probe_event) {
+ /* new ports are detected on RTE_ETH_EVENT_NEW event */
+ for (pi = 0; pi < RTE_MAX_ETHPORTS; pi++)
+ if (ports[pi].port_status == RTE_PORT_HANDLING &&
+ ports[pi].need_setup != 0)
+ setup_attached_port(pi);
+ return;
+ }
+
+ /* second attach mode: iterator */
+ RTE_ETH_FOREACH_MATCHING_DEV(pi, identifier, &iterator) {
+ /* setup ports matching the devargs used for probing */
+ if (port_is_forwarding(pi))
+ continue; /* port was already attached before */
+ setup_attached_port(pi);
+ }
+}
+
+static void
+setup_attached_port(portid_t pi)
+{
+ unsigned int socket_id;
+ int ret;
+
+ socket_id = (unsigned)rte_eth_dev_socket_id(pi);
+ /* if socket_id is invalid, set to the first available socket. */
+ if (check_socket_id(socket_id) < 0)
+ socket_id = socket_ids[0];
+ reconfig(pi, socket_id);
+ ret = rte_eth_promiscuous_enable(pi);
+ if (ret != 0)
+ printf("Error during enabling promiscuous mode for port %u: %s - ignore\n",
+ pi, rte_strerror(-ret));
+
+ ports_ids[nb_ports++] = pi;
+ fwd_ports_ids[nb_fwd_ports++] = pi;
+ nb_cfg_ports = nb_fwd_ports;
+ ports[pi].need_setup = 0;
+ ports[pi].port_status = RTE_PORT_STOPPED;
+
+ printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
+ printf("Done\n");
+}
+
+static void
+detach_device(struct rte_device *dev)
+{
+ portid_t sibling;
+
+ if (dev == NULL) {
+ printf("Device already removed\n");
+ return;
+ }
+
+ printf("Removing a device...\n");
+
+ if (rte_dev_remove(dev) < 0) {
+ TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
+ return;
+ }
+ RTE_ETH_FOREACH_DEV_OF(sibling, dev) {
+ /* reset mapping between old ports and removed device */
+ rte_eth_devices[sibling].device = NULL;
+ if (ports[sibling].port_status != RTE_PORT_CLOSED) {
+ /* sibling ports are forced to be closed */
+ ports[sibling].port_status = RTE_PORT_CLOSED;
+ printf("Port %u is closed\n", sibling);
+ }
+ }
+
+ remove_invalid_ports();
+
+ printf("Device is detached\n");
+ printf("Now total ports is %d\n", nb_ports);
+ printf("Done\n");
+ return;
+}
+
+void
+detach_port_device(portid_t port_id)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+
+ if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+ if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+ printf("Port not stopped\n");
+ return;
+ }
+ printf("Port was not closed\n");
+ if (ports[port_id].flow_list)
+ port_flow_flush(port_id);
+ }
+
+ detach_device(rte_eth_devices[port_id].device);
+}
+
+void
+detach_devargs(char *identifier)
+{
+ struct rte_dev_iterator iterator;
+ struct rte_devargs da;
+ portid_t port_id;
+
+ printf("Removing a device...\n");
+
+ memset(&da, 0, sizeof(da));
+ if (rte_devargs_parsef(&da, "%s", identifier)) {
+ printf("cannot parse identifier\n");
+ if (da.args)
+ free(da.args);
+ return;
+ }
+
+ RTE_ETH_FOREACH_MATCHING_DEV(port_id, identifier, &iterator) {
+ if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+ if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+ printf("Port %u not stopped\n", port_id);
+ rte_eth_iterator_cleanup(&iterator);
+ return;
+ }
+
+ /* sibling ports are forced to be closed */
+ if (ports[port_id].flow_list)
+ port_flow_flush(port_id);
+ ports[port_id].port_status = RTE_PORT_CLOSED;
+ printf("Port %u is now closed\n", port_id);
+ }
+ }
+
+ if (rte_eal_hotplug_remove(da.bus->name, da.name) != 0) {
+ TESTPMD_LOG(ERR, "Failed to detach device %s(%s)\n",
+ da.name, da.bus->name);
+ return;
+ }
+
+ remove_invalid_ports();
+
+ printf("Device %s is detached\n", identifier);
+ printf("Now total ports is %d\n", nb_ports);
+ printf("Done\n");
+}
+
+void
+pmd_test_exit(void)
+{
+ portid_t pt_id;
+ int ret;
+ int i;
+
+ if (test_done == 0)
+ stop_packet_forwarding();
+
+ for (i = 0 ; i < RTE_MAX_NUMA_NODES ; i++) {
+ if (mempools[i]) {
+ if (mp_alloc_type == MP_ALLOC_ANON)
+ rte_mempool_mem_iter(mempools[i], dma_unmap_cb,
+ NULL);
+ }
+ }
+ if (ports != NULL) {
+ no_link_check = 1;
+ RTE_ETH_FOREACH_DEV(pt_id) {
+ printf("\nStopping port %d...\n", pt_id);
+ fflush(stdout);
+ stop_port(pt_id);
+ }
+ RTE_ETH_FOREACH_DEV(pt_id) {
+ printf("\nShutting down port %d...\n", pt_id);
+ fflush(stdout);
+ close_port(pt_id);
+ }
+ }
+
+ if (hot_plug) {
+ ret = rte_dev_event_monitor_stop();
+ if (ret) {
+ RTE_LOG(ERR, EAL,
+ "fail to stop device event monitor.");
+ return;
+ }
+
+ ret = rte_dev_event_callback_unregister(NULL,
+ dev_event_callback, NULL);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL,
+ "fail to unregister device event callback.\n");
+ return;
+ }
+
+ ret = rte_dev_hotplug_handle_disable();
+ if (ret) {
+ RTE_LOG(ERR, EAL,
+ "fail to disable hotplug handling.\n");
+ return;
+ }
+ }
+ for (i = 0 ; i < RTE_MAX_NUMA_NODES ; i++) {
+ if (mempools[i])
+ rte_mempool_free(mempools[i]);
+ }
+
+ printf("\nBye...\n");
+}
+
+typedef void (*cmd_func_t)(void);
+struct pmd_test_command {
+ const char *cmd_name;
+ cmd_func_t cmd_func;
+};
+
+/* Check the link status of all ports in up to 9s, and print them finally */
+static void
+check_all_ports_link_status(uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
+ portid_t portid;
+ uint8_t count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+ int ret;
+
+ printf("Checking link statuses...\n");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ all_ports_up = 1;
+ RTE_ETH_FOREACH_DEV(portid) {
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ memset(&link, 0, sizeof(link));
+ ret = rte_eth_link_get_nowait(portid, &link);
+ if (ret < 0) {
+ all_ports_up = 0;
+ if (print_flag == 1)
+ printf("Port %u link get failed: %s\n",
+ portid, rte_strerror(-ret));
+ continue;
+ }
+ /* print link status if flag set */
+ if (print_flag == 1) {
+ if (link.link_status)
+ printf(
+ "Port%d Link Up. speed %u Mbps- %s\n",
+ portid, link.link_speed,
+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex"));
+ else
+ printf("Port %d Link Down\n", portid);
+ continue;
+ }
+ /* clear all_ports_up flag if any link down */
+ if (link.link_status == ETH_LINK_DOWN) {
+ all_ports_up = 0;
+ break;
+ }
+ }
+ /* after finally printing all link status, get out */
+ if (print_flag == 1)
+ break;
+
+ if (all_ports_up == 0) {
+ fflush(stdout);
+ rte_delay_ms(CHECK_INTERVAL);
+ }
+
+ /* set the print_flag if all ports up or timeout */
+ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
+ print_flag = 1;
+ }
+
+ if (lsc_interrupt)
+ break;
+ }
+}
+
+/*
+ * This callback is for remove a port for a device. It has limitation because
+ * it is not for multiple port removal for a device.
+ * TODO: the device detach invoke will plan to be removed from user side to
+ * eal. And convert all PMDs to free port resources on ether device closing.
+ */
+static void
+rmv_port_callback(void *arg)
+{
+ int need_to_start = 0;
+ int org_no_link_check = no_link_check;
+ portid_t port_id = (intptr_t)arg;
+ struct rte_device *dev;
+
+ RTE_ETH_VALID_PORTID_OR_RET(port_id);
+
+ if (!test_done && port_is_forwarding(port_id)) {
+ need_to_start = 1;
+ stop_packet_forwarding();
+ }
+ no_link_check = 1;
+ stop_port(port_id);
+ no_link_check = org_no_link_check;
+
+ /* Save rte_device pointer before closing ethdev port */
+ dev = rte_eth_devices[port_id].device;
+ close_port(port_id);
+ detach_device(dev); /* might be already removed or have more ports */
+
+ if (need_to_start)
+ start_packet_forwarding(0);
+}
+
+/* This function is used by the interrupt thread */
+static int
+eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
+ void *ret_param)
+{
+ RTE_SET_USED(param);
+ RTE_SET_USED(ret_param);
+
+ if (type >= RTE_ETH_EVENT_MAX) {
+ fprintf(stderr, "\nPort %" PRIu16 ": %s called upon invalid event %d\n",
+ port_id, __func__, type);
+ fflush(stderr);
+ } else if (event_print_mask & (UINT32_C(1) << type)) {
+ printf("\nPort %" PRIu16 ": %s event\n", port_id,
+ eth_event_desc[type]);
+ fflush(stdout);
+ }
+
+ switch (type) {
+ case RTE_ETH_EVENT_NEW:
+ ports[port_id].need_setup = 1;
+ ports[port_id].port_status = RTE_PORT_HANDLING;
+ break;
+ case RTE_ETH_EVENT_INTR_RMV:
+ if (port_id_is_invalid(port_id, DISABLED_WARN))
+ break;
+ if (rte_eal_alarm_set(100000,
+ rmv_port_callback, (void *)(intptr_t)port_id))
+ fprintf(stderr, "Could not set up deferred device removal\n");
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int
+register_eth_event_callback(void)
+{
+ int ret;
+ enum rte_eth_event_type event;
+
+ for (event = RTE_ETH_EVENT_UNKNOWN;
+ event < RTE_ETH_EVENT_MAX; event++) {
+ ret = rte_eth_dev_callback_register(RTE_ETH_ALL,
+ event,
+ eth_event_callback,
+ NULL);
+ if (ret != 0) {
+ TESTPMD_LOG(ERR, "Failed to register callback for "
+ "%s event\n", eth_event_desc[event]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* This function is used by the interrupt thread */
+static void
+dev_event_callback(const char *device_name, enum rte_dev_event_type type,
+ __rte_unused void *arg)
+{
+ uint16_t port_id;
+ int ret;
+
+ if (type >= RTE_DEV_EVENT_MAX) {
+ fprintf(stderr, "%s called upon invalid event %d\n",
+ __func__, type);
+ fflush(stderr);
+ }
+
+ switch (type) {
+ case RTE_DEV_EVENT_REMOVE:
+ RTE_LOG(DEBUG, EAL, "The device: %s has been removed!\n",
+ device_name);
+ ret = rte_eth_dev_get_port_by_name(device_name, &port_id);
+ if (ret) {
+ RTE_LOG(ERR, EAL, "can not get port by device %s!\n",
+ device_name);
+ return;
+ }
+ /*
+ * Because the user's callback is invoked in eal interrupt
+ * callback, the interrupt callback need to be finished before
+ * it can be unregistered when detaching device. So finish
+ * callback soon and use a deferred removal to detach device
+ * is need. It is a workaround, once the device detaching be
+ * moved into the eal in the future, the deferred removal could
+ * be deleted.
+ */
+ if (rte_eal_alarm_set(100000,
+ rmv_port_callback, (void *)(intptr_t)port_id))
+ RTE_LOG(ERR, EAL,
+ "Could not set up deferred device removal\n");
+ break;
+ case RTE_DEV_EVENT_ADD:
+ RTE_LOG(ERR, EAL, "The device: %s has been added!\n",
+ device_name);
+ /* TODO: After finish kernel driver binding,
+ * begin to attach port.
+ */
+ break;
+ default:
+ break;
+ }
+}
+
+static int
+set_tx_queue_stats_mapping_registers(portid_t port_id, struct rte_port *port)
+{
+ uint16_t i;
+ int diag;
+ uint8_t mapping_found = 0;
+
+ for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
+ if ((tx_queue_stats_mappings[i].port_id == port_id) &&
+ (tx_queue_stats_mappings[i].queue_id < nb_txq )) {
+ diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id,
+ tx_queue_stats_mappings[i].queue_id,
+ tx_queue_stats_mappings[i].stats_counter_id);
+ if (diag != 0)
+ return diag;
+ mapping_found = 1;
+ }
+ }
+ if (mapping_found)
+ port->tx_queue_stats_mapping_enabled = 1;
+ return 0;
+}
+
+static int
+set_rx_queue_stats_mapping_registers(portid_t port_id, struct rte_port *port)
+{
+ uint16_t i;
+ int diag;
+ uint8_t mapping_found = 0;
+
+ for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
+ if ((rx_queue_stats_mappings[i].port_id == port_id) &&
+ (rx_queue_stats_mappings[i].queue_id < nb_rxq )) {
+ diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id,
+ rx_queue_stats_mappings[i].queue_id,
+ rx_queue_stats_mappings[i].stats_counter_id);
+ if (diag != 0)
+ return diag;
+ mapping_found = 1;
+ }
+ }
+ if (mapping_found)
+ port->rx_queue_stats_mapping_enabled = 1;
+ return 0;
+}
+
+static void
+map_port_queue_stats_mapping_registers(portid_t pi, struct rte_port *port)
+{
+ int diag = 0;
+
+ diag = set_tx_queue_stats_mapping_registers(pi, port);
+ if (diag != 0) {
+ if (diag == -ENOTSUP) {
+ port->tx_queue_stats_mapping_enabled = 0;
+ printf("TX queue stats mapping not supported port id=%d\n", pi);
+ }
+ else
+ rte_exit(EXIT_FAILURE,
+ "set_tx_queue_stats_mapping_registers "
+ "failed for port id=%d diag=%d\n",
+ pi, diag);
+ }
+
+ diag = set_rx_queue_stats_mapping_registers(pi, port);
+ if (diag != 0) {
+ if (diag == -ENOTSUP) {
+ port->rx_queue_stats_mapping_enabled = 0;
+ printf("RX queue stats mapping not supported port id=%d\n", pi);
+ }
+ else
+ rte_exit(EXIT_FAILURE,
+ "set_rx_queue_stats_mapping_registers "
+ "failed for port id=%d diag=%d\n",
+ pi, diag);
+ }
+}
+
+static void
+rxtx_port_config(struct rte_port *port)
+{
+ uint16_t qid;
+ uint64_t offloads;
+
+ for (qid = 0; qid < nb_rxq; qid++) {
+ offloads = port->rx_conf[qid].offloads;
+ port->rx_conf[qid] = port->dev_info.default_rxconf;
+ if (offloads != 0)
+ port->rx_conf[qid].offloads = offloads;
+
+ /* Check if any Rx parameters have been passed */
+ if (rx_pthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf[qid].rx_thresh.pthresh = rx_pthresh;
+
+ if (rx_hthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf[qid].rx_thresh.hthresh = rx_hthresh;
+
+ if (rx_wthresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf[qid].rx_thresh.wthresh = rx_wthresh;
+
+ if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
+ port->rx_conf[qid].rx_free_thresh = rx_free_thresh;
+
+ if (rx_drop_en != RTE_PMD_PARAM_UNSET)
+ port->rx_conf[qid].rx_drop_en = rx_drop_en;
+
+ port->nb_rx_desc[qid] = nb_rxd;
+ }
+
+ for (qid = 0; qid < nb_txq; qid++) {
+ offloads = port->tx_conf[qid].offloads;
+ port->tx_conf[qid] = port->dev_info.default_txconf;
+ if (offloads != 0)
+ port->tx_conf[qid].offloads = offloads;
+
+ /* Check if any Tx parameters have been passed */
+ if (tx_pthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf[qid].tx_thresh.pthresh = tx_pthresh;
+
+ if (tx_hthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf[qid].tx_thresh.hthresh = tx_hthresh;
+
+ if (tx_wthresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf[qid].tx_thresh.wthresh = tx_wthresh;
+
+ if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf[qid].tx_rs_thresh = tx_rs_thresh;
+
+ if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
+ port->tx_conf[qid].tx_free_thresh = tx_free_thresh;
+
+ port->nb_tx_desc[qid] = nb_txd;
+ }
+}
+
+void
+init_port_config(void)
+{
+ portid_t pid;
+ struct rte_port *port;
+ int ret;
+
+ RTE_ETH_FOREACH_DEV(pid) {
+ port = &ports[pid];
+ port->dev_conf.fdir_conf = fdir_conf;
+
+ ret = eth_dev_info_get_print_err(pid, &port->dev_info);
+ if (ret != 0)
+ return;
+
+ if (nb_rxq > 1) {
+ port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+ port->dev_conf.rx_adv_conf.rss_conf.rss_hf =
+ rss_hf & port->dev_info.flow_type_rss_offloads;
+ } else {
+ port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
+ port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
+ }
+
+ if (port->dcb_flag == 0) {
+ if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0)
+ port->dev_conf.rxmode.mq_mode =
+ (enum rte_eth_rx_mq_mode)
+ (rx_mq_mode & ETH_MQ_RX_RSS);
+ else
+ port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+ }
+
+ rxtx_port_config(port);
+
+ ret = eth_macaddr_get_print_err(pid, &port->eth_addr);
+ if (ret != 0)
+ return;
+
+ map_port_queue_stats_mapping_registers(pid, port);
+#if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS
+ rte_pmd_ixgbe_bypass_init(pid);
+#endif
+
+ if (lsc_interrupt &&
+ (rte_eth_devices[pid].data->dev_flags &
+ RTE_ETH_DEV_INTR_LSC))
+ port->dev_conf.intr_conf.lsc = 1;
+ if (rmv_interrupt &&
+ (rte_eth_devices[pid].data->dev_flags &
+ RTE_ETH_DEV_INTR_RMV))
+ port->dev_conf.intr_conf.rmv = 1;
+ }
+}
+
+void set_port_slave_flag(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ port->slave_flag = 1;
+}
+
+void clear_port_slave_flag(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ port->slave_flag = 0;
+}
+
+uint8_t port_is_bonding_slave(portid_t slave_pid)
+{
+ struct rte_port *port;
+
+ port = &ports[slave_pid];
+ if ((rte_eth_devices[slave_pid].data->dev_flags &
+ RTE_ETH_DEV_BONDED_SLAVE) || (port->slave_flag == 1))
+ return 1;
+ return 0;
+}
+
+const uint16_t vlan_tags[] = {
+ 0, 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
+};
+
+static int
+get_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf,
+ enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en)
+{
+ uint8_t i;
+ int32_t rc;
+ struct rte_eth_rss_conf rss_conf;
+
+ /*
+ * Builds up the correct configuration for dcb+vt based on the vlan tags array
+ * given above, and the number of traffic classes available for use.
+ */
+ if (dcb_mode == DCB_VT_ENABLED) {
+ struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf =
+ &eth_conf->rx_adv_conf.vmdq_dcb_conf;
+ struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf =
+ &eth_conf->tx_adv_conf.vmdq_dcb_tx_conf;
+
+ /* VMDQ+DCB RX and TX configurations */
+ vmdq_rx_conf->enable_default_pool = 0;
+ vmdq_rx_conf->default_pool = 0;
+ vmdq_rx_conf->nb_queue_pools =
+ (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
+ vmdq_tx_conf->nb_queue_pools =
+ (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS);
+
+ vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools;
+ for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) {
+ vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i];
+ vmdq_rx_conf->pool_map[i].pools =
+ 1 << (i % vmdq_rx_conf->nb_queue_pools);
+ }
+ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
+ vmdq_rx_conf->dcb_tc[i] = i % num_tcs;
+ vmdq_tx_conf->dcb_tc[i] = i % num_tcs;
+ }
+
+ /* set DCB mode of RX and TX of multiple queues */
+ eth_conf->rxmode.mq_mode =
+ (enum rte_eth_rx_mq_mode)
+ (rx_mq_mode & ETH_MQ_RX_VMDQ_DCB);
+ eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB;
+ } else {
+ struct rte_eth_dcb_rx_conf *rx_conf =
+ &eth_conf->rx_adv_conf.dcb_rx_conf;
+ struct rte_eth_dcb_tx_conf *tx_conf =
+ &eth_conf->tx_adv_conf.dcb_tx_conf;
+
+ memset(&rss_conf, 0, sizeof(struct rte_eth_rss_conf));
+
+ rc = rte_eth_dev_rss_hash_conf_get(pid, &rss_conf);
+ if (rc != 0)
+ return rc;
+
+ rx_conf->nb_tcs = num_tcs;
+ tx_conf->nb_tcs = num_tcs;
+
+ for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) {
+ rx_conf->dcb_tc[i] = i % num_tcs;
+ tx_conf->dcb_tc[i] = i % num_tcs;
+ }
+
+ eth_conf->rxmode.mq_mode =
+ (enum rte_eth_rx_mq_mode)
+ (rx_mq_mode & ETH_MQ_RX_DCB_RSS);
+ eth_conf->rx_adv_conf.rss_conf = rss_conf;
+ eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
+ }
+
+ if (pfc_en)
+ eth_conf->dcb_capability_en =
+ ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT;
+ else
+ eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT;
+
+ return 0;
+}
+
+int
+init_port_dcb_config(portid_t pid,
+ enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en)
+{
+ struct rte_eth_conf port_conf;
+ struct rte_port *rte_port;
+ int retval;
+ uint16_t i;
+
+ rte_port = &ports[pid];
+
+ memset(&port_conf, 0, sizeof(struct rte_eth_conf));
+ /* Enter DCB configuration status */
+ dcb_config = 1;
+
+ port_conf.rxmode = rte_port->dev_conf.rxmode;
+ port_conf.txmode = rte_port->dev_conf.txmode;
+
+ /*set configuration of DCB in vt mode and DCB in non-vt mode*/
+ retval = get_eth_dcb_conf(pid, &port_conf, dcb_mode, num_tcs, pfc_en);
+ if (retval < 0)
+ return retval;
+ port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+
+ /* re-configure the device . */
+ retval = rte_eth_dev_configure(pid, nb_rxq, nb_rxq, &port_conf);
+ if (retval < 0)
+ return retval;
+
+ retval = eth_dev_info_get_print_err(pid, &rte_port->dev_info);
+ if (retval != 0)
+ return retval;
+
+ /* If dev_info.vmdq_pool_base is greater than 0,
+ * the queue id of vmdq pools is started after pf queues.
+ */
+ if (dcb_mode == DCB_VT_ENABLED &&
+ rte_port->dev_info.vmdq_pool_base > 0) {
+ printf("VMDQ_DCB multi-queue mode is nonsensical"
+ " for port %d.", pid);
+ return -1;
+ }
+
+ /* Assume the ports in testpmd have the same dcb capability
+ * and has the same number of rxq and txq in dcb mode
+ */
+ if (dcb_mode == DCB_VT_ENABLED) {
+ if (rte_port->dev_info.max_vfs > 0) {
+ nb_rxq = rte_port->dev_info.nb_rx_queues;
+ nb_txq = rte_port->dev_info.nb_tx_queues;
+ } else {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ }
+ } else {
+ /*if vt is disabled, use all pf queues */
+ if (rte_port->dev_info.vmdq_pool_base == 0) {
+ nb_rxq = rte_port->dev_info.max_rx_queues;
+ nb_txq = rte_port->dev_info.max_tx_queues;
+ } else {
+ nb_rxq = (queueid_t)num_tcs;
+ nb_txq = (queueid_t)num_tcs;
+
+ }
+ }
+ rx_free_thresh = 64;
+
+ memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf));
+
+ rxtx_port_config(rte_port);
+ /* VLAN filter */
+ rte_port->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+ for (i = 0; i < RTE_DIM(vlan_tags); i++)
+ rx_vft_set(pid, vlan_tags[i], 1);
+
+ retval = eth_macaddr_get_print_err(pid, &rte_port->eth_addr);
+ if (retval != 0)
+ return retval;
+
+ map_port_queue_stats_mapping_registers(pid, rte_port);
+
+ rte_port->dcb_flag = 1;
+
+ return 0;
+}
+
+static void
+init_port(void)
+{
+ /* Configuration of Ethernet ports. */
+ ports = rte_zmalloc("testpmd: ports",
+ sizeof(struct rte_port) * RTE_MAX_ETHPORTS,
+ RTE_CACHE_LINE_SIZE);
+ if (ports == NULL) {
+ rte_exit(EXIT_FAILURE,
+ "rte_zmalloc(%d struct rte_port) failed\n",
+ RTE_MAX_ETHPORTS);
+ }
+
+ /* Initialize ports NUMA structures */
+ memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+ memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+ memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS);
+}
+
+static void
+force_quit(void)
+{
+ pmd_test_exit();
+ prompt_exit();
+}
+
+static void
+print_stats(void)
+{
+ uint8_t i;
+ const char clr[] = { 27, '[', '2', 'J', '\0' };
+ const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' };
+
+ /* Clear screen and move to top left */
+ printf("%s%s", clr, top_left);
+
+ printf("\nPort statistics ====================================");
+ for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+ nic_stats_display(fwd_ports_ids[i]);
+
+ fflush(stdout);
+}
+
+static void
+signal_handler(int signum)
+{
+ if (signum == SIGINT || signum == SIGTERM) {
+ printf("\nSignal %d received, preparing to exit...\n",
+ signum);
+#ifdef RTE_LIBRTE_PDUMP
+ /* uninitialize packet capture framework */
+ rte_pdump_uninit();
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (latencystats_enabled != 0)
+ rte_latencystats_uninit();
+#endif
+ force_quit();
+ /* Set flag to indicate the force termination. */
+ f_quit = 1;
+ /* exit with the expected status */
+ signal(signum, SIG_DFL);
+ kill(getpid(), signum);
+ }
+}
+
+int
+main(int argc, char** argv)
+{
+ int diag;
+ portid_t port_id;
+ uint16_t count;
+ int ret;
+
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
+
+ testpmd_logtype = rte_log_register("testpmd");
+ if (testpmd_logtype < 0)
+ rte_exit(EXIT_FAILURE, "Cannot register log type");
+ rte_log_set_level(testpmd_logtype, RTE_LOG_DEBUG);
+
+ diag = rte_eal_init(argc, argv);
+ if (diag < 0)
+ rte_exit(EXIT_FAILURE, "Cannot init EAL: %s\n",
+ rte_strerror(rte_errno));
+
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+ rte_exit(EXIT_FAILURE,
+ "Secondary process type not supported.\n");
+
+ ret = register_eth_event_callback();
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE, "Cannot register for ethdev events");
+
+#ifdef RTE_LIBRTE_PDUMP
+ /* initialize packet capture framework */
+ rte_pdump_init();
+#endif
+
+ count = 0;
+ RTE_ETH_FOREACH_DEV(port_id) {
+ ports_ids[count] = port_id;
+ count++;
+ }
+ nb_ports = (portid_t) count;
+ if (nb_ports == 0)
+ TESTPMD_LOG(WARNING, "No probed ethernet devices\n");
+
+ /* allocate port structures, and init them */
+ init_port();
+
+ set_def_fwd_config();
+ if (nb_lcores == 0)
+ rte_exit(EXIT_FAILURE, "No cores defined for forwarding\n"
+ "Check the core mask argument\n");
+
+ /* Bitrate/latency stats disabled by default */
+#ifdef RTE_LIBRTE_BITRATE
+ bitrate_enabled = 0;
+#endif
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ latencystats_enabled = 0;
+#endif
+
+ /* on FreeBSD, mlockall() is disabled by default */
+#ifdef RTE_EXEC_ENV_FREEBSD
+ do_mlockall = 0;
+#else
+ do_mlockall = 1;
+#endif
+
+ argc -= diag;
+ argv += diag;
+ if (argc > 1)
+ launch_args_parse(argc, argv);
+
+ if (do_mlockall && mlockall(MCL_CURRENT | MCL_FUTURE)) {
+ TESTPMD_LOG(NOTICE, "mlockall() failed with error \"%s\"\n",
+ strerror(errno));
+ }
+
+ if (tx_first && interactive)
+ rte_exit(EXIT_FAILURE, "--tx-first cannot be used on "
+ "interactive mode.\n");
+
+ if (tx_first && lsc_interrupt) {
+ printf("Warning: lsc_interrupt needs to be off when "
+ " using tx_first. Disabling.\n");
+ lsc_interrupt = 0;
+ }
+
+ if (!nb_rxq && !nb_txq)
+ printf("Warning: Either rx or tx queues should be non-zero\n");
+
+ if (nb_rxq > 1 && nb_rxq > nb_txq)
+ printf("Warning: nb_rxq=%d enables RSS configuration, "
+ "but nb_txq=%d will prevent to fully test it.\n",
+ nb_rxq, nb_txq);
+
+ init_config();
+
+ if (hot_plug) {
+ ret = rte_dev_hotplug_handle_enable();
+ if (ret) {
+ RTE_LOG(ERR, EAL,
+ "fail to enable hotplug handling.");
+ return -1;
+ }
+
+ ret = rte_dev_event_monitor_start();
+ if (ret) {
+ RTE_LOG(ERR, EAL,
+ "fail to start device event monitoring.");
+ return -1;
+ }
+
+ ret = rte_dev_event_callback_register(NULL,
+ dev_event_callback, NULL);
+ if (ret) {
+ RTE_LOG(ERR, EAL,
+ "fail to register device event callback\n");
+ return -1;
+ }
+ }
+
+ if (!no_device_start && start_port(RTE_PORT_ALL) != 0)
+ rte_exit(EXIT_FAILURE, "Start ports failed\n");
+
+ /* set all ports to promiscuous mode by default */
+ RTE_ETH_FOREACH_DEV(port_id) {
+ ret = rte_eth_promiscuous_enable(port_id);
+ if (ret != 0)
+ printf("Error during enabling promiscuous mode for port %u: %s - ignore\n",
+ port_id, rte_strerror(-ret));
+ }
+
+ /* Init metrics library */
+ rte_metrics_init(rte_socket_id());
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+ if (latencystats_enabled != 0) {
+ int ret = rte_latencystats_init(1, NULL);
+ if (ret)
+ printf("Warning: latencystats init()"
+ " returned error %d\n", ret);
+ printf("Latencystats running on lcore %d\n",
+ latencystats_lcore_id);
+ }
+#endif
+
+ /* Setup bitrate stats */
+#ifdef RTE_LIBRTE_BITRATE
+ if (bitrate_enabled != 0) {
+ bitrate_data = rte_stats_bitrate_create();
+ if (bitrate_data == NULL)
+ rte_exit(EXIT_FAILURE,
+ "Could not allocate bitrate data.\n");
+ rte_stats_bitrate_reg(bitrate_data);
+ }
+#endif
+
+#ifdef RTE_LIBRTE_CMDLINE
+ if (strlen(cmdline_filename) != 0)
+ cmdline_read_from_file(cmdline_filename);
+
+ if (interactive == 1) {
+ if (auto_start) {
+ printf("Start automatic packet forwarding\n");
+ start_packet_forwarding(0);
+ }
+ prompt();
+ pmd_test_exit();
+ } else
+#endif
+ {
+ char c;
+ int rc;
+
+ f_quit = 0;
+
+ printf("No commandline core given, start packet forwarding\n");
+ start_packet_forwarding(tx_first);
+ if (stats_period != 0) {
+ uint64_t prev_time = 0, cur_time, diff_time = 0;
+ uint64_t timer_period;
+
+ /* Convert to number of cycles */
+ timer_period = stats_period * rte_get_timer_hz();
+
+ while (f_quit == 0) {
+ cur_time = rte_get_timer_cycles();
+ diff_time += cur_time - prev_time;
+
+ if (diff_time >= timer_period) {
+ print_stats();
+ /* Reset the timer */
+ diff_time = 0;
+ }
+ /* Sleep to avoid unnecessary checks */
+ prev_time = cur_time;
+ sleep(1);
+ }
+ }
+
+ printf("Press enter to exit\n");
+ rc = read(0, &c, 1);
+ pmd_test_exit();
+ if (rc < 0)
+ return 1;
+ }
+
+ ret = rte_eal_cleanup();
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ "EAL cleanup failed: %s\n", strerror(-ret));
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/spdk/dpdk/app/test-pmd/testpmd.h b/src/spdk/dpdk/app/test-pmd/testpmd.h
new file mode 100644
index 000000000..a80375093
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/testpmd.h
@@ -0,0 +1,938 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#ifndef _TESTPMD_H_
+#define _TESTPMD_H_
+
+#include <stdbool.h>
+
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_gro.h>
+#include <rte_gso.h>
+#include <cmdline.h>
+
+#define RTE_PORT_ALL (~(portid_t)0x0)
+
+#define RTE_TEST_RX_DESC_MAX 2048
+#define RTE_TEST_TX_DESC_MAX 2048
+
+#define RTE_PORT_STOPPED (uint16_t)0
+#define RTE_PORT_STARTED (uint16_t)1
+#define RTE_PORT_CLOSED (uint16_t)2
+#define RTE_PORT_HANDLING (uint16_t)3
+
+/*
+ * It is used to allocate the memory for hash key.
+ * The hash key size is NIC dependent.
+ */
+#define RSS_HASH_KEY_LENGTH 64
+
+/*
+ * Default size of the mbuf data buffer to receive standard 1518-byte
+ * Ethernet frames in a mono-segment memory buffer.
+ */
+#define DEFAULT_MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
+/**< Default size of mbuf data buffer. */
+
+/*
+ * The maximum number of segments per packet is used when creating
+ * scattered transmit packets composed of a list of mbufs.
+ */
+#define RTE_MAX_SEGS_PER_PKT 255 /**< nb_segs is a 8-bit unsigned char. */
+
+#define MAX_PKT_BURST 512
+#define DEF_PKT_BURST 32
+
+#define DEF_MBUF_CACHE 250
+
+#define RTE_CACHE_LINE_SIZE_ROUNDUP(size) \
+ (RTE_CACHE_LINE_SIZE * ((size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE))
+
+#define NUMA_NO_CONFIG 0xFF
+#define UMA_NO_CONFIG 0xFF
+
+typedef uint8_t lcoreid_t;
+typedef uint16_t portid_t;
+typedef uint16_t queueid_t;
+typedef uint16_t streamid_t;
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+#define SOFTNIC 1
+#else
+#define SOFTNIC 0
+#endif
+
+enum {
+ PORT_TOPOLOGY_PAIRED,
+ PORT_TOPOLOGY_CHAINED,
+ PORT_TOPOLOGY_LOOP,
+};
+
+enum {
+ MP_ALLOC_NATIVE, /**< allocate and populate mempool natively */
+ MP_ALLOC_ANON,
+ /**< allocate mempool natively, but populate using anonymous memory */
+ MP_ALLOC_XMEM,
+ /**< allocate and populate mempool using anonymous memory */
+ MP_ALLOC_XMEM_HUGE,
+ /**< allocate and populate mempool using anonymous hugepage memory */
+ MP_ALLOC_XBUF
+ /**< allocate mempool natively, use rte_pktmbuf_pool_create_extbuf */
+};
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+/**
+ * The data structure associated with RX and TX packet burst statistics
+ * that are recorded for each forwarding stream.
+ */
+struct pkt_burst_stats {
+ unsigned int pkt_burst_spread[MAX_PKT_BURST];
+};
+#endif
+
+/** Information for a given RSS type. */
+struct rss_type_info {
+ const char *str; /**< Type name. */
+ uint64_t rss_type; /**< Type value. */
+};
+
+/**
+ * RSS type information table.
+ *
+ * An entry with a NULL type name terminates the list.
+ */
+extern const struct rss_type_info rss_type_table[];
+
+/**
+ * Dynf name array.
+ *
+ * Array that holds the name for each dynf.
+ */
+extern char dynf_names[64][RTE_MBUF_DYN_NAMESIZE];
+
+/**
+ * The data structure associated with a forwarding stream between a receive
+ * port/queue and a transmit port/queue.
+ */
+struct fwd_stream {
+ /* "read-only" data */
+ portid_t rx_port; /**< port to poll for received packets */
+ queueid_t rx_queue; /**< RX queue to poll on "rx_port" */
+ portid_t tx_port; /**< forwarding port of received packets */
+ queueid_t tx_queue; /**< TX queue to send forwarded packets */
+ streamid_t peer_addr; /**< index of peer ethernet address of packets */
+
+ unsigned int retry_enabled;
+
+ /* "read-write" results */
+ uint64_t rx_packets; /**< received packets */
+ uint64_t tx_packets; /**< received packets transmitted */
+ uint64_t fwd_dropped; /**< received packets not forwarded */
+ uint64_t rx_bad_ip_csum ; /**< received packets has bad ip checksum */
+ uint64_t rx_bad_l4_csum ; /**< received packets has bad l4 checksum */
+ uint64_t rx_bad_outer_l4_csum;
+ /**< received packets has bad outer l4 checksum */
+ unsigned int gro_times; /**< GRO operation times */
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t core_cycles; /**< used for RX and TX processing */
+#endif
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ struct pkt_burst_stats rx_burst_stats;
+ struct pkt_burst_stats tx_burst_stats;
+#endif
+};
+
+/** Descriptor for a single flow. */
+struct port_flow {
+ struct port_flow *next; /**< Next flow in list. */
+ struct port_flow *tmp; /**< Temporary linking. */
+ uint32_t id; /**< Flow rule ID. */
+ struct rte_flow *flow; /**< Opaque flow object returned by PMD. */
+ struct rte_flow_conv_rule rule; /* Saved flow rule description. */
+ uint8_t data[]; /**< Storage for flow rule description */
+};
+
+#ifdef SOFTNIC
+/**
+ * The data structure associate with softnic port
+ */
+struct softnic_port {
+ uint32_t default_tm_hierarchy_enable; /**< default tm hierarchy */
+ struct fwd_lcore **fwd_lcore_arg; /**< softnic fwd core parameters */
+};
+#endif
+
+/**
+ * The data structure associated with each port.
+ */
+struct rte_port {
+ struct rte_eth_dev_info dev_info; /**< PCI info + driver name */
+ struct rte_eth_conf dev_conf; /**< Port configuration. */
+ struct rte_ether_addr eth_addr; /**< Port ethernet address */
+ struct rte_eth_stats stats; /**< Last port statistics */
+ unsigned int socket_id; /**< For NUMA support */
+ uint16_t parse_tunnel:1; /**< Parse internal headers */
+ uint16_t tso_segsz; /**< Segmentation offload MSS for non-tunneled packets. */
+ uint16_t tunnel_tso_segsz; /**< Segmentation offload MSS for tunneled pkts. */
+ uint16_t tx_vlan_id;/**< The tag ID */
+ uint16_t tx_vlan_id_outer;/**< The outer tag ID */
+ uint8_t tx_queue_stats_mapping_enabled;
+ uint8_t rx_queue_stats_mapping_enabled;
+ volatile uint16_t port_status; /**< port started or not */
+ uint8_t need_setup; /**< port just attached */
+ uint8_t need_reconfig; /**< need reconfiguring port or not */
+ uint8_t need_reconfig_queues; /**< need reconfiguring queues or not */
+ uint8_t rss_flag; /**< enable rss or not */
+ uint8_t dcb_flag; /**< enable dcb */
+ uint16_t nb_rx_desc[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue rx desc number */
+ uint16_t nb_tx_desc[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue tx desc number */
+ struct rte_eth_rxconf rx_conf[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue rx configuration */
+ struct rte_eth_txconf tx_conf[RTE_MAX_QUEUES_PER_PORT+1]; /**< per queue tx configuration */
+ struct rte_ether_addr *mc_addr_pool; /**< pool of multicast addrs */
+ uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */
+ uint8_t slave_flag; /**< bonding slave port */
+ struct port_flow *flow_list; /**< Associated flows. */
+ const struct rte_eth_rxtx_callback *rx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
+ const struct rte_eth_rxtx_callback *tx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
+#ifdef SOFTNIC
+ struct softnic_port softport; /**< softnic params */
+#endif
+ /**< metadata value to insert in Tx packets. */
+ uint32_t tx_metadata;
+ const struct rte_eth_rxtx_callback *tx_set_md_cb[RTE_MAX_QUEUES_PER_PORT+1];
+ /**< dynamic flags. */
+ uint64_t mbuf_dynf;
+ const struct rte_eth_rxtx_callback *tx_set_dynf_cb[RTE_MAX_QUEUES_PER_PORT+1];
+};
+
+/**
+ * The data structure associated with each forwarding logical core.
+ * The logical cores are internally numbered by a core index from 0 to
+ * the maximum number of logical cores - 1.
+ * The system CPU identifier of all logical cores are setup in a global
+ * CPU id. configuration table.
+ */
+struct fwd_lcore {
+ struct rte_gso_ctx gso_ctx; /**< GSO context */
+ struct rte_mempool *mbp; /**< The mbuf pool to use by this core */
+ void *gro_ctx; /**< GRO context */
+ streamid_t stream_idx; /**< index of 1st stream in "fwd_streams" */
+ streamid_t stream_nb; /**< number of streams in "fwd_streams" */
+ lcoreid_t cpuid_idx; /**< index of logical core in CPU id table */
+ queueid_t tx_queue; /**< TX queue to send forwarded packets */
+ volatile char stopped; /**< stop forwarding when set */
+};
+
+/*
+ * Forwarding mode operations:
+ * - IO forwarding mode (default mode)
+ * Forwards packets unchanged.
+ *
+ * - MAC forwarding mode
+ * Set the source and the destination Ethernet addresses of packets
+ * before forwarding them.
+ *
+ * - IEEE1588 forwarding mode
+ * Check that received IEEE1588 Precise Time Protocol (PTP) packets are
+ * filtered and timestamped by the hardware.
+ * Forwards packets unchanged on the same port.
+ * Check that sent IEEE1588 PTP packets are timestamped by the hardware.
+ */
+typedef void (*port_fwd_begin_t)(portid_t pi);
+typedef void (*port_fwd_end_t)(portid_t pi);
+typedef void (*packet_fwd_t)(struct fwd_stream *fs);
+
+struct fwd_engine {
+ const char *fwd_mode_name; /**< Forwarding mode name. */
+ port_fwd_begin_t port_fwd_begin; /**< NULL if nothing special to do. */
+ port_fwd_end_t port_fwd_end; /**< NULL if nothing special to do. */
+ packet_fwd_t packet_fwd; /**< Mandatory. */
+};
+
+#define BURST_TX_WAIT_US 1
+#define BURST_TX_RETRIES 64
+
+extern uint32_t burst_tx_delay_time;
+extern uint32_t burst_tx_retry_num;
+
+extern struct fwd_engine io_fwd_engine;
+extern struct fwd_engine mac_fwd_engine;
+extern struct fwd_engine mac_swap_engine;
+extern struct fwd_engine flow_gen_engine;
+extern struct fwd_engine rx_only_engine;
+extern struct fwd_engine tx_only_engine;
+extern struct fwd_engine csum_fwd_engine;
+extern struct fwd_engine icmp_echo_engine;
+extern struct fwd_engine noisy_vnf_engine;
+#ifdef SOFTNIC
+extern struct fwd_engine softnic_fwd_engine;
+#endif
+#ifdef RTE_LIBRTE_IEEE1588
+extern struct fwd_engine ieee1588_fwd_engine;
+#endif
+
+extern struct fwd_engine * fwd_engines[]; /**< NULL terminated array. */
+extern cmdline_parse_inst_t cmd_set_raw;
+extern cmdline_parse_inst_t cmd_show_set_raw;
+extern cmdline_parse_inst_t cmd_show_set_raw_all;
+
+extern uint16_t mempool_flags;
+
+/**
+ * Forwarding Configuration
+ *
+ */
+struct fwd_config {
+ struct fwd_engine *fwd_eng; /**< Packet forwarding mode. */
+ streamid_t nb_fwd_streams; /**< Nb. of forward streams to process. */
+ lcoreid_t nb_fwd_lcores; /**< Nb. of logical cores to launch. */
+ portid_t nb_fwd_ports; /**< Nb. of ports involved. */
+};
+
+/**
+ * DCB mode enable
+ */
+enum dcb_mode_enable
+{
+ DCB_VT_ENABLED,
+ DCB_ENABLED
+};
+
+#define MAX_TX_QUEUE_STATS_MAPPINGS 1024 /* MAX_PORT of 32 @ 32 tx_queues/port */
+#define MAX_RX_QUEUE_STATS_MAPPINGS 4096 /* MAX_PORT of 32 @ 128 rx_queues/port */
+
+struct queue_stats_mappings {
+ portid_t port_id;
+ uint16_t queue_id;
+ uint8_t stats_counter_id;
+} __rte_cache_aligned;
+
+extern struct queue_stats_mappings tx_queue_stats_mappings_array[];
+extern struct queue_stats_mappings rx_queue_stats_mappings_array[];
+
+/* Assign both tx and rx queue stats mappings to the same default values */
+extern struct queue_stats_mappings *tx_queue_stats_mappings;
+extern struct queue_stats_mappings *rx_queue_stats_mappings;
+
+extern uint16_t nb_tx_queue_stats_mappings;
+extern uint16_t nb_rx_queue_stats_mappings;
+
+extern uint8_t xstats_hide_zero; /**< Hide zero values for xstats display */
+
+/* globals used for configuration */
+extern uint16_t verbose_level; /**< Drives messages being displayed, if any. */
+extern int testpmd_logtype; /**< Log type for testpmd logs */
+extern uint8_t interactive;
+extern uint8_t auto_start;
+extern uint8_t tx_first;
+extern char cmdline_filename[PATH_MAX]; /**< offline commands file */
+extern uint8_t numa_support; /**< set by "--numa" parameter */
+extern uint16_t port_topology; /**< set by "--port-topology" parameter */
+extern uint8_t no_flush_rx; /**<set by "--no-flush-rx" parameter */
+extern uint8_t flow_isolate_all; /**< set by "--flow-isolate-all */
+extern uint8_t mp_alloc_type;
+/**< set by "--mp-anon" or "--mp-alloc" parameter */
+extern uint8_t no_link_check; /**<set by "--disable-link-check" parameter */
+extern uint8_t no_device_start; /**<set by "--disable-device-start" parameter */
+extern volatile int test_done; /* stop packet forwarding when set to 1. */
+extern uint8_t lsc_interrupt; /**< disabled by "--no-lsc-interrupt" parameter */
+extern uint8_t rmv_interrupt; /**< disabled by "--no-rmv-interrupt" parameter */
+extern uint32_t event_print_mask;
+/**< set by "--print-event xxxx" and "--mask-event xxxx parameters */
+extern bool setup_on_probe_event; /**< disabled by port setup-on iterator */
+extern uint8_t hot_plug; /**< enable by "--hot-plug" parameter */
+extern int do_mlockall; /**< set by "--mlockall" or "--no-mlockall" parameter */
+extern uint8_t clear_ptypes; /**< disabled by set ptype cmd */
+
+#ifdef RTE_LIBRTE_IXGBE_BYPASS
+extern uint32_t bypass_timeout; /**< Store the NIC bypass watchdog timeout */
+#endif
+
+/*
+ * Store specified sockets on which memory pool to be used by ports
+ * is allocated.
+ */
+extern uint8_t port_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which RX ring to be used by ports
+ * is allocated.
+ */
+extern uint8_t rxring_numa[RTE_MAX_ETHPORTS];
+
+/*
+ * Store specified sockets on which TX ring to be used by ports
+ * is allocated.
+ */
+extern uint8_t txring_numa[RTE_MAX_ETHPORTS];
+
+extern uint8_t socket_num;
+
+/*
+ * Configuration of logical cores:
+ * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
+ */
+extern lcoreid_t nb_lcores; /**< Number of logical cores probed at init time. */
+extern lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */
+extern lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */
+extern unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE];
+extern unsigned int num_sockets;
+extern unsigned int socket_ids[RTE_MAX_NUMA_NODES];
+
+/*
+ * Configuration of Ethernet ports:
+ * nb_fwd_ports <= nb_cfg_ports <= nb_ports
+ */
+extern portid_t nb_ports; /**< Number of ethernet ports probed at init time. */
+extern portid_t nb_cfg_ports; /**< Number of configured ports. */
+extern portid_t nb_fwd_ports; /**< Number of forwarding ports. */
+extern portid_t fwd_ports_ids[RTE_MAX_ETHPORTS];
+extern struct rte_port *ports;
+
+extern struct rte_eth_rxmode rx_mode;
+extern struct rte_eth_txmode tx_mode;
+
+extern uint64_t rss_hf;
+
+extern queueid_t nb_hairpinq;
+extern queueid_t nb_rxq;
+extern queueid_t nb_txq;
+
+extern uint16_t nb_rxd;
+extern uint16_t nb_txd;
+
+extern int16_t rx_free_thresh;
+extern int8_t rx_drop_en;
+extern int16_t tx_free_thresh;
+extern int16_t tx_rs_thresh;
+
+extern uint16_t noisy_tx_sw_bufsz;
+extern uint16_t noisy_tx_sw_buf_flush_time;
+extern uint64_t noisy_lkup_mem_sz;
+extern uint64_t noisy_lkup_num_writes;
+extern uint64_t noisy_lkup_num_reads;
+extern uint64_t noisy_lkup_num_reads_writes;
+
+extern uint8_t dcb_config;
+extern uint8_t dcb_test;
+
+extern uint16_t mbuf_data_size; /**< Mbuf data space size. */
+extern uint32_t param_total_num_mbufs;
+
+extern uint16_t stats_period;
+
+#ifdef RTE_LIBRTE_LATENCY_STATS
+extern uint8_t latencystats_enabled;
+extern lcoreid_t latencystats_lcore_id;
+#endif
+
+#ifdef RTE_LIBRTE_BITRATE
+extern lcoreid_t bitrate_lcore_id;
+extern uint8_t bitrate_enabled;
+#endif
+
+extern struct rte_fdir_conf fdir_conf;
+
+/*
+ * Configuration of packet segments used by the "txonly" processing engine.
+ */
+#define TXONLY_DEF_PACKET_LEN 64
+extern uint16_t tx_pkt_length; /**< Length of TXONLY packet */
+extern uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT]; /**< Seg. lengths */
+extern uint8_t tx_pkt_nb_segs; /**< Number of segments in TX packets */
+
+enum tx_pkt_split {
+ TX_PKT_SPLIT_OFF,
+ TX_PKT_SPLIT_ON,
+ TX_PKT_SPLIT_RND,
+};
+
+extern enum tx_pkt_split tx_pkt_split;
+
+extern uint8_t txonly_multi_flow;
+
+extern uint16_t nb_pkt_per_burst;
+extern uint16_t mb_mempool_cache;
+extern int8_t rx_pthresh;
+extern int8_t rx_hthresh;
+extern int8_t rx_wthresh;
+extern int8_t tx_pthresh;
+extern int8_t tx_hthresh;
+extern int8_t tx_wthresh;
+
+extern uint16_t tx_udp_src_port;
+extern uint16_t tx_udp_dst_port;
+
+extern uint32_t tx_ip_src_addr;
+extern uint32_t tx_ip_dst_addr;
+
+extern struct fwd_config cur_fwd_config;
+extern struct fwd_engine *cur_fwd_eng;
+extern uint32_t retry_enabled;
+extern struct fwd_lcore **fwd_lcores;
+extern struct fwd_stream **fwd_streams;
+
+extern uint16_t vxlan_gpe_udp_port; /**< UDP port of tunnel VXLAN-GPE. */
+
+extern portid_t nb_peer_eth_addrs; /**< Number of peer ethernet addresses. */
+extern struct rte_ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS];
+
+extern uint32_t burst_tx_delay_time; /**< Burst tx delay time(us) for mac-retry. */
+extern uint32_t burst_tx_retry_num; /**< Burst tx retry number for mac-retry. */
+
+#define GRO_DEFAULT_ITEM_NUM_PER_FLOW 32
+#define GRO_DEFAULT_FLOW_NUM (RTE_GRO_MAX_BURST_ITEM_NUM / \
+ GRO_DEFAULT_ITEM_NUM_PER_FLOW)
+
+#define GRO_DEFAULT_FLUSH_CYCLES 1
+#define GRO_MAX_FLUSH_CYCLES 4
+
+struct gro_status {
+ struct rte_gro_param param;
+ uint8_t enable;
+};
+extern struct gro_status gro_ports[RTE_MAX_ETHPORTS];
+extern uint8_t gro_flush_cycles;
+
+#define GSO_MAX_PKT_BURST 2048
+struct gso_status {
+ uint8_t enable;
+};
+extern struct gso_status gso_ports[RTE_MAX_ETHPORTS];
+extern uint16_t gso_max_segment_size;
+
+/* VXLAN encap/decap parameters. */
+struct vxlan_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ uint32_t select_tos_ttl:1;
+ uint8_t vni[3];
+ rte_be16_t udp_src;
+ rte_be16_t udp_dst;
+ rte_be32_t ipv4_src;
+ rte_be32_t ipv4_dst;
+ uint8_t ipv6_src[16];
+ uint8_t ipv6_dst[16];
+ rte_be16_t vlan_tci;
+ uint8_t ip_tos;
+ uint8_t ip_ttl;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+
+extern struct vxlan_encap_conf vxlan_encap_conf;
+
+/* NVGRE encap/decap parameters. */
+struct nvgre_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ uint8_t tni[3];
+ rte_be32_t ipv4_src;
+ rte_be32_t ipv4_dst;
+ uint8_t ipv6_src[16];
+ uint8_t ipv6_dst[16];
+ rte_be16_t vlan_tci;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+
+extern struct nvgre_encap_conf nvgre_encap_conf;
+
+/* L2 encap parameters. */
+struct l2_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ rte_be16_t vlan_tci;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+extern struct l2_encap_conf l2_encap_conf;
+
+/* L2 decap parameters. */
+struct l2_decap_conf {
+ uint32_t select_vlan:1;
+};
+extern struct l2_decap_conf l2_decap_conf;
+
+/* MPLSoGRE encap parameters. */
+struct mplsogre_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ uint8_t label[3];
+ rte_be32_t ipv4_src;
+ rte_be32_t ipv4_dst;
+ uint8_t ipv6_src[16];
+ uint8_t ipv6_dst[16];
+ rte_be16_t vlan_tci;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+extern struct mplsogre_encap_conf mplsogre_encap_conf;
+
+/* MPLSoGRE decap parameters. */
+struct mplsogre_decap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+};
+extern struct mplsogre_decap_conf mplsogre_decap_conf;
+
+/* MPLSoUDP encap parameters. */
+struct mplsoudp_encap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+ uint8_t label[3];
+ rte_be16_t udp_src;
+ rte_be16_t udp_dst;
+ rte_be32_t ipv4_src;
+ rte_be32_t ipv4_dst;
+ uint8_t ipv6_src[16];
+ uint8_t ipv6_dst[16];
+ rte_be16_t vlan_tci;
+ uint8_t eth_src[RTE_ETHER_ADDR_LEN];
+ uint8_t eth_dst[RTE_ETHER_ADDR_LEN];
+};
+extern struct mplsoudp_encap_conf mplsoudp_encap_conf;
+
+/* MPLSoUDP decap parameters. */
+struct mplsoudp_decap_conf {
+ uint32_t select_ipv4:1;
+ uint32_t select_vlan:1;
+};
+extern struct mplsoudp_decap_conf mplsoudp_decap_conf;
+
+extern enum rte_eth_rx_mq_mode rx_mq_mode;
+
+static inline unsigned int
+lcore_num(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; ++i)
+ if (fwd_lcores_cpuids[i] == rte_lcore_id())
+ return i;
+
+ rte_panic("lcore_id of current thread not found in fwd_lcores_cpuids\n");
+}
+
+void
+parse_fwd_portlist(const char *port);
+
+static inline struct fwd_lcore *
+current_fwd_lcore(void)
+{
+ return fwd_lcores[lcore_num()];
+}
+
+/* Mbuf Pools */
+static inline void
+mbuf_poolname_build(unsigned int sock_id, char* mp_name, int name_size)
+{
+ snprintf(mp_name, name_size, "mbuf_pool_socket_%u", sock_id);
+}
+
+static inline struct rte_mempool *
+mbuf_pool_find(unsigned int sock_id)
+{
+ char pool_name[RTE_MEMPOOL_NAMESIZE];
+
+ mbuf_poolname_build(sock_id, pool_name, sizeof(pool_name));
+ return rte_mempool_lookup((const char *)pool_name);
+}
+
+/**
+ * Read/Write operations on a PCI register of a port.
+ */
+static inline uint32_t
+port_pci_reg_read(struct rte_port *port, uint32_t reg_off)
+{
+ const struct rte_pci_device *pci_dev;
+ const struct rte_bus *bus;
+ void *reg_addr;
+ uint32_t reg_v;
+
+ if (!port->dev_info.device) {
+ printf("Invalid device\n");
+ return 0;
+ }
+
+ bus = rte_bus_find_by_device(port->dev_info.device);
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(port->dev_info.device);
+ } else {
+ printf("Not a PCI device\n");
+ return 0;
+ }
+
+ reg_addr = ((char *)pci_dev->mem_resource[0].addr + reg_off);
+ reg_v = *((volatile uint32_t *)reg_addr);
+ return rte_le_to_cpu_32(reg_v);
+}
+
+#define port_id_pci_reg_read(pt_id, reg_off) \
+ port_pci_reg_read(&ports[(pt_id)], (reg_off))
+
+static inline void
+port_pci_reg_write(struct rte_port *port, uint32_t reg_off, uint32_t reg_v)
+{
+ const struct rte_pci_device *pci_dev;
+ const struct rte_bus *bus;
+ void *reg_addr;
+
+ if (!port->dev_info.device) {
+ printf("Invalid device\n");
+ return;
+ }
+
+ bus = rte_bus_find_by_device(port->dev_info.device);
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(port->dev_info.device);
+ } else {
+ printf("Not a PCI device\n");
+ return;
+ }
+
+ reg_addr = ((char *)pci_dev->mem_resource[0].addr + reg_off);
+ *((volatile uint32_t *)reg_addr) = rte_cpu_to_le_32(reg_v);
+}
+
+#define port_id_pci_reg_write(pt_id, reg_off, reg_value) \
+ port_pci_reg_write(&ports[(pt_id)], (reg_off), (reg_value))
+
+/* Prototypes */
+unsigned int parse_item_list(char* str, const char* item_name,
+ unsigned int max_items,
+ unsigned int *parsed_items, int check_unique_values);
+void launch_args_parse(int argc, char** argv);
+void cmdline_read_from_file(const char *filename);
+void prompt(void);
+void prompt_exit(void);
+void nic_stats_display(portid_t port_id);
+void nic_stats_clear(portid_t port_id);
+void nic_xstats_display(portid_t port_id);
+void nic_xstats_clear(portid_t port_id);
+void nic_stats_mapping_display(portid_t port_id);
+void device_infos_display(const char *identifier);
+void port_infos_display(portid_t port_id);
+void port_summary_display(portid_t port_id);
+void port_summary_header_display(void);
+void port_offload_cap_display(portid_t port_id);
+void rx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
+void tx_queue_infos_display(portid_t port_idi, uint16_t queue_id);
+void fwd_lcores_config_display(void);
+void pkt_fwd_config_display(struct fwd_config *cfg);
+void rxtx_config_display(void);
+void fwd_config_setup(void);
+void set_def_fwd_config(void);
+void reconfig(portid_t new_port_id, unsigned socket_id);
+int init_fwd_streams(void);
+void update_fwd_ports(portid_t new_pid);
+
+void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
+
+void port_mtu_set(portid_t port_id, uint16_t mtu);
+void port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_pos);
+void port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
+ uint8_t bit_v);
+void port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos);
+void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
+ uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value);
+void port_reg_display(portid_t port_id, uint32_t reg_off);
+void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value);
+int port_flow_validate(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions);
+int port_flow_create(portid_t port_id,
+ const struct rte_flow_attr *attr,
+ const struct rte_flow_item *pattern,
+ const struct rte_flow_action *actions);
+void update_age_action_context(const struct rte_flow_action *actions,
+ struct port_flow *pf);
+int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule);
+int port_flow_flush(portid_t port_id);
+int port_flow_dump(portid_t port_id, const char *file_name);
+int port_flow_query(portid_t port_id, uint32_t rule,
+ const struct rte_flow_action *action);
+void port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group);
+void port_flow_aged(portid_t port_id, uint8_t destroy);
+int port_flow_isolate(portid_t port_id, int set);
+
+void rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id);
+void tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id);
+
+int set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc);
+int set_fwd_lcores_mask(uint64_t lcoremask);
+void set_fwd_lcores_number(uint16_t nb_lc);
+
+void set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt);
+void set_fwd_ports_mask(uint64_t portmask);
+void set_fwd_ports_number(uint16_t nb_pt);
+int port_is_forwarding(portid_t port_id);
+
+void rx_vlan_strip_set(portid_t port_id, int on);
+void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on);
+
+void rx_vlan_filter_set(portid_t port_id, int on);
+void rx_vlan_all_filter_set(portid_t port_id, int on);
+void rx_vlan_qinq_strip_set(portid_t port_id, int on);
+int rx_vft_set(portid_t port_id, uint16_t vlan_id, int on);
+void vlan_extend_set(portid_t port_id, int on);
+void vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type,
+ uint16_t tp_id);
+void tx_vlan_set(portid_t port_id, uint16_t vlan_id);
+void tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer);
+void tx_vlan_reset(portid_t port_id);
+void tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on);
+
+void set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value);
+
+void set_xstats_hide_zero(uint8_t on_off);
+
+void set_verbose_level(uint16_t vb_level);
+void set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs);
+void show_tx_pkt_segments(void);
+void set_tx_pkt_split(const char *name);
+void set_nb_pkt_per_burst(uint16_t pkt_burst);
+char *list_pkt_forwarding_modes(void);
+char *list_pkt_forwarding_retry_modes(void);
+void set_pkt_forwarding_mode(const char *fwd_mode);
+void start_packet_forwarding(int with_tx_first);
+void fwd_stats_display(void);
+void fwd_stats_reset(void);
+void stop_packet_forwarding(void);
+void dev_set_link_up(portid_t pid);
+void dev_set_link_down(portid_t pid);
+void init_port_config(void);
+void set_port_slave_flag(portid_t slave_pid);
+void clear_port_slave_flag(portid_t slave_pid);
+uint8_t port_is_bonding_slave(portid_t slave_pid);
+
+int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
+ enum rte_eth_nb_tcs num_tcs,
+ uint8_t pfc_en);
+int start_port(portid_t pid);
+void stop_port(portid_t pid);
+void close_port(portid_t pid);
+void reset_port(portid_t pid);
+void attach_port(char *identifier);
+void detach_devargs(char *identifier);
+void detach_port_device(portid_t port_id);
+int all_ports_stopped(void);
+int port_is_stopped(portid_t port_id);
+int port_is_started(portid_t port_id);
+void pmd_test_exit(void);
+void fdir_get_infos(portid_t port_id);
+void fdir_set_flex_mask(portid_t port_id,
+ struct rte_eth_fdir_flex_mask *cfg);
+void fdir_set_flex_payload(portid_t port_id,
+ struct rte_eth_flex_payload_cfg *cfg);
+void port_rss_reta_info(portid_t port_id,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t nb_entries);
+
+void set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on);
+
+int set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate);
+int set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate,
+ uint64_t q_msk);
+
+void port_rss_hash_conf_show(portid_t port_id, int show_rss_key);
+void port_rss_hash_key_update(portid_t port_id, char rss_type[],
+ uint8_t *hash_key, uint hash_key_len);
+int rx_queue_id_is_invalid(queueid_t rxq_id);
+int tx_queue_id_is_invalid(queueid_t txq_id);
+void setup_gro(const char *onoff, portid_t port_id);
+void setup_gro_flush_cycles(uint8_t cycles);
+void show_gro(portid_t port_id);
+void setup_gso(const char *mode, portid_t port_id);
+int eth_dev_info_get_print_err(uint16_t port_id,
+ struct rte_eth_dev_info *dev_info);
+void eth_set_promisc_mode(uint16_t port_id, int enable);
+void eth_set_allmulticast_mode(uint16_t port, int enable);
+int eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link);
+int eth_macaddr_get_print_err(uint16_t port_id,
+ struct rte_ether_addr *mac_addr);
+
+/* Functions to display the set of MAC addresses added to a port*/
+void show_macs(portid_t port_id);
+void show_mcast_macs(portid_t port_id);
+
+/* Functions to manage the set of filtered Multicast MAC addresses */
+void mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr);
+void mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr);
+void port_dcb_info_display(portid_t port_id);
+
+uint8_t *open_file(const char *file_path, uint32_t *size);
+int save_file(const char *file_path, uint8_t *buf, uint32_t size);
+int close_file(uint8_t *buf);
+
+void port_queue_region_info_display(portid_t port_id, void *buf);
+
+enum print_warning {
+ ENABLED_WARN = 0,
+ DISABLED_WARN
+};
+int port_id_is_invalid(portid_t port_id, enum print_warning warning);
+void print_valid_ports(void);
+int new_socket_id(unsigned int socket_id);
+
+queueid_t get_allowed_max_nb_rxq(portid_t *pid);
+int check_nb_rxq(queueid_t rxq);
+queueid_t get_allowed_max_nb_txq(portid_t *pid);
+int check_nb_txq(queueid_t txq);
+int check_nb_rxd(queueid_t rxd);
+int check_nb_txd(queueid_t txd);
+queueid_t get_allowed_max_nb_hairpinq(portid_t *pid);
+int check_nb_hairpinq(queueid_t hairpinq);
+
+uint16_t dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+ uint16_t nb_pkts, __rte_unused uint16_t max_pkts,
+ __rte_unused void *user_param);
+
+uint16_t dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+ uint16_t nb_pkts, __rte_unused void *user_param);
+
+void add_rx_dump_callbacks(portid_t portid);
+void remove_rx_dump_callbacks(portid_t portid);
+void add_tx_dump_callbacks(portid_t portid);
+void remove_tx_dump_callbacks(portid_t portid);
+void configure_rxtx_dump_callbacks(uint16_t verbose);
+
+uint16_t tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue,
+ struct rte_mbuf *pkts[], uint16_t nb_pkts,
+ __rte_unused void *user_param);
+void add_tx_md_callback(portid_t portid);
+void remove_tx_md_callback(portid_t portid);
+
+uint16_t tx_pkt_set_dynf(uint16_t port_id, __rte_unused uint16_t queue,
+ struct rte_mbuf *pkts[], uint16_t nb_pkts,
+ __rte_unused void *user_param);
+void add_tx_dynf_callback(portid_t portid);
+void remove_tx_dynf_callback(portid_t portid);
+
+/*
+ * Work-around of a compilation error with ICC on invocations of the
+ * rte_be_to_cpu_16() function.
+ */
+#ifdef __GCC__
+#define RTE_BE_TO_CPU_16(be_16_v) rte_be_to_cpu_16((be_16_v))
+#define RTE_CPU_TO_BE_16(cpu_16_v) rte_cpu_to_be_16((cpu_16_v))
+#else
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+#define RTE_BE_TO_CPU_16(be_16_v) (be_16_v)
+#define RTE_CPU_TO_BE_16(cpu_16_v) (cpu_16_v)
+#else
+#define RTE_BE_TO_CPU_16(be_16_v) \
+ (uint16_t) ((((be_16_v) & 0xFF) << 8) | ((be_16_v) >> 8))
+#define RTE_CPU_TO_BE_16(cpu_16_v) \
+ (uint16_t) ((((cpu_16_v) & 0xFF) << 8) | ((cpu_16_v) >> 8))
+#endif
+#endif /* __GCC__ */
+
+#define TESTPMD_LOG(level, fmt, args...) \
+ rte_log(RTE_LOG_ ## level, testpmd_logtype, "testpmd: " fmt, ## args)
+
+#endif /* _TESTPMD_H_ */
diff --git a/src/spdk/dpdk/app/test-pmd/txonly.c b/src/spdk/dpdk/app/test-pmd/txonly.c
new file mode 100644
index 000000000..076ccaf8f
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/txonly.c
@@ -0,0 +1,361 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_string_fns.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+/* use RFC863 Discard Protocol */
+uint16_t tx_udp_src_port = 9;
+uint16_t tx_udp_dst_port = 9;
+
+/* use RFC5735 / RFC2544 reserved network test addresses */
+uint32_t tx_ip_src_addr = (198U << 24) | (18 << 16) | (0 << 8) | 1;
+uint32_t tx_ip_dst_addr = (198U << 24) | (18 << 16) | (0 << 8) | 2;
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+
+static struct rte_ipv4_hdr pkt_ip_hdr; /**< IP header of transmitted packets. */
+RTE_DEFINE_PER_LCORE(uint8_t, _ip_var); /**< IP address variation */
+static struct rte_udp_hdr pkt_udp_hdr; /**< UDP header of tx packets. */
+
+static void
+copy_buf_to_pkt_segs(void* buf, unsigned len, struct rte_mbuf *pkt,
+ unsigned offset)
+{
+ struct rte_mbuf *seg;
+ void *seg_buf;
+ unsigned copy_len;
+
+ seg = pkt;
+ while (offset >= seg->data_len) {
+ offset -= seg->data_len;
+ seg = seg->next;
+ }
+ copy_len = seg->data_len - offset;
+ seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset);
+ while (len > copy_len) {
+ rte_memcpy(seg_buf, buf, (size_t) copy_len);
+ len -= copy_len;
+ buf = ((char*) buf + copy_len);
+ seg = seg->next;
+ seg_buf = rte_pktmbuf_mtod(seg, char *);
+ copy_len = seg->data_len;
+ }
+ rte_memcpy(seg_buf, buf, (size_t) len);
+}
+
+static inline void
+copy_buf_to_pkt(void* buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
+{
+ if (offset + len <= pkt->data_len) {
+ rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset),
+ buf, (size_t) len);
+ return;
+ }
+ copy_buf_to_pkt_segs(buf, len, pkt, offset);
+}
+
+static void
+setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
+ struct rte_udp_hdr *udp_hdr,
+ uint16_t pkt_data_len)
+{
+ uint16_t *ptr16;
+ uint32_t ip_cksum;
+ uint16_t pkt_len;
+
+ /*
+ * Initialize UDP header.
+ */
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
+ udp_hdr->src_port = rte_cpu_to_be_16(tx_udp_src_port);
+ udp_hdr->dst_port = rte_cpu_to_be_16(tx_udp_dst_port);
+ udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_len);
+ udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+
+ /*
+ * Initialize IP header.
+ */
+ pkt_len = (uint16_t) (pkt_len + sizeof(struct rte_ipv4_hdr));
+ ip_hdr->version_ihl = RTE_IPV4_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = IPPROTO_UDP;
+ ip_hdr->packet_id = 0;
+ ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_len);
+ ip_hdr->src_addr = rte_cpu_to_be_32(tx_ip_src_addr);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(tx_ip_dst_addr);
+
+ /*
+ * Compute IP header checksum.
+ */
+ ptr16 = (unaligned_uint16_t*) ip_hdr;
+ ip_cksum = 0;
+ ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
+ ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
+ ip_cksum += ptr16[4];
+ ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
+ ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
+
+ /*
+ * Reduce 32 bit checksum to 16 bits and complement it.
+ */
+ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
+ (ip_cksum & 0x0000FFFF);
+ if (ip_cksum > 65535)
+ ip_cksum -= 65535;
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ if (ip_cksum == 0)
+ ip_cksum = 0xFFFF;
+ ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+}
+
+static inline bool
+pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
+ struct rte_ether_hdr *eth_hdr, const uint16_t vlan_tci,
+ const uint16_t vlan_tci_outer, const uint64_t ol_flags)
+{
+ struct rte_mbuf *pkt_segs[RTE_MAX_SEGS_PER_PKT];
+ struct rte_mbuf *pkt_seg;
+ uint32_t nb_segs, pkt_len;
+ uint8_t i;
+
+ if (unlikely(tx_pkt_split == TX_PKT_SPLIT_RND))
+ nb_segs = rte_rand() % tx_pkt_nb_segs + 1;
+ else
+ nb_segs = tx_pkt_nb_segs;
+
+ if (nb_segs > 1) {
+ if (rte_mempool_get_bulk(mbp, (void **)pkt_segs, nb_segs - 1))
+ return false;
+ }
+
+ rte_pktmbuf_reset_headroom(pkt);
+ pkt->data_len = tx_pkt_seg_lengths[0];
+ pkt->ol_flags &= EXT_ATTACHED_MBUF;
+ pkt->ol_flags |= ol_flags;
+ pkt->vlan_tci = vlan_tci;
+ pkt->vlan_tci_outer = vlan_tci_outer;
+ pkt->l2_len = sizeof(struct rte_ether_hdr);
+ pkt->l3_len = sizeof(struct rte_ipv4_hdr);
+
+ pkt_len = pkt->data_len;
+ pkt_seg = pkt;
+ for (i = 1; i < nb_segs; i++) {
+ pkt_seg->next = pkt_segs[i - 1];
+ pkt_seg = pkt_seg->next;
+ pkt_seg->data_len = tx_pkt_seg_lengths[i];
+ pkt_len += pkt_seg->data_len;
+ }
+ pkt_seg->next = NULL; /* Last segment of packet. */
+ /*
+ * Copy headers in first packet segment(s).
+ */
+ copy_buf_to_pkt(eth_hdr, sizeof(*eth_hdr), pkt, 0);
+ copy_buf_to_pkt(&pkt_ip_hdr, sizeof(pkt_ip_hdr), pkt,
+ sizeof(struct rte_ether_hdr));
+ if (txonly_multi_flow) {
+ uint8_t ip_var = RTE_PER_LCORE(_ip_var);
+ struct rte_ipv4_hdr *ip_hdr;
+ uint32_t addr;
+
+ ip_hdr = rte_pktmbuf_mtod_offset(pkt,
+ struct rte_ipv4_hdr *,
+ sizeof(struct rte_ether_hdr));
+ /*
+ * Generate multiple flows by varying IP src addr. This
+ * enables packets are well distributed by RSS in
+ * receiver side if any and txonly mode can be a decent
+ * packet generator for developer's quick performance
+ * regression test.
+ */
+ addr = (tx_ip_dst_addr | (ip_var++ << 8)) + rte_lcore_id();
+ ip_hdr->src_addr = rte_cpu_to_be_32(addr);
+ RTE_PER_LCORE(_ip_var) = ip_var;
+ }
+ copy_buf_to_pkt(&pkt_udp_hdr, sizeof(pkt_udp_hdr), pkt,
+ sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr));
+ /*
+ * Complete first mbuf of packet and append it to the
+ * burst of packets to be transmitted.
+ */
+ pkt->nb_segs = nb_segs;
+ pkt->pkt_len = pkt_len;
+
+ return true;
+}
+
+/*
+ * Transmit a burst of multi-segments packets.
+ */
+static void
+pkt_burst_transmit(struct fwd_stream *fs)
+{
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_port *txp;
+ struct rte_mbuf *pkt;
+ struct rte_mempool *mbp;
+ struct rte_ether_hdr eth_hdr;
+ uint16_t nb_tx;
+ uint16_t nb_pkt;
+ uint16_t vlan_tci, vlan_tci_outer;
+ uint32_t retry;
+ uint64_t ol_flags = 0;
+ uint64_t tx_offloads;
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ uint64_t start_tsc;
+ uint64_t end_tsc;
+ uint64_t core_cycles;
+#endif
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ start_tsc = rte_rdtsc();
+#endif
+
+ mbp = current_fwd_lcore()->mbp;
+ txp = &ports[fs->tx_port];
+ tx_offloads = txp->dev_conf.txmode.offloads;
+ vlan_tci = txp->tx_vlan_id;
+ vlan_tci_outer = txp->tx_vlan_id_outer;
+ if (tx_offloads & DEV_TX_OFFLOAD_VLAN_INSERT)
+ ol_flags = PKT_TX_VLAN_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_QINQ_INSERT)
+ ol_flags |= PKT_TX_QINQ_PKT;
+ if (tx_offloads & DEV_TX_OFFLOAD_MACSEC_INSERT)
+ ol_flags |= PKT_TX_MACSEC;
+
+ /*
+ * Initialize Ethernet header.
+ */
+ rte_ether_addr_copy(&peer_eth_addrs[fs->peer_addr], &eth_hdr.d_addr);
+ rte_ether_addr_copy(&ports[fs->tx_port].eth_addr, &eth_hdr.s_addr);
+ eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+
+ if (rte_mempool_get_bulk(mbp, (void **)pkts_burst,
+ nb_pkt_per_burst) == 0) {
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ if (unlikely(!pkt_burst_prepare(pkts_burst[nb_pkt], mbp,
+ &eth_hdr, vlan_tci,
+ vlan_tci_outer,
+ ol_flags))) {
+ rte_mempool_put_bulk(mbp,
+ (void **)&pkts_burst[nb_pkt],
+ nb_pkt_per_burst - nb_pkt);
+ break;
+ }
+ }
+ } else {
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_mbuf_raw_alloc(mbp);
+ if (pkt == NULL)
+ break;
+ if (unlikely(!pkt_burst_prepare(pkt, mbp, &eth_hdr,
+ vlan_tci,
+ vlan_tci_outer,
+ ol_flags))) {
+ rte_pktmbuf_free(pkt);
+ break;
+ }
+ pkts_burst[nb_pkt] = pkt;
+ }
+ }
+
+ if (nb_pkt == 0)
+ return;
+
+ nb_tx = rte_eth_tx_burst(fs->tx_port, fs->tx_queue, pkts_burst, nb_pkt);
+ /*
+ * Retry if necessary
+ */
+ if (unlikely(nb_tx < nb_pkt) && fs->retry_enabled) {
+ retry = 0;
+ while (nb_tx < nb_pkt && retry++ < burst_tx_retry_num) {
+ rte_delay_us(burst_tx_delay_time);
+ nb_tx += rte_eth_tx_burst(fs->tx_port, fs->tx_queue,
+ &pkts_burst[nb_tx], nb_pkt - nb_tx);
+ }
+ }
+ fs->tx_packets += nb_tx;
+
+ if (txonly_multi_flow)
+ RTE_PER_LCORE(_ip_var) -= nb_pkt - nb_tx;
+
+#ifdef RTE_TEST_PMD_RECORD_BURST_STATS
+ fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
+#endif
+ if (unlikely(nb_tx < nb_pkt)) {
+ if (verbose_level > 0 && fs->fwd_dropped == 0)
+ printf("port %d tx_queue %d - drop "
+ "(nb_pkt:%u - nb_tx:%u)=%u packets\n",
+ fs->tx_port, fs->tx_queue,
+ (unsigned) nb_pkt, (unsigned) nb_tx,
+ (unsigned) (nb_pkt - nb_tx));
+ fs->fwd_dropped += (nb_pkt - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_pkt);
+ }
+
+#ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
+ end_tsc = rte_rdtsc();
+ core_cycles = (end_tsc - start_tsc);
+ fs->core_cycles = (uint64_t) (fs->core_cycles + core_cycles);
+#endif
+}
+
+static void
+tx_only_begin(__rte_unused portid_t pi)
+{
+ uint16_t pkt_data_len;
+
+ pkt_data_len = (uint16_t) (tx_pkt_length - (
+ sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr) +
+ sizeof(struct rte_udp_hdr)));
+ setup_pkt_udp_ip_headers(&pkt_ip_hdr, &pkt_udp_hdr, pkt_data_len);
+}
+
+struct fwd_engine tx_only_engine = {
+ .fwd_mode_name = "txonly",
+ .port_fwd_begin = tx_only_begin,
+ .port_fwd_end = NULL,
+ .packet_fwd = pkt_burst_transmit,
+};
diff --git a/src/spdk/dpdk/app/test-pmd/util.c b/src/spdk/dpdk/app/test-pmd/util.c
new file mode 100644
index 000000000..8488fa1a8
--- /dev/null
+++ b/src/spdk/dpdk/app/test-pmd/util.c
@@ -0,0 +1,377 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ * Copyright 2018 Mellanox Technologies, Ltd
+ */
+
+#include <stdio.h>
+
+#include <rte_net.h>
+#include <rte_mbuf.h>
+#include <rte_ether.h>
+#include <rte_vxlan.h>
+#include <rte_ethdev.h>
+#include <rte_flow.h>
+
+#include "testpmd.h"
+
+static inline void
+print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", what, buf);
+}
+
+static inline void
+dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+ uint16_t nb_pkts, int is_rx)
+{
+ struct rte_mbuf *mb;
+ const struct rte_ether_hdr *eth_hdr;
+ struct rte_ether_hdr _eth_hdr;
+ uint16_t eth_type;
+ uint64_t ol_flags;
+ uint16_t i, packet_type;
+ uint16_t is_encapsulation;
+ char buf[256];
+ struct rte_net_hdr_lens hdr_lens;
+ uint32_t sw_packet_type;
+ uint16_t udp_port;
+ uint32_t vx_vni;
+ const char *reason;
+ int dynf_index;
+
+ if (!nb_pkts)
+ return;
+ printf("port %u/queue %u: %s %u packets\n",
+ port_id, queue,
+ is_rx ? "received" : "sent",
+ (unsigned int) nb_pkts);
+ for (i = 0; i < nb_pkts; i++) {
+ mb = pkts[i];
+ eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr);
+ eth_type = RTE_BE_TO_CPU_16(eth_hdr->ether_type);
+ ol_flags = mb->ol_flags;
+ packet_type = mb->packet_type;
+ is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
+
+ print_ether_addr(" src=", &eth_hdr->s_addr);
+ print_ether_addr(" - dst=", &eth_hdr->d_addr);
+ printf(" - type=0x%04x - length=%u - nb_segs=%d",
+ eth_type, (unsigned int) mb->pkt_len,
+ (int)mb->nb_segs);
+ if (ol_flags & PKT_RX_RSS_HASH) {
+ printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss);
+ printf(" - RSS queue=0x%x", (unsigned int) queue);
+ }
+ if (ol_flags & PKT_RX_FDIR) {
+ printf(" - FDIR matched ");
+ if (ol_flags & PKT_RX_FDIR_ID)
+ printf("ID=0x%x",
+ mb->hash.fdir.hi);
+ else if (ol_flags & PKT_RX_FDIR_FLX)
+ printf("flex bytes=0x%08x %08x",
+ mb->hash.fdir.hi, mb->hash.fdir.lo);
+ else
+ printf("hash=0x%x ID=0x%x ",
+ mb->hash.fdir.hash, mb->hash.fdir.id);
+ }
+ if (ol_flags & PKT_RX_TIMESTAMP)
+ printf(" - timestamp %"PRIu64" ", mb->timestamp);
+ if (ol_flags & PKT_RX_QINQ)
+ printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
+ mb->vlan_tci, mb->vlan_tci_outer);
+ else if (ol_flags & PKT_RX_VLAN)
+ printf(" - VLAN tci=0x%x", mb->vlan_tci);
+ if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA))
+ printf(" - Tx metadata: 0x%x",
+ *RTE_FLOW_DYNF_METADATA(mb));
+ if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA))
+ printf(" - Rx metadata: 0x%x",
+ *RTE_FLOW_DYNF_METADATA(mb));
+ for (dynf_index = 0; dynf_index < 64; dynf_index++) {
+ if (dynf_names[dynf_index][0] != '\0')
+ printf(" - dynf %s: %d",
+ dynf_names[dynf_index],
+ !!(ol_flags & (1UL << dynf_index)));
+ }
+ if (mb->packet_type) {
+ rte_get_ptype_name(mb->packet_type, buf, sizeof(buf));
+ printf(" - hw ptype: %s", buf);
+ }
+ sw_packet_type = rte_net_get_ptype(mb, &hdr_lens,
+ RTE_PTYPE_ALL_MASK);
+ rte_get_ptype_name(sw_packet_type, buf, sizeof(buf));
+ printf(" - sw ptype: %s", buf);
+ if (sw_packet_type & RTE_PTYPE_L2_MASK)
+ printf(" - l2_len=%d", hdr_lens.l2_len);
+ if (sw_packet_type & RTE_PTYPE_L3_MASK)
+ printf(" - l3_len=%d", hdr_lens.l3_len);
+ if (sw_packet_type & RTE_PTYPE_L4_MASK)
+ printf(" - l4_len=%d", hdr_lens.l4_len);
+ if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK)
+ printf(" - tunnel_len=%d", hdr_lens.tunnel_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK)
+ printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK)
+ printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len);
+ if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK)
+ printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len);
+ if (is_encapsulation) {
+ struct rte_ipv4_hdr *ipv4_hdr;
+ struct rte_ipv6_hdr *ipv6_hdr;
+ struct rte_udp_hdr *udp_hdr;
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+ uint8_t l4_proto;
+ struct rte_vxlan_hdr *vxlan_hdr;
+
+ l2_len = sizeof(struct rte_ether_hdr);
+
+ /* Do not support ipv4 option field */
+ if (RTE_ETH_IS_IPV4_HDR(packet_type)) {
+ l3_len = sizeof(struct rte_ipv4_hdr);
+ ipv4_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct rte_ipv4_hdr *,
+ l2_len);
+ l4_proto = ipv4_hdr->next_proto_id;
+ } else {
+ l3_len = sizeof(struct rte_ipv6_hdr);
+ ipv6_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct rte_ipv6_hdr *,
+ l2_len);
+ l4_proto = ipv6_hdr->proto;
+ }
+ if (l4_proto == IPPROTO_UDP) {
+ udp_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct rte_udp_hdr *,
+ l2_len + l3_len);
+ l4_len = sizeof(struct rte_udp_hdr);
+ vxlan_hdr = rte_pktmbuf_mtod_offset(mb,
+ struct rte_vxlan_hdr *,
+ l2_len + l3_len + l4_len);
+ udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port);
+ vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni);
+ printf(" - VXLAN packet: packet type =%d, "
+ "Destination UDP port =%d, VNI = %d",
+ packet_type, udp_port, vx_vni >> 8);
+ }
+ }
+ printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send",
+ (unsigned int) queue);
+ printf("\n");
+ rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf));
+ printf(" ol_flags: %s\n", buf);
+ if (rte_mbuf_check(mb, 1, &reason) < 0)
+ printf("INVALID mbuf: %s\n", reason);
+ }
+}
+
+uint16_t
+dump_rx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+ uint16_t nb_pkts, __rte_unused uint16_t max_pkts,
+ __rte_unused void *user_param)
+{
+ dump_pkt_burst(port_id, queue, pkts, nb_pkts, 1);
+ return nb_pkts;
+}
+
+uint16_t
+dump_tx_pkts(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
+ uint16_t nb_pkts, __rte_unused void *user_param)
+{
+ dump_pkt_burst(port_id, queue, pkts, nb_pkts, 0);
+ return nb_pkts;
+}
+
+uint16_t
+tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue,
+ struct rte_mbuf *pkts[], uint16_t nb_pkts,
+ __rte_unused void *user_param)
+{
+ uint16_t i = 0;
+
+ /*
+ * Add metadata value to every Tx packet,
+ * and set ol_flags accordingly.
+ */
+ if (rte_flow_dynf_metadata_avail())
+ for (i = 0; i < nb_pkts; i++) {
+ *RTE_FLOW_DYNF_METADATA(pkts[i]) =
+ ports[port_id].tx_metadata;
+ pkts[i]->ol_flags |= PKT_TX_DYNF_METADATA;
+ }
+ return nb_pkts;
+}
+
+void
+add_tx_md_callback(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (!ports[portid].tx_set_md_cb[queue])
+ ports[portid].tx_set_md_cb[queue] =
+ rte_eth_add_tx_callback(portid, queue,
+ tx_pkt_set_md, NULL);
+}
+
+void
+remove_tx_md_callback(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (ports[portid].tx_set_md_cb[queue]) {
+ rte_eth_remove_tx_callback(portid, queue,
+ ports[portid].tx_set_md_cb[queue]);
+ ports[portid].tx_set_md_cb[queue] = NULL;
+ }
+}
+
+uint16_t
+tx_pkt_set_dynf(uint16_t port_id, __rte_unused uint16_t queue,
+ struct rte_mbuf *pkts[], uint16_t nb_pkts,
+ __rte_unused void *user_param)
+{
+ uint16_t i = 0;
+
+ if (ports[port_id].mbuf_dynf)
+ for (i = 0; i < nb_pkts; i++)
+ pkts[i]->ol_flags |= ports[port_id].mbuf_dynf;
+ return nb_pkts;
+}
+
+void
+add_tx_dynf_callback(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (!ports[portid].tx_set_dynf_cb[queue])
+ ports[portid].tx_set_dynf_cb[queue] =
+ rte_eth_add_tx_callback(portid, queue,
+ tx_pkt_set_dynf, NULL);
+}
+
+void
+remove_tx_dynf_callback(portid_t portid)
+{
+ struct rte_eth_dev_info dev_info;
+ uint16_t queue;
+ int ret;
+
+ if (port_id_is_invalid(portid, ENABLED_WARN))
+ return;
+
+ ret = eth_dev_info_get_print_err(portid, &dev_info);
+ if (ret != 0)
+ return;
+
+ for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
+ if (ports[portid].tx_set_dynf_cb[queue]) {
+ rte_eth_remove_tx_callback(portid, queue,
+ ports[portid].tx_set_dynf_cb[queue]);
+ ports[portid].tx_set_dynf_cb[queue] = NULL;
+ }
+}
+
+int
+eth_dev_info_get_print_err(uint16_t port_id,
+ struct rte_eth_dev_info *dev_info)
+{
+ int ret;
+
+ ret = rte_eth_dev_info_get(port_id, dev_info);
+ if (ret != 0)
+ printf("Error during getting device (port %u) info: %s\n",
+ port_id, strerror(-ret));
+
+ return ret;
+}
+
+void
+eth_set_promisc_mode(uint16_t port, int enable)
+{
+ int ret;
+
+ if (enable)
+ ret = rte_eth_promiscuous_enable(port);
+ else
+ ret = rte_eth_promiscuous_disable(port);
+
+ if (ret != 0)
+ printf("Error during %s promiscuous mode for port %u: %s\n",
+ enable ? "enabling" : "disabling",
+ port, rte_strerror(-ret));
+}
+
+void
+eth_set_allmulticast_mode(uint16_t port, int enable)
+{
+ int ret;
+
+ if (enable)
+ ret = rte_eth_allmulticast_enable(port);
+ else
+ ret = rte_eth_allmulticast_disable(port);
+
+ if (ret != 0)
+ printf("Error during %s all-multicast mode for port %u: %s\n",
+ enable ? "enabling" : "disabling",
+ port, rte_strerror(-ret));
+}
+
+int
+eth_link_get_nowait_print_err(uint16_t port_id, struct rte_eth_link *link)
+{
+ int ret;
+
+ ret = rte_eth_link_get_nowait(port_id, link);
+ if (ret < 0)
+ printf("Device (port %u) link get (without wait) failed: %s\n",
+ port_id, rte_strerror(-ret));
+
+ return ret;
+}
+
+int
+eth_macaddr_get_print_err(uint16_t port_id, struct rte_ether_addr *mac_addr)
+{
+ int ret;
+
+ ret = rte_eth_macaddr_get(port_id, mac_addr);
+ if (ret != 0)
+ printf("Error getting device (port %u) mac address: %s\n",
+ port_id, rte_strerror(-ret));
+
+ return ret;
+}
diff --git a/src/spdk/dpdk/app/test-sad/Makefile b/src/spdk/dpdk/app/test-sad/Makefile
new file mode 100644
index 000000000..9b5a7ddc6
--- /dev/null
+++ b/src/spdk/dpdk/app/test-sad/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
+
+APP = testsad
+
+CFLAGS += $(WERROR_FLAGS)
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test-sad/main.c b/src/spdk/dpdk/app/test-sad/main.c
new file mode 100644
index 000000000..b01e84c57
--- /dev/null
+++ b/src/spdk/dpdk/app/test-sad/main.c
@@ -0,0 +1,671 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <rte_string_fns.h>
+#include <rte_ipsec_sad.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_ip.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+
+#define PRINT_USAGE_START "%s [EAL options] --\n"
+
+#define GET_CB_FIELD(in, fd, base, lim, dlm) do { \
+ unsigned long val; \
+ char *end_fld; \
+ errno = 0; \
+ val = strtoul((in), &end_fld, (base)); \
+ if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \
+ return -EINVAL; \
+ (fd) = (typeof(fd))val; \
+ (in) = end_fld + 1; \
+} while (0)
+
+#define DEF_RULE_NUM 0x10000
+#define DEF_TUPLES_NUM 0x100000
+#define BURST_SZ_MAX 64
+
+static struct {
+ const char *prgname;
+ const char *rules_file;
+ const char *tuples_file;
+ uint32_t nb_rules;
+ uint32_t nb_tuples;
+ uint32_t nb_rules_32;
+ uint32_t nb_rules_64;
+ uint32_t nb_rules_96;
+ uint32_t nb_tuples_rnd;
+ uint32_t burst_sz;
+ uint8_t fract_32;
+ uint8_t fract_64;
+ uint8_t fract_96;
+ uint8_t fract_rnd_tuples;
+ int ipv6;
+ int verbose;
+ int parallel_lookup;
+ int concurrent_rw;
+} config = {
+ .rules_file = NULL,
+ .tuples_file = NULL,
+ .nb_rules = DEF_RULE_NUM,
+ .nb_tuples = DEF_TUPLES_NUM,
+ .nb_rules_32 = 0,
+ .nb_rules_64 = 0,
+ .nb_rules_96 = 0,
+ .nb_tuples_rnd = 0,
+ .burst_sz = BURST_SZ_MAX,
+ .fract_32 = 90,
+ .fract_64 = 9,
+ .fract_96 = 1,
+ .fract_rnd_tuples = 0,
+ .ipv6 = 0,
+ .verbose = 0,
+ .parallel_lookup = 0,
+ .concurrent_rw = 0
+};
+
+enum {
+ CB_RULE_SPI,
+ CB_RULE_DIP,
+ CB_RULE_SIP,
+ CB_RULE_LEN,
+ CB_RULE_NUM,
+};
+
+static char line[LINE_MAX];
+struct rule {
+ union rte_ipsec_sad_key tuple;
+ int rule_type;
+};
+
+static struct rule *rules_tbl;
+static struct rule *tuples_tbl;
+
+static int
+parse_distrib(const char *in)
+{
+ int a, b, c;
+
+ GET_CB_FIELD(in, a, 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in, b, 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in, c, 0, UINT8_MAX, 0);
+
+ if ((a + b + c) != 100)
+ return -EINVAL;
+
+ config.fract_32 = a;
+ config.fract_64 = b;
+ config.fract_96 = c;
+
+ return 0;
+}
+
+static void
+print_config(void)
+{
+ fprintf(stdout,
+ "Rules total: %u\n"
+ "Configured rules distribution SPI/SPI_DIP/SIP_DIP_SIP:"
+ "%u/%u/%u\n"
+ "SPI only rules: %u\n"
+ "SPI_DIP rules: %u\n"
+ "SPI_DIP_SIP rules: %u\n"
+ "Lookup tuples: %u\n"
+ "Lookup burst size %u\n"
+ "Configured fraction of random tuples: %u\n"
+ "Random lookup tuples: %u\n",
+ config.nb_rules, config.fract_32, config.fract_64,
+ config.fract_96, config.nb_rules_32, config.nb_rules_64,
+ config.nb_rules_96, config.nb_tuples, config.burst_sz,
+ config.fract_rnd_tuples, config.nb_tuples_rnd);
+}
+
+static void
+print_usage(void)
+{
+ fprintf(stdout,
+ PRINT_USAGE_START
+ "[-f <rules file>]\n"
+ "[-t <tuples file for lookup>]\n"
+ "[-n <rules number (if -f is not specified)>]\n"
+ "[-l <lookup tuples number (if -t is not specified)>]\n"
+ "[-6 <ipv6 tests>]\n"
+ "[-d <\"/\" separated rules length distribution"
+ "(if -f is not specified)>]\n"
+ "[-r <random tuples fraction to lookup"
+ "(if -t is not specified)>]\n"
+ "[-b <lookup burst size: 1-64 >]\n"
+ "[-v <verbose, print results on lookup>]\n"
+ "[-p <parallel lookup on all available cores>]\n"
+ "[-c <init sad supporting read/write concurrency>]\n",
+ config.prgname);
+
+}
+
+static int
+get_str_num(FILE *f, int num)
+{
+ int n_lines = 0;
+
+ if (f != NULL) {
+ while (fgets(line, sizeof(line), f) != NULL)
+ n_lines++;
+ rewind(f);
+ } else {
+ n_lines = num;
+ }
+ return n_lines;
+}
+
+static int
+parse_file(FILE *f, struct rule *tbl, int rule_tbl)
+{
+ int ret, i, j = 0;
+ char *s, *sp, *in[CB_RULE_NUM];
+ static const char *dlm = " \t\n";
+ int string_tok_nb = RTE_DIM(in);
+
+ string_tok_nb -= (rule_tbl == 0) ? 1 : 0;
+ while (fgets(line, sizeof(line), f) != NULL) {
+ s = line;
+ for (i = 0; i != string_tok_nb; i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+ GET_CB_FIELD(in[CB_RULE_SPI], tbl[j].tuple.v4.spi, 0,
+ UINT32_MAX, 0);
+
+ if (config.ipv6)
+ ret = inet_pton(AF_INET6, in[CB_RULE_DIP],
+ &tbl[j].tuple.v6.dip);
+ else
+ ret = inet_pton(AF_INET, in[CB_RULE_DIP],
+ &tbl[j].tuple.v4.dip);
+ if (ret != 1)
+ return -EINVAL;
+ if (config.ipv6)
+ ret = inet_pton(AF_INET6, in[CB_RULE_SIP],
+ &tbl[j].tuple.v6.sip);
+ else
+ ret = inet_pton(AF_INET, in[CB_RULE_SIP],
+ &tbl[j].tuple.v4.sip);
+ if (ret != 1)
+ return -EINVAL;
+ if ((rule_tbl) && (in[CB_RULE_LEN] != NULL)) {
+ if (strcmp(in[CB_RULE_LEN], "SPI_DIP_SIP") == 0) {
+ tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP;
+ config.nb_rules_96++;
+ } else if (strcmp(in[CB_RULE_LEN], "SPI_DIP") == 0) {
+ tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP;
+ config.nb_rules_64++;
+ } else if (strcmp(in[CB_RULE_LEN], "SPI") == 0) {
+ tbl[j].rule_type = RTE_IPSEC_SAD_SPI_ONLY;
+ config.nb_rules_32++;
+ } else {
+ return -EINVAL;
+ }
+ }
+ j++;
+ }
+ return 0;
+}
+
+static uint64_t
+get_rnd_rng(uint64_t l, uint64_t u)
+{
+ if (l == u)
+ return l;
+ else
+ return (rte_rand() % (u - l) + l);
+}
+
+static void
+get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl)
+{
+ unsigned int i, j, rnd;
+ int rule_type;
+ double edge = 0;
+ double step;
+
+ step = (double)UINT32_MAX / nb_rules;
+ for (i = 0; i < nb_rules; i++, edge += step) {
+ rnd = rte_rand() % 100;
+ if (rule_tbl) {
+ tbl[i].tuple.v4.spi = get_rnd_rng((uint64_t)edge,
+ (uint64_t)(edge + step));
+ if (config.ipv6) {
+ for (j = 0; j < 16; j++) {
+ tbl[i].tuple.v6.dip[j] = rte_rand();
+ tbl[i].tuple.v6.sip[j] = rte_rand();
+ }
+ } else {
+ tbl[i].tuple.v4.dip = rte_rand();
+ tbl[i].tuple.v4.sip = rte_rand();
+ }
+ if (rnd >= (100UL - config.fract_32)) {
+ rule_type = RTE_IPSEC_SAD_SPI_ONLY;
+ config.nb_rules_32++;
+ } else if (rnd >= (100UL - (config.fract_32 +
+ config.fract_64))) {
+ rule_type = RTE_IPSEC_SAD_SPI_DIP;
+ config.nb_rules_64++;
+ } else {
+ rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP;
+ config.nb_rules_96++;
+ }
+ tbl[i].rule_type = rule_type;
+ } else {
+ if (rnd >= 100UL - config.fract_rnd_tuples) {
+ tbl[i].tuple.v4.spi =
+ get_rnd_rng((uint64_t)edge,
+ (uint64_t)(edge + step));
+ if (config.ipv6) {
+ for (j = 0; j < 16; j++) {
+ tbl[i].tuple.v6.dip[j] =
+ rte_rand();
+ tbl[i].tuple.v6.sip[j] =
+ rte_rand();
+ }
+ } else {
+ tbl[i].tuple.v4.dip = rte_rand();
+ tbl[i].tuple.v4.sip = rte_rand();
+ }
+ config.nb_tuples_rnd++;
+ } else {
+ tbl[i].tuple.v4.spi = rules_tbl[i %
+ config.nb_rules].tuple.v4.spi;
+ if (config.ipv6) {
+ int r_idx = i % config.nb_rules;
+ memcpy(tbl[i].tuple.v6.dip,
+ rules_tbl[r_idx].tuple.v6.dip,
+ sizeof(tbl[i].tuple.v6.dip));
+ memcpy(tbl[i].tuple.v6.sip,
+ rules_tbl[r_idx].tuple.v6.sip,
+ sizeof(tbl[i].tuple.v6.sip));
+ } else {
+ tbl[i].tuple.v4.dip = rules_tbl[i %
+ config.nb_rules].tuple.v4.dip;
+ tbl[i].tuple.v4.sip = rules_tbl[i %
+ config.nb_rules].tuple.v4.sip;
+ }
+ }
+ }
+ }
+}
+
+static void
+tbl_init(struct rule **tbl, uint32_t *n_entries,
+ const char *file_name, int rule_tbl)
+{
+ FILE *f = NULL;
+ int ret;
+ const char *rules = "rules";
+ const char *tuples = "tuples";
+
+ if (file_name != NULL) {
+ f = fopen(file_name, "r");
+ if (f == NULL)
+ rte_exit(-EINVAL, "failed to open file: %s\n",
+ file_name);
+ }
+
+ printf("init %s table...", (rule_tbl) ? rules : tuples);
+ *n_entries = get_str_num(f, *n_entries);
+ printf("%d entries\n", *n_entries);
+ *tbl = rte_zmalloc(NULL, sizeof(struct rule) * *n_entries,
+ RTE_CACHE_LINE_SIZE);
+ if (*tbl == NULL)
+ rte_exit(-ENOMEM, "failed to allocate tbl\n");
+
+ if (f != NULL) {
+ printf("parse file %s\n", file_name);
+ ret = parse_file(f, *tbl, rule_tbl);
+ if (ret != 0)
+ rte_exit(-EINVAL, "failed to parse file %s\n"
+ "rules file must be: "
+ "<uint32_t: spi> <space> "
+ "<ip_addr: dip> <space> "
+ "<ip_addr: sip> <space> "
+ "<string: SPI|SPI_DIP|SIP_DIP_SIP>\n"
+ "tuples file must be: "
+ "<uint32_t: spi> <space> "
+ "<ip_addr: dip> <space> "
+ "<ip_addr: sip>\n",
+ file_name);
+ } else {
+ printf("generate random values in %s table\n",
+ (rule_tbl) ? rules : tuples);
+ get_random_rules(*tbl, *n_entries, rule_tbl);
+ }
+ if (f != NULL)
+ fclose(f);
+}
+
+static void
+parse_opts(int argc, char **argv)
+{
+ int opt, ret;
+ char *endptr;
+
+ while ((opt = getopt(argc, argv, "f:t:n:d:l:r:6b:vpc")) != -1) {
+ switch (opt) {
+ case 'f':
+ config.rules_file = optarg;
+ break;
+ case 't':
+ config.tuples_file = optarg;
+ break;
+ case 'n':
+ errno = 0;
+ config.nb_rules = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.nb_rules == 0) ||
+ (endptr[0] != 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -n\n");
+ }
+ break;
+ case 'd':
+ ret = parse_distrib(optarg);
+ if (ret != 0) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -d\n");
+ }
+ break;
+ case 'b':
+ errno = 0;
+ config.burst_sz = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.burst_sz == 0) ||
+ (config.burst_sz > BURST_SZ_MAX) ||
+ (endptr[0] != 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -b\n");
+ }
+ break;
+ case 'l':
+ errno = 0;
+ config.nb_tuples = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.nb_tuples == 0) ||
+ (endptr[0] != 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -l\n");
+ }
+ break;
+ case 'r':
+ errno = 0;
+ config.fract_rnd_tuples = strtoul(optarg, &endptr, 10);
+ if ((errno != 0) || (config.fract_rnd_tuples == 0) ||
+ (config.fract_rnd_tuples >= 100) ||
+ (endptr[0] != 0)) {
+ print_usage();
+ rte_exit(-EINVAL, "Invalid option -r\n");
+ }
+ break;
+ case '6':
+ config.ipv6 = 1;
+ break;
+ case 'v':
+ config.verbose = 1;
+ break;
+ case 'p':
+ config.parallel_lookup = 1;
+ break;
+ case 'c':
+ config.concurrent_rw = 1;
+ break;
+ default:
+ print_usage();
+ rte_exit(-EINVAL, "Invalid options\n");
+ }
+ }
+}
+
+static void
+print_addr(int af, const void *addr)
+{
+ char str[INET6_ADDRSTRLEN];
+ const char *ret;
+
+ ret = inet_ntop(af, addr, str, sizeof(str));
+ if (ret != NULL)
+ printf("%s", str);
+}
+
+static void
+print_tuple(int af, uint32_t spi, const void *dip, const void *sip)
+{
+
+ printf("<SPI: %u DIP: ", spi);
+ print_addr(af, dip);
+ printf(" SIP: ");
+ print_addr(af, sip);
+ printf(">");
+}
+
+static void
+print_result(const union rte_ipsec_sad_key *key, void *res)
+{
+ struct rule *rule = res;
+ const struct rte_ipsec_sadv4_key *v4;
+ const struct rte_ipsec_sadv6_key *v6;
+ const char *spi_only = "SPI_ONLY";
+ const char *spi_dip = "SPI_DIP";
+ const char *spi_dip_sip = "SPI_DIP_SIP";
+ const char *rule_type;
+ const void *dip, *sip;
+ uint32_t spi;
+ int af;
+
+ af = (config.ipv6) ? AF_INET6 : AF_INET;
+ v4 = &key->v4;
+ v6 = &key->v6;
+ spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
+ dip = (config.ipv6 == 0) ? &v4->dip : (const void *)v6->dip;
+ sip = (config.ipv6 == 0) ? &v4->sip : (const void *)v6->sip;
+
+ if (res == NULL) {
+ printf("TUPLE: ");
+ print_tuple(af, spi, dip, sip);
+ printf(" not found\n");
+ return;
+ }
+
+ switch (rule->rule_type) {
+ case RTE_IPSEC_SAD_SPI_ONLY:
+ rule_type = spi_only;
+ break;
+ case RTE_IPSEC_SAD_SPI_DIP:
+ rule_type = spi_dip;
+ break;
+ case RTE_IPSEC_SAD_SPI_DIP_SIP:
+ rule_type = spi_dip_sip;
+ break;
+ default:
+ return;
+ }
+
+ print_tuple(af, spi, dip, sip);
+ v4 = &rule->tuple.v4;
+ v6 = &rule->tuple.v6;
+ spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
+ dip = (config.ipv6 == 0) ? &v4->dip : (const void *)v6->dip;
+ sip = (config.ipv6 == 0) ? &v4->sip : (const void *)v6->sip;
+ printf("\n\tpoints to RULE ID %zu ",
+ RTE_PTR_DIFF(res, rules_tbl)/sizeof(struct rule));
+ print_tuple(af, spi, dip, sip);
+ printf(" %s\n", rule_type);
+}
+
+static int
+lookup(void *arg)
+{
+ int ret;
+ unsigned int i, j;
+ const union rte_ipsec_sad_key *keys[BURST_SZ_MAX];
+ void *vals[BURST_SZ_MAX];
+ uint64_t start, acc = 0;
+ uint32_t burst_sz;
+ struct rte_ipsec_sad *sad = arg;
+
+ if (config.nb_tuples == 0)
+ return 0;
+
+ burst_sz = RTE_MIN(config.burst_sz, config.nb_tuples);
+ for (i = 0; i < config.nb_tuples; i += burst_sz) {
+ for (j = 0; j < burst_sz; j++)
+ keys[j] = (union rte_ipsec_sad_key *)
+ (&tuples_tbl[i + j].tuple);
+ start = rte_rdtsc_precise();
+ ret = rte_ipsec_sad_lookup(sad, keys, vals, burst_sz);
+ acc += rte_rdtsc_precise() - start;
+ if (ret < 0)
+ rte_exit(-EINVAL, "Lookup failed\n");
+ if (config.verbose) {
+ for (j = 0; j < burst_sz; j++)
+ print_result(keys[j], vals[j]);
+ }
+ }
+ acc = (acc == 0) ? UINT64_MAX : acc;
+ printf("Average lookup cycles %.2Lf, lookups/sec: %.2Lf\n",
+ (long double)acc / config.nb_tuples,
+ (long double)config.nb_tuples * rte_get_tsc_hz() / acc);
+
+ return 0;
+}
+
+static void
+add_rules(struct rte_ipsec_sad *sad, uint32_t fract)
+{
+ int32_t ret;
+ uint32_t i, j, f, fn, n;
+ uint64_t start, tm[fract + 1];
+ uint32_t nm[fract + 1];
+
+ f = (config.nb_rules > fract) ? config.nb_rules / fract : 1;
+
+ for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) {
+
+ fn = n + f;
+ fn = fn > config.nb_rules ? config.nb_rules : fn;
+
+ start = rte_rdtsc_precise();
+ for (i = n; i != fn; i++) {
+ ret = rte_ipsec_sad_add(sad,
+ &rules_tbl[i].tuple,
+ rules_tbl[i].rule_type, &rules_tbl[i]);
+ if (ret != 0)
+ rte_exit(ret, "%s failed @ %u-th rule\n",
+ __func__, i);
+ }
+ tm[j] = rte_rdtsc_precise() - start;
+ nm[j] = fn - n;
+ }
+
+ for (i = 0; i != j; i++)
+ printf("ADD %u rules, %.2Lf cycles/rule, %.2Lf ADD/sec\n",
+ nm[i], (long double)tm[i] / nm[i],
+ (long double)nm[i] * rte_get_tsc_hz() / tm[i]);
+}
+
+static void
+del_rules(struct rte_ipsec_sad *sad, uint32_t fract)
+{
+ int32_t ret;
+ uint32_t i, j, f, fn, n;
+ uint64_t start, tm[fract + 1];
+ uint32_t nm[fract + 1];
+
+ f = (config.nb_rules > fract) ? config.nb_rules / fract : 1;
+
+ for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) {
+
+ fn = n + f;
+ fn = fn > config.nb_rules ? config.nb_rules : fn;
+
+ start = rte_rdtsc_precise();
+ for (i = n; i != fn; i++) {
+ ret = rte_ipsec_sad_del(sad,
+ &rules_tbl[i].tuple,
+ rules_tbl[i].rule_type);
+ if (ret != 0 && ret != -ENOENT)
+ rte_exit(ret, "%s failed @ %u-th rule\n",
+ __func__, i);
+ }
+ tm[j] = rte_rdtsc_precise() - start;
+ nm[j] = fn - n;
+ }
+
+ for (i = 0; i != j; i++)
+ printf("DEL %u rules, %.2Lf cycles/rule, %.2Lf DEL/sec\n",
+ nm[i], (long double)tm[i] / nm[i],
+ (long double)nm[i] * rte_get_tsc_hz() / tm[i]);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret;
+ struct rte_ipsec_sad *sad;
+ struct rte_ipsec_sad_conf conf;
+ unsigned int lcore_id;
+
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_panic("Cannot init EAL\n");
+
+ argc -= ret;
+ argv += ret;
+
+ config.prgname = argv[0];
+
+ parse_opts(argc, argv);
+ tbl_init(&rules_tbl, &config.nb_rules, config.rules_file, 1);
+ tbl_init(&tuples_tbl, &config.nb_tuples, config.tuples_file, 0);
+ if (config.rules_file != NULL) {
+ config.fract_32 = (100 * config.nb_rules_32) / config.nb_rules;
+ config.fract_64 = (100 * config.nb_rules_64) / config.nb_rules;
+ config.fract_96 = (100 * config.nb_rules_96) / config.nb_rules;
+ }
+ if (config.tuples_file != NULL) {
+ config.fract_rnd_tuples = 0;
+ config.nb_tuples_rnd = 0;
+ }
+ conf.socket_id = -1;
+ conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = config.nb_rules_32 * 5 / 4;
+ conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = config.nb_rules_64 * 5 / 4;
+ conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = config.nb_rules_96 * 5 / 4;
+ if (config.ipv6)
+ conf.flags |= RTE_IPSEC_SAD_FLAG_IPV6;
+ if (config.concurrent_rw)
+ conf.flags |= RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY;
+ sad = rte_ipsec_sad_create("test", &conf);
+ if (sad == NULL)
+ rte_exit(-rte_errno, "can not allocate SAD table\n");
+
+ print_config();
+
+ add_rules(sad, 10);
+ if (config.parallel_lookup)
+ rte_eal_mp_remote_launch(lookup, sad, SKIP_MASTER);
+
+ lookup(sad);
+ if (config.parallel_lookup)
+ RTE_LCORE_FOREACH_SLAVE(lcore_id)
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ return -1;
+
+ del_rules(sad, 10);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test-sad/meson.build b/src/spdk/dpdk/app/test-sad/meson.build
new file mode 100644
index 000000000..db15b658d
--- /dev/null
+++ b/src/spdk/dpdk/app/test-sad/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+sources = files('main.c')
+deps += ['ipsec', 'net']
diff --git a/src/spdk/dpdk/app/test/Makefile b/src/spdk/dpdk/app/test/Makefile
new file mode 100644
index 000000000..5b119aa61
--- /dev/null
+++ b/src/spdk/dpdk/app/test/Makefile
@@ -0,0 +1,307 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2017 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+ifeq ($(CONFIG_RTE_APP_TEST),y)
+
+# default rule
+all:
+
+# Define an externally linked resource. A linked resource is an arbitrary
+# file that is linked into the test binary. The application refers to this
+# resource by name. The linked generates identifiers beg_<name> and end_<name>
+# for referencing by the C code.
+#
+# Parameters: <unique name>, <file to be linked>
+define linked_resource
+SRCS-y += $(1).res.o
+$(1).res.o: $(2)
+ @ echo ' MKRES $$@'
+ $Q [ "$$(<D)" = . ] || ln -fs $$<
+ $Q $(OBJCOPY) -I binary -B $(RTE_OBJCOPY_ARCH) -O $(RTE_OBJCOPY_TARGET) \
+ --rename-section \
+ .data=.rodata,alloc,load,data,contents,readonly \
+ --redefine-sym _binary_$$(subst .,_,$$(<F))_start=beg_$(1) \
+ --redefine-sym _binary_$$(subst .,_,$$(<F))_end=end_$(1) \
+ --redefine-sym _binary_$$(subst .,_,$$(<F))_size=siz_$(1) \
+ $$(<F) $$@
+endef
+
+ifeq ($(CONFIG_RTE_APP_TEST_RESOURCE_TAR),y)
+define linked_tar_resource
+$(1).tar: $(2)
+ @ echo ' TAR $$@'
+ $Q tar -C $$(dir $$<) -cf $$@ $$(notdir $$<)
+$(call linked_resource,$(1),$(1).tar)
+endef
+else # ! CONFIG_RTE_APP_TEST_RESOURCE_TAR
+linked_tar_resource =
+endif # CONFIG_RTE_APP_TEST_RESOURCE_TAR
+
+#
+# library name
+#
+APP = test
+
+#
+# all sources are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) := commands.c
+SRCS-y += test.c
+SRCS-y += resource.c
+SRCS-y += test_resource.c
+test_resource.res: test_resource.c
+ @ cp $< $@
+$(eval $(call linked_resource,test_resource_c,test_resource.res))
+$(eval $(call linked_tar_resource,test_resource_tar,test_resource.c))
+SRCS-$(CONFIG_RTE_APP_TEST_RESOURCE_TAR) += test_cfgfile.c
+$(eval $(call linked_tar_resource,test_cfgfiles,test_cfgfiles))
+SRCS-y += test_prefetch.c
+SRCS-y += test_byteorder.c
+SRCS-y += test_per_lcore.c
+SRCS-y += test_atomic.c
+SRCS-y += test_barrier.c
+SRCS-y += test_malloc.c
+SRCS-y += test_cycles.c
+SRCS-y += test_mcslock.c
+SRCS-y += test_spinlock.c
+SRCS-y += test_ticketlock.c
+SRCS-y += test_memory.c
+SRCS-y += test_memzone.c
+SRCS-y += test_bitmap.c
+SRCS-y += test_reciprocal_division.c
+SRCS-y += test_reciprocal_division_perf.c
+SRCS-y += test_fbarray.c
+SRCS-y += test_external_mem.c
+SRCS-y += test_rand_perf.c
+
+SRCS-y += test_ring.c
+SRCS-y += test_ring_mpmc_stress.c
+SRCS-y += test_ring_hts_stress.c
+SRCS-y += test_ring_perf.c
+SRCS-y += test_ring_peek_stress.c
+SRCS-y += test_ring_rts_stress.c
+SRCS-y += test_ring_stress.c
+SRCS-y += test_pmd_perf.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_TABLE),y)
+SRCS-y += test_table.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test_table_pipeline.c
+SRCS-y += test_table_tables.c
+SRCS-y += test_table_ports.c
+SRCS-y += test_table_combined.c
+SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_table_acl.c
+SRCS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += test_flow_classify.c
+endif
+
+SRCS-y += test_rwlock.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_STACK) += test_stack.c
+SRCS-$(CONFIG_RTE_LIBRTE_STACK) += test_stack_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer.c
+SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_perf.c
+SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_racecond.c
+SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_secondary.c
+
+SRCS-y += test_mempool.c
+SRCS-y += test_mempool_perf.c
+
+SRCS-y += test_mbuf.c
+SRCS-y += test_logs.c
+
+SRCS-y += test_memcpy.c
+SRCS-y += test_memcpy_perf.c
+
+
+SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member.c
+SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd.c
+SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_thash.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_multiwriter.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite_lf_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_RIB) += test_rib.c
+SRCS-$(CONFIG_RTE_LIBRTE_RIB) += test_rib6.c
+SRCS-$(CONFIG_RTE_LIBRTE_FIB) += test_fib.c
+SRCS-$(CONFIG_RTE_LIBRTE_FIB) += test_fib6.c
+SRCS-$(CONFIG_RTE_LIBRTE_FIB) += test_fib_perf.c
+SRCS-$(CONFIG_RTE_LIBRTE_FIB) += test_fib6_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_perf.c
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
+SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += test_telemetry_json.c
+
+SRCS-y += test_debug.c
+SRCS-y += test_errno.c
+SRCS-y += test_tailq.c
+SRCS-y += test_string_fns.c
+SRCS-y += test_cpuflags.c
+SRCS-y += test_mp_secondary.c
+SRCS-y += test_eal_flags.c
+SRCS-y += test_eal_fs.c
+SRCS-y += test_alarm.c
+SRCS-y += test_interrupts.c
+SRCS-y += test_version.c
+SRCS-y += test_func_reentrancy.c
+SRCS-y += test_trace.c
+SRCS-y += test_trace_register.c
+SRCS-y += test_trace_perf.c
+SRCS-y += test_service_cores.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
+SRCS-y += sample_packet_forward.c
+SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) += test_bitratestats.c
+SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += test_latencystats.c
+SRCS-$(CONFIG_RTE_LIBRTE_PDUMP) += test_pdump.c
+endif
+
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_etheraddr.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_portlist.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_ipaddr.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_cirbuf.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_string.c
+SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_lib.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_NET) += test_crc.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_SCHED),y)
+SRCS-y += test_red.c
+SRCS-y += test_sched.c
+endif
+
+SRCS-$(CONFIG_RTE_LIBRTE_METER) += test_meter.c
+SRCS-$(CONFIG_RTE_LIBRTE_KNI) += test_kni.c
+SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power.c test_power_cpufreq.c
+SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power_kvm_vm.c
+SRCS-y += test_common.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor.c
+SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_REORDER) += test_reorder.c
+
+SRCS-y += virtual_pmd.c
+SRCS-y += packet_burst_generator.c
+SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_acl.c
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding_mode4.c
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_NULL),y)
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += test_link_bonding_rssconf.c
+endif
+
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_pmd_ring_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_blockcipher.c
+SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev.c
+SRCS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += test_cryptodev_asym.c
+SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_cryptodev_security_pdcp.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_METRICS) += test_metrics.c
+
+ifeq ($(CONFIG_RTE_COMPRESSDEV_TEST),y)
+SRCS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV) += test_compressdev.c
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y)
+SRCS-y += test_eventdev.c
+SRCS-y += test_event_ring.c
+SRCS-y += test_event_eth_rx_adapter.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_event_eth_tx_adapter.c
+SRCS-y += test_event_timer_adapter.c
+SRCS-y += test_event_crypto_adapter.c
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_GRAPH), y)
+SRCS-y += test_graph.c
+SRCS-y += test_graph_perf.c
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_RAWDEV),y)
+SRCS-y += test_rawdev.c
+endif
+
+SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) += test_kvargs.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_BPF) += test_bpf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_RCU) += test_rcu_qsbr.c test_rcu_qsbr_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_security.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c test_ipsec_perf.c
+SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c
+ifeq ($(CONFIG_RTE_LIBRTE_IPSEC),y)
+LDLIBS += -lrte_ipsec
+endif
+
+CFLAGS += -O3
+# Strict-aliasing rules are violated by uint8_t[] to context size casts.
+CFLAGS += -fno-strict-aliasing
+CFLAGS += $(WERROR_FLAGS)
+
+LDLIBS += -lm
+
+ifeq ($(CONFIG_RTE_LIBRTE_PDUMP),y)
+LDLIBS += -lpthread
+endif
+
+ifeq ($(CONFIG_RTE_COMPRESSDEV_TEST),y)
+ifeq ($(CONFIG_RTE_LIBRTE_COMPRESSDEV),y)
+LDLIBS += -lz
+endif
+endif
+
+# Disable VTA for memcpy test
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+ifeq ($(shell test $(GCC_VERSION) -ge 44 && echo 1), 1)
+CFLAGS_test_memcpy.o += -fno-var-tracking-assignments
+CFLAGS_test_memcpy_perf.o += -fno-var-tracking-assignments
+endif
+endif
+
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
+LDLIBS += -lrte_pmd_bond
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_NULL),y)
+LDLIBS += -lrte_pmd_null
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
+LDLIBS += -lrte_pmd_ring
+endif
+
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER),y)
+LDLIBS += -lrte_pmd_crypto_scheduler
+endif
+
+endif
+
+ifeq ($(CONFIG_RTE_APP_TEST_RESOURCE_TAR),y)
+LDLIBS += -larchive
+endif
+
+include $(RTE_SDK)/mk/rte.app.mk
+
+endif
diff --git a/src/spdk/dpdk/app/test/autotest.py b/src/spdk/dpdk/app/test/autotest.py
new file mode 100644
index 000000000..b42f48879
--- /dev/null
+++ b/src/spdk/dpdk/app/test/autotest.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# Script that uses either test app or qemu controlled by python-pexpect
+from __future__ import print_function
+import autotest_data
+import autotest_runner
+import sys
+
+
+def usage():
+ print("Usage: autotest.py [test app|test iso image] ",
+ "[target] [whitelist|-blacklist]")
+
+if len(sys.argv) < 3:
+ usage()
+ sys.exit(1)
+
+target = sys.argv[2]
+
+test_whitelist = None
+test_blacklist = None
+
+# get blacklist/whitelist
+if len(sys.argv) > 3:
+ testlist = sys.argv[3].split(',')
+ testlist = [test.lower() for test in testlist]
+ if testlist[0].startswith('-'):
+ testlist[0] = testlist[0].lstrip('-')
+ test_blacklist = testlist
+ else:
+ test_whitelist = testlist
+
+cmdline = "%s -c f" % (sys.argv[1])
+
+print(cmdline)
+
+# how many workers to run tests with. FreeBSD doesn't support multiple primary
+# processes, so make it 1, otherwise make it 4. ignored for non-parallel tests
+n_processes = 1 if "bsd" in target else 4
+
+runner = autotest_runner.AutotestRunner(cmdline, target, test_blacklist,
+ test_whitelist, n_processes)
+
+runner.parallel_tests = autotest_data.parallel_test_list[:]
+runner.non_parallel_tests = autotest_data.non_parallel_test_list[:]
+
+num_fails = runner.run_all_tests()
+
+sys.exit(num_fails)
diff --git a/src/spdk/dpdk/app/test/autotest_data.py b/src/spdk/dpdk/app/test/autotest_data.py
new file mode 100644
index 000000000..7b1d01389
--- /dev/null
+++ b/src/spdk/dpdk/app/test/autotest_data.py
@@ -0,0 +1,796 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# Test data for autotests
+
+from autotest_test_funcs import *
+
+# groups of tests that can be run in parallel
+# the grouping has been found largely empirically
+parallel_test_list = [
+ {
+ "Name": "Cycles autotest",
+ "Command": "cycles_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Timer autotest",
+ "Command": "timer_autotest",
+ "Func": timer_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Debug autotest",
+ "Command": "debug_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Errno autotest",
+ "Command": "errno_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Meter autotest",
+ "Command": "meter_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Common autotest",
+ "Command": "common_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Resource autotest",
+ "Command": "resource_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Memory autotest",
+ "Command": "memory_autotest",
+ "Func": memory_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Read/write lock autotest",
+ "Command": "rwlock_autotest",
+ "Func": rwlock_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Logs autotest",
+ "Command": "logs_autotest",
+ "Func": logs_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "CPU flags autotest",
+ "Command": "cpuflags_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Version autotest",
+ "Command": "version_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "EAL filesystem autotest",
+ "Command": "eal_fs_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "EAL flags autotest",
+ "Command": "eal_flags_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash autotest",
+ "Command": "hash_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "LPM autotest",
+ "Command": "lpm_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "LPM6 autotest",
+ "Command": "lpm6_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RIB autotest",
+ "Command": "rib_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RIB slow autotest",
+ "Command": "rib_slow_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RIB6 autotest",
+ "Command": "rib6_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RIB6 slow autotest",
+ "Command": "rib6_slow_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB autotest",
+ "Command": "fib_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB slow autotest",
+ "Command": "fib_slow_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB6 autotest",
+ "Command": "fib6_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB6 slow autotest",
+ "Command": "fib6_slow_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Memcpy autotest",
+ "Command": "memcpy_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Memzone autotest",
+ "Command": "memzone_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "String autotest",
+ "Command": "string_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Alarm autotest",
+ "Command": "alarm_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Malloc autotest",
+ "Command": "malloc_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Multi-process autotest",
+ "Command": "multiprocess_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Mbuf autotest",
+ "Command": "mbuf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Per-lcore autotest",
+ "Command": "per_lcore_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Ring autotest",
+ "Command": "ring_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Spinlock autotest",
+ "Command": "spinlock_autotest",
+ "Func": spinlock_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Ticketlock autotest",
+ "Command": "ticketlock_autotest",
+ "Func": ticketlock_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "MCSlock autotest",
+ "Command": "mcslock_autotest",
+ "Func": mcslock_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Byte order autotest",
+ "Command": "byteorder_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "TAILQ autotest",
+ "Command": "tailq_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Command-line autotest",
+ "Command": "cmdline_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Interrupts autotest",
+ "Command": "interrupt_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Function reentrancy autotest",
+ "Command": "func_reentrancy_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Mempool autotest",
+ "Command": "mempool_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Atomics autotest",
+ "Command": "atomic_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Prefetch autotest",
+ "Command": "prefetch_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Red autotest",
+ "Command": "red_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "PMD ring autotest",
+ "Command": "ring_pmd_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Access list control autotest",
+ "Command": "acl_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Sched autotest",
+ "Command": "sched_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Eventdev selftest octeontx",
+ "Command": "eventdev_selftest_octeontx",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Event ring autotest",
+ "Command": "event_ring_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Table autotest",
+ "Command": "table_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Flow classify autotest",
+ "Command": "flow_classify_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Event eth rx adapter autotest",
+ "Command": "event_eth_rx_adapter_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "User delay",
+ "Command": "user_delay_us",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Sleep delay",
+ "Command": "delay_us_sleep_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Rawdev autotest",
+ "Command": "rawdev_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Kvargs autotest",
+ "Command": "kvargs_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Link bonding autotest",
+ "Command": "link_bonding_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Link bonding mode4 autotest",
+ "Command": "link_bonding_mode4_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Link bonding rssconf autotest",
+ "Command": "link_bonding_rssconf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Crc autotest",
+ "Command": "crc_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Distributor autotest",
+ "Command": "distributor_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Reorder autotest",
+ "Command": "reorder_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Barrier autotest",
+ "Command": "barrier_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Bitmap test",
+ "Command": "bitmap_test",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash multiwriter autotest",
+ "Command": "hash_multiwriter_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Service autotest",
+ "Command": "service_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Timer racecond autotest",
+ "Command": "timer_racecond_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Member autotest",
+ "Command": "member_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Efd_autotest",
+ "Command": "efd_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Thash autotest",
+ "Command": "thash_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash function autotest",
+ "Command": "hash_functions_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev sw mvsam autotest",
+ "Command": "cryptodev_sw_mvsam_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev dpaa2 sec autotest",
+ "Command": "cryptodev_dpaa2_sec_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev dpaa sec autotest",
+ "Command": "cryptodev_dpaa_sec_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev qat autotest",
+ "Command": "cryptodev_qat_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev aesni mb autotest",
+ "Command": "cryptodev_aesni_mb_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev openssl autotest",
+ "Command": "cryptodev_openssl_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev scheduler autotest",
+ "Command": "cryptodev_scheduler_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev aesni gcm autotest",
+ "Command": "cryptodev_aesni_gcm_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev null autotest",
+ "Command": "cryptodev_null_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev sw snow3g autotest",
+ "Command": "cryptodev_sw_snow3g_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev sw kasumi autotest",
+ "Command": "cryptodev_sw_kasumi_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Cryptodev_sw_zuc_autotest",
+ "Command": "cryptodev_sw_zuc_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Reciprocal division",
+ "Command": "reciprocal_division",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Red all",
+ "Command": "red_all",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Fbarray autotest",
+ "Command": "fbarray_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "External memory autotest",
+ "Command": "external_mem_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Metrics autotest",
+ "Command": "metrics_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Bitratestats autotest",
+ "Command": "bitratestats_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Latencystats autotest",
+ "Command": "latencystats_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Pdump autotest",
+ "Command": "pdump_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "IPsec_SAD",
+ "Command": "ipsec_sad_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ #
+ #Please always keep all dump tests at the end and together!
+ #
+ {
+ "Name": "Dump physmem",
+ "Command": "dump_physmem",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump memzone",
+ "Command": "dump_memzone",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump struct sizes",
+ "Command": "dump_struct_sizes",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump mempool",
+ "Command": "dump_mempool",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump malloc stats",
+ "Command": "dump_malloc_stats",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump devargs",
+ "Command": "dump_devargs",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump log types",
+ "Command": "dump_log_types",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Dump_ring",
+ "Command": "dump_ring",
+ "Func": dump_autotest,
+ "Report": None,
+ },
+]
+
+# tests that should not be run when any other tests are running
+non_parallel_test_list = [
+ {
+ "Name": "Eventdev common autotest",
+ "Command": "eventdev_common_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Eventdev selftest sw",
+ "Command": "eventdev_selftest_sw",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "KNI autotest",
+ "Command": "kni_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Mempool performance autotest",
+ "Command": "mempool_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Memcpy performance autotest",
+ "Command": "memcpy_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash performance autotest",
+ "Command": "hash_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash read-write concurrency functional autotest",
+ "Command": "hash_readwrite_func_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash read-write concurrency perf autotest",
+ "Command": "hash_readwrite_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Hash read-write lock-free concurrency perf autotest",
+ "Command": "hash_readwrite_lf_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Power autotest",
+ "Command": "power_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Power cpufreq autotest",
+ "Command": "power_cpufreq_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Power KVM VM autotest",
+ "Command": "power_kvm_vm_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Timer performance autotest",
+ "Command": "timer_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+
+ "Name": "Pmd perf autotest",
+ "Command": "pmd_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Ring pmd perf autotest",
+ "Command": "ring_pmd_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Distributor perf autotest",
+ "Command": "distributor_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Red_perf",
+ "Command": "red_perf",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Lpm6 perf autotest",
+ "Command": "lpm6_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Lpm perf autotest",
+ "Command": "lpm_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB perf autotest",
+ "Command": "fib_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "FIB6 perf autotest",
+ "Command": "fib6_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Efd perf autotest",
+ "Command": "efd_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Member perf autotest",
+ "Command": "member_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "Reciprocal division perf",
+ "Command": "reciprocal_division_perf",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RCU QSBR autotest",
+ "Command": "rcu_qsbr_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ {
+ "Name": "RCU QSBR performance autotest",
+ "Command": "rcu_qsbr_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+ #
+ # Please always make sure that ring_perf is the last test!
+ #
+ {
+ "Name": "Ring performance autotest",
+ "Command": "ring_perf_autotest",
+ "Func": default_autotest,
+ "Report": None,
+ },
+]
diff --git a/src/spdk/dpdk/app/test/autotest_runner.py b/src/spdk/dpdk/app/test/autotest_runner.py
new file mode 100644
index 000000000..95e74c760
--- /dev/null
+++ b/src/spdk/dpdk/app/test/autotest_runner.py
@@ -0,0 +1,439 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# The main logic behind running autotests in parallel
+
+from __future__ import print_function
+import StringIO
+import csv
+from multiprocessing import Pool, Queue
+import pexpect
+import re
+import subprocess
+import sys
+import time
+import glob
+import os
+
+# wait for prompt
+def wait_prompt(child):
+ try:
+ child.sendline()
+ result = child.expect(["RTE>>", pexpect.TIMEOUT, pexpect.EOF],
+ timeout=120)
+ except:
+ return False
+ if result == 0:
+ return True
+ else:
+ return False
+
+
+# get all valid NUMA nodes
+def get_numa_nodes():
+ return [
+ int(
+ re.match(r"node(\d+)", os.path.basename(node))
+ .group(1)
+ )
+ for node in glob.glob("/sys/devices/system/node/node*")
+ ]
+
+
+# find first (or any, really) CPU on a particular node, will be used to spread
+# processes around NUMA nodes to avoid exhausting memory on particular node
+def first_cpu_on_node(node_nr):
+ cpu_path = glob.glob("/sys/devices/system/node/node%d/cpu*" % node_nr)
+ r = re.compile(r"cpu(\d+)")
+ cpu_name = filter(None,
+ map(r.match,
+ map(os.path.basename, cpu_path)
+ )
+ )
+ # for compatibility between python 3 and 2 we need to make interable out
+ # of filter return as it returns list in python 2 and a generator in 3
+ m = next(iter(cpu_name))
+ return int(m.group(1))
+
+
+pool_child = None # per-process child
+
+
+# we initialize each worker with a queue because we need per-pool unique
+# command-line arguments, but we cannot do different arguments in an initializer
+# because the API doesn't allow per-worker initializer arguments. so, instead,
+# we will initialize with a shared queue, and dequeue command-line arguments
+# from this queue
+def pool_init(queue, result_queue):
+ global pool_child
+
+ cmdline, prefix = queue.get()
+ start_time = time.time()
+ name = ("Start %s" % prefix) if prefix != "" else "Start"
+
+ # use default prefix if no prefix was specified
+ prefix_cmdline = "--file-prefix=%s" % prefix if prefix != "" else ""
+
+ # append prefix to cmdline
+ cmdline = "%s %s" % (cmdline, prefix_cmdline)
+
+ # prepare logging of init
+ startuplog = StringIO.StringIO()
+
+ # run test app
+ try:
+
+ print("\n%s %s\n" % ("=" * 20, prefix), file=startuplog)
+ print("\ncmdline=%s" % cmdline, file=startuplog)
+
+ pool_child = pexpect.spawn(cmdline, logfile=startuplog)
+
+ # wait for target to boot
+ if not wait_prompt(pool_child):
+ pool_child.close()
+
+ result = tuple((-1,
+ "Fail [No prompt]",
+ name,
+ time.time() - start_time,
+ startuplog.getvalue(),
+ None))
+ pool_child = None
+ else:
+ result = tuple((0,
+ "Success",
+ name,
+ time.time() - start_time,
+ startuplog.getvalue(),
+ None))
+ except:
+ result = tuple((-1,
+ "Fail [Can't run]",
+ name,
+ time.time() - start_time,
+ startuplog.getvalue(),
+ None))
+ pool_child = None
+
+ result_queue.put(result)
+
+
+# run a test
+# each result tuple in results list consists of:
+# result value (0 or -1)
+# result string
+# test name
+# total test run time (double)
+# raw test log
+# test report (if not available, should be None)
+#
+# this function needs to be outside AutotestRunner class because otherwise Pool
+# won't work (or rather it will require quite a bit of effort to make it work).
+def run_test(target, test):
+ global pool_child
+
+ if pool_child is None:
+ return -1, "Fail [No test process]", test["Name"], 0, "", None
+
+ # create log buffer for each test
+ # in multiprocessing environment, the logging would be
+ # interleaved and will create a mess, hence the buffering
+ logfile = StringIO.StringIO()
+ pool_child.logfile = logfile
+
+ # make a note when the test started
+ start_time = time.time()
+
+ try:
+ # print test name to log buffer
+ print("\n%s %s\n" % ("-" * 20, test["Name"]), file=logfile)
+
+ # run test function associated with the test
+ result = test["Func"](pool_child, test["Command"])
+
+ # make a note when the test was finished
+ end_time = time.time()
+
+ log = logfile.getvalue()
+
+ # append test data to the result tuple
+ result += (test["Name"], end_time - start_time, log)
+
+ # call report function, if any defined, and supply it with
+ # target and complete log for test run
+ if test["Report"]:
+ report = test["Report"](target, log)
+
+ # append report to results tuple
+ result += (report,)
+ else:
+ # report is None
+ result += (None,)
+ except:
+ # make a note when the test crashed
+ end_time = time.time()
+
+ # mark test as failed
+ result = (-1, "Fail [Crash]", test["Name"],
+ end_time - start_time, logfile.getvalue(), None)
+
+ # return test results
+ return result
+
+
+# class representing an instance of autotests run
+class AutotestRunner:
+ cmdline = ""
+ parallel_test_groups = []
+ non_parallel_test_groups = []
+ logfile = None
+ csvwriter = None
+ target = ""
+ start = None
+ n_tests = 0
+ fails = 0
+ log_buffers = []
+ blacklist = []
+ whitelist = []
+
+ def __init__(self, cmdline, target, blacklist, whitelist, n_processes):
+ self.cmdline = cmdline
+ self.target = target
+ self.blacklist = blacklist
+ self.whitelist = whitelist
+ self.skipped = []
+ self.parallel_tests = []
+ self.non_parallel_tests = []
+ self.n_processes = n_processes
+ self.active_processes = 0
+
+ # parse the binary for available test commands
+ binary = cmdline.split()[0]
+ stripped = 'not stripped' not in \
+ subprocess.check_output(['file', binary])
+ if not stripped:
+ symbols = subprocess.check_output(['nm', binary]).decode('utf-8')
+ self.avail_cmds = re.findall('test_register_(\w+)', symbols)
+ else:
+ self.avail_cmds = None
+
+ # log file filename
+ logfile = "%s.log" % target
+ csvfile = "%s.csv" % target
+
+ self.logfile = open(logfile, "w")
+ csvfile = open(csvfile, "w")
+ self.csvwriter = csv.writer(csvfile)
+
+ # prepare results table
+ self.csvwriter.writerow(["test_name", "test_result", "result_str"])
+
+ # set up cmdline string
+ def __get_cmdline(self, cpu_nr):
+ cmdline = ("taskset -c %i " % cpu_nr) + self.cmdline
+
+ return cmdline
+
+ def __process_result(self, result):
+
+ # unpack result tuple
+ test_result, result_str, test_name, \
+ test_time, log, report = result
+
+ # get total run time
+ cur_time = time.time()
+ total_time = int(cur_time - self.start)
+
+ # print results, test run time and total time since start
+ result = ("%s:" % test_name).ljust(30)
+ result += result_str.ljust(29)
+ result += "[%02dm %02ds]" % (test_time / 60, test_time % 60)
+
+ # don't print out total time every line, it's the same anyway
+ print(result + "[%02dm %02ds]" % (total_time / 60, total_time % 60))
+
+ # if test failed and it wasn't a "start" test
+ if test_result < 0:
+ self.fails += 1
+
+ # collect logs
+ self.log_buffers.append(log)
+
+ # create report if it exists
+ if report:
+ try:
+ f = open("%s_%s_report.rst" %
+ (self.target, test_name), "w")
+ except IOError:
+ print("Report for %s could not be created!" % test_name)
+ else:
+ with f:
+ f.write(report)
+
+ # write test result to CSV file
+ self.csvwriter.writerow([test_name, test_result, result_str])
+
+ # this function checks individual test and decides if this test should be in
+ # the group by comparing it against whitelist/blacklist. it also checks if
+ # the test is compiled into the binary, and marks it as skipped if necessary
+ def __filter_test(self, test):
+ test_cmd = test["Command"]
+ test_id = test_cmd
+
+ # dump tests are specified in full e.g. "Dump_mempool"
+ if "_autotest" in test_id:
+ test_id = test_id[:-len("_autotest")]
+
+ # filter out blacklisted/whitelisted tests
+ if self.blacklist and test_id in self.blacklist:
+ return False
+ if self.whitelist and test_id not in self.whitelist:
+ return False
+
+ # if test wasn't compiled in, remove it as well
+ if self.avail_cmds and test_cmd not in self.avail_cmds:
+ result = 0, "Skipped [Not compiled]", test_id, 0, "", None
+ self.skipped.append(tuple(result))
+ return False
+
+ return True
+
+ def __run_test_group(self, test_group, worker_cmdlines):
+ group_queue = Queue()
+ init_result_queue = Queue()
+ for proc, cmdline in enumerate(worker_cmdlines):
+ prefix = "test%i" % proc if len(worker_cmdlines) > 1 else ""
+ group_queue.put(tuple((cmdline, prefix)))
+
+ # create a pool of worker threads
+ # we will initialize child in the initializer, and we don't need to
+ # close the child because when the pool worker gets destroyed, child
+ # closes the process
+ pool = Pool(processes=len(worker_cmdlines),
+ initializer=pool_init,
+ initargs=(group_queue, init_result_queue))
+
+ results = []
+
+ # process all initialization results
+ for _ in range(len(worker_cmdlines)):
+ self.__process_result(init_result_queue.get())
+
+ # run all tests asynchronously
+ for test in test_group:
+ result = pool.apply_async(run_test, (self.target, test))
+ results.append(result)
+
+ # tell the pool to stop all processes once done
+ pool.close()
+
+ # iterate while we have group execution results to get
+ while len(results) > 0:
+ # iterate over a copy to be able to safely delete results
+ # this iterates over a list of group results
+ for async_result in results[:]:
+ # if the thread hasn't finished yet, continue
+ if not async_result.ready():
+ continue
+
+ res = async_result.get()
+
+ self.__process_result(res)
+
+ # remove result from results list once we're done with it
+ results.remove(async_result)
+
+ # iterate over test groups and run tests associated with them
+ def run_all_tests(self):
+ # filter groups
+ self.parallel_tests = list(
+ filter(self.__filter_test,
+ self.parallel_tests)
+ )
+ self.non_parallel_tests = list(
+ filter(self.__filter_test,
+ self.non_parallel_tests)
+ )
+
+ parallel_cmdlines = []
+ # FreeBSD doesn't have NUMA support
+ numa_nodes = get_numa_nodes()
+ if len(numa_nodes) > 0:
+ for proc in range(self.n_processes):
+ # spread cpu affinity between NUMA nodes to have less chance of
+ # running out of memory while running multiple test apps in
+ # parallel. to do that, alternate between NUMA nodes in a round
+ # robin fashion, and pick an arbitrary CPU from that node to
+ # taskset our execution to
+ numa_node = numa_nodes[self.active_processes % len(numa_nodes)]
+ cpu_nr = first_cpu_on_node(numa_node)
+ parallel_cmdlines += [self.__get_cmdline(cpu_nr)]
+ # increase number of active processes so that the next cmdline
+ # gets a different NUMA node
+ self.active_processes += 1
+ else:
+ parallel_cmdlines = [self.cmdline] * self.n_processes
+
+ print("Running tests with %d workers" % self.n_processes)
+
+ # create table header
+ print("")
+ print("Test name".ljust(30) + "Test result".ljust(29) +
+ "Test".center(9) + "Total".center(9))
+ print("=" * 80)
+
+ if len(self.skipped):
+ print("Skipped autotests:")
+
+ # print out any skipped tests
+ for result in self.skipped:
+ # unpack result tuple
+ test_result, result_str, test_name, _, _, _ = result
+ self.csvwriter.writerow([test_name, test_result, result_str])
+
+ t = ("%s:" % test_name).ljust(30)
+ t += result_str.ljust(29)
+ t += "[00m 00s]"
+
+ print(t)
+
+ # make a note of tests start time
+ self.start = time.time()
+
+ # whatever happens, try to save as much logs as possible
+ try:
+ if len(self.parallel_tests) > 0:
+ print("Parallel autotests:")
+ self.__run_test_group(self.parallel_tests, parallel_cmdlines)
+
+ if len(self.non_parallel_tests) > 0:
+ print("Non-parallel autotests:")
+ self.__run_test_group(self.non_parallel_tests, [self.cmdline])
+
+ # get total run time
+ cur_time = time.time()
+ total_time = int(cur_time - self.start)
+
+ # print out summary
+ print("=" * 80)
+ print("Total run time: %02dm %02ds" % (total_time / 60,
+ total_time % 60))
+ if self.fails != 0:
+ print("Number of failed tests: %s" % str(self.fails))
+
+ # write summary to logfile
+ self.logfile.write("Summary\n")
+ self.logfile.write("Target: ".ljust(15) + "%s\n" % self.target)
+ self.logfile.write("Tests: ".ljust(15) + "%i\n" % self.n_tests)
+ self.logfile.write("Failed tests: ".ljust(
+ 15) + "%i\n" % self.fails)
+ except:
+ print("Exception occurred")
+ print(sys.exc_info())
+ self.fails = 1
+
+ # drop logs from all executions to a logfile
+ for buf in self.log_buffers:
+ self.logfile.write(buf.replace("\r", ""))
+
+ return self.fails
diff --git a/src/spdk/dpdk/app/test/autotest_test_funcs.py b/src/spdk/dpdk/app/test/autotest_test_funcs.py
new file mode 100644
index 000000000..26688b713
--- /dev/null
+++ b/src/spdk/dpdk/app/test/autotest_test_funcs.py
@@ -0,0 +1,342 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+# Test functions
+
+import pexpect
+
+# default autotest, used to run most tests
+# waits for "Test OK"
+
+
+def default_autotest(child, test_name):
+ child.sendline(test_name)
+ result = child.expect(["Test OK", "Test Failed",
+ "Command not found", pexpect.TIMEOUT], timeout=900)
+ if result == 1:
+ return -1, "Fail"
+ elif result == 2:
+ return -1, "Fail [Not found]"
+ elif result == 3:
+ return -1, "Fail [Timeout]"
+ return 0, "Success"
+
+# autotest used to run dump commands
+# just fires the command
+
+
+def dump_autotest(child, test_name):
+ child.sendline(test_name)
+ return 0, "Success"
+
+# memory autotest
+# reads output and waits for Test OK
+
+
+def memory_autotest(child, test_name):
+ lines = 0
+ error = ''
+ child.sendline(test_name)
+ while True:
+ regexp = "IOVA:0x[0-9a-f]*, len:([0-9]*), virt:0x[0-9a-f]*, " \
+ "socket_id:[0-9]*"
+ index = child.expect([regexp, "Test OK", "Test Failed",
+ pexpect.TIMEOUT], timeout=10)
+ if index == 3:
+ return -1, "Fail [Timeout]"
+ elif index == 1:
+ break
+ elif index == 2:
+ return -1, "Fail"
+ else:
+ lines = lines + 1
+ size = int(child.match.groups()[0], 10)
+ if size <= 0:
+ error = 'Bad size'
+
+ if lines <= 0:
+ return -1, "Fail [No entries]"
+ if error != '':
+ return -1, "Fail [{}]".format(error)
+ return 0, "Success"
+
+
+def spinlock_autotest(child, test_name):
+ i = 0
+ ir = 0
+ child.sendline(test_name)
+ while True:
+ index = child.expect(["Test OK",
+ "Test Failed",
+ "Hello from core ([0-9]*) !",
+ "Hello from within recursive locks "
+ "from ([0-9]*) !",
+ pexpect.TIMEOUT], timeout=5)
+ # ok
+ if index == 0:
+ break
+
+ # message, check ordering
+ elif index == 2:
+ if int(child.match.groups()[0]) < i:
+ return -1, "Fail [Bad order]"
+ i = int(child.match.groups()[0])
+ elif index == 3:
+ if int(child.match.groups()[0]) < ir:
+ return -1, "Fail [Bad order]"
+ ir = int(child.match.groups()[0])
+
+ # fail
+ elif index == 4:
+ return -1, "Fail [Timeout]"
+ elif index == 1:
+ return -1, "Fail"
+
+ return 0, "Success"
+
+
+def rwlock_autotest(child, test_name):
+ i = 0
+ child.sendline(test_name)
+ while True:
+ index = child.expect(["Test OK",
+ "Test Failed",
+ "Hello from core ([0-9]*) !",
+ "Global write lock taken on master "
+ "core ([0-9]*)",
+ pexpect.TIMEOUT], timeout=10)
+ # ok
+ if index == 0:
+ if i != 0xffff:
+ return -1, "Fail [Message is missing]"
+ break
+
+ # message, check ordering
+ elif index == 2:
+ if int(child.match.groups()[0]) < i:
+ return -1, "Fail [Bad order]"
+ i = int(child.match.groups()[0])
+
+ # must be the last message, check ordering
+ elif index == 3:
+ i = 0xffff
+
+ elif index == 4:
+ return -1, "Fail [Timeout]"
+
+ # fail
+ else:
+ return -1, "Fail"
+
+ return 0, "Success"
+
+
+def ticketlock_autotest(child, test_name):
+ i = 0
+ ir = 0
+ child.sendline(test_name)
+ while True:
+ index = child.expect(["Test OK",
+ "Test Failed",
+ "Hello from core ([0-9]*) !",
+ "Hello from within recursive locks "
+ "from ([0-9]*) !",
+ pexpect.TIMEOUT], timeout=5)
+ # ok
+ if index == 0:
+ break
+
+ # message, check ordering
+ elif index == 2:
+ if int(child.match.groups()[0]) < i:
+ return -1, "Fail [Bad order]"
+ i = int(child.match.groups()[0])
+ elif index == 3:
+ if int(child.match.groups()[0]) < ir:
+ return -1, "Fail [Bad order]"
+ ir = int(child.match.groups()[0])
+
+ # fail
+ elif index == 4:
+ return -1, "Fail [Timeout]"
+ elif index == 1:
+ return -1, "Fail"
+
+ return 0, "Success"
+
+def mcslock_autotest(child, test_name):
+ i = 0
+ ir = 0
+ child.sendline(test_name)
+ while True:
+ index = child.expect(["Test OK",
+ "Test Failed",
+ "lcore ([0-9]*) state: ([0-1])"
+ "MCS lock taken on core ([0-9]*)",
+ "MCS lock released on core ([0-9]*)",
+ pexpect.TIMEOUT], timeout=5)
+ # ok
+ if index == 0:
+ break
+
+ # message, check ordering
+ elif index == 2:
+ if int(child.match.groups()[0]) < i:
+ return -1, "Fail [Bad order]"
+ i = int(child.match.groups()[0])
+ elif index == 3:
+ if int(child.match.groups()[0]) < ir:
+ return -1, "Fail [Bad order]"
+ ir = int(child.match.groups()[0])
+
+ # fail
+ elif index == 4:
+ return -1, "Fail [Timeout]"
+ elif index == 1:
+ return -1, "Fail"
+
+ return 0, "Success"
+
+def logs_autotest(child, test_name):
+ child.sendline(test_name)
+
+ log_list = [
+ "TESTAPP1: error message",
+ "TESTAPP1: critical message",
+ "TESTAPP2: critical message",
+ "TESTAPP1: error message",
+ ]
+
+ for log_msg in log_list:
+ index = child.expect([log_msg,
+ "Test OK",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=10)
+
+ if index == 3:
+ return -1, "Fail [Timeout]"
+ # not ok
+ elif index != 0:
+ return -1, "Fail"
+
+ index = child.expect(["Test OK",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=10)
+
+ return 0, "Success"
+
+
+def timer_autotest(child, test_name):
+ child.sendline(test_name)
+
+ index = child.expect(["Start timer stress tests",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=5)
+
+ if index == 1:
+ return -1, "Fail"
+ elif index == 2:
+ return -1, "Fail [Timeout]"
+
+ index = child.expect(["Start timer stress tests 2",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=5)
+
+ if index == 1:
+ return -1, "Fail"
+ elif index == 2:
+ return -1, "Fail [Timeout]"
+
+ index = child.expect(["Start timer basic tests",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=5)
+
+ if index == 1:
+ return -1, "Fail"
+ elif index == 2:
+ return -1, "Fail [Timeout]"
+
+ lcore_tim0 = -1
+ lcore_tim1 = -1
+ lcore_tim2 = -1
+ lcore_tim3 = -1
+
+ while True:
+ index = child.expect(["TESTTIMER: ([0-9]*): callback id=([0-9]*) "
+ "count=([0-9]*) on core ([0-9]*)",
+ "Test OK",
+ "Test Failed",
+ pexpect.TIMEOUT], timeout=10)
+
+ if index == 1:
+ break
+
+ if index == 2:
+ return -1, "Fail"
+ elif index == 3:
+ return -1, "Fail [Timeout]"
+
+ try:
+ id = int(child.match.groups()[1])
+ cnt = int(child.match.groups()[2])
+ lcore = int(child.match.groups()[3])
+ except:
+ return -1, "Fail [Cannot parse]"
+
+ # timer0 always expires on the same core when cnt < 20
+ if id == 0:
+ if lcore_tim0 == -1:
+ lcore_tim0 = lcore
+ elif lcore != lcore_tim0 and cnt < 20:
+ return -1, "Fail [lcore != lcore_tim0 (%d, %d)]" \
+ % (lcore, lcore_tim0)
+ if cnt > 21:
+ return -1, "Fail [tim0 cnt > 21]"
+
+ # timer1 each time expires on a different core
+ if id == 1:
+ if lcore == lcore_tim1:
+ return -1, "Fail [lcore == lcore_tim1 (%d, %d)]" \
+ % (lcore, lcore_tim1)
+ lcore_tim1 = lcore
+ if cnt > 10:
+ return -1, "Fail [tim1 cnt > 30]"
+
+ # timer0 always expires on the same core
+ if id == 2:
+ if lcore_tim2 == -1:
+ lcore_tim2 = lcore
+ elif lcore != lcore_tim2:
+ return -1, "Fail [lcore != lcore_tim2 (%d, %d)]" \
+ % (lcore, lcore_tim2)
+ if cnt > 30:
+ return -1, "Fail [tim2 cnt > 30]"
+
+ # timer0 always expires on the same core
+ if id == 3:
+ if lcore_tim3 == -1:
+ lcore_tim3 = lcore
+ elif lcore != lcore_tim3:
+ return -1, "Fail [lcore_tim3 changed (%d -> %d)]" \
+ % (lcore, lcore_tim3)
+ if cnt > 30:
+ return -1, "Fail [tim3 cnt > 30]"
+
+ # must be 2 different cores
+ if lcore_tim0 == lcore_tim3:
+ return -1, "Fail [lcore_tim0 (%d) == lcore_tim3 (%d)]" \
+ % (lcore_tim0, lcore_tim3)
+
+ return 0, "Success"
+
+
+def ring_autotest(child, test_name):
+ child.sendline(test_name)
+ index = child.expect(["Test OK", "Test Failed",
+ pexpect.TIMEOUT], timeout=2)
+ if index == 1:
+ return -1, "Fail"
+ elif index == 2:
+ return -1, "Fail [Timeout]"
+
+ return 0, "Success"
diff --git a/src/spdk/dpdk/app/test/commands.c b/src/spdk/dpdk/app/test/commands.c
new file mode 100644
index 000000000..d48dd513d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/commands.c
@@ -0,0 +1,383 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <termios.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_devargs.h>
+
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_parse_ipaddr.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+/****************/
+
+static struct test_commands_list commands_list =
+ TAILQ_HEAD_INITIALIZER(commands_list);
+
+void
+add_test_command(struct test_command *t)
+{
+ TAILQ_INSERT_TAIL(&commands_list, t, next);
+}
+
+struct cmd_autotest_result {
+ cmdline_fixed_string_t autotest;
+};
+
+static void cmd_autotest_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct test_command *t;
+ struct cmd_autotest_result *res = parsed_result;
+ int ret = 0;
+
+ TAILQ_FOREACH(t, &commands_list, next) {
+ if (!strcmp(res->autotest, t->command))
+ ret = t->callback();
+ }
+
+ last_test_result = ret;
+ if (ret == 0)
+ printf("Test OK\n");
+ else if (ret == TEST_SKIPPED)
+ printf("Test Skipped\n");
+ else
+ printf("Test Failed\n");
+ fflush(stdout);
+}
+
+cmdline_parse_token_string_t cmd_autotest_autotest =
+ TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest,
+ "");
+
+cmdline_parse_inst_t cmd_autotest = {
+ .f = cmd_autotest_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "launch autotest",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_autotest_autotest,
+ NULL,
+ },
+};
+
+/****************/
+
+struct cmd_dump_result {
+ cmdline_fixed_string_t dump;
+};
+
+static void
+dump_struct_sizes(void)
+{
+#define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
+ DUMP_SIZE(struct rte_mbuf);
+ DUMP_SIZE(struct rte_mempool);
+ DUMP_SIZE(struct rte_ring);
+#undef DUMP_SIZE
+}
+
+static void cmd_dump_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_dump_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_physmem"))
+ rte_dump_physmem_layout(stdout);
+ else if (!strcmp(res->dump, "dump_memzone"))
+ rte_memzone_dump(stdout);
+ else if (!strcmp(res->dump, "dump_struct_sizes"))
+ dump_struct_sizes();
+ else if (!strcmp(res->dump, "dump_ring"))
+ rte_ring_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_mempool"))
+ rte_mempool_list_dump(stdout);
+ else if (!strcmp(res->dump, "dump_devargs"))
+ rte_devargs_dump(stdout);
+ else if (!strcmp(res->dump, "dump_log_types"))
+ rte_log_dump(stdout);
+ else if (!strcmp(res->dump, "dump_malloc_stats"))
+ rte_malloc_dump_stats(stdout, NULL);
+ else if (!strcmp(res->dump, "dump_malloc_heaps"))
+ rte_malloc_dump_heaps(stdout);
+}
+
+cmdline_parse_token_string_t cmd_dump_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
+ "dump_physmem#"
+ "dump_memzone#"
+ "dump_struct_sizes#"
+ "dump_ring#"
+ "dump_mempool#"
+ "dump_malloc_stats#"
+ "dump_malloc_heaps#"
+ "dump_devargs#"
+ "dump_log_types");
+
+cmdline_parse_inst_t cmd_dump = {
+ .f = cmd_dump_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "dump status",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_dump,
+ NULL,
+ },
+};
+
+/****************/
+
+struct cmd_dump_one_result {
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t name;
+};
+
+static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_dump_one_result *res = parsed_result;
+
+ if (!strcmp(res->dump, "dump_ring")) {
+ struct rte_ring *r;
+ r = rte_ring_lookup(res->name);
+ if (r == NULL) {
+ cmdline_printf(cl, "Cannot find ring\n");
+ return;
+ }
+ rte_ring_dump(stdout, r);
+ }
+ else if (!strcmp(res->dump, "dump_mempool")) {
+ struct rte_mempool *mp;
+ mp = rte_mempool_lookup(res->name);
+ if (mp == NULL) {
+ cmdline_printf(cl, "Cannot find mempool\n");
+ return;
+ }
+ rte_mempool_dump(stdout, mp);
+ }
+}
+
+cmdline_parse_token_string_t cmd_dump_one_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump,
+ "dump_ring#dump_mempool");
+
+cmdline_parse_token_string_t cmd_dump_one_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL);
+
+cmdline_parse_inst_t cmd_dump_one = {
+ .f = cmd_dump_one_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_one_dump,
+ (void *)&cmd_dump_one_name,
+ NULL,
+ },
+};
+
+/****************/
+
+struct cmd_quit_result {
+ cmdline_fixed_string_t quit;
+};
+
+static void
+cmd_quit_parsed(__rte_unused void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ cmdline_quit(cl);
+}
+
+cmdline_parse_token_string_t cmd_quit_quit =
+ TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit,
+ "quit");
+
+cmdline_parse_inst_t cmd_quit = {
+ .f = cmd_quit_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "exit application",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_quit_quit,
+ NULL,
+ },
+};
+
+/****************/
+
+struct cmd_set_rxtx_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t mode;
+};
+
+static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_rxtx_result *res = parsed_result;
+ if (test_set_rxtx_conf(res->mode) < 0)
+ cmdline_printf(cl, "Cannot find such mode\n");
+}
+
+cmdline_parse_token_string_t cmd_set_rxtx_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set,
+ "set_rxtx_mode");
+
+cmdline_parse_token_string_t cmd_set_rxtx_mode =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL);
+
+cmdline_parse_inst_t cmd_set_rxtx = {
+ .f = cmd_set_rxtx_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set rxtx routine: "
+ "set_rxtx <mode>",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_set_rxtx_set,
+ (void *)&cmd_set_rxtx_mode,
+ NULL,
+ },
+};
+
+/****************/
+
+struct cmd_set_rxtx_anchor {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t type;
+};
+
+static void
+cmd_set_rxtx_anchor_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_rxtx_anchor *res = parsed_result;
+ if (test_set_rxtx_anchor(res->type) < 0)
+ cmdline_printf(cl, "Cannot find such anchor\n");
+}
+
+cmdline_parse_token_string_t cmd_set_rxtx_anchor_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set,
+ "set_rxtx_anchor");
+
+cmdline_parse_token_string_t cmd_set_rxtx_anchor_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL);
+
+cmdline_parse_inst_t cmd_set_rxtx_anchor = {
+ .f = cmd_set_rxtx_anchor_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set rxtx anchor: "
+ "set_rxtx_anchor <type>",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_set_rxtx_anchor_set,
+ (void *)&cmd_set_rxtx_anchor_type,
+ NULL,
+ },
+};
+
+/****************/
+
+/* for stream control */
+struct cmd_set_rxtx_sc {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t type;
+};
+
+static void
+cmd_set_rxtx_sc_parsed(void *parsed_result,
+ struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_rxtx_sc *res = parsed_result;
+ if (test_set_rxtx_sc(res->type) < 0)
+ cmdline_printf(cl, "Cannot find such stream control\n");
+}
+
+cmdline_parse_token_string_t cmd_set_rxtx_sc_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set,
+ "set_rxtx_sc");
+
+cmdline_parse_token_string_t cmd_set_rxtx_sc_type =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL);
+
+cmdline_parse_inst_t cmd_set_rxtx_sc = {
+ .f = cmd_set_rxtx_sc_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set rxtx stream control: "
+ "set_rxtx_sc <type>",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_set_rxtx_sc_set,
+ (void *)&cmd_set_rxtx_sc_type,
+ NULL,
+ },
+};
+
+/****************/
+
+
+cmdline_parse_ctx_t main_ctx[] = {
+ (cmdline_parse_inst_t *)&cmd_autotest,
+ (cmdline_parse_inst_t *)&cmd_dump,
+ (cmdline_parse_inst_t *)&cmd_dump_one,
+ (cmdline_parse_inst_t *)&cmd_quit,
+ (cmdline_parse_inst_t *)&cmd_set_rxtx,
+ (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
+ (cmdline_parse_inst_t *)&cmd_set_rxtx_sc,
+ NULL,
+};
+
+int commands_init(void)
+{
+ struct test_command *t;
+ char *commands;
+ int commands_len = 0;
+
+ TAILQ_FOREACH(t, &commands_list, next) {
+ commands_len += strlen(t->command) + 1;
+ }
+
+ commands = (char *)calloc(commands_len, sizeof(char));
+ if (!commands)
+ return -1;
+
+ TAILQ_FOREACH(t, &commands_list, next) {
+ strlcat(commands, t->command, commands_len);
+ if (TAILQ_NEXT(t, next) != NULL)
+ strlcat(commands, "#", commands_len);
+ }
+
+ cmd_autotest_autotest.string_data.str = commands;
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/get-coremask.sh b/src/spdk/dpdk/app/test/get-coremask.sh
new file mode 100755
index 000000000..bb8cf404d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/get-coremask.sh
@@ -0,0 +1,13 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+if [ "$(uname)" = "Linux" ] ; then
+ cat /sys/devices/system/cpu/present
+elif [ "$(uname)" = "FreeBSD" ] ; then
+ ncpus=$(/sbin/sysctl -n hw.ncpu)
+ echo 0-$(expr $ncpus - 1)
+else
+# fallback
+ echo 0-3
+fi
diff --git a/src/spdk/dpdk/app/test/has-hugepage.sh b/src/spdk/dpdk/app/test/has-hugepage.sh
new file mode 100755
index 000000000..d600fad31
--- /dev/null
+++ b/src/spdk/dpdk/app/test/has-hugepage.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020 Mellanox Technologies, Ltd
+
+if [ "$(uname)" = "Linux" ] ; then
+ cat /proc/sys/vm/nr_hugepages || echo 0
+elif [ "$(uname)" = "FreeBSD" ] ; then
+ echo 1 # assume FreeBSD always has hugepages
+else
+ echo 0
+fi
diff --git a/src/spdk/dpdk/app/test/meson.build b/src/spdk/dpdk/app/test/meson.build
new file mode 100644
index 000000000..1715ddbcb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/meson.build
@@ -0,0 +1,497 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+if not get_option('tests')
+ subdir_done()
+endif
+
+test_sources = files('commands.c',
+ 'packet_burst_generator.c',
+ 'test.c',
+ 'test_acl.c',
+ 'test_alarm.c',
+ 'test_atomic.c',
+ 'test_barrier.c',
+ 'test_bpf.c',
+ 'test_byteorder.c',
+ 'test_cmdline.c',
+ 'test_cmdline_cirbuf.c',
+ 'test_cmdline_etheraddr.c',
+ 'test_cmdline_ipaddr.c',
+ 'test_cmdline_lib.c',
+ 'test_cmdline_num.c',
+ 'test_cmdline_portlist.c',
+ 'test_cmdline_string.c',
+ 'test_common.c',
+ 'test_cpuflags.c',
+ 'test_crc.c',
+ 'test_cryptodev.c',
+ 'test_cryptodev_asym.c',
+ 'test_cryptodev_blockcipher.c',
+ 'test_cryptodev_security_pdcp.c',
+ 'test_cycles.c',
+ 'test_debug.c',
+ 'test_distributor.c',
+ 'test_distributor_perf.c',
+ 'test_eal_flags.c',
+ 'test_eal_fs.c',
+ 'test_efd.c',
+ 'test_efd_perf.c',
+ 'test_errno.c',
+ 'test_event_crypto_adapter.c',
+ 'test_event_eth_rx_adapter.c',
+ 'test_event_ring.c',
+ 'test_event_timer_adapter.c',
+ 'test_eventdev.c',
+ 'test_external_mem.c',
+ 'test_fbarray.c',
+ 'test_fib.c',
+ 'test_fib_perf.c',
+ 'test_fib6.c',
+ 'test_fib6_perf.c',
+ 'test_func_reentrancy.c',
+ 'test_flow_classify.c',
+ 'test_graph.c',
+ 'test_graph_perf.c',
+ 'test_hash.c',
+ 'test_hash_functions.c',
+ 'test_hash_multiwriter.c',
+ 'test_hash_readwrite.c',
+ 'test_hash_perf.c',
+ 'test_hash_readwrite_lf_perf.c',
+ 'test_interrupts.c',
+ 'test_ipfrag.c',
+ 'test_ipsec.c',
+ 'test_ipsec_sad.c',
+ 'test_ipsec_perf.c',
+ 'test_kni.c',
+ 'test_kvargs.c',
+ 'test_logs.c',
+ 'test_lpm.c',
+ 'test_lpm6.c',
+ 'test_lpm6_perf.c',
+ 'test_lpm_perf.c',
+ 'test_malloc.c',
+ 'test_mbuf.c',
+ 'test_member.c',
+ 'test_member_perf.c',
+ 'test_memcpy.c',
+ 'test_memcpy_perf.c',
+ 'test_memory.c',
+ 'test_mempool.c',
+ 'test_mempool_perf.c',
+ 'test_memzone.c',
+ 'test_meter.c',
+ 'test_metrics.c',
+ 'test_mcslock.c',
+ 'test_mp_secondary.c',
+ 'test_per_lcore.c',
+ 'test_pmd_perf.c',
+ 'test_power.c',
+ 'test_power_cpufreq.c',
+ 'test_power_kvm_vm.c',
+ 'test_prefetch.c',
+ 'test_rand_perf.c',
+ 'test_rawdev.c',
+ 'test_rcu_qsbr.c',
+ 'test_rcu_qsbr_perf.c',
+ 'test_reciprocal_division.c',
+ 'test_reciprocal_division_perf.c',
+ 'test_red.c',
+ 'test_reorder.c',
+ 'test_rib.c',
+ 'test_rib6.c',
+ 'test_ring.c',
+ 'test_ring_mpmc_stress.c',
+ 'test_ring_hts_stress.c',
+ 'test_ring_peek_stress.c',
+ 'test_ring_perf.c',
+ 'test_ring_rts_stress.c',
+ 'test_ring_stress.c',
+ 'test_rwlock.c',
+ 'test_sched.c',
+ 'test_security.c',
+ 'test_service_cores.c',
+ 'test_spinlock.c',
+ 'test_stack.c',
+ 'test_stack_perf.c',
+ 'test_string_fns.c',
+ 'test_table.c',
+ 'test_table_acl.c',
+ 'test_table_combined.c',
+ 'test_table_pipeline.c',
+ 'test_table_ports.c',
+ 'test_table_tables.c',
+ 'test_tailq.c',
+ 'test_thash.c',
+ 'test_timer.c',
+ 'test_timer_perf.c',
+ 'test_timer_racecond.c',
+ 'test_timer_secondary.c',
+ 'test_ticketlock.c',
+ 'test_trace.c',
+ 'test_trace_register.c',
+ 'test_trace_perf.c',
+ 'test_version.c',
+ 'virtual_pmd.c'
+)
+
+test_deps = ['acl',
+ 'bus_pci',
+ 'bus_vdev',
+ 'bitratestats',
+ 'bpf',
+ 'cfgfile',
+ 'cmdline',
+ 'cryptodev',
+ 'distributor',
+ 'efd',
+ 'ethdev',
+ 'eventdev',
+ 'fib',
+ 'flow_classify',
+ 'graph',
+ 'hash',
+ 'ipsec',
+ 'latencystats',
+ 'lpm',
+ 'member',
+ 'metrics',
+ 'node',
+ 'pipeline',
+ 'port',
+ 'rawdev',
+ 'rcu',
+ 'reorder',
+ 'rib',
+ 'ring',
+ 'security',
+ 'stack',
+ 'timer'
+]
+
+# Each test is marked with flag true/false
+# to indicate whether it can run in no-huge mode.
+fast_tests = [
+ ['acl_autotest', true],
+ ['alarm_autotest', false],
+ ['atomic_autotest', false],
+ ['byteorder_autotest', true],
+ ['cmdline_autotest', true],
+ ['common_autotest', true],
+ ['cpuflags_autotest', true],
+ ['cycles_autotest', true],
+ ['debug_autotest', true],
+ ['eal_flags_c_opt_autotest', false],
+ ['eal_flags_master_opt_autotest', false],
+ ['eal_flags_n_opt_autotest', false],
+ ['eal_flags_hpet_autotest', false],
+ ['eal_flags_no_huge_autotest', false],
+ ['eal_flags_w_opt_autotest', false],
+ ['eal_flags_b_opt_autotest', false],
+ ['eal_flags_vdev_opt_autotest', false],
+ ['eal_flags_r_opt_autotest', false],
+ ['eal_flags_mem_autotest', false],
+ ['eal_flags_file_prefix_autotest', false],
+ ['eal_flags_misc_autotest', false],
+ ['eal_fs_autotest', true],
+ ['errno_autotest', true],
+ ['event_ring_autotest', true],
+ ['fib_autotest', true],
+ ['fib6_autotest', true],
+ ['func_reentrancy_autotest', false],
+ ['flow_classify_autotest', false],
+ ['hash_autotest', true],
+ ['interrupt_autotest', true],
+ ['ipfrag_autotest', false],
+ ['logs_autotest', true],
+ ['lpm_autotest', true],
+ ['lpm6_autotest', true],
+ ['malloc_autotest', false],
+ ['mbuf_autotest', false],
+ ['mcslock_autotest', false],
+ ['memcpy_autotest', true],
+ ['memory_autotest', false],
+ ['mempool_autotest', false],
+ ['memzone_autotest', false],
+ ['meter_autotest', true],
+ ['multiprocess_autotest', false],
+ ['per_lcore_autotest', true],
+ ['prefetch_autotest', true],
+ ['rcu_qsbr_autotest', true],
+ ['red_autotest', true],
+ ['rib_autotest', true],
+ ['rib6_autotest', true],
+ ['ring_autotest', true],
+ ['rwlock_test1_autotest', true],
+ ['rwlock_rda_autotest', true],
+ ['rwlock_rds_wrm_autotest', true],
+ ['rwlock_rde_wro_autotest', true],
+ ['sched_autotest', true],
+ ['security_autotest', false],
+ ['spinlock_autotest', true],
+ ['stack_autotest', false],
+ ['stack_lf_autotest', false],
+ ['string_autotest', true],
+ ['table_autotest', true],
+ ['tailq_autotest', true],
+ ['timer_autotest', false],
+ ['user_delay_us', true],
+ ['version_autotest', true],
+ ['crc_autotest', true],
+ ['delay_us_sleep_autotest', true],
+ ['distributor_autotest', false],
+ ['eventdev_common_autotest', true],
+ ['fbarray_autotest', true],
+ ['hash_readwrite_func_autotest', false],
+ ['ipsec_autotest', true],
+ ['kni_autotest', false],
+ ['kvargs_autotest', true],
+ ['member_autotest', true],
+ ['metrics_autotest', true],
+ ['power_cpufreq_autotest', false],
+ ['power_autotest', true],
+ ['power_kvm_vm_autotest', false],
+ ['reorder_autotest', true],
+ ['service_autotest', true],
+ ['thash_autotest', true],
+ ['trace_autotest', true],
+]
+
+perf_test_names = [
+ 'ring_perf_autotest',
+ 'mempool_perf_autotest',
+ 'memcpy_perf_autotest',
+ 'hash_perf_autotest',
+ 'timer_perf_autotest',
+ 'reciprocal_division',
+ 'reciprocal_division_perf',
+ 'lpm_perf_autotest',
+ 'rib_slow_autotest',
+ 'fib_slow_autotest',
+ 'fib_perf_autotest',
+ 'red_all',
+ 'barrier_autotest',
+ 'hash_multiwriter_autotest',
+ 'timer_racecond_autotest',
+ 'efd_autotest',
+ 'hash_functions_autotest',
+ 'member_perf_autotest',
+ 'efd_perf_autotest',
+ 'lpm6_perf_autotest',
+ 'rib6_slow_autotest',
+ 'fib6_slow_autotest',
+ 'fib6_perf_autotest',
+ 'rcu_qsbr_perf_autotest',
+ 'red_perf',
+ 'distributor_perf_autotest',
+ 'pmd_perf_autotest',
+ 'stack_perf_autotest',
+ 'stack_lf_perf_autotest',
+ 'rand_perf_autotest',
+ 'hash_readwrite_perf_autotest',
+ 'hash_readwrite_lf_perf_autotest',
+ 'trace_perf_autotest',
+ 'ipsec_perf_autotest',
+]
+
+driver_test_names = [
+ 'cryptodev_aesni_mb_autotest',
+ 'cryptodev_aesni_gcm_autotest',
+ 'cryptodev_dpaa_sec_autotest',
+ 'cryptodev_dpaa2_sec_autotest',
+ 'cryptodev_null_autotest',
+ 'cryptodev_octeontx2_autotest',
+ 'cryptodev_openssl_autotest',
+ 'cryptodev_openssl_asym_autotest',
+ 'cryptodev_qat_autotest',
+ 'cryptodev_sw_armv8_autotest',
+ 'cryptodev_sw_kasumi_autotest',
+ 'cryptodev_sw_mvsam_autotest',
+ 'cryptodev_sw_snow3g_autotest',
+ 'cryptodev_sw_zuc_autotest',
+ 'eventdev_selftest_octeontx',
+ 'eventdev_selftest_sw',
+ 'rawdev_autotest',
+]
+
+dump_test_names = [
+ 'dump_struct_sizes',
+ 'dump_mempool',
+ 'dump_malloc_stats',
+ 'dump_devargs',
+ 'dump_log_types',
+ 'dump_ring',
+ 'dump_physmem',
+ 'dump_memzone',
+]
+
+# The following linkages are an exception to allow running the
+# unit tests without requiring that the developer install the
+# DPDK libraries. Explicit linkage of drivers (plugin libraries)
+# in applications should not be used.
+if dpdk_conf.has('RTE_LIBRTE_RING_MEMPOOL')
+ test_deps += 'mempool_ring'
+endif
+if dpdk_conf.has('RTE_LIBRTE_STACK_MEMPOOL')
+ test_deps += 'mempool_stack'
+endif
+if dpdk_conf.has('RTE_LIBRTE_SKELETON_EVENTDEV_PMD')
+ test_deps += 'pmd_skeleton_event'
+endif
+if dpdk_conf.has('RTE_LIBRTE_TELEMETRY')
+ test_sources += 'test_telemetry_json.c'
+ fast_tests += [['telemetry_json_autotest', true]]
+endif
+
+# The following linkages of drivers are required because
+# they are used via a driver-specific API.
+if dpdk_conf.has('RTE_LIBRTE_BOND_PMD')
+ test_deps += 'pmd_bond'
+ test_sources += ['test_link_bonding.c', 'test_link_bonding_rssconf.c']
+ driver_test_names += ['link_bonding_autotest', 'link_bonding_rssconf_autotest']
+endif
+if dpdk_conf.has('RTE_LIBRTE_RING_PMD')
+ test_deps += 'pmd_ring'
+ test_sources += 'test_pmd_ring_perf.c'
+ test_sources += 'test_pmd_ring.c'
+ test_sources += 'test_event_eth_tx_adapter.c'
+ test_sources += 'test_bitratestats.c'
+ test_sources += 'test_latencystats.c'
+ test_sources += 'test_link_bonding_mode4.c'
+ test_sources += 'sample_packet_forward.c'
+ test_sources += 'test_pdump.c'
+ fast_tests += [['ring_pmd_autotest', true]]
+ perf_test_names += 'ring_pmd_perf_autotest'
+ fast_tests += [['event_eth_tx_adapter_autotest', false]]
+ fast_tests += [['bitratestats_autotest', true]]
+ fast_tests += [['latencystats_autotest', true]]
+ driver_test_names += 'link_bonding_mode4_autotest'
+ fast_tests += [['pdump_autotest', true]]
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_POWER')
+ test_deps += 'power'
+endif
+if dpdk_conf.has('RTE_LIBRTE_KNI')
+ test_deps += 'kni'
+endif
+if dpdk_conf.has('RTE_LIBRTE_PDUMP')
+ test_deps += 'pdump'
+endif
+
+if cc.has_argument('-Wno-format-truncation')
+ cflags += '-Wno-format-truncation'
+endif
+
+# specify -D_GNU_SOURCE unconditionally
+cflags += '-D_GNU_SOURCE'
+# Strict-aliasing rules are violated by uint8_t[] to context size casts.
+cflags += '-fno-strict-aliasing'
+
+test_dep_objs = []
+if dpdk_conf.has('RTE_LIBRTE_COMPRESSDEV')
+ compress_test_dep = dependency('zlib', required: false)
+ if compress_test_dep.found()
+ test_dep_objs += compress_test_dep
+ test_sources += 'test_compressdev.c'
+ test_deps += 'compressdev'
+ fast_tests += [['compressdev_autotest', false]]
+ endif
+endif
+
+if dpdk_conf.has('RTE_LIBRTE_PMD_CRYPTO_SCHEDULER')
+ driver_test_names += 'cryptodev_scheduler_autotest'
+endif
+
+foreach d:test_deps
+ def_lib = get_option('default_library')
+ test_dep_objs += get_variable(def_lib + '_rte_' + d)
+endforeach
+test_dep_objs += cc.find_library('execinfo', required: false)
+
+link_libs = []
+link_nodes = []
+if get_option('default_library') == 'static'
+ link_libs = dpdk_drivers
+ link_nodes = dpdk_graph_nodes
+endif
+
+dpdk_test = executable('dpdk-test',
+ test_sources,
+ link_whole: link_libs + link_nodes,
+ dependencies: test_dep_objs,
+ c_args: cflags,
+ install_rpath: driver_install_path,
+ install: true)
+
+has_hugepage = run_command('has-hugepage.sh').stdout().strip() != '0'
+message('hugepage availability: @0@'.format(has_hugepage))
+
+# some perf tests (eg: memcpy perf autotest)take very long
+# to complete, so timeout to 10 minutes
+timeout_seconds = 600
+timeout_seconds_fast = 10
+
+get_coremask = find_program('get-coremask.sh')
+num_cores_arg = '-l ' + run_command(get_coremask).stdout().strip()
+
+default_test_args = [num_cores_arg]
+
+foreach arg : fast_tests
+ test_args = default_test_args
+ run_test = true
+ if not has_hugepage
+ if arg[1]
+ test_args += ['--no-huge', '-m', '2048']
+ else
+ run_test = false
+ endif
+ endif
+
+ if (get_option('default_library') == 'shared' and
+ arg[0] == 'event_eth_tx_adapter_autotest')
+ foreach drv:dpdk_drivers
+ test_args += ['-d', drv.full_path().split('.a')[0] + '.so']
+ endforeach
+ endif
+ if is_linux
+ test_args += ['--file-prefix=@0@'.format(arg[0])]
+ endif
+
+ if run_test
+ test(arg[0], dpdk_test,
+ env : ['DPDK_TEST=' + arg[0]],
+ args : test_args,
+ timeout : timeout_seconds_fast,
+ is_parallel : false,
+ suite : 'fast-tests')
+ endif
+endforeach
+
+foreach arg : perf_test_names
+ test(arg, dpdk_test,
+ env : ['DPDK_TEST=' + arg],
+ args : default_test_args,
+ timeout : timeout_seconds,
+ is_parallel : false,
+ suite : 'perf-tests')
+endforeach
+
+foreach arg : driver_test_names
+ test(arg, dpdk_test,
+ env : ['DPDK_TEST=' + arg],
+ args : default_test_args,
+ timeout : timeout_seconds,
+ is_parallel : false,
+ suite : 'driver-tests')
+endforeach
+
+foreach arg : dump_test_names
+ test(arg, dpdk_test,
+ env : ['DPDK_TEST=' + arg],
+ args : default_test_args,
+ timeout : timeout_seconds,
+ is_parallel : false,
+ suite : 'debug-tests')
+endforeach
diff --git a/src/spdk/dpdk/app/test/packet_burst_generator.c b/src/spdk/dpdk/app/test/packet_burst_generator.c
new file mode 100644
index 000000000..f203f9d09
--- /dev/null
+++ b/src/spdk/dpdk/app/test/packet_burst_generator.c
@@ -0,0 +1,457 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_byteorder.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+
+#include "packet_burst_generator.h"
+
+#define UDP_SRC_PORT 1024
+#define UDP_DST_PORT 1024
+
+
+#define IP_DEFTTL 64 /* from RFC 1340. */
+
+static void
+copy_buf_to_pkt_segs(void *buf, unsigned len, struct rte_mbuf *pkt,
+ unsigned offset)
+{
+ struct rte_mbuf *seg;
+ void *seg_buf;
+ unsigned copy_len;
+
+ seg = pkt;
+ while (offset >= seg->data_len) {
+ offset -= seg->data_len;
+ seg = seg->next;
+ }
+ copy_len = seg->data_len - offset;
+ seg_buf = rte_pktmbuf_mtod_offset(seg, char *, offset);
+ while (len > copy_len) {
+ rte_memcpy(seg_buf, buf, (size_t) copy_len);
+ len -= copy_len;
+ buf = ((char *) buf + copy_len);
+ seg = seg->next;
+ seg_buf = rte_pktmbuf_mtod(seg, void *);
+ }
+ rte_memcpy(seg_buf, buf, (size_t) len);
+}
+
+static inline void
+copy_buf_to_pkt(void *buf, unsigned len, struct rte_mbuf *pkt, unsigned offset)
+{
+ if (offset + len <= pkt->data_len) {
+ rte_memcpy(rte_pktmbuf_mtod_offset(pkt, char *, offset), buf,
+ (size_t) len);
+ return;
+ }
+ copy_buf_to_pkt_segs(buf, len, pkt, offset);
+}
+
+void
+initialize_eth_header(struct rte_ether_hdr *eth_hdr,
+ struct rte_ether_addr *src_mac,
+ struct rte_ether_addr *dst_mac, uint16_t ether_type,
+ uint8_t vlan_enabled, uint16_t van_id)
+{
+ rte_ether_addr_copy(dst_mac, &eth_hdr->d_addr);
+ rte_ether_addr_copy(src_mac, &eth_hdr->s_addr);
+
+ if (vlan_enabled) {
+ struct rte_vlan_hdr *vhdr = (struct rte_vlan_hdr *)(
+ (uint8_t *)eth_hdr + sizeof(struct rte_ether_hdr));
+
+ eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+
+ vhdr->eth_proto = rte_cpu_to_be_16(ether_type);
+ vhdr->vlan_tci = van_id;
+ } else {
+ eth_hdr->ether_type = rte_cpu_to_be_16(ether_type);
+ }
+}
+
+void
+initialize_arp_header(struct rte_arp_hdr *arp_hdr,
+ struct rte_ether_addr *src_mac,
+ struct rte_ether_addr *dst_mac,
+ uint32_t src_ip, uint32_t dst_ip,
+ uint32_t opcode)
+{
+ arp_hdr->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER);
+ arp_hdr->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ arp_hdr->arp_hlen = RTE_ETHER_ADDR_LEN;
+ arp_hdr->arp_plen = sizeof(uint32_t);
+ arp_hdr->arp_opcode = rte_cpu_to_be_16(opcode);
+ rte_ether_addr_copy(src_mac, &arp_hdr->arp_data.arp_sha);
+ arp_hdr->arp_data.arp_sip = src_ip;
+ rte_ether_addr_copy(dst_mac, &arp_hdr->arp_data.arp_tha);
+ arp_hdr->arp_data.arp_tip = dst_ip;
+}
+
+uint16_t
+initialize_udp_header(struct rte_udp_hdr *udp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len)
+{
+ uint16_t pkt_len;
+
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
+
+ udp_hdr->src_port = rte_cpu_to_be_16(src_port);
+ udp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
+ udp_hdr->dgram_len = rte_cpu_to_be_16(pkt_len);
+ udp_hdr->dgram_cksum = 0; /* No UDP checksum. */
+
+ return pkt_len;
+}
+
+uint16_t
+initialize_tcp_header(struct rte_tcp_hdr *tcp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len)
+{
+ uint16_t pkt_len;
+
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_tcp_hdr));
+
+ memset(tcp_hdr, 0, sizeof(struct rte_tcp_hdr));
+ tcp_hdr->src_port = rte_cpu_to_be_16(src_port);
+ tcp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
+
+ return pkt_len;
+}
+
+uint16_t
+initialize_sctp_header(struct rte_sctp_hdr *sctp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len)
+{
+ uint16_t pkt_len;
+
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
+
+ sctp_hdr->src_port = rte_cpu_to_be_16(src_port);
+ sctp_hdr->dst_port = rte_cpu_to_be_16(dst_port);
+ sctp_hdr->tag = 0;
+ sctp_hdr->cksum = 0; /* No SCTP checksum. */
+
+ return pkt_len;
+}
+
+uint16_t
+initialize_ipv6_header(struct rte_ipv6_hdr *ip_hdr, uint8_t *src_addr,
+ uint8_t *dst_addr, uint16_t pkt_data_len)
+{
+ ip_hdr->vtc_flow = 0;
+ ip_hdr->payload_len = pkt_data_len;
+ ip_hdr->proto = IPPROTO_UDP;
+ ip_hdr->hop_limits = IP_DEFTTL;
+
+ rte_memcpy(ip_hdr->src_addr, src_addr, sizeof(ip_hdr->src_addr));
+ rte_memcpy(ip_hdr->dst_addr, dst_addr, sizeof(ip_hdr->dst_addr));
+
+ return (uint16_t) (pkt_data_len + sizeof(struct rte_ipv6_hdr));
+}
+
+uint16_t
+initialize_ipv4_header(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
+ uint32_t dst_addr, uint16_t pkt_data_len)
+{
+ uint16_t pkt_len;
+ unaligned_uint16_t *ptr16;
+ uint32_t ip_cksum;
+
+ /*
+ * Initialize IP header.
+ */
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_ipv4_hdr));
+
+ ip_hdr->version_ihl = RTE_IPV4_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = IPPROTO_UDP;
+ ip_hdr->packet_id = 0;
+ ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
+ ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
+
+ /*
+ * Compute IP header checksum.
+ */
+ ptr16 = (unaligned_uint16_t *)ip_hdr;
+ ip_cksum = 0;
+ ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
+ ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
+ ip_cksum += ptr16[4];
+ ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
+ ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
+
+ /*
+ * Reduce 32 bit checksum to 16 bits and complement it.
+ */
+ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
+ (ip_cksum & 0x0000FFFF);
+ ip_cksum %= 65536;
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ if (ip_cksum == 0)
+ ip_cksum = 0xFFFF;
+ ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+
+ return pkt_len;
+}
+
+uint16_t
+initialize_ipv4_header_proto(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
+ uint32_t dst_addr, uint16_t pkt_data_len, uint8_t proto)
+{
+ uint16_t pkt_len;
+ unaligned_uint16_t *ptr16;
+ uint32_t ip_cksum;
+
+ /*
+ * Initialize IP header.
+ */
+ pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_ipv4_hdr));
+
+ ip_hdr->version_ihl = RTE_IPV4_VHL_DEF;
+ ip_hdr->type_of_service = 0;
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = IP_DEFTTL;
+ ip_hdr->next_proto_id = proto;
+ ip_hdr->packet_id = 0;
+ ip_hdr->total_length = rte_cpu_to_be_16(pkt_len);
+ ip_hdr->src_addr = rte_cpu_to_be_32(src_addr);
+ ip_hdr->dst_addr = rte_cpu_to_be_32(dst_addr);
+
+ /*
+ * Compute IP header checksum.
+ */
+ ptr16 = (unaligned_uint16_t *)ip_hdr;
+ ip_cksum = 0;
+ ip_cksum += ptr16[0]; ip_cksum += ptr16[1];
+ ip_cksum += ptr16[2]; ip_cksum += ptr16[3];
+ ip_cksum += ptr16[4];
+ ip_cksum += ptr16[6]; ip_cksum += ptr16[7];
+ ip_cksum += ptr16[8]; ip_cksum += ptr16[9];
+
+ /*
+ * Reduce 32 bit checksum to 16 bits and complement it.
+ */
+ ip_cksum = ((ip_cksum & 0xFFFF0000) >> 16) +
+ (ip_cksum & 0x0000FFFF);
+ ip_cksum %= 65536;
+ ip_cksum = (~ip_cksum) & 0x0000FFFF;
+ if (ip_cksum == 0)
+ ip_cksum = 0xFFFF;
+ ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
+
+ return pkt_len;
+}
+
+/*
+ * The maximum number of segments per packet is used when creating
+ * scattered transmit packets composed of a list of mbufs.
+ */
+#define RTE_MAX_SEGS_PER_PKT 255 /**< pkt.nb_segs is a 8-bit unsigned char. */
+
+
+int
+generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
+ struct rte_ether_hdr *eth_hdr, uint8_t vlan_enabled,
+ void *ip_hdr, uint8_t ipv4, struct rte_udp_hdr *udp_hdr,
+ int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs)
+{
+ int i, nb_pkt = 0;
+ size_t eth_hdr_size;
+
+ struct rte_mbuf *pkt_seg;
+ struct rte_mbuf *pkt;
+
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_pktmbuf_alloc(mp);
+ if (pkt == NULL) {
+nomore_mbuf:
+ if (nb_pkt == 0)
+ return -1;
+ break;
+ }
+
+ pkt->data_len = pkt_len;
+ pkt_seg = pkt;
+ for (i = 1; i < nb_pkt_segs; i++) {
+ pkt_seg->next = rte_pktmbuf_alloc(mp);
+ if (pkt_seg->next == NULL) {
+ pkt->nb_segs = i;
+ rte_pktmbuf_free(pkt);
+ goto nomore_mbuf;
+ }
+ pkt_seg = pkt_seg->next;
+ pkt_seg->data_len = pkt_len;
+ }
+ pkt_seg->next = NULL; /* Last segment of packet. */
+
+ /*
+ * Copy headers in first packet segment(s).
+ */
+ if (vlan_enabled)
+ eth_hdr_size = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_vlan_hdr);
+ else
+ eth_hdr_size = sizeof(struct rte_ether_hdr);
+
+ copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
+
+ if (ipv4) {
+ copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv4_hdr),
+ pkt, eth_hdr_size);
+ copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
+ eth_hdr_size + sizeof(struct rte_ipv4_hdr));
+ } else {
+ copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
+ pkt, eth_hdr_size);
+ copy_buf_to_pkt(udp_hdr, sizeof(*udp_hdr), pkt,
+ eth_hdr_size + sizeof(struct rte_ipv6_hdr));
+ }
+
+ /*
+ * Complete first mbuf of packet and append it to the
+ * burst of packets to be transmitted.
+ */
+ pkt->nb_segs = nb_pkt_segs;
+ pkt->pkt_len = pkt_len;
+ pkt->l2_len = eth_hdr_size;
+
+ if (ipv4) {
+ pkt->vlan_tci = RTE_ETHER_TYPE_IPV4;
+ pkt->l3_len = sizeof(struct rte_ipv4_hdr);
+ } else {
+ pkt->vlan_tci = RTE_ETHER_TYPE_IPV6;
+ pkt->l3_len = sizeof(struct rte_ipv6_hdr);
+ }
+
+ pkts_burst[nb_pkt] = pkt;
+ }
+
+ return nb_pkt;
+}
+
+int
+generate_packet_burst_proto(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, struct rte_ether_hdr *eth_hdr,
+ uint8_t vlan_enabled, void *ip_hdr,
+ uint8_t ipv4, uint8_t proto, void *proto_hdr,
+ int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs)
+{
+ int i, nb_pkt = 0;
+ size_t eth_hdr_size;
+
+ struct rte_mbuf *pkt_seg;
+ struct rte_mbuf *pkt;
+
+ for (nb_pkt = 0; nb_pkt < nb_pkt_per_burst; nb_pkt++) {
+ pkt = rte_pktmbuf_alloc(mp);
+ if (pkt == NULL) {
+nomore_mbuf:
+ if (nb_pkt == 0)
+ return -1;
+ break;
+ }
+
+ pkt->data_len = pkt_len;
+ pkt_seg = pkt;
+ for (i = 1; i < nb_pkt_segs; i++) {
+ pkt_seg->next = rte_pktmbuf_alloc(mp);
+ if (pkt_seg->next == NULL) {
+ pkt->nb_segs = i;
+ rte_pktmbuf_free(pkt);
+ goto nomore_mbuf;
+ }
+ pkt_seg = pkt_seg->next;
+ pkt_seg->data_len = pkt_len;
+ }
+ pkt_seg->next = NULL; /* Last segment of packet. */
+
+ /*
+ * Copy headers in first packet segment(s).
+ */
+ if (vlan_enabled)
+ eth_hdr_size = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_vlan_hdr);
+ else
+ eth_hdr_size = sizeof(struct rte_ether_hdr);
+
+ copy_buf_to_pkt(eth_hdr, eth_hdr_size, pkt, 0);
+
+ if (ipv4) {
+ copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv4_hdr),
+ pkt, eth_hdr_size);
+ switch (proto) {
+ case IPPROTO_UDP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_udp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv4_hdr));
+ break;
+ case IPPROTO_TCP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_tcp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv4_hdr));
+ break;
+ case IPPROTO_SCTP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_sctp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv4_hdr));
+ break;
+ default:
+ break;
+ }
+ } else {
+ copy_buf_to_pkt(ip_hdr, sizeof(struct rte_ipv6_hdr),
+ pkt, eth_hdr_size);
+ switch (proto) {
+ case IPPROTO_UDP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_udp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv6_hdr));
+ break;
+ case IPPROTO_TCP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_tcp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv6_hdr));
+ break;
+ case IPPROTO_SCTP:
+ copy_buf_to_pkt(proto_hdr,
+ sizeof(struct rte_sctp_hdr), pkt,
+ eth_hdr_size +
+ sizeof(struct rte_ipv6_hdr));
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Complete first mbuf of packet and append it to the
+ * burst of packets to be transmitted.
+ */
+ pkt->nb_segs = nb_pkt_segs;
+ pkt->pkt_len = pkt_len;
+ pkt->l2_len = eth_hdr_size;
+
+ if (ipv4) {
+ pkt->vlan_tci = RTE_ETHER_TYPE_IPV4;
+ pkt->l3_len = sizeof(struct rte_ipv4_hdr);
+ } else {
+ pkt->vlan_tci = RTE_ETHER_TYPE_IPV6;
+ pkt->l3_len = sizeof(struct rte_ipv6_hdr);
+ }
+
+ pkts_burst[nb_pkt] = pkt;
+ }
+
+ return nb_pkt;
+}
diff --git a/src/spdk/dpdk/app/test/packet_burst_generator.h b/src/spdk/dpdk/app/test/packet_burst_generator.h
new file mode 100644
index 000000000..b99286f50
--- /dev/null
+++ b/src/spdk/dpdk/app/test/packet_burst_generator.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef PACKET_BURST_GENERATOR_H_
+#define PACKET_BURST_GENERATOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_mbuf.h>
+#include <rte_ether.h>
+#include <rte_arp.h>
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_tcp.h>
+#include <rte_sctp.h>
+
+#define IPV4_ADDR(a, b, c, d)(((a & 0xff) << 24) | ((b & 0xff) << 16) | \
+ ((c & 0xff) << 8) | (d & 0xff))
+
+#define PACKET_BURST_GEN_PKT_LEN 60
+#define PACKET_BURST_GEN_PKT_LEN_128 128
+
+void
+initialize_eth_header(struct rte_ether_hdr *eth_hdr,
+ struct rte_ether_addr *src_mac,
+ struct rte_ether_addr *dst_mac, uint16_t ether_type,
+ uint8_t vlan_enabled, uint16_t van_id);
+
+void
+initialize_arp_header(struct rte_arp_hdr *arp_hdr,
+ struct rte_ether_addr *src_mac, struct rte_ether_addr *dst_mac,
+ uint32_t src_ip, uint32_t dst_ip, uint32_t opcode);
+
+uint16_t
+initialize_udp_header(struct rte_udp_hdr *udp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len);
+
+uint16_t
+initialize_tcp_header(struct rte_tcp_hdr *tcp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len);
+
+uint16_t
+initialize_sctp_header(struct rte_sctp_hdr *sctp_hdr, uint16_t src_port,
+ uint16_t dst_port, uint16_t pkt_data_len);
+
+uint16_t
+initialize_ipv6_header(struct rte_ipv6_hdr *ip_hdr, uint8_t *src_addr,
+ uint8_t *dst_addr, uint16_t pkt_data_len);
+
+uint16_t
+initialize_ipv4_header(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
+ uint32_t dst_addr, uint16_t pkt_data_len);
+
+uint16_t
+initialize_ipv4_header_proto(struct rte_ipv4_hdr *ip_hdr, uint32_t src_addr,
+ uint32_t dst_addr, uint16_t pkt_data_len, uint8_t proto);
+
+int
+generate_packet_burst(struct rte_mempool *mp, struct rte_mbuf **pkts_burst,
+ struct rte_ether_hdr *eth_hdr, uint8_t vlan_enabled,
+ void *ip_hdr, uint8_t ipv4, struct rte_udp_hdr *udp_hdr,
+ int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs);
+
+int
+generate_packet_burst_proto(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, struct rte_ether_hdr *eth_hdr,
+ uint8_t vlan_enabled, void *ip_hdr,
+ uint8_t ipv4, uint8_t proto, void *proto_hdr,
+ int nb_pkt_per_burst, uint8_t pkt_len, uint8_t nb_pkt_segs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PACKET_BURST_GENERATOR_H_ */
diff --git a/src/spdk/dpdk/app/test/process.h b/src/spdk/dpdk/app/test/process.h
new file mode 100644
index 000000000..c3b378033
--- /dev/null
+++ b/src/spdk/dpdk/app/test/process.h
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _PROCESS_H_
+#define _PROCESS_H_
+
+#include <errno.h> /* errno */
+#include <limits.h> /* PATH_MAX */
+#include <libgen.h> /* basename et al */
+#include <stdlib.h> /* NULL */
+#include <string.h> /* strerror */
+#include <unistd.h> /* readlink */
+#include <dirent.h>
+#include <sys/wait.h>
+
+#include <rte_string_fns.h> /* strlcpy */
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+#define self "curproc"
+#define exe "file"
+#else
+#define self "self"
+#define exe "exe"
+#endif
+
+#ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
+#include <pthread.h>
+extern void *send_pkts(void *empty);
+extern uint16_t flag_for_send_pkts;
+#endif
+#endif
+
+/*
+ * launches a second copy of the test process using the given argv parameters,
+ * which should include argv[0] as the process name. To identify in the
+ * subprocess the source of the call, the env_value parameter is set in the
+ * environment as $RTE_TEST
+ */
+static inline int
+process_dup(const char *const argv[], int numargs, const char *env_value)
+{
+ int num;
+ char *argv_cpy[numargs + 1];
+ int i, status;
+ char path[32];
+#ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
+ pthread_t thread;
+#endif
+#endif
+
+ pid_t pid = fork();
+ if (pid < 0)
+ return -1;
+ else if (pid == 0) {
+ /* make a copy of the arguments to be passed to exec */
+ for (i = 0; i < numargs; i++)
+ argv_cpy[i] = strdup(argv[i]);
+ argv_cpy[i] = NULL;
+ num = numargs;
+
+#ifdef RTE_EXEC_ENV_LINUX
+ {
+ const char *procdir = "/proc/" self "/fd/";
+ struct dirent *dirent;
+ char *endptr;
+ int fd, fdir;
+ DIR *dir;
+
+ /* close all open file descriptors, check /proc/self/fd
+ * to only call close on open fds. Exclude fds 0, 1 and
+ * 2
+ */
+ dir = opendir(procdir);
+ if (dir == NULL) {
+ rte_panic("Error opening %s: %s\n", procdir,
+ strerror(errno));
+ }
+
+ fdir = dirfd(dir);
+ if (fdir < 0) {
+ status = errno;
+ closedir(dir);
+ rte_panic("Error %d obtaining fd for dir %s: %s\n",
+ fdir, procdir,
+ strerror(status));
+ }
+
+ while ((dirent = readdir(dir)) != NULL) {
+ errno = 0;
+ fd = strtol(dirent->d_name, &endptr, 10);
+ if (errno != 0 || endptr[0] != '\0') {
+ printf("Error converting name fd %d %s:\n",
+ fd, dirent->d_name);
+ continue;
+ }
+
+ if (fd == fdir || fd <= 2)
+ continue;
+
+ close(fd);
+ }
+ closedir(dir);
+ }
+#endif
+ printf("Running binary with argv[]:");
+ for (i = 0; i < num; i++)
+ printf("'%s' ", argv_cpy[i]);
+ printf("\n");
+
+ /* set the environment variable */
+ if (setenv(RECURSIVE_ENV_VAR, env_value, 1) != 0)
+ rte_panic("Cannot export environment variable\n");
+
+ strlcpy(path, "/proc/" self "/" exe, sizeof(path));
+ if (execv(path, argv_cpy) < 0) {
+ if (errno == ENOENT) {
+ printf("Could not find '%s', is procfs mounted?\n",
+ path);
+ }
+ rte_panic("Cannot exec: %s\n", strerror(errno));
+ }
+ }
+ /* parent process does a wait */
+#ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
+ if ((strcmp(env_value, "run_pdump_server_tests") == 0))
+ pthread_create(&thread, NULL, &send_pkts, NULL);
+#endif
+#endif
+
+ while (wait(&status) != pid)
+ ;
+#ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
+ if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
+ flag_for_send_pkts = 0;
+ pthread_join(thread, NULL);
+ }
+#endif
+#endif
+ return status;
+}
+
+/* FreeBSD doesn't support file prefixes, so force compile failures for any
+ * tests attempting to use this function on FreeBSD.
+ */
+#ifdef RTE_EXEC_ENV_LINUX
+static char *
+get_current_prefix(char *prefix, int size)
+{
+ char path[PATH_MAX] = {0};
+ char buf[PATH_MAX] = {0};
+
+ /* get file for config (fd is always 3) */
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", 3);
+
+ /* return NULL on error */
+ if (readlink(path, buf, sizeof(buf)) == -1)
+ return NULL;
+
+ /* get the prefix */
+ snprintf(prefix, size, "%s", basename(dirname(buf)));
+
+ return prefix;
+}
+#endif
+
+#endif /* _PROCESS_H_ */
diff --git a/src/spdk/dpdk/app/test/resource.c b/src/spdk/dpdk/app/test/resource.c
new file mode 100644
index 000000000..34465f166
--- /dev/null
+++ b/src/spdk/dpdk/app/test/resource.c
@@ -0,0 +1,276 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_debug.h>
+
+#include "resource.h"
+
+struct resource_list resource_list = TAILQ_HEAD_INITIALIZER(resource_list);
+
+size_t resource_size(const struct resource *r)
+{
+ return r->end - r->begin;
+}
+
+const struct resource *resource_find(const char *name)
+{
+ struct resource *r;
+
+ TAILQ_FOREACH(r, &resource_list, next) {
+ RTE_VERIFY(r->name);
+
+ if (!strcmp(r->name, name))
+ return r;
+ }
+
+ return NULL;
+}
+
+int resource_fwrite(const struct resource *r, FILE *f)
+{
+ const size_t goal = resource_size(r);
+ size_t total = 0;
+
+ while (total < goal) {
+ size_t wlen = fwrite(r->begin + total, 1, goal - total, f);
+ if (wlen == 0) {
+ perror(__func__);
+ return -1;
+ }
+
+ total += wlen;
+ }
+
+ return 0;
+}
+
+int resource_fwrite_file(const struct resource *r, const char *fname)
+{
+ FILE *f;
+ int ret;
+
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ perror(__func__);
+ return -1;
+ }
+
+ ret = resource_fwrite(r, f);
+ fclose(f);
+ return ret;
+}
+
+#ifdef RTE_APP_TEST_RESOURCE_TAR
+#include <archive.h>
+#include <archive_entry.h>
+
+static int do_copy(struct archive *r, struct archive *w)
+{
+ const void *buf;
+ size_t len;
+#if ARCHIVE_VERSION_NUMBER >= 3000000
+ int64_t off;
+#else
+ off_t off;
+#endif
+ int ret;
+
+ while (1) {
+ ret = archive_read_data_block(r, &buf, &len, &off);
+ if (ret == ARCHIVE_RETRY)
+ continue;
+
+ if (ret == ARCHIVE_EOF)
+ return 0;
+
+ if (ret != ARCHIVE_OK)
+ return ret;
+
+ do {
+ ret = archive_write_data_block(w, buf, len, off);
+ if (ret != ARCHIVE_OK && ret != ARCHIVE_RETRY)
+ return ret;
+ } while (ret != ARCHIVE_OK);
+ }
+}
+
+int resource_untar(const struct resource *res)
+{
+ struct archive *r;
+ struct archive *w;
+ struct archive_entry *e;
+ void *p;
+ int flags = 0;
+ int ret;
+
+ p = malloc(resource_size(res));
+ if (p == NULL)
+ rte_panic("Failed to malloc %zu B\n", resource_size(res));
+
+ memcpy(p, res->begin, resource_size(res));
+
+ r = archive_read_new();
+ if (r == NULL) {
+ free(p);
+ return -1;
+ }
+
+ archive_read_support_format_all(r);
+ archive_read_support_filter_all(r);
+
+ w = archive_write_disk_new();
+ if (w == NULL) {
+ archive_read_free(r);
+ free(p);
+ return -1;
+ }
+
+ flags |= ARCHIVE_EXTRACT_PERM;
+ flags |= ARCHIVE_EXTRACT_FFLAGS;
+ archive_write_disk_set_options(w, flags);
+ archive_write_disk_set_standard_lookup(w);
+
+ ret = archive_read_open_memory(r, p, resource_size(res));
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ while (1) {
+ ret = archive_read_next_header(r, &e);
+ if (ret == ARCHIVE_EOF)
+ break;
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ ret = archive_write_header(w, e);
+ if (ret == ARCHIVE_EOF)
+ break;
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ if (archive_entry_size(e) == 0)
+ continue;
+
+ ret = do_copy(r, w);
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ ret = archive_write_finish_entry(w);
+ if (ret != ARCHIVE_OK)
+ goto fail;
+ }
+
+ archive_write_free(w);
+ archive_read_free(r);
+ free(p);
+ return 0;
+
+fail:
+ archive_write_free(w);
+ archive_read_free(r);
+ free(p);
+ rte_panic("Failed: %s\n", archive_error_string(r));
+ return -1;
+}
+
+int resource_rm_by_tar(const struct resource *res)
+{
+ struct archive *r;
+ struct archive_entry *e;
+ void *p;
+ int try_again = 1;
+ int attempts = 0;
+ int ret;
+
+ p = malloc(resource_size(res));
+ if (p == NULL)
+ rte_panic("Failed to malloc %zu B\n", resource_size(res));
+
+ memcpy(p, res->begin, resource_size(res));
+
+ /*
+ * If somebody creates a file somewhere inside the extracted TAR
+ * hierarchy during a test the resource_rm_by_tar might loop
+ * infinitely. We prevent this by adding the attempts counter there.
+ * In normal case, max N iteration is done where N is the depth of
+ * the file-hierarchy.
+ */
+ while (try_again && attempts < 10000) {
+ r = archive_read_new();
+ if (r == NULL) {
+ free(p);
+ return -1;
+ }
+
+ archive_read_support_format_all(r);
+ archive_read_support_filter_all(r);
+
+ ret = archive_read_open_memory(r, p, resource_size(res));
+ if (ret != ARCHIVE_OK) {
+ fprintf(stderr, "Failed: %s\n",
+ archive_error_string(r));
+ goto fail;
+ }
+
+ try_again = 0;
+
+ while (1) {
+ ret = archive_read_next_header(r, &e);
+ if (ret == ARCHIVE_EOF)
+ break;
+ if (ret != ARCHIVE_OK)
+ goto fail;
+
+ ret = remove(archive_entry_pathname(e));
+ if (ret < 0) {
+ switch (errno) {
+ case ENOTEMPTY:
+ case EEXIST:
+ try_again = 1;
+ break;
+
+ /* should not usually happen: */
+ case ENOENT:
+ case ENOTDIR:
+ case EROFS:
+ attempts += 1;
+ continue;
+ default:
+ perror("Failed to remove file");
+ goto fail;
+ }
+ }
+ }
+
+ archive_read_free(r);
+ attempts += 1;
+ }
+
+ if (attempts >= 10000) {
+ fprintf(stderr, "Failed to remove archive\n");
+ free(p);
+ return -1;
+ }
+
+ free(p);
+ return 0;
+
+fail:
+ archive_read_free(r);
+ free(p);
+
+ rte_panic("Failed: %s\n", archive_error_string(r));
+ return -1;
+}
+
+#endif /* RTE_APP_TEST_RESOURCE_TAR */
+
+void resource_register(struct resource *r)
+{
+ TAILQ_INSERT_TAIL(&resource_list, r, next);
+}
diff --git a/src/spdk/dpdk/app/test/resource.h b/src/spdk/dpdk/app/test/resource.h
new file mode 100644
index 000000000..c75ebd4b5
--- /dev/null
+++ b/src/spdk/dpdk/app/test/resource.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ */
+
+#ifndef _RESOURCE_H_
+#define _RESOURCE_H_
+
+/**
+ * @file
+ *
+ * Test Resource API
+ *
+ * Each test can require and use some external resources. Usually, an external
+ * resource is a file or a filesystem sub-hierarchy. A resource is included
+ * inside the test executable.
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <stddef.h>
+
+#include <rte_eal.h>
+#include <rte_common.h>
+
+TAILQ_HEAD(resource_list, resource);
+extern struct resource_list resource_list;
+
+/**
+ * Representation of a resource. It points to the resource's binary data.
+ * The semantics of the binary data are defined by the target test.
+ */
+struct resource {
+ const char *name; /**< Unique name of the resource */
+ const char *begin; /**< Start of resource data */
+ const char *end; /**< End of resource data */
+ TAILQ_ENTRY(resource) next;
+};
+
+/**
+ * @return size of the given resource
+ */
+size_t resource_size(const struct resource *r);
+
+/**
+ * Find a resource by name in the global list of resources.
+ */
+const struct resource *resource_find(const char *name);
+
+/**
+ * Write the raw data of the resource to the given file.
+ * @return 0 on success
+ */
+int resource_fwrite(const struct resource *r, FILE *f);
+
+/**
+ * Write the raw data of the resource to the given file given by name.
+ * The name is relative to the current working directory.
+ * @return 0 on success
+ */
+int resource_fwrite_file(const struct resource *r, const char *fname);
+
+/**
+ * Treat the given resource as a tar archive. Extract
+ * the archive to the current directory.
+ */
+int resource_untar(const struct resource *res);
+
+/**
+ * Treat the given resource as a tar archive. Remove
+ * all files (related to the current directory) listed
+ * in the tar archive.
+ */
+int resource_rm_by_tar(const struct resource *res);
+
+/**
+ * Register a resource in the global list of resources.
+ * Not intended for direct use, please check the REGISTER_RESOURCE
+ * macro.
+ */
+void resource_register(struct resource *r);
+
+/**
+ * Definition of a resource linked externally (by means of the used toolchain).
+ * Only the base name of the resource is expected. The name refers to the
+ * linked pointers beg_<name> and end_<name> provided externally.
+ */
+#define REGISTER_LINKED_RESOURCE(n) \
+extern const char beg_ ##n; \
+extern const char end_ ##n; \
+REGISTER_RESOURCE(n, &beg_ ##n, &end_ ##n) \
+
+/**
+ * Definition of a resource described by its name, and pointers begin, end.
+ */
+#define REGISTER_RESOURCE(n, b, e) \
+static struct resource linkres_ ##n = { \
+ .name = RTE_STR(n), \
+ .begin = b, \
+ .end = e, \
+}; \
+RTE_INIT(resinitfn_ ##n) \
+{ \
+ resource_register(&linkres_ ##n); \
+}
+
+#endif
diff --git a/src/spdk/dpdk/app/test/sample_packet_forward.c b/src/spdk/dpdk/app/test/sample_packet_forward.c
new file mode 100644
index 000000000..61384b3d9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/sample_packet_forward.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_eth_ring.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+#include <rte_bus_vdev.h>
+#include "rte_lcore.h"
+#include "rte_mempool.h"
+#include "rte_ring.h"
+
+#include "sample_packet_forward.h"
+
+/* Sample test to create virtual rings and tx,rx portid from rings */
+int
+test_ring_setup(struct rte_ring **ring, uint16_t *portid)
+{
+ *ring = rte_ring_create("R0", RING_SIZE, rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (*ring == NULL) {
+ printf("%s() line %u: rte_ring_create R0 failed",
+ __func__, __LINE__);
+ return -1;
+ }
+ *portid = rte_eth_from_rings("net_ringa", ring, NUM_QUEUES,
+ ring, NUM_QUEUES, rte_socket_id());
+
+ return 0;
+}
+
+/* Sample test to free the mempool */
+void
+test_mp_free(struct rte_mempool *mp)
+{
+ rte_mempool_free(mp);
+}
+
+/* Sample test to free the virtual rings */
+void
+test_ring_free(struct rte_ring *rxtx)
+{
+ rte_ring_free(rxtx);
+}
+
+/* Sample test to release the vdev */
+void
+test_vdev_uninit(const char *vdev)
+{
+ rte_vdev_uninit(vdev);
+}
+
+/* sample test to allocate the mempool */
+int
+test_get_mempool(struct rte_mempool **mp, char *poolname)
+{
+ *mp = rte_pktmbuf_pool_create(poolname, NB_MBUF, 32, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ if (*mp == NULL)
+ return -1;
+ return 0;
+}
+
+/* sample test to allocate buffer for pkts */
+int
+test_get_mbuf_from_pool(struct rte_mempool **mp, struct rte_mbuf **pbuf,
+ char *poolname)
+{
+ int ret = 0;
+
+ ret = test_get_mempool(mp, poolname);
+ if (ret < 0)
+ return -1;
+ if (rte_pktmbuf_alloc_bulk(*mp, pbuf, NUM_PACKETS) != 0) {
+ printf("%s() line %u: rte_pktmbuf_alloc_bulk failed", __func__,
+ __LINE__);
+ return -1;
+ }
+ return 0;
+}
+
+/* sample test to deallocate the allocated buffers and mempool */
+void
+test_put_mbuf_to_pool(struct rte_mempool *mp, struct rte_mbuf **pbuf)
+{
+ int itr = 0;
+
+ for (itr = 0; itr < NUM_PACKETS; itr++)
+ rte_pktmbuf_free(pbuf[itr]);
+ rte_mempool_free(mp);
+}
+
+/* Sample test to forward packets using virtual portids */
+int
+test_packet_forward(struct rte_mbuf **pbuf, uint16_t portid, uint16_t queue_id)
+{
+ /* send and receive packet and check for stats update */
+ if (rte_eth_tx_burst(portid, queue_id, pbuf, NUM_PACKETS)
+ < NUM_PACKETS) {
+ printf("%s() line %u: Error sending packet to"
+ " port %d\n", __func__, __LINE__, portid);
+ return -1;
+ }
+ if (rte_eth_rx_burst(portid, queue_id, pbuf, NUM_PACKETS)
+ < NUM_PACKETS) {
+ printf("%s() line %u: Error receiving packet from"
+ " port %d\n", __func__, __LINE__, portid);
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/sample_packet_forward.h b/src/spdk/dpdk/app/test/sample_packet_forward.h
new file mode 100644
index 000000000..6789217de
--- /dev/null
+++ b/src/spdk/dpdk/app/test/sample_packet_forward.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _SAMPLE_PACKET_FORWARD_H_
+#define _SAMPLE_PACKET_FORWARD_H_
+
+#include <stdint.h>
+
+/* MACROS to support virtual ring creation */
+#define RING_SIZE 256
+#define NUM_QUEUES 1
+#define NB_MBUF 512
+
+#define NUM_PACKETS 10
+
+struct rte_mbuf;
+struct rte_mempool;
+struct rte_ring;
+
+/* Sample test to create virtual rings and tx,rx portid from rings */
+int test_ring_setup(struct rte_ring **ring, uint16_t *portid);
+
+/* Sample test to free the virtual rings */
+void test_ring_free(struct rte_ring *rxtx);
+
+/* Sample test to forward packet using virtual port id */
+int test_packet_forward(struct rte_mbuf **pbuf, uint16_t portid,
+ uint16_t queue_id);
+
+/* sample test to allocate buffer for pkts */
+int test_get_mbuf_from_pool(struct rte_mempool **mp, struct rte_mbuf **pbuf,
+ char *poolname);
+
+/* Sample test to create the mempool */
+int test_get_mempool(struct rte_mempool **mp, char *poolname);
+
+/* sample test to deallocate the allocated buffers and mempool */
+void test_put_mbuf_to_pool(struct rte_mempool *mp, struct rte_mbuf **pbuf);
+
+/* Sample test to free the mempool */
+void test_mp_free(struct rte_mempool *mp);
+
+/* Sample test to release the vdev */
+void test_vdev_uninit(const char *vdev);
+
+#endif /* _SAMPLE_PACKET_FORWARD_H_ */
diff --git a/src/spdk/dpdk/app/test/test.c b/src/spdk/dpdk/app/test/test.c
new file mode 100644
index 000000000..94d26ab1f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test.c
@@ -0,0 +1,311 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <termios.h>
+#include <ctype.h>
+#include <sys/queue.h>
+
+#ifdef RTE_LIBRTE_CMDLINE
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+extern cmdline_parse_ctx_t main_ctx[];
+#endif
+
+#include <rte_memory.h>
+#include <rte_eal.h>
+#include <rte_cycles.h>
+#include <rte_log.h>
+#include <rte_string_fns.h>
+#ifdef RTE_LIBRTE_TIMER
+#include <rte_timer.h>
+#endif
+
+#include "test.h"
+#ifdef RTE_LIBRTE_PDUMP
+#include "test_pdump.h"
+#endif
+
+#define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
+
+const char *prgname; /* to be set to argv[0] */
+
+static const char *recursive_call; /* used in linux for MP and other tests */
+
+static int
+no_action(void){ return 0; }
+
+static int
+do_recursive_call(void)
+{
+ unsigned i;
+ struct {
+ const char *env_var;
+ int (*action_fn)(void);
+ } actions[] = {
+ { "run_secondary_instances", test_mp_secondary },
+#ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
+ { "run_pdump_server_tests", test_pdump },
+#endif
+#endif
+ { "test_missing_c_flag", no_action },
+ { "test_master_lcore_flag", no_action },
+ { "test_invalid_n_flag", no_action },
+ { "test_no_hpet_flag", no_action },
+ { "test_whitelist_flag", no_action },
+ { "test_invalid_b_flag", no_action },
+ { "test_invalid_vdev_flag", no_action },
+ { "test_invalid_r_flag", no_action },
+ { "test_misc_flags", no_action },
+ { "test_memory_flags", no_action },
+ { "test_file_prefix", no_action },
+ { "test_no_huge_flag", no_action },
+#ifdef RTE_LIBRTE_TIMER
+ { "timer_secondary_spawn_wait", test_timer_secondary },
+#endif
+ };
+
+ if (recursive_call == NULL)
+ return -1;
+ for (i = 0; i < RTE_DIM(actions); i++) {
+ if (strcmp(actions[i].env_var, recursive_call) == 0)
+ return (actions[i].action_fn)();
+ }
+ printf("ERROR - missing action to take for %s\n", recursive_call);
+ return -1;
+}
+
+int last_test_result;
+
+#define MAX_EXTRA_ARGS 32
+
+int
+main(int argc, char **argv)
+{
+#ifdef RTE_LIBRTE_CMDLINE
+ struct cmdline *cl;
+#endif
+ char *extra_args;
+ int ret;
+
+ extra_args = getenv("DPDK_TEST_PARAMS");
+ if (extra_args != NULL && strlen(extra_args) > 0) {
+ char **all_argv;
+ char *eargv[MAX_EXTRA_ARGS];
+ int all_argc;
+ int eargc;
+ int i;
+
+ RTE_LOG(INFO, APP, "Using additional DPDK_TEST_PARAMS: '%s'\n",
+ extra_args);
+ eargc = rte_strsplit(extra_args, strlen(extra_args),
+ eargv, MAX_EXTRA_ARGS, ' ');
+
+ /* merge argc/argv and the environment args */
+ all_argc = argc + eargc;
+ all_argv = malloc(sizeof(*all_argv) * (all_argc + 1));
+ if (all_argv == NULL) {
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < argc; i++)
+ all_argv[i] = argv[i];
+ for (i = 0; i < eargc; i++)
+ all_argv[argc + i] = eargv[i];
+ all_argv[all_argc] = NULL;
+
+ /* call eal_init with combined args */
+ ret = rte_eal_init(all_argc, all_argv);
+ free(all_argv);
+ } else
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0) {
+ ret = -1;
+ goto out;
+ }
+
+#ifdef RTE_LIBRTE_TIMER
+ if (rte_timer_subsystem_init() < 0) {
+ ret = -1;
+ goto out;
+ }
+#endif
+
+ if (commands_init() < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ argv += ret;
+
+ prgname = argv[0];
+
+ recursive_call = getenv(RECURSIVE_ENV_VAR);
+ if (recursive_call != NULL) {
+ ret = do_recursive_call();
+ goto out;
+ }
+
+#ifdef RTE_LIBEAL_USE_HPET
+ if (rte_eal_hpet_init(1) < 0)
+#endif
+ RTE_LOG(INFO, APP,
+ "HPET is not enabled, using TSC as default timer\n");
+
+
+#ifdef RTE_LIBRTE_CMDLINE
+ cl = cmdline_stdin_new(main_ctx, "RTE>>");
+ if (cl == NULL) {
+ ret = -1;
+ goto out;
+ }
+
+ char *dpdk_test = getenv("DPDK_TEST");
+ if (dpdk_test && strlen(dpdk_test)) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s\n", dpdk_test);
+ if (cmdline_in(cl, buf, strlen(buf)) < 0) {
+ printf("error on cmdline input\n");
+ ret = -1;
+ goto out;
+ }
+
+ cmdline_stdin_exit(cl);
+ ret = last_test_result;
+ goto out;
+ }
+ /* if no DPDK_TEST env variable, go interactive */
+ cmdline_interact(cl);
+ cmdline_stdin_exit(cl);
+#endif
+ ret = 0;
+
+out:
+#ifdef RTE_LIBRTE_TIMER
+ rte_timer_subsystem_finalize();
+#endif
+ rte_eal_cleanup();
+ return ret;
+}
+
+
+int
+unit_test_suite_runner(struct unit_test_suite *suite)
+{
+ int test_success;
+ unsigned int total = 0, executed = 0, skipped = 0;
+ unsigned int succeeded = 0, failed = 0, unsupported = 0;
+ const char *status;
+
+ if (suite->suite_name) {
+ printf(" + ------------------------------------------------------- +\n");
+ printf(" + Test Suite : %s\n", suite->suite_name);
+ }
+
+ if (suite->setup) {
+ test_success = suite->setup();
+ if (test_success != 0) {
+ /*
+ * setup did not pass, so count all enabled tests and
+ * mark them as failed/skipped
+ */
+ while (suite->unit_test_cases[total].testcase) {
+ if (!suite->unit_test_cases[total].enabled ||
+ test_success == TEST_SKIPPED)
+ skipped++;
+ else
+ failed++;
+ total++;
+ }
+ goto suite_summary;
+ }
+ }
+
+ printf(" + ------------------------------------------------------- +\n");
+
+ while (suite->unit_test_cases[total].testcase) {
+ if (!suite->unit_test_cases[total].enabled) {
+ skipped++;
+ total++;
+ continue;
+ } else {
+ executed++;
+ }
+
+ /* run test case setup */
+ if (suite->unit_test_cases[total].setup)
+ test_success = suite->unit_test_cases[total].setup();
+ else
+ test_success = TEST_SUCCESS;
+
+ if (test_success == TEST_SUCCESS) {
+ /* run the test case */
+ test_success = suite->unit_test_cases[total].testcase();
+ if (test_success == TEST_SUCCESS)
+ succeeded++;
+ else if (test_success == TEST_SKIPPED)
+ skipped++;
+ else if (test_success == -ENOTSUP)
+ unsupported++;
+ else
+ failed++;
+ } else if (test_success == -ENOTSUP) {
+ unsupported++;
+ } else {
+ failed++;
+ }
+
+ /* run the test case teardown */
+ if (suite->unit_test_cases[total].teardown)
+ suite->unit_test_cases[total].teardown();
+
+ if (test_success == TEST_SUCCESS)
+ status = "succeeded";
+ else if (test_success == TEST_SKIPPED)
+ status = "skipped";
+ else if (test_success == -ENOTSUP)
+ status = "unsupported";
+ else
+ status = "failed";
+
+ printf(" + TestCase [%2d] : %s %s\n", total,
+ suite->unit_test_cases[total].name, status);
+
+ total++;
+ }
+
+ /* Run test suite teardown */
+ if (suite->teardown)
+ suite->teardown();
+
+ goto suite_summary;
+
+suite_summary:
+ printf(" + ------------------------------------------------------- +\n");
+ printf(" + Test Suite Summary \n");
+ printf(" + Tests Total : %2d\n", total);
+ printf(" + Tests Skipped : %2d\n", skipped);
+ printf(" + Tests Executed : %2d\n", executed);
+ printf(" + Tests Unsupported: %2d\n", unsupported);
+ printf(" + Tests Passed : %2d\n", succeeded);
+ printf(" + Tests Failed : %2d\n", failed);
+ printf(" + ------------------------------------------------------- +\n");
+
+ last_test_result = failed;
+
+ if (failed)
+ return TEST_FAILED;
+ if (total == skipped)
+ return TEST_SKIPPED;
+ return TEST_SUCCESS;
+}
diff --git a/src/spdk/dpdk/app/test/test.h b/src/spdk/dpdk/app/test/test.h
new file mode 100644
index 000000000..b07f6c1ef
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _TEST_H_
+#define _TEST_H_
+
+#include <stddef.h>
+#include <sys/queue.h>
+
+#include <rte_hexdump.h>
+#include <rte_common.h>
+
+#define TEST_SUCCESS EXIT_SUCCESS
+#define TEST_FAILED -1
+#define TEST_SKIPPED 77
+
+/* Before including test.h file you can define
+ * TEST_TRACE_FAILURE(_file, _line, _func) macro to better trace/debug test
+ * failures. Mostly useful in test development phase. */
+#ifndef TEST_TRACE_FAILURE
+# define TEST_TRACE_FAILURE(_file, _line, _func)
+#endif
+
+#include <rte_test.h>
+
+#define TEST_ASSERT RTE_TEST_ASSERT
+
+#define TEST_ASSERT_EQUAL RTE_TEST_ASSERT_EQUAL
+
+/* Compare two buffers (length in bytes) */
+#define TEST_ASSERT_BUFFERS_ARE_EQUAL(a, b, len, msg, ...) do { \
+ if (memcmp(a, b, len)) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ return TEST_FAILED; \
+ } \
+} while (0)
+
+/* Compare two buffers with offset (length and offset in bytes) */
+#define TEST_ASSERT_BUFFERS_ARE_EQUAL_OFFSET(a, b, len, off, msg, ...) do { \
+ const uint8_t *_a_with_off = (const uint8_t *)a + off; \
+ const uint8_t *_b_with_off = (const uint8_t *)b + off; \
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(_a_with_off, _b_with_off, len, msg); \
+} while (0)
+
+/* Compare two buffers (length in bits) */
+#define TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(a, b, len, msg, ...) do { \
+ uint8_t _last_byte_a, _last_byte_b; \
+ uint8_t _last_byte_mask, _last_byte_bits; \
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(a, b, (len >> 3), msg); \
+ if (len % 8) { \
+ _last_byte_bits = len % 8; \
+ _last_byte_mask = ~((1 << (8 - _last_byte_bits)) - 1); \
+ _last_byte_a = ((const uint8_t *)a)[len >> 3]; \
+ _last_byte_b = ((const uint8_t *)b)[len >> 3]; \
+ _last_byte_a &= _last_byte_mask; \
+ _last_byte_b &= _last_byte_mask; \
+ if (_last_byte_a != _last_byte_b) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__);\
+ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ return TEST_FAILED; \
+ } \
+ } \
+} while (0)
+
+/* Compare two buffers with offset (length and offset in bits) */
+#define TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT_OFFSET(a, b, len, off, msg, ...) do { \
+ uint8_t _first_byte_a, _first_byte_b; \
+ uint8_t _first_byte_mask, _first_byte_bits; \
+ uint32_t _len_without_first_byte = (off % 8) ? \
+ len - (8 - (off % 8)) : \
+ len; \
+ uint32_t _off_in_bytes = (off % 8) ? (off >> 3) + 1 : (off >> 3); \
+ const uint8_t *_a_with_off = (const uint8_t *)a + _off_in_bytes; \
+ const uint8_t *_b_with_off = (const uint8_t *)b + _off_in_bytes; \
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(_a_with_off, _b_with_off, \
+ _len_without_first_byte, msg); \
+ if (off % 8) { \
+ _first_byte_bits = 8 - (off % 8); \
+ _first_byte_mask = (1 << _first_byte_bits) - 1; \
+ _first_byte_a = *(_a_with_off - 1); \
+ _first_byte_b = *(_b_with_off - 1); \
+ _first_byte_a &= _first_byte_mask; \
+ _first_byte_b &= _first_byte_mask; \
+ if (_first_byte_a != _first_byte_b) { \
+ printf("TestCase %s() line %d failed: " \
+ msg "\n", __func__, __LINE__, ##__VA_ARGS__); \
+ TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ return TEST_FAILED; \
+ } \
+ } \
+} while (0)
+
+#define TEST_ASSERT_NOT_EQUAL RTE_TEST_ASSERT_NOT_EQUAL
+
+#define TEST_ASSERT_SUCCESS RTE_TEST_ASSERT_SUCCESS
+
+#define TEST_ASSERT_FAIL RTE_TEST_ASSERT_FAIL
+
+#define TEST_ASSERT_NULL RTE_TEST_ASSERT_NULL
+
+#define TEST_ASSERT_NOT_NULL RTE_TEST_ASSERT_NOT_NULL
+
+struct unit_test_case {
+ int (*setup)(void);
+ void (*teardown)(void);
+ int (*testcase)(void);
+ const char *name;
+ unsigned enabled;
+};
+
+#define TEST_CASE(fn) { NULL, NULL, fn, #fn, 1 }
+
+#define TEST_CASE_NAMED(name, fn) { NULL, NULL, fn, name, 1 }
+
+#define TEST_CASE_ST(setup, teardown, testcase) \
+ { setup, teardown, testcase, #testcase, 1 }
+
+
+#define TEST_CASE_DISABLED(fn) { NULL, NULL, fn, #fn, 0 }
+
+#define TEST_CASE_ST_DISABLED(setup, teardown, testcase) \
+ { setup, teardown, testcase, #testcase, 0 }
+
+#define TEST_CASES_END() { NULL, NULL, NULL, NULL, 0 }
+
+static inline void
+debug_hexdump(FILE *file, const char *title, const void *buf, size_t len)
+{
+ if (rte_log_get_global_level() == RTE_LOG_DEBUG)
+ rte_hexdump(file, title, buf, len);
+}
+
+struct unit_test_suite {
+ const char *suite_name;
+ int (*setup)(void);
+ void (*teardown)(void);
+ struct unit_test_case unit_test_cases[];
+};
+
+int unit_test_suite_runner(struct unit_test_suite *suite);
+extern int last_test_result;
+
+#define RECURSIVE_ENV_VAR "RTE_TEST_RECURSIVE"
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_string.h>
+
+extern const char *prgname;
+
+int commands_init(void);
+
+int test_mp_secondary(void);
+int test_timer_secondary(void);
+
+int test_set_rxtx_conf(cmdline_fixed_string_t mode);
+int test_set_rxtx_anchor(cmdline_fixed_string_t type);
+int test_set_rxtx_sc(cmdline_fixed_string_t type);
+
+typedef int (test_callback)(void);
+TAILQ_HEAD(test_commands_list, test_command);
+struct test_command {
+ TAILQ_ENTRY(test_command) next;
+ const char *command;
+ test_callback *callback;
+};
+
+void add_test_command(struct test_command *t);
+
+/* Register a test function with its command string */
+#define REGISTER_TEST_COMMAND(cmd, func) \
+ static struct test_command test_struct_##cmd = { \
+ .command = RTE_STR(cmd), \
+ .callback = func, \
+ }; \
+ RTE_INIT(test_register_##cmd) \
+ { \
+ add_test_command(&test_struct_##cmd); \
+ }
+
+#endif
diff --git a/src/spdk/dpdk/app/test/test_acl.c b/src/spdk/dpdk/app/test/test_acl.c
new file mode 100644
index 000000000..316bf4d06
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_acl.c
@@ -0,0 +1,1743 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+
+#include <rte_string_fns.h>
+#include <rte_mbuf.h>
+#include <rte_byteorder.h>
+#include <rte_ip.h>
+#include <rte_acl.h>
+#include <rte_common.h>
+
+#include "test_acl.h"
+
+#define BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT)
+
+#define LEN RTE_ACL_MAX_CATEGORIES
+
+RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS);
+
+struct rte_acl_param acl_param = {
+ .name = "acl_ctx",
+ .socket_id = SOCKET_ID_ANY,
+ .rule_size = RTE_ACL_IPV4VLAN_RULE_SZ,
+ .max_rule_num = 0x30000,
+};
+
+struct rte_acl_ipv4vlan_rule acl_rule = {
+ .data = { .priority = 1, .category_mask = 0xff },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 0,
+ .dst_port_high = UINT16_MAX,
+};
+
+const uint32_t ipv4_7tuple_layout[RTE_ACL_IPV4VLAN_NUM] = {
+ offsetof(struct ipv4_7tuple, proto),
+ offsetof(struct ipv4_7tuple, vlan),
+ offsetof(struct ipv4_7tuple, ip_src),
+ offsetof(struct ipv4_7tuple, ip_dst),
+ offsetof(struct ipv4_7tuple, port_src),
+};
+
+
+/* byteswap to cpu or network order */
+static void
+bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+
+ if (to_be) {
+ /* swap all bytes so that they are in network order */
+ data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
+ data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
+ data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
+ data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
+ data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
+ data[i].domain = rte_cpu_to_be_16(data[i].domain);
+ } else {
+ data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
+ data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
+ data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
+ data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
+ data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
+ data[i].domain = rte_be_to_cpu_16(data[i].domain);
+ }
+ }
+}
+
+static int
+acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule)
+{
+ if (rule->src_port_low > rule->src_port_high ||
+ rule->dst_port_low > rule->dst_port_high ||
+ rule->src_mask_len > BIT_SIZEOF(rule->src_addr) ||
+ rule->dst_mask_len > BIT_SIZEOF(rule->dst_addr))
+ return -EINVAL;
+ return 0;
+}
+
+static void
+acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ ro->data = ri->data;
+
+ ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
+
+ ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
+ ri->domain_mask;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
+ ri->src_mask_len;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
+ ri->src_port_high;
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
+ ri->dst_port_high;
+}
+
+/*
+ * Add ipv4vlan rules to an existing ACL context.
+ * This function is not multi-thread safe.
+ *
+ * @param ctx
+ * ACL context to add patterns to.
+ * @param rules
+ * Array of rules to add to the ACL context.
+ * Note that all fields in rte_acl_ipv4vlan_rule structures are expected
+ * to be in host byte order.
+ * @param num
+ * Number of elements in the input array of rules.
+ * @return
+ * - -ENOMEM if there is no space in the ACL context for these rules.
+ * - -EINVAL if the parameters are invalid.
+ * - Zero if operation completed successfully.
+ */
+static int
+rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx,
+ const struct rte_acl_ipv4vlan_rule *rules,
+ uint32_t num)
+{
+ int32_t rc;
+ uint32_t i;
+ struct acl_ipv4vlan_rule rv;
+
+ if (ctx == NULL || rules == NULL)
+ return -EINVAL;
+
+ /* check input rules. */
+ for (i = 0; i != num; i++) {
+ rc = acl_ipv4vlan_check_rule(rules + i);
+ if (rc != 0) {
+ RTE_LOG(ERR, ACL, "%s: rule #%u is invalid\n",
+ __func__, i + 1);
+ return rc;
+ }
+ }
+
+ /* perform conversion to the internal format and add to the context. */
+ for (i = 0, rc = 0; i != num && rc == 0; i++) {
+ acl_ipv4vlan_convert_rule(rules + i, &rv);
+ rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&rv, 1);
+ }
+
+ return rc;
+}
+
+static void
+acl_ipv4vlan_config(struct rte_acl_config *cfg,
+ const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
+ uint32_t num_categories)
+{
+ static const struct rte_acl_field_def
+ ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PROTO,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_VLAN,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_VLAN,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_SRC,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_DST,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ },
+ };
+
+ memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
+ cfg->num_fields = RTE_DIM(ipv4_defs);
+
+ cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PROTO];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_VLAN];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_VLAN] +
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_SRC];
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_DST];
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PORTS];
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PORTS] +
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
+
+ cfg->num_categories = num_categories;
+}
+
+/*
+ * Analyze set of ipv4vlan rules and build required internal
+ * run-time structures.
+ * This function is not multi-thread safe.
+ *
+ * @param ctx
+ * ACL context to build.
+ * @param layout
+ * Layout of input data to search through.
+ * @param num_categories
+ * Maximum number of categories to use in that build.
+ * @return
+ * - -ENOMEM if couldn't allocate enough memory.
+ * - -EINVAL if the parameters are invalid.
+ * - Negative error code if operation failed.
+ * - Zero if operation completed successfully.
+ */
+static int
+rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx,
+ const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
+ uint32_t num_categories)
+{
+ struct rte_acl_config cfg;
+
+ if (ctx == NULL || layout == NULL)
+ return -EINVAL;
+
+ memset(&cfg, 0, sizeof(cfg));
+ acl_ipv4vlan_config(&cfg, layout, num_categories);
+ return rte_acl_build(ctx, &cfg);
+}
+
+/*
+ * Test scalar and SSE ACL lookup.
+ */
+static int
+test_classify_run(struct rte_acl_ctx *acx, struct ipv4_7tuple test_data[],
+ size_t dim)
+{
+ int ret, i;
+ uint32_t result, count;
+ uint32_t results[dim * RTE_ACL_MAX_CATEGORIES];
+ const uint8_t *data[dim];
+ /* swap all bytes in the data to network order */
+ bswap_test_data(test_data, dim, 1);
+
+ /* store pointers to test data */
+ for (i = 0; i < (int) dim; i++)
+ data[i] = (uint8_t *)&test_data[i];
+
+ /**
+ * these will run quite a few times, it's necessary to test code paths
+ * from num=0 to num>8
+ */
+ for (count = 0; count <= dim; count++) {
+ ret = rte_acl_classify(acx, data, results,
+ count, RTE_ACL_MAX_CATEGORIES);
+ if (ret != 0) {
+ printf("Line %i: SSE classify failed!\n", __LINE__);
+ goto err;
+ }
+
+ /* check if we allow everything we should allow */
+ for (i = 0; i < (int) count; i++) {
+ result =
+ results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
+ if (result != test_data[i].allow) {
+ printf("Line %i: Error in allow results at %i "
+ "(expected %"PRIu32" got %"PRIu32")!\n",
+ __LINE__, i, test_data[i].allow,
+ result);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ /* check if we deny everything we should deny */
+ for (i = 0; i < (int) count; i++) {
+ result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
+ if (result != test_data[i].deny) {
+ printf("Line %i: Error in deny results at %i "
+ "(expected %"PRIu32" got %"PRIu32")!\n",
+ __LINE__, i, test_data[i].deny,
+ result);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+ }
+
+ /* make a quick check for scalar */
+ ret = rte_acl_classify_alg(acx, data, results,
+ dim, RTE_ACL_MAX_CATEGORIES,
+ RTE_ACL_CLASSIFY_SCALAR);
+ if (ret != 0) {
+ printf("Line %i: scalar classify failed!\n", __LINE__);
+ goto err;
+ }
+
+ /* check if we allow everything we should allow */
+ for (i = 0; i < (int) dim; i++) {
+ result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
+ if (result != test_data[i].allow) {
+ printf("Line %i: Error in allow results at %i "
+ "(expected %"PRIu32" got %"PRIu32")!\n",
+ __LINE__, i, test_data[i].allow,
+ result);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ /* check if we deny everything we should deny */
+ for (i = 0; i < (int) dim; i++) {
+ result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
+ if (result != test_data[i].deny) {
+ printf("Line %i: Error in deny results at %i "
+ "(expected %"PRIu32" got %"PRIu32")!\n",
+ __LINE__, i, test_data[i].deny,
+ result);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ ret = 0;
+
+err:
+ /* swap data back to cpu order so that next time tests don't fail */
+ bswap_test_data(test_data, dim, 0);
+ return ret;
+}
+
+static int
+test_classify_buid(struct rte_acl_ctx *acx,
+ const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
+{
+ int ret;
+
+ /* add rules to the context */
+ ret = rte_acl_ipv4vlan_add_rules(acx, rules, num);
+ if (ret != 0) {
+ printf("Line %i: Adding rules to ACL context failed!\n",
+ __LINE__);
+ return ret;
+ }
+
+ /* try building the context */
+ ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout,
+ RTE_ACL_MAX_CATEGORIES);
+ if (ret != 0) {
+ printf("Line %i: Building ACL context failed!\n", __LINE__);
+ return ret;
+ }
+
+ return 0;
+}
+
+#define TEST_CLASSIFY_ITER 4
+
+/*
+ * Test scalar and SSE ACL lookup.
+ */
+static int
+test_classify(void)
+{
+ struct rte_acl_ctx *acx;
+ int i, ret;
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ ret = 0;
+ for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
+
+ if ((i & 1) == 0)
+ rte_acl_reset(acx);
+ else
+ rte_acl_reset_rules(acx);
+
+ ret = test_classify_buid(acx, acl_test_rules,
+ RTE_DIM(acl_test_rules));
+ if (ret != 0) {
+ printf("Line %i, iter: %d: "
+ "Adding rules to ACL context failed!\n",
+ __LINE__, i);
+ break;
+ }
+
+ ret = test_classify_run(acx, acl_test_data,
+ RTE_DIM(acl_test_data));
+ if (ret != 0) {
+ printf("Line %i, iter: %d: %s failed!\n",
+ __LINE__, i, __func__);
+ break;
+ }
+
+ /* reset rules and make sure that classify still works ok. */
+ rte_acl_reset_rules(acx);
+ ret = test_classify_run(acx, acl_test_data,
+ RTE_DIM(acl_test_data));
+ if (ret != 0) {
+ printf("Line %i, iter: %d: %s failed!\n",
+ __LINE__, i, __func__);
+ break;
+ }
+ }
+
+ rte_acl_free(acx);
+ return ret;
+}
+
+static int
+test_build_ports_range(void)
+{
+ static const struct rte_acl_ipv4vlan_rule test_rules[] = {
+ {
+ /* match all packets. */
+ .data = {
+ .userdata = 1,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 101,
+ },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 0,
+ .dst_port_high = UINT16_MAX,
+ },
+ {
+ /* match all packets with dst ports [54-65280]. */
+ .data = {
+ .userdata = 2,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 102,
+ },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 54,
+ .dst_port_high = 65280,
+ },
+ {
+ /* match all packets with dst ports [0-52]. */
+ .data = {
+ .userdata = 3,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 103,
+ },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 0,
+ .dst_port_high = 52,
+ },
+ {
+ /* match all packets with dst ports [53]. */
+ .data = {
+ .userdata = 4,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 99,
+ },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 53,
+ .dst_port_high = 53,
+ },
+ {
+ /* match all packets with dst ports [65279-65535]. */
+ .data = {
+ .userdata = 5,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 98,
+ },
+ .src_port_low = 0,
+ .src_port_high = UINT16_MAX,
+ .dst_port_low = 65279,
+ .dst_port_high = UINT16_MAX,
+ },
+ };
+
+ static struct ipv4_7tuple test_data[] = {
+ {
+ .proto = 6,
+ .ip_src = RTE_IPV4(10, 1, 1, 1),
+ .ip_dst = RTE_IPV4(192, 168, 0, 33),
+ .port_dst = 53,
+ .allow = 1,
+ },
+ {
+ .proto = 6,
+ .ip_src = RTE_IPV4(127, 84, 33, 1),
+ .ip_dst = RTE_IPV4(1, 2, 3, 4),
+ .port_dst = 65281,
+ .allow = 1,
+ },
+ };
+
+ struct rte_acl_ctx *acx;
+ int32_t ret, i, j;
+ uint32_t results[RTE_DIM(test_data)];
+ const uint8_t *data[RTE_DIM(test_data)];
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ /* swap all bytes in the data to network order */
+ bswap_test_data(test_data, RTE_DIM(test_data), 1);
+
+ /* store pointers to test data */
+ for (i = 0; i != RTE_DIM(test_data); i++)
+ data[i] = (uint8_t *)&test_data[i];
+
+ for (i = 0; i != RTE_DIM(test_rules); i++) {
+ rte_acl_reset(acx);
+ ret = test_classify_buid(acx, test_rules, i + 1);
+ if (ret != 0) {
+ printf("Line %i, iter: %d: "
+ "Adding rules to ACL context failed!\n",
+ __LINE__, i);
+ break;
+ }
+ ret = rte_acl_classify(acx, data, results,
+ RTE_DIM(data), 1);
+ if (ret != 0) {
+ printf("Line %i, iter: %d: classify failed!\n",
+ __LINE__, i);
+ break;
+ }
+
+ /* check results */
+ for (j = 0; j != RTE_DIM(results); j++) {
+ if (results[j] != test_data[j].allow) {
+ printf("Line %i: Error in allow results at %i "
+ "(expected %"PRIu32" got %"PRIu32")!\n",
+ __LINE__, j, test_data[j].allow,
+ results[j]);
+ ret = -EINVAL;
+ }
+ }
+ }
+
+ bswap_test_data(test_data, RTE_DIM(test_data), 0);
+
+ rte_acl_free(acx);
+ return ret;
+}
+
+static void
+convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ ro->data = ri->data;
+
+ ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
+
+ ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
+ ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
+ ri->domain_mask;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
+ ri->src_mask_len;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
+ ri->src_port_high;
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
+ ri->dst_port_high;
+}
+
+/*
+ * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
+ * RTE_ACL_FIELD_TYPE_BITMASK.
+ */
+static void
+convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ uint32_t v;
+
+ convert_rule(ri, ro);
+ v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
+ RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
+ v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 =
+ RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
+}
+
+/*
+ * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
+ * RTE_ACL_FIELD_TYPE_RANGE.
+ */
+static void
+convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ uint32_t hi, lo, mask;
+
+ convert_rule(ri, ro);
+
+ mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
+ mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
+ lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask;
+ hi = lo + ~mask;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
+
+ mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
+ mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
+ lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask;
+ hi = lo + ~mask;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
+ */
+static void
+convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ struct rte_acl_field t1, t2;
+
+ convert_rule(ri, ro);
+
+ t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
+ t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
+
+ ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD];
+ ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD];
+
+ ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
+ ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
+ */
+static void
+convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
+ struct acl_ipv4vlan_rule *ro)
+{
+ struct rte_acl_field t;
+
+ convert_rule(ri, ro);
+
+ t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD];
+ ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] =
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD];
+
+ ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
+}
+
+static void
+ipv4vlan_config(struct rte_acl_config *cfg,
+ const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
+ uint32_t num_categories)
+{
+ static const struct rte_acl_field_def
+ ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PROTO,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_VLAN,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_VLAN,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_SRC,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_DST,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
+ .input_index = RTE_ACL_IPV4VLAN_PORTS,
+ },
+ };
+
+ memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
+ cfg->num_fields = RTE_DIM(ipv4_defs);
+
+ cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PROTO];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_VLAN];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_VLAN] +
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_SRC];
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_DST];
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PORTS];
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
+ layout[RTE_ACL_IPV4VLAN_PORTS] +
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
+
+ cfg->num_categories = num_categories;
+}
+
+static int
+convert_rules(struct rte_acl_ctx *acx,
+ void (*convert)(const struct rte_acl_ipv4vlan_rule *,
+ struct acl_ipv4vlan_rule *),
+ const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
+{
+ int32_t rc;
+ uint32_t i;
+ struct acl_ipv4vlan_rule r;
+
+ for (i = 0; i != num; i++) {
+ convert(rules + i, &r);
+ rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
+ if (rc != 0) {
+ printf("Line %i: Adding rule %u to ACL context "
+ "failed with error code: %d\n",
+ __LINE__, i, rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void
+convert_config(struct rte_acl_config *cfg)
+{
+ ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
+ */
+static void
+convert_config_1(struct rte_acl_config *cfg)
+{
+ ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
+ */
+static void
+convert_config_2(struct rte_acl_config *cfg)
+{
+ ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
+ */
+static void
+convert_config_3(struct rte_acl_config *cfg)
+{
+ struct rte_acl_field_def t1, t2;
+
+ ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
+
+ t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
+ t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
+
+ /* swap VLAN1 and SRCP rule definition. */
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index;
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index;
+
+ /* swap VLAN2 and DSTP rule definition. */
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD];
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index;
+ cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index;
+
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type;
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size;
+ cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset;
+
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type;
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size;
+ cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset;
+}
+
+/*
+ * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
+ */
+static void
+convert_config_4(struct rte_acl_config *cfg)
+{
+ struct rte_acl_field_def t;
+
+ ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
+
+ t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
+
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] =
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD];
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index;
+ cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index;
+
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type;
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size;
+ cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset;
+}
+
+
+static int
+build_convert_rules(struct rte_acl_ctx *acx,
+ void (*config)(struct rte_acl_config *),
+ size_t max_size)
+{
+ struct rte_acl_config cfg;
+
+ memset(&cfg, 0, sizeof(cfg));
+ config(&cfg);
+ cfg.max_size = max_size;
+ return rte_acl_build(acx, &cfg);
+}
+
+static int
+test_convert_rules(const char *desc,
+ void (*config)(struct rte_acl_config *),
+ void (*convert)(const struct rte_acl_ipv4vlan_rule *,
+ struct acl_ipv4vlan_rule *))
+{
+ struct rte_acl_ctx *acx;
+ int32_t rc;
+ uint32_t i;
+ static const size_t mem_sizes[] = {0, -1};
+
+ printf("running %s(%s)\n", __func__, desc);
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ rc = convert_rules(acx, convert, acl_test_rules,
+ RTE_DIM(acl_test_rules));
+ if (rc != 0)
+ printf("Line %i: Error converting ACL rules!\n", __LINE__);
+
+ for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
+
+ rc = build_convert_rules(acx, config, mem_sizes[i]);
+ if (rc != 0) {
+ printf("Line %i: Error @ build_convert_rules(%zu)!\n",
+ __LINE__, mem_sizes[i]);
+ break;
+ }
+
+ rc = test_classify_run(acx, acl_test_data,
+ RTE_DIM(acl_test_data));
+ if (rc != 0)
+ printf("%s failed at line %i, max_size=%zu\n",
+ __func__, __LINE__, mem_sizes[i]);
+ }
+
+ rte_acl_free(acx);
+ return rc;
+}
+
+static int
+test_convert(void)
+{
+ static const struct {
+ const char *desc;
+ void (*config)(struct rte_acl_config *);
+ void (*convert)(const struct rte_acl_ipv4vlan_rule *,
+ struct acl_ipv4vlan_rule *);
+ } convert_param[] = {
+ {
+ "acl_ipv4vlan_tuple",
+ convert_config,
+ convert_rule,
+ },
+ {
+ "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
+ "for IPv4",
+ convert_config_1,
+ convert_rule_1,
+ },
+ {
+ "acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
+ "for IPv4",
+ convert_config_2,
+ convert_rule_2,
+ },
+ {
+ "acl_ipv4vlan_tuple: swap VLAN and PORTs order",
+ convert_config_3,
+ convert_rule_3,
+ },
+ {
+ "acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
+ convert_config_4,
+ convert_rule_4,
+ },
+ };
+
+ uint32_t i;
+ int32_t rc;
+
+ for (i = 0; i != RTE_DIM(convert_param); i++) {
+ rc = test_convert_rules(convert_param[i].desc,
+ convert_param[i].config,
+ convert_param[i].convert);
+ if (rc != 0) {
+ printf("%s for test-case: %s failed, error code: %d;\n",
+ __func__, convert_param[i].desc, rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Test wrong layout behavior
+ * This test supplies the ACL context with invalid layout, which results in
+ * ACL matching the wrong stuff. However, it should match the wrong stuff
+ * the right way. We switch around source and destination addresses,
+ * source and destination ports, and protocol will point to first byte of
+ * destination port.
+ */
+static int
+test_invalid_layout(void)
+{
+ struct rte_acl_ctx *acx;
+ int ret, i;
+
+ uint32_t results[RTE_DIM(invalid_layout_data)];
+ const uint8_t *data[RTE_DIM(invalid_layout_data)];
+
+ const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
+ /* proto points to destination port's first byte */
+ offsetof(struct ipv4_7tuple, port_dst),
+
+ 0, /* VLAN not used */
+
+ /* src and dst addresses are swapped */
+ offsetof(struct ipv4_7tuple, ip_dst),
+ offsetof(struct ipv4_7tuple, ip_src),
+
+ /*
+ * we can't swap ports here, so we will swap
+ * them in the data
+ */
+ offsetof(struct ipv4_7tuple, port_src),
+ };
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ /* putting a lot of rules into the context results in greater
+ * coverage numbers. it doesn't matter if they are identical */
+ for (i = 0; i < 1000; i++) {
+ /* add rules to the context */
+ ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
+ RTE_DIM(invalid_layout_rules));
+ if (ret != 0) {
+ printf("Line %i: Adding rules to ACL context failed!\n",
+ __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+ }
+
+ /* try building the context */
+ ret = rte_acl_ipv4vlan_build(acx, layout, 1);
+ if (ret != 0) {
+ printf("Line %i: Building ACL context failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* swap all bytes in the data to network order */
+ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
+
+ /* prepare data */
+ for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
+ data[i] = (uint8_t *)&invalid_layout_data[i];
+ }
+
+ /* classify tuples */
+ ret = rte_acl_classify_alg(acx, data, results,
+ RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
+ if (ret != 0) {
+ printf("Line %i: SSE classify failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ for (i = 0; i < (int) RTE_DIM(results); i++) {
+ if (results[i] != invalid_layout_data[i].allow) {
+ printf("Line %i: Wrong results at %i "
+ "(result=%u, should be %u)!\n",
+ __LINE__, i, results[i],
+ invalid_layout_data[i].allow);
+ goto err;
+ }
+ }
+
+ /* classify tuples (scalar) */
+ ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
+ RTE_ACL_CLASSIFY_SCALAR);
+
+ if (ret != 0) {
+ printf("Line %i: Scalar classify failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ for (i = 0; i < (int) RTE_DIM(results); i++) {
+ if (results[i] != invalid_layout_data[i].allow) {
+ printf("Line %i: Wrong results at %i "
+ "(result=%u, should be %u)!\n",
+ __LINE__, i, results[i],
+ invalid_layout_data[i].allow);
+ goto err;
+ }
+ }
+
+ rte_acl_free(acx);
+
+ /* swap data back to cpu order so that next time tests don't fail */
+ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
+
+ return 0;
+err:
+
+ /* swap data back to cpu order so that next time tests don't fail */
+ bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
+
+ rte_acl_free(acx);
+
+ return -1;
+}
+
+/*
+ * Test creating and finding ACL contexts, and adding rules
+ */
+static int
+test_create_find_add(void)
+{
+ struct rte_acl_param param;
+ struct rte_acl_ctx *acx, *acx2, *tmp;
+ struct rte_acl_ipv4vlan_rule rules[LEN];
+
+ const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
+
+ const char *acx_name = "acx";
+ const char *acx2_name = "acx2";
+ int i, ret;
+
+ /* create two contexts */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.max_rule_num = 2;
+
+ param.name = acx_name;
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
+ return -1;
+ }
+
+ param.name = acx2_name;
+ acx2 = rte_acl_create(&param);
+ if (acx2 == NULL || acx2 == acx) {
+ printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* try to create third one, with an existing name */
+ param.name = acx_name;
+ tmp = rte_acl_create(&param);
+ if (tmp != acx) {
+ printf("Line %i: Creating context with existing name "
+ "test failed!\n",
+ __LINE__);
+ if (tmp)
+ rte_acl_free(tmp);
+ goto err;
+ }
+
+ param.name = acx2_name;
+ tmp = rte_acl_create(&param);
+ if (tmp != acx2) {
+ printf("Line %i: Creating context with existing "
+ "name test 2 failed!\n",
+ __LINE__);
+ if (tmp)
+ rte_acl_free(tmp);
+ goto err;
+ }
+
+ /* try to find existing ACL contexts */
+ tmp = rte_acl_find_existing(acx_name);
+ if (tmp != acx) {
+ printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
+ if (tmp)
+ rte_acl_free(tmp);
+ goto err;
+ }
+
+ tmp = rte_acl_find_existing(acx2_name);
+ if (tmp != acx2) {
+ printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
+ if (tmp)
+ rte_acl_free(tmp);
+ goto err;
+ }
+
+ /* try to find non-existing context */
+ tmp = rte_acl_find_existing("invalid");
+ if (tmp != NULL) {
+ printf("Line %i: Non-existent ACL context found!\n", __LINE__);
+ goto err;
+ }
+
+ /* free context */
+ rte_acl_free(acx);
+
+
+ /* create valid (but severely limited) acx */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.max_rule_num = LEN;
+
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating %s!\n", __LINE__, param.name);
+ goto err;
+ }
+
+ /* create dummy acl */
+ for (i = 0; i < LEN; i++) {
+ memcpy(&rules[i], &acl_rule,
+ sizeof(struct rte_acl_ipv4vlan_rule));
+ /* skip zero */
+ rules[i].data.userdata = i + 1;
+ /* one rule per category */
+ rules[i].data.category_mask = 1 << i;
+ }
+
+ /* try filling up the context */
+ ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
+ if (ret != 0) {
+ printf("Line %i: Adding %i rules to ACL context failed!\n",
+ __LINE__, LEN);
+ goto err;
+ }
+
+ /* try adding to a (supposedly) full context */
+ ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
+ if (ret == 0) {
+ printf("Line %i: Adding rules to full ACL context should"
+ "have failed!\n", __LINE__);
+ goto err;
+ }
+
+ /* try building the context */
+ ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
+ if (ret != 0) {
+ printf("Line %i: Building ACL context failed!\n", __LINE__);
+ goto err;
+ }
+
+ rte_acl_free(acx);
+ rte_acl_free(acx2);
+
+ return 0;
+err:
+ rte_acl_free(acx);
+ rte_acl_free(acx2);
+ return -1;
+}
+
+/*
+ * test various invalid rules
+ */
+static int
+test_invalid_rules(void)
+{
+ struct rte_acl_ctx *acx;
+ int ret;
+
+ struct rte_acl_ipv4vlan_rule rule;
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ /* test inverted high/low source and destination ports.
+ * originally, there was a problem with memory consumption when using
+ * such rules.
+ */
+ /* create dummy acl */
+ memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
+ rule.data.userdata = 1;
+ rule.dst_port_low = 0xfff0;
+ rule.dst_port_high = 0x0010;
+
+ /* add rules to context and try to build it */
+ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
+ if (ret == 0) {
+ printf("Line %i: Adding rules to ACL context "
+ "should have failed!\n", __LINE__);
+ goto err;
+ }
+
+ rule.dst_port_low = 0x0;
+ rule.dst_port_high = 0xffff;
+ rule.src_port_low = 0xfff0;
+ rule.src_port_high = 0x0010;
+
+ /* add rules to context and try to build it */
+ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
+ if (ret == 0) {
+ printf("Line %i: Adding rules to ACL context "
+ "should have failed!\n", __LINE__);
+ goto err;
+ }
+
+ rule.dst_port_low = 0x0;
+ rule.dst_port_high = 0xffff;
+ rule.src_port_low = 0x0;
+ rule.src_port_high = 0xffff;
+
+ rule.dst_mask_len = 33;
+
+ /* add rules to context and try to build it */
+ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
+ if (ret == 0) {
+ printf("Line %i: Adding rules to ACL context "
+ "should have failed!\n", __LINE__);
+ goto err;
+ }
+
+ rule.dst_mask_len = 0;
+ rule.src_mask_len = 33;
+
+ /* add rules to context and try to build it */
+ ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
+ if (ret == 0) {
+ printf("Line %i: Adding rules to ACL context "
+ "should have failed!\n", __LINE__);
+ goto err;
+ }
+
+ rte_acl_free(acx);
+
+ return 0;
+
+err:
+ rte_acl_free(acx);
+
+ return -1;
+}
+
+/*
+ * test functions by passing invalid or
+ * non-workable parameters.
+ *
+ * we do very limited testing of classify functions here
+ * because those are performance-critical and
+ * thus don't do much parameter checking.
+ */
+static int
+test_invalid_parameters(void)
+{
+ struct rte_acl_param param;
+ struct rte_acl_ctx *acx;
+ struct rte_acl_ipv4vlan_rule rule;
+ int result;
+
+ uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
+
+
+ /**
+ * rte_ac_create()
+ */
+
+ /* NULL param */
+ acx = rte_acl_create(NULL);
+ if (acx != NULL) {
+ printf("Line %i: ACL context creation with NULL param "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* zero rule size */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.rule_size = 0;
+
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: ACL context creation with zero rule len "
+ "failed!\n", __LINE__);
+ return -1;
+ } else
+ rte_acl_free(acx);
+
+ /* zero max rule num */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.max_rule_num = 0;
+
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: ACL context creation with zero rule num "
+ "failed!\n", __LINE__);
+ return -1;
+ } else
+ rte_acl_free(acx);
+
+ if (rte_eal_has_hugepages()) {
+ /* invalid NUMA node */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.socket_id = RTE_MAX_NUMA_NODES + 1;
+
+ acx = rte_acl_create(&param);
+ if (acx != NULL) {
+ printf("Line %i: ACL context creation with invalid "
+ "NUMA should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+ }
+
+ /* NULL name */
+ memcpy(&param, &acl_param, sizeof(param));
+ param.name = NULL;
+
+ acx = rte_acl_create(&param);
+ if (acx != NULL) {
+ printf("Line %i: ACL context creation with NULL name "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /**
+ * rte_acl_find_existing
+ */
+
+ acx = rte_acl_find_existing(NULL);
+ if (acx != NULL) {
+ printf("Line %i: NULL ACL context found!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /**
+ * rte_acl_ipv4vlan_add_rules
+ */
+
+ /* initialize everything */
+ memcpy(&param, &acl_param, sizeof(param));
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: ACL context creation failed!\n", __LINE__);
+ return -1;
+ }
+
+ memcpy(&rule, &acl_rule, sizeof(rule));
+
+ /* NULL context */
+ result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
+ if (result == 0) {
+ printf("Line %i: Adding rules with NULL ACL context "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* NULL rule */
+ result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
+ if (result == 0) {
+ printf("Line %i: Adding NULL rule to ACL context "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* zero count (should succeed) */
+ result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
+ if (result != 0) {
+ printf("Line %i: Adding 0 rules to ACL context failed!\n",
+ __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* free ACL context */
+ rte_acl_free(acx);
+
+
+ /**
+ * rte_acl_ipv4vlan_build
+ */
+
+ /* reinitialize context */
+ memcpy(&param, &acl_param, sizeof(param));
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: ACL context creation failed!\n", __LINE__);
+ return -1;
+ }
+
+ /* NULL context */
+ result = rte_acl_ipv4vlan_build(NULL, layout, 1);
+ if (result == 0) {
+ printf("Line %i: Building with NULL context "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* NULL layout */
+ result = rte_acl_ipv4vlan_build(acx, NULL, 1);
+ if (result == 0) {
+ printf("Line %i: Building with NULL layout "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* zero categories (should not fail) */
+ result = rte_acl_ipv4vlan_build(acx, layout, 0);
+ if (result == 0) {
+ printf("Line %i: Building with 0 categories should fail!\n",
+ __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* SSE classify test */
+
+ /* cover zero categories in classify (should not fail) */
+ result = rte_acl_classify(acx, NULL, NULL, 0, 0);
+ if (result != 0) {
+ printf("Line %i: SSE classify with zero categories "
+ "failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* cover invalid but positive categories in classify */
+ result = rte_acl_classify(acx, NULL, NULL, 0, 3);
+ if (result == 0) {
+ printf("Line %i: SSE classify with 3 categories "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* scalar classify test */
+
+ /* cover zero categories in classify (should not fail) */
+ result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0,
+ RTE_ACL_CLASSIFY_SCALAR);
+ if (result != 0) {
+ printf("Line %i: Scalar classify with zero categories "
+ "failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* cover invalid but positive categories in classify */
+ result = rte_acl_classify(acx, NULL, NULL, 0, 3);
+ if (result == 0) {
+ printf("Line %i: Scalar classify with 3 categories "
+ "should have failed!\n", __LINE__);
+ rte_acl_free(acx);
+ return -1;
+ }
+
+ /* free ACL context */
+ rte_acl_free(acx);
+
+
+ /**
+ * make sure void functions don't crash with NULL parameters
+ */
+
+ rte_acl_free(NULL);
+
+ rte_acl_dump(NULL);
+
+ return 0;
+}
+
+/**
+ * Various tests that don't test much but improve coverage
+ */
+static int
+test_misc(void)
+{
+ struct rte_acl_param param;
+ struct rte_acl_ctx *acx;
+
+ /* create context */
+ memcpy(&param, &acl_param, sizeof(param));
+
+ acx = rte_acl_create(&param);
+ if (acx == NULL) {
+ printf("Line %i: Error creating ACL context!\n", __LINE__);
+ return -1;
+ }
+
+ /* dump context with rules - useful for coverage */
+ rte_acl_list_dump();
+
+ rte_acl_dump(acx);
+
+ rte_acl_free(acx);
+
+ return 0;
+}
+
+static uint32_t
+get_u32_range_max(void)
+{
+ uint32_t i, max;
+
+ max = 0;
+ for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
+ max = RTE_MAX(max, acl_u32_range_test_rules[i].src_mask_len);
+ return max;
+}
+
+static uint32_t
+get_u32_range_min(void)
+{
+ uint32_t i, min;
+
+ min = UINT32_MAX;
+ for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
+ min = RTE_MIN(min, acl_u32_range_test_rules[i].src_addr);
+ return min;
+}
+
+static const struct rte_acl_ipv4vlan_rule *
+find_u32_range_rule(uint32_t val)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
+ if (val >= acl_u32_range_test_rules[i].src_addr &&
+ val <= acl_u32_range_test_rules[i].src_mask_len)
+ return acl_u32_range_test_rules + i;
+ }
+ return NULL;
+}
+
+static void
+fill_u32_range_data(struct ipv4_7tuple tdata[], uint32_t start, uint32_t num)
+{
+ uint32_t i;
+ const struct rte_acl_ipv4vlan_rule *r;
+
+ for (i = 0; i != num; i++) {
+ tdata[i].ip_src = start + i;
+ r = find_u32_range_rule(start + i);
+ if (r != NULL)
+ tdata[i].allow = r->data.userdata;
+ }
+}
+
+static int
+test_u32_range(void)
+{
+ int32_t rc;
+ uint32_t i, k, max, min;
+ struct rte_acl_ctx *acx;
+ struct acl_ipv4vlan_rule r;
+ struct ipv4_7tuple test_data[64];
+
+ acx = rte_acl_create(&acl_param);
+ if (acx == NULL) {
+ printf("%s#%i: Error creating ACL context!\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
+ convert_rule(&acl_u32_range_test_rules[i], &r);
+ rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
+ if (rc != 0) {
+ printf("%s#%i: Adding rule to ACL context "
+ "failed with error code: %d\n",
+ __func__, __LINE__, rc);
+ rte_acl_free(acx);
+ return rc;
+ }
+ }
+
+ rc = build_convert_rules(acx, convert_config_2, 0);
+ if (rc != 0) {
+ printf("%s#%i Error @ build_convert_rules!\n",
+ __func__, __LINE__);
+ rte_acl_free(acx);
+ return rc;
+ }
+
+ max = get_u32_range_max();
+ min = get_u32_range_min();
+
+ max = RTE_MAX(max, max + 1);
+ min = RTE_MIN(min, min - 1);
+
+ printf("%s#%d starting range test from %u to %u\n",
+ __func__, __LINE__, min, max);
+
+ for (i = min; i <= max; i += k) {
+
+ k = RTE_MIN(max - i + 1, RTE_DIM(test_data));
+
+ memset(test_data, 0, sizeof(test_data));
+ fill_u32_range_data(test_data, i, k);
+
+ rc = test_classify_run(acx, test_data, k);
+ if (rc != 0) {
+ printf("%s#%d failed at [%u, %u) interval\n",
+ __func__, __LINE__, i, i + k);
+ break;
+ }
+ }
+
+ rte_acl_free(acx);
+ return rc;
+}
+
+static int
+test_acl(void)
+{
+ if (test_invalid_parameters() < 0)
+ return -1;
+ if (test_invalid_rules() < 0)
+ return -1;
+ if (test_create_find_add() < 0)
+ return -1;
+ if (test_invalid_layout() < 0)
+ return -1;
+ if (test_misc() < 0)
+ return -1;
+ if (test_classify() < 0)
+ return -1;
+ if (test_build_ports_range() < 0)
+ return -1;
+ if (test_convert() < 0)
+ return -1;
+ if (test_u32_range() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(acl_autotest, test_acl);
diff --git a/src/spdk/dpdk/app/test/test_acl.h b/src/spdk/dpdk/app/test/test_acl.h
new file mode 100644
index 000000000..4cdead0b7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_acl.h
@@ -0,0 +1,712 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef TEST_ACL_H_
+#define TEST_ACL_H_
+
+struct ipv4_7tuple {
+ uint16_t vlan;
+ uint16_t domain;
+ uint8_t proto;
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint32_t allow;
+ uint32_t deny;
+};
+
+/**
+ * Legacy support for 7-tuple IPv4 and VLAN rule.
+ * This structure and corresponding API is deprecated.
+ */
+struct rte_acl_ipv4vlan_rule {
+ struct rte_acl_rule_data data; /**< Miscellaneous data for the rule. */
+ uint8_t proto; /**< IPv4 protocol ID. */
+ uint8_t proto_mask; /**< IPv4 protocol ID mask. */
+ uint16_t vlan; /**< VLAN ID. */
+ uint16_t vlan_mask; /**< VLAN ID mask. */
+ uint16_t domain; /**< VLAN domain. */
+ uint16_t domain_mask; /**< VLAN domain mask. */
+ uint32_t src_addr; /**< IPv4 source address. */
+ uint32_t src_mask_len; /**< IPv4 source address mask. */
+ uint32_t dst_addr; /**< IPv4 destination address. */
+ uint32_t dst_mask_len; /**< IPv4 destination address mask. */
+ uint16_t src_port_low; /**< L4 source port low. */
+ uint16_t src_port_high; /**< L4 source port high. */
+ uint16_t dst_port_low; /**< L4 destination port low. */
+ uint16_t dst_port_high; /**< L4 destination port high. */
+};
+
+/**
+ * Specifies fields layout inside rte_acl_rule for rte_acl_ipv4vlan_rule.
+ */
+enum {
+ RTE_ACL_IPV4VLAN_PROTO_FIELD,
+ RTE_ACL_IPV4VLAN_VLAN1_FIELD,
+ RTE_ACL_IPV4VLAN_VLAN2_FIELD,
+ RTE_ACL_IPV4VLAN_SRC_FIELD,
+ RTE_ACL_IPV4VLAN_DST_FIELD,
+ RTE_ACL_IPV4VLAN_SRCP_FIELD,
+ RTE_ACL_IPV4VLAN_DSTP_FIELD,
+ RTE_ACL_IPV4VLAN_NUM_FIELDS
+};
+
+/**
+ * Macro to define rule size for rte_acl_ipv4vlan_rule.
+ */
+#define RTE_ACL_IPV4VLAN_RULE_SZ \
+ RTE_ACL_RULE_SZ(RTE_ACL_IPV4VLAN_NUM_FIELDS)
+
+/*
+ * That effectively defines order of IPV4VLAN classifications:
+ * - PROTO
+ * - VLAN (TAG and DOMAIN)
+ * - SRC IP ADDRESS
+ * - DST IP ADDRESS
+ * - PORTS (SRC and DST)
+ */
+enum {
+ RTE_ACL_IPV4VLAN_PROTO,
+ RTE_ACL_IPV4VLAN_VLAN,
+ RTE_ACL_IPV4VLAN_SRC,
+ RTE_ACL_IPV4VLAN_DST,
+ RTE_ACL_IPV4VLAN_PORTS,
+ RTE_ACL_IPV4VLAN_NUM
+};
+
+/* rules for invalid layout test */
+struct rte_acl_ipv4vlan_rule invalid_layout_rules[] = {
+ /* test src and dst address */
+ {
+ .data = {.userdata = 1, .category_mask = 1,
+ .priority = 1},
+ .src_addr = RTE_IPV4(10,0,0,0),
+ .src_mask_len = 24,
+ },
+ {
+ .data = {.userdata = 2, .category_mask = 1,
+ .priority = 1},
+ .dst_addr = RTE_IPV4(10,0,0,0),
+ .dst_mask_len = 24,
+ },
+ /* test src and dst ports */
+ {
+ .data = {.userdata = 3, .category_mask = 1,
+ .priority = 1},
+ .dst_port_low = 100,
+ .dst_port_high = 100,
+ },
+ {
+ .data = {.userdata = 4, .category_mask = 1,
+ .priority = 1},
+ .src_port_low = 100,
+ .src_port_high = 100,
+ },
+ /* test proto */
+ {
+ .data = {.userdata = 5, .category_mask = 1,
+ .priority = 1},
+ .proto = 0xf,
+ .proto_mask = 0xf
+ },
+ {
+ .data = {.userdata = 6, .category_mask = 1,
+ .priority = 1},
+ .dst_port_low = 0xf,
+ .dst_port_high = 0xf,
+ }
+};
+
+/* these might look odd because they don't match up the rules. This is
+ * intentional, as the invalid layout test presumes returning the correct
+ * results using the wrong data layout.
+ */
+struct ipv4_7tuple invalid_layout_data[] = {
+ {.ip_src = RTE_IPV4(10,0,1,0)}, /* should not match */
+ {.ip_src = RTE_IPV4(10,0,0,1), .allow = 2}, /* should match 2 */
+ {.port_src = 100, .allow = 4}, /* should match 4 */
+ {.port_dst = 0xf, .allow = 6}, /* should match 6 */
+};
+
+#define ACL_ALLOW 0
+#define ACL_DENY 1
+#define ACL_ALLOW_MASK 0x1
+#define ACL_DENY_MASK 0x2
+
+/* ruleset for ACL unit test */
+struct rte_acl_ipv4vlan_rule acl_test_rules[] = {
+/* destination IP addresses */
+ /* matches all packets traveling to 192.168.0.0/16 */
+ {
+ .data = {.userdata = 1, .category_mask = ACL_ALLOW_MASK,
+ .priority = 230},
+ .dst_addr = RTE_IPV4(192,168,0,0),
+ .dst_mask_len = 16,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets traveling to 192.168.1.0/24 */
+ {
+ .data = {.userdata = 2, .category_mask = ACL_ALLOW_MASK,
+ .priority = 330},
+ .dst_addr = RTE_IPV4(192,168,1,0),
+ .dst_mask_len = 24,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets traveling to 192.168.1.50 */
+ {
+ .data = {.userdata = 3, .category_mask = ACL_DENY_MASK,
+ .priority = 230},
+ .dst_addr = RTE_IPV4(192,168,1,50),
+ .dst_mask_len = 32,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* source IP addresses */
+ /* matches all packets traveling from 10.0.0.0/8 */
+ {
+ .data = {.userdata = 4, .category_mask = ACL_ALLOW_MASK,
+ .priority = 240},
+ .src_addr = RTE_IPV4(10,0,0,0),
+ .src_mask_len = 8,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets traveling from 10.1.1.0/24 */
+ {
+ .data = {.userdata = 5, .category_mask = ACL_ALLOW_MASK,
+ .priority = 340},
+ .src_addr = RTE_IPV4(10,1,1,0),
+ .src_mask_len = 24,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets traveling from 10.1.1.1 */
+ {
+ .data = {.userdata = 6, .category_mask = ACL_DENY_MASK,
+ .priority = 240},
+ .src_addr = RTE_IPV4(10,1,1,1),
+ .src_mask_len = 32,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* VLAN tag */
+ /* matches all packets with lower 7 bytes of VLAN tag equal to 0x64 */
+ {
+ .data = {.userdata = 7, .category_mask = ACL_ALLOW_MASK,
+ .priority = 260},
+ .vlan = 0x64,
+ .vlan_mask = 0x7f,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with VLAN tags that have 0x5 in them */
+ {
+ .data = {.userdata = 8, .category_mask = ACL_ALLOW_MASK,
+ .priority = 260},
+ .vlan = 0x5,
+ .vlan_mask = 0x5,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with VLAN tag 5 */
+ {
+ .data = {.userdata = 9, .category_mask = ACL_DENY_MASK,
+ .priority = 360},
+ .vlan = 0x5,
+ .vlan_mask = 0xffff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* VLAN domain */
+ /* matches all packets with lower 7 bytes of domain equal to 0x64 */
+ {
+ .data = {.userdata = 10, .category_mask = ACL_ALLOW_MASK,
+ .priority = 250},
+ .domain = 0x64,
+ .domain_mask = 0x7f,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with domains that have 0x5 in them */
+ {
+ .data = {.userdata = 11, .category_mask = ACL_ALLOW_MASK,
+ .priority = 350},
+ .domain = 0x5,
+ .domain_mask = 0x5,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with domain 5 */
+ {
+ .data = {.userdata = 12, .category_mask = ACL_DENY_MASK,
+ .priority = 350},
+ .domain = 0x5,
+ .domain_mask = 0xffff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* destination port */
+ /* matches everything with dst port 80 */
+ {
+ .data = {.userdata = 13, .category_mask = ACL_ALLOW_MASK,
+ .priority = 310},
+ .dst_port_low = 80,
+ .dst_port_high = 80,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ },
+ /* matches everything with dst port 22-1023 */
+ {
+ .data = {.userdata = 14, .category_mask = ACL_ALLOW_MASK,
+ .priority = 210},
+ .dst_port_low = 22,
+ .dst_port_high = 1023,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ },
+ /* matches everything with dst port 1020 */
+ {
+ .data = {.userdata = 15, .category_mask = ACL_DENY_MASK,
+ .priority = 310},
+ .dst_port_low = 1020,
+ .dst_port_high = 1020,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ },
+ /* matches everything with dst portrange 1000-2000 */
+ {
+ .data = {.userdata = 16, .category_mask = ACL_DENY_MASK,
+ .priority = 210},
+ .dst_port_low = 1000,
+ .dst_port_high = 2000,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ },
+
+/* source port */
+ /* matches everything with src port 80 */
+ {
+ .data = {.userdata = 17, .category_mask = ACL_ALLOW_MASK,
+ .priority = 320},
+ .src_port_low = 80,
+ .src_port_high = 80,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches everything with src port 22-1023 */
+ {
+ .data = {.userdata = 18, .category_mask = ACL_ALLOW_MASK,
+ .priority = 220},
+ .src_port_low = 22,
+ .src_port_high = 1023,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches everything with src port 1020 */
+ {
+ .data = {.userdata = 19, .category_mask = ACL_DENY_MASK,
+ .priority = 320},
+ .src_port_low = 1020,
+ .src_port_high = 1020,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches everything with src portrange 1000-2000 */
+ {
+ .data = {.userdata = 20, .category_mask = ACL_DENY_MASK,
+ .priority = 220},
+ .src_port_low = 1000,
+ .src_port_high = 2000,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* protocol number */
+ /* matches all packets with protocol number either 0x64 or 0xE4 */
+ {
+ .data = {.userdata = 21, .category_mask = ACL_ALLOW_MASK,
+ .priority = 270},
+ .proto = 0x64,
+ .proto_mask = 0x7f,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with protocol that have 0x5 in them */
+ {
+ .data = {.userdata = 22, .category_mask = ACL_ALLOW_MASK,
+ .priority = 1},
+ .proto = 0x5,
+ .proto_mask = 0x5,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+ /* matches all packets with protocol 5 */
+ {
+ .data = {.userdata = 23, .category_mask = ACL_DENY_MASK,
+ .priority = 370},
+ .proto = 0x5,
+ .proto_mask = 0xff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 0,
+ .dst_port_high = 0xffff,
+ },
+
+/* rules combining various fields */
+ {
+ .data = {.userdata = 24, .category_mask = ACL_ALLOW_MASK,
+ .priority = 400},
+ /** make sure that unmasked bytes don't fail! */
+ .dst_addr = RTE_IPV4(1,2,3,4),
+ .dst_mask_len = 16,
+ .src_addr = RTE_IPV4(5,6,7,8),
+ .src_mask_len = 24,
+ .proto = 0x5,
+ .proto_mask = 0xff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 22,
+ .dst_port_high = 1024,
+ .vlan = 0x8100,
+ .vlan_mask = 0xffff,
+ .domain = 0x64,
+ .domain_mask = 0xffff,
+ },
+ {
+ .data = {.userdata = 25, .category_mask = ACL_DENY_MASK,
+ .priority = 400},
+ .dst_addr = RTE_IPV4(5,6,7,8),
+ .dst_mask_len = 24,
+ .src_addr = RTE_IPV4(1,2,3,4),
+ .src_mask_len = 16,
+ .proto = 0x5,
+ .proto_mask = 0xff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 22,
+ .dst_port_high = 1024,
+ .vlan = 0x8100,
+ .vlan_mask = 0xffff,
+ .domain = 0x64,
+ .domain_mask = 0xffff,
+ },
+ {
+ .data = {.userdata = 26, .category_mask = ACL_ALLOW_MASK,
+ .priority = 500},
+ .dst_addr = RTE_IPV4(1,2,3,4),
+ .dst_mask_len = 8,
+ .src_addr = RTE_IPV4(5,6,7,8),
+ .src_mask_len = 32,
+ .proto = 0x5,
+ .proto_mask = 0xff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 22,
+ .dst_port_high = 1024,
+ .vlan = 0x64,
+ .vlan_mask = 0xffff,
+ },
+ {
+ .data = {.userdata = 27, .category_mask = ACL_DENY_MASK,
+ .priority = 500},
+ .dst_addr = RTE_IPV4(5,6,7,8),
+ .dst_mask_len = 32,
+ .src_addr = RTE_IPV4(1,2,3,4),
+ .src_mask_len = 8,
+ .proto = 0x5,
+ .proto_mask = 0xff,
+ .src_port_low = 0,
+ .src_port_high = 0xffff,
+ .dst_port_low = 22,
+ .dst_port_high = 1024,
+ .vlan = 0x64,
+ .vlan_mask = 0xffff,
+ },
+};
+
+/* data for ACL unit test */
+struct ipv4_7tuple acl_test_data[] = {
+/* testing single rule aspects */
+ {.ip_src = RTE_IPV4(10,0,0,0), .allow = 4}, /* should match 4 */
+ {.ip_src = RTE_IPV4(10,1,1,2), .allow = 5}, /* should match 5 */
+ {.ip_src = RTE_IPV4(10,1,1,1), .allow = 5,
+ .deny = 6}, /* should match 5, 6 */
+ {.ip_dst = RTE_IPV4(10,0,0,0)}, /* should not match */
+ {.ip_dst = RTE_IPV4(10,1,1,2)}, /* should not match */
+ {.ip_dst = RTE_IPV4(10,1,1,1)}, /* should not match */
+
+ {.ip_src = RTE_IPV4(192,168,2,50)}, /* should not match */
+ {.ip_src = RTE_IPV4(192,168,1,2)}, /* should not match */
+ {.ip_src = RTE_IPV4(192,168,1,50)}, /* should not match */
+ {.ip_dst = RTE_IPV4(192,168,2,50), .allow = 1}, /* should match 1 */
+ {.ip_dst = RTE_IPV4(192,168,1,49), .allow = 2}, /* should match 2 */
+ {.ip_dst = RTE_IPV4(192,168,1,50), .allow = 2,
+ .deny = 3}, /* should match 2, 3 */
+
+ {.vlan = 0x64, .allow = 7}, /* should match 7 */
+ {.vlan = 0xfE4, .allow = 7}, /* should match 7 */
+ {.vlan = 0xE2}, /* should not match */
+ {.vlan = 0xD, .allow = 8}, /* should match 8 */
+ {.vlan = 0x6}, /* should not match */
+ {.vlan = 0x5, .allow = 8, .deny = 9}, /* should match 8, 9 */
+
+ {.domain = 0x64, .allow = 10}, /* should match 10 */
+ {.domain = 0xfE4, .allow = 10}, /* should match 10 */
+ {.domain = 0xE2}, /* should not match */
+ {.domain = 0xD, .allow = 11}, /* should match 11 */
+ {.domain = 0x6}, /* should not match */
+ {.domain = 0x5, .allow = 11, .deny = 12}, /* should match 11, 12 */
+
+ {.port_dst = 80, .allow = 13}, /* should match 13 */
+ {.port_dst = 79, .allow = 14}, /* should match 14 */
+ {.port_dst = 81, .allow = 14}, /* should match 14 */
+ {.port_dst = 21}, /* should not match */
+ {.port_dst = 1024, .deny = 16}, /* should match 16 */
+ {.port_dst = 1020, .allow = 14, .deny = 15}, /* should match 14, 15 */
+
+ {.port_src = 80, .allow = 17}, /* should match 17 */
+ {.port_src = 79, .allow = 18}, /* should match 18 */
+ {.port_src = 81, .allow = 18}, /* should match 18 */
+ {.port_src = 21}, /* should not match */
+ {.port_src = 1024, .deny = 20}, /* should match 20 */
+ {.port_src = 1020, .allow = 18, .deny = 19}, /* should match 18, 19 */
+
+ {.proto = 0x64, .allow = 21}, /* should match 21 */
+ {.proto = 0xE4, .allow = 21}, /* should match 21 */
+ {.proto = 0xE2}, /* should not match */
+ {.proto = 0xD, .allow = 22}, /* should match 22 */
+ {.proto = 0x6}, /* should not match */
+ {.proto = 0x5, .allow = 22, .deny = 23}, /* should match 22, 23 */
+
+/* testing matching multiple rules at once */
+ {.vlan = 0x5, .ip_src = RTE_IPV4(10,1,1,1),
+ .allow = 5, .deny = 9}, /* should match 5, 9 */
+ {.vlan = 0x5, .ip_src = RTE_IPV4(192,168,2,50),
+ .allow = 8, .deny = 9}, /* should match 8, 9 */
+ {.vlan = 0x55, .ip_src = RTE_IPV4(192,168,1,49),
+ .allow = 8}, /* should match 8 */
+ {.port_dst = 80, .port_src = 1024,
+ .allow = 13, .deny = 20}, /* should match 13,20 */
+ {.port_dst = 79, .port_src = 1024,
+ .allow = 14, .deny = 20}, /* should match 14,20 */
+ {.proto = 0x5, .ip_dst = RTE_IPV4(192,168,2,50),
+ .allow = 1, .deny = 23}, /* should match 1, 23 */
+
+ {.proto = 0x5, .ip_dst = RTE_IPV4(192,168,1,50),
+ .allow = 2, .deny = 23}, /* should match 2, 23 */
+ {.vlan = 0x64, .domain = 0x5,
+ .allow = 11, .deny = 12}, /* should match 11, 12 */
+ {.proto = 0x5, .port_src = 80,
+ .allow = 17, .deny = 23}, /* should match 17, 23 */
+ {.proto = 0x5, .port_dst = 80,
+ .allow = 13, .deny = 23}, /* should match 13, 23 */
+ {.proto = 0x51, .port_src = 5000}, /* should not match */
+ {.ip_src = RTE_IPV4(192,168,1,50),
+ .ip_dst = RTE_IPV4(10,0,0,0),
+ .proto = 0x51,
+ .port_src = 5000,
+ .port_dst = 5000}, /* should not match */
+
+/* test full packet rules */
+ {
+ .ip_dst = RTE_IPV4(1,2,100,200),
+ .ip_src = RTE_IPV4(5,6,7,254),
+ .proto = 0x5,
+ .vlan = 0x8100,
+ .domain = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 24,
+ .deny = 23
+ }, /* should match 23, 24 */
+ {
+ .ip_dst = RTE_IPV4(5,6,7,254),
+ .ip_src = RTE_IPV4(1,2,100,200),
+ .proto = 0x5,
+ .vlan = 0x8100,
+ .domain = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 13,
+ .deny = 25
+ }, /* should match 13, 25 */
+ {
+ .ip_dst = RTE_IPV4(1,10,20,30),
+ .ip_src = RTE_IPV4(5,6,7,8),
+ .proto = 0x5,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 26,
+ .deny = 23
+ }, /* should match 23, 26 */
+ {
+ .ip_dst = RTE_IPV4(5,6,7,8),
+ .ip_src = RTE_IPV4(1,10,20,30),
+ .proto = 0x5,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 13,
+ .deny = 27
+ }, /* should match 13, 27 */
+ {
+ .ip_dst = RTE_IPV4(2,2,3,4),
+ .ip_src = RTE_IPV4(4,6,7,8),
+ .proto = 0x5,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 13,
+ .deny = 23
+ }, /* should match 13, 23 */
+ {
+ .ip_dst = RTE_IPV4(1,2,3,4),
+ .ip_src = RTE_IPV4(4,6,7,8),
+ .proto = 0x5,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 80,
+ .allow = 13,
+ .deny = 23
+ }, /* should match 13, 23 */
+
+
+/* visual separator! */
+ {
+ .ip_dst = RTE_IPV4(1,2,100,200),
+ .ip_src = RTE_IPV4(5,6,7,254),
+ .proto = 0x55,
+ .vlan = 0x8000,
+ .domain = 0x6464,
+ .port_src = 12345,
+ .port_dst = 8080,
+ .allow = 10
+ }, /* should match 10 */
+ {
+ .ip_dst = RTE_IPV4(5,6,7,254),
+ .ip_src = RTE_IPV4(1,2,100,200),
+ .proto = 0x55,
+ .vlan = 0x8100,
+ .domain = 0x6464,
+ .port_src = 12345,
+ .port_dst = 180,
+ .allow = 10
+ }, /* should match 10 */
+ {
+ .ip_dst = RTE_IPV4(1,10,20,30),
+ .ip_src = RTE_IPV4(5,6,7,8),
+ .proto = 0x55,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 180,
+ .allow = 7
+ }, /* should match 7 */
+ {
+ .ip_dst = RTE_IPV4(5,6,7,8),
+ .ip_src = RTE_IPV4(1,10,20,30),
+ .proto = 0x55,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 180,
+ .allow = 7
+ }, /* should match 7 */
+ {
+ .ip_dst = RTE_IPV4(2,2,3,4),
+ .ip_src = RTE_IPV4(4,6,7,8),
+ .proto = 0x55,
+ .vlan = 0x64,
+ .port_src = 12345,
+ .port_dst = 180,
+ .allow = 7
+ }, /* should match 7 */
+ {
+ .ip_dst = RTE_IPV4(1,2,3,4),
+ .ip_src = RTE_IPV4(4,6,7,8),
+ .proto = 0x50,
+ .vlan = 0x6466,
+ .port_src = 12345,
+ .port_dst = 12345,
+ }, /* should not match */
+};
+
+/*
+ * ruleset for ACL 32 bit range (by src addr) unit test
+ * keep them ordered by priority in descending order.
+ */
+struct rte_acl_ipv4vlan_rule acl_u32_range_test_rules[] = {
+ {
+ .data = {
+ .userdata = 500,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 500
+ },
+ .src_addr = RTE_IPV4(0, 0, 0, 1),
+ .src_mask_len = RTE_IPV4(0, 0, 2, 58),
+ },
+ {
+ .data = {
+ .userdata = 400,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 400
+ },
+ .src_addr = RTE_IPV4(0, 4, 3, 2),
+ .src_mask_len = RTE_IPV4(0, 4, 7, 255),
+ },
+ {
+ .data = {
+ .userdata = 300,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 300
+ },
+ .src_addr = RTE_IPV4(0, 1, 12, 14),
+ .src_mask_len = RTE_IPV4(0, 3, 11, 13),
+ },
+ {
+ .data = {
+ .userdata = 200,
+ .category_mask = ACL_ALLOW_MASK,
+ .priority = 200
+ },
+ .src_addr = RTE_IPV4(0, 0, 1, 40),
+ .src_mask_len = RTE_IPV4(0, 4, 5, 6),
+ },
+};
+
+#endif /* TEST_ACL_H_ */
diff --git a/src/spdk/dpdk/app/test/test_alarm.c b/src/spdk/dpdk/app/test/test_alarm.c
new file mode 100644
index 000000000..951b7f07b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_alarm.c
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_interrupts.h>
+#include <rte_atomic.h>
+#include <rte_alarm.h>
+
+#include "test.h"
+
+#define US_PER_MS 1000
+
+#define RTE_TEST_ALARM_TIMEOUT 10 /* ms */
+#define RTE_TEST_CHECK_PERIOD 3 /* ms */
+#define RTE_TEST_MAX_REPEAT 20
+
+static volatile int flag;
+
+static void
+test_alarm_callback(void *cb_arg)
+{
+ flag = 1;
+ printf("Callback setting flag - OK. [cb_arg = %p]\n", cb_arg);
+}
+
+static rte_atomic32_t cb_count;
+
+static void
+test_multi_cb(void *arg)
+{
+ rte_atomic32_inc(&cb_count);
+ printf("In %s - arg = %p\n", __func__, arg);
+}
+
+static volatile int recursive_error = 0;
+
+static void
+test_remove_in_callback(void *arg)
+{
+ printf("In %s - arg = %p\n", __func__, arg);
+ if (rte_eal_alarm_cancel(test_remove_in_callback, arg) ||
+ rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1)) {
+ printf("Error - cancelling callback from within function succeeded!\n");
+ recursive_error = 1;
+ }
+ flag = (int)((uintptr_t)arg);
+}
+
+static volatile int flag_2;
+
+static void
+test_remove_in_callback_2(void *arg)
+{
+ if (rte_eal_alarm_cancel(test_remove_in_callback_2, arg) || rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1)) {
+ printf("Error - cancelling callback of test_remove_in_callback_2\n");
+ return;
+ }
+ flag_2 = 1;
+}
+
+static int
+test_multi_alarms(void)
+{
+ int rm_count = 0;
+ int count = 0;
+ cb_count.cnt = 0;
+
+ printf("Expect 6 callbacks in order...\n");
+ /* add two alarms in order */
+ rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1);
+ rte_eal_alarm_set(20 * US_PER_MS, test_multi_cb, (void *)2);
+
+ /* now add in reverse order */
+ rte_eal_alarm_set(60 * US_PER_MS, test_multi_cb, (void *)6);
+ rte_eal_alarm_set(50 * US_PER_MS, test_multi_cb, (void *)5);
+ rte_eal_alarm_set(40 * US_PER_MS, test_multi_cb, (void *)4);
+ rte_eal_alarm_set(30 * US_PER_MS, test_multi_cb, (void *)3);
+
+ /* wait for expiry */
+ rte_delay_ms(65);
+ if (cb_count.cnt != 6) {
+ printf("Missing callbacks\n");
+ /* remove any callbacks that might remain */
+ rte_eal_alarm_cancel(test_multi_cb, (void *)-1);
+ return -1;
+ }
+
+ cb_count.cnt = 0;
+ printf("Expect only callbacks with args 1 and 3...\n");
+ /* Add 3 flags, then delete one */
+ rte_eal_alarm_set(30 * US_PER_MS, test_multi_cb, (void *)3);
+ rte_eal_alarm_set(20 * US_PER_MS, test_multi_cb, (void *)2);
+ rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1);
+ rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *)2);
+
+ rte_delay_ms(35);
+ if (cb_count.cnt != 2 || rm_count != 1) {
+ printf("Error: invalid flags count or alarm removal failure"
+ " - flags value = %d, expected = %d\n",
+ (int)cb_count.cnt, 2);
+ /* remove any callbacks that might remain */
+ rte_eal_alarm_cancel(test_multi_cb, (void *)-1);
+ return -1;
+ }
+
+ printf("Testing adding and then removing multiple alarms\n");
+ /* finally test that no callbacks are called if we delete them all*/
+ rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)1);
+ rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)2);
+ rte_eal_alarm_set(10 * US_PER_MS, test_multi_cb, (void *)3);
+ rm_count = rte_eal_alarm_cancel(test_alarm_callback, (void *)-1);
+ if (rm_count != 0) {
+ printf("Error removing non-existant alarm succeeded\n");
+ rte_eal_alarm_cancel(test_multi_cb, (void *) -1);
+ return -1;
+ }
+ rm_count = rte_eal_alarm_cancel(test_multi_cb, (void *) -1);
+ if (rm_count != 3) {
+ printf("Error removing all pending alarm callbacks\n");
+ return -1;
+ }
+
+ /* Test that we cannot cancel an alarm from within the callback itself
+ * Also test that we can cancel head-of-line callbacks ok.*/
+ flag = 0;
+ recursive_error = 0;
+ rte_eal_alarm_set(10 * US_PER_MS, test_remove_in_callback, (void *)1);
+ rte_eal_alarm_set(20 * US_PER_MS, test_remove_in_callback, (void *)2);
+ rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)1);
+ if (rm_count != 1) {
+ printf("Error cancelling head-of-list callback\n");
+ return -1;
+ }
+ rte_delay_ms(15);
+ if (flag != 0) {
+ printf("Error, cancelling head-of-list leads to premature callback\n");
+ return -1;
+ }
+
+ while (flag != 2 && count++ < RTE_TEST_MAX_REPEAT)
+ rte_delay_ms(10);
+
+ if (flag != 2) {
+ printf("Error - expected callback not called\n");
+ rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1);
+ return -1;
+ }
+ if (recursive_error == 1)
+ return -1;
+
+ /* Check if it can cancel all for the same callback */
+ printf("Testing canceling all for the same callback\n");
+ flag_2 = 0;
+ rte_eal_alarm_set(10 * US_PER_MS, test_remove_in_callback, (void *)1);
+ rte_eal_alarm_set(20 * US_PER_MS, test_remove_in_callback_2, (void *)2);
+ rte_eal_alarm_set(30 * US_PER_MS, test_remove_in_callback_2, (void *)3);
+ rte_eal_alarm_set(40 * US_PER_MS, test_remove_in_callback, (void *)4);
+ rm_count = rte_eal_alarm_cancel(test_remove_in_callback_2, (void *)-1);
+ if (rm_count != 2) {
+ printf("Error, cannot cancel all for the same callback\n");
+ return -1;
+ }
+ rm_count = rte_eal_alarm_cancel(test_remove_in_callback, (void *)-1);
+ if (rm_count != 2) {
+ printf("Error, cannot cancel all for the same callback\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_alarm(void)
+{
+ int count = 0;
+#ifdef RTE_EXEC_ENV_FREEBSD
+ printf("The alarm API is not supported on FreeBSD\n");
+ return 0;
+#endif
+ /* check if the callback will be called */
+ printf("check if the callback will be called\n");
+ flag = 0;
+ if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT * US_PER_MS,
+ test_alarm_callback, NULL) < 0) {
+ printf("fail to set alarm callback\n");
+ return -1;
+ }
+ while (flag == 0 && count++ < RTE_TEST_MAX_REPEAT)
+ rte_delay_ms(RTE_TEST_CHECK_PERIOD);
+
+ if (flag == 0){
+ printf("Callback not called\n");
+ return -1;
+ }
+
+ /* check if it will fail to set alarm with wrong us value */
+ printf("check if it will fail to set alarm with wrong ms values\n");
+ if (rte_eal_alarm_set(0, test_alarm_callback,
+ NULL) >= 0) {
+ printf("should not be successful with 0 us value\n");
+ return -1;
+ }
+ if (rte_eal_alarm_set(UINT64_MAX - 1, test_alarm_callback,
+ NULL) >= 0) {
+ printf("should not be successful with (UINT64_MAX-1) us value\n");
+ return -1;
+ }
+
+ /* check if it will fail to set alarm with null callback parameter */
+ printf("check if it will fail to set alarm with null callback parameter\n");
+ if (rte_eal_alarm_set(RTE_TEST_ALARM_TIMEOUT, NULL, NULL) >= 0) {
+ printf("should not be successful to set alarm with null callback parameter\n");
+ return -1;
+ }
+
+ /* check if it will fail to remove alarm with null callback parameter */
+ printf("check if it will fail to remove alarm with null callback parameter\n");
+ if (rte_eal_alarm_cancel(NULL, NULL) == 0) {
+ printf("should not be successful to remove alarm with null callback parameter");
+ return -1;
+ }
+
+ if (test_multi_alarms() != 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(alarm_autotest, test_alarm);
diff --git a/src/spdk/dpdk/app/test/test_atomic.c b/src/spdk/dpdk/app/test/test_atomic.c
new file mode 100644
index 000000000..214452e54
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_atomic.c
@@ -0,0 +1,634 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ * Copyright(c) 2019 Arm Limited
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_random.h>
+#include <rte_hash_crc.h>
+
+#include "test.h"
+
+/*
+ * Atomic Variables
+ * ================
+ *
+ * - The main test function performs several subtests. The first
+ * checks that the usual inc/dec/add/sub functions are working
+ * correctly:
+ *
+ * - Initialize 16-bit, 32-bit and 64-bit atomic variables to specific
+ * values.
+ *
+ * - These variables are incremented and decremented on each core at
+ * the same time in ``test_atomic_usual()``.
+ *
+ * - The function checks that once all lcores finish their function,
+ * the value of the atomic variables are still the same.
+ *
+ * - Test "test and set" functions.
+ *
+ * - Initialize 16-bit, 32-bit and 64-bit atomic variables to zero.
+ *
+ * - Invoke ``test_atomic_tas()`` on each lcore: before doing anything
+ * else. The cores are waiting a synchro using ``while
+ * (rte_atomic32_read(&val) == 0)`` which is triggered by the main test
+ * function. Then all cores do a
+ * ``rte_atomicXX_test_and_set()`` at the same time. If it is successful,
+ * it increments another atomic counter.
+ *
+ * - The main function checks that the atomic counter was incremented
+ * twice only (one for 16-bit, one for 32-bit and one for 64-bit values).
+ *
+ * - Test "add/sub and return" functions
+ *
+ * - Initialize 16-bit, 32-bit and 64-bit atomic variables to zero.
+ *
+ * - Invoke ``test_atomic_addsub_return()`` on each lcore. Before doing
+ * anything else, the cores are waiting a synchro. Each lcore does
+ * this operation several times::
+ *
+ * tmp = rte_atomicXX_add_return(&a, 1);
+ * atomic_add(&count, tmp);
+ * tmp = rte_atomicXX_sub_return(&a, 1);
+ * atomic_sub(&count, tmp+1);
+ *
+ * - At the end of the test, the *count* value must be 0.
+ *
+ * - Test "128-bit compare and swap" (aarch64 and x86_64 only)
+ *
+ * - Initialize 128-bit atomic variables to zero.
+ *
+ * - Invoke ``test_atomic128_cmp_exchange()`` on each lcore. Before doing
+ * anything else, the cores are waiting a synchro. Each lcore does
+ * these compare and swap (CAS) operations several times::
+ *
+ * Acquired CAS update counter.val[0] + 2; counter.val[1] + 1;
+ * Released CAS update counter.val[0] + 2; counter.val[1] + 1;
+ * Acquired_Released CAS update counter.val[0] + 2; counter.val[1] + 1;
+ * Relaxed CAS update counter.val[0] + 2; counter.val[1] + 1;
+ *
+ * - At the end of the test, the *count128* first 64-bit value and
+ * second 64-bit value differ by the total iterations.
+ *
+ * - Test "atomic exchange" functions
+ *
+ * - Create a 64 bit token that can be tested for data integrity
+ *
+ * - Invoke ``test_atomic_exchange`` on each lcore. Before doing
+ * anything else, the cores wait for a synchronization event.
+ * Each core then does the follwoing for N iterations:
+ *
+ * Generate a new token with a data integrity check
+ * Exchange the new token for previously generated token
+ * Increment a counter if a corrupt token was received
+ *
+ * - At the end of the test, the number of corrupted tokens must be 0.
+ */
+
+#define NUM_ATOMIC_TYPES 3
+
+#define N 1000000
+
+static rte_atomic16_t a16;
+static rte_atomic32_t a32;
+static rte_atomic64_t a64;
+static rte_atomic64_t count;
+static rte_atomic32_t synchro;
+
+static int
+test_atomic_usual(__rte_unused void *arg)
+{
+ unsigned i;
+
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ for (i = 0; i < N; i++)
+ rte_atomic16_inc(&a16);
+ for (i = 0; i < N; i++)
+ rte_atomic16_dec(&a16);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic16_add(&a16, 5);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic16_sub(&a16, 5);
+
+ for (i = 0; i < N; i++)
+ rte_atomic32_inc(&a32);
+ for (i = 0; i < N; i++)
+ rte_atomic32_dec(&a32);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic32_add(&a32, 5);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic32_sub(&a32, 5);
+
+ for (i = 0; i < N; i++)
+ rte_atomic64_inc(&a64);
+ for (i = 0; i < N; i++)
+ rte_atomic64_dec(&a64);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic64_add(&a64, 5);
+ for (i = 0; i < (N / 5); i++)
+ rte_atomic64_sub(&a64, 5);
+
+ return 0;
+}
+
+static int
+test_atomic_tas(__rte_unused void *arg)
+{
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ if (rte_atomic16_test_and_set(&a16))
+ rte_atomic64_inc(&count);
+ if (rte_atomic32_test_and_set(&a32))
+ rte_atomic64_inc(&count);
+ if (rte_atomic64_test_and_set(&a64))
+ rte_atomic64_inc(&count);
+
+ return 0;
+}
+
+static int
+test_atomic_addsub_and_return(__rte_unused void *arg)
+{
+ uint32_t tmp16;
+ uint32_t tmp32;
+ uint64_t tmp64;
+ unsigned i;
+
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ for (i = 0; i < N; i++) {
+ tmp16 = rte_atomic16_add_return(&a16, 1);
+ rte_atomic64_add(&count, tmp16);
+
+ tmp16 = rte_atomic16_sub_return(&a16, 1);
+ rte_atomic64_sub(&count, tmp16+1);
+
+ tmp32 = rte_atomic32_add_return(&a32, 1);
+ rte_atomic64_add(&count, tmp32);
+
+ tmp32 = rte_atomic32_sub_return(&a32, 1);
+ rte_atomic64_sub(&count, tmp32+1);
+
+ tmp64 = rte_atomic64_add_return(&a64, 1);
+ rte_atomic64_add(&count, tmp64);
+
+ tmp64 = rte_atomic64_sub_return(&a64, 1);
+ rte_atomic64_sub(&count, tmp64+1);
+ }
+
+ return 0;
+}
+
+/*
+ * rte_atomic32_inc_and_test() would increase a 32 bits counter by one and then
+ * test if that counter is equal to 0. It would return true if the counter is 0
+ * and false if the counter is not 0. rte_atomic64_inc_and_test() could do the
+ * same thing but for a 64 bits counter.
+ * Here checks that if the 32/64 bits counter is equal to 0 after being atomically
+ * increased by one. If it is, increase the variable of "count" by one which would
+ * be checked as the result later.
+ *
+ */
+static int
+test_atomic_inc_and_test(__rte_unused void *arg)
+{
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ if (rte_atomic16_inc_and_test(&a16)) {
+ rte_atomic64_inc(&count);
+ }
+ if (rte_atomic32_inc_and_test(&a32)) {
+ rte_atomic64_inc(&count);
+ }
+ if (rte_atomic64_inc_and_test(&a64)) {
+ rte_atomic64_inc(&count);
+ }
+
+ return 0;
+}
+
+/*
+ * rte_atomicXX_dec_and_test() should decrease a 32 bits counter by one and then
+ * test if that counter is equal to 0. It should return true if the counter is 0
+ * and false if the counter is not 0.
+ * This test checks if the counter is equal to 0 after being atomically
+ * decreased by one. If it is, increase the value of "count" by one which is to
+ * be checked as the result later.
+ */
+static int
+test_atomic_dec_and_test(__rte_unused void *arg)
+{
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ if (rte_atomic16_dec_and_test(&a16))
+ rte_atomic64_inc(&count);
+
+ if (rte_atomic32_dec_and_test(&a32))
+ rte_atomic64_inc(&count);
+
+ if (rte_atomic64_dec_and_test(&a64))
+ rte_atomic64_inc(&count);
+
+ return 0;
+}
+
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+static rte_int128_t count128;
+
+/*
+ * rte_atomic128_cmp_exchange() should update a 128 bits counter's first 64
+ * bits by 2 and the second 64 bits by 1 in this test. It should return true
+ * if the compare exchange operation is successful.
+ * This test repeats 128 bits compare and swap operations N rounds. In each
+ * iteration it runs compare and swap operation with different memory models.
+ */
+static int
+test_atomic128_cmp_exchange(__rte_unused void *arg)
+{
+ rte_int128_t expected;
+ int success;
+ unsigned int i;
+
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ expected = count128;
+
+ for (i = 0; i < N; i++) {
+ do {
+ rte_int128_t desired;
+
+ desired.val[0] = expected.val[0] + 2;
+ desired.val[1] = expected.val[1] + 1;
+
+ success = rte_atomic128_cmp_exchange(&count128,
+ &expected, &desired, 1,
+ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
+ } while (success == 0);
+
+ do {
+ rte_int128_t desired;
+
+ desired.val[0] = expected.val[0] + 2;
+ desired.val[1] = expected.val[1] + 1;
+
+ success = rte_atomic128_cmp_exchange(&count128,
+ &expected, &desired, 1,
+ __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+ } while (success == 0);
+
+ do {
+ rte_int128_t desired;
+
+ desired.val[0] = expected.val[0] + 2;
+ desired.val[1] = expected.val[1] + 1;
+
+ success = rte_atomic128_cmp_exchange(&count128,
+ &expected, &desired, 1,
+ __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+ } while (success == 0);
+
+ do {
+ rte_int128_t desired;
+
+ desired.val[0] = expected.val[0] + 2;
+ desired.val[1] = expected.val[1] + 1;
+
+ success = rte_atomic128_cmp_exchange(&count128,
+ &expected, &desired, 1,
+ __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+ } while (success == 0);
+ }
+
+ return 0;
+}
+#endif
+
+/*
+ * Helper definitions/variables/functions for
+ * atomic exchange tests
+ */
+typedef union {
+ uint16_t u16;
+ uint8_t u8[2];
+} test16_t;
+
+typedef union {
+ uint32_t u32;
+ uint16_t u16[2];
+ uint8_t u8[4];
+} test32_t;
+
+typedef union {
+ uint64_t u64;
+ uint32_t u32[2];
+ uint16_t u16[4];
+ uint8_t u8[8];
+} test64_t;
+
+const uint8_t CRC8_POLY = 0x91;
+uint8_t crc8_table[256];
+
+volatile uint16_t token16;
+volatile uint32_t token32;
+volatile uint64_t token64;
+
+static void
+build_crc8_table(void)
+{
+ uint8_t val;
+ int i, j;
+
+ for (i = 0; i < 256; i++) {
+ val = i;
+ for (j = 0; j < 8; j++) {
+ if (val & 1)
+ val ^= CRC8_POLY;
+ val >>= 1;
+ }
+ crc8_table[i] = val;
+ }
+}
+
+static uint8_t
+get_crc8(uint8_t *message, int length)
+{
+ uint8_t crc = 0;
+ int i;
+
+ for (i = 0; i < length; i++)
+ crc = crc8_table[crc ^ message[i]];
+ return crc;
+}
+
+/*
+ * The atomic exchange test sets up a token in memory and
+ * then spins up multiple lcores whose job is to generate
+ * new tokens, exchange that new token for the old one held
+ * in memory, and then verify that the old token is still
+ * valid (i.e. the exchange did not corrupt the token).
+ *
+ * A token is made up of random data and 8 bits of crc
+ * covering that random data. The following is an example
+ * of a 64bit token.
+ *
+ * +------------+------------+
+ * | 63 56 | 55 0 |
+ * +------------+------------+
+ * | CRC8 | Data |
+ * +------------+------------+
+ */
+static int
+test_atomic_exchange(__rte_unused void *arg)
+{
+ int i;
+ test16_t nt16, ot16; /* new token, old token */
+ test32_t nt32, ot32;
+ test64_t nt64, ot64;
+
+ /* Wait until all of the other threads have been dispatched */
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ /*
+ * Let the battle begin! Every thread attempts to steal the current
+ * token with an atomic exchange operation and install its own newly
+ * generated token. If the old token is valid (i.e. it has the
+ * appropriate crc32 hash for the data) then the test iteration has
+ * passed. If the token is invalid, increment the counter.
+ */
+ for (i = 0; i < N; i++) {
+
+ /* Test 64bit Atomic Exchange */
+ nt64.u64 = rte_rand();
+ nt64.u8[7] = get_crc8(&nt64.u8[0], sizeof(nt64) - 1);
+ ot64.u64 = rte_atomic64_exchange(&token64, nt64.u64);
+ if (ot64.u8[7] != get_crc8(&ot64.u8[0], sizeof(ot64) - 1))
+ rte_atomic64_inc(&count);
+
+ /* Test 32bit Atomic Exchange */
+ nt32.u32 = (uint32_t)rte_rand();
+ nt32.u8[3] = get_crc8(&nt32.u8[0], sizeof(nt32) - 1);
+ ot32.u32 = rte_atomic32_exchange(&token32, nt32.u32);
+ if (ot32.u8[3] != get_crc8(&ot32.u8[0], sizeof(ot32) - 1))
+ rte_atomic64_inc(&count);
+
+ /* Test 16bit Atomic Exchange */
+ nt16.u16 = (uint16_t)rte_rand();
+ nt16.u8[1] = get_crc8(&nt16.u8[0], sizeof(nt16) - 1);
+ ot16.u16 = rte_atomic16_exchange(&token16, nt16.u16);
+ if (ot16.u8[1] != get_crc8(&ot16.u8[0], sizeof(ot16) - 1))
+ rte_atomic64_inc(&count);
+ }
+
+ return 0;
+}
+static int
+test_atomic(void)
+{
+ rte_atomic16_init(&a16);
+ rte_atomic32_init(&a32);
+ rte_atomic64_init(&a64);
+ rte_atomic64_init(&count);
+ rte_atomic32_init(&synchro);
+
+ rte_atomic16_set(&a16, 1UL << 10);
+ rte_atomic32_set(&a32, 1UL << 10);
+ rte_atomic64_set(&a64, 1ULL << 33);
+
+ printf("usual inc/dec/add/sub functions\n");
+
+ rte_eal_mp_remote_launch(test_atomic_usual, NULL, SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_set(&synchro, 0);
+
+ if (rte_atomic16_read(&a16) != 1UL << 10) {
+ printf("Atomic16 usual functions failed\n");
+ return -1;
+ }
+
+ if (rte_atomic32_read(&a32) != 1UL << 10) {
+ printf("Atomic32 usual functions failed\n");
+ return -1;
+ }
+
+ if (rte_atomic64_read(&a64) != 1ULL << 33) {
+ printf("Atomic64 usual functions failed\n");
+ return -1;
+ }
+
+ printf("test and set\n");
+
+ rte_atomic64_set(&a64, 0);
+ rte_atomic32_set(&a32, 0);
+ rte_atomic16_set(&a16, 0);
+ rte_atomic64_set(&count, 0);
+ rte_eal_mp_remote_launch(test_atomic_tas, NULL, SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_set(&synchro, 0);
+
+ if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) {
+ printf("Atomic test and set failed\n");
+ return -1;
+ }
+
+ printf("add/sub and return\n");
+
+ rte_atomic64_set(&a64, 0);
+ rte_atomic32_set(&a32, 0);
+ rte_atomic16_set(&a16, 0);
+ rte_atomic64_set(&count, 0);
+ rte_eal_mp_remote_launch(test_atomic_addsub_and_return, NULL,
+ SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_set(&synchro, 0);
+
+ if (rte_atomic64_read(&count) != 0) {
+ printf("Atomic add/sub+return failed\n");
+ return -1;
+ }
+
+ /*
+ * Set a64, a32 and a16 with the same value of minus "number of slave
+ * lcores", launch all slave lcores to atomically increase by one and
+ * test them respectively.
+ * Each lcore should have only one chance to increase a64 by one and
+ * then check if it is equal to 0, but there should be only one lcore
+ * that finds that it is 0. It is similar for a32 and a16.
+ * Then a variable of "count", initialized to zero, is increased by
+ * one if a64, a32 or a16 is 0 after being increased and tested
+ * atomically.
+ * We can check if "count" is finally equal to 3 to see if all slave
+ * lcores performed "atomic inc and test" right.
+ */
+ printf("inc and test\n");
+
+ rte_atomic64_clear(&a64);
+ rte_atomic32_clear(&a32);
+ rte_atomic16_clear(&a16);
+ rte_atomic32_clear(&synchro);
+ rte_atomic64_clear(&count);
+
+ rte_atomic64_set(&a64, (int64_t)(1 - (int64_t)rte_lcore_count()));
+ rte_atomic32_set(&a32, (int32_t)(1 - (int32_t)rte_lcore_count()));
+ rte_atomic16_set(&a16, (int16_t)(1 - (int16_t)rte_lcore_count()));
+ rte_eal_mp_remote_launch(test_atomic_inc_and_test, NULL, SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_clear(&synchro);
+
+ if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) {
+ printf("Atomic inc and test failed %d\n", (int)count.cnt);
+ return -1;
+ }
+
+ /*
+ * Same as above, but this time we set the values to "number of slave
+ * lcores", and decrement instead of increment.
+ */
+ printf("dec and test\n");
+
+ rte_atomic32_clear(&synchro);
+ rte_atomic64_clear(&count);
+
+ rte_atomic64_set(&a64, (int64_t)(rte_lcore_count() - 1));
+ rte_atomic32_set(&a32, (int32_t)(rte_lcore_count() - 1));
+ rte_atomic16_set(&a16, (int16_t)(rte_lcore_count() - 1));
+ rte_eal_mp_remote_launch(test_atomic_dec_and_test, NULL, SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_clear(&synchro);
+
+ if (rte_atomic64_read(&count) != NUM_ATOMIC_TYPES) {
+ printf("Atomic dec and test failed\n");
+ return -1;
+ }
+
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ /*
+ * This case tests the functionality of rte_atomic128_cmp_exchange
+ * API. It calls rte_atomic128_cmp_exchange with four kinds of memory
+ * models successively on each slave core. Once each 128-bit atomic
+ * compare and swap operation is successful, it updates the global
+ * 128-bit counter by 2 for the first 64-bit and 1 for the second
+ * 64-bit. Each slave core iterates this test N times.
+ * At the end of test, verify whether the first 64-bits of the 128-bit
+ * counter and the second 64bits is differ by the total iterations. If
+ * it is, the test passes.
+ */
+ printf("128-bit compare and swap test\n");
+ uint64_t iterations = 0;
+
+ rte_atomic32_clear(&synchro);
+ count128.val[0] = 0;
+ count128.val[1] = 0;
+
+ rte_eal_mp_remote_launch(test_atomic128_cmp_exchange, NULL,
+ SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_clear(&synchro);
+
+ iterations = count128.val[0] - count128.val[1];
+ if (iterations != 4*N*(rte_lcore_count()-1)) {
+ printf("128-bit compare and swap failed\n");
+ return -1;
+ }
+#endif
+
+ /*
+ * Test 16/32/64bit atomic exchange.
+ */
+ test64_t t;
+
+ printf("exchange test\n");
+
+ rte_atomic32_clear(&synchro);
+ rte_atomic64_clear(&count);
+
+ /* Generate the CRC8 lookup table */
+ build_crc8_table();
+
+ /* Create the initial tokens used by the test */
+ t.u64 = rte_rand();
+ token16 = (get_crc8(&t.u8[0], sizeof(token16) - 1) << 8)
+ | (t.u16[0] & 0x00ff);
+ token32 = ((uint32_t)get_crc8(&t.u8[0], sizeof(token32) - 1) << 24)
+ | (t.u32[0] & 0x00ffffff);
+ token64 = ((uint64_t)get_crc8(&t.u8[0], sizeof(token64) - 1) << 56)
+ | (t.u64 & 0x00ffffffffffffff);
+
+ rte_eal_mp_remote_launch(test_atomic_exchange, NULL, SKIP_MASTER);
+ rte_atomic32_set(&synchro, 1);
+ rte_eal_mp_wait_lcore();
+ rte_atomic32_clear(&synchro);
+
+ if (rte_atomic64_read(&count) > 0) {
+ printf("Atomic exchange test failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+REGISTER_TEST_COMMAND(atomic_autotest, test_atomic);
diff --git a/src/spdk/dpdk/app/test/test_barrier.c b/src/spdk/dpdk/app/test/test_barrier.c
new file mode 100644
index 000000000..43b5f6232
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_barrier.c
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+ /*
+ * This is a simple functional test for rte_smp_mb() implementation.
+ * I.E. make sure that LOAD and STORE operations that precede the
+ * rte_smp_mb() call are globally visible across the lcores
+ * before the the LOAD and STORE operations that follows it.
+ * The test uses simple implementation of Peterson's lock algorithm
+ * (https://en.wikipedia.org/wiki/Peterson%27s_algorithm)
+ * for two execution units to make sure that rte_smp_mb() prevents
+ * store-load reordering to happen.
+ * Also when executed on a single lcore could be used as a approxiamate
+ * estimation of number of cycles particular implementation of rte_smp_mb()
+ * will take.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_pause.h>
+#include <rte_random.h>
+#include <rte_cycles.h>
+#include <rte_vect.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+#define ADD_MAX 8
+#define ITER_MAX 0x1000000
+
+enum plock_use_type {
+ USE_MB,
+ USE_SMP_MB,
+ USE_NUM
+};
+
+struct plock {
+ volatile uint32_t flag[2];
+ volatile uint32_t victim;
+ enum plock_use_type utype;
+};
+
+/*
+ * Lock plus protected by it two counters.
+ */
+struct plock_test {
+ struct plock lock;
+ uint64_t val;
+ uint64_t iter;
+};
+
+/*
+ * Each active lcore shares plock_test struct with it's left and right
+ * neighbours.
+ */
+struct lcore_plock_test {
+ struct plock_test *pt[2]; /* shared, lock-protected data */
+ uint64_t sum[2]; /* local copy of the shared data */
+ uint64_t iter; /* number of iterations to perfom */
+ uint32_t lc; /* given lcore id */
+};
+
+static inline void
+store_load_barrier(uint32_t utype)
+{
+ if (utype == USE_MB)
+ rte_mb();
+ else if (utype == USE_SMP_MB)
+ rte_smp_mb();
+ else
+ RTE_VERIFY(0);
+}
+
+/*
+ * Peterson lock implementation.
+ */
+static void
+plock_lock(struct plock *l, uint32_t self)
+{
+ uint32_t other;
+
+ other = self ^ 1;
+
+ l->flag[self] = 1;
+ rte_smp_wmb();
+ l->victim = self;
+
+ store_load_barrier(l->utype);
+
+ while (l->flag[other] == 1 && l->victim == self)
+ rte_pause();
+ rte_smp_rmb();
+}
+
+static void
+plock_unlock(struct plock *l, uint32_t self)
+{
+ rte_smp_wmb();
+ l->flag[self] = 0;
+}
+
+static void
+plock_reset(struct plock *l, enum plock_use_type utype)
+{
+ memset(l, 0, sizeof(*l));
+ l->utype = utype;
+}
+
+/*
+ * grab the lock, update both counters, release the lock.
+ */
+static void
+plock_add(struct plock_test *pt, uint32_t self, uint32_t n)
+{
+ plock_lock(&pt->lock, self);
+ pt->iter++;
+ pt->val += n;
+ plock_unlock(&pt->lock, self);
+}
+
+static int
+plock_test1_lcore(void *data)
+{
+ uint64_t tm;
+ uint32_t lc, ln;
+ uint64_t i, n;
+ struct lcore_plock_test *lpt;
+
+ lpt = data;
+ lc = rte_lcore_id();
+
+ /* find lcore_plock_test struct for given lcore */
+ for (ln = rte_lcore_count(); ln != 0 && lpt->lc != lc; lpt++, ln--)
+ ;
+
+ if (ln == 0) {
+ printf("%s(%u) error at init\n", __func__, lc);
+ return -1;
+ }
+
+ n = rte_rand() % ADD_MAX;
+ tm = rte_get_timer_cycles();
+
+ /*
+ * for each iteration:
+ * - update shared, locked protected data in a safe manner
+ * - update local copy of the shared data
+ */
+ for (i = 0; i != lpt->iter; i++) {
+
+ plock_add(lpt->pt[0], 0, n);
+ plock_add(lpt->pt[1], 1, n);
+
+ lpt->sum[0] += n;
+ lpt->sum[1] += n;
+
+ n = (n + 1) % ADD_MAX;
+ }
+
+ tm = rte_get_timer_cycles() - tm;
+
+ printf("%s(%u): %" PRIu64 " iterations finished, in %" PRIu64
+ " cycles, %#Lf cycles/iteration, "
+ "local sum={%" PRIu64 ", %" PRIu64 "}\n",
+ __func__, lc, i, tm, (long double)tm / i,
+ lpt->sum[0], lpt->sum[1]);
+ return 0;
+}
+
+/*
+ * For N active lcores we allocate N+1 lcore_plock_test structures.
+ * Each active lcore shares one lcore_plock_test structure with its
+ * left lcore neighbor and one lcore_plock_test structure with its
+ * right lcore neighbor.
+ * During the test each lcore updates data in both shared structures and
+ * its local copies. Then at validation phase we check that our shared
+ * and local data are the same.
+ */
+static int
+plock_test(uint64_t iter, enum plock_use_type utype)
+{
+ int32_t rc;
+ uint32_t i, lc, n;
+ uint64_t *sum;
+ struct plock_test *pt;
+ struct lcore_plock_test *lpt;
+
+ /* init phase, allocate and initialize shared data */
+
+ n = rte_lcore_count();
+ pt = calloc(n + 1, sizeof(*pt));
+ lpt = calloc(n, sizeof(*lpt));
+ sum = calloc(n + 1, sizeof(*sum));
+
+ printf("%s(iter=%" PRIu64 ", utype=%u) started on %u lcores\n",
+ __func__, iter, utype, n);
+
+ if (pt == NULL || lpt == NULL || sum == NULL) {
+ printf("%s: failed to allocate memory for %u lcores\n",
+ __func__, n);
+ free(pt);
+ free(lpt);
+ free(sum);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i != n + 1; i++)
+ plock_reset(&pt[i].lock, utype);
+
+ i = 0;
+ RTE_LCORE_FOREACH(lc) {
+
+ lpt[i].lc = lc;
+ lpt[i].iter = iter;
+ lpt[i].pt[0] = pt + i;
+ lpt[i].pt[1] = pt + i + 1;
+ i++;
+ }
+
+ lpt[i - 1].pt[1] = pt;
+
+ for (i = 0; i != n; i++)
+ printf("lpt[%u]={lc=%u, pt={%p, %p},};\n",
+ i, lpt[i].lc, lpt[i].pt[0], lpt[i].pt[1]);
+
+
+ /* test phase - start and wait for completion on each active lcore */
+
+ rte_eal_mp_remote_launch(plock_test1_lcore, lpt, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ /* validation phase - make sure that shared and local data match */
+
+ for (i = 0; i != n; i++) {
+ sum[i] += lpt[i].sum[0];
+ sum[i + 1] += lpt[i].sum[1];
+ }
+
+ sum[0] += sum[i];
+
+ rc = 0;
+ for (i = 0; i != n; i++) {
+ printf("%s: sum[%u]=%" PRIu64 ", pt[%u].val=%" PRIu64 ", pt[%u].iter=%" PRIu64 ";\n",
+ __func__, i, sum[i], i, pt[i].val, i, pt[i].iter);
+
+ /* race condition occurred, lock doesn't work properly */
+ if (sum[i] != pt[i].val || 2 * iter != pt[i].iter) {
+ printf("error: local and shared sums don't match\n");
+ rc = -1;
+ }
+ }
+
+ free(pt);
+ free(lpt);
+ free(sum);
+
+ printf("%s(utype=%u) returns %d\n", __func__, utype, rc);
+ return rc;
+}
+
+static int
+test_barrier(void)
+{
+ int32_t i, ret, rc[USE_NUM];
+
+ for (i = 0; i != RTE_DIM(rc); i++)
+ rc[i] = plock_test(ITER_MAX, i);
+
+ ret = 0;
+ for (i = 0; i != RTE_DIM(rc); i++) {
+ printf("%s for utype=%d %s\n",
+ __func__, i, rc[i] == 0 ? "passed" : "failed");
+ ret |= rc[i];
+ }
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(barrier_autotest, test_barrier);
diff --git a/src/spdk/dpdk/app/test/test_bitmap.c b/src/spdk/dpdk/app/test/test_bitmap.c
new file mode 100644
index 000000000..a8204d329
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_bitmap.c
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_bitmap.h>
+#include <rte_malloc.h>
+
+#include "test.h"
+
+#define MAX_BITS 1000
+
+static int
+test_bitmap_scan_operations(struct rte_bitmap *bmp)
+{
+ uint32_t pos = 0;
+ uint64_t slab1_magic = 0xBADC0FFEEBADF00D;
+ uint64_t slab2_magic = 0xFEEDDEADDEADF00D;
+ uint64_t out_slab = 0;
+
+ rte_bitmap_reset(bmp);
+
+ rte_bitmap_set_slab(bmp, pos, slab1_magic);
+ rte_bitmap_set_slab(bmp, pos + RTE_BITMAP_SLAB_BIT_SIZE, slab2_magic);
+
+ if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
+ printf("Failed to get slab from bitmap.\n");
+ return TEST_FAILED;
+ }
+
+ if (slab1_magic != out_slab) {
+ printf("Scan operation sanity failed.\n");
+ return TEST_FAILED;
+ }
+
+ if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
+ printf("Failed to get slab from bitmap.\n");
+ return TEST_FAILED;
+ }
+
+ if (slab2_magic != out_slab) {
+ printf("Scan operation sanity failed.\n");
+ return TEST_FAILED;
+ }
+
+ /* Wrap around */
+ if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
+ printf("Failed to get slab from bitmap.\n");
+ return TEST_FAILED;
+ }
+
+ if (slab1_magic != out_slab) {
+ printf("Scan operation wrap around failed.\n");
+ return TEST_FAILED;
+ }
+
+ /* Scan reset check. */
+ __rte_bitmap_scan_init(bmp);
+
+ if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
+ printf("Failed to get slab from bitmap.\n");
+ return TEST_FAILED;
+ }
+
+ if (slab1_magic != out_slab) {
+ printf("Scan reset operation failed.\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bitmap_slab_set_get(struct rte_bitmap *bmp)
+{
+ uint32_t pos = 0;
+ uint64_t slab_magic = 0xBADC0FFEEBADF00D;
+ uint64_t out_slab = 0;
+
+ rte_bitmap_reset(bmp);
+ rte_bitmap_set_slab(bmp, pos, slab_magic);
+
+ if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
+ printf("Failed to get slab from bitmap.\n");
+ return TEST_FAILED;
+ }
+
+
+ if (slab_magic != out_slab) {
+ printf("Invalid slab in bitmap.\n");
+ return TEST_FAILED;
+ }
+
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bitmap_set_get_clear(struct rte_bitmap *bmp)
+{
+ uint64_t val;
+ int i;
+
+ rte_bitmap_reset(bmp);
+ for (i = 0; i < MAX_BITS; i++)
+ rte_bitmap_set(bmp, i);
+
+ for (i = 0; i < MAX_BITS; i++) {
+ if (!rte_bitmap_get(bmp, i)) {
+ printf("Failed to get set bit.\n");
+ return TEST_FAILED;
+ }
+ }
+
+ for (i = 0; i < MAX_BITS; i++)
+ rte_bitmap_clear(bmp, i);
+
+ for (i = 0; i < MAX_BITS; i++) {
+ if (rte_bitmap_get(bmp, i)) {
+ printf("Failed to clear set bit.\n");
+ return TEST_FAILED;
+ }
+ }
+
+ rte_bitmap_reset(bmp);
+
+ /* Alternate slab set test */
+ for (i = 0; i < MAX_BITS; i++) {
+ if (i % RTE_BITMAP_SLAB_BIT_SIZE)
+ rte_bitmap_set(bmp, i);
+ }
+
+ for (i = 0; i < MAX_BITS; i++) {
+ val = rte_bitmap_get(bmp, i);
+ if (((i % RTE_BITMAP_SLAB_BIT_SIZE) && !val) ||
+ (!(i % RTE_BITMAP_SLAB_BIT_SIZE) && val)) {
+ printf("Failed to get set bit.\n");
+ return TEST_FAILED;
+ }
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bitmap_all_clear(void)
+{
+ void *mem;
+ uint32_t bmp_size;
+ struct rte_bitmap *bmp;
+
+ bmp_size =
+ rte_bitmap_get_memory_footprint(MAX_BITS);
+
+ mem = rte_zmalloc("test_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+ if (mem == NULL) {
+ printf("Failed to allocate memory for bitmap\n");
+ return TEST_FAILED;
+ }
+
+ bmp = rte_bitmap_init(MAX_BITS, mem, bmp_size);
+ if (bmp == NULL) {
+ printf("Failed to init bitmap\n");
+ return TEST_FAILED;
+ }
+
+ if (test_bitmap_set_get_clear(bmp) < 0)
+ return TEST_FAILED;
+
+ if (test_bitmap_slab_set_get(bmp) < 0)
+ return TEST_FAILED;
+
+ if (test_bitmap_scan_operations(bmp) < 0)
+ return TEST_FAILED;
+
+ rte_bitmap_free(bmp);
+ rte_free(mem);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bitmap_all_set(void)
+{
+ void *mem;
+ uint32_t i;
+ uint64_t slab;
+ uint32_t pos;
+ uint32_t bmp_size;
+ struct rte_bitmap *bmp;
+
+ bmp_size =
+ rte_bitmap_get_memory_footprint(MAX_BITS);
+
+ mem = rte_zmalloc("test_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+ if (mem == NULL) {
+ printf("Failed to allocate memory for bitmap\n");
+ return TEST_FAILED;
+ }
+
+ bmp = rte_bitmap_init_with_all_set(MAX_BITS, mem, bmp_size);
+ if (bmp == NULL) {
+ printf("Failed to init bitmap\n");
+ return TEST_FAILED;
+ }
+
+ for (i = 0; i < MAX_BITS; i++) {
+ pos = slab = 0;
+ if (!rte_bitmap_scan(bmp, &pos, &slab)) {
+ printf("Failed with init bitmap.\n");
+ return TEST_FAILED;
+ }
+ pos += (slab ? __builtin_ctzll(slab) : 0);
+ rte_bitmap_clear(bmp, pos);
+ }
+
+ if (rte_bitmap_scan(bmp, &pos, &slab)) {
+ printf("Too much bits set.\n");
+ return TEST_FAILED;
+ }
+
+ rte_bitmap_free(bmp);
+ rte_free(mem);
+
+ return TEST_SUCCESS;
+
+}
+
+static int
+test_bitmap(void)
+{
+ if (test_bitmap_all_clear() != TEST_SUCCESS)
+ return TEST_FAILED;
+ return test_bitmap_all_set();
+}
+
+REGISTER_TEST_COMMAND(bitmap_test, test_bitmap);
diff --git a/src/spdk/dpdk/app/test/test_bitratestats.c b/src/spdk/dpdk/app/test/test_bitratestats.c
new file mode 100644
index 000000000..39d7f734d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_bitratestats.c
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <errno.h>
+#include <rte_lcore.h>
+#include <rte_memzone.h>
+#include <rte_metrics.h>
+#include <rte_bitrate.h>
+
+#include "sample_packet_forward.h"
+#include "test.h"
+
+#define BIT_NUM_PACKETS 10
+#define QUEUE_ID 0
+
+static uint16_t portid;
+static struct rte_stats_bitrates *bitrate_data;
+static struct rte_ring *ring;
+
+/* To test whether rte_stats_bitrate_create is successful */
+static int
+test_stats_bitrate_create(void)
+{
+ bitrate_data = rte_stats_bitrate_create();
+ TEST_ASSERT(bitrate_data != NULL, "rte_stats_bitrate_create failed");
+
+ return TEST_SUCCESS;
+}
+
+/* To test free the resources from bitrate_reg test */
+static int
+test_stats_bitrate_free(void)
+{
+ int ret = 0;
+
+ ret = rte_metrics_deinit();
+ TEST_ASSERT(ret >= 0, "Test Failed: rte_metrics_deinit failed");
+
+ return TEST_SUCCESS;
+}
+
+/* To test bit rate registration */
+static int
+test_stats_bitrate_reg(void)
+{
+ int ret = 0;
+
+ /* Test to register bit rate without metrics init */
+ ret = rte_stats_bitrate_reg(bitrate_data);
+ TEST_ASSERT(ret < 0, "Test Failed: rte_stats_bitrate_reg succeeded "
+ "without metrics init, ret:%d", ret);
+
+ /* Metrics initialization */
+ rte_metrics_init(rte_socket_id());
+ /* Test to register bit rate after metrics init */
+ ret = rte_stats_bitrate_reg(bitrate_data);
+ TEST_ASSERT((ret >= 0), "Test Failed: rte_stats_bitrate_reg %d", ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test the bit rate registration with invalid pointer */
+static int
+test_stats_bitrate_reg_invalidpointer(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_reg(NULL);
+ TEST_ASSERT(ret < 0, "Test Failed: Expected failure < 0 but "
+ "got %d", ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test bit rate calculation with invalid bit rate data pointer */
+static int
+test_stats_bitrate_calc_invalid_bitrate_data(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_calc(NULL, portid);
+ TEST_ASSERT(ret < 0, "Test Failed: rte_stats_bitrate_calc "
+ "ret:%d", ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test the bit rate calculation with invalid portid
+ * (higher than max ports)
+ */
+static int
+test_stats_bitrate_calc_invalid_portid_1(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_calc(bitrate_data, 33);
+ TEST_ASSERT(ret == -EINVAL, "Test Failed: Expected -%d for higher "
+ "portid rte_stats_bitrate_calc ret:%d", EINVAL, ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test the bit rate calculation with invalid portid (lesser than 0) */
+static int
+test_stats_bitrate_calc_invalid_portid_2(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_calc(bitrate_data, -1);
+ TEST_ASSERT(ret == -EINVAL, "Test Failed: Expected -%d for invalid "
+ "portid rte_stats_bitrate_calc ret:%d", EINVAL, ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test the bit rate calculation with non-existing portid */
+static int
+test_stats_bitrate_calc_non_existing_portid(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_calc(bitrate_data, 31);
+ TEST_ASSERT(ret == -EINVAL, "Test Failed: Expected -%d for "
+ "non-existing portid rte_stats_bitrate_calc ret:%d",
+ EINVAL, ret);
+
+ return TEST_SUCCESS;
+}
+
+/* To test the bit rate calculation with valid bit rate data, valid portid */
+static int
+test_stats_bitrate_calc(void)
+{
+ int ret = 0;
+
+ ret = rte_stats_bitrate_calc(bitrate_data, portid);
+ TEST_ASSERT(ret >= 0, "Test Failed: Expected >=0 for valid portid "
+ "rte_stats_bitrate_calc ret:%d", ret);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bit_packet_forward(void)
+{
+ int ret;
+ struct rte_mbuf *pbuf[BIT_NUM_PACKETS] = { };
+ struct rte_mempool *mp;
+ char poolname[] = "mbuf_pool";
+ ret = test_get_mbuf_from_pool(&mp, pbuf, poolname);
+ if (ret < 0) {
+ printf("allocate mbuf pool Failed\n");
+ return TEST_FAILED;
+ }
+ ret = test_packet_forward(pbuf, portid, QUEUE_ID);
+ if (ret < 0)
+ printf("send pkts Failed\n");
+ test_put_mbuf_to_pool(mp, pbuf);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_bit_ring_setup(void)
+{
+ test_ring_setup(&ring, &portid);
+ printf("port in ring setup : %d\n", portid);
+
+ return TEST_SUCCESS;
+}
+
+static void
+test_bit_ring_free(void)
+{
+ test_ring_free(ring);
+ test_vdev_uninit("net_ring_net_ringa");
+ rte_memzone_free(rte_memzone_lookup("RTE_METRICS"));
+}
+
+static struct
+unit_test_suite bitratestats_testsuite = {
+ .suite_name = "BitRate Stats Unit Test Suite",
+ .setup = test_bit_ring_setup,
+ .teardown = test_bit_ring_free,
+ .unit_test_cases = {
+ /* TEST CASE 1: Test to create bit rate data */
+ TEST_CASE(test_stats_bitrate_create),
+
+ /* TEST CASE 2: Test to register bit rate metrics
+ * without metrics init and after metrics init
+ */
+ TEST_CASE(test_stats_bitrate_reg),
+
+ /* TEST CASE 3: Test to register bit rate metrics
+ * with invalid bit rate data
+ */
+ TEST_CASE(test_stats_bitrate_reg_invalidpointer),
+
+ /* TEST CASE 4: Test to calculate bit rate data metrics
+ * with invalid bit rate data
+ */
+ TEST_CASE(test_stats_bitrate_calc_invalid_bitrate_data),
+
+ /* TEST CASE 5: Test to calculate bit rate data metrics
+ * with portid exceeding the max ports
+ */
+ TEST_CASE(test_stats_bitrate_calc_invalid_portid_1),
+
+ /* TEST CASE 6: Test to calculate bit rate data metrics
+ * with portid less than 0
+ */
+ TEST_CASE(test_stats_bitrate_calc_invalid_portid_2),
+
+ /* TEST CASE 7: Test to calculate bit rate data metrics
+ * with non-existing portid
+ */
+ TEST_CASE(test_stats_bitrate_calc_non_existing_portid),
+
+ /* TEST CASE 8: Test to calculate bit rate data metrics
+ * with valid portid, valid bit rate data
+ */
+ TEST_CASE_ST(test_bit_packet_forward, NULL,
+ test_stats_bitrate_calc),
+ /* TEST CASE 9: Test to do the cleanup w.r.t create */
+ TEST_CASE(test_stats_bitrate_free),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_bitratestats(void)
+{
+ return unit_test_suite_runner(&bitratestats_testsuite);
+}
+REGISTER_TEST_COMMAND(bitratestats_autotest, test_bitratestats);
diff --git a/src/spdk/dpdk/app/test/test_bpf.c b/src/spdk/dpdk/app/test/test_bpf.c
new file mode 100644
index 000000000..ee534687a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_bpf.c
@@ -0,0 +1,2783 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <rte_memory.h>
+#include <rte_debug.h>
+#include <rte_hexdump.h>
+#include <rte_random.h>
+#include <rte_byteorder.h>
+#include <rte_errno.h>
+#include <rte_bpf.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+/*
+ * Basic functional tests for librte_bpf.
+ * The main procedure - load eBPF program, execute it and
+ * compare restuls with expected values.
+ */
+
+struct dummy_offset {
+ uint64_t u64;
+ uint32_t u32;
+ uint16_t u16;
+ uint8_t u8;
+};
+
+struct dummy_vect8 {
+ struct dummy_offset in[8];
+ struct dummy_offset out[8];
+};
+
+struct dummy_net {
+ struct rte_ether_hdr eth_hdr;
+ struct rte_vlan_hdr vlan_hdr;
+ struct rte_ipv4_hdr ip_hdr;
+};
+
+#define TEST_FILL_1 0xDEADBEEF
+
+#define TEST_MUL_1 21
+#define TEST_MUL_2 -100
+
+#define TEST_SHIFT_1 15
+#define TEST_SHIFT_2 33
+
+#define TEST_JCC_1 0
+#define TEST_JCC_2 -123
+#define TEST_JCC_3 5678
+#define TEST_JCC_4 TEST_FILL_1
+
+#define TEST_IMM_1 UINT64_MAX
+#define TEST_IMM_2 ((uint64_t)INT64_MIN)
+#define TEST_IMM_3 ((uint64_t)INT64_MAX + INT32_MAX)
+#define TEST_IMM_4 ((uint64_t)UINT32_MAX)
+#define TEST_IMM_5 ((uint64_t)UINT32_MAX + 1)
+
+#define TEST_MEMFROB 0x2a2a2a2a
+
+#define STRING_GEEK 0x6B656567
+#define STRING_WEEK 0x6B656577
+
+#define TEST_NETMASK 0xffffff00
+#define TEST_SUBNET 0xaca80200
+
+uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+
+uint32_t ip_src_addr = (172U << 24) | (168U << 16) | (2 << 8) | 1;
+uint32_t ip_dst_addr = (172U << 24) | (168U << 16) | (2 << 8) | 2;
+
+struct bpf_test {
+ const char *name;
+ size_t arg_sz;
+ struct rte_bpf_prm prm;
+ void (*prepare)(void *);
+ int (*check_result)(uint64_t, const void *);
+ uint32_t allow_fail;
+};
+
+/*
+ * Compare return value and result data with expected ones.
+ * Report a failure if they don't match.
+ */
+static int
+cmp_res(const char *func, uint64_t exp_rc, uint64_t ret_rc,
+ const void *exp_res, const void *ret_res, size_t res_sz)
+{
+ int32_t ret;
+
+ ret = 0;
+ if (exp_rc != ret_rc) {
+ printf("%s@%d: invalid return value, expected: 0x%" PRIx64
+ ",result: 0x%" PRIx64 "\n",
+ func, __LINE__, exp_rc, ret_rc);
+ ret |= -1;
+ }
+
+ if (memcmp(exp_res, ret_res, res_sz) != 0) {
+ printf("%s: invalid value\n", func);
+ rte_memdump(stdout, "expected", exp_res, res_sz);
+ rte_memdump(stdout, "result", ret_res, res_sz);
+ ret |= -1;
+ }
+
+ return ret;
+}
+
+/* store immediate test-cases */
+static const struct ebpf_insn test_store1_prog[] = {
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u8),
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u16),
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u32),
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u64),
+ .imm = TEST_FILL_1,
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_store1_prepare(void *arg)
+{
+ struct dummy_offset *df;
+
+ df = arg;
+ memset(df, 0, sizeof(*df));
+}
+
+static int
+test_store1_check(uint64_t rc, const void *arg)
+{
+ const struct dummy_offset *dft;
+ struct dummy_offset dfe;
+
+ dft = arg;
+
+ memset(&dfe, 0, sizeof(dfe));
+ dfe.u64 = (int32_t)TEST_FILL_1;
+ dfe.u32 = dfe.u64;
+ dfe.u16 = dfe.u64;
+ dfe.u8 = dfe.u64;
+
+ return cmp_res(__func__, 1, rc, &dfe, dft, sizeof(dfe));
+}
+
+/* store register test-cases */
+static const struct ebpf_insn test_store2_prog[] = {
+
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u8),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u16),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+/* load test-cases */
+static const struct ebpf_insn test_load1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u8),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u16),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ /* return sum */
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_4,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_load1_prepare(void *arg)
+{
+ struct dummy_offset *df;
+
+ df = arg;
+
+ memset(df, 0, sizeof(*df));
+ df->u64 = (int32_t)TEST_FILL_1;
+ df->u32 = df->u64;
+ df->u16 = df->u64;
+ df->u8 = df->u64;
+}
+
+static int
+test_load1_check(uint64_t rc, const void *arg)
+{
+ uint64_t v;
+ const struct dummy_offset *dft;
+
+ dft = arg;
+ v = dft->u64;
+ v += dft->u32;
+ v += dft->u16;
+ v += dft->u8;
+
+ return cmp_res(__func__, v, rc, dft, dft, sizeof(*dft));
+}
+
+/* load immediate test-cases */
+static const struct ebpf_insn test_ldimm1_prog[] = {
+
+ {
+ .code = (BPF_LD | BPF_IMM | EBPF_DW),
+ .dst_reg = EBPF_REG_0,
+ .imm = (uint32_t)TEST_IMM_1,
+ },
+ {
+ .imm = TEST_IMM_1 >> 32,
+ },
+ {
+ .code = (BPF_LD | BPF_IMM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .imm = (uint32_t)TEST_IMM_2,
+ },
+ {
+ .imm = TEST_IMM_2 >> 32,
+ },
+ {
+ .code = (BPF_LD | BPF_IMM | EBPF_DW),
+ .dst_reg = EBPF_REG_5,
+ .imm = (uint32_t)TEST_IMM_3,
+ },
+ {
+ .imm = TEST_IMM_3 >> 32,
+ },
+ {
+ .code = (BPF_LD | BPF_IMM | EBPF_DW),
+ .dst_reg = EBPF_REG_7,
+ .imm = (uint32_t)TEST_IMM_4,
+ },
+ {
+ .imm = TEST_IMM_4 >> 32,
+ },
+ {
+ .code = (BPF_LD | BPF_IMM | EBPF_DW),
+ .dst_reg = EBPF_REG_9,
+ .imm = (uint32_t)TEST_IMM_5,
+ },
+ {
+ .imm = TEST_IMM_5 >> 32,
+ },
+ /* return sum */
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_5,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_7,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_9,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static int
+test_ldimm1_check(uint64_t rc, const void *arg)
+{
+ uint64_t v1, v2;
+
+ v1 = TEST_IMM_1;
+ v2 = TEST_IMM_2;
+ v1 += v2;
+ v2 = TEST_IMM_3;
+ v1 += v2;
+ v2 = TEST_IMM_4;
+ v1 += v2;
+ v2 = TEST_IMM_5;
+ v1 += v2;
+
+ return cmp_res(__func__, v1, rc, arg, arg, 0);
+}
+
+
+/* alu mul test-cases */
+static const struct ebpf_insn test_mul1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[2].u32),
+ },
+ {
+ .code = (BPF_ALU | BPF_MUL | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_MUL_1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_MUL | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_MUL_2,
+ },
+ {
+ .code = (BPF_ALU | BPF_MUL | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_MUL | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[0].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[1].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[2].u64),
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_mul1_prepare(void *arg)
+{
+ struct dummy_vect8 *dv;
+ uint64_t v;
+
+ dv = arg;
+
+ v = rte_rand();
+
+ memset(dv, 0, sizeof(*dv));
+ dv->in[0].u32 = v;
+ dv->in[1].u64 = v << 12 | v >> 6;
+ dv->in[2].u32 = -v;
+}
+
+static int
+test_mul1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4;
+ const struct dummy_vect8 *dvt;
+ struct dummy_vect8 dve;
+
+ dvt = arg;
+ memset(&dve, 0, sizeof(dve));
+
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[1].u64;
+ r4 = dvt->in[2].u32;
+
+ r2 = (uint32_t)r2 * TEST_MUL_1;
+ r3 *= TEST_MUL_2;
+ r4 = (uint32_t)(r4 * r2);
+ r4 *= r3;
+
+ dve.out[0].u64 = r2;
+ dve.out[1].u64 = r3;
+ dve.out[2].u64 = r4;
+
+ return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
+}
+
+/* alu shift test-cases */
+static const struct ebpf_insn test_shift1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[2].u32),
+ },
+ {
+ .code = (BPF_ALU | BPF_LSH | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_SHIFT_1,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_ARSH | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_SHIFT_2,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[0].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[1].u64),
+ },
+ {
+ .code = (BPF_ALU | BPF_RSH | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_4,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_LSH | BPF_X),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_4,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[2].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[3].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[2].u32),
+ },
+ {
+ .code = (BPF_ALU | BPF_AND | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = sizeof(uint64_t) * CHAR_BIT - 1,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_ARSH | BPF_X),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_ALU | BPF_AND | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = sizeof(uint32_t) * CHAR_BIT - 1,
+ },
+ {
+ .code = (BPF_ALU | BPF_LSH | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[4].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[5].u64),
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_shift1_prepare(void *arg)
+{
+ struct dummy_vect8 *dv;
+ uint64_t v;
+
+ dv = arg;
+
+ v = rte_rand();
+
+ memset(dv, 0, sizeof(*dv));
+ dv->in[0].u32 = v;
+ dv->in[1].u64 = v << 12 | v >> 6;
+ dv->in[2].u32 = (-v ^ 5);
+}
+
+static int
+test_shift1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4;
+ const struct dummy_vect8 *dvt;
+ struct dummy_vect8 dve;
+
+ dvt = arg;
+ memset(&dve, 0, sizeof(dve));
+
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[1].u64;
+ r4 = dvt->in[2].u32;
+
+ r2 = (uint32_t)r2 << TEST_SHIFT_1;
+ r3 = (int64_t)r3 >> TEST_SHIFT_2;
+
+ dve.out[0].u64 = r2;
+ dve.out[1].u64 = r3;
+
+ r2 = (uint32_t)r2 >> r4;
+ r3 <<= r4;
+
+ dve.out[2].u64 = r2;
+ dve.out[3].u64 = r3;
+
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[1].u64;
+ r4 = dvt->in[2].u32;
+
+ r2 &= sizeof(uint64_t) * CHAR_BIT - 1;
+ r3 = (int64_t)r3 >> r2;
+ r2 &= sizeof(uint32_t) * CHAR_BIT - 1;
+ r4 = (uint32_t)r4 << r2;
+
+ dve.out[4].u64 = r4;
+ dve.out[5].u64 = r3;
+
+ return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
+}
+
+/* jmp test-cases */
+static const struct ebpf_insn test_jump1_prog[] = {
+
+ [0] = {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0,
+ },
+ [1] = {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ [2] = {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u64),
+ },
+ [3] = {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u32),
+ },
+ [4] = {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_5,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ [5] = {
+ .code = (BPF_JMP | BPF_JEQ | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_JCC_1,
+ .off = 8,
+ },
+ [6] = {
+ .code = (BPF_JMP | EBPF_JSLE | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_JCC_2,
+ .off = 9,
+ },
+ [7] = {
+ .code = (BPF_JMP | BPF_JGT | BPF_K),
+ .dst_reg = EBPF_REG_4,
+ .imm = TEST_JCC_3,
+ .off = 10,
+ },
+ [8] = {
+ .code = (BPF_JMP | BPF_JSET | BPF_K),
+ .dst_reg = EBPF_REG_5,
+ .imm = TEST_JCC_4,
+ .off = 11,
+ },
+ [9] = {
+ .code = (BPF_JMP | EBPF_JNE | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_3,
+ .off = 12,
+ },
+ [10] = {
+ .code = (BPF_JMP | EBPF_JSGT | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_4,
+ .off = 13,
+ },
+ [11] = {
+ .code = (BPF_JMP | EBPF_JLE | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_5,
+ .off = 14,
+ },
+ [12] = {
+ .code = (BPF_JMP | BPF_JSET | BPF_X),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_5,
+ .off = 15,
+ },
+ [13] = {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+ [14] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x1,
+ },
+ [15] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -10,
+ },
+ [16] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x2,
+ },
+ [17] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -11,
+ },
+ [18] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x4,
+ },
+ [19] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -12,
+ },
+ [20] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x8,
+ },
+ [21] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -13,
+ },
+ [22] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x10,
+ },
+ [23] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -14,
+ },
+ [24] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x20,
+ },
+ [25] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -15,
+ },
+ [26] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x40,
+ },
+ [27] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -16,
+ },
+ [28] = {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x80,
+ },
+ [29] = {
+ .code = (BPF_JMP | BPF_JA),
+ .off = -17,
+ },
+};
+
+static void
+test_jump1_prepare(void *arg)
+{
+ struct dummy_vect8 *dv;
+ uint64_t v1, v2;
+
+ dv = arg;
+
+ v1 = rte_rand();
+ v2 = rte_rand();
+
+ memset(dv, 0, sizeof(*dv));
+ dv->in[0].u64 = v1;
+ dv->in[1].u64 = v2;
+ dv->in[0].u32 = (v1 << 12) + (v2 >> 6);
+ dv->in[1].u32 = (v2 << 12) - (v1 >> 6);
+}
+
+static int
+test_jump1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4, r5, rv;
+ const struct dummy_vect8 *dvt;
+
+ dvt = arg;
+
+ rv = 0;
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[0].u64;
+ r4 = dvt->in[1].u32;
+ r5 = dvt->in[1].u64;
+
+ if (r2 == TEST_JCC_1)
+ rv |= 0x1;
+ if ((int64_t)r3 <= TEST_JCC_2)
+ rv |= 0x2;
+ if (r4 > TEST_JCC_3)
+ rv |= 0x4;
+ if (r5 & TEST_JCC_4)
+ rv |= 0x8;
+ if (r2 != r3)
+ rv |= 0x10;
+ if ((int64_t)r2 > (int64_t)r4)
+ rv |= 0x20;
+ if (r2 <= r5)
+ rv |= 0x40;
+ if (r3 & r5)
+ rv |= 0x80;
+
+ return cmp_res(__func__, rv, rc, &rv, &rc, sizeof(rv));
+}
+
+/* Jump test case - check ip4_dest in particular subnet */
+static const struct ebpf_insn test_jump2_prog[] = {
+
+ [0] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0xe,
+ },
+ [1] = {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = 12,
+ },
+ [2] = {
+ .code = (BPF_JMP | EBPF_JNE | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .off = 2,
+ .imm = 0x81,
+ },
+ [3] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0x12,
+ },
+ [4] = {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = 16,
+ },
+ [5] = {
+ .code = (EBPF_ALU64 | BPF_AND | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = 0xffff,
+ },
+ [6] = {
+ .code = (BPF_JMP | EBPF_JNE | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .off = 9,
+ .imm = 0x8,
+ },
+ [7] = {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ },
+ [8] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0,
+ },
+ [9] = {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_1,
+ .off = 16,
+ },
+ [10] = {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_NETMASK,
+ },
+ [11] = {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
+ .dst_reg = EBPF_REG_3,
+ .imm = sizeof(uint32_t) * CHAR_BIT,
+ },
+ [12] = {
+ .code = (BPF_ALU | BPF_AND | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ },
+ [13] = {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_SUBNET,
+ },
+ [14] = {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
+ .dst_reg = EBPF_REG_3,
+ .imm = sizeof(uint32_t) * CHAR_BIT,
+ },
+ [15] = {
+ .code = (BPF_JMP | BPF_JEQ | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = 1,
+ },
+ [16] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = -1,
+ },
+ [17] = {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+/* Preparing a vlan packet */
+static void
+test_jump2_prepare(void *arg)
+{
+ struct dummy_net *dn;
+
+ dn = arg;
+ memset(dn, 0, sizeof(*dn));
+
+ /*
+ * Initialize ether header.
+ */
+ rte_ether_addr_copy((struct rte_ether_addr *)dst_mac,
+ &dn->eth_hdr.d_addr);
+ rte_ether_addr_copy((struct rte_ether_addr *)src_mac,
+ &dn->eth_hdr.s_addr);
+ dn->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+
+ /*
+ * Initialize vlan header.
+ */
+ dn->vlan_hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ dn->vlan_hdr.vlan_tci = 32;
+
+ /*
+ * Initialize IP header.
+ */
+ dn->ip_hdr.version_ihl = 0x45; /*IP_VERSION | IP_HDRLEN*/
+ dn->ip_hdr.time_to_live = 64; /* IP_DEFTTL */
+ dn->ip_hdr.next_proto_id = IPPROTO_TCP;
+ dn->ip_hdr.packet_id = rte_cpu_to_be_16(0x463c);
+ dn->ip_hdr.total_length = rte_cpu_to_be_16(60);
+ dn->ip_hdr.src_addr = rte_cpu_to_be_32(ip_src_addr);
+ dn->ip_hdr.dst_addr = rte_cpu_to_be_32(ip_dst_addr);
+}
+
+static int
+test_jump2_check(uint64_t rc, const void *arg)
+{
+ const struct rte_ether_hdr *eth_hdr = arg;
+ const struct rte_ipv4_hdr *ipv4_hdr;
+ const void *next = eth_hdr;
+ uint16_t eth_type;
+ uint64_t v = -1;
+
+ if (eth_hdr->ether_type == htons(0x8100)) {
+ const struct rte_vlan_hdr *vlan_hdr =
+ (const void *)(eth_hdr + 1);
+ eth_type = vlan_hdr->eth_proto;
+ next = vlan_hdr + 1;
+ } else {
+ eth_type = eth_hdr->ether_type;
+ next = eth_hdr + 1;
+ }
+
+ if (eth_type == htons(0x0800)) {
+ ipv4_hdr = next;
+ if ((ipv4_hdr->dst_addr & rte_cpu_to_be_32(TEST_NETMASK)) ==
+ rte_cpu_to_be_32(TEST_SUBNET)) {
+ v = 0;
+ }
+ }
+
+ return cmp_res(__func__, v, rc, arg, arg, sizeof(arg));
+}
+
+/* alu (add, sub, and, or, xor, neg) test-cases */
+static const struct ebpf_insn test_alu1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_5,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ {
+ .code = (BPF_ALU | BPF_AND | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_ALU | BPF_XOR | BPF_K),
+ .dst_reg = EBPF_REG_4,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_5,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[0].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[1].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[2].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_5,
+ .off = offsetof(struct dummy_vect8, out[3].u64),
+ },
+ {
+ .code = (BPF_ALU | BPF_OR | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_XOR | BPF_X),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_4,
+ },
+ {
+ .code = (BPF_ALU | BPF_SUB | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_5,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_AND | BPF_X),
+ .dst_reg = EBPF_REG_5,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[4].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[5].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[6].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_5,
+ .off = offsetof(struct dummy_vect8, out[7].u64),
+ },
+ /* return (-r2 + (-r3)) */
+ {
+ .code = (BPF_ALU | BPF_NEG),
+ .dst_reg = EBPF_REG_2,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_NEG),
+ .dst_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static int
+test_alu1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4, r5, rv;
+ const struct dummy_vect8 *dvt;
+ struct dummy_vect8 dve;
+
+ dvt = arg;
+ memset(&dve, 0, sizeof(dve));
+
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[0].u64;
+ r4 = dvt->in[1].u32;
+ r5 = dvt->in[1].u64;
+
+ r2 = (uint32_t)r2 & TEST_FILL_1;
+ r3 |= (int32_t) TEST_FILL_1;
+ r4 = (uint32_t)r4 ^ TEST_FILL_1;
+ r5 += (int32_t)TEST_FILL_1;
+
+ dve.out[0].u64 = r2;
+ dve.out[1].u64 = r3;
+ dve.out[2].u64 = r4;
+ dve.out[3].u64 = r5;
+
+ r2 = (uint32_t)r2 | (uint32_t)r3;
+ r3 ^= r4;
+ r4 = (uint32_t)r4 - (uint32_t)r5;
+ r5 &= r2;
+
+ dve.out[4].u64 = r2;
+ dve.out[5].u64 = r3;
+ dve.out[6].u64 = r4;
+ dve.out[7].u64 = r5;
+
+ r2 = -(int32_t)r2;
+ rv = (uint32_t)r2;
+ r3 = -r3;
+ rv += r3;
+
+ return cmp_res(__func__, rv, rc, dve.out, dvt->out, sizeof(dve.out));
+}
+
+/* endianness conversions (BE->LE/LE->BE) test-cases */
+static const struct ebpf_insn test_bele1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u16),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u64),
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
+ .dst_reg = EBPF_REG_2,
+ .imm = sizeof(uint16_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
+ .dst_reg = EBPF_REG_3,
+ .imm = sizeof(uint32_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_BE),
+ .dst_reg = EBPF_REG_4,
+ .imm = sizeof(uint64_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[0].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[1].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[2].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u16),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u64),
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
+ .dst_reg = EBPF_REG_2,
+ .imm = sizeof(uint16_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
+ .dst_reg = EBPF_REG_3,
+ .imm = sizeof(uint32_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_ALU | EBPF_END | EBPF_TO_LE),
+ .dst_reg = EBPF_REG_4,
+ .imm = sizeof(uint64_t) * CHAR_BIT,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[3].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[4].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[5].u64),
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_bele1_prepare(void *arg)
+{
+ struct dummy_vect8 *dv;
+
+ dv = arg;
+
+ memset(dv, 0, sizeof(*dv));
+ dv->in[0].u64 = rte_rand();
+ dv->in[0].u32 = dv->in[0].u64;
+ dv->in[0].u16 = dv->in[0].u64;
+}
+
+static int
+test_bele1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4;
+ const struct dummy_vect8 *dvt;
+ struct dummy_vect8 dve;
+
+ dvt = arg;
+ memset(&dve, 0, sizeof(dve));
+
+ r2 = dvt->in[0].u16;
+ r3 = dvt->in[0].u32;
+ r4 = dvt->in[0].u64;
+
+ r2 = rte_cpu_to_be_16(r2);
+ r3 = rte_cpu_to_be_32(r3);
+ r4 = rte_cpu_to_be_64(r4);
+
+ dve.out[0].u64 = r2;
+ dve.out[1].u64 = r3;
+ dve.out[2].u64 = r4;
+
+ r2 = dvt->in[0].u16;
+ r3 = dvt->in[0].u32;
+ r4 = dvt->in[0].u64;
+
+ r2 = rte_cpu_to_le_16(r2);
+ r3 = rte_cpu_to_le_32(r3);
+ r4 = rte_cpu_to_le_64(r4);
+
+ dve.out[3].u64 = r2;
+ dve.out[4].u64 = r3;
+ dve.out[5].u64 = r4;
+
+ return cmp_res(__func__, 1, rc, dve.out, dvt->out, sizeof(dve.out));
+}
+
+/* atomic add test-cases */
+static const struct ebpf_insn test_xadd1_prog[] = {
+
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = -1,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_4,
+ .imm = TEST_FILL_1,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_5,
+ .imm = TEST_MUL_1,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_5,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_5,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_6,
+ .imm = TEST_MUL_2,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_6,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_6,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_7,
+ .imm = TEST_JCC_2,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_7,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_7,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_8,
+ .imm = TEST_JCC_3,
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | BPF_W),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_8,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_STX | EBPF_XADD | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_8,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static int
+test_xadd1_check(uint64_t rc, const void *arg)
+{
+ uint64_t rv;
+ const struct dummy_offset *dft;
+ struct dummy_offset dfe;
+
+ dft = arg;
+ memset(&dfe, 0, sizeof(dfe));
+
+ rv = 1;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = -1;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = (int32_t)TEST_FILL_1;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = TEST_MUL_1;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = TEST_MUL_2;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = TEST_JCC_2;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ rv = TEST_JCC_3;
+ rte_atomic32_add((rte_atomic32_t *)&dfe.u32, rv);
+ rte_atomic64_add((rte_atomic64_t *)&dfe.u64, rv);
+
+ return cmp_res(__func__, 1, rc, &dfe, dft, sizeof(dfe));
+}
+
+/* alu div test-cases */
+static const struct ebpf_insn test_div1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[0].u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[1].u64),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[2].u32),
+ },
+ {
+ .code = (BPF_ALU | BPF_DIV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = TEST_MUL_1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_MOD | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = TEST_MUL_2,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_ALU | BPF_MOD | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_DIV | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ .off = offsetof(struct dummy_vect8, out[0].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_3,
+ .off = offsetof(struct dummy_vect8, out[1].u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_4,
+ .off = offsetof(struct dummy_vect8, out[2].u64),
+ },
+ /* check that we can handle division by zero gracefully. */
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_vect8, in[3].u32),
+ },
+ {
+ .code = (BPF_ALU | BPF_DIV | BPF_X),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_2,
+ },
+ /* return 1 */
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static int
+test_div1_check(uint64_t rc, const void *arg)
+{
+ uint64_t r2, r3, r4;
+ const struct dummy_vect8 *dvt;
+ struct dummy_vect8 dve;
+
+ dvt = arg;
+ memset(&dve, 0, sizeof(dve));
+
+ r2 = dvt->in[0].u32;
+ r3 = dvt->in[1].u64;
+ r4 = dvt->in[2].u32;
+
+ r2 = (uint32_t)r2 / TEST_MUL_1;
+ r3 %= TEST_MUL_2;
+ r2 |= 1;
+ r3 |= 1;
+ r4 = (uint32_t)(r4 % r2);
+ r4 /= r3;
+
+ dve.out[0].u64 = r2;
+ dve.out[1].u64 = r3;
+ dve.out[2].u64 = r4;
+
+ /*
+ * in the test prog we attempted to divide by zero.
+ * so return value should return 0.
+ */
+ return cmp_res(__func__, 0, rc, dve.out, dvt->out, sizeof(dve.out));
+}
+
+/* call test-cases */
+static const struct ebpf_insn test_call1_prog[] = {
+
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_2,
+ .off = -4,
+ },
+ {
+ .code = (BPF_STX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_3,
+ .off = -16,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_10,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_SUB | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 4,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_10,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_SUB | BPF_K),
+ .dst_reg = EBPF_REG_3,
+ .imm = 16,
+ },
+ {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_10,
+ .off = -4,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_10,
+ .off = -16
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+dummy_func1(const void *p, uint32_t *v32, uint64_t *v64)
+{
+ const struct dummy_offset *dv;
+
+ dv = p;
+
+ v32[0] += dv->u16;
+ v64[0] += dv->u8;
+}
+
+static int
+test_call1_check(uint64_t rc, const void *arg)
+{
+ uint32_t v32;
+ uint64_t v64;
+ const struct dummy_offset *dv;
+
+ dv = arg;
+
+ v32 = dv->u32;
+ v64 = dv->u64;
+ dummy_func1(arg, &v32, &v64);
+ v64 += v32;
+
+ if (v64 != rc) {
+ printf("%s@%d: invalid return value "
+ "expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
+ __func__, __LINE__, v64, rc);
+ return -1;
+ }
+ return 0;
+ return cmp_res(__func__, v64, rc, dv, dv, sizeof(*dv));
+}
+
+static const struct rte_bpf_xsym test_call1_xsym[] = {
+ {
+ .name = RTE_STR(dummy_func1),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func1,
+ .nb_args = 3,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(uint32_t),
+ },
+ [2] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(uint64_t),
+ },
+ },
+ },
+ },
+};
+
+static const struct ebpf_insn test_call2_prog[] = {
+
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = -(int32_t)sizeof(struct dummy_offset),
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_10,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = -2 * (int32_t)sizeof(struct dummy_offset),
+ },
+ {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ .off = -(int32_t)(sizeof(struct dummy_offset) -
+ offsetof(struct dummy_offset, u64)),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_10,
+ .off = -(int32_t)(sizeof(struct dummy_offset) -
+ offsetof(struct dummy_offset, u32)),
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_1,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
+ offsetof(struct dummy_offset, u16)),
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_1,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ .off = -(int32_t)(2 * sizeof(struct dummy_offset) -
+ offsetof(struct dummy_offset, u8)),
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+
+};
+
+static void
+dummy_func2(struct dummy_offset *a, struct dummy_offset *b)
+{
+ uint64_t v;
+
+ v = 0;
+ a->u64 = v++;
+ a->u32 = v++;
+ a->u16 = v++;
+ a->u8 = v++;
+ b->u64 = v++;
+ b->u32 = v++;
+ b->u16 = v++;
+ b->u8 = v++;
+}
+
+static int
+test_call2_check(uint64_t rc, const void *arg)
+{
+ uint64_t v;
+ struct dummy_offset a, b;
+
+ RTE_SET_USED(arg);
+
+ dummy_func2(&a, &b);
+ v = a.u64 + a.u32 + b.u16 + b.u8;
+
+ if (v != rc) {
+ printf("%s@%d: invalid return value "
+ "expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
+ __func__, __LINE__, v, rc);
+ return -1;
+ }
+ return 0;
+}
+
+static const struct rte_bpf_xsym test_call2_xsym[] = {
+ {
+ .name = RTE_STR(dummy_func2),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func2,
+ .nb_args = 2,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ },
+ },
+};
+
+static const struct ebpf_insn test_call3_prog[] = {
+
+ {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_0,
+ .off = offsetof(struct dummy_offset, u8),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_H),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_0,
+ .off = offsetof(struct dummy_offset, u16),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_0,
+ .off = offsetof(struct dummy_offset, u32),
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | EBPF_DW),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_0,
+ .off = offsetof(struct dummy_offset, u64),
+ },
+ /* return sum */
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_4,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_3,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static const struct dummy_offset *
+dummy_func3(const struct dummy_vect8 *p)
+{
+ return &p->in[RTE_DIM(p->in) - 1];
+}
+
+static void
+test_call3_prepare(void *arg)
+{
+ struct dummy_vect8 *pv;
+ struct dummy_offset *df;
+
+ pv = arg;
+ df = (struct dummy_offset *)(uintptr_t)dummy_func3(pv);
+
+ memset(pv, 0, sizeof(*pv));
+ df->u64 = (int32_t)TEST_FILL_1;
+ df->u32 = df->u64;
+ df->u16 = df->u64;
+ df->u8 = df->u64;
+}
+
+static int
+test_call3_check(uint64_t rc, const void *arg)
+{
+ uint64_t v;
+ const struct dummy_vect8 *pv;
+ const struct dummy_offset *dft;
+
+ pv = arg;
+ dft = dummy_func3(pv);
+
+ v = dft->u64;
+ v += dft->u32;
+ v += dft->u16;
+ v += dft->u8;
+
+ return cmp_res(__func__, v, rc, pv, pv, sizeof(*pv));
+}
+
+static const struct rte_bpf_xsym test_call3_xsym[] = {
+ {
+ .name = RTE_STR(dummy_func3),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func3,
+ .nb_args = 1,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .ret = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ },
+};
+
+/* Test for stack corruption in multiple function calls */
+static const struct ebpf_insn test_call4_prog[] = {
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_10,
+ .off = -4,
+ .imm = 1,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_10,
+ .off = -3,
+ .imm = 2,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_10,
+ .off = -2,
+ .imm = 3,
+ },
+ {
+ .code = (BPF_ST | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_10,
+ .off = -1,
+ .imm = 4,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ },
+ {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 4,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_SUB | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ .off = -4,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_10,
+ .off = -3,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_3,
+ .src_reg = EBPF_REG_10,
+ .off = -2,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_4,
+ .src_reg = EBPF_REG_10,
+ .off = -1,
+ },
+ {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_XOR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = TEST_MEMFROB,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+/* Gathering the bytes together */
+static uint32_t
+dummy_func4_1(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
+{
+ return (a << 24) | (b << 16) | (c << 8) | (d << 0);
+}
+
+/* Implementation of memfrob */
+static uint32_t
+dummy_func4_0(uint32_t *s, uint8_t n)
+{
+ char *p = (char *) s;
+ while (n-- > 0)
+ *p++ ^= 42;
+ return *s;
+}
+
+
+static int
+test_call4_check(uint64_t rc, const void *arg)
+{
+ uint8_t a[4] = {1, 2, 3, 4};
+ uint32_t s, v = 0;
+
+ RTE_SET_USED(arg);
+
+ s = dummy_func4_0((uint32_t *)a, 4);
+
+ s = dummy_func4_1(a[0], a[1], a[2], a[3]);
+
+ v = s ^ TEST_MEMFROB;
+
+ return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
+}
+
+static const struct rte_bpf_xsym test_call4_xsym[] = {
+ [0] = {
+ .name = RTE_STR(dummy_func4_0),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func4_0,
+ .nb_args = 2,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = 4 * sizeof(uint8_t),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint8_t),
+ },
+ },
+ .ret = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint32_t),
+ },
+ },
+ },
+ [1] = {
+ .name = RTE_STR(dummy_func4_1),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func4_1,
+ .nb_args = 4,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint8_t),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint8_t),
+ },
+ [2] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint8_t),
+ },
+ [3] = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint8_t),
+ },
+ },
+ .ret = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint32_t),
+ },
+ },
+ },
+};
+
+/* string compare test case */
+static const struct ebpf_insn test_call5_prog[] = {
+
+ [0] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = STRING_GEEK,
+ },
+ [1] = {
+ .code = (BPF_STX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_1,
+ .off = -8,
+ },
+ [2] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_6,
+ .imm = 0,
+ },
+ [3] = {
+ .code = (BPF_STX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_6,
+ .off = -4,
+ },
+ [4] = {
+ .code = (BPF_STX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_6,
+ .off = -12,
+ },
+ [5] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = STRING_WEEK,
+ },
+ [6] = {
+ .code = (BPF_STX | BPF_MEM | BPF_W),
+ .dst_reg = EBPF_REG_10,
+ .src_reg = EBPF_REG_1,
+ .off = -16,
+ },
+ [7] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ },
+ [8] = {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = -8,
+ },
+ [9] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ },
+ [10] = {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ [11] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_0,
+ },
+ [12] = {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = -1,
+ },
+ [13] = {
+ .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = 0x20,
+ },
+ [14] = {
+ .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = 0x20,
+ },
+ [15] = {
+ .code = (BPF_JMP | EBPF_JNE | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .off = 11,
+ .imm = 0,
+ },
+ [16] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_10,
+ },
+ [17] = {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = -8,
+ },
+ [18] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_10,
+ },
+ [19] = {
+ .code = (EBPF_ALU64 | BPF_ADD | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = -16,
+ },
+ [20] = {
+ .code = (BPF_JMP | EBPF_CALL),
+ .imm = 0,
+ },
+ [21] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_0,
+ },
+ [22] = {
+ .code = (EBPF_ALU64 | BPF_LSH | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = 0x20,
+ },
+ [23] = {
+ .code = (EBPF_ALU64 | BPF_RSH | BPF_K),
+ .dst_reg = EBPF_REG_1,
+ .imm = 0x20,
+ },
+ [24] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_X),
+ .dst_reg = EBPF_REG_0,
+ .src_reg = EBPF_REG_1,
+ },
+ [25] = {
+ .code = (BPF_JMP | BPF_JEQ | BPF_X),
+ .dst_reg = EBPF_REG_1,
+ .src_reg = EBPF_REG_6,
+ .off = 1,
+ },
+ [26] = {
+ .code = (EBPF_ALU64 | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0,
+ },
+ [27] = {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+/* String comparision impelementation, return 0 if equal else difference */
+static uint32_t
+dummy_func5(const char *s1, const char *s2)
+{
+ while (*s1 && (*s1 == *s2)) {
+ s1++;
+ s2++;
+ }
+ return *(const unsigned char *)s1 - *(const unsigned char *)s2;
+}
+
+static int
+test_call5_check(uint64_t rc, const void *arg)
+{
+ char a[] = "geek";
+ char b[] = "week";
+ uint32_t v;
+
+ RTE_SET_USED(arg);
+
+ v = dummy_func5(a, a);
+ if (v != 0) {
+ v = -1;
+ goto fail;
+ }
+
+ v = dummy_func5(a, b);
+ if (v == 0)
+ goto fail;
+
+ v = 0;
+
+fail:
+
+ return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
+}
+
+static const struct rte_bpf_xsym test_call5_xsym[] = {
+ [0] = {
+ .name = RTE_STR(dummy_func5),
+ .type = RTE_BPF_XTYPE_FUNC,
+ .func = {
+ .val = (void *)dummy_func5,
+ .nb_args = 2,
+ .args = {
+ [0] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(char),
+ },
+ [1] = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(char),
+ },
+ },
+ .ret = {
+ .type = RTE_BPF_ARG_RAW,
+ .size = sizeof(uint32_t),
+ },
+ },
+ },
+};
+
+static const struct bpf_test tests[] = {
+ {
+ .name = "test_store1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_store1_prog,
+ .nb_ins = RTE_DIM(test_store1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_store1_check,
+ },
+ {
+ .name = "test_store2",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_store2_prog,
+ .nb_ins = RTE_DIM(test_store2_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_store1_check,
+ },
+ {
+ .name = "test_load1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_load1_prog,
+ .nb_ins = RTE_DIM(test_load1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_load1_prepare,
+ .check_result = test_load1_check,
+ },
+ {
+ .name = "test_ldimm1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_ldimm1_prog,
+ .nb_ins = RTE_DIM(test_ldimm1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_ldimm1_check,
+ },
+ {
+ .name = "test_mul1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_mul1_prog,
+ .nb_ins = RTE_DIM(test_mul1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_mul1_prepare,
+ .check_result = test_mul1_check,
+ },
+ {
+ .name = "test_shift1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_shift1_prog,
+ .nb_ins = RTE_DIM(test_shift1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_shift1_prepare,
+ .check_result = test_shift1_check,
+ },
+ {
+ .name = "test_jump1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_jump1_prog,
+ .nb_ins = RTE_DIM(test_jump1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_jump1_prepare,
+ .check_result = test_jump1_check,
+ },
+ {
+ .name = "test_jump2",
+ .arg_sz = sizeof(struct dummy_net),
+ .prm = {
+ .ins = test_jump2_prog,
+ .nb_ins = RTE_DIM(test_jump2_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_net),
+ },
+ },
+ .prepare = test_jump2_prepare,
+ .check_result = test_jump2_check,
+ },
+ {
+ .name = "test_alu1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_alu1_prog,
+ .nb_ins = RTE_DIM(test_alu1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_jump1_prepare,
+ .check_result = test_alu1_check,
+ },
+ {
+ .name = "test_bele1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_bele1_prog,
+ .nb_ins = RTE_DIM(test_bele1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_bele1_prepare,
+ .check_result = test_bele1_check,
+ },
+ {
+ .name = "test_xadd1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_xadd1_prog,
+ .nb_ins = RTE_DIM(test_xadd1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_xadd1_check,
+ },
+ {
+ .name = "test_div1",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_div1_prog,
+ .nb_ins = RTE_DIM(test_div1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ },
+ .prepare = test_mul1_prepare,
+ .check_result = test_div1_check,
+ },
+ {
+ .name = "test_call1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_call1_prog,
+ .nb_ins = RTE_DIM(test_call1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ .xsym = test_call1_xsym,
+ .nb_xsym = RTE_DIM(test_call1_xsym),
+ },
+ .prepare = test_load1_prepare,
+ .check_result = test_call1_check,
+ /* for now don't support function calls on 32 bit platform */
+ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
+ },
+ {
+ .name = "test_call2",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_call2_prog,
+ .nb_ins = RTE_DIM(test_call2_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ .xsym = test_call2_xsym,
+ .nb_xsym = RTE_DIM(test_call2_xsym),
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_call2_check,
+ /* for now don't support function calls on 32 bit platform */
+ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
+ },
+ {
+ .name = "test_call3",
+ .arg_sz = sizeof(struct dummy_vect8),
+ .prm = {
+ .ins = test_call3_prog,
+ .nb_ins = RTE_DIM(test_call3_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_vect8),
+ },
+ .xsym = test_call3_xsym,
+ .nb_xsym = RTE_DIM(test_call3_xsym),
+ },
+ .prepare = test_call3_prepare,
+ .check_result = test_call3_check,
+ /* for now don't support function calls on 32 bit platform */
+ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
+ },
+ {
+ .name = "test_call4",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_call4_prog,
+ .nb_ins = RTE_DIM(test_call4_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = 2 * sizeof(struct dummy_offset),
+ },
+ .xsym = test_call4_xsym,
+ .nb_xsym = RTE_DIM(test_call4_xsym),
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_call4_check,
+ /* for now don't support function calls on 32 bit platform */
+ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
+ },
+ {
+ .name = "test_call5",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_call5_prog,
+ .nb_ins = RTE_DIM(test_call5_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ .xsym = test_call5_xsym,
+ .nb_xsym = RTE_DIM(test_call5_xsym),
+ },
+ .prepare = test_store1_prepare,
+ .check_result = test_call5_check,
+ /* for now don't support function calls on 32 bit platform */
+ .allow_fail = (sizeof(uint64_t) != sizeof(uintptr_t)),
+ },
+};
+
+static int
+run_test(const struct bpf_test *tst)
+{
+ int32_t ret, rv;
+ int64_t rc;
+ struct rte_bpf *bpf;
+ struct rte_bpf_jit jit;
+ uint8_t tbuf[tst->arg_sz];
+
+ printf("%s(%s) start\n", __func__, tst->name);
+
+ bpf = rte_bpf_load(&tst->prm);
+ if (bpf == NULL) {
+ printf("%s@%d: failed to load bpf code, error=%d(%s);\n",
+ __func__, __LINE__, rte_errno, strerror(rte_errno));
+ return -1;
+ }
+
+ tst->prepare(tbuf);
+
+ rc = rte_bpf_exec(bpf, tbuf);
+ ret = tst->check_result(rc, tbuf);
+ if (ret != 0) {
+ printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
+ __func__, __LINE__, tst->name, ret, strerror(ret));
+ }
+
+ rte_bpf_get_jit(bpf, &jit);
+ if (jit.func == NULL)
+ return 0;
+
+ tst->prepare(tbuf);
+ rc = jit.func(tbuf);
+ rv = tst->check_result(rc, tbuf);
+ ret |= rv;
+ if (rv != 0) {
+ printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
+ __func__, __LINE__, tst->name, rv, strerror(ret));
+ }
+
+ rte_bpf_destroy(bpf);
+ return ret;
+
+}
+
+static int
+test_bpf(void)
+{
+ int32_t rc, rv;
+ uint32_t i;
+
+ rc = 0;
+ for (i = 0; i != RTE_DIM(tests); i++) {
+ rv = run_test(tests + i);
+ if (tests[i].allow_fail == 0)
+ rc |= rv;
+ }
+
+ return rc;
+}
+
+REGISTER_TEST_COMMAND(bpf_autotest, test_bpf);
diff --git a/src/spdk/dpdk/app/test/test_byteorder.c b/src/spdk/dpdk/app/test/test_byteorder.c
new file mode 100644
index 000000000..03c08d9ab
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_byteorder.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_byteorder.h>
+
+#include "test.h"
+
+static volatile uint16_t u16 = 0x1337;
+static volatile uint32_t u32 = 0xdeadbeefUL;
+static volatile uint64_t u64 = 0xdeadcafebabefaceULL;
+
+/*
+ * Byteorder functions
+ * ===================
+ *
+ * - check that optimized byte swap functions are working for each
+ * size (16, 32, 64 bits)
+ */
+
+static int
+test_byteorder(void)
+{
+ uint16_t res_u16;
+ uint32_t res_u32;
+ uint64_t res_u64;
+
+ res_u16 = rte_bswap16(u16);
+ printf("%"PRIx16" -> %"PRIx16"\n", u16, res_u16);
+ if (res_u16 != 0x3713)
+ return -1;
+
+ res_u32 = rte_bswap32(u32);
+ printf("%"PRIx32" -> %"PRIx32"\n", u32, res_u32);
+ if (res_u32 != 0xefbeaddeUL)
+ return -1;
+
+ res_u64 = rte_bswap64(u64);
+ printf("%"PRIx64" -> %"PRIx64"\n", u64, res_u64);
+ if (res_u64 != 0xcefabebafecaaddeULL)
+ return -1;
+
+ res_u16 = rte_bswap16(0x1337);
+ printf("const %"PRIx16" -> %"PRIx16"\n", 0x1337, res_u16);
+ if (res_u16 != 0x3713)
+ return -1;
+
+ res_u32 = rte_bswap32(0xdeadbeefUL);
+ printf("const %"PRIx32" -> %"PRIx32"\n", (uint32_t) 0xdeadbeef, res_u32);
+ if (res_u32 != 0xefbeaddeUL)
+ return -1;
+
+ res_u64 = rte_bswap64(0xdeadcafebabefaceULL);
+ printf("const %"PRIx64" -> %"PRIx64"\n", (uint64_t) 0xdeadcafebabefaceULL, res_u64);
+ if (res_u64 != 0xcefabebafecaaddeULL)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(byteorder_autotest, test_byteorder);
diff --git a/src/spdk/dpdk/app/test/test_cfgfile.c b/src/spdk/dpdk/app/test/test_cfgfile.c
new file mode 100644
index 000000000..2f596affe
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfile.c
@@ -0,0 +1,334 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Wind River Systems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_cfgfile.h>
+
+#include "test.h"
+#include "resource.h"
+
+
+#define CFG_FILES_ETC "test_cfgfiles/etc"
+
+REGISTER_LINKED_RESOURCE(test_cfgfiles);
+
+static int
+test_cfgfile_setup(void)
+{
+ const struct resource *r;
+ int ret;
+
+ r = resource_find("test_cfgfiles");
+ TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+
+ ret = resource_untar(r);
+ TEST_ASSERT_SUCCESS(ret, "failed to untar %s", r->name);
+
+ return 0;
+}
+
+static int
+test_cfgfile_cleanup(void)
+{
+ const struct resource *r;
+ int ret;
+
+ r = resource_find("test_cfgfiles");
+ TEST_ASSERT_NOT_NULL(r, "missing resource test_cfgfiles");
+
+ ret = resource_rm_by_tar(r);
+ TEST_ASSERT_SUCCESS(ret, "Failed to delete resource %s", r->name);
+
+ return 0;
+}
+
+static int
+_test_cfgfile_sample(struct rte_cfgfile *cfgfile)
+{
+ const char *value;
+ int ret;
+
+ ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
+ TEST_ASSERT(ret == 2, "Unexpected number of sections: %d", ret);
+
+ ret = rte_cfgfile_has_section(cfgfile, "section1");
+ TEST_ASSERT(ret, "section1 section missing");
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "section1");
+ TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret);
+
+ value = rte_cfgfile_get_entry(cfgfile, "section1", "key1");
+ TEST_ASSERT(strcmp("value1", value) == 0,
+ "key1 unexpected value: %s", value);
+
+ ret = rte_cfgfile_has_section(cfgfile, "section2");
+ TEST_ASSERT(ret, "section2 section missing");
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "section2");
+ TEST_ASSERT(ret == 2, "section2 unexpected number of entries: %d", ret);
+
+ value = rte_cfgfile_get_entry(cfgfile, "section2", "key2");
+ TEST_ASSERT(strcmp("value2", value) == 0,
+ "key2 unexpected value: %s", value);
+
+ value = rte_cfgfile_get_entry(cfgfile, "section2", "key3");
+ TEST_ASSERT(strcmp("value3", value) == 0,
+ "key3 unexpected value: %s", value);
+
+ return 0;
+}
+
+static int
+test_cfgfile_sample1(void)
+{
+ struct rte_cfgfile *cfgfile;
+ int ret;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/sample1.ini", 0);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
+
+ ret = _test_cfgfile_sample(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile_sample2(void)
+{
+ struct rte_cfgfile_parameters params;
+ struct rte_cfgfile *cfgfile;
+ int ret;
+
+ /* override comment character */
+ memset(&params, 0, sizeof(params));
+ params.comment_character = '#';
+
+ cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
+ &params);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini");
+
+ ret = _test_cfgfile_sample(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret);
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile_realloc_sections(void)
+{
+ struct rte_cfgfile *cfgfile;
+ int ret;
+ const char *value;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
+
+ ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
+ TEST_ASSERT(ret == 9, "Unexpected number of sections: %d", ret);
+
+ ret = rte_cfgfile_has_section(cfgfile, "section9");
+ TEST_ASSERT(ret, "section9 missing");
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "section3");
+ TEST_ASSERT(ret == 21,
+ "section3 unexpected number of entries: %d", ret);
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "section9");
+ TEST_ASSERT(ret == 8, "section9 unexpected number of entries: %d", ret);
+
+ value = rte_cfgfile_get_entry(cfgfile, "section9", "key8");
+ TEST_ASSERT(strcmp("value8_section9", value) == 0,
+ "key unexpected value: %s", value);
+
+ ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini");
+ TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file");
+ remove("/tmp/cfgfile_save.ini");
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile_invalid_section_header(void)
+{
+ struct rte_cfgfile *cfgfile;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/invalid_section.ini", 0);
+ TEST_ASSERT_NULL(cfgfile, "Expected failured did not occur");
+
+ return 0;
+}
+
+static int
+test_cfgfile_invalid_comment(void)
+{
+ struct rte_cfgfile_parameters params;
+ struct rte_cfgfile *cfgfile;
+
+ /* override comment character with an invalid one */
+ memset(&params, 0, sizeof(params));
+ params.comment_character = '$';
+
+ cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC "/sample2.ini", 0,
+ &params);
+ TEST_ASSERT_NULL(cfgfile, "Expected failured did not occur");
+
+ return 0;
+}
+
+static int
+test_cfgfile_invalid_key_value_pair(void)
+{
+ struct rte_cfgfile *cfgfile;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini", 0);
+ TEST_ASSERT_NULL(cfgfile, "Expected failured did not occur");
+
+ return 0;
+}
+
+static int
+test_cfgfile_empty_key_value_pair(void)
+{
+ struct rte_cfgfile *cfgfile;
+ const char *value;
+ int ret;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty_key_value.ini",
+ CFG_FLAG_EMPTY_VALUES);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse empty_key_value.ini");
+
+ ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
+ TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
+
+ ret = rte_cfgfile_has_section(cfgfile, "section1");
+ TEST_ASSERT(ret, "section1 missing");
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "section1");
+ TEST_ASSERT(ret == 1, "section1 unexpected number of entries: %d", ret);
+
+ value = rte_cfgfile_get_entry(cfgfile, "section1", "key");
+ TEST_ASSERT(strlen(value) == 0, "key unexpected value: %s", value);
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile_missing_section(void)
+{
+ struct rte_cfgfile *cfgfile;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini", 0);
+ TEST_ASSERT_NULL(cfgfile, "Expected failured did not occur");
+
+ return 0;
+}
+
+static int
+test_cfgfile_global_properties(void)
+{
+ struct rte_cfgfile *cfgfile;
+ const char *value;
+ int ret;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/missing_section.ini",
+ CFG_FLAG_GLOBAL_SECTION);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
+
+ ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
+ TEST_ASSERT(ret == 1, "Unexpected number of sections: %d", ret);
+
+ ret = rte_cfgfile_has_section(cfgfile, "GLOBAL");
+ TEST_ASSERT(ret, "global section missing");
+
+ ret = rte_cfgfile_section_num_entries(cfgfile, "GLOBAL");
+ TEST_ASSERT(ret == 1, "GLOBAL unexpected number of entries: %d", ret);
+
+ value = rte_cfgfile_get_entry(cfgfile, "GLOBAL", "key");
+ TEST_ASSERT(strcmp("value", value) == 0,
+ "key unexpected value: %s", value);
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile_empty_file(void)
+{
+ struct rte_cfgfile *cfgfile;
+ int ret;
+
+ cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/empty.ini", 0);
+ TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file");
+
+ ret = rte_cfgfile_num_sections(cfgfile, NULL, 0);
+ TEST_ASSERT(ret == 0, "Unexpected number of sections: %d", ret);
+
+ ret = rte_cfgfile_close(cfgfile);
+ TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile");
+
+ return 0;
+}
+
+static int
+test_cfgfile(void)
+{
+ if (test_cfgfile_setup())
+ return -1;
+
+ if (test_cfgfile_sample1())
+ return -1;
+
+ if (test_cfgfile_sample2())
+ return -1;
+
+ if (test_cfgfile_realloc_sections())
+ return -1;
+
+ if (test_cfgfile_invalid_section_header())
+ return -1;
+
+ if (test_cfgfile_invalid_comment())
+ return -1;
+
+ if (test_cfgfile_invalid_key_value_pair())
+ return -1;
+
+ if (test_cfgfile_empty_key_value_pair())
+ return -1;
+
+ if (test_cfgfile_missing_section())
+ return -1;
+
+ if (test_cfgfile_global_properties())
+ return -1;
+
+ if (test_cfgfile_empty_file())
+ return -1;
+
+ if (test_cfgfile_cleanup())
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(cfgfile_autotest, test_cfgfile);
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty.ini
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty.ini
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty_key_value.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty_key_value.ini
new file mode 100644
index 000000000..53284467b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/empty_key_value.ini
@@ -0,0 +1,3 @@
+[section1]
+; this is section 1
+key=
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/invalid_section.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/invalid_section.ini
new file mode 100644
index 000000000..95d680397
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/invalid_section.ini
@@ -0,0 +1,3 @@
+[invalid
+; this is section 1
+key1=value1
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/line_too_long.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/line_too_long.ini
new file mode 100644
index 000000000..1dce16483
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/line_too_long.ini
@@ -0,0 +1,3 @@
+[section1]
+; this is section 1
+012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/missing_section.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/missing_section.ini
new file mode 100644
index 000000000..c78e131b4
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/missing_section.ini
@@ -0,0 +1,2 @@
+; no section
+key=value
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/realloc_sections.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/realloc_sections.ini
new file mode 100644
index 000000000..e653e40c6
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/realloc_sections.ini
@@ -0,0 +1,128 @@
+[section1]
+key1=value1_section1
+key2=value2_section1
+key3=value3_section1
+key4=value4_section1
+key5=value5_section1
+key6=value6_section1
+key7=value7_section1
+key8=value8_section1
+key9=value9_section1
+key10=value10_section1
+key11=value11_section1
+key12=value12_section1
+key13=value13_section1
+key14=value14_section1
+key15=value15_section1
+key16=value16_section1
+key17=value17_section1
+key18=value18_section1
+key19=value19_section1
+key20=value20_section1
+key21=value21_section1
+
+[section2]
+key1=value1_section2
+key2=value2_section2
+key3=value3_section2
+key4=value4_section2
+key5=value5_section2
+key6=value6_section2
+key7=value7_section2
+key8=value8_section2
+key9=value9_section2
+key10=value10_section2
+key11=value11_section2
+key12=value12_section2
+key13=value13_section2
+key14=value14_section2
+key15=value15_section2
+key16=value16_section2
+key17=value17_section2
+key18=value18_section2
+key19=value19_section2
+key20=value20_section2
+key21=value21_section2
+
+[section3]
+key1=value1_section3
+key2=value2_section3
+key3=value3_section3
+key4=value4_section3
+key5=value5_section3
+key6=value6_section3
+key7=value7_section3
+key8=value8_section3
+key9=value9_section3
+key10=value10_section3
+key11=value11_section3
+key12=value12_section3
+key13=value13_section3
+key14=value14_section3
+key15=value15_section3
+key16=value16_section3
+key17=value17_section3
+key18=value18_section3
+key19=value19_section3
+key20=value20_section3
+key21=value21_section3
+
+[section4]
+key1=value1_section4
+key2=value2_section4
+key3=value3_section4
+key4=value4_section4
+key5=value5_section4
+key6=value6_section4
+key7=value7_section4
+key8=value8_section4
+
+[section5]
+key1=value1_section5
+key2=value2_section5
+key3=value3_section5
+key4=value4_section5
+key5=value5_section5
+key6=value6_section5
+key7=value7_section5
+key8=value8_section5
+
+[section6]
+key1=value1_section6
+key2=value2_section6
+key3=value3_section6
+key4=value4_section6
+key5=value5_section6
+key6=value6_section6
+key7=value7_section6
+key8=value8_section6
+
+[section7]
+key1=value1_section7
+key2=value2_section7
+key3=value3_section7
+key4=value4_section7
+key5=value5_section7
+key6=value6_section7
+key7=value7_section7
+key8=value8_section7
+
+[section8]
+key1=value1_section8
+key2=value2_section8
+key3=value3_section8
+key4=value4_section8
+key5=value5_section8
+key6=value6_section8
+key7=value7_section8
+key8=value8_section8
+
+[section9]
+key1=value1_section9
+key2=value2_section9
+key3=value3_section9
+key4=value4_section9
+key5=value5_section9
+key6=value6_section9
+key7=value7_section9
+key8=value8_section9
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample1.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample1.ini
new file mode 100644
index 000000000..aef91c241
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample1.ini
@@ -0,0 +1,12 @@
+; this is a global comment
+
+[section1]
+; this is section 1
+key1=value1
+
+[section2]
+; this is section 2
+;key1=value1
+key2=value2
+key3=value3 ; this is key3
+ignore-missing-separator
diff --git a/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample2.ini b/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample2.ini
new file mode 100644
index 000000000..21075e976
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cfgfiles/etc/sample2.ini
@@ -0,0 +1,12 @@
+# this is a global comment
+
+[section1]
+# this is section 1
+key1=value1
+
+[section2]
+# this is section 2
+#key1=value1
+key2=value2
+key3=value3 # this is key3
+ignore-missing-separator
diff --git a/src/spdk/dpdk/app/test/test_cmdline.c b/src/spdk/dpdk/app/test/test_cmdline.c
new file mode 100644
index 000000000..115bee966
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline.c
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+
+#include "test.h"
+#include "test_cmdline.h"
+
+static int
+test_cmdline(void)
+{
+ printf("Testind parsing ethernet addresses...\n");
+ if (test_parse_etheraddr_valid() < 0)
+ return -1;
+ if (test_parse_etheraddr_invalid_data() < 0)
+ return -1;
+ if (test_parse_etheraddr_invalid_param() < 0)
+ return -1;
+ printf("Testind parsing port lists...\n");
+ if (test_parse_portlist_valid() < 0)
+ return -1;
+ if (test_parse_portlist_invalid_data() < 0)
+ return -1;
+ if (test_parse_portlist_invalid_param() < 0)
+ return -1;
+ printf("Testind parsing numbers...\n");
+ if (test_parse_num_valid() < 0)
+ return -1;
+ if (test_parse_num_invalid_data() < 0)
+ return -1;
+ if (test_parse_num_invalid_param() < 0)
+ return -1;
+ printf("Testing parsing IP addresses...\n");
+ if (test_parse_ipaddr_valid() < 0)
+ return -1;
+ if (test_parse_ipaddr_invalid_data() < 0)
+ return -1;
+ if (test_parse_ipaddr_invalid_param() < 0)
+ return -1;
+ printf("Testing parsing strings...\n");
+ if (test_parse_string_valid() < 0)
+ return -1;
+ if (test_parse_string_invalid_data() < 0)
+ return -1;
+ if (test_parse_string_invalid_param() < 0)
+ return -1;
+ printf("Testing circular buffer...\n");
+ if (test_cirbuf_char() < 0)
+ return -1;
+ if (test_cirbuf_string() < 0)
+ return -1;
+ if (test_cirbuf_align() < 0)
+ return -1;
+ if (test_cirbuf_invalid_param() < 0)
+ return -1;
+ printf("Testing library functions...\n");
+ if (test_cmdline_lib() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(cmdline_autotest, test_cmdline);
diff --git a/src/spdk/dpdk/app/test/test_cmdline.h b/src/spdk/dpdk/app/test/test_cmdline.h
new file mode 100644
index 000000000..1854caf8f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef TEST_CMDLINE_H_
+#define TEST_CMDLINE_H_
+
+#define CMDLINE_TEST_BUFSIZE 64
+
+/* cmdline_parse_num tests */
+int test_parse_num_valid(void);
+int test_parse_num_invalid_data(void);
+int test_parse_num_invalid_param(void);
+
+/* cmdline_parse_etheraddr tests */
+int test_parse_etheraddr_valid(void);
+int test_parse_etheraddr_invalid_data(void);
+int test_parse_etheraddr_invalid_param(void);
+
+/* cmdline_parse_portlist tests */
+int test_parse_portlist_valid(void);
+int test_parse_portlist_invalid_data(void);
+int test_parse_portlist_invalid_param(void);
+
+/* cmdline_parse_ipaddr tests */
+int test_parse_ipaddr_valid(void);
+int test_parse_ipaddr_invalid_data(void);
+int test_parse_ipaddr_invalid_param(void);
+
+/* cmdline_parse_string tests */
+int test_parse_string_valid(void);
+int test_parse_string_invalid_data(void);
+int test_parse_string_invalid_param(void);
+
+/* cmdline_cirbuf tests */
+int test_cirbuf_invalid_param(void);
+int test_cirbuf_char(void);
+int test_cirbuf_string(void);
+int test_cirbuf_align(void);
+
+/* test the rest of the library */
+int test_cmdline_lib(void);
+
+#endif /* TEST_CMDLINE_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cmdline_cirbuf.c b/src/spdk/dpdk/app/test/test_cmdline_cirbuf.c
new file mode 100644
index 000000000..8ac326cb0
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_cirbuf.c
@@ -0,0 +1,1301 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+
+#include <cmdline_cirbuf.h>
+
+#include "test_cmdline.h"
+
+/* different length strings */
+#define CIRBUF_STR_HEAD " HEAD"
+#define CIRBUF_STR_TAIL "TAIL"
+
+/* miscellaneous tests - they make bullseye happy */
+static int
+test_cirbuf_string_misc(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /*
+ * add strings to head and tail, but read only tail
+ * this results in read operation that does not transcend
+ * from buffer end to buffer beginning (in other words,
+ * strlen <= cb->maxlen - cb->end)
+ */
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* add string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* read string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to get string from tail!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: tail strings do not match!\n");
+ return -1;
+ }
+ /* clear buffers */
+ memset(tmp, 0, sizeof(tmp));
+ memset(buf, 0, sizeof(buf));
+
+
+
+ /*
+ * add a string to buffer when start/end is at end of buffer
+ */
+
+ /*
+ * reinitialize circular buffer with start at the end of cirbuf
+ */
+ if (cirbuf_init(&cb, buf, CMDLINE_TEST_BUFSIZE - 2, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+
+ /* add string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to add string to tail!\n");
+ return -1;
+ }
+ /* read string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to get string from tail!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: tail strings do not match!\n");
+ return -1;
+ }
+ /* clear tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* read string from tail */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to get string from head!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) {
+ printf("Error: headstrings do not match!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test adding and deleting strings */
+static int
+test_cirbuf_string_add_del(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* read string from head */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to get string from head!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) {
+ printf("Error: head strings do not match!\n");
+ return -1;
+ }
+ /* clear tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+ /* read string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to get string from head!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) != 0) {
+ printf("Error: head strings do not match!\n");
+ return -1;
+ }
+ /* delete string from head*/
+ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) {
+ printf("Error: failed to delete string from head!\n");
+ return -1;
+ }
+ /* verify string was deleted */
+ if (cirbuf_del_head_safe(&cb) == 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+ /* clear tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to add string to tail!\n");
+ return -1;
+ }
+ /* get string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to get string from tail!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: tail strings do not match!\n");
+ return -1;
+ }
+ /* clear tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+ /* get string from head */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to get string from tail!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: tail strings do not match!\n");
+ return -1;
+ }
+ /* delete string from tail */
+ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to delete string from tail!\n");
+ return -1;
+ }
+ /* verify string was deleted */
+ if (cirbuf_del_tail_safe(&cb) == 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test adding from head and deleting from tail, and vice versa */
+static int
+test_cirbuf_string_add_del_reverse(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* delete string from tail */
+ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD)) < 0) {
+ printf("Error: failed to delete string from tail!\n");
+ return -1;
+ }
+ /* verify string was deleted */
+ if (cirbuf_del_tail_safe(&cb) == 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+ /* clear tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to add string to tail!\n");
+ return -1;
+ }
+ /* delete string from head */
+ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to delete string from head!\n");
+ return -1;
+ }
+ /* verify string was deleted */
+ if (cirbuf_del_head_safe(&cb) == 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* try to write more than available */
+static int
+test_cirbuf_string_add_boundaries(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ unsigned i;
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* fill the buffer from tail */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_TAIL) + 1; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* try adding a string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ > 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* try adding a string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ > 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* fill the buffer from head */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE - sizeof(CIRBUF_STR_HEAD) + 1; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* try adding a string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ > 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* try adding a string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ > 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* try to read/delete more than written */
+static int
+test_cirbuf_string_get_del_boundaries(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* read more than written (head) */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1)
+ != sizeof(CIRBUF_STR_HEAD)) {
+ printf("Error: unexpected result when reading too much data!\n");
+ return -1;
+ }
+ /* read more than written (tail) */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) + 1)
+ != sizeof(CIRBUF_STR_HEAD)) {
+ printf("Error: unexpected result when reading too much data!\n");
+ return -1;
+ }
+ /* delete more than written (head) */
+ if (cirbuf_del_buf_head(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) {
+ printf("Error: unexpected result when deleting too much data!\n");
+ return -1;
+ }
+ /* delete more than written (tail) */
+ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_HEAD) + 1) == 0) {
+ printf("Error: unexpected result when deleting too much data!\n");
+ return -1;
+ }
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to tail */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL))
+ != (sizeof(CIRBUF_STR_TAIL))) {
+ printf("Error: failed to add string to tail!\n");
+ return -1;
+ }
+ /* read more than written (tail) */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1)
+ != sizeof(CIRBUF_STR_TAIL)) {
+ printf("Error: unexpected result when reading too much data!\n");
+ return -1;
+ }
+ /* read more than written (head) */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_TAIL) + 1)
+ != sizeof(CIRBUF_STR_TAIL)) {
+ printf("Error: unexpected result when reading too much data!\n");
+ return -1;
+ }
+ /* delete more than written (tail) */
+ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) {
+ printf("Error: unexpected result when deleting too much data!\n");
+ return -1;
+ }
+ /* delete more than written (head) */
+ if (cirbuf_del_buf_tail(&cb, sizeof(CIRBUF_STR_TAIL) + 1) == 0) {
+ printf("Error: unexpected result when deleting too much data!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* try to read/delete less than written */
+static int
+test_cirbuf_string_get_del_partial(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+ char tmp2[CMDLINE_TEST_BUFSIZE];
+
+ /* initialize buffers */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+ memset(tmp2, 0, sizeof(tmp));
+
+ strlcpy(tmp2, CIRBUF_STR_HEAD, sizeof(tmp2));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD))
+ != (sizeof(CIRBUF_STR_HEAD))) {
+ printf("Error: failed to add string to head!\n");
+ return -1;
+ }
+ /* read less than written (head) */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1)
+ != sizeof(CIRBUF_STR_HEAD) - 1) {
+ printf("Error: unexpected result when reading from head!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, tmp2, sizeof(CIRBUF_STR_HEAD) - 1) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+ memset(tmp, 0, sizeof(tmp));
+ /* read less than written (tail) */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1)
+ != sizeof(CIRBUF_STR_HEAD) - 1) {
+ printf("Error: unexpected result when reading from tail!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ /*
+ * verify correct deletion
+ */
+
+ /* clear buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+ /* delete less than written (head) */
+ if (cirbuf_del_buf_head(&cb, 1) != 0) {
+ printf("Error: delete from head failed!\n");
+ return -1;
+ }
+ /* read from head */
+ if (cirbuf_get_buf_head(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 1)
+ != sizeof(CIRBUF_STR_HEAD) - 1) {
+ printf("Error: unexpected result when reading from head!\n");
+ return -1;
+ }
+ /* since we deleted from head, first char should be deleted */
+ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 1) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+ /* clear buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+ /* delete less than written (tail) */
+ if (cirbuf_del_buf_tail(&cb, 1) != 0) {
+ printf("Error: delete from tail failed!\n");
+ return -1;
+ }
+ /* read from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp, sizeof(CIRBUF_STR_HEAD) - 2)
+ != sizeof(CIRBUF_STR_HEAD) - 2) {
+ printf("Error: unexpected result when reading from head!\n");
+ return -1;
+ }
+ /* since we deleted from tail, last char should be deleted */
+ if (strncmp(tmp, &tmp2[1], sizeof(CIRBUF_STR_HEAD) - 2) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test cmdline_cirbuf char add/del functions */
+static int
+test_cirbuf_char_add_del(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+
+ /* clear buffer */
+ memset(buf, 0, sizeof(buf));
+ memset(tmp, 0, sizeof(tmp));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /*
+ * try to delete something from cirbuf. since it's empty,
+ * these should fail.
+ */
+ if (cirbuf_del_head_safe(&cb) == 0) {
+ printf("Error: deleting from empty cirbuf head succeeded!\n");
+ return -1;
+ }
+ if (cirbuf_del_tail_safe(&cb) == 0) {
+ printf("Error: deleting from empty cirbuf tail succeeded!\n");
+ return -1;
+ }
+
+ /*
+ * add, verify and delete. these should pass.
+ */
+ if (cirbuf_add_head_safe(&cb,'h') < 0) {
+ printf("Error: adding to cirbuf head failed!\n");
+ return -1;
+ }
+ if (cirbuf_get_head(&cb) != 'h') {
+ printf("Error: wrong head content!\n");
+ return -1;
+ }
+ if (cirbuf_del_head_safe(&cb) < 0) {
+ printf("Error: deleting from cirbuf head failed!\n");
+ return -1;
+ }
+ if (cirbuf_add_tail_safe(&cb,'t') < 0) {
+ printf("Error: adding to cirbuf tail failed!\n");
+ return -1;
+ }
+ if (cirbuf_get_tail(&cb) != 't') {
+ printf("Error: wrong tail content!\n");
+ return -1;
+ }
+ if (cirbuf_del_tail_safe(&cb) < 0) {
+ printf("Error: deleting from cirbuf tail failed!\n");
+ return -1;
+ }
+ /* do the same for unsafe versions. those are void. */
+ cirbuf_add_head(&cb,'h');
+ if (cirbuf_get_head(&cb) != 'h') {
+ printf("Error: wrong head content!\n");
+ return -1;
+ }
+ cirbuf_del_head(&cb);
+
+ /* test if char has been deleted. we can't call cirbuf_get_head
+ * because it's unsafe, but we can call cirbuf_get_buf_head.
+ */
+ if (cirbuf_get_buf_head(&cb, tmp, 1) > 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ cirbuf_add_tail(&cb,'t');
+ if (cirbuf_get_tail(&cb) != 't') {
+ printf("Error: wrong tail content!\n");
+ return -1;
+ }
+ cirbuf_del_tail(&cb);
+
+ /* test if char has been deleted. we can't call cirbuf_get_tail
+ * because it's unsafe, but we can call cirbuf_get_buf_tail.
+ */
+ if (cirbuf_get_buf_tail(&cb, tmp, 1) > 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test filling up buffer with chars */
+static int
+test_cirbuf_char_fill(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ unsigned i;
+
+ /* clear buffer */
+ memset(buf, 0, sizeof(buf));
+
+ /*
+ * initialize circular buffer
+ */
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /*
+ * fill the buffer from head or tail, verify contents, test boundaries
+ * and clear the buffer
+ */
+
+ /* fill the buffer from tail */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+ /* verify that contents of the buffer are what they are supposed to be */
+ for (i = 0; i < sizeof(buf); i++) {
+ if (buf[i] != 't') {
+ printf("Error: wrong content in buffer!\n");
+ return -1;
+ }
+ }
+ /* try to add to a full buffer from tail */
+ if (cirbuf_add_tail_safe(&cb, 't') == 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* try to add to a full buffer from head */
+ if (cirbuf_add_head_safe(&cb, 'h') == 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* delete buffer from tail */
+ for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++)
+ cirbuf_del_tail_safe(&cb);
+ /* try to delete from an empty buffer */
+ if (cirbuf_del_tail_safe(&cb) >= 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ /* fill the buffer from head */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+ /* verify that contents of the buffer are what they are supposed to be */
+ for (i = 0; i < sizeof(buf); i++) {
+ if (buf[i] != 'h') {
+ printf("Error: wrong content in buffer!\n");
+ return -1;
+ }
+ }
+ /* try to add to a full buffer from head */
+ if (cirbuf_add_head_safe(&cb,'h') >= 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* try to add to a full buffer from tail */
+ if (cirbuf_add_tail_safe(&cb, 't') == 0) {
+ printf("Error: buffer should have been full!\n");
+ return -1;
+ }
+ /* delete buffer from head */
+ for(i = 0; i < CMDLINE_TEST_BUFSIZE; i++)
+ cirbuf_del_head_safe(&cb);
+ /* try to delete from an empty buffer */
+ if (cirbuf_del_head_safe(&cb) >= 0) {
+ printf("Error: buffer should have been empty!\n");
+ return -1;
+ }
+
+ /*
+ * fill the buffer from both head and tail, with alternating characters,
+ * verify contents and clear the buffer
+ */
+
+ /* fill half of buffer from tail */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++)
+ cirbuf_add_tail_safe(&cb, (char) (i % 2 ? 't' : 'T'));
+ /* fill other half of the buffer from head */
+ for (i = 0; i < CMDLINE_TEST_BUFSIZE / 2; i++)
+ cirbuf_add_head_safe(&cb, (char) (i % 2 ? 'H' : 'h')); /* added in reverse */
+
+ /* verify that contents of the buffer are what they are supposed to be */
+ for (i = 0; i < sizeof(buf) / 2; i++) {
+ if (buf[i] != (char) (i % 2 ? 't' : 'T')) {
+ printf("Error: wrong content in buffer at %u!\n", i);
+ return -1;
+ }
+ }
+ for (i = sizeof(buf) / 2; i < sizeof(buf); i++) {
+ if (buf[i] != (char) (i % 2 ? 'h' : 'H')) {
+ printf("Error: wrong content in buffer %u!\n", i);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* test left alignment */
+static int
+test_cirbuf_align_left(void)
+{
+#define HALF_OFFSET CMDLINE_TEST_BUFSIZE / 2
+#define SMALL_OFFSET HALF_OFFSET / 2
+/* resulting buffer lengths for each of the test cases */
+#define LEN1 HALF_OFFSET - SMALL_OFFSET - 1
+#define LEN2 HALF_OFFSET + SMALL_OFFSET + 2
+#define LEN3 HALF_OFFSET - SMALL_OFFSET
+#define LEN4 HALF_OFFSET + SMALL_OFFSET - 1
+
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+ unsigned i;
+
+ /*
+ * align left when start < end and start in left half
+ */
+
+ /*
+ * initialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push end into left half */
+ for (i = 0; i < HALF_OFFSET - 1; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* push start into left half < end */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_del_head_safe(&cb);
+
+ /* align */
+ if (cirbuf_align_left(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* verify result */
+ if (cb.start != 0 || cb.len != LEN1 || cb.end != cb.len - 1) {
+ printf("Error: buffer alignment is wrong!\n");
+ return -1;
+ }
+
+ /*
+ * align left when start > end and start in left half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into left half */
+ for (i = 0; i < HALF_OFFSET + 2; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half > start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* align */
+ if (cirbuf_align_left(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* verify result */
+ if (cb.start != 0 || cb.len != LEN2 || cb.end != cb.len - 1) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * align left when start < end and start in right half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into the right half */
+ for (i = 0; i < HALF_OFFSET; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half > start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_del_tail_safe(&cb);
+
+ /* align */
+ if (cirbuf_align_left(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* verify result */
+ if (cb.start != 0 || cb.len != LEN3 || cb.end != cb.len - 1) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * align left when start > end and start in right half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into the right half */
+ for (i = 0; i < HALF_OFFSET - 1; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half < start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* align */
+ if (cirbuf_align_left(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* verify result */
+ if (cb.start != 0 || cb.len != LEN4 ||
+ cb.end != cb.len - 1) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * Verify that alignment doesn't corrupt data
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to tail and head */
+ if (cirbuf_add_buf_head(&cb, CIRBUF_STR_HEAD,
+ sizeof(CIRBUF_STR_HEAD)) < 0 || cirbuf_add_buf_tail(&cb,
+ CIRBUF_STR_TAIL, sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to add strings!\n");
+ return -1;
+ }
+
+ /* align */
+ if (cirbuf_align_left(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* get string from head */
+ if (cirbuf_get_buf_head(&cb, tmp,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to read string from head!\n");
+ return -1;
+ }
+
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ /* reset tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+ /* get string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to read string from head!\n");
+ return -1;
+ }
+
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test right alignment */
+static int
+test_cirbuf_align_right(void)
+{
+#define END_OFFSET CMDLINE_TEST_BUFSIZE - 1
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char tmp[CMDLINE_TEST_BUFSIZE];
+ unsigned i;
+
+
+ /*
+ * align right when start < end and start in left half
+ */
+
+ /*
+ * initialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to initialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push end into left half */
+ for (i = 0; i < HALF_OFFSET - 1; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* push start into left half < end */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_del_head_safe(&cb);
+
+ /* align */
+ cirbuf_align_right(&cb);
+
+ /* verify result */
+ if (cb.start != END_OFFSET || cb.len != LEN1 || cb.end != cb.len - 2) {
+ printf("Error: buffer alignment is wrong!\n");
+ return -1;
+ }
+
+ /*
+ * align right when start > end and start in left half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into left half */
+ for (i = 0; i < HALF_OFFSET + 2; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half > start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* align */
+ cirbuf_align_right(&cb);
+
+ /* verify result */
+ if (cb.start != END_OFFSET || cb.len != LEN2 || cb.end != cb.len - 2) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * align right when start < end and start in right half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into the right half */
+ for (i = 0; i < HALF_OFFSET; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half > start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_del_tail_safe(&cb);
+
+ /* align */
+ cirbuf_align_right(&cb);
+
+ /* verify result */
+ if (cb.end != END_OFFSET || cb.len != LEN3 || cb.start != cb.end - cb.len + 1) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * align right when start > end and start in right half
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* push start into the right half */
+ for (i = 0; i < HALF_OFFSET - 1; i++)
+ cirbuf_add_head_safe(&cb, 'h');
+
+ /* push end into left half < start */
+ for (i = 0; i < SMALL_OFFSET; i++)
+ cirbuf_add_tail_safe(&cb, 't');
+
+ /* align */
+ cirbuf_align_right(&cb);
+
+ /* verify result */
+ if (cb.end != END_OFFSET || cb.len != LEN4 || cb.start != cb.end - cb.len + 1) {
+ printf("Error: buffer alignment is wrong!");
+ return -1;
+ }
+
+ /*
+ * Verify that alignment doesn't corrupt data
+ */
+
+ /*
+ * reinitialize circular buffer
+ */
+ memset(buf, 0, sizeof(buf));
+ if (cirbuf_init(&cb, buf, 0, sizeof(buf)) < 0) {
+ printf("Error: failed to reinitialize circular buffer!\n");
+ return -1;
+ }
+
+ /* add string to tail and head */
+ if (cirbuf_add_buf_tail(&cb, CIRBUF_STR_TAIL,
+ sizeof(CIRBUF_STR_TAIL)) < 0 || cirbuf_add_buf_head(&cb,
+ CIRBUF_STR_HEAD, sizeof(CIRBUF_STR_HEAD)) < 0) {
+ printf("Error: failed to add strings!\n");
+ return -1;
+ }
+
+ /* align */
+ if (cirbuf_align_right(&cb) < 0) {
+ printf("Error: alignment failed!\n");
+ return -1;
+ }
+
+ /* get string from head */
+ if (cirbuf_get_buf_head(&cb, tmp,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to read string from head!\n");
+ return -1;
+ }
+
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ /* reset tmp buffer */
+ memset(tmp, 0, sizeof(tmp));
+
+ /* get string from tail */
+ if (cirbuf_get_buf_tail(&cb, tmp,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) < 0) {
+ printf("Error: failed to read string from head!\n");
+ return -1;
+ }
+ /* verify string */
+ if (strncmp(tmp, CIRBUF_STR_HEAD "\0" CIRBUF_STR_TAIL,
+ sizeof(CIRBUF_STR_HEAD) + sizeof(CIRBUF_STR_TAIL)) != 0) {
+ printf("Error: strings mismatch!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* call functions with invalid parameters */
+int
+test_cirbuf_invalid_param(void)
+{
+ struct cirbuf cb;
+ char buf[CMDLINE_TEST_BUFSIZE];
+
+ /* null cirbuf */
+ if (cirbuf_init(0, buf, 0, sizeof(buf)) == 0)
+ return -1;
+ /* null buffer */
+ if (cirbuf_init(&cb, 0, 0, sizeof(buf)) == 0)
+ return -1;
+ /* null cirbuf */
+ if (cirbuf_add_head_safe(0, 'h') == 0)
+ return -1;
+ if (cirbuf_add_tail_safe(0, 't') == 0)
+ return -1;
+ if (cirbuf_del_head_safe(0) == 0)
+ return -1;
+ if (cirbuf_del_tail_safe(0) == 0)
+ return -1;
+ /* null buffer */
+ if (cirbuf_add_buf_head(&cb, 0, 0) == 0)
+ return -1;
+ if (cirbuf_add_buf_tail(&cb, 0, 0) == 0)
+ return -1;
+ /* null cirbuf */
+ if (cirbuf_add_buf_head(0, buf, 0) == 0)
+ return -1;
+ if (cirbuf_add_buf_tail(0, buf, 0) == 0)
+ return -1;
+ /* null size */
+ if (cirbuf_add_buf_head(&cb, buf, 0) == 0)
+ return -1;
+ if (cirbuf_add_buf_tail(&cb, buf, 0) == 0)
+ return -1;
+ /* null cirbuf */
+ if (cirbuf_del_buf_head(0, 0) == 0)
+ return -1;
+ if (cirbuf_del_buf_tail(0, 0) == 0)
+ return -1;
+ /* null size */
+ if (cirbuf_del_buf_head(&cb, 0) == 0)
+ return -1;
+ if (cirbuf_del_buf_tail(&cb, 0) == 0)
+ return -1;
+ /* null cirbuf */
+ if (cirbuf_get_buf_head(0, 0, 0) == 0)
+ return -1;
+ if (cirbuf_get_buf_tail(0, 0, 0) == 0)
+ return -1;
+ /* null buffer */
+ if (cirbuf_get_buf_head(&cb, 0, 0) == 0)
+ return -1;
+ if (cirbuf_get_buf_tail(&cb, 0, 0) == 0)
+ return -1;
+ /* null size, this is valid but should return 0 */
+ if (cirbuf_get_buf_head(&cb, buf, 0) != 0)
+ return -1;
+ if (cirbuf_get_buf_tail(&cb, buf, 0) != 0)
+ return -1;
+ /* null cirbuf */
+ if (cirbuf_align_left(0) == 0)
+ return -1;
+ if (cirbuf_align_right(0) == 0)
+ return -1;
+
+ return 0;
+}
+
+/* test cmdline_cirbuf char functions */
+int
+test_cirbuf_char(void)
+{
+ int ret;
+
+ ret = test_cirbuf_char_add_del();
+ if (ret < 0)
+ return -1;
+
+ ret = test_cirbuf_char_fill();
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* test cmdline_cirbuf string functions */
+int
+test_cirbuf_string(void)
+{
+ if (test_cirbuf_string_add_del() < 0)
+ return -1;
+
+ if (test_cirbuf_string_add_del_reverse() < 0)
+ return -1;
+
+ if (test_cirbuf_string_add_boundaries() < 0)
+ return -1;
+
+ if (test_cirbuf_string_get_del_boundaries() < 0)
+ return -1;
+
+ if (test_cirbuf_string_get_del_partial() < 0)
+ return -1;
+
+ if (test_cirbuf_string_misc() < 0)
+ return -1;
+
+ return 0;
+}
+
+/* test cmdline_cirbuf align functions */
+int
+test_cirbuf_align(void)
+{
+ if (test_cirbuf_align_left() < 0)
+ return -1;
+ if (test_cirbuf_align_right() < 0)
+ return -1;
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_etheraddr.c b/src/spdk/dpdk/app/test/test_cmdline_etheraddr.c
new file mode 100644
index 000000000..9691c32ba
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_etheraddr.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rte_ether.h>
+#include <rte_string_fns.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_etheraddr.h>
+
+#include "test_cmdline.h"
+
+struct ether_addr_str {
+ const char * str;
+ uint64_t address;
+};
+
+/* valid strings */
+const struct ether_addr_str ether_addr_valid_strs[] = {
+ {"01:23:45:67:89:AB", 0xAB8967452301ULL},
+ {"4567:89AB:CDEF", 0xEFCDAB896745ULL},
+};
+
+/* valid strings with various garbage at the end.
+ * these strings are still valid because parser checks for
+ * end of token, which is either space chars, null char or
+ * a hash sign.
+ */
+const char * ether_addr_garbage_strs[] = {
+ "00:11:22:33:44:55\0garbage",
+ "00:11:22:33:44:55#garbage",
+ "00:11:22:33:44:55 garbage",
+ "00:11:22:33:44:55\tgarbage",
+ "00:11:22:33:44:55\ngarbage",
+ "00:11:22:33:44:55\rgarbage",
+ "00:11:22:33:44:55#",
+ "00:11:22:33:44:55 ",
+ "00:11:22:33:44:55\t",
+ "00:11:22:33:44:55\n",
+ "00:11:22:33:44:55\r",
+};
+#define GARBAGE_ETHERADDR 0x554433221100ULL /* corresponding address */
+
+
+const char * ether_addr_invalid_strs[] = {
+ /* valid chars, invalid syntax */
+ "0123:45:67:89:AB",
+ "01:23:4567:89:AB",
+ "01:23:45:67:89AB",
+ "012:345:678:9AB",
+ "01:23:45:67:89:ABC",
+ "01:23:45:67:89:A",
+ "01:23:45:67:89",
+ "01:23:45:67:89:AB:CD",
+ /* invalid chars, valid syntax */
+ "IN:VA:LI:DC:HA:RS",
+ "INVA:LIDC:HARS",
+ /* misc */
+ "01 23 45 67 89 AB",
+ "01.23.45.67.89.AB",
+ "01,23,45,67,89,AB",
+ "01:23:45\0:67:89:AB",
+ "01:23:45#:67:89:AB",
+ "random invalid text",
+ "random text",
+ "",
+ "\0",
+ " ",
+};
+
+static int
+is_addr_different(const struct rte_ether_addr addr, uint64_t num)
+{
+ int i;
+ for (i = 0; i < RTE_ETHER_ADDR_LEN; i++, num >>= 8)
+ if (addr.addr_bytes[i] != (num & 0xFF)) {
+ return 1;
+ }
+ return 0;
+}
+
+/* test invalid parameters */
+int
+test_parse_etheraddr_invalid_param(void)
+{
+ char buf[CMDLINE_TEST_BUFSIZE];
+ struct rte_ether_addr result;
+ int ret = 0;
+
+ /* try all null */
+ ret = cmdline_parse_etheraddr(NULL, NULL, NULL, 0);
+ if (ret != -1) {
+ printf("Error: parser accepted null parameters!\n");
+ return -1;
+ }
+
+ /* try null buf */
+ ret = cmdline_parse_etheraddr(NULL, NULL, (void*)&result,
+ sizeof(result));
+ if (ret != -1) {
+ printf("Error: parser accepted null string!\n");
+ return -1;
+ }
+
+ /* try null result */
+
+ /* copy string to buffer */
+ strlcpy(buf, ether_addr_valid_strs[0].str, sizeof(buf));
+
+ ret = cmdline_parse_etheraddr(NULL, buf, NULL, 0);
+ if (ret == -1) {
+ printf("Error: parser rejected null result!\n");
+ return -1;
+ }
+
+ /* token is not used in ether_parse anyway so there's no point in
+ * testing it */
+
+ /* test help function */
+ memset(&buf, 0, sizeof(buf));
+
+ /* coverage! */
+ ret = cmdline_get_help_etheraddr(NULL, buf, sizeof(buf));
+ if (ret < 0) {
+ printf("Error: help function failed with valid parameters!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test valid parameters but invalid data */
+int
+test_parse_etheraddr_invalid_data(void)
+{
+ int ret = 0;
+ unsigned i;
+ struct rte_ether_addr result;
+
+ /* test full strings */
+ for (i = 0; i < RTE_DIM(ether_addr_invalid_strs); i++) {
+
+ memset(&result, 0, sizeof(struct rte_ether_addr));
+
+ ret = cmdline_parse_etheraddr(NULL, ether_addr_invalid_strs[i],
+ (void*)&result, sizeof(result));
+ if (ret != -1) {
+ printf("Error: parsing %s succeeded!\n",
+ ether_addr_invalid_strs[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* test valid parameters and data */
+int
+test_parse_etheraddr_valid(void)
+{
+ int ret = 0;
+ unsigned i;
+ struct rte_ether_addr result;
+
+ /* test full strings */
+ for (i = 0; i < RTE_DIM(ether_addr_valid_strs); i++) {
+
+ memset(&result, 0, sizeof(struct rte_ether_addr));
+
+ ret = cmdline_parse_etheraddr(NULL, ether_addr_valid_strs[i].str,
+ (void*)&result, sizeof(result));
+ if (ret < 0) {
+ printf("Error: parsing %s failed!\n",
+ ether_addr_valid_strs[i].str);
+ return -1;
+ }
+ if (is_addr_different(result, ether_addr_valid_strs[i].address)) {
+ printf("Error: parsing %s failed: address mismatch!\n",
+ ether_addr_valid_strs[i].str);
+ return -1;
+ }
+ }
+
+ /* test garbage strings */
+ for (i = 0; i < RTE_DIM(ether_addr_garbage_strs); i++) {
+
+ memset(&result, 0, sizeof(struct rte_ether_addr));
+
+ ret = cmdline_parse_etheraddr(NULL, ether_addr_garbage_strs[i],
+ (void*)&result, sizeof(result));
+ if (ret < 0) {
+ printf("Error: parsing %s failed!\n",
+ ether_addr_garbage_strs[i]);
+ return -1;
+ }
+ if (is_addr_different(result, GARBAGE_ETHERADDR)) {
+ printf("Error: parsing %s failed: address mismatch!\n",
+ ether_addr_garbage_strs[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_ipaddr.c b/src/spdk/dpdk/app/test/test_cmdline_ipaddr.c
new file mode 100644
index 000000000..b3f50d80d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_ipaddr.c
@@ -0,0 +1,671 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <rte_string_fns.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_ipaddr.h>
+
+#include "test_cmdline.h"
+
+#define IP4(a,b,c,d) {((uint32_t)(((a) & 0xff)) | \
+ (((b) & 0xff) << 8) | \
+ (((c) & 0xff) << 16) | \
+ ((d) & 0xff) << 24)}
+
+#define U16_SWAP(x) \
+ (((x & 0xFF) << 8) | ((x & 0xFF00) >> 8))
+
+/* create IPv6 address, swapping bytes where needed */
+#ifndef s6_addr16
+# define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#define IP6(a,b,c,d,e,f,g,h) .ipv6 = \
+ {.s6_addr16 = \
+ {U16_SWAP(a),U16_SWAP(b),U16_SWAP(c),U16_SWAP(d),\
+ U16_SWAP(e),U16_SWAP(f),U16_SWAP(g),U16_SWAP(h)}}
+
+/** these are defined in netinet/in.h but not present in linux headers */
+#ifndef NIPQUAD
+
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+#define NIPQUAD(addr) \
+ (unsigned)((unsigned char *)&addr)[0], \
+ (unsigned)((unsigned char *)&addr)[1], \
+ (unsigned)((unsigned char *)&addr)[2], \
+ (unsigned)((unsigned char *)&addr)[3]
+
+#define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+#define NIP6(addr) \
+ (unsigned)((addr).s6_addr[0]), \
+ (unsigned)((addr).s6_addr[1]), \
+ (unsigned)((addr).s6_addr[2]), \
+ (unsigned)((addr).s6_addr[3]), \
+ (unsigned)((addr).s6_addr[4]), \
+ (unsigned)((addr).s6_addr[5]), \
+ (unsigned)((addr).s6_addr[6]), \
+ (unsigned)((addr).s6_addr[7]), \
+ (unsigned)((addr).s6_addr[8]), \
+ (unsigned)((addr).s6_addr[9]), \
+ (unsigned)((addr).s6_addr[10]), \
+ (unsigned)((addr).s6_addr[11]), \
+ (unsigned)((addr).s6_addr[12]), \
+ (unsigned)((addr).s6_addr[13]), \
+ (unsigned)((addr).s6_addr[14]), \
+ (unsigned)((addr).s6_addr[15])
+
+#endif
+
+
+
+struct ipaddr_str {
+ const char * str;
+ cmdline_ipaddr_t addr;
+ unsigned flags;
+};
+
+const struct ipaddr_str ipaddr_valid_strs[] = {
+ {"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0},
+ CMDLINE_IPADDR_V4},
+ {"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0},
+ CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
+ {"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24},
+ CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
+ {"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24},
+ CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
+ {"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1},
+ CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
+ {"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0},
+ CMDLINE_IPADDR_V6},
+ {"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0},
+ CMDLINE_IPADDR_V6},
+ {"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ {"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ /* RFC5952 requests that only lowercase should be used */
+ {"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6,
+ {IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)},
+ 0},
+ CMDLINE_IPADDR_V6},
+ {"1234::1234/64", {AF_INET6,
+ {IP6(0x1234,0,0,0,0,0,0,0x1234)},
+ 64},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ {"1234::/64", {AF_INET6,
+ {IP6(0x1234,0,0,0,0,0,0,0)},
+ 64},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ {"1:1::1/32", {AF_INET6,
+ {IP6(1,1,0,0,0,0,0,1)},
+ 32},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ {"1:2:3:4::/64", {AF_INET6,
+ {IP6(1,2,3,4,0,0,0,0)},
+ 64},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ {"::ffff:192.168.1.0/64", {AF_INET6,
+ {IP6(0,0,0,0,0,0xFFFF,0xC0A8,0x100)},
+ 64},
+ CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
+ /* RFC5952 requests not using :: to skip one block of zeros*/
+ {"1::2:3:4:5:6:7", {AF_INET6,
+ {IP6(1,0,2,3,4,5,6,7)},
+ 0},
+ CMDLINE_IPADDR_V6},
+};
+
+const char * ipaddr_garbage_addr4_strs[] = {
+ /* IPv4 */
+ "192.168.1.0 garbage",
+ "192.168.1.0\0garbage",
+ "192.168.1.0#garbage",
+ "192.168.1.0\tgarbage",
+ "192.168.1.0\rgarbage",
+ "192.168.1.0\ngarbage",
+};
+#define IPv4_GARBAGE_ADDR IP4(192,168,1,0)
+
+const char * ipaddr_garbage_addr6_strs[] = {
+ /* IPv6 */
+ "1:2:3:4::8 garbage",
+ "1:2:3:4::8#garbage",
+ "1:2:3:4::8\0garbage",
+ "1:2:3:4::8\rgarbage",
+ "1:2:3:4::8\ngarbage",
+ "1:2:3:4::8\tgarbage",
+};
+#define IPv6_GARBAGE_ADDR {IP6(1,2,3,4,0,0,0,8)}
+
+const char * ipaddr_garbage_network4_strs[] = {
+ /* IPv4 */
+ "192.168.1.0/24 garbage",
+ "192.168.1.0/24\0garbage",
+ "192.168.1.0/24#garbage",
+ "192.168.1.0/24\tgarbage",
+ "192.168.1.0/24\rgarbage",
+ "192.168.1.0/24\ngarbage",
+};
+#define IPv4_GARBAGE_PREFIX 24
+
+const char * ipaddr_garbage_network6_strs[] = {
+ /* IPv6 */
+ "1:2:3:4::8/64 garbage",
+ "1:2:3:4::8/64#garbage",
+ "1:2:3:4::8/64\0garbage",
+ "1:2:3:4::8/64\rgarbage",
+ "1:2:3:4::8/64\ngarbage",
+ "1:2:3:4::8/64\tgarbage",
+};
+#define IPv6_GARBAGE_PREFIX 64
+
+
+
+const char * ipaddr_invalid_strs[] = {
+ /** IPv4 **/
+
+ /* invalid numbers */
+ "0.0.0.-1",
+ "0.0.-1.0",
+ "0.-1.0.0",
+ "-1.0.0.0",
+ "0.0.0.-1/24",
+ "256.123.123.123",
+ "255.256.123.123",
+ "255.255.256.123",
+ "255.255.255.256",
+ "256.123.123.123/24",
+ "255.256.123.123/24",
+ "255.255.256.123/24",
+ "255.255.255.256/24",
+ /* invalid network mask */
+ "1.2.3.4/33",
+ "1.2.3.4/33231313",
+ "1.2.3.4/-1",
+ "1.2.3.4/24/33",
+ "1.2.3.4/24/-1",
+ "1.2.3.4/24/",
+ /* wrong format */
+ "1/24"
+ "/24"
+ "123.123.123",
+ "123.123.123.",
+ "123.123.123.123.",
+ "123.123.123..123",
+ "123.123.123.123.123",
+ ".123.123.123",
+ ".123.123.123.123",
+ "123.123.123/24",
+ "123.123.123./24",
+ "123.123.123.123./24",
+ "123.123.123..123/24",
+ "123.123.123.123.123/24",
+ ".123.123.123/24",
+ ".123.123.123.123/24",
+ /* invalid characters */
+ "123.123.123.12F",
+ "123.123.12F.123",
+ "123.12F.123.123",
+ "12F.123.123.123",
+ "12J.123.123.123",
+ "123,123,123,123",
+ "123!123!123!12F",
+ "123.123.123.123/4F",
+
+ /** IPv6 **/
+
+ /* wrong format */
+ "::fffff",
+ "ffff:",
+ "1:2:3:4:5:6:7:192.168.1.1",
+ "1234:192.168.1.1:ffff::",
+ "1:2:3:4:5:6:7:890ab",
+ "1:2:3:4:5:6:7890a:b",
+ "1:2:3:4:5:67890:a:b",
+ "1:2:3:4:56789:0:a:b",
+ "1:2:3:45678:9:0:a:b",
+ "1:2:34567:8:9:0:a:b",
+ "1:23456:7:8:9:0:a:b",
+ "12345:6:7:8:9:0:a:b",
+ "1:::2",
+ "1::::2",
+ "::fffff/64",
+ "1::2::3",
+ "1::2::3/64",
+ ":1:2",
+ ":1:2/64",
+ ":1::2",
+ ":1::2/64",
+ "1::2:3:4:5:6:7:8/64",
+
+ /* invalid network mask */
+ "1:2:3:4:5:6:7:8/129",
+ "1:2:3:4:5:6:7:8/-1",
+
+ /* invalid characters */
+ "a:b:c:d:e:f:g::",
+
+ /** misc **/
+
+ /* too long */
+ "1234:1234:1234:1234:1234:1234:1234:1234:1234:1234:1234"
+ "random invalid text",
+ "",
+ "\0",
+ " ",
+};
+
+static void
+dump_addr(cmdline_ipaddr_t addr)
+{
+ switch (addr.family) {
+ case AF_INET:
+ {
+ printf(NIPQUAD_FMT " prefixlen=%u\n",
+ NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen);
+ break;
+ }
+ case AF_INET6:
+ {
+ printf(NIP6_FMT " prefixlen=%u\n",
+ NIP6(addr.addr.ipv6), addr.prefixlen);
+ break;
+ }
+ default:
+ printf("Can't dump: unknown address family.\n");
+ return;
+ }
+}
+
+
+static int
+is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2)
+{
+ if (addr1.family != addr2.family)
+ return 1;
+
+ if (addr1.prefixlen != addr2.prefixlen)
+ return 1;
+
+ switch (addr1.family) {
+ /* IPv4 */
+ case AF_INET:
+ if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4,
+ sizeof(struct in_addr)) != 0)
+ return 1;
+ break;
+ /* IPv6 */
+ case AF_INET6:
+ {
+ if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6,
+ sizeof(struct in6_addr)) != 0)
+ return 1;
+ break;
+ }
+ /* thing that should not be */
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+static int
+can_parse_addr(unsigned addr_flags, unsigned test_flags)
+{
+ if ((test_flags & addr_flags) == addr_flags) {
+ /* if we are not trying to parse network addresses */
+ if (test_flags < CMDLINE_IPADDR_NETWORK)
+ return 1;
+ /* if this is a network address */
+ else if (addr_flags & CMDLINE_IPADDR_NETWORK)
+ return 1;
+ }
+ return 0;
+}
+
+int
+test_parse_ipaddr_valid(void)
+{
+ cmdline_parse_token_ipaddr_t token;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ cmdline_ipaddr_t result;
+ unsigned i;
+ uint8_t flags;
+ int ret;
+
+ /* cover all cases in help */
+ for (flags = 0x1; flags < 0x8; flags++) {
+ token.ipaddr_data.flags = flags;
+
+ memset(buf, 0, sizeof(buf));
+
+ if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf)) == -1) {
+ printf("Error: help rejected valid parameters!\n");
+ return -1;
+ }
+ }
+
+ /* test valid strings */
+ for (i = 0; i < RTE_DIM(ipaddr_valid_strs); i++) {
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(result));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_valid_strs[i].str, (void*)&result,
+ sizeof(result));
+
+ /* if should have passed, or should have failed */
+ if ((ret < 0) ==
+ (can_parse_addr(ipaddr_valid_strs[i].flags, flags))) {
+ printf("Error: unexpected behavior when parsing %s as %s!\n",
+ ipaddr_valid_strs[i].str, buf);
+ printf("Parsed result: ");
+ dump_addr(result);
+ printf("Expected result: ");
+ dump_addr(ipaddr_valid_strs[i].addr);
+ return -1;
+ }
+ if (ret != -1 &&
+ is_addr_different(result, ipaddr_valid_strs[i].addr)) {
+ printf("Error: result mismatch when parsing %s as %s!\n",
+ ipaddr_valid_strs[i].str, buf);
+ printf("Parsed result: ");
+ dump_addr(result);
+ printf("Expected result: ");
+ dump_addr(ipaddr_valid_strs[i].addr);
+ return -1;
+ }
+ }
+ }
+
+ /* test garbage ipv4 address strings */
+ for (i = 0; i < RTE_DIM(ipaddr_garbage_addr4_strs); i++) {
+
+ struct in_addr tmp = IPv4_GARBAGE_ADDR;
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(result));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_garbage_addr4_strs[i], (void*)&result,
+ sizeof(result));
+
+ /* if should have passed, or should have failed */
+ if ((ret < 0) ==
+ (can_parse_addr(CMDLINE_IPADDR_V4, flags))) {
+ printf("Error: unexpected behavior when parsing %s as %s!\n",
+ ipaddr_garbage_addr4_strs[i], buf);
+ return -1;
+ }
+ if (ret != -1 &&
+ memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
+ printf("Error: result mismatch when parsing %s as %s!\n",
+ ipaddr_garbage_addr4_strs[i], buf);
+ return -1;
+ }
+ }
+ }
+
+ /* test garbage ipv6 address strings */
+ for (i = 0; i < RTE_DIM(ipaddr_garbage_addr6_strs); i++) {
+
+ cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(result));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_garbage_addr6_strs[i], (void*)&result,
+ sizeof(result));
+
+ /* if should have passed, or should have failed */
+ if ((ret < 0) ==
+ (can_parse_addr(CMDLINE_IPADDR_V6, flags))) {
+ printf("Error: unexpected behavior when parsing %s as %s!\n",
+ ipaddr_garbage_addr6_strs[i], buf);
+ return -1;
+ }
+ if (ret != -1 &&
+ memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
+ printf("Error: result mismatch when parsing %s as %s!\n",
+ ipaddr_garbage_addr6_strs[i], buf);
+ return -1;
+ }
+ }
+ }
+
+
+ /* test garbage ipv4 network strings */
+ for (i = 0; i < RTE_DIM(ipaddr_garbage_network4_strs); i++) {
+
+ struct in_addr tmp = IPv4_GARBAGE_ADDR;
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(result));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_garbage_network4_strs[i], (void*)&result,
+ sizeof(result));
+
+ /* if should have passed, or should have failed */
+ if ((ret < 0) ==
+ (can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) {
+ printf("Error: unexpected behavior when parsing %s as %s!\n",
+ ipaddr_garbage_network4_strs[i], buf);
+ return -1;
+ }
+ if (ret != -1 &&
+ memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
+ printf("Error: result mismatch when parsing %s as %s!\n",
+ ipaddr_garbage_network4_strs[i], buf);
+ return -1;
+ }
+ }
+ }
+
+ /* test garbage ipv6 address strings */
+ for (i = 0; i < RTE_DIM(ipaddr_garbage_network6_strs); i++) {
+
+ cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(result));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_garbage_network6_strs[i], (void*)&result,
+ sizeof(result));
+
+ /* if should have passed, or should have failed */
+ if ((ret < 0) ==
+ (can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) {
+ printf("Error: unexpected behavior when parsing %s as %s!\n",
+ ipaddr_garbage_network6_strs[i], buf);
+ return -1;
+ }
+ if (ret != -1 &&
+ memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
+ printf("Error: result mismatch when parsing %s as %s!\n",
+ ipaddr_garbage_network6_strs[i], buf);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+test_parse_ipaddr_invalid_data(void)
+{
+ cmdline_parse_token_ipaddr_t token;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ cmdline_ipaddr_t result;
+ unsigned i;
+ uint8_t flags;
+ int ret;
+
+ memset(&result, 0, sizeof(result));
+
+ /* test invalid strings */
+ for (i = 0; i < RTE_DIM(ipaddr_invalid_strs); i++) {
+
+ /* test each valid string against different flags */
+ for (flags = 1; flags < 0x8; flags++) {
+
+ /* skip bad flag */
+ if (flags == CMDLINE_IPADDR_NETWORK)
+ continue;
+
+ /* clear out everything */
+ memset(buf, 0, sizeof(buf));
+ memset(&token, 0, sizeof(token));
+
+ token.ipaddr_data.flags = flags;
+
+ cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ ipaddr_invalid_strs[i], (void*)&result,
+ sizeof(result));
+
+ if (ret != -1) {
+ printf("Error: parsing %s as %s succeeded!\n",
+ ipaddr_invalid_strs[i], buf);
+ printf("Parsed result: ");
+ dump_addr(result);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+test_parse_ipaddr_invalid_param(void)
+{
+ cmdline_parse_token_ipaddr_t token;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ cmdline_ipaddr_t result;
+
+ snprintf(buf, sizeof(buf), "1.2.3.4");
+ token.ipaddr_data.flags = CMDLINE_IPADDR_V4;
+
+ /* null token */
+ if (cmdline_parse_ipaddr(NULL, buf, (void*)&result,
+ sizeof(result)) != -1) {
+ printf("Error: parser accepted invalid parameters!\n");
+ return -1;
+ }
+ /* null buffer */
+ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ NULL, (void*)&result, sizeof(result)) != -1) {
+ printf("Error: parser accepted invalid parameters!\n");
+ return -1;
+ }
+ /* empty buffer */
+ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ "", (void*)&result, sizeof(result)) != -1) {
+ printf("Error: parser accepted invalid parameters!\n");
+ return -1;
+ }
+ /* null result */
+ if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ buf, NULL, 0) == -1) {
+ printf("Error: parser rejected null result!\n");
+ return -1;
+ }
+
+ /* null token */
+ if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) {
+ printf("Error: help accepted invalid parameters!\n");
+ return -1;
+ }
+ /* null buffer */
+ if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
+ NULL, 0) != -1) {
+ printf("Error: help accepted invalid parameters!\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_lib.c b/src/spdk/dpdk/app/test/test_cmdline_lib.c
new file mode 100644
index 000000000..dec465da5
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_lib.c
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <termios.h>
+#include <ctype.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+
+#include <cmdline_vt100.h>
+#include <cmdline_rdline.h>
+#include <cmdline_parse.h>
+#include <cmdline_socket.h>
+#include <cmdline.h>
+
+#include "test_cmdline.h"
+
+/****************************************************************/
+/* static functions required for some tests */
+static void
+valid_buffer(__rte_unused struct rdline *rdl,
+ __rte_unused const char *buf,
+ __rte_unused unsigned int size)
+{
+}
+
+static int
+complete_buffer(__rte_unused struct rdline *rdl,
+ __rte_unused const char *buf,
+ __rte_unused char *dstbuf,
+ __rte_unused unsigned int dstsize,
+ __rte_unused int *state)
+{
+ return 0;
+}
+
+/****************************************************************/
+
+static int
+test_cmdline_parse_fns(void)
+{
+ struct cmdline cl;
+ int i = 0;
+ char dst[CMDLINE_TEST_BUFSIZE];
+
+ if (cmdline_parse(NULL, "buffer") >= 0)
+ goto error;
+ if (cmdline_parse(&cl, NULL) >= 0)
+ goto error;
+
+ if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0)
+ goto error;
+ if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0)
+ goto error;
+ if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0)
+ goto error;
+ if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0)
+ goto error;
+
+ return 0;
+
+error:
+ printf("Error: function accepted null parameter!\n");
+ return -1;
+}
+
+static int
+test_cmdline_rdline_fns(void)
+{
+ struct rdline rdl;
+ rdline_write_char_t *wc = &cmdline_write_char;
+ rdline_validate_t *v = &valid_buffer;
+ rdline_complete_t *c = &complete_buffer;
+
+ if (rdline_init(NULL, wc, v, c) >= 0)
+ goto error;
+ if (rdline_init(&rdl, NULL, v, c) >= 0)
+ goto error;
+ if (rdline_init(&rdl, wc, NULL, c) >= 0)
+ goto error;
+ if (rdline_init(&rdl, wc, v, NULL) >= 0)
+ goto error;
+ if (rdline_char_in(NULL, 0) >= 0)
+ goto error;
+ if (rdline_get_buffer(NULL) != NULL)
+ goto error;
+ if (rdline_add_history(NULL, "history") >= 0)
+ goto error;
+ if (rdline_add_history(&rdl, NULL) >= 0)
+ goto error;
+ if (rdline_get_history_item(NULL, 0) != NULL)
+ goto error;
+
+ /* void functions */
+ rdline_newline(NULL, "prompt");
+ rdline_newline(&rdl, NULL);
+ rdline_stop(NULL);
+ rdline_quit(NULL);
+ rdline_restart(NULL);
+ rdline_redisplay(NULL);
+ rdline_reset(NULL);
+ rdline_clear_history(NULL);
+
+ return 0;
+
+error:
+ printf("Error: function accepted null parameter!\n");
+ return -1;
+}
+
+static int
+test_cmdline_vt100_fns(void)
+{
+ if (vt100_parser(NULL, 0) >= 0) {
+ printf("Error: function accepted null parameter!\n");
+ return -1;
+ }
+
+ /* void functions */
+ vt100_init(NULL);
+
+ return 0;
+}
+
+static int
+test_cmdline_socket_fns(void)
+{
+ cmdline_parse_ctx_t ctx;
+
+ if (cmdline_stdin_new(NULL, "prompt") != NULL)
+ goto error;
+ if (cmdline_stdin_new(&ctx, NULL) != NULL)
+ goto error;
+ if (cmdline_file_new(NULL, "prompt", "/dev/null") != NULL)
+ goto error;
+ if (cmdline_file_new(&ctx, NULL, "/dev/null") != NULL)
+ goto error;
+ if (cmdline_file_new(&ctx, "prompt", NULL) != NULL)
+ goto error;
+ if (cmdline_file_new(&ctx, "prompt", "-/invalid/~/path") != NULL) {
+ printf("Error: succeeded in opening invalid file for reading!");
+ return -1;
+ }
+ if (cmdline_file_new(&ctx, "prompt", "/dev/null") == NULL) {
+ printf("Error: failed to open /dev/null for reading!");
+ return -1;
+ }
+
+ /* void functions */
+ cmdline_stdin_exit(NULL);
+
+ return 0;
+error:
+ printf("Error: function accepted null parameter!\n");
+ return -1;
+}
+
+static int
+test_cmdline_fns(void)
+{
+ cmdline_parse_ctx_t ctx;
+ struct cmdline cl, *tmp;
+
+ memset(&ctx, 0, sizeof(ctx));
+ tmp = cmdline_new(&ctx, "test", -1, -1);
+ if (tmp == NULL)
+ goto error;
+
+ if (cmdline_new(NULL, "prompt", 0, 0) != NULL)
+ goto error;
+ if (cmdline_new(&ctx, NULL, 0, 0) != NULL)
+ goto error;
+ if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0)
+ goto error;
+ if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0)
+ goto error;
+ if (cmdline_write_char(NULL, 0) >= 0)
+ goto error;
+
+ /* void functions */
+ cmdline_set_prompt(NULL, "prompt");
+ cmdline_free(NULL);
+ cmdline_printf(NULL, "format");
+ /* this should fail as stream handles are invalid */
+ cmdline_printf(tmp, "format");
+ cmdline_interact(NULL);
+ cmdline_quit(NULL);
+
+ /* check if void calls change anything when they should fail */
+ cl = *tmp;
+
+ cmdline_printf(&cl, NULL);
+ if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
+ cmdline_set_prompt(&cl, NULL);
+ if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
+ cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE);
+ if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
+
+ cmdline_free(tmp);
+
+ return 0;
+
+error:
+ printf("Error: function accepted null parameter!\n");
+ return -1;
+mismatch:
+ printf("Error: data changed!\n");
+ return -1;
+}
+
+/* test library functions. the point of these tests is not so much to test
+ * functions' behaviour as it is to make sure there are no segfaults if
+ * they are called with invalid parameters.
+ */
+int
+test_cmdline_lib(void)
+{
+ if (test_cmdline_parse_fns() < 0)
+ return -1;
+ if (test_cmdline_rdline_fns() < 0)
+ return -1;
+ if (test_cmdline_vt100_fns() < 0)
+ return -1;
+ if (test_cmdline_socket_fns() < 0)
+ return -1;
+ if (test_cmdline_fns() < 0)
+ return -1;
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_num.c b/src/spdk/dpdk/app/test/test_cmdline_num.c
new file mode 100644
index 000000000..a6ad95507
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_num.c
@@ -0,0 +1,580 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rte_string_fns.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+
+#include "test_cmdline.h"
+
+struct num_unsigned_str {
+ const char * str;
+ uint64_t result;
+};
+
+struct num_signed_str {
+ const char * str;
+ int64_t result;
+};
+
+const struct num_unsigned_str num_valid_positive_strs[] = {
+ /* decimal positive */
+ {"0", 0 },
+ {"127", INT8_MAX },
+ {"128", INT8_MAX + 1 },
+ {"255", UINT8_MAX },
+ {"256", UINT8_MAX + 1 },
+ {"32767", INT16_MAX },
+ {"32768", INT16_MAX + 1 },
+ {"65535", UINT16_MAX },
+ {"65536", UINT16_MAX + 1 },
+ {"2147483647", INT32_MAX },
+ {"2147483648", INT32_MAX + 1U },
+ {"4294967295", UINT32_MAX },
+ {"4294967296", UINT32_MAX + 1ULL },
+ {"9223372036854775807", INT64_MAX },
+ {"9223372036854775808", INT64_MAX + 1ULL},
+ {"18446744073709551615", UINT64_MAX },
+ /* hexadecimal (no leading zeroes) */
+ {"0x0", 0 },
+ {"0x7F", INT8_MAX },
+ {"0x80", INT8_MAX + 1 },
+ {"0xFF", UINT8_MAX },
+ {"0x100", UINT8_MAX + 1 },
+ {"0x7FFF", INT16_MAX },
+ {"0x8000", INT16_MAX + 1 },
+ {"0xFFFF", UINT16_MAX },
+ {"0x10000", UINT16_MAX + 1 },
+ {"0x7FFFFFFF", INT32_MAX },
+ {"0x80000000", INT32_MAX + 1U },
+ {"0xFFFFFFFF", UINT32_MAX },
+ {"0x100000000", UINT32_MAX + 1ULL },
+ {"0x7FFFFFFFFFFFFFFF", INT64_MAX },
+ {"0x8000000000000000", INT64_MAX + 1ULL},
+ {"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
+ /* hexadecimal (with leading zeroes) */
+ {"0x00", 0 },
+ {"0x7F", INT8_MAX },
+ {"0x80", INT8_MAX + 1 },
+ {"0xFF", UINT8_MAX },
+ {"0x0100", UINT8_MAX + 1 },
+ {"0x7FFF", INT16_MAX },
+ {"0x8000", INT16_MAX + 1 },
+ {"0xFFFF", UINT16_MAX },
+ {"0x00010000", UINT16_MAX + 1 },
+ {"0x7FFFFFFF", INT32_MAX },
+ {"0x80000000", INT32_MAX + 1U },
+ {"0xFFFFFFFF", UINT32_MAX },
+ {"0x0000000100000000", UINT32_MAX + 1ULL },
+ {"0x7FFFFFFFFFFFFFFF", INT64_MAX },
+ {"0x8000000000000000", INT64_MAX + 1ULL},
+ {"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
+ /* check all characters */
+ {"0x1234567890ABCDEF", 0x1234567890ABCDEFULL },
+ {"0x1234567890abcdef", 0x1234567890ABCDEFULL },
+ /* binary (no leading zeroes) */
+ {"0b0", 0 },
+ {"0b1111111", INT8_MAX },
+ {"0b10000000", INT8_MAX + 1 },
+ {"0b11111111", UINT8_MAX },
+ {"0b100000000", UINT8_MAX + 1 },
+ {"0b111111111111111", INT16_MAX },
+ {"0b1000000000000000", INT16_MAX + 1 },
+ {"0b1111111111111111", UINT16_MAX },
+ {"0b10000000000000000", UINT16_MAX + 1 },
+ {"0b1111111111111111111111111111111", INT32_MAX },
+ {"0b10000000000000000000000000000000", INT32_MAX + 1U },
+ {"0b11111111111111111111111111111111", UINT32_MAX },
+ {"0b100000000000000000000000000000000", UINT32_MAX + 1ULL },
+ {"0b111111111111111111111111111111111111111111111111111111111111111",
+ INT64_MAX },
+ {"0b1000000000000000000000000000000000000000000000000000000000000000",
+ INT64_MAX + 1ULL},
+ {"0b1111111111111111111111111111111111111111111111111111111111111111",
+ UINT64_MAX },
+ /* binary (with leading zeroes) */
+ {"0b01111111", INT8_MAX },
+ {"0b0000000100000000", UINT8_MAX + 1 },
+ {"0b0111111111111111", INT16_MAX },
+ {"0b00000000000000010000000000000000", UINT16_MAX + 1 },
+ {"0b01111111111111111111111111111111", INT32_MAX },
+ {"0b0000000000000000000000000000000100000000000000000000000000000000",
+ UINT32_MAX + 1ULL },
+ {"0b0111111111111111111111111111111111111111111111111111111111111111",
+ INT64_MAX },
+ /* octal */
+ {"00", 0 },
+ {"0177", INT8_MAX },
+ {"0200", INT8_MAX + 1 },
+ {"0377", UINT8_MAX },
+ {"0400", UINT8_MAX + 1 },
+ {"077777", INT16_MAX },
+ {"0100000", INT16_MAX + 1 },
+ {"0177777", UINT16_MAX },
+ {"0200000", UINT16_MAX + 1 },
+ {"017777777777", INT32_MAX },
+ {"020000000000", INT32_MAX + 1U },
+ {"037777777777", UINT32_MAX },
+ {"040000000000", UINT32_MAX + 1ULL },
+ {"0777777777777777777777", INT64_MAX },
+ {"01000000000000000000000", INT64_MAX + 1ULL},
+ {"01777777777777777777777", UINT64_MAX },
+ /* check all numbers */
+ {"012345670", 012345670 },
+ {"076543210", 076543210 },
+};
+
+const struct num_signed_str num_valid_negative_strs[] = {
+ /* deciman negative */
+ {"-128", INT8_MIN },
+ {"-129", INT8_MIN - 1 },
+ {"-32768", INT16_MIN },
+ {"-32769", INT16_MIN - 1 },
+ {"-2147483648", INT32_MIN },
+ {"-2147483649", INT32_MIN - 1LL },
+ {"-9223372036854775808", INT64_MIN },
+};
+
+const struct num_unsigned_str num_garbage_positive_strs[] = {
+ /* valid strings with garbage on the end, should still be valid */
+ /* decimal */
+ {"9223372036854775807\0garbage", INT64_MAX },
+ {"9223372036854775807\tgarbage", INT64_MAX },
+ {"9223372036854775807\rgarbage", INT64_MAX },
+ {"9223372036854775807\ngarbage", INT64_MAX },
+ {"9223372036854775807#garbage", INT64_MAX },
+ {"9223372036854775807 garbage", INT64_MAX },
+ /* hex */
+ {"0x7FFFFFFFFFFFFFFF\0garbage", INT64_MAX },
+ {"0x7FFFFFFFFFFFFFFF\tgarbage", INT64_MAX },
+ {"0x7FFFFFFFFFFFFFFF\rgarbage", INT64_MAX },
+ {"0x7FFFFFFFFFFFFFFF\ngarbage", INT64_MAX },
+ {"0x7FFFFFFFFFFFFFFF#garbage", INT64_MAX },
+ {"0x7FFFFFFFFFFFFFFF garbage", INT64_MAX },
+ /* binary */
+ {"0b1111111111111111111111111111111\0garbage", INT32_MAX },
+ {"0b1111111111111111111111111111111\rgarbage", INT32_MAX },
+ {"0b1111111111111111111111111111111\tgarbage", INT32_MAX },
+ {"0b1111111111111111111111111111111\ngarbage", INT32_MAX },
+ {"0b1111111111111111111111111111111#garbage", INT32_MAX },
+ {"0b1111111111111111111111111111111 garbage", INT32_MAX },
+ /* octal */
+ {"01777777777777777777777\0garbage", UINT64_MAX },
+ {"01777777777777777777777\rgarbage", UINT64_MAX },
+ {"01777777777777777777777\tgarbage", UINT64_MAX },
+ {"01777777777777777777777\ngarbage", UINT64_MAX },
+ {"01777777777777777777777#garbage", UINT64_MAX },
+ {"01777777777777777777777 garbage", UINT64_MAX },
+};
+
+const struct num_signed_str num_garbage_negative_strs[] = {
+ /* valid strings with garbage on the end, should still be valid */
+ {"-9223372036854775808\0garbage", INT64_MIN },
+ {"-9223372036854775808\rgarbage", INT64_MIN },
+ {"-9223372036854775808\tgarbage", INT64_MIN },
+ {"-9223372036854775808\ngarbage", INT64_MIN },
+ {"-9223372036854775808#garbage", INT64_MIN },
+ {"-9223372036854775808 garbage", INT64_MIN },
+};
+
+const char * num_invalid_strs[] = {
+ "18446744073709551616", /* out of range unsigned */
+ "-9223372036854775809", /* out of range negative signed */
+ "0x10000000000000000", /* out of range hex */
+ /* out of range binary */
+ "0b10000000000000000000000000000000000000000000000000000000000000000",
+ "020000000000000000000000", /* out of range octal */
+ /* wrong chars */
+ "0123456239",
+ "0x1234580AGE",
+ "0b0111010101g001",
+ "0b01110101017001",
+ /* false negative numbers */
+ "-12345F623",
+ "-0x1234580A",
+ "-0b0111010101",
+ /* too long (128+ chars) */
+ "0b1111000011110000111100001111000011110000111100001111000011110000"
+ "1111000011110000111100001111000011110000111100001111000011110000",
+ "1E3",
+ "0A",
+ "-B",
+ "+4",
+ "1.23G",
+ "",
+ " ",
+ "#",
+ "\r",
+ "\t",
+ "\n",
+ "\0",
+};
+
+static int
+can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
+{
+ switch (type) {
+ case UINT8:
+ if (expected_result > UINT8_MAX)
+ return 0;
+ break;
+ case UINT16:
+ if (expected_result > UINT16_MAX)
+ return 0;
+ break;
+ case UINT32:
+ if (expected_result > UINT32_MAX)
+ return 0;
+ break;
+ case INT8:
+ if (expected_result > INT8_MAX)
+ return 0;
+ break;
+ case INT16:
+ if (expected_result > INT16_MAX)
+ return 0;
+ break;
+ case INT32:
+ if (expected_result > INT32_MAX)
+ return 0;
+ break;
+ case INT64:
+ if (expected_result > INT64_MAX)
+ return 0;
+ break;
+ default:
+ return 1;
+ }
+ return 1;
+}
+
+static int
+can_parse_signed(int64_t expected_result, enum cmdline_numtype type)
+{
+ switch (type) {
+ case UINT8:
+ if (expected_result > UINT8_MAX || expected_result < 0)
+ return 0;
+ break;
+ case UINT16:
+ if (expected_result > UINT16_MAX || expected_result < 0)
+ return 0;
+ break;
+ case UINT32:
+ if (expected_result > UINT32_MAX || expected_result < 0)
+ return 0;
+ break;
+ case UINT64:
+ if (expected_result < 0)
+ return 0;
+ break;
+ case INT8:
+ if (expected_result > INT8_MAX || expected_result < INT8_MIN)
+ return 0;
+ break;
+ case INT16:
+ if (expected_result > INT16_MAX || expected_result < INT16_MIN)
+ return 0;
+ break;
+ case INT32:
+ if (expected_result > INT32_MAX || expected_result < INT32_MIN)
+ return 0;
+ break;
+ default:
+ return 1;
+ }
+ return 1;
+}
+
+/* test invalid parameters */
+int
+test_parse_num_invalid_param(void)
+{
+ char buf[CMDLINE_TEST_BUFSIZE];
+ uint32_t result;
+ cmdline_parse_token_num_t token;
+ int ret = 0;
+
+ /* set up a token */
+ token.num_data.type = UINT32;
+
+ /* copy string to buffer */
+ strlcpy(buf, num_valid_positive_strs[0].str, sizeof(buf));
+
+ /* try all null */
+ ret = cmdline_parse_num(NULL, NULL, NULL, 0);
+ if (ret != -1) {
+ printf("Error: parser accepted null parameters!\n");
+ return -1;
+ }
+
+ /* try null token */
+ ret = cmdline_parse_num(NULL, buf, (void*)&result, sizeof(result));
+ if (ret != -1) {
+ printf("Error: parser accepted null token!\n");
+ return -1;
+ }
+
+ /* try null buf */
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL,
+ (void*)&result, sizeof(result));
+ if (ret != -1) {
+ printf("Error: parser accepted null string!\n");
+ return -1;
+ }
+
+ /* try null result */
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf,
+ NULL, 0);
+ if (ret == -1) {
+ printf("Error: parser rejected null result!\n");
+ return -1;
+ }
+
+ /* test help function */
+ memset(&buf, 0, sizeof(buf));
+
+ /* try all null */
+ ret = cmdline_get_help_num(NULL, NULL, 0);
+ if (ret != -1) {
+ printf("Error: help function accepted null parameters!\n");
+ return -1;
+ }
+
+ /* try null token */
+ ret = cmdline_get_help_num(NULL, buf, sizeof(buf));
+ if (ret != -1) {
+ printf("Error: help function accepted null token!\n");
+ return -1;
+ }
+
+ /* coverage! */
+ ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf));
+ if (ret < 0) {
+ printf("Error: help function failed with valid parameters!\n");
+ return -1;
+ }
+
+ return 0;
+}
+/* test valid parameters but invalid data */
+int
+test_parse_num_invalid_data(void)
+{
+ enum cmdline_numtype type;
+ int ret = 0;
+ unsigned i;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ uint64_t result; /* pick largest buffer */
+ cmdline_parse_token_num_t token;
+
+ /* cycle through all possible parsed types */
+ for (type = UINT8; type <= INT64; type++) {
+ token.num_data.type = type;
+
+ /* test full strings */
+ for (i = 0; i < RTE_DIM(num_invalid_strs); i++) {
+
+ memset(&result, 0, sizeof(uint64_t));
+ memset(&buf, 0, sizeof(buf));
+
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
+ num_invalid_strs[i], (void*)&result, sizeof(result));
+ if (ret != -1) {
+ /* get some info about what we are trying to parse */
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ printf("Error: parsing %s as %s succeeded!\n",
+ num_invalid_strs[i], buf);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* test valid parameters and data */
+int
+test_parse_num_valid(void)
+{
+ int ret = 0;
+ enum cmdline_numtype type;
+ unsigned i;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ uint64_t result;
+ cmdline_parse_token_num_t token;
+
+ /** valid strings **/
+
+ /* cycle through all possible parsed types */
+ for (type = UINT8; type <= INT64; type++) {
+ token.num_data.type = type;
+
+ /* test positive strings */
+ for (i = 0; i < RTE_DIM(num_valid_positive_strs); i++) {
+ result = 0;
+ memset(&buf, 0, sizeof(buf));
+
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
+ num_valid_positive_strs[i].str,
+ (void*)&result, sizeof(result));
+
+ /* if it should have passed but didn't, or if it should have failed but didn't */
+ if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) {
+ printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
+ num_valid_positive_strs[i].str, buf);
+ return -1;
+ }
+ /* check if result matches what it should have matched
+ * since unsigned numbers don't care about number of bits, we can just convert
+ * everything to uint64_t without any worries. */
+ if (ret > 0 && num_valid_positive_strs[i].result != result) {
+ printf("Error: parsing %s as %s failed: result mismatch!\n",
+ num_valid_positive_strs[i].str, buf);
+ return -1;
+ }
+ }
+
+ /* test negative strings */
+ for (i = 0; i < RTE_DIM(num_valid_negative_strs); i++) {
+ result = 0;
+ memset(&buf, 0, sizeof(buf));
+
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
+ num_valid_negative_strs[i].str,
+ (void*)&result, sizeof(result));
+
+ /* if it should have passed but didn't, or if it should have failed but didn't */
+ if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) {
+ printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
+ num_valid_negative_strs[i].str, buf);
+ return -1;
+ }
+ /* check if result matches what it should have matched
+ * the result is signed in this case, so we have to account for that */
+ if (ret > 0) {
+ /* detect negative */
+ switch (type) {
+ case INT8:
+ result = (int8_t) result;
+ break;
+ case INT16:
+ result = (int16_t) result;
+ break;
+ case INT32:
+ result = (int32_t) result;
+ break;
+ default:
+ break;
+ }
+ if (num_valid_negative_strs[i].result == (int64_t) result)
+ continue;
+ printf("Error: parsing %s as %s failed: result mismatch!\n",
+ num_valid_negative_strs[i].str, buf);
+ return -1;
+ }
+ }
+ }
+
+ /** garbage strings **/
+
+ /* cycle through all possible parsed types */
+ for (type = UINT8; type <= INT64; type++) {
+ token.num_data.type = type;
+
+ /* test positive garbage strings */
+ for (i = 0; i < RTE_DIM(num_garbage_positive_strs); i++) {
+ result = 0;
+ memset(&buf, 0, sizeof(buf));
+
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
+ num_garbage_positive_strs[i].str,
+ (void*)&result, sizeof(result));
+
+ /* if it should have passed but didn't, or if it should have failed but didn't */
+ if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) {
+ printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
+ num_garbage_positive_strs[i].str, buf);
+ return -1;
+ }
+ /* check if result matches what it should have matched
+ * since unsigned numbers don't care about number of bits, we can just convert
+ * everything to uint64_t without any worries. */
+ if (ret > 0 && num_garbage_positive_strs[i].result != result) {
+ printf("Error: parsing %s as %s failed: result mismatch!\n",
+ num_garbage_positive_strs[i].str, buf);
+ return -1;
+ }
+ }
+
+ /* test negative strings */
+ for (i = 0; i < RTE_DIM(num_garbage_negative_strs); i++) {
+ result = 0;
+ memset(&buf, 0, sizeof(buf));
+
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token,
+ num_garbage_negative_strs[i].str,
+ (void*)&result, sizeof(result));
+
+ /* if it should have passed but didn't, or if it should have failed but didn't */
+ if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) {
+ printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
+ num_garbage_negative_strs[i].str, buf);
+ return -1;
+ }
+ /* check if result matches what it should have matched
+ * the result is signed in this case, so we have to account for that */
+ if (ret > 0) {
+ /* detect negative */
+ switch (type) {
+ case INT8:
+ if (result & (INT8_MAX + 1))
+ result |= 0xFFFFFFFFFFFFFF00ULL;
+ break;
+ case INT16:
+ if (result & (INT16_MAX + 1))
+ result |= 0xFFFFFFFFFFFF0000ULL;
+ break;
+ case INT32:
+ if (result & (INT32_MAX + 1ULL))
+ result |= 0xFFFFFFFF00000000ULL;
+ break;
+ default:
+ break;
+ }
+ if (num_garbage_negative_strs[i].result == (int64_t) result)
+ continue;
+ printf("Error: parsing %s as %s failed: result mismatch!\n",
+ num_garbage_negative_strs[i].str, buf);
+ return -1;
+ }
+ }
+ }
+
+ memset(&buf, 0, sizeof(buf));
+
+ /* coverage! */
+ cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
+ buf, sizeof(buf));
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_portlist.c b/src/spdk/dpdk/app/test/test_cmdline_portlist.c
new file mode 100644
index 000000000..fd354214a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_portlist.c
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_portlist.h>
+
+#include "test_cmdline.h"
+
+struct portlist_str {
+ const char * str;
+ uint32_t portmap;
+};
+
+/* valid strings */
+const struct portlist_str portlist_valid_strs[] = {
+ {"0", 0x1U },
+ {"0-10", 0x7FFU},
+ {"10-20", 0x1FFC00U},
+ {"all", UINT32_MAX},
+ {"0,1,2,3", 0xFU},
+ {"0,1-5", 0x3FU},
+ {"0,0,0", 0x1U},
+ {"31,0-10,15", 0x800087FFU},
+ {"0000", 0x1U},
+ {"00,01,02,03", 0xFU},
+ {"000,001,002,003", 0xFU},
+};
+
+/* valid strings but with garbage at the end.
+ * these strings should still be valid because parser checks
+ * for end of token, which is either a space/tab, a newline/return,
+ * or a hash sign.
+ */
+
+const char * portlist_garbage_strs[] = {
+ "0-31 garbage",
+ "0-31#garbage",
+ "0-31\0garbage",
+ "0-31\ngarbage",
+ "0-31\rgarbage",
+ "0-31\tgarbage",
+ "0,1,2,3-31 garbage",
+ "0,1,2,3-31#garbage",
+ "0,1,2,3-31\0garbage",
+ "0,1,2,3-31\ngarbage",
+ "0,1,2,3-31\rgarbage",
+ "0,1,2,3-31\tgarbage",
+ "all garbage",
+ "all#garbage",
+ "all\0garbage",
+ "all\ngarbage",
+ "all\rgarbage",
+ "all\tgarbage",
+};
+
+/* invalid strings */
+const char * portlist_invalid_strs[] = {
+ /* valid syntax, invalid chars */
+ "A-B",
+ "0-S",
+ "1,2,3,4,Q",
+ "A-4,3-15",
+ "0-31invalid",
+ /* valid chars, invalid syntax */
+ "1, 2",
+ "1- 4",
+ ",2",
+ ",2 ",
+ "-1, 4",
+ "5-1",
+ "2-",
+ /* misc */
+ "-"
+ "a",
+ "A",
+ ",",
+ "#",
+ " ",
+ "\0",
+ "",
+ /* too long */
+ "0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,"
+ "0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2",
+};
+
+/* test invalid parameters */
+int
+test_parse_portlist_invalid_param(void)
+{
+ cmdline_portlist_t result;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ int ret;
+
+ memset(&buf, 0, sizeof(buf));
+ memset(&result, 0, sizeof(cmdline_portlist_t));
+
+ /* try all null */
+ ret = cmdline_parse_portlist(NULL, NULL, NULL, 0);
+ if (ret != -1) {
+ printf("Error: parser accepted null parameters!\n");
+ return -1;
+ }
+
+ /* try null buf */
+ ret = cmdline_parse_portlist(NULL, NULL, (void*)&result,
+ sizeof(result));
+ if (ret != -1) {
+ printf("Error: parser accepted null string!\n");
+ return -1;
+ }
+
+ /* try null result */
+ ret = cmdline_parse_portlist(NULL, portlist_valid_strs[0].str, NULL, 0);
+ if (ret == -1) {
+ printf("Error: parser rejected null result!\n");
+ return -1;
+ }
+
+ /* token is not used in ether_parse anyway so there's no point in
+ * testing it */
+
+ /* test help function */
+
+ /* coverage! */
+ ret = cmdline_get_help_portlist(NULL, buf, sizeof(buf));
+ if (ret < 0) {
+ printf("Error: help function failed with valid parameters!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test valid parameters but invalid data */
+int
+test_parse_portlist_invalid_data(void)
+{
+ int ret = 0;
+ unsigned i;
+ cmdline_portlist_t result;
+
+ /* test invalid strings */
+ for (i = 0; i < RTE_DIM(portlist_invalid_strs); i++) {
+
+ memset(&result, 0, sizeof(cmdline_portlist_t));
+
+ ret = cmdline_parse_portlist(NULL, portlist_invalid_strs[i],
+ (void*)&result, sizeof(result));
+ if (ret != -1) {
+ printf("Error: parsing %s succeeded!\n",
+ portlist_invalid_strs[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* test valid parameters and data */
+int
+test_parse_portlist_valid(void)
+{
+ int ret = 0;
+ unsigned i;
+ cmdline_portlist_t result;
+
+ /* test full strings */
+ for (i = 0; i < RTE_DIM(portlist_valid_strs); i++) {
+
+ memset(&result, 0, sizeof(cmdline_portlist_t));
+
+ ret = cmdline_parse_portlist(NULL, portlist_valid_strs[i].str,
+ (void*)&result, sizeof(result));
+ if (ret < 0) {
+ printf("Error: parsing %s failed!\n",
+ portlist_valid_strs[i].str);
+ return -1;
+ }
+ if (result.map != portlist_valid_strs[i].portmap) {
+ printf("Error: parsing %s failed: map mismatch!\n",
+ portlist_valid_strs[i].str);
+ return -1;
+ }
+ }
+
+ /* test garbage strings */
+ for (i = 0; i < RTE_DIM(portlist_garbage_strs); i++) {
+
+ memset(&result, 0, sizeof(cmdline_portlist_t));
+
+ ret = cmdline_parse_portlist(NULL, portlist_garbage_strs[i],
+ (void*)&result, sizeof(result));
+ if (ret < 0) {
+ printf("Error: parsing %s failed!\n",
+ portlist_garbage_strs[i]);
+ return -1;
+ }
+ if (result.map != UINT32_MAX) {
+ printf("Error: parsing %s failed: map mismatch!\n",
+ portlist_garbage_strs[i]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_cmdline_string.c b/src/spdk/dpdk/app/test/test_cmdline_string.c
new file mode 100644
index 000000000..97516c940
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cmdline_string.c
@@ -0,0 +1,370 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_string_fns.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_string.h>
+
+#include "test_cmdline.h"
+
+/* structures needed to run tests */
+
+struct string_elt_str {
+ const char * str; /* parsed string */
+ const char * result; /* expected string */
+ int idx; /* position at which result is expected to be */
+};
+
+struct string_elt_str string_elt_strs[] = {
+ {"one#two#three", "three", 2},
+ {"one#two with spaces#three", "three", 2},
+ {"one#two\twith\ttabs#three", "three", 2},
+ {"one#two\rwith\rreturns#three", "three", 2},
+ {"one#two\nwith\nnewlines#three", "three", 2},
+ {"one#two#three", "one", 0},
+ {"one#two#three", "two", 1},
+ {"one#two\0three", "two", 1},
+ {"one#two with spaces#three", "two with spaces", 1},
+ {"one#two\twith\ttabs#three", "two\twith\ttabs", 1},
+ {"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1},
+ {"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1},
+};
+
+#if (CMDLINE_TEST_BUFSIZE < STR_TOKEN_SIZE) \
+|| (CMDLINE_TEST_BUFSIZE < STR_MULTI_TOKEN_SIZE)
+#undef CMDLINE_TEST_BUFSIZE
+#define CMDLINE_TEST_BUFSIZE RTE_MAX(STR_TOKEN_SIZE, STR_MULTI_TOKEN_SIZE)
+#endif
+
+struct string_nb_str {
+ const char * str; /* parsed string */
+ int nb_strs; /* expected number of strings in str */
+};
+
+struct string_nb_str string_nb_strs[] = {
+ {"one#two#three", 3},
+ {"one", 1},
+ {"one# \t two \r # three \n #four", 4},
+};
+
+
+
+struct string_parse_str {
+ const char * str; /* parsed string */
+ const char * fixed_str; /* parsing mode (any, fixed or multi) */
+ const char * result; /* expected result */
+};
+
+struct string_parse_str string_parse_strs[] = {
+ {"one", NULL, "one"}, /* any string */
+ {"two", "one#two#three", "two"}, /* multiple choice string */
+ {"three", "three", "three"}, /* fixed string */
+ {"three", "one#two with\rgarbage\tcharacters\n#three", "three"},
+ {"two with\rgarbage\tcharacters\n",
+ "one#two with\rgarbage\tcharacters\n#three",
+ "two with\rgarbage\tcharacters\n"},
+ {"one two", "one", "one"}, /* fixed string */
+ {"one two", TOKEN_STRING_MULTI, "one two"}, /* multi string */
+ {"one two", NULL, "one"}, /* any string */
+ {"one two #three", TOKEN_STRING_MULTI, "one two "},
+ /* multi string with comment */
+};
+
+
+
+struct string_invalid_str {
+ const char * str; /* parsed string */
+ const char * fixed_str; /* parsing mode (any, fixed or multi) */
+};
+
+struct string_invalid_str string_invalid_strs[] = {
+ {"invalid", "one"}, /* fixed string */
+ {"invalid", "one#two#three"}, /* multiple choice string */
+ {"invalid", "invalidone"}, /* string that starts the same */
+ {"invalidone", "invalid"}, /* string that starts the same */
+ {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!", NULL },
+ {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!", "fixed" },
+ {"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!", "multi#choice#string" },
+ {"invalid",
+ "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
+ "toolong!!!" },
+ {"", "invalid"}
+};
+
+
+
+const char * string_help_strs[] = {
+ NULL,
+ "fixed_str",
+ "multi#str",
+};
+
+#define SMALL_BUF 8
+
+/* test invalid parameters */
+int
+test_parse_string_invalid_param(void)
+{
+ cmdline_parse_token_string_t token;
+ int result;
+ char buf[CMDLINE_TEST_BUFSIZE];
+
+ memset(&token, 0, sizeof(token));
+
+ snprintf(buf, sizeof(buf), "buffer");
+
+ /* test null token */
+ if (cmdline_get_help_string(
+ NULL, buf, 0) != -1) {
+ printf("Error: function accepted null token!\n");
+ return -1;
+ }
+ if (cmdline_complete_get_elt_string(
+ NULL, 0, buf, 0) != -1) {
+ printf("Error: function accepted null token!\n");
+ return -1;
+ }
+ if (cmdline_complete_get_nb_string(NULL) != -1) {
+ printf("Error: function accepted null token!\n");
+ return -1;
+ }
+ if (cmdline_parse_string(NULL, buf, NULL, 0) != -1) {
+ printf("Error: function accepted null token!\n");
+ return -1;
+ }
+ /* test null buffer */
+ if (cmdline_complete_get_elt_string(
+ (cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) {
+ printf("Error: function accepted null buffer!\n");
+ return -1;
+ }
+ if (cmdline_parse_string(
+ (cmdline_parse_token_hdr_t*)&token, NULL,
+ (void*)&result, sizeof(result)) != -1) {
+ printf("Error: function accepted null buffer!\n");
+ return -1;
+ }
+ if (cmdline_get_help_string(
+ (cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) {
+ printf("Error: function accepted null buffer!\n");
+ return -1;
+ }
+ /* test null result */
+ if (cmdline_parse_string(
+ (cmdline_parse_token_hdr_t*)&token, buf, NULL, 0) == -1) {
+ printf("Error: function rejected null result!\n");
+ return -1;
+ }
+ /* test negative index */
+ if (cmdline_complete_get_elt_string(
+ (cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) {
+ printf("Error: function accepted negative index!\n");
+ return -1;
+ }
+ return 0;
+}
+
+/* test valid parameters but invalid data */
+int
+test_parse_string_invalid_data(void)
+{
+ cmdline_parse_token_string_t token;
+ cmdline_parse_token_string_t help_token;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char help_str[CMDLINE_TEST_BUFSIZE];
+ char small_buf[SMALL_BUF];
+ unsigned i;
+
+ /* test parsing invalid strings */
+ for (i = 0; i < RTE_DIM(string_invalid_strs); i++) {
+ memset(&token, 0, sizeof(token));
+ memset(buf, 0, sizeof(buf));
+
+ /* prepare test token data */
+ token.string_data.str = string_invalid_strs[i].fixed_str;
+
+ if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
+ string_invalid_strs[i].str, (void*)buf,
+ sizeof(buf)) != -1) {
+ memset(help_str, 0, sizeof(help_str));
+ memset(&help_token, 0, sizeof(help_token));
+
+ help_token.string_data.str = string_invalid_strs[i].fixed_str;
+
+ /* get parse type so we can give a good error message */
+ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
+ sizeof(help_str));
+
+ printf("Error: parsing %s as %s succeeded!\n",
+ string_invalid_strs[i].str, help_str);
+ return -1;
+ }
+ }
+
+ /* misc tests (big comments signify test cases) */
+ memset(&token, 0, sizeof(token));
+ memset(small_buf, 0, sizeof(small_buf));
+
+ /*
+ * try to get element from a null token
+ */
+ token.string_data.str = NULL;
+ if (cmdline_complete_get_elt_string(
+ (cmdline_parse_token_hdr_t*)&token, 1,
+ buf, sizeof(buf)) != -1) {
+ printf("Error: getting token from null token string!\n");
+ return -1;
+ }
+
+ /*
+ * try to get element into a buffer that is too small
+ */
+ token.string_data.str = "too_small_buffer";
+ if (cmdline_complete_get_elt_string(
+ (cmdline_parse_token_hdr_t*)&token, 0,
+ small_buf, sizeof(small_buf)) != -1) {
+ printf("Error: writing token into too small a buffer succeeded!\n");
+ return -1;
+ }
+
+ /*
+ * get help string written into a buffer smaller than help string
+ * truncation should occur
+ */
+ token.string_data.str = NULL;
+ if (cmdline_get_help_string(
+ (cmdline_parse_token_hdr_t*)&token,
+ small_buf, sizeof(small_buf)) == -1) {
+ printf("Error: writing help string into too small a buffer failed!\n");
+ return -1;
+ }
+ /* get help string for "any string" so we can compare it with small_buf */
+ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
+ sizeof(help_str));
+ if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) {
+ printf("Error: help string mismatch!\n");
+ return -1;
+ }
+ /* check null terminator */
+ if (small_buf[sizeof(small_buf) - 1] != '\0') {
+ printf("Error: small buffer doesn't have a null terminator!\n");
+ return -1;
+ }
+
+ /*
+ * try to count tokens in a null token
+ */
+ token.string_data.str = NULL;
+ if (cmdline_complete_get_nb_string(
+ (cmdline_parse_token_hdr_t*)&token) != 0) {
+ printf("Error: getting token count from null token succeeded!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* test valid parameters and data */
+int
+test_parse_string_valid(void)
+{
+ cmdline_parse_token_string_t token;
+ cmdline_parse_token_string_t help_token;
+ char buf[CMDLINE_TEST_BUFSIZE];
+ char help_str[CMDLINE_TEST_BUFSIZE];
+ unsigned i;
+
+ /* test parsing strings */
+ for (i = 0; i < RTE_DIM(string_parse_strs); i++) {
+ memset(&token, 0, sizeof(token));
+ memset(buf, 0, sizeof(buf));
+
+ token.string_data.str = string_parse_strs[i].fixed_str;
+
+ if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
+ string_parse_strs[i].str, (void*)buf,
+ sizeof(buf)) < 0) {
+
+ /* clean help data */
+ memset(&help_token, 0, sizeof(help_token));
+ memset(help_str, 0, sizeof(help_str));
+
+ /* prepare help token */
+ help_token.string_data.str = string_parse_strs[i].fixed_str;
+
+ /* get help string so that we get an informative error message */
+ cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
+ sizeof(help_str));
+
+ printf("Error: parsing %s as %s failed!\n",
+ string_parse_strs[i].str, help_str);
+ return -1;
+ }
+ if (strcmp(buf, string_parse_strs[i].result) != 0) {
+ printf("Error: result mismatch!\n");
+ return -1;
+ }
+ }
+
+ /* get number of string tokens and verify it's correct */
+ for (i = 0; i < RTE_DIM(string_nb_strs); i++) {
+ memset(&token, 0, sizeof(token));
+
+ token.string_data.str = string_nb_strs[i].str;
+
+ if (cmdline_complete_get_nb_string(
+ (cmdline_parse_token_hdr_t*)&token) <
+ string_nb_strs[i].nb_strs) {
+ printf("Error: strings count mismatch!\n");
+ return -1;
+ }
+ }
+
+ /* get token at specified position and verify it's correct */
+ for (i = 0; i < RTE_DIM(string_elt_strs); i++) {
+ memset(&token, 0, sizeof(token));
+ memset(buf, 0, sizeof(buf));
+
+ token.string_data.str = string_elt_strs[i].str;
+
+ if (cmdline_complete_get_elt_string(
+ (cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx,
+ buf, sizeof(buf)) < 0) {
+ printf("Error: getting string element failed!\n");
+ return -1;
+ }
+ if (strncmp(buf, string_elt_strs[i].result,
+ sizeof(buf)) != 0) {
+ printf("Error: result mismatch!\n");
+ return -1;
+ }
+ }
+
+ /* cover all cases with help strings */
+ for (i = 0; i < RTE_DIM(string_help_strs); i++) {
+ memset(&help_token, 0, sizeof(help_token));
+ memset(help_str, 0, sizeof(help_str));
+ help_token.string_data.str = string_help_strs[i];
+ if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token,
+ help_str, sizeof(help_str)) < 0) {
+ printf("Error: help operation failed!\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_common.c b/src/spdk/dpdk/app/test/test_common.c
new file mode 100644
index 000000000..12bd1cad9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_common.c
@@ -0,0 +1,327 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <math.h>
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_pause.h>
+
+#include "test.h"
+
+#define MAX_NUM 1 << 20
+
+#define FAIL(x)\
+ {printf(x "() test failed!\n");\
+ return -1;}
+
+/* this is really a sanity check */
+static int
+test_macros(int __rte_unused unused_parm)
+{
+#define SMALLER 0x1000U
+#define BIGGER 0x2000U
+#define PTR_DIFF BIGGER - SMALLER
+#define FAIL_MACRO(x)\
+ {printf(#x "() test failed!\n");\
+ return -1;}
+
+ uintptr_t unused = 0;
+
+ RTE_SET_USED(unused);
+
+ if ((uintptr_t)RTE_PTR_ADD(SMALLER, PTR_DIFF) != BIGGER)
+ FAIL_MACRO(RTE_PTR_ADD);
+ if ((uintptr_t)RTE_PTR_SUB(BIGGER, PTR_DIFF) != SMALLER)
+ FAIL_MACRO(RTE_PTR_SUB);
+ if (RTE_PTR_DIFF(BIGGER, SMALLER) != PTR_DIFF)
+ FAIL_MACRO(RTE_PTR_DIFF);
+ if (RTE_MAX(SMALLER, BIGGER) != BIGGER)
+ FAIL_MACRO(RTE_MAX);
+ if (RTE_MIN(SMALLER, BIGGER) != SMALLER)
+ FAIL_MACRO(RTE_MIN);
+
+ if (strncmp(RTE_STR(test), "test", sizeof("test")))
+ FAIL_MACRO(RTE_STR);
+
+ return 0;
+}
+
+static int
+test_bsf(void)
+{
+ uint32_t shift, pos;
+
+ /* safe versions should be able to handle 0 */
+ if (rte_bsf32_safe(0, &pos) != 0)
+ FAIL("rte_bsf32_safe");
+ if (rte_bsf64_safe(0, &pos) != 0)
+ FAIL("rte_bsf64_safe");
+
+ for (shift = 0; shift < 63; shift++) {
+ uint32_t val32;
+ uint64_t val64;
+
+ val64 = 1ULL << shift;
+ if ((uint32_t)rte_bsf64(val64) != shift)
+ FAIL("rte_bsf64");
+ if (rte_bsf64_safe(val64, &pos) != 1)
+ FAIL("rte_bsf64_safe");
+ if (pos != shift)
+ FAIL("rte_bsf64_safe");
+
+ if (shift > 31)
+ continue;
+
+ val32 = 1U << shift;
+ if ((uint32_t)rte_bsf32(val32) != shift)
+ FAIL("rte_bsf32");
+ if (rte_bsf32_safe(val32, &pos) != 1)
+ FAIL("rte_bsf32_safe");
+ if (pos != shift)
+ FAIL("rte_bsf32_safe");
+ }
+
+ return 0;
+}
+
+static int
+test_misc(void)
+{
+ char memdump[] = "memdump_test";
+
+ rte_memdump(stdout, "test", memdump, sizeof(memdump));
+ rte_hexdump(stdout, "test", memdump, sizeof(memdump));
+
+ rte_pause();
+
+ return 0;
+}
+
+static int
+test_align(void)
+{
+#define FAIL_ALIGN(x, i, p)\
+ {printf(x "() test failed: %u %u\n", i, p);\
+ return -1;}
+#define FAIL_ALIGN64(x, j, q)\
+ {printf(x "() test failed: %"PRIu64" %"PRIu64"\n", j, q);\
+ return -1; }
+#define ERROR_FLOOR(res, i, pow) \
+ (res % pow) || /* check if not aligned */ \
+ ((res / pow) != (i / pow)) /* check if correct alignment */
+#define ERROR_CEIL(res, i, pow) \
+ (res % pow) || /* check if not aligned */ \
+ ((i % pow) == 0 ? /* check if ceiling is invoked */ \
+ val / pow != i / pow : /* if aligned */ \
+ val / pow != (i / pow) + 1) /* if not aligned, hence +1 */
+
+ uint32_t i, p, val;
+ uint64_t j, q;
+
+ for (i = 1, p = 1; i <= MAX_NUM; i ++) {
+ if (rte_align32pow2(i) != p)
+ FAIL_ALIGN("rte_align32pow2", i, p);
+ if (i == p)
+ p <<= 1;
+ }
+
+ for (i = 1, p = 1; i <= MAX_NUM; i++) {
+ if (rte_align32prevpow2(i) != p)
+ FAIL_ALIGN("rte_align32prevpow2", i, p);
+ if (rte_is_power_of_2(i + 1))
+ p = i + 1;
+ }
+
+ for (j = 1, q = 1; j <= MAX_NUM ; j++) {
+ if (rte_align64pow2(j) != q)
+ FAIL_ALIGN64("rte_align64pow2", j, q);
+ if (j == q)
+ q <<= 1;
+ }
+
+ for (j = 1, q = 1; j <= MAX_NUM ; j++) {
+ if (rte_align64prevpow2(j) != q)
+ FAIL_ALIGN64("rte_align64prevpow2", j, q);
+ if (rte_is_power_of_2(j + 1))
+ q = j + 1;
+ }
+
+ for (p = 2; p <= MAX_NUM; p <<= 1) {
+
+ if (!rte_is_power_of_2(p))
+ FAIL("rte_is_power_of_2");
+
+ for (i = 1; i <= MAX_NUM; i++) {
+ /* align floor */
+ if (RTE_ALIGN_FLOOR((uintptr_t)i, p) % p)
+ FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
+
+ val = RTE_PTR_ALIGN_FLOOR((uintptr_t) i, p);
+ if (ERROR_FLOOR(val, i, p))
+ FAIL_ALIGN("RTE_PTR_ALIGN_FLOOR", i, p);
+
+ val = RTE_ALIGN_FLOOR(i, p);
+ if (ERROR_FLOOR(val, i, p))
+ FAIL_ALIGN("RTE_ALIGN_FLOOR", i, p);
+
+ /* align ceiling */
+ val = RTE_PTR_ALIGN((uintptr_t) i, p);
+ if (ERROR_CEIL(val, i, p))
+ FAIL_ALIGN("RTE_PTR_ALIGN", i, p);
+
+ val = RTE_ALIGN(i, p);
+ if (ERROR_CEIL(val, i, p))
+ FAIL_ALIGN("RTE_ALIGN", i, p);
+
+ val = RTE_ALIGN_CEIL(i, p);
+ if (ERROR_CEIL(val, i, p))
+ FAIL_ALIGN("RTE_ALIGN_CEIL", i, p);
+
+ val = RTE_PTR_ALIGN_CEIL((uintptr_t)i, p);
+ if (ERROR_CEIL(val, i, p))
+ FAIL_ALIGN("RTE_PTR_ALIGN_CEIL", i, p);
+
+ /* by this point we know that val is aligned to p */
+ if (!rte_is_aligned((void*)(uintptr_t) val, p))
+ FAIL("rte_is_aligned");
+ }
+ }
+
+ for (p = 1; p <= MAX_NUM / 2; p++) {
+ for (i = 1; i <= MAX_NUM / 2; i++) {
+ val = RTE_ALIGN_MUL_CEIL(i, p);
+ if (val % p != 0 || val < i)
+ FAIL_ALIGN("RTE_ALIGN_MUL_CEIL", i, p);
+ val = RTE_ALIGN_MUL_FLOOR(i, p);
+ if (val % p != 0 || val > i)
+ FAIL_ALIGN("RTE_ALIGN_MUL_FLOOR", i, p);
+ val = RTE_ALIGN_MUL_NEAR(i, p);
+ if (val % p != 0 || ((val != RTE_ALIGN_MUL_CEIL(i, p))
+ & (val != RTE_ALIGN_MUL_FLOOR(i, p))))
+ FAIL_ALIGN("RTE_ALIGN_MUL_NEAR", i, p);
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_log2(void)
+{
+ uint32_t i, base, compare;
+ const uint32_t max = 0x10000;
+ const uint32_t step = 1;
+
+ compare = rte_log2_u32(0);
+ if (compare != 0) {
+ printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare);
+ return TEST_FAILED;
+ }
+
+ compare = rte_log2_u64(0);
+ if (compare != 0) {
+ printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare);
+ return TEST_FAILED;
+ }
+
+ for (i = 1; i < max; i = i + step) {
+ uint64_t i64;
+
+ /* extend range for 64-bit */
+ i64 = (uint64_t)i << 32;
+ base = (uint32_t)ceilf(log2(i64));
+ compare = rte_log2_u64(i64);
+ if (base != compare) {
+ printf("Wrong rte_log2_u64(%" PRIx64 ") val %x, expected %x\n",
+ i64, compare, base);
+ return TEST_FAILED;
+ }
+
+ base = (uint32_t)ceilf(log2((uint32_t)i));
+ compare = rte_log2_u32((uint32_t)i);
+ if (base != compare) {
+ printf("Wrong rte_log2_u32(%x) val %x, expected %x\n",
+ i, compare, base);
+ return TEST_FAILED;
+ }
+ compare = rte_log2_u64((uint64_t)i);
+ if (base != compare) {
+ printf("Wrong rte_log2_u64(%x) val %x, expected %x\n",
+ i, compare, base);
+ return TEST_FAILED;
+ }
+ }
+ return 0;
+}
+
+static int
+test_fls(void)
+{
+ struct fls_test_vector {
+ uint32_t arg;
+ int rc;
+ };
+ int expected, rc;
+ uint32_t i, arg;
+
+ const struct fls_test_vector test[] = {
+ {0x0, 0},
+ {0x1, 1},
+ {0x4000, 15},
+ {0x80000000, 32},
+ };
+
+ for (i = 0; i < RTE_DIM(test); i++) {
+ uint64_t arg64;
+
+ arg = test[i].arg;
+ rc = rte_fls_u32(arg);
+ expected = test[i].rc;
+ if (rc != expected) {
+ printf("Wrong rte_fls_u32(0x%x) rc=%d, expected=%d\n",
+ arg, rc, expected);
+ return TEST_FAILED;
+ }
+ /* 64-bit version */
+ arg = test[i].arg;
+ rc = rte_fls_u64(arg);
+ expected = test[i].rc;
+ if (rc != expected) {
+ printf("Wrong rte_fls_u64(0x%x) rc=%d, expected=%d\n",
+ arg, rc, expected);
+ return TEST_FAILED;
+ }
+ /* 64-bit version shifted by 32 bits */
+ arg64 = (uint64_t)test[i].arg << 32;
+ rc = rte_fls_u64(arg64);
+ /* don't shift zero */
+ expected = test[i].rc == 0 ? 0 : test[i].rc + 32;
+ if (rc != expected) {
+ printf("Wrong rte_fls_u64(0x%" PRIx64 ") rc=%d, expected=%d\n",
+ arg64, rc, expected);
+ return TEST_FAILED;
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_common(void)
+{
+ int ret = 0;
+ ret |= test_align();
+ ret |= test_macros(0);
+ ret |= test_misc();
+ ret |= test_bsf();
+ ret |= test_log2();
+ ret |= test_fls();
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(common_autotest, test_common);
diff --git a/src/spdk/dpdk/app/test/test_compressdev.c b/src/spdk/dpdk/app/test/test_compressdev.c
new file mode 100644
index 000000000..0571c17ec
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_compressdev.c
@@ -0,0 +1,4273 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 - 2019 Intel Corporation
+ */
+#include <string.h>
+#include <zlib.h>
+#include <math.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_compressdev.h>
+#include <rte_string_fns.h>
+
+#include "test_compressdev_test_buffer.h"
+#include "test.h"
+
+#define DIV_CEIL(a, b) ((a) / (b) + ((a) % (b) != 0))
+
+#define DEFAULT_WINDOW_SIZE 15
+#define DEFAULT_MEM_LEVEL 8
+#define MAX_DEQD_RETRIES 10
+#define DEQUEUE_WAIT_TIME 10000
+
+/*
+ * 30% extra size for compressed data compared to original data,
+ * in case data size cannot be reduced and it is actually bigger
+ * due to the compress block headers
+ */
+#define COMPRESS_BUF_SIZE_RATIO 1.3
+#define COMPRESS_BUF_SIZE_RATIO_DISABLED 1.0
+#define COMPRESS_BUF_SIZE_RATIO_OVERFLOW 0.2
+#define NUM_LARGE_MBUFS 16
+#define SMALL_SEG_SIZE 256
+#define MAX_SEGS 16
+#define NUM_OPS 16
+#define NUM_MAX_XFORMS 16
+#define NUM_MAX_INFLIGHT_OPS 128
+#define CACHE_SIZE 0
+
+#define ZLIB_CRC_CHECKSUM_WINDOW_BITS 31
+#define ZLIB_HEADER_SIZE 2
+#define ZLIB_TRAILER_SIZE 4
+#define GZIP_HEADER_SIZE 10
+#define GZIP_TRAILER_SIZE 8
+
+#define OUT_OF_SPACE_BUF 1
+
+#define MAX_MBUF_SEGMENT_SIZE 65535
+#define MAX_DATA_MBUF_SIZE (MAX_MBUF_SEGMENT_SIZE - RTE_PKTMBUF_HEADROOM)
+#define NUM_BIG_MBUFS (512 + 1)
+#define BIG_DATA_TEST_SIZE (MAX_DATA_MBUF_SIZE * 2)
+
+/* constants for "im buffer" tests start here */
+
+/* number of mbufs lower than number of inflight ops */
+#define IM_BUF_NUM_MBUFS 3
+/* above threshold (QAT_FALLBACK_THLD) and below max mbuf size */
+#define IM_BUF_DATA_TEST_SIZE_LB 59600
+/* data size smaller than the queue capacity */
+#define IM_BUF_DATA_TEST_SIZE_SGL (MAX_DATA_MBUF_SIZE * IM_BUF_NUM_MBUFS)
+/* number of mbufs bigger than number of inflight ops */
+#define IM_BUF_NUM_MBUFS_OVER (NUM_MAX_INFLIGHT_OPS + 1)
+/* data size bigger than the queue capacity */
+#define IM_BUF_DATA_TEST_SIZE_OVER (MAX_DATA_MBUF_SIZE * IM_BUF_NUM_MBUFS_OVER)
+/* number of mid-size mbufs */
+#define IM_BUF_NUM_MBUFS_MID ((NUM_MAX_INFLIGHT_OPS / 3) + 1)
+/* capacity of mid-size mbufs */
+#define IM_BUF_DATA_TEST_SIZE_MID (MAX_DATA_MBUF_SIZE * IM_BUF_NUM_MBUFS_MID)
+
+
+const char *
+huffman_type_strings[] = {
+ [RTE_COMP_HUFFMAN_DEFAULT] = "PMD default",
+ [RTE_COMP_HUFFMAN_FIXED] = "Fixed",
+ [RTE_COMP_HUFFMAN_DYNAMIC] = "Dynamic"
+};
+
+enum zlib_direction {
+ ZLIB_NONE,
+ ZLIB_COMPRESS,
+ ZLIB_DECOMPRESS,
+ ZLIB_ALL
+};
+
+enum varied_buff {
+ LB_BOTH = 0, /* both input and output are linear*/
+ SGL_BOTH, /* both input and output are chained */
+ SGL_TO_LB, /* input buffer is chained */
+ LB_TO_SGL /* output buffer is chained */
+};
+
+enum overflow_test {
+ OVERFLOW_DISABLED,
+ OVERFLOW_ENABLED
+};
+
+enum ratio_switch {
+ RATIO_DISABLED,
+ RATIO_ENABLED
+};
+
+enum operation_type {
+ OPERATION_COMPRESSION,
+ OPERATION_DECOMPRESSION
+};
+
+struct priv_op_data {
+ uint16_t orig_idx;
+};
+
+struct comp_testsuite_params {
+ struct rte_mempool *large_mbuf_pool;
+ struct rte_mempool *small_mbuf_pool;
+ struct rte_mempool *big_mbuf_pool;
+ struct rte_mempool *op_pool;
+ struct rte_comp_xform *def_comp_xform;
+ struct rte_comp_xform *def_decomp_xform;
+};
+
+struct interim_data_params {
+ const char * const *test_bufs;
+ unsigned int num_bufs;
+ uint16_t *buf_idx;
+ struct rte_comp_xform **compress_xforms;
+ struct rte_comp_xform **decompress_xforms;
+ unsigned int num_xforms;
+};
+
+struct test_data_params {
+ enum rte_comp_op_type compress_state;
+ enum rte_comp_op_type decompress_state;
+ enum varied_buff buff_type;
+ enum zlib_direction zlib_dir;
+ unsigned int out_of_space;
+ unsigned int big_data;
+ /* stateful decompression specific parameters */
+ unsigned int decompress_output_block_size;
+ unsigned int decompress_steps_max;
+ /* external mbufs specific parameters */
+ unsigned int use_external_mbufs;
+ unsigned int inbuf_data_size;
+ const struct rte_memzone *inbuf_memzone;
+ const struct rte_memzone *compbuf_memzone;
+ const struct rte_memzone *uncompbuf_memzone;
+ /* overflow test activation */
+ enum overflow_test overflow;
+ enum ratio_switch ratio;
+};
+
+struct test_private_arrays {
+ struct rte_mbuf **uncomp_bufs;
+ struct rte_mbuf **comp_bufs;
+ struct rte_comp_op **ops;
+ struct rte_comp_op **ops_processed;
+ void **priv_xforms;
+ uint64_t *compress_checksum;
+ uint32_t *compressed_data_size;
+ void **stream;
+ char **all_decomp_data;
+ unsigned int *decomp_produced_data_size;
+ uint16_t num_priv_xforms;
+};
+
+static struct comp_testsuite_params testsuite_params = { 0 };
+
+
+static void
+testsuite_teardown(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+
+ if (rte_mempool_in_use_count(ts_params->large_mbuf_pool))
+ RTE_LOG(ERR, USER1, "Large mbuf pool still has unfreed bufs\n");
+ if (rte_mempool_in_use_count(ts_params->small_mbuf_pool))
+ RTE_LOG(ERR, USER1, "Small mbuf pool still has unfreed bufs\n");
+ if (rte_mempool_in_use_count(ts_params->big_mbuf_pool))
+ RTE_LOG(ERR, USER1, "Big mbuf pool still has unfreed bufs\n");
+ if (rte_mempool_in_use_count(ts_params->op_pool))
+ RTE_LOG(ERR, USER1, "op pool still has unfreed ops\n");
+
+ rte_mempool_free(ts_params->large_mbuf_pool);
+ rte_mempool_free(ts_params->small_mbuf_pool);
+ rte_mempool_free(ts_params->big_mbuf_pool);
+ rte_mempool_free(ts_params->op_pool);
+ rte_free(ts_params->def_comp_xform);
+ rte_free(ts_params->def_decomp_xform);
+}
+
+static int
+testsuite_setup(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint32_t max_buf_size = 0;
+ unsigned int i;
+
+ if (rte_compressdev_count() == 0) {
+ RTE_LOG(WARNING, USER1, "Need at least one compress device\n");
+ return TEST_SKIPPED;
+ }
+
+ RTE_LOG(NOTICE, USER1, "Running tests on device %s\n",
+ rte_compressdev_name_get(0));
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++)
+ max_buf_size = RTE_MAX(max_buf_size,
+ strlen(compress_test_bufs[i]) + 1);
+
+ /*
+ * Buffers to be used in compression and decompression.
+ * Since decompressed data might be larger than
+ * compressed data (due to block header),
+ * buffers should be big enough for both cases.
+ */
+ max_buf_size *= COMPRESS_BUF_SIZE_RATIO;
+ ts_params->large_mbuf_pool = rte_pktmbuf_pool_create("large_mbuf_pool",
+ NUM_LARGE_MBUFS,
+ CACHE_SIZE, 0,
+ max_buf_size + RTE_PKTMBUF_HEADROOM,
+ rte_socket_id());
+ if (ts_params->large_mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Large mbuf pool could not be created\n");
+ return TEST_FAILED;
+ }
+
+ /* Create mempool with smaller buffers for SGL testing */
+ ts_params->small_mbuf_pool = rte_pktmbuf_pool_create("small_mbuf_pool",
+ NUM_LARGE_MBUFS * MAX_SEGS,
+ CACHE_SIZE, 0,
+ SMALL_SEG_SIZE + RTE_PKTMBUF_HEADROOM,
+ rte_socket_id());
+ if (ts_params->small_mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Small mbuf pool could not be created\n");
+ goto exit;
+ }
+
+ /* Create mempool with big buffers for SGL testing */
+ ts_params->big_mbuf_pool = rte_pktmbuf_pool_create("big_mbuf_pool",
+ NUM_BIG_MBUFS + 1,
+ CACHE_SIZE, 0,
+ MAX_MBUF_SEGMENT_SIZE,
+ rte_socket_id());
+ if (ts_params->big_mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Big mbuf pool could not be created\n");
+ goto exit;
+ }
+
+ ts_params->op_pool = rte_comp_op_pool_create("op_pool", NUM_OPS,
+ 0, sizeof(struct priv_op_data),
+ rte_socket_id());
+ if (ts_params->op_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Operation pool could not be created\n");
+ goto exit;
+ }
+
+ ts_params->def_comp_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (ts_params->def_comp_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Default compress xform could not be created\n");
+ goto exit;
+ }
+ ts_params->def_decomp_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (ts_params->def_decomp_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Default decompress xform could not be created\n");
+ goto exit;
+ }
+
+ /* Initializes default values for compress/decompress xforms */
+ ts_params->def_comp_xform->type = RTE_COMP_COMPRESS;
+ ts_params->def_comp_xform->compress.algo = RTE_COMP_ALGO_DEFLATE,
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ ts_params->def_comp_xform->compress.level = RTE_COMP_LEVEL_PMD_DEFAULT;
+ ts_params->def_comp_xform->compress.chksum = RTE_COMP_CHECKSUM_NONE;
+ ts_params->def_comp_xform->compress.window_size = DEFAULT_WINDOW_SIZE;
+
+ ts_params->def_decomp_xform->type = RTE_COMP_DECOMPRESS;
+ ts_params->def_decomp_xform->decompress.algo = RTE_COMP_ALGO_DEFLATE,
+ ts_params->def_decomp_xform->decompress.chksum = RTE_COMP_CHECKSUM_NONE;
+ ts_params->def_decomp_xform->decompress.window_size = DEFAULT_WINDOW_SIZE;
+
+ return TEST_SUCCESS;
+
+exit:
+ testsuite_teardown();
+
+ return TEST_FAILED;
+}
+
+static int
+generic_ut_setup(void)
+{
+ /* Configure compressdev (one device, one queue pair) */
+ struct rte_compressdev_config config = {
+ .socket_id = rte_socket_id(),
+ .nb_queue_pairs = 1,
+ .max_nb_priv_xforms = NUM_MAX_XFORMS,
+ .max_nb_streams = 1
+ };
+
+ if (rte_compressdev_configure(0, &config) < 0) {
+ RTE_LOG(ERR, USER1, "Device configuration failed\n");
+ return -1;
+ }
+
+ if (rte_compressdev_queue_pair_setup(0, 0, NUM_MAX_INFLIGHT_OPS,
+ rte_socket_id()) < 0) {
+ RTE_LOG(ERR, USER1, "Queue pair setup failed\n");
+ return -1;
+ }
+
+ if (rte_compressdev_start(0) < 0) {
+ RTE_LOG(ERR, USER1, "Device could not be started\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+generic_ut_teardown(void)
+{
+ rte_compressdev_stop(0);
+ if (rte_compressdev_close(0) < 0)
+ RTE_LOG(ERR, USER1, "Device could not be closed\n");
+}
+
+static int
+test_compressdev_invalid_configuration(void)
+{
+ struct rte_compressdev_config invalid_config;
+ struct rte_compressdev_config valid_config = {
+ .socket_id = rte_socket_id(),
+ .nb_queue_pairs = 1,
+ .max_nb_priv_xforms = NUM_MAX_XFORMS,
+ .max_nb_streams = 1
+ };
+ struct rte_compressdev_info dev_info;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+
+ /* Invalid configuration with 0 queue pairs */
+ memcpy(&invalid_config, &valid_config,
+ sizeof(struct rte_compressdev_config));
+ invalid_config.nb_queue_pairs = 0;
+
+ TEST_ASSERT_FAIL(rte_compressdev_configure(0, &invalid_config),
+ "Device configuration was successful "
+ "with no queue pairs (invalid)\n");
+
+ /*
+ * Invalid configuration with too many queue pairs
+ * (if there is an actual maximum number of queue pairs)
+ */
+ rte_compressdev_info_get(0, &dev_info);
+ if (dev_info.max_nb_queue_pairs != 0) {
+ memcpy(&invalid_config, &valid_config,
+ sizeof(struct rte_compressdev_config));
+ invalid_config.nb_queue_pairs = dev_info.max_nb_queue_pairs + 1;
+
+ TEST_ASSERT_FAIL(rte_compressdev_configure(0, &invalid_config),
+ "Device configuration was successful "
+ "with too many queue pairs (invalid)\n");
+ }
+
+ /* Invalid queue pair setup, with no number of queue pairs set */
+ TEST_ASSERT_FAIL(rte_compressdev_queue_pair_setup(0, 0,
+ NUM_MAX_INFLIGHT_OPS, rte_socket_id()),
+ "Queue pair setup was successful "
+ "with no queue pairs set (invalid)\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+compare_buffers(const char *buffer1, uint32_t buffer1_len,
+ const char *buffer2, uint32_t buffer2_len)
+{
+ if (buffer1_len != buffer2_len) {
+ RTE_LOG(ERR, USER1, "Buffer lengths are different\n");
+ return -1;
+ }
+
+ if (memcmp(buffer1, buffer2, buffer1_len) != 0) {
+ RTE_LOG(ERR, USER1, "Buffers are different\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Maps compressdev and Zlib flush flags
+ */
+static int
+map_zlib_flush_flag(enum rte_comp_flush_flag flag)
+{
+ switch (flag) {
+ case RTE_COMP_FLUSH_NONE:
+ return Z_NO_FLUSH;
+ case RTE_COMP_FLUSH_SYNC:
+ return Z_SYNC_FLUSH;
+ case RTE_COMP_FLUSH_FULL:
+ return Z_FULL_FLUSH;
+ case RTE_COMP_FLUSH_FINAL:
+ return Z_FINISH;
+ /*
+ * There should be only the values above,
+ * so this should never happen
+ */
+ default:
+ return -1;
+ }
+}
+
+static int
+compress_zlib(struct rte_comp_op *op,
+ const struct rte_comp_xform *xform, int mem_level)
+{
+ z_stream stream;
+ int zlib_flush;
+ int strategy, window_bits, comp_level;
+ int ret = TEST_FAILED;
+ uint8_t *single_src_buf = NULL;
+ uint8_t *single_dst_buf = NULL;
+
+ /* initialize zlib stream */
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED)
+ strategy = Z_FIXED;
+ else
+ strategy = Z_DEFAULT_STRATEGY;
+
+ /*
+ * Window bits is the base two logarithm of the window size (in bytes).
+ * When doing raw DEFLATE, this number will be negative.
+ */
+ window_bits = -(xform->compress.window_size);
+ if (xform->compress.chksum == RTE_COMP_CHECKSUM_ADLER32)
+ window_bits *= -1;
+ else if (xform->compress.chksum == RTE_COMP_CHECKSUM_CRC32)
+ window_bits = ZLIB_CRC_CHECKSUM_WINDOW_BITS;
+
+ comp_level = xform->compress.level;
+
+ if (comp_level != RTE_COMP_LEVEL_NONE)
+ ret = deflateInit2(&stream, comp_level, Z_DEFLATED,
+ window_bits, mem_level, strategy);
+ else
+ ret = deflateInit(&stream, Z_NO_COMPRESSION);
+
+ if (ret != Z_OK) {
+ printf("Zlib deflate could not be initialized\n");
+ goto exit;
+ }
+
+ /* Assuming stateless operation */
+ /* SGL Input */
+ if (op->m_src->nb_segs > 1) {
+ single_src_buf = rte_malloc(NULL,
+ rte_pktmbuf_pkt_len(op->m_src), 0);
+ if (single_src_buf == NULL) {
+ RTE_LOG(ERR, USER1, "Buffer could not be allocated\n");
+ goto exit;
+ }
+
+ if (rte_pktmbuf_read(op->m_src, op->src.offset,
+ rte_pktmbuf_pkt_len(op->m_src) -
+ op->src.offset,
+ single_src_buf) == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Buffer could not be read entirely\n");
+ goto exit;
+ }
+
+ stream.avail_in = op->src.length;
+ stream.next_in = single_src_buf;
+
+ } else {
+ stream.avail_in = op->src.length;
+ stream.next_in = rte_pktmbuf_mtod_offset(op->m_src, uint8_t *,
+ op->src.offset);
+ }
+ /* SGL output */
+ if (op->m_dst->nb_segs > 1) {
+
+ single_dst_buf = rte_malloc(NULL,
+ rte_pktmbuf_pkt_len(op->m_dst), 0);
+ if (single_dst_buf == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Buffer could not be allocated\n");
+ goto exit;
+ }
+
+ stream.avail_out = op->m_dst->pkt_len;
+ stream.next_out = single_dst_buf;
+
+ } else {/* linear output */
+ stream.avail_out = op->m_dst->data_len;
+ stream.next_out = rte_pktmbuf_mtod_offset(op->m_dst, uint8_t *,
+ op->dst.offset);
+ }
+
+ /* Stateless operation, all buffer will be compressed in one go */
+ zlib_flush = map_zlib_flush_flag(op->flush_flag);
+ ret = deflate(&stream, zlib_flush);
+
+ if (stream.avail_in != 0) {
+ RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
+ goto exit;
+ }
+
+ if (ret != Z_STREAM_END)
+ goto exit;
+
+ /* Copy data to destination SGL */
+ if (op->m_dst->nb_segs > 1) {
+ uint32_t remaining_data = stream.total_out;
+ uint8_t *src_data = single_dst_buf;
+ struct rte_mbuf *dst_buf = op->m_dst;
+
+ while (remaining_data > 0) {
+ uint8_t *dst_data = rte_pktmbuf_mtod_offset(dst_buf,
+ uint8_t *, op->dst.offset);
+ /* Last segment */
+ if (remaining_data < dst_buf->data_len) {
+ memcpy(dst_data, src_data, remaining_data);
+ remaining_data = 0;
+ } else {
+ memcpy(dst_data, src_data, dst_buf->data_len);
+ remaining_data -= dst_buf->data_len;
+ src_data += dst_buf->data_len;
+ dst_buf = dst_buf->next;
+ }
+ }
+ }
+
+ op->consumed = stream.total_in;
+ if (xform->compress.chksum == RTE_COMP_CHECKSUM_ADLER32) {
+ rte_pktmbuf_adj(op->m_dst, ZLIB_HEADER_SIZE);
+ rte_pktmbuf_trim(op->m_dst, ZLIB_TRAILER_SIZE);
+ op->produced = stream.total_out - (ZLIB_HEADER_SIZE +
+ ZLIB_TRAILER_SIZE);
+ } else if (xform->compress.chksum == RTE_COMP_CHECKSUM_CRC32) {
+ rte_pktmbuf_adj(op->m_dst, GZIP_HEADER_SIZE);
+ rte_pktmbuf_trim(op->m_dst, GZIP_TRAILER_SIZE);
+ op->produced = stream.total_out - (GZIP_HEADER_SIZE +
+ GZIP_TRAILER_SIZE);
+ } else
+ op->produced = stream.total_out;
+
+ op->status = RTE_COMP_OP_STATUS_SUCCESS;
+ op->output_chksum = stream.adler;
+
+ deflateReset(&stream);
+
+ ret = 0;
+exit:
+ deflateEnd(&stream);
+ rte_free(single_src_buf);
+ rte_free(single_dst_buf);
+
+ return ret;
+}
+
+static int
+decompress_zlib(struct rte_comp_op *op,
+ const struct rte_comp_xform *xform)
+{
+ z_stream stream;
+ int window_bits;
+ int zlib_flush;
+ int ret = TEST_FAILED;
+ uint8_t *single_src_buf = NULL;
+ uint8_t *single_dst_buf = NULL;
+
+ /* initialize zlib stream */
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ /*
+ * Window bits is the base two logarithm of the window size (in bytes).
+ * When doing raw DEFLATE, this number will be negative.
+ */
+ window_bits = -(xform->decompress.window_size);
+ ret = inflateInit2(&stream, window_bits);
+
+ if (ret != Z_OK) {
+ printf("Zlib deflate could not be initialized\n");
+ goto exit;
+ }
+
+ /* Assuming stateless operation */
+ /* SGL */
+ if (op->m_src->nb_segs > 1) {
+ single_src_buf = rte_malloc(NULL,
+ rte_pktmbuf_pkt_len(op->m_src), 0);
+ if (single_src_buf == NULL) {
+ RTE_LOG(ERR, USER1, "Buffer could not be allocated\n");
+ goto exit;
+ }
+ single_dst_buf = rte_malloc(NULL,
+ rte_pktmbuf_pkt_len(op->m_dst), 0);
+ if (single_dst_buf == NULL) {
+ RTE_LOG(ERR, USER1, "Buffer could not be allocated\n");
+ goto exit;
+ }
+ if (rte_pktmbuf_read(op->m_src, 0,
+ rte_pktmbuf_pkt_len(op->m_src),
+ single_src_buf) == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Buffer could not be read entirely\n");
+ goto exit;
+ }
+
+ stream.avail_in = op->src.length;
+ stream.next_in = single_src_buf;
+ stream.avail_out = rte_pktmbuf_pkt_len(op->m_dst);
+ stream.next_out = single_dst_buf;
+
+ } else {
+ stream.avail_in = op->src.length;
+ stream.next_in = rte_pktmbuf_mtod(op->m_src, uint8_t *);
+ stream.avail_out = op->m_dst->data_len;
+ stream.next_out = rte_pktmbuf_mtod(op->m_dst, uint8_t *);
+ }
+
+ /* Stateless operation, all buffer will be compressed in one go */
+ zlib_flush = map_zlib_flush_flag(op->flush_flag);
+ ret = inflate(&stream, zlib_flush);
+
+ if (stream.avail_in != 0) {
+ RTE_LOG(ERR, USER1, "Buffer could not be read entirely\n");
+ goto exit;
+ }
+
+ if (ret != Z_STREAM_END)
+ goto exit;
+
+ if (op->m_src->nb_segs > 1) {
+ uint32_t remaining_data = stream.total_out;
+ uint8_t *src_data = single_dst_buf;
+ struct rte_mbuf *dst_buf = op->m_dst;
+
+ while (remaining_data > 0) {
+ uint8_t *dst_data = rte_pktmbuf_mtod(dst_buf,
+ uint8_t *);
+ /* Last segment */
+ if (remaining_data < dst_buf->data_len) {
+ memcpy(dst_data, src_data, remaining_data);
+ remaining_data = 0;
+ } else {
+ memcpy(dst_data, src_data, dst_buf->data_len);
+ remaining_data -= dst_buf->data_len;
+ src_data += dst_buf->data_len;
+ dst_buf = dst_buf->next;
+ }
+ }
+ }
+
+ op->consumed = stream.total_in;
+ op->produced = stream.total_out;
+ op->status = RTE_COMP_OP_STATUS_SUCCESS;
+
+ inflateReset(&stream);
+
+ ret = 0;
+exit:
+ inflateEnd(&stream);
+
+ return ret;
+}
+
+static int
+prepare_sgl_bufs(const char *test_buf, struct rte_mbuf *head_buf,
+ uint32_t total_data_size,
+ struct rte_mempool *small_mbuf_pool,
+ struct rte_mempool *large_mbuf_pool,
+ uint8_t limit_segs_in_sgl,
+ uint16_t seg_size)
+{
+ uint32_t remaining_data = total_data_size;
+ uint16_t num_remaining_segs = DIV_CEIL(remaining_data, seg_size);
+ struct rte_mempool *pool;
+ struct rte_mbuf *next_seg;
+ uint32_t data_size;
+ char *buf_ptr;
+ const char *data_ptr = test_buf;
+ uint16_t i;
+ int ret;
+
+ if (limit_segs_in_sgl != 0 && num_remaining_segs > limit_segs_in_sgl)
+ num_remaining_segs = limit_segs_in_sgl - 1;
+
+ /*
+ * Allocate data in the first segment (header) and
+ * copy data if test buffer is provided
+ */
+ if (remaining_data < seg_size)
+ data_size = remaining_data;
+ else
+ data_size = seg_size;
+
+ buf_ptr = rte_pktmbuf_append(head_buf, data_size);
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Not enough space in the 1st buffer\n");
+ return -1;
+ }
+
+ if (data_ptr != NULL) {
+ /* Copy characters without NULL terminator */
+ memcpy(buf_ptr, data_ptr, data_size);
+ data_ptr += data_size;
+ }
+ remaining_data -= data_size;
+ num_remaining_segs--;
+
+ /*
+ * Allocate the rest of the segments,
+ * copy the rest of the data and chain the segments.
+ */
+ for (i = 0; i < num_remaining_segs; i++) {
+
+ if (i == (num_remaining_segs - 1)) {
+ /* last segment */
+ if (remaining_data > seg_size)
+ pool = large_mbuf_pool;
+ else
+ pool = small_mbuf_pool;
+ data_size = remaining_data;
+ } else {
+ data_size = seg_size;
+ pool = small_mbuf_pool;
+ }
+
+ next_seg = rte_pktmbuf_alloc(pool);
+ if (next_seg == NULL) {
+ RTE_LOG(ERR, USER1,
+ "New segment could not be allocated "
+ "from the mempool\n");
+ return -1;
+ }
+ buf_ptr = rte_pktmbuf_append(next_seg, data_size);
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Not enough space in the buffer\n");
+ rte_pktmbuf_free(next_seg);
+ return -1;
+ }
+ if (data_ptr != NULL) {
+ /* Copy characters without NULL terminator */
+ memcpy(buf_ptr, data_ptr, data_size);
+ data_ptr += data_size;
+ }
+ remaining_data -= data_size;
+
+ ret = rte_pktmbuf_chain(head_buf, next_seg);
+ if (ret != 0) {
+ rte_pktmbuf_free(next_seg);
+ RTE_LOG(ERR, USER1,
+ "Segment could not chained\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)
+{
+}
+
+static int
+test_run_enqueue_dequeue(struct rte_comp_op **ops,
+ struct rte_comp_op **ops_processed,
+ unsigned int num_bufs)
+{
+ uint16_t num_enqd, num_deqd, num_total_deqd;
+ unsigned int deqd_retries = 0;
+ int res = 0;
+
+ /* Enqueue and dequeue all operations */
+ num_enqd = rte_compressdev_enqueue_burst(0, 0, ops, num_bufs);
+ if (num_enqd < num_bufs) {
+ RTE_LOG(ERR, USER1,
+ "Some operations could not be enqueued\n");
+ res = -1;
+ }
+
+ /* dequeue ops even on error (same number of ops as was enqueued) */
+
+ num_total_deqd = 0;
+ while (num_total_deqd < num_enqd) {
+ /*
+ * If retrying a dequeue call, wait for 10 ms to allow
+ * enough time to the driver to process the operations
+ */
+ if (deqd_retries != 0) {
+ /*
+ * Avoid infinite loop if not all the
+ * operations get out of the device
+ */
+ if (deqd_retries == MAX_DEQD_RETRIES) {
+ RTE_LOG(ERR, USER1,
+ "Not all operations could be dequeued\n");
+ res = -1;
+ break;
+ }
+ usleep(DEQUEUE_WAIT_TIME);
+ }
+ num_deqd = rte_compressdev_dequeue_burst(0, 0,
+ &ops_processed[num_total_deqd], num_bufs);
+ num_total_deqd += num_deqd;
+ deqd_retries++;
+
+ }
+
+ return res;
+}
+
+/**
+ * Arrays initialization. Input buffers preparation for compression.
+ *
+ * API that initializes all the private arrays to NULL
+ * and allocates input buffers to perform compression operations.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_setup_com_bufs(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ const struct test_private_arrays *test_priv_data)
+{
+ /* local variables: */
+ unsigned int i;
+ uint32_t data_size;
+ char *buf_ptr;
+ int ret;
+ char **all_decomp_data = test_priv_data->all_decomp_data;
+
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+
+ /* from int_data: */
+ const char * const *test_bufs = int_data->test_bufs;
+ unsigned int num_bufs = int_data->num_bufs;
+
+ /* from test_data: */
+ unsigned int buff_type = test_data->buff_type;
+ unsigned int big_data = test_data->big_data;
+
+ /* from test_priv_data: */
+ struct rte_mbuf **uncomp_bufs = test_priv_data->uncomp_bufs;
+ struct rte_mempool *buf_pool;
+
+ static struct rte_mbuf_ext_shared_info inbuf_info;
+
+ size_t array_size = sizeof(void *) * num_bufs;
+
+ /* Initialize all arrays to NULL */
+ memset(test_priv_data->uncomp_bufs, 0, array_size);
+ memset(test_priv_data->comp_bufs, 0, array_size);
+ memset(test_priv_data->ops, 0, array_size);
+ memset(test_priv_data->ops_processed, 0, array_size);
+ memset(test_priv_data->priv_xforms, 0, array_size);
+ memset(test_priv_data->compressed_data_size,
+ 0, sizeof(uint32_t) * num_bufs);
+
+ if (test_data->decompress_state == RTE_COMP_OP_STATEFUL) {
+ data_size = strlen(test_bufs[0]) + 1;
+ *all_decomp_data = rte_malloc(NULL, data_size,
+ RTE_CACHE_LINE_SIZE);
+ }
+
+ if (big_data)
+ buf_pool = ts_params->big_mbuf_pool;
+ else if (buff_type == SGL_BOTH)
+ buf_pool = ts_params->small_mbuf_pool;
+ else
+ buf_pool = ts_params->large_mbuf_pool;
+
+ /* for compression uncomp_bufs is used as a source buffer */
+ /* allocation from buf_pool (mempool type) */
+ ret = rte_pktmbuf_alloc_bulk(buf_pool,
+ uncomp_bufs, num_bufs);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Source mbufs could not be allocated "
+ "from the mempool\n");
+ return -1;
+ }
+
+ if (test_data->use_external_mbufs) {
+ inbuf_info.free_cb = extbuf_free_callback;
+ inbuf_info.fcb_opaque = NULL;
+ rte_mbuf_ext_refcnt_set(&inbuf_info, 1);
+ for (i = 0; i < num_bufs; i++) {
+ rte_pktmbuf_attach_extbuf(uncomp_bufs[i],
+ test_data->inbuf_memzone->addr,
+ test_data->inbuf_memzone->iova,
+ test_data->inbuf_data_size,
+ &inbuf_info);
+ buf_ptr = rte_pktmbuf_append(uncomp_bufs[i],
+ test_data->inbuf_data_size);
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Append extra bytes to the source mbuf failed\n");
+ return -1;
+ }
+ }
+ } else if (buff_type == SGL_BOTH || buff_type == SGL_TO_LB) {
+ for (i = 0; i < num_bufs; i++) {
+ data_size = strlen(test_bufs[i]) + 1;
+ if (prepare_sgl_bufs(test_bufs[i], uncomp_bufs[i],
+ data_size,
+ big_data ? buf_pool : ts_params->small_mbuf_pool,
+ big_data ? buf_pool : ts_params->large_mbuf_pool,
+ big_data ? 0 : MAX_SEGS,
+ big_data ? MAX_DATA_MBUF_SIZE : SMALL_SEG_SIZE) < 0)
+ return -1;
+ }
+ } else {
+ for (i = 0; i < num_bufs; i++) {
+ data_size = strlen(test_bufs[i]) + 1;
+
+ buf_ptr = rte_pktmbuf_append(uncomp_bufs[i], data_size);
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Append extra bytes to the source mbuf failed\n");
+ return -1;
+ }
+ strlcpy(buf_ptr, test_bufs[i], data_size);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Data size calculation (for both compression and decompression).
+ *
+ * Calculate size of anticipated output buffer required for both
+ * compression and decompression operations based on input int_data.
+ *
+ * @param op_type
+ * Operation type: compress or decompress
+ * @param out_of_space_and_zlib
+ * Boolean value to switch into "out of space" buffer if set.
+ * To test "out-of-space" data size, zlib_decompress must be set as well.
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param i
+ * current buffer index
+ * @return
+ * data size
+ */
+static inline uint32_t
+test_mbufs_calculate_data_size(
+ enum operation_type op_type,
+ unsigned int out_of_space_and_zlib,
+ const struct test_private_arrays *test_priv_data,
+ const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ unsigned int i)
+{
+ /* local variables: */
+ uint32_t data_size;
+ struct priv_op_data *priv_data;
+ float ratio_val;
+ enum ratio_switch ratio = test_data->ratio;
+
+ uint8_t not_zlib_compr; /* true if zlib isn't current compression dev */
+ enum overflow_test overflow = test_data->overflow;
+
+ /* from test_priv_data: */
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+
+ /* from int_data: */
+ const char * const *test_bufs = int_data->test_bufs;
+
+ if (out_of_space_and_zlib)
+ data_size = OUT_OF_SPACE_BUF;
+ else {
+ if (op_type == OPERATION_COMPRESSION) {
+ not_zlib_compr = (test_data->zlib_dir == ZLIB_DECOMPRESS
+ || test_data->zlib_dir == ZLIB_NONE);
+
+ ratio_val = (ratio == RATIO_ENABLED) ?
+ COMPRESS_BUF_SIZE_RATIO :
+ COMPRESS_BUF_SIZE_RATIO_DISABLED;
+
+ ratio_val = (not_zlib_compr &&
+ (overflow == OVERFLOW_ENABLED)) ?
+ COMPRESS_BUF_SIZE_RATIO_OVERFLOW :
+ ratio_val;
+
+ data_size = strlen(test_bufs[i]) * ratio_val;
+ } else {
+ priv_data = (struct priv_op_data *)
+ (ops_processed[i] + 1);
+ data_size = strlen(test_bufs[priv_data->orig_idx]) + 1;
+ }
+ }
+
+ return data_size;
+}
+
+
+/**
+ * Memory buffers preparation (for both compression and decompression).
+ *
+ * Function allocates output buffers to perform compression
+ * or decompression operations depending on value of op_type.
+ *
+ * @param op_type
+ * Operation type: compress or decompress
+ * @param out_of_space_and_zlib
+ * Boolean value to switch into "out of space" buffer if set.
+ * To test "out-of-space" data size, zlib_decompress must be set as well.
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param current_extbuf_info,
+ * The structure containing all the information related to external mbufs
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_setup_output_bufs(
+ enum operation_type op_type,
+ unsigned int out_of_space_and_zlib,
+ const struct test_private_arrays *test_priv_data,
+ const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ struct rte_mbuf_ext_shared_info *current_extbuf_info)
+{
+ /* local variables: */
+ unsigned int i;
+ uint32_t data_size;
+ int ret;
+ char *buf_ptr;
+
+ /* from test_priv_data: */
+ struct rte_mbuf **current_bufs;
+
+ /* from int_data: */
+ unsigned int num_bufs = int_data->num_bufs;
+
+ /* from test_data: */
+ unsigned int buff_type = test_data->buff_type;
+ unsigned int big_data = test_data->big_data;
+ const struct rte_memzone *current_memzone;
+
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *buf_pool;
+
+ if (big_data)
+ buf_pool = ts_params->big_mbuf_pool;
+ else if (buff_type == SGL_BOTH)
+ buf_pool = ts_params->small_mbuf_pool;
+ else
+ buf_pool = ts_params->large_mbuf_pool;
+
+ if (op_type == OPERATION_COMPRESSION)
+ current_bufs = test_priv_data->comp_bufs;
+ else
+ current_bufs = test_priv_data->uncomp_bufs;
+
+ /* the mbufs allocation*/
+ ret = rte_pktmbuf_alloc_bulk(buf_pool, current_bufs, num_bufs);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Destination mbufs could not be allocated "
+ "from the mempool\n");
+ return -1;
+ }
+
+ if (test_data->use_external_mbufs) {
+ current_extbuf_info->free_cb = extbuf_free_callback;
+ current_extbuf_info->fcb_opaque = NULL;
+ rte_mbuf_ext_refcnt_set(current_extbuf_info, 1);
+ if (op_type == OPERATION_COMPRESSION)
+ current_memzone = test_data->compbuf_memzone;
+ else
+ current_memzone = test_data->uncompbuf_memzone;
+
+ for (i = 0; i < num_bufs; i++) {
+ rte_pktmbuf_attach_extbuf(current_bufs[i],
+ current_memzone->addr,
+ current_memzone->iova,
+ current_memzone->len,
+ current_extbuf_info);
+ rte_pktmbuf_append(current_bufs[i],
+ current_memzone->len);
+ }
+ } else {
+ for (i = 0; i < num_bufs; i++) {
+
+ enum rte_comp_huffman comp_huffman =
+ ts_params->def_comp_xform->compress.deflate.huffman;
+
+ /* data size calculation */
+ data_size = test_mbufs_calculate_data_size(
+ op_type,
+ out_of_space_and_zlib,
+ test_priv_data,
+ int_data,
+ test_data,
+ i);
+
+ if (comp_huffman != RTE_COMP_HUFFMAN_DYNAMIC) {
+ if (op_type == OPERATION_DECOMPRESSION)
+ data_size *= COMPRESS_BUF_SIZE_RATIO;
+ }
+
+ /* data allocation */
+ if (buff_type == SGL_BOTH || buff_type == LB_TO_SGL) {
+ ret = prepare_sgl_bufs(NULL, current_bufs[i],
+ data_size,
+ big_data ? buf_pool :
+ ts_params->small_mbuf_pool,
+ big_data ? buf_pool :
+ ts_params->large_mbuf_pool,
+ big_data ? 0 : MAX_SEGS,
+ big_data ? MAX_DATA_MBUF_SIZE :
+ SMALL_SEG_SIZE);
+ if (ret < 0)
+ return -1;
+ } else {
+ buf_ptr = rte_pktmbuf_append(current_bufs[i],
+ data_size);
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Append extra bytes to the destination mbuf failed\n");
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * The main compression function.
+ *
+ * Function performs compression operation.
+ * Operation(s) configuration, depending on CLI parameters.
+ * Operation(s) processing.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_deflate_comp_run(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ const struct test_private_arrays *test_priv_data)
+{
+ /* local variables: */
+ struct priv_op_data *priv_data;
+ unsigned int i;
+ uint16_t num_priv_xforms = 0;
+ int ret;
+ int ret_status = 0;
+ char *buf_ptr;
+
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+
+ /* from test_data: */
+ enum rte_comp_op_type operation_type = test_data->compress_state;
+ unsigned int zlib_compress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_COMPRESS);
+
+ /* from int_data: */
+ struct rte_comp_xform **compress_xforms = int_data->compress_xforms;
+ unsigned int num_xforms = int_data->num_xforms;
+ unsigned int num_bufs = int_data->num_bufs;
+
+ /* from test_priv_data: */
+ struct rte_mbuf **comp_bufs = test_priv_data->comp_bufs;
+ struct rte_mbuf **uncomp_bufs = test_priv_data->uncomp_bufs;
+ struct rte_comp_op **ops = test_priv_data->ops;
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+ void **priv_xforms = test_priv_data->priv_xforms;
+
+ const struct rte_compressdev_capabilities *capa =
+ rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+
+ /* Build the compression operations */
+ ret = rte_comp_op_bulk_alloc(ts_params->op_pool, ops, num_bufs);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Compress operations could not be allocated "
+ "from the mempool\n");
+ ret_status = -1;
+ goto exit;
+ }
+
+ for (i = 0; i < num_bufs; i++) {
+ ops[i]->m_src = uncomp_bufs[i];
+ ops[i]->m_dst = comp_bufs[i];
+ ops[i]->src.offset = 0;
+ ops[i]->src.length = rte_pktmbuf_pkt_len(uncomp_bufs[i]);
+ ops[i]->dst.offset = 0;
+
+ RTE_LOG(DEBUG, USER1,
+ "Uncompressed buffer length = %u compressed buffer length = %u",
+ rte_pktmbuf_pkt_len(uncomp_bufs[i]),
+ rte_pktmbuf_pkt_len(comp_bufs[i]));
+
+ if (operation_type == RTE_COMP_OP_STATELESS) {
+ ops[i]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ } else {
+ RTE_LOG(ERR, USER1,
+ "Compression: stateful operations are not "
+ "supported in these tests yet\n");
+ ret_status = -1;
+ goto exit;
+ }
+ ops[i]->input_chksum = 0;
+ /*
+ * Store original operation index in private data,
+ * since ordering does not have to be maintained,
+ * when dequeueing from compressdev, so a comparison
+ * at the end of the test can be done.
+ */
+ priv_data = (struct priv_op_data *) (ops[i] + 1);
+ priv_data->orig_idx = i;
+ }
+
+ /* Compress data (either with Zlib API or compressdev API */
+ if (zlib_compress) {
+ for (i = 0; i < num_bufs; i++) {
+ const struct rte_comp_xform *compress_xform =
+ compress_xforms[i % num_xforms];
+ ret = compress_zlib(ops[i], compress_xform,
+ DEFAULT_MEM_LEVEL);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ ops_processed[i] = ops[i];
+ }
+ } else {
+ /* Create compress private xform data */
+ for (i = 0; i < num_xforms; i++) {
+ ret = rte_compressdev_private_xform_create(0,
+ (const struct rte_comp_xform *)
+ compress_xforms[i],
+ &priv_xforms[i]);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Compression private xform "
+ "could not be created\n");
+ ret_status = -1;
+ goto exit;
+ }
+ num_priv_xforms++;
+ }
+ if (capa->comp_feature_flags &
+ RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
+ /* Attach shareable private xform data to ops */
+ for (i = 0; i < num_bufs; i++)
+ ops[i]->private_xform =
+ priv_xforms[i % num_xforms];
+ } else {
+ /* Create rest of the private xforms for the other ops */
+ for (i = num_xforms; i < num_bufs; i++) {
+ ret = rte_compressdev_private_xform_create(0,
+ compress_xforms[i % num_xforms],
+ &priv_xforms[i]);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Compression private xform "
+ "could not be created\n");
+ ret_status = -1;
+ goto exit;
+ }
+ num_priv_xforms++;
+ }
+ /* Attach non shareable private xform data to ops */
+ for (i = 0; i < num_bufs; i++)
+ ops[i]->private_xform = priv_xforms[i];
+ }
+
+recovery_lb:
+ ret = test_run_enqueue_dequeue(ops, ops_processed, num_bufs);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Compression: enqueue/dequeue operation failed\n");
+ ret_status = -1;
+ goto exit;
+ }
+
+ for (i = 0; i < num_bufs; i++) {
+ test_priv_data->compressed_data_size[i] +=
+ ops_processed[i]->produced;
+
+ if (ops_processed[i]->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE) {
+
+ ops[i]->status =
+ RTE_COMP_OP_STATUS_NOT_PROCESSED;
+ ops[i]->src.offset +=
+ ops_processed[i]->consumed;
+ ops[i]->src.length -=
+ ops_processed[i]->consumed;
+ ops[i]->dst.offset +=
+ ops_processed[i]->produced;
+
+ buf_ptr = rte_pktmbuf_append(
+ ops[i]->m_dst,
+ ops_processed[i]->produced);
+
+ if (buf_ptr == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Data recovery: append extra bytes to the current mbuf failed\n");
+ ret_status = -1;
+ goto exit;
+ }
+ goto recovery_lb;
+ }
+ }
+ }
+
+exit:
+ /* Free resources */
+ if (ret_status < 0)
+ for (i = 0; i < num_bufs; i++) {
+ rte_comp_op_free(ops[i]);
+ ops[i] = NULL;
+ ops_processed[i] = NULL;
+ }
+
+ /* Free compress private xforms */
+ for (i = 0; i < num_priv_xforms; i++) {
+ if (priv_xforms[i] != NULL) {
+ rte_compressdev_private_xform_free(0, priv_xforms[i]);
+ priv_xforms[i] = NULL;
+ }
+ }
+
+ return ret_status;
+}
+
+/**
+ * Prints out the test report. Memory freeing.
+ *
+ * Called after successful compression.
+ * Operation(s) status validation and decompression buffers freeing.
+
+ * -1 returned if function fail.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 2: Some operation is not supported
+ * - 1: Decompression should be skipped
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_deflate_comp_finalize(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ const struct test_private_arrays *test_priv_data)
+{
+ /* local variables: */
+ unsigned int i;
+ struct priv_op_data *priv_data;
+
+ /* from int_data: */
+ unsigned int num_xforms = int_data->num_xforms;
+ struct rte_comp_xform **compress_xforms = int_data->compress_xforms;
+ uint16_t *buf_idx = int_data->buf_idx;
+ unsigned int num_bufs = int_data->num_bufs;
+
+ /* from test_priv_data: */
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+ uint64_t *compress_checksum = test_priv_data->compress_checksum;
+ struct rte_mbuf **uncomp_bufs = test_priv_data->uncomp_bufs;
+ struct rte_comp_op **ops = test_priv_data->ops;
+
+ /* from test_data: */
+ unsigned int out_of_space = test_data->out_of_space;
+ unsigned int zlib_compress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_COMPRESS);
+ unsigned int zlib_decompress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_DECOMPRESS);
+
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
+ uint16_t xform_idx = priv_data->orig_idx % num_xforms;
+ const struct rte_comp_compress_xform *compress_xform =
+ &compress_xforms[xform_idx]->compress;
+ enum rte_comp_huffman huffman_type =
+ compress_xform->deflate.huffman;
+ char engine[] = "zlib (directly, not PMD)";
+ if (zlib_decompress)
+ strlcpy(engine, "PMD", sizeof(engine));
+
+ RTE_LOG(DEBUG, USER1, "Buffer %u compressed by %s from %u to"
+ " %u bytes (level = %d, huffman = %s)\n",
+ buf_idx[priv_data->orig_idx], engine,
+ ops_processed[i]->consumed, ops_processed[i]->produced,
+ compress_xform->level,
+ huffman_type_strings[huffman_type]);
+ RTE_LOG(DEBUG, USER1, "Compression ratio = %.2f\n",
+ ops_processed[i]->consumed == 0 ? 0 :
+ (float)ops_processed[i]->produced /
+ ops_processed[i]->consumed * 100);
+ if (compress_xform->chksum != RTE_COMP_CHECKSUM_NONE)
+ compress_checksum[i] = ops_processed[i]->output_chksum;
+ ops[i] = NULL;
+ }
+
+ /*
+ * Check operation status and free source mbufs (destination mbuf and
+ * compress operation information is needed for the decompression stage)
+ */
+ for (i = 0; i < num_bufs; i++) {
+ if (out_of_space && !zlib_compress) {
+ if (ops_processed[i]->status !=
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
+ RTE_LOG(ERR, USER1,
+ "Operation without expected out of "
+ "space status error\n");
+ return -1;
+ } else
+ continue;
+ }
+
+ if (ops_processed[i]->status != RTE_COMP_OP_STATUS_SUCCESS) {
+ if (test_data->overflow == OVERFLOW_ENABLED) {
+ if (ops_processed[i]->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
+ RTE_LOG(INFO, USER1,
+ "Out-of-space-recoverable functionality"
+ " is not supported on this device\n");
+ return 2;
+ }
+ }
+
+ RTE_LOG(ERR, USER1,
+ "Comp: Some operations were not successful\n");
+ return -1;
+ }
+ priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
+ rte_pktmbuf_free(uncomp_bufs[priv_data->orig_idx]);
+ uncomp_bufs[priv_data->orig_idx] = NULL;
+ }
+
+ if (out_of_space && !zlib_compress)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * The main decompression function.
+ *
+ * Function performs decompression operation.
+ * Operation(s) configuration, depending on CLI parameters.
+ * Operation(s) processing.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_deflate_decomp_run(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ struct test_private_arrays *test_priv_data)
+{
+
+ /* local variables: */
+ struct priv_op_data *priv_data;
+ unsigned int i;
+ uint16_t num_priv_xforms = 0;
+ int ret;
+ int ret_status = 0;
+
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+
+ /* from test_data: */
+ enum rte_comp_op_type operation_type = test_data->decompress_state;
+ unsigned int zlib_decompress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_DECOMPRESS);
+
+ /* from int_data: */
+ struct rte_comp_xform **decompress_xforms = int_data->decompress_xforms;
+ unsigned int num_xforms = int_data->num_xforms;
+ unsigned int num_bufs = int_data->num_bufs;
+
+ /* from test_priv_data: */
+ struct rte_mbuf **uncomp_bufs = test_priv_data->uncomp_bufs;
+ struct rte_mbuf **comp_bufs = test_priv_data->comp_bufs;
+ struct rte_comp_op **ops = test_priv_data->ops;
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+ void **priv_xforms = test_priv_data->priv_xforms;
+ uint32_t *compressed_data_size = test_priv_data->compressed_data_size;
+ void **stream = test_priv_data->stream;
+
+ const struct rte_compressdev_capabilities *capa =
+ rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+
+ ret = rte_comp_op_bulk_alloc(ts_params->op_pool, ops, num_bufs);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Decompress operations could not be allocated "
+ "from the mempool\n");
+ ret_status = -1;
+ goto exit;
+ }
+
+ /* Source buffer is the compressed data from the previous operations */
+ for (i = 0; i < num_bufs; i++) {
+ ops[i]->m_src = comp_bufs[i];
+ ops[i]->m_dst = uncomp_bufs[i];
+ ops[i]->src.offset = 0;
+ /*
+ * Set the length of the compressed data to the
+ * number of bytes that were produced in the previous stage
+ */
+
+ if (compressed_data_size[i])
+ ops[i]->src.length = compressed_data_size[i];
+ else
+ ops[i]->src.length = ops_processed[i]->produced;
+
+ ops[i]->dst.offset = 0;
+
+ if (operation_type == RTE_COMP_OP_STATELESS) {
+ ops[i]->flush_flag = RTE_COMP_FLUSH_FINAL;
+ ops[i]->op_type = RTE_COMP_OP_STATELESS;
+ } else if (!zlib_decompress) {
+ ops[i]->flush_flag = RTE_COMP_FLUSH_SYNC;
+ ops[i]->op_type = RTE_COMP_OP_STATEFUL;
+ } else {
+ RTE_LOG(ERR, USER1,
+ "Decompression: stateful operations are"
+ " not supported in these tests yet\n");
+ ret_status = -1;
+ goto exit;
+ }
+ ops[i]->input_chksum = 0;
+ /*
+ * Copy private data from previous operations,
+ * to keep the pointer to the original buffer
+ */
+ memcpy(ops[i] + 1, ops_processed[i] + 1,
+ sizeof(struct priv_op_data));
+ }
+
+ /*
+ * Free the previous compress operations,
+ * as they are not needed anymore
+ */
+ rte_comp_op_bulk_free(ops_processed, num_bufs);
+
+ /* Decompress data (either with Zlib API or compressdev API */
+ if (zlib_decompress) {
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)(ops[i] + 1);
+ uint16_t xform_idx = priv_data->orig_idx % num_xforms;
+ const struct rte_comp_xform *decompress_xform =
+ decompress_xforms[xform_idx];
+
+ ret = decompress_zlib(ops[i], decompress_xform);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ ops_processed[i] = ops[i];
+ }
+ } else {
+ if (operation_type == RTE_COMP_OP_STATELESS) {
+ /* Create decompress private xform data */
+ for (i = 0; i < num_xforms; i++) {
+ ret = rte_compressdev_private_xform_create(0,
+ (const struct rte_comp_xform *)
+ decompress_xforms[i],
+ &priv_xforms[i]);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Decompression private xform "
+ "could not be created\n");
+ ret_status = -1;
+ goto exit;
+ }
+ num_priv_xforms++;
+ }
+
+ if (capa->comp_feature_flags &
+ RTE_COMP_FF_SHAREABLE_PRIV_XFORM) {
+ /* Attach shareable private xform data to ops */
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)
+ (ops[i] + 1);
+ uint16_t xform_idx =
+ priv_data->orig_idx % num_xforms;
+ ops[i]->private_xform =
+ priv_xforms[xform_idx];
+ }
+ } else {
+ /* Create rest of the private xforms */
+ /* for the other ops */
+ for (i = num_xforms; i < num_bufs; i++) {
+ ret =
+ rte_compressdev_private_xform_create(0,
+ decompress_xforms[i % num_xforms],
+ &priv_xforms[i]);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Decompression private xform"
+ " could not be created\n");
+ ret_status = -1;
+ goto exit;
+ }
+ num_priv_xforms++;
+ }
+
+ /* Attach non shareable private xform data */
+ /* to ops */
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)
+ (ops[i] + 1);
+ uint16_t xform_idx =
+ priv_data->orig_idx;
+ ops[i]->private_xform =
+ priv_xforms[xform_idx];
+ }
+ }
+ } else {
+ /* Create a stream object for stateful decompression */
+ ret = rte_compressdev_stream_create(0,
+ decompress_xforms[0], stream);
+ if (ret < 0) {
+ RTE_LOG(ERR, USER1,
+ "Decompression stream could not be created, error %d\n",
+ ret);
+ ret_status = -1;
+ goto exit;
+ }
+ /* Attach stream to ops */
+ for (i = 0; i < num_bufs; i++)
+ ops[i]->stream = *stream;
+ }
+
+ test_priv_data->num_priv_xforms = num_priv_xforms;
+ }
+
+exit:
+ return ret_status;
+}
+
+/**
+ * Prints out the test report. Memory freeing.
+ *
+ * Called after successful decompression.
+ * Operation(s) status validation and compression buffers freeing.
+
+ * -1 returned if function fail.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 2: Next step must be executed by the caller (stateful decompression only)
+ * - 1: On success (caller should stop and exit)
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_deflate_decomp_finalize(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ const struct test_private_arrays *test_priv_data)
+{
+ /* local variables: */
+ unsigned int i;
+ struct priv_op_data *priv_data;
+ static unsigned int step;
+
+ /* from int_data: */
+ uint16_t *buf_idx = int_data->buf_idx;
+ unsigned int num_bufs = int_data->num_bufs;
+ const char * const *test_bufs = int_data->test_bufs;
+ struct rte_comp_xform **compress_xforms = int_data->compress_xforms;
+
+ /* from test_priv_data: */
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+ struct rte_mbuf **comp_bufs = test_priv_data->comp_bufs;
+ struct rte_comp_op **ops = test_priv_data->ops;
+ uint64_t *compress_checksum = test_priv_data->compress_checksum;
+ unsigned int *decomp_produced_data_size =
+ test_priv_data->decomp_produced_data_size;
+ char **all_decomp_data = test_priv_data->all_decomp_data;
+
+ /* from test_data: */
+ unsigned int out_of_space = test_data->out_of_space;
+ enum rte_comp_op_type operation_type = test_data->decompress_state;
+
+ unsigned int zlib_compress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_COMPRESS);
+ unsigned int zlib_decompress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_DECOMPRESS);
+
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
+ char engine[] = "zlib, (directly, no PMD)";
+ if (zlib_compress)
+ strlcpy(engine, "pmd", sizeof(engine));
+ RTE_LOG(DEBUG, USER1,
+ "Buffer %u decompressed by %s from %u to %u bytes\n",
+ buf_idx[priv_data->orig_idx], engine,
+ ops_processed[i]->consumed, ops_processed[i]->produced);
+ ops[i] = NULL;
+ }
+
+ /*
+ * Check operation status and free source mbuf (destination mbuf and
+ * compress operation information is still needed)
+ */
+ for (i = 0; i < num_bufs; i++) {
+ if (out_of_space && !zlib_decompress) {
+ if (ops_processed[i]->status !=
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED) {
+
+ RTE_LOG(ERR, USER1,
+ "Operation without expected out of "
+ "space status error\n");
+ return -1;
+ } else
+ continue;
+ }
+
+ if (operation_type == RTE_COMP_OP_STATEFUL
+ && (ops_processed[i]->status ==
+ RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE
+ || ops_processed[i]->status ==
+ RTE_COMP_OP_STATUS_SUCCESS)) {
+
+ RTE_LOG(DEBUG, USER1,
+ ".............RECOVERABLE\n");
+
+ /* collect the output into all_decomp_data */
+ const void *ptr = rte_pktmbuf_read(
+ ops_processed[i]->m_dst,
+ ops_processed[i]->dst.offset,
+ ops_processed[i]->produced,
+ *all_decomp_data +
+ *decomp_produced_data_size);
+ if (ptr != *all_decomp_data +
+ *decomp_produced_data_size)
+ rte_memcpy(*all_decomp_data +
+ *decomp_produced_data_size,
+ ptr, ops_processed[i]->produced);
+
+ *decomp_produced_data_size +=
+ ops_processed[i]->produced;
+ if (ops_processed[i]->src.length >
+ ops_processed[i]->consumed) {
+ if (ops_processed[i]->status ==
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Operation finished too early\n");
+ return -1;
+ }
+ step++;
+ if (step >= test_data->decompress_steps_max) {
+ RTE_LOG(ERR, USER1,
+ "Operation exceeded maximum steps\n");
+ return -1;
+ }
+ ops[i] = ops_processed[i];
+ ops[i]->status =
+ RTE_COMP_OP_STATUS_NOT_PROCESSED;
+ ops[i]->src.offset +=
+ ops_processed[i]->consumed;
+ ops[i]->src.length -=
+ ops_processed[i]->consumed;
+ /* repeat the operation */
+ return 2;
+ } else {
+ /* Compare the original stream with the */
+ /* decompressed stream (in size and the data) */
+ priv_data = (struct priv_op_data *)
+ (ops_processed[i] + 1);
+ const char *buf1 =
+ test_bufs[priv_data->orig_idx];
+ const char *buf2 = *all_decomp_data;
+
+ if (compare_buffers(buf1, strlen(buf1) + 1,
+ buf2, *decomp_produced_data_size) < 0)
+ return -1;
+ /* Test checksums */
+ if (compress_xforms[0]->compress.chksum
+ != RTE_COMP_CHECKSUM_NONE) {
+ if (ops_processed[i]->output_chksum
+ != compress_checksum[i]) {
+ RTE_LOG(ERR, USER1,
+ "The checksums differ\n"
+ "Compression Checksum: %" PRIu64 "\tDecompression "
+ "Checksum: %" PRIu64 "\n", compress_checksum[i],
+ ops_processed[i]->output_chksum);
+ return -1;
+ }
+ }
+ }
+ } else if (ops_processed[i]->status !=
+ RTE_COMP_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "Decomp: Some operations were not successful, status = %u\n",
+ ops_processed[i]->status);
+ return -1;
+ }
+ priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
+ rte_pktmbuf_free(comp_bufs[priv_data->orig_idx]);
+ comp_bufs[priv_data->orig_idx] = NULL;
+ }
+
+ if (out_of_space && !zlib_decompress)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * Validation of the output (compression/decompression) data.
+ *
+ * The function compares the source stream with the output stream,
+ * after decompression, to check if compression/decompression
+ * was correct.
+ * -1 returned if function fail.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @param test_priv_data
+ * A container used for aggregation all the private test arrays.
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static int
+test_results_validation(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data,
+ const struct test_private_arrays *test_priv_data)
+{
+ /* local variables: */
+ unsigned int i;
+ struct priv_op_data *priv_data;
+ const char *buf1;
+ const char *buf2;
+ char *contig_buf = NULL;
+ uint32_t data_size;
+
+ /* from int_data: */
+ struct rte_comp_xform **compress_xforms = int_data->compress_xforms;
+ unsigned int num_bufs = int_data->num_bufs;
+ const char * const *test_bufs = int_data->test_bufs;
+
+ /* from test_priv_data: */
+ uint64_t *compress_checksum = test_priv_data->compress_checksum;
+ struct rte_comp_op **ops_processed = test_priv_data->ops_processed;
+
+ /*
+ * Compare the original stream with the decompressed stream
+ * (in size and the data)
+ */
+ for (i = 0; i < num_bufs; i++) {
+ priv_data = (struct priv_op_data *)(ops_processed[i] + 1);
+ buf1 = test_data->use_external_mbufs ?
+ test_data->inbuf_memzone->addr :
+ test_bufs[priv_data->orig_idx];
+ data_size = test_data->use_external_mbufs ?
+ test_data->inbuf_data_size :
+ strlen(buf1) + 1;
+
+ contig_buf = rte_malloc(NULL, ops_processed[i]->produced, 0);
+ if (contig_buf == NULL) {
+ RTE_LOG(ERR, USER1, "Contiguous buffer could not "
+ "be allocated\n");
+ goto exit;
+ }
+
+ buf2 = rte_pktmbuf_read(ops_processed[i]->m_dst, 0,
+ ops_processed[i]->produced, contig_buf);
+ if (compare_buffers(buf1, data_size,
+ buf2, ops_processed[i]->produced) < 0)
+ goto exit;
+
+ /* Test checksums */
+ if (compress_xforms[0]->compress.chksum !=
+ RTE_COMP_CHECKSUM_NONE) {
+ if (ops_processed[i]->output_chksum !=
+ compress_checksum[i]) {
+ RTE_LOG(ERR, USER1, "The checksums differ\n"
+ "Compression Checksum: %" PRIu64 "\tDecompression "
+ "Checksum: %" PRIu64 "\n", compress_checksum[i],
+ ops_processed[i]->output_chksum);
+ goto exit;
+ }
+ }
+
+ rte_free(contig_buf);
+ contig_buf = NULL;
+ }
+ return 0;
+
+exit:
+ rte_free(contig_buf);
+ return -1;
+}
+
+/**
+ * Compresses and decompresses input stream with compressdev API and Zlib API
+ *
+ * Basic test function. Common for all the functional tests.
+ * -1 returned if function fail.
+ *
+ * @param int_data
+ * Interim data containing session/transformation objects.
+ * @param test_data
+ * The test parameters set by users (command line parameters).
+ * @return
+ * - 1: Some operation not supported
+ * - 0: On success.
+ * - -1: On error.
+ */
+
+static int
+test_deflate_comp_decomp(const struct interim_data_params *int_data,
+ const struct test_data_params *test_data)
+{
+ unsigned int num_bufs = int_data->num_bufs;
+ unsigned int out_of_space = test_data->out_of_space;
+
+ void *stream = NULL;
+ char *all_decomp_data = NULL;
+ unsigned int decomp_produced_data_size = 0;
+
+ int ret_status = -1;
+ int ret;
+ struct rte_mbuf *uncomp_bufs[num_bufs];
+ struct rte_mbuf *comp_bufs[num_bufs];
+ struct rte_comp_op *ops[num_bufs];
+ struct rte_comp_op *ops_processed[num_bufs];
+ void *priv_xforms[num_bufs];
+ unsigned int i;
+
+ uint64_t compress_checksum[num_bufs];
+ uint32_t compressed_data_size[num_bufs];
+ char *contig_buf = NULL;
+
+ struct rte_mbuf_ext_shared_info compbuf_info;
+ struct rte_mbuf_ext_shared_info decompbuf_info;
+
+ const struct rte_compressdev_capabilities *capa;
+
+ /* Compressing with CompressDev */
+ unsigned int zlib_compress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_COMPRESS);
+ unsigned int zlib_decompress =
+ (test_data->zlib_dir == ZLIB_ALL ||
+ test_data->zlib_dir == ZLIB_DECOMPRESS);
+
+ struct test_private_arrays test_priv_data;
+
+ test_priv_data.uncomp_bufs = uncomp_bufs;
+ test_priv_data.comp_bufs = comp_bufs;
+ test_priv_data.ops = ops;
+ test_priv_data.ops_processed = ops_processed;
+ test_priv_data.priv_xforms = priv_xforms;
+ test_priv_data.compress_checksum = compress_checksum;
+ test_priv_data.compressed_data_size = compressed_data_size;
+
+ test_priv_data.stream = &stream;
+ test_priv_data.all_decomp_data = &all_decomp_data;
+ test_priv_data.decomp_produced_data_size = &decomp_produced_data_size;
+
+ test_priv_data.num_priv_xforms = 0; /* it's used for deompression only */
+
+ capa = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ if (capa == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress device does not support DEFLATE\n");
+ return -1;
+ }
+
+ /* Prepare the source mbufs with the data */
+ ret = test_setup_com_bufs(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ RTE_LOG(DEBUG, USER1, "<<< COMPRESSION >>>\n");
+
+/* COMPRESSION */
+
+ /* Prepare output (destination) mbufs for compressed data */
+ ret = test_setup_output_bufs(
+ OPERATION_COMPRESSION,
+ out_of_space == 1 && !zlib_compress,
+ &test_priv_data,
+ int_data,
+ test_data,
+ &compbuf_info);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ /* Run compression */
+ ret = test_deflate_comp_run(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ ret = test_deflate_comp_finalize(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ } else if (ret == 1) {
+ ret_status = 0;
+ goto exit;
+ } else if (ret == 2) {
+ ret_status = 1; /* some operation not supported */
+ goto exit;
+ }
+
+/* DECOMPRESSION */
+
+ RTE_LOG(DEBUG, USER1, "<<< DECOMPRESSION >>>\n");
+
+ /* Prepare output (destination) mbufs for decompressed data */
+ ret = test_setup_output_bufs(
+ OPERATION_DECOMPRESSION,
+ out_of_space == 1 && !zlib_decompress,
+ &test_priv_data,
+ int_data,
+ test_data,
+ &decompbuf_info);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ /* Run decompression */
+ ret = test_deflate_decomp_run(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+
+ if (!zlib_decompress) {
+next_step: /* next step for stateful decompression only */
+ ret = test_run_enqueue_dequeue(ops, ops_processed, num_bufs);
+ if (ret < 0) {
+ ret_status = -1;
+ RTE_LOG(ERR, USER1,
+ "Decompression: enqueue/dequeue operation failed\n");
+ }
+ }
+
+ ret = test_deflate_decomp_finalize(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ } else if (ret == 1) {
+ ret_status = 0;
+ goto exit;
+ } else if (ret == 2) {
+ goto next_step;
+ }
+
+/* FINAL PROCESSING */
+
+ ret = test_results_validation(int_data, test_data, &test_priv_data);
+ if (ret < 0) {
+ ret_status = -1;
+ goto exit;
+ }
+ ret_status = 0;
+
+exit:
+ /* Free resources */
+
+ if (stream != NULL)
+ rte_compressdev_stream_free(0, stream);
+ if (all_decomp_data != NULL)
+ rte_free(all_decomp_data);
+
+ /* Free compress private xforms */
+ for (i = 0; i < test_priv_data.num_priv_xforms; i++) {
+ if (priv_xforms[i] != NULL) {
+ rte_compressdev_private_xform_free(0, priv_xforms[i]);
+ priv_xforms[i] = NULL;
+ }
+ }
+ for (i = 0; i < num_bufs; i++) {
+ rte_pktmbuf_free(uncomp_bufs[i]);
+ rte_pktmbuf_free(comp_bufs[i]);
+ rte_comp_op_free(ops[i]);
+ rte_comp_op_free(ops_processed[i]);
+ }
+ rte_free(contig_buf);
+
+ return ret_status;
+}
+
+static int
+test_compressdev_deflate_stateless_fixed(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i;
+ int ret;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_FIXED) == 0)
+ return -ENOTSUP;
+
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+ compress_xform->compress.deflate.huffman = RTE_COMP_HUFFMAN_FIXED;
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &compress_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_dynamic(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i;
+ int ret;
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+ compress_xform->compress.deflate.huffman = RTE_COMP_HUFFMAN_DYNAMIC;
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &compress_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_multi_op(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t num_bufs = RTE_DIM(compress_test_bufs);
+ uint16_t buf_idx[num_bufs];
+ uint16_t i;
+ int ret;
+
+ for (i = 0; i < num_bufs; i++)
+ buf_idx[i] = i;
+
+ struct interim_data_params int_data = {
+ compress_test_bufs,
+ num_bufs,
+ buf_idx,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_compressdev_deflate_stateless_multi_level(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ unsigned int level;
+ uint16_t i;
+ int ret;
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &compress_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ for (level = RTE_COMP_LEVEL_MIN; level <= RTE_COMP_LEVEL_MAX;
+ level++) {
+ compress_xform->compress.level = level;
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ return ret;
+}
+
+#define NUM_XFORMS 3
+static int
+test_compressdev_deflate_stateless_multi_xform(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t num_bufs = NUM_XFORMS;
+ struct rte_comp_xform *compress_xforms[NUM_XFORMS] = {NULL};
+ struct rte_comp_xform *decompress_xforms[NUM_XFORMS] = {NULL};
+ const char *test_buffers[NUM_XFORMS];
+ uint16_t i;
+ unsigned int level = RTE_COMP_LEVEL_MIN;
+ uint16_t buf_idx[num_bufs];
+ int ret;
+
+ /* Create multiple xforms with various levels */
+ for (i = 0; i < NUM_XFORMS; i++) {
+ compress_xforms[i] = rte_malloc(NULL,
+ sizeof(struct rte_comp_xform), 0);
+ if (compress_xforms[i] == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(compress_xforms[i], ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+ compress_xforms[i]->compress.level = level;
+ level++;
+
+ decompress_xforms[i] = rte_malloc(NULL,
+ sizeof(struct rte_comp_xform), 0);
+ if (decompress_xforms[i] == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Decompress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(decompress_xforms[i], ts_params->def_decomp_xform,
+ sizeof(struct rte_comp_xform));
+ }
+
+ for (i = 0; i < NUM_XFORMS; i++) {
+ buf_idx[i] = 0;
+ /* Use the same buffer in all sessions */
+ test_buffers[i] = compress_test_bufs[0];
+ }
+
+ struct interim_data_params int_data = {
+ test_buffers,
+ num_bufs,
+ buf_idx,
+ compress_xforms,
+ decompress_xforms,
+ NUM_XFORMS
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ /* Compress with compressdev, decompress with Zlib */
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ ret = TEST_SUCCESS;
+
+exit:
+ for (i = 0; i < NUM_XFORMS; i++) {
+ rte_free(compress_xforms[i]);
+ rte_free(decompress_xforms[i]);
+ }
+
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_sgl(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i;
+ int ret;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ if (capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_LB_OUT) {
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ test_data.buff_type = SGL_TO_LB;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ test_data.buff_type = SGL_TO_LB;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (capab->comp_feature_flags & RTE_COMP_FF_OOP_LB_IN_SGL_OUT) {
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ test_data.buff_type = LB_TO_SGL;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ test_data.buff_type = LB_TO_SGL;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_compressdev_deflate_stateless_checksum(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i;
+ int ret;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ /* Check if driver supports any checksum */
+ if ((capab->comp_feature_flags & RTE_COMP_FF_CRC32_CHECKSUM) == 0 &&
+ (capab->comp_feature_flags &
+ RTE_COMP_FF_ADLER32_CHECKSUM) == 0 &&
+ (capab->comp_feature_flags &
+ RTE_COMP_FF_CRC32_ADLER32_CHECKSUM) == 0)
+ return -ENOTSUP;
+
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1, "Compress xform could not be created\n");
+ return TEST_FAILED;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+
+ struct rte_comp_xform *decompress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (decompress_xform == NULL) {
+ RTE_LOG(ERR, USER1, "Decompress xform could not be created\n");
+ rte_free(compress_xform);
+ return TEST_FAILED;
+ }
+
+ memcpy(decompress_xform, ts_params->def_decomp_xform,
+ sizeof(struct rte_comp_xform));
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &compress_xform,
+ &decompress_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ /* Check if driver supports crc32 checksum and test */
+ if ((capab->comp_feature_flags & RTE_COMP_FF_CRC32_CHECKSUM)) {
+ compress_xform->compress.chksum = RTE_COMP_CHECKSUM_CRC32;
+ decompress_xform->decompress.chksum = RTE_COMP_CHECKSUM_CRC32;
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ /* Compress with compressdev, decompress with Zlib */
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Generate zlib checksum and test against selected
+ * drivers decompression checksum
+ */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Generate compression and decompression
+ * checksum of selected driver
+ */
+ test_data.zlib_dir = ZLIB_NONE;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+ }
+
+ /* Check if driver supports adler32 checksum and test */
+ if ((capab->comp_feature_flags & RTE_COMP_FF_ADLER32_CHECKSUM)) {
+ compress_xform->compress.chksum = RTE_COMP_CHECKSUM_ADLER32;
+ decompress_xform->decompress.chksum = RTE_COMP_CHECKSUM_ADLER32;
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Generate zlib checksum and test against selected
+ * drivers decompression checksum
+ */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ /* Generate compression and decompression
+ * checksum of selected driver
+ */
+ test_data.zlib_dir = ZLIB_NONE;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+ }
+
+ /* Check if driver supports combined crc and adler checksum and test */
+ if ((capab->comp_feature_flags & RTE_COMP_FF_CRC32_ADLER32_CHECKSUM)) {
+ compress_xform->compress.chksum =
+ RTE_COMP_CHECKSUM_CRC32_ADLER32;
+ decompress_xform->decompress.chksum =
+ RTE_COMP_CHECKSUM_CRC32_ADLER32;
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Generate compression and decompression
+ * checksum of selected driver
+ */
+ test_data.zlib_dir = ZLIB_NONE;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ rte_free(decompress_xform);
+ return ret;
+}
+
+static int
+test_compressdev_out_of_space_buffer(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ int ret;
+ uint16_t i;
+ const struct rte_compressdev_capabilities *capab;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_FIXED) == 0)
+ return -ENOTSUP;
+
+ struct interim_data_params int_data = {
+ &compress_test_bufs[0],
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 1, /* run out-of-space test */
+ .big_data = 0,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ if (capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) {
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ test_data.buff_type = SGL_BOTH;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ test_data.buff_type = SGL_BOTH;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_dynamic_big(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret;
+ unsigned int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, BIG_DATA_TEST_SIZE, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ struct interim_data_params int_data = {
+ (const char * const *)&test_buffer,
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(BIG_DATA_TEST_SIZE);
+ for (j = 0; j < BIG_DATA_TEST_SIZE - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+ test_buffer[BIG_DATA_TEST_SIZE - 1] = 0;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ ret = test_deflate_comp_decomp(&int_data, &test_data);
+ if (ret < 0)
+ goto exit;
+
+ ret = TEST_SUCCESS;
+
+exit:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateful_decomp(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ int ret;
+ uint16_t i;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if (!(capab->comp_feature_flags & RTE_COMP_FF_STATEFUL_DECOMPRESSION))
+ return -ENOTSUP;
+
+ struct interim_data_params int_data = {
+ &compress_test_bufs[0],
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATEFUL,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_COMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .decompress_output_block_size = 2000,
+ .decompress_steps_max = 4,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ /* Compress with Zlib, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ if (capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) {
+ /* Now test with SGL buffers */
+ test_data.buff_type = SGL_BOTH;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateful_decomp_checksum(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ int ret;
+ uint16_t i;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if (!(capab->comp_feature_flags & RTE_COMP_FF_STATEFUL_DECOMPRESSION))
+ return -ENOTSUP;
+
+ /* Check if driver supports any checksum */
+ if (!(capab->comp_feature_flags &
+ (RTE_COMP_FF_CRC32_CHECKSUM | RTE_COMP_FF_ADLER32_CHECKSUM |
+ RTE_COMP_FF_CRC32_ADLER32_CHECKSUM)))
+ return -ENOTSUP;
+
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1, "Compress xform could not be created\n");
+ return TEST_FAILED;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+
+ struct rte_comp_xform *decompress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+ if (decompress_xform == NULL) {
+ RTE_LOG(ERR, USER1, "Decompress xform could not be created\n");
+ rte_free(compress_xform);
+ return TEST_FAILED;
+ }
+
+ memcpy(decompress_xform, ts_params->def_decomp_xform,
+ sizeof(struct rte_comp_xform));
+
+ struct interim_data_params int_data = {
+ &compress_test_bufs[0],
+ 1,
+ &i,
+ &compress_xform,
+ &decompress_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATEFUL,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_COMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .decompress_output_block_size = 2000,
+ .decompress_steps_max = 4,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ /* Check if driver supports crc32 checksum and test */
+ if (capab->comp_feature_flags & RTE_COMP_FF_CRC32_CHECKSUM) {
+ compress_xform->compress.chksum = RTE_COMP_CHECKSUM_CRC32;
+ decompress_xform->decompress.chksum = RTE_COMP_CHECKSUM_CRC32;
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.buff_type = LB_BOTH;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ if (capab->comp_feature_flags &
+ RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) {
+ /* Now test with SGL buffers */
+ test_data.buff_type = SGL_BOTH;
+ if (test_deflate_comp_decomp(&int_data,
+ &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ }
+ }
+
+ /* Check if driver supports adler32 checksum and test */
+ if (capab->comp_feature_flags & RTE_COMP_FF_ADLER32_CHECKSUM) {
+ compress_xform->compress.chksum = RTE_COMP_CHECKSUM_ADLER32;
+ decompress_xform->decompress.chksum = RTE_COMP_CHECKSUM_ADLER32;
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.buff_type = LB_BOTH;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ if (capab->comp_feature_flags &
+ RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) {
+ /* Now test with SGL buffers */
+ test_data.buff_type = SGL_BOTH;
+ if (test_deflate_comp_decomp(&int_data,
+ &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ }
+ }
+
+ /* Check if driver supports combined crc and adler checksum and test */
+ if (capab->comp_feature_flags & RTE_COMP_FF_CRC32_ADLER32_CHECKSUM) {
+ compress_xform->compress.chksum =
+ RTE_COMP_CHECKSUM_CRC32_ADLER32;
+ decompress_xform->decompress.chksum =
+ RTE_COMP_CHECKSUM_CRC32_ADLER32;
+ /* Zlib doesn't support combined checksum */
+ test_data.zlib_dir = ZLIB_NONE;
+ /* Compress stateless, decompress stateful with compressdev */
+ test_data.buff_type = LB_BOTH;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ if (capab->comp_feature_flags &
+ RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) {
+ /* Now test with SGL buffers */
+ test_data.buff_type = SGL_BOTH;
+ if (test_deflate_comp_decomp(&int_data,
+ &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ }
+ }
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ rte_free(decompress_xform);
+ return ret;
+}
+
+static const struct rte_memzone *
+make_memzone(const char *name, size_t size)
+{
+ unsigned int socket_id = rte_socket_id();
+ char mz_name[RTE_MEMZONE_NAMESIZE];
+ const struct rte_memzone *memzone;
+
+ snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "%s_%u", name, socket_id);
+ memzone = rte_memzone_lookup(mz_name);
+ if (memzone != NULL && memzone->len != size) {
+ rte_memzone_free(memzone);
+ memzone = NULL;
+ }
+ if (memzone == NULL) {
+ memzone = rte_memzone_reserve_aligned(mz_name, size, socket_id,
+ RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE);
+ if (memzone == NULL)
+ RTE_LOG(ERR, USER1, "Can't allocate memory zone %s",
+ mz_name);
+ }
+ return memzone;
+}
+
+static int
+test_compressdev_external_mbufs(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ size_t data_len = 0;
+ uint16_t i;
+ int ret = TEST_FAILED;
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++)
+ data_len = RTE_MAX(data_len, strlen(compress_test_bufs[i]) + 1);
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .use_external_mbufs = 1,
+ .inbuf_data_size = data_len,
+ .inbuf_memzone = make_memzone("inbuf", data_len),
+ .compbuf_memzone = make_memzone("compbuf", data_len *
+ COMPRESS_BUF_SIZE_RATIO),
+ .uncompbuf_memzone = make_memzone("decompbuf", data_len),
+ .overflow = OVERFLOW_DISABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ /* prepare input data */
+ data_len = strlen(compress_test_bufs[i]) + 1;
+ rte_memcpy(test_data.inbuf_memzone->addr, compress_test_bufs[i],
+ data_len);
+ test_data.inbuf_data_size = data_len;
+ int_data.buf_idx = &i;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0)
+ goto exit;
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0)
+ goto exit;
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_memzone_free(test_data.inbuf_memzone);
+ rte_memzone_free(test_data.compbuf_memzone);
+ rte_memzone_free(test_data.uncompbuf_memzone);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_stateless_fixed_oos_recoverable(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i;
+ int ret;
+ int comp_result;
+ const struct rte_compressdev_capabilities *capab;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_FIXED) == 0)
+ return -ENOTSUP;
+
+ struct rte_comp_xform *compress_xform =
+ rte_malloc(NULL, sizeof(struct rte_comp_xform), 0);
+
+ if (compress_xform == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Compress xform could not be created\n");
+ ret = TEST_FAILED;
+ goto exit;
+ }
+
+ memcpy(compress_xform, ts_params->def_comp_xform,
+ sizeof(struct rte_comp_xform));
+ compress_xform->compress.deflate.huffman = RTE_COMP_HUFFMAN_FIXED;
+
+ struct interim_data_params int_data = {
+ NULL,
+ 1,
+ NULL,
+ &compress_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_DECOMPRESS,
+ .out_of_space = 0,
+ .big_data = 0,
+ .overflow = OVERFLOW_ENABLED,
+ .ratio = RATIO_ENABLED
+ };
+
+ for (i = 0; i < RTE_DIM(compress_test_bufs); i++) {
+ int_data.test_bufs = &compress_test_bufs[i];
+ int_data.buf_idx = &i;
+
+ /* Compress with compressdev, decompress with Zlib */
+ test_data.zlib_dir = ZLIB_DECOMPRESS;
+ comp_result = test_deflate_comp_decomp(&int_data, &test_data);
+ if (comp_result < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ } else if (comp_result > 0) {
+ ret = -ENOTSUP;
+ goto exit;
+ }
+
+ /* Compress with Zlib, decompress with compressdev */
+ test_data.zlib_dir = ZLIB_COMPRESS;
+ comp_result = test_deflate_comp_decomp(&int_data, &test_data);
+ if (comp_result < 0) {
+ ret = TEST_FAILED;
+ goto exit;
+ } else if (comp_result > 0) {
+ ret = -ENOTSUP;
+ goto exit;
+ }
+ }
+
+ ret = TEST_SUCCESS;
+
+exit:
+ rte_free(compress_xform);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_LB_1op(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_LB, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for 'im buffer' test\n");
+ return TEST_FAILED;
+ }
+
+ struct interim_data_params int_data = {
+ (const char * const *)&test_buffer,
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ /* must be LB to SGL,
+ * input LB buffer reaches its maximum,
+ * if ratio 1.3 than another mbuf must be
+ * created and attached
+ */
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_LB);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_LB - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_LB_2ops_first(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_LB, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for 'im buffer' test\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = test_buffer;
+ test_buffers[1] = compress_test_bufs[0];
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_LB);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_LB - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_LB_2ops_second(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_LB, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for 'im buffer' test\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_LB);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_LB - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_LB_3ops(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[3];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_LB, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for 'im buffer' test\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+ test_buffers[2] = compress_test_bufs[1];
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 3,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_LB);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_LB - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_LB_4ops(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[4];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_LB, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for 'im buffer' test\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+ test_buffers[2] = compress_test_bufs[1];
+ test_buffers[3] = test_buffer;
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 4,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = LB_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_LB);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_LB - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+
+static int
+test_compressdev_deflate_im_buffers_SGL_1op(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_SGL, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ struct interim_data_params int_data = {
+ (const char * const *)&test_buffer,
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_SGL);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_SGL - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_SGL_2ops_first(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_SGL, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = test_buffer;
+ test_buffers[1] = compress_test_bufs[0];
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_SGL);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_SGL - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_SGL_2ops_second(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_SGL, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_SGL);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_SGL - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_SGL_3ops(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[3];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_SGL, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+ test_buffers[2] = compress_test_bufs[1];
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 3,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_SGL);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_SGL - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+
+static int
+test_compressdev_deflate_im_buffers_SGL_4ops(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[4];
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_SGL, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+ test_buffers[2] = compress_test_bufs[1];
+ test_buffers[3] = test_buffer;
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 4,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_SGL);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_SGL - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_SGL_over_1op(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_OVER, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ struct interim_data_params int_data = {
+ (const char * const *)&test_buffer,
+ 1,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_OVER);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_OVER - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_SUCCESS;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+
+ return ret;
+}
+
+
+static int
+test_compressdev_deflate_im_buffers_SGL_over_2ops_first(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_OVER, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = test_buffer;
+ test_buffers[1] = compress_test_bufs[0];
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_OVER);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_OVER - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_SUCCESS;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static int
+test_compressdev_deflate_im_buffers_SGL_over_2ops_second(void)
+{
+ struct comp_testsuite_params *ts_params = &testsuite_params;
+ uint16_t i = 0;
+ int ret = TEST_SUCCESS;
+ int j;
+ const struct rte_compressdev_capabilities *capab;
+ char *test_buffer = NULL;
+ const char *test_buffers[2];
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+
+ capab = rte_compressdev_capability_get(0, RTE_COMP_ALGO_DEFLATE);
+ TEST_ASSERT(capab != NULL, "Failed to retrieve device capabilities");
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_HUFFMAN_DYNAMIC) == 0)
+ return -ENOTSUP;
+
+ if ((capab->comp_feature_flags & RTE_COMP_FF_OOP_SGL_IN_SGL_OUT) == 0)
+ return -ENOTSUP;
+
+ test_buffer = rte_malloc(NULL, IM_BUF_DATA_TEST_SIZE_OVER, 0);
+ if (test_buffer == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't allocate buffer for big-data\n");
+ return TEST_FAILED;
+ }
+
+ test_buffers[0] = compress_test_bufs[0];
+ test_buffers[1] = test_buffer;
+
+ struct interim_data_params int_data = {
+ (const char * const *)test_buffers,
+ 2,
+ &i,
+ &ts_params->def_comp_xform,
+ &ts_params->def_decomp_xform,
+ 1
+ };
+
+ struct test_data_params test_data = {
+ .compress_state = RTE_COMP_OP_STATELESS,
+ .decompress_state = RTE_COMP_OP_STATELESS,
+ .buff_type = SGL_BOTH,
+ .zlib_dir = ZLIB_NONE,
+ .out_of_space = 0,
+ .big_data = 1,
+ .overflow = OVERFLOW_DISABLED,
+ .ratio = RATIO_DISABLED
+ };
+
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DYNAMIC;
+
+ /* fill the buffer with data based on rand. data */
+ srand(IM_BUF_DATA_TEST_SIZE_OVER);
+ for (j = 0; j < IM_BUF_DATA_TEST_SIZE_OVER - 1; ++j)
+ test_buffer[j] = (uint8_t)(rand() % ((uint8_t)-1)) | 1;
+
+ /* Compress with compressdev, decompress with compressdev */
+ if (test_deflate_comp_decomp(&int_data, &test_data) < 0) {
+ ret = TEST_SUCCESS;
+ goto end;
+ }
+
+end:
+ ts_params->def_comp_xform->compress.deflate.huffman =
+ RTE_COMP_HUFFMAN_DEFAULT;
+ rte_free(test_buffer);
+ return ret;
+}
+
+static struct unit_test_suite compressdev_testsuite = {
+ .suite_name = "compressdev unit test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(NULL, NULL,
+ test_compressdev_invalid_configuration),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_fixed),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_dynamic),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_dynamic_big),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_multi_op),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_multi_level),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_multi_xform),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_sgl),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_checksum),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_out_of_space_buffer),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateful_decomp),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateful_decomp_checksum),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_external_mbufs),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_stateless_fixed_oos_recoverable),
+
+ /* Positive test cases for IM buffer handling verification */
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_LB_1op),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_LB_2ops_first),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_LB_2ops_second),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_LB_3ops),
+
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_LB_4ops),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_1op),
+
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_2ops_first),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_2ops_second),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_3ops),
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_4ops),
+
+ /* Negative test cases for IM buffer handling verification */
+
+ /* For this test huge mempool is necessary.
+ * It tests one case:
+ * only one op containing big amount of data, so that
+ * number of requested descriptors higher than number
+ * of available descriptors (128)
+ */
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_over_1op),
+
+ /* For this test huge mempool is necessary.
+ * 2 ops. First op contains big amount of data:
+ * number of requested descriptors higher than number
+ * of available descriptors (128), the second op is
+ * relatively small. In this case both ops are rejected
+ */
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_over_2ops_first),
+
+ TEST_CASE_ST(generic_ut_setup, generic_ut_teardown,
+ test_compressdev_deflate_im_buffers_SGL_over_2ops_second),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_compressdev(void)
+{
+ return unit_test_suite_runner(&compressdev_testsuite);
+}
+
+REGISTER_TEST_COMMAND(compressdev_autotest, test_compressdev);
diff --git a/src/spdk/dpdk/app/test/test_compressdev_test_buffer.h b/src/spdk/dpdk/app/test/test_compressdev_test_buffer.h
new file mode 100644
index 000000000..4a16ade15
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_compressdev_test_buffer.h
@@ -0,0 +1,297 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2020 Intel Corporation
+ */
+
+#ifndef TEST_COMPRESSDEV_TEST_BUFFERS_H_
+#define TEST_COMPRESSDEV_TEST_BUFFERS_H_
+
+/*
+ * These test buffers are snippets obtained
+ * from the Canterbury and Calgary Corpus
+ * collection.
+ */
+
+/* Snippet of Alice's Adventures in Wonderland */
+static const char test_buf_alice[] =
+ " Alice was beginning to get very tired of sitting by her sister\n"
+ "on the bank, and of having nothing to do: once or twice she had\n"
+ "peeped into the book her sister was reading, but it had no\n"
+ "pictures or conversations in it, `and what is the use of a book,'\n"
+ "thought Alice `without pictures or conversation?'\n\n"
+ " So she was considering in her own mind (as well as she could,\n"
+ "for the hot day made her feel very sleepy and stupid), whether\n"
+ "the pleasure of making a daisy-chain would be worth the trouble\n"
+ "of getting up and picking the daisies, when suddenly a White\n"
+ "Rabbit with pink eyes ran close by her.\n\n"
+ " There was nothing so VERY remarkable in that; nor did Alice\n"
+ "think it so VERY much out of the way to hear the Rabbit say to\n"
+ "itself, `Oh dear! Oh dear! I shall be late!' (when she thought\n"
+ "it over afterwards, it occurred to her that she ought to have\n"
+ "wondered at this, but at the time it all seemed quite natural);\n"
+ "but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-\n"
+ "POCKET, and looked at it, and then hurried on, Alice started to\n"
+ "her feet, for it flashed across her mind that she had never\n"
+ "before seen a rabbit with either a waistcoat-pocket, or a watch to\n"
+ "take out of it, and burning with curiosity, she ran across the\n"
+ "field after it, and fortunately was just in time to see it pop\n"
+ "down a large rabbit-hole under the hedge.\n\n"
+ " In another moment down went Alice after it, never once\n"
+ "considering how in the world she was to get out again.\n\n"
+ " The rabbit-hole went straight on like a tunnel for some way,\n"
+ "and then dipped suddenly down, so suddenly that Alice had not a\n"
+ "moment to think about stopping herself before she found herself\n"
+ "falling down a very deep well.\n\n"
+ " Either the well was very deep, or she fell very slowly, for she\n"
+ "had plenty of time as she went down to look about her and to\n"
+ "wonder what was going to happen next. First, she tried to look\n"
+ "down and make out what she was coming to, but it was too dark to\n"
+ "see anything; then she looked at the sides of the well, and\n"
+ "noticed that they were filled with cupboards and book-shelves;\n"
+ "here and there she saw maps and pictures hung upon pegs. She\n"
+ "took down a jar from one of the shelves as she passed; it was\n"
+ "labelled `ORANGE MARMALADE', but to her great disappointment it\n"
+ "was empty: she did not like to drop the jar for fear of killing\n"
+ "somebody, so managed to put it into one of the cupboards as she\n"
+ "fell past it.\n\n"
+ " `Well!' thought Alice to herself, `after such a fall as this, I\n"
+ "shall think nothing of tumbling down stairs! How brave they'll\n"
+ "all think me at home! Why, I wouldn't say anything about it,\n"
+ "even if I fell off the top of the house!' (Which was very likely\n"
+ "true.)\n\n"
+ " Down, down, down. Would the fall NEVER come to an end! `I\n"
+ "wonder how many miles I've fallen by this time?' she said aloud.\n"
+ "`I must be getting somewhere near the centre of the earth. Let\n"
+ "me see: that would be four thousand miles down, I think--' (for,\n"
+ "you see, Alice had learnt several things of this sort in her\n"
+ "lessons in the schoolroom, and though this was not a VERY good\n"
+ "opportunity for showing off her knowledge, as there was no one to\n"
+ "listen to her, still it was good practice to say it over) `--yes,\n"
+ "that's about the right distance--but then I wonder what Latitude\n"
+ "or Longitude I've got to?' (Alice had no idea what Latitude was,\n"
+ "or Longitude either, but thought they were nice grand words to\n"
+ "say.)\n\n"
+ " Presently she began again. `I wonder if I shall fall right\n"
+ "THROUGH the earth! How funny it'll seem to come out among the\n"
+ "people that walk with their heads downward! The Antipathies, I\n"
+ "think--' (she was rather glad there WAS no one listening, this\n"
+ "time, as it didn't sound at all the right word) `--but I shall\n"
+ "have to ask them what the name of the country is, you know.\n"
+ "Please, Ma'am, is this New Zealand or Australia?' (and she tried\n"
+ "to curtsey as she spoke--fancy CURTSEYING as you're falling\n"
+ "through the air! Do you think you could manage it?) `And what\n"
+ "an ignorant little girl she'll think me for asking! No, it'll\n"
+ "never do to ask: perhaps I shall see it written up somewhere.'\n"
+ " Down, down, down. There was nothing else to do, so Alice soon\n"
+ "began talking again. `Dinah'll miss me very much to-night, I\n"
+ "should think!' (Dinah was the cat.) `I hope they'll remember\n"
+ "her saucer of milk at tea-time. Dinah my dear! I wish you were\n"
+ "down here with me! There are no mice in the air, I'm afraid, but\n"
+ "you might catch a bat, and that's very like a mouse, you know.\n"
+ "But do cats eat bats, I wonder?' And here Alice began to get\n"
+ "rather sleepy, and went on saying to herself, in a dreamy sort of\n"
+ "way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do\n"
+ "bats eat cats?' for, you see, as she couldn't answer either\n"
+ "question, it didn't much matter which way she put it. She felt\n"
+ "that she was dozing off, and had just begun to dream that she\n"
+ "was walking hand in hand with Dinah, and saying to her very\n"
+ "earnestly, `Now, Dinah, tell me the truth: did you ever eat a\n"
+ "bat?' when suddenly, thump! thump! down she came upon a heap of\n"
+ "sticks and dry leaves, and the fall was over.\n\n";
+
+/* Snippet of Shakespeare play */
+static const char test_buf_shakespeare[] =
+ "CHARLES wrestler to Frederick.\n"
+ "\n"
+ "\n"
+ "OLIVER |\n"
+ " |\n"
+ "JAQUES (JAQUES DE BOYS:) | sons of Sir Rowland de Boys.\n"
+ " |\n"
+ "ORLANDO |\n"
+ "\n"
+ "\n"
+ "ADAM |\n"
+ " | servants to Oliver.\n"
+ "DENNIS |\n"
+ "\n"
+ "\n"
+ "TOUCHSTONE a clown.\n"
+ "\n"
+ "SIR OLIVER MARTEXT a vicar.\n"
+ "\n"
+ "\n"
+ "CORIN |\n"
+ " | shepherds.\n"
+ "SILVIUS |\n"
+ "\n"
+ "\n"
+ "WILLIAM a country fellow in love with Audrey.\n"
+ "\n"
+ " A person representing HYMEN. (HYMEN:)\n"
+ "\n"
+ "ROSALIND daughter to the banished duke.\n"
+ "\n"
+ "CELIA daughter to Frederick.\n"
+ "\n"
+ "PHEBE a shepherdess.\n"
+ "\n"
+ "AUDREY a country wench.\n"
+ "\n"
+ " Lords, pages, and attendants, &c.\n"
+ " (Forester:)\n"
+ " (A Lord:)\n"
+ " (First Lord:)\n"
+ " (Second Lord:)\n"
+ " (First Page:)\n"
+ " (Second Page:)\n"
+ "\n"
+ "\n"
+ "SCENE Oliver's house; Duke Frederick's court; and the\n"
+ " Forest of Arden.\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ " AS YOU LIKE IT\n"
+ "\n"
+ "\n"
+ "ACT I\n"
+ "\n"
+ "\n"
+ "\n"
+ "SCENE I Orchard of Oliver's house.\n"
+ "\n"
+ "\n"
+ " [Enter ORLANDO and ADAM]\n"
+ "\n"
+ "ORLANDO As I remember, Adam, it was upon this fashion\n"
+ " bequeathed me by will but poor a thousand crowns,\n"
+ " and, as thou sayest, charged my brother, on his\n"
+ " blessing, to breed me well: and there begins my\n"
+ " sadness. My brother Jaques he keeps at school, and\n"
+ " report speaks goldenly of his profit: for my part,\n"
+ " he keeps me rustically at home, or, to speak more\n"
+ " properly, stays me here at home unkept; for call you\n"
+ " that keeping for a gentleman of my birth, that\n"
+ " differs not from the stalling of an ox? His horses\n"
+ " are bred better; for, besides that they are fair\n"
+ " with their feeding, they are taught their manage,\n"
+ " and to that end riders dearly hired: but I, his\n"
+ " brother, gain nothing under him but growth; for the\n"
+ " which his animals on his dunghills are as much\n"
+ " bound to him as I. Besides this nothing that he so\n"
+ " plentifully gives me, the something that nature gave\n"
+ " me his countenance seems to take from me: he lets\n"
+ " me feed with his hinds, bars me the place of a\n"
+ " brother, and, as much as in him lies, mines my\n"
+ " gentility with my education. This is it, Adam, that\n"
+ " grieves me; and the spirit of my father, which I\n"
+ " think is within me, begins to mutiny against this\n"
+ " servitude: I will no longer endure it, though yet I\n"
+ " know no wise remedy how to avoid it.\n"
+ "\n"
+ "ADAM Yonder comes my master, your brother.\n"
+ "\n"
+ "ORLANDO Go apart, Adam, and thou shalt hear how he will\n";
+
+/* Snippet of Alice's Adventures in Wonderland */
+static const char test_buf_alice2[] =
+ "`Curiouser and curiouser!' cried Alice (she was so much\n"
+ "surprised, that for the moment she quite forgot how to speak good\n"
+ "English); `now I'm opening out like the largest telescope that\n"
+ "ever was! Good-bye, feet!' (for when she looked down at her\n"
+ "feet, they seemed to be almost out of sight, they were getting so\n"
+ "far off). `Oh, my poor little feet, I wonder who will put on\n"
+ "your shoes and stockings for you now, dears? I'm sure _I_ shan't\n"
+ "be able! I shall be a great deal too far off to trouble myself\n"
+ "about you: you must manage the best way you can; --but I must be\n"
+ "kind to them,' thought Alice, `or perhaps they won't walk the\n"
+ "way I want to go! Let me see: I'll give them a new pair of\n"
+ "boots every Christmas.'\n"
+ "\n"
+ " And she went on planning to herself how she would manage it.\n"
+ "`They must go by the carrier,' she thought; `and how funny it'll\n"
+ "seem, sending presents to one's own feet! And how odd the\n"
+ "directions will look!\n"
+ "\n"
+ " ALICE'S RIGHT FOOT, ESQ.\n"
+ " HEARTHRUG,\n"
+ " NEAR THE FENDER,\n"
+ " (WITH ALICE'S LOVE).\n"
+ "\n"
+ "Oh dear, what nonsense I'm talking!'\n"
+ "\n"
+ " Just then her head struck against the roof of the hall: in\n"
+ "fact she was now more than nine feet high, and she at once took\n"
+ "up the little golden key and hurried off to the garden door.\n"
+ "\n"
+ " Poor Alice! It was as much as she could do, lying down on one\n"
+ "side, to look through into the garden with one eye; but to get\n"
+ "through was more hopeless than ever: she sat down and began to\n"
+ "cry again.\n"
+ "\n"
+ " `You ought to be ashamed of yourself,' said Alice, `a great\n"
+ "girl like you,' (she might well say this), `to go on crying in\n"
+ "this way! Stop this moment, I tell you!' But she went on all\n"
+ "the same, shedding gallons of tears, until there was a large pool\n"
+ "all round her, about four inches deep and reaching half down the\n"
+ "hall.\n"
+ "\n"
+ " After a time she heard a little pattering of feet in the\n"
+ "distance, and she hastily dried her eyes to see what was coming.\n"
+ "It was the White Rabbit returning, splendidly dressed, with a\n"
+ "pair of white kid gloves in one hand and a large fan in the\n"
+ "other: he came trotting along in a great hurry, muttering to\n"
+ "himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she\n"
+ "be savage if I've kept her waiting!' Alice felt so desperate\n"
+ "that she was ready to ask help of any one; so, when the Rabbit\n"
+ "came near her, she began, in a low, timid voice, `If you please,\n"
+ "sir--' The Rabbit started violently, dropped the white kid\n"
+ "gloves and the fan, and skurried away into the darkness as hard\n"
+ "as he could go.\n"
+ "\n"
+ " Alice took up the fan and gloves, and, as the hall was very\n"
+ "hot, she kept fanning herself all the time she went on talking:\n"
+ "`Dear, dear! How queer everything is to-day! And yesterday\n"
+ "things went on just as usual. I wonder if I've been changed in\n"
+ "the night? Let me think: was I the same when I got up this\n"
+ "morning? I almost think I can remember feeling a little\n"
+ "different. But if I'm not the same, the next question is, Who in\n"
+ "the world am I? Ah, THAT'S the great puzzle!' And she began\n"
+ "thinking over all the children she knew that were of the same age\n"
+ "as herself, to see if she could have been changed for any of\n"
+ "them.\n"
+ "\n"
+ " `I'm sure I'm not Ada,' she said, `for her hair goes in such\n"
+ "long ringlets, and mine doesn't go in ringlets at all; and I'm\n"
+ "sure I can't be Mabel, for I know all sorts of things, and she,\n"
+ "oh! she knows such a very little! Besides, SHE'S she, and I'm I,\n"
+ "and--oh dear, how puzzling it all is! I'll try if I know all the\n"
+ "things I used to know. Let me see: four times five is twelve,\n"
+ "and four times six is thirteen, and four times seven is--oh dear!\n"
+ "I shall never get to twenty at that rate! However, the\n"
+ "Multiplication Table doesn't signify: let's try Geography.\n"
+ "London is the capital of Paris, and Paris is the capital of Rome,\n"
+ "and Rome--no, THAT'S all wrong, I'm certain! I must have been\n"
+ "changed for Mabel! I'll try and say ''How doth the little--''\n"
+ "and she crossed her hands on her lap as if she were saying lessons,\n"
+ "and began to repeat it, but her voice sounded hoarse and\n"
+ "strange, and the words did not come the same as they used to do:--\n"
+ "\n"
+ " `How doth the little crocodile\n"
+ " Improve his shining tail,\n"
+ " And pour the waters of the Nile\n"
+ " On every golden scale!\n"
+ "\n"
+ " `How cheerfully he seems to grin,\n"
+ " How neatly spread his claws,\n"
+ " And welcome little fishes in\n"
+ " With gently smiling jaws!'\n";
+
+static const char * const compress_test_bufs[] = {
+ test_buf_alice,
+ test_buf_shakespeare,
+ test_buf_alice2
+};
+
+#endif /* TEST_COMPRESSDEV_TEST_BUFFERS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cpuflags.c b/src/spdk/dpdk/app/test/test_cpuflags.c
new file mode 100644
index 000000000..06718631f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cpuflags.c
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+
+#include <errno.h>
+#include <stdint.h>
+#include <rte_cpuflags.h>
+#include <rte_debug.h>
+
+#include "test.h"
+
+
+/* convenience define */
+#define CHECK_FOR_FLAG(x) \
+ result = rte_cpu_get_flag_enabled(x); \
+ printf("%s\n", cpu_flag_result(result)); \
+ if (result == -ENOENT) \
+ return -1;
+
+/*
+ * Helper function to display result
+ */
+static inline const char *
+cpu_flag_result(int result)
+{
+ switch (result) {
+ case 0:
+ return "NOT PRESENT";
+ case 1:
+ return "OK";
+ default:
+ return "ERROR";
+ }
+}
+
+
+
+/*
+ * CPUID test
+ * ===========
+ *
+ * - Check flags from different registers with rte_cpu_get_flag_enabled()
+ * - Check if register and CPUID functions fail properly
+ */
+
+static int
+test_cpuflags(void)
+{
+ int result;
+ printf("\nChecking for flags from different registers...\n");
+
+#ifdef RTE_ARCH_PPC_64
+ printf("Check for PPC64:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_PPC64);
+
+ printf("Check for PPC32:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_PPC32);
+
+ printf("Check for VSX:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_VSX);
+
+ printf("Check for DFP:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_DFP);
+
+ printf("Check for FPU:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_FPU);
+
+ printf("Check for SMT:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SMT);
+
+ printf("Check for MMU:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_MMU);
+
+ printf("Check for ALTIVEC:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ALTIVEC);
+
+ printf("Check for ARCH_2_06:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_06);
+
+ printf("Check for ARCH_2_07:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ARCH_2_07);
+
+ printf("Check for ICACHE_SNOOP:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ICACHE_SNOOP);
+#endif
+
+#if defined(RTE_ARCH_ARM)
+ printf("Check for NEON:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_NEON);
+#endif
+
+#if defined(RTE_ARCH_ARM64)
+ printf("Check for FP:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_FP);
+
+ printf("Check for ASIMD:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_NEON);
+
+ printf("Check for EVTSTRM:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_EVTSTRM);
+
+ printf("Check for AES:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_AES);
+
+ printf("Check for PMULL:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_PMULL);
+
+ printf("Check for SHA1:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SHA1);
+
+ printf("Check for SHA2:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SHA2);
+
+ printf("Check for CRC32:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_CRC32);
+
+ printf("Check for ATOMICS:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ATOMICS);
+#endif
+
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
+ printf("Check for SSE:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SSE);
+
+ printf("Check for SSE2:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SSE2);
+
+ printf("Check for SSE3:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SSE3);
+
+ printf("Check for SSE4.1:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_1);
+
+ printf("Check for SSE4.2:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_SSE4_2);
+
+ printf("Check for AVX:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_AVX);
+
+ printf("Check for AVX2:\t\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_AVX2);
+
+ printf("Check for AVX512F:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_AVX512F);
+
+ printf("Check for TRBOBST:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_TRBOBST);
+
+ printf("Check for ENERGY_EFF:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_ENERGY_EFF);
+
+ printf("Check for LAHF_SAHF:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_LAHF_SAHF);
+
+ printf("Check for 1GB_PG:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_1GB_PG);
+
+ printf("Check for INVTSC:\t");
+ CHECK_FOR_FLAG(RTE_CPUFLAG_INVTSC);
+#endif
+
+ /*
+ * Check if invalid data is handled properly
+ */
+ printf("\nCheck for invalid flag:\t");
+ result = rte_cpu_get_flag_enabled(RTE_CPUFLAG_NUMFLAGS);
+ printf("%s\n", cpu_flag_result(result));
+ if (result != -ENOENT)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(cpuflags_autotest, test_cpuflags);
diff --git a/src/spdk/dpdk/app/test/test_crc.c b/src/spdk/dpdk/app/test/test_crc.c
new file mode 100644
index 000000000..f8a74e04e
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_crc.c
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include "test.h"
+
+#include <rte_hexdump.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_net_crc.h>
+
+#define CRC_VEC_LEN 32
+#define CRC32_VEC_LEN1 1512
+#define CRC32_VEC_LEN2 348
+#define CRC16_VEC_LEN1 12
+#define CRC16_VEC_LEN2 2
+#define LINE_LEN 75
+
+/* CRC test vector */
+static const uint8_t crc_vec[CRC_VEC_LEN] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+};
+
+/* 32-bit CRC test vector */
+static const uint8_t crc32_vec1[12] = {
+ 0xBE, 0xD7, 0x23, 0x47, 0x6B, 0x8F,
+ 0xB3, 0x14, 0x5E, 0xFB, 0x35, 0x59,
+};
+
+/* 16-bit CRC test vector 1 */
+static const uint8_t crc16_vec1[CRC16_VEC_LEN1] = {
+ 0x0D, 0x01, 0x01, 0x23, 0x45, 0x67,
+ 0x89, 0x01, 0x23, 0x45, 0x00, 0x01,
+};
+
+/* 16-bit CRC test vector 2 */
+static const uint8_t crc16_vec2[CRC16_VEC_LEN2] = {
+ 0x03, 0x3f,
+};
+/** CRC results */
+static const uint32_t crc32_vec_res = 0xb491aab4;
+static const uint32_t crc32_vec1_res = 0xac54d294;
+static const uint32_t crc32_vec2_res = 0xefaae02f;
+static const uint32_t crc16_vec_res = 0x6bec;
+static const uint16_t crc16_vec1_res = 0x8cdd;
+static const uint16_t crc16_vec2_res = 0xec5b;
+
+static int
+crc_calc(const uint8_t *vec,
+ uint32_t vec_len,
+ enum rte_net_crc_type type)
+{
+ /* compute CRC */
+ uint32_t ret = rte_net_crc_calc(vec, vec_len, type);
+
+ /* dump data on console */
+ debug_hexdump(stdout, NULL, vec, vec_len);
+
+ return ret;
+}
+
+static int
+test_crc_calc(void)
+{
+ uint32_t i;
+ enum rte_net_crc_type type;
+ uint8_t *test_data;
+ uint32_t result;
+ int error;
+
+ /* 32-bit ethernet CRC: Test 1 */
+ type = RTE_NET_CRC32_ETH;
+
+ result = crc_calc(crc_vec, CRC_VEC_LEN, type);
+ if (result != crc32_vec_res)
+ return -1;
+
+ /* 32-bit ethernet CRC: Test 2 */
+ test_data = rte_zmalloc(NULL, CRC32_VEC_LEN1, 0);
+
+ for (i = 0; i < CRC32_VEC_LEN1; i += 12)
+ rte_memcpy(&test_data[i], crc32_vec1, 12);
+
+ result = crc_calc(test_data, CRC32_VEC_LEN1, type);
+ if (result != crc32_vec1_res) {
+ error = -2;
+ goto fail;
+ }
+
+ /* 32-bit ethernet CRC: Test 3 */
+ for (i = 0; i < CRC32_VEC_LEN2; i += 12)
+ rte_memcpy(&test_data[i], crc32_vec1, 12);
+
+ result = crc_calc(test_data, CRC32_VEC_LEN2, type);
+ if (result != crc32_vec2_res) {
+ error = -3;
+ goto fail;
+ }
+
+ /* 16-bit CCITT CRC: Test 4 */
+ type = RTE_NET_CRC16_CCITT;
+ result = crc_calc(crc_vec, CRC_VEC_LEN, type);
+ if (result != crc16_vec_res) {
+ error = -4;
+ goto fail;
+ }
+ /* 16-bit CCITT CRC: Test 5 */
+ result = crc_calc(crc16_vec1, CRC16_VEC_LEN1, type);
+ if (result != crc16_vec1_res) {
+ error = -5;
+ goto fail;
+ }
+ /* 16-bit CCITT CRC: Test 6 */
+ result = crc_calc(crc16_vec2, CRC16_VEC_LEN2, type);
+ if (result != crc16_vec2_res) {
+ error = -6;
+ goto fail;
+ }
+
+ rte_free(test_data);
+ return 0;
+
+fail:
+ rte_free(test_data);
+ return error;
+}
+
+static int
+test_crc(void)
+{
+ int ret;
+ /* set CRC scalar mode */
+ rte_net_crc_set_alg(RTE_NET_CRC_SCALAR);
+
+ ret = test_crc_calc();
+ if (ret < 0) {
+ printf("test_crc (scalar): failed (%d)\n", ret);
+ return ret;
+ }
+ /* set CRC sse4.2 mode */
+ rte_net_crc_set_alg(RTE_NET_CRC_SSE42);
+
+ ret = test_crc_calc();
+ if (ret < 0) {
+ printf("test_crc (x86_64_SSE4.2): failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* set CRC neon mode */
+ rte_net_crc_set_alg(RTE_NET_CRC_NEON);
+
+ ret = test_crc_calc();
+ if (ret < 0) {
+ printf("test crc (arm64 neon pmull): failed (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(crc_autotest, test_crc);
diff --git a/src/spdk/dpdk/app/test/test_cryptodev.c b/src/spdk/dpdk/app/test/test_cryptodev.c
new file mode 100644
index 000000000..8f631468b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev.c
@@ -0,0 +1,13265 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2020 Intel Corporation
+ */
+
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_pause.h>
+#include <rte_bus_vdev.h>
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_string_fns.h>
+
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+#include <rte_cryptodev_scheduler.h>
+#include <rte_cryptodev_scheduler_operations.h>
+#endif
+
+#include <rte_lcore.h>
+
+#include "test.h"
+#include "test_cryptodev.h"
+
+#include "test_cryptodev_blockcipher.h"
+#include "test_cryptodev_aes_test_vectors.h"
+#include "test_cryptodev_des_test_vectors.h"
+#include "test_cryptodev_hash_test_vectors.h"
+#include "test_cryptodev_kasumi_test_vectors.h"
+#include "test_cryptodev_kasumi_hash_test_vectors.h"
+#include "test_cryptodev_snow3g_test_vectors.h"
+#include "test_cryptodev_snow3g_hash_test_vectors.h"
+#include "test_cryptodev_zuc_test_vectors.h"
+#include "test_cryptodev_aead_test_vectors.h"
+#include "test_cryptodev_hmac_test_vectors.h"
+#include "test_cryptodev_mixed_test_vectors.h"
+#ifdef RTE_LIBRTE_SECURITY
+#include "test_cryptodev_security_pdcp_test_vectors.h"
+#include "test_cryptodev_security_pdcp_test_func.h"
+#endif
+
+#define VDEV_ARGS_SIZE 100
+#define MAX_NB_SESSIONS 4
+
+#define IN_PLACE 0
+#define OUT_OF_PLACE 1
+
+static int gbl_driver_id;
+
+static enum rte_security_session_action_type gbl_action_type =
+ RTE_SECURITY_ACTION_TYPE_NONE;
+
+struct crypto_testsuite_params {
+ struct rte_mempool *mbuf_pool;
+ struct rte_mempool *large_mbuf_pool;
+ struct rte_mempool *op_mpool;
+ struct rte_mempool *session_mpool;
+ struct rte_mempool *session_priv_mpool;
+ struct rte_cryptodev_config conf;
+ struct rte_cryptodev_qp_conf qp_conf;
+
+ uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
+ uint8_t valid_dev_count;
+};
+
+struct crypto_unittest_params {
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_crypto_sym_xform aead_xform;
+
+ union {
+ struct rte_cryptodev_sym_session *sess;
+#ifdef RTE_LIBRTE_SECURITY
+ struct rte_security_session *sec_session;
+#endif
+ };
+#ifdef RTE_LIBRTE_SECURITY
+ enum rte_security_session_action_type type;
+#endif
+ struct rte_crypto_op *op;
+
+ struct rte_mbuf *obuf, *ibuf;
+
+ uint8_t *digest;
+};
+
+#define ALIGN_POW2_ROUNDUP(num, align) \
+ (((num) + (align) - 1) & ~((align) - 1))
+
+/*
+ * Forward declarations.
+ */
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(
+ struct crypto_unittest_params *ut_params, uint8_t *cipher_key,
+ uint8_t *hmac_key);
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_sym_session *sess,
+ struct crypto_unittest_params *ut_params,
+ struct crypto_testsuite_params *ts_param,
+ const uint8_t *cipher,
+ const uint8_t *digest,
+ const uint8_t *iv);
+
+static struct rte_mbuf *
+setup_test_string(struct rte_mempool *mpool,
+ const char *string, size_t len, uint8_t blocksize)
+{
+ struct rte_mbuf *m = rte_pktmbuf_alloc(mpool);
+ size_t t_len = len - (blocksize ? (len % blocksize) : 0);
+
+ memset(m->buf_addr, 0, m->buf_len);
+ if (m) {
+ char *dst = rte_pktmbuf_append(m, t_len);
+
+ if (!dst) {
+ rte_pktmbuf_free(m);
+ return NULL;
+ }
+ if (string != NULL)
+ rte_memcpy(dst, string, t_len);
+ else
+ memset(dst, 0, t_len);
+ }
+
+ return m;
+}
+
+/* Get number of bytes in X bits (rounding up) */
+static uint32_t
+ceil_byte_length(uint32_t num_bits)
+{
+ if (num_bits % 8)
+ return ((num_bits >> 3) + 1);
+ else
+ return (num_bits >> 3);
+}
+
+static void
+process_cpu_aead_op(uint8_t dev_id, struct rte_crypto_op *op)
+{
+ int32_t n, st;
+ void *iv;
+ struct rte_crypto_sym_op *sop;
+ union rte_crypto_sym_ofs ofs;
+ struct rte_crypto_sgl sgl;
+ struct rte_crypto_sym_vec symvec;
+ struct rte_crypto_vec vec[UINT8_MAX];
+
+ sop = op->sym;
+
+ n = rte_crypto_mbuf_to_vec(sop->m_src, sop->aead.data.offset,
+ sop->aead.data.length, vec, RTE_DIM(vec));
+
+ if (n < 0 || n != sop->m_src->nb_segs) {
+ op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+ return;
+ }
+
+ sgl.vec = vec;
+ sgl.num = n;
+ symvec.sgl = &sgl;
+ iv = rte_crypto_op_ctod_offset(op, void *, IV_OFFSET);
+ symvec.iv = &iv;
+ symvec.aad = (void **)&sop->aead.aad.data;
+ symvec.digest = (void **)&sop->aead.digest.data;
+ symvec.status = &st;
+ symvec.num = 1;
+
+ ofs.raw = 0;
+
+ n = rte_cryptodev_sym_cpu_crypto_process(dev_id, sop->session, ofs,
+ &symvec);
+
+ if (n != 1)
+ op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+ else
+ op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+}
+
+static void
+process_cpu_crypt_auth_op(uint8_t dev_id, struct rte_crypto_op *op)
+{
+ int32_t n, st;
+ void *iv;
+ struct rte_crypto_sym_op *sop;
+ union rte_crypto_sym_ofs ofs;
+ struct rte_crypto_sgl sgl;
+ struct rte_crypto_sym_vec symvec;
+ struct rte_crypto_vec vec[UINT8_MAX];
+
+ sop = op->sym;
+
+ n = rte_crypto_mbuf_to_vec(sop->m_src, sop->auth.data.offset,
+ sop->auth.data.length, vec, RTE_DIM(vec));
+
+ if (n < 0 || n != sop->m_src->nb_segs) {
+ op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+ return;
+ }
+
+ sgl.vec = vec;
+ sgl.num = n;
+ symvec.sgl = &sgl;
+ iv = rte_crypto_op_ctod_offset(op, void *, IV_OFFSET);
+ symvec.iv = &iv;
+ symvec.aad = (void **)&sop->aead.aad.data;
+ symvec.digest = (void **)&sop->auth.digest.data;
+ symvec.status = &st;
+ symvec.num = 1;
+
+ ofs.raw = 0;
+ ofs.ofs.cipher.head = sop->cipher.data.offset - sop->auth.data.offset;
+ ofs.ofs.cipher.tail = (sop->auth.data.offset + sop->auth.data.length) -
+ (sop->cipher.data.offset + sop->cipher.data.length);
+
+ n = rte_cryptodev_sym_cpu_crypto_process(dev_id, sop->session, ofs,
+ &symvec);
+
+ if (n != 1)
+ op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+ else
+ op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+}
+
+static struct rte_crypto_op *
+process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op)
+{
+
+ RTE_VERIFY(gbl_action_type != RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO);
+
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1, "Error sending packet for encryption\n");
+ return NULL;
+ }
+
+ op = NULL;
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
+ rte_pause();
+
+ if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ RTE_LOG(DEBUG, USER1, "Operation status %d\n", op->status);
+ return NULL;
+ }
+
+ return op;
+}
+
+static struct crypto_testsuite_params testsuite_params = { NULL };
+static struct crypto_unittest_params unittest_params;
+
+static int
+testsuite_setup(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_info info;
+ uint32_t i = 0, nb_devs, dev_id;
+ int ret;
+ uint16_t qp_id;
+
+ memset(ts_params, 0, sizeof(*ts_params));
+
+ ts_params->mbuf_pool = rte_mempool_lookup("CRYPTO_MBUFPOOL");
+ if (ts_params->mbuf_pool == NULL) {
+ /* Not already created so create */
+ ts_params->mbuf_pool = rte_pktmbuf_pool_create(
+ "CRYPTO_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (ts_params->mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+ }
+
+ ts_params->large_mbuf_pool = rte_mempool_lookup(
+ "CRYPTO_LARGE_MBUFPOOL");
+ if (ts_params->large_mbuf_pool == NULL) {
+ /* Not already created so create */
+ ts_params->large_mbuf_pool = rte_pktmbuf_pool_create(
+ "CRYPTO_LARGE_MBUFPOOL",
+ 1, 0, 0, UINT16_MAX,
+ rte_socket_id());
+ if (ts_params->large_mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Can't create CRYPTO_LARGE_MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+ }
+
+ ts_params->op_mpool = rte_crypto_op_pool_create(
+ "MBUF_CRYPTO_SYM_OP_POOL",
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ NUM_MBUFS, MBUF_CACHE_SIZE,
+ DEFAULT_NUM_XFORMS *
+ sizeof(struct rte_crypto_sym_xform) +
+ MAXIMUM_IV_LENGTH,
+ rte_socket_id());
+ if (ts_params->op_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ /* Create an AESNI MB device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD), NULL);
+
+ TEST_ASSERT(ret == 0,
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
+ }
+ }
+
+ /* Create an AESNI GCM device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD)));
+ if (nb_devs < 1) {
+ TEST_ASSERT_SUCCESS(rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD), NULL),
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD));
+ }
+ }
+
+ /* Create a SNOW 3G device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD)));
+ if (nb_devs < 1) {
+ TEST_ASSERT_SUCCESS(rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD), NULL),
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD));
+ }
+ }
+
+ /* Create a KASUMI device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_KASUMI_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_KASUMI_PMD)));
+ if (nb_devs < 1) {
+ TEST_ASSERT_SUCCESS(rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_KASUMI_PMD), NULL),
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_KASUMI_PMD));
+ }
+ }
+
+ /* Create a ZUC device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ZUC_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ZUC_PMD)));
+ if (nb_devs < 1) {
+ TEST_ASSERT_SUCCESS(rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_ZUC_PMD), NULL),
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_ZUC_PMD));
+ }
+ }
+
+ /* Create a NULL device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD), NULL);
+
+ TEST_ASSERT(ret == 0,
+ "Failed to create instance of"
+ " pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD));
+ }
+ }
+
+ /* Create an OPENSSL device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD),
+ NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create "
+ "instance of pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
+ }
+ }
+
+ /* Create a ARMv8 device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ARMV8_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ARMV8_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),
+ NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create "
+ "instance of pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
+ }
+ }
+
+ /* Create a MVSAM device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_MVSAM_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_MVSAM_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_MVSAM_PMD),
+ NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create "
+ "instance of pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_MVSAM_PMD));
+ }
+ }
+
+ /* Create an CCP device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_CCP_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_CCP_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_CCP_PMD),
+ NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create "
+ "instance of pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_CCP_PMD));
+ }
+ }
+
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+ char vdev_args[VDEV_ARGS_SIZE] = {""};
+ char temp_str[VDEV_ARGS_SIZE] = {"mode=multi-core,"
+ "ordering=enable,name=cryptodev_test_scheduler,corelist="};
+ uint16_t slave_core_count = 0;
+ uint16_t socket_id = 0;
+
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD))) {
+
+ /* Identify the Slave Cores
+ * Use 2 slave cores for the device args
+ */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ if (slave_core_count > 1)
+ break;
+ snprintf(vdev_args, sizeof(vdev_args),
+ "%s%d", temp_str, i);
+ strcpy(temp_str, vdev_args);
+ strlcat(temp_str, ";", sizeof(temp_str));
+ slave_core_count++;
+ socket_id = rte_lcore_to_socket_id(i);
+ }
+ if (slave_core_count != 2) {
+ RTE_LOG(ERR, USER1,
+ "Cryptodev scheduler test require at least "
+ "two slave cores to run. "
+ "Please use the correct coremask.\n");
+ return TEST_FAILED;
+ }
+ strcpy(temp_str, vdev_args);
+ snprintf(vdev_args, sizeof(vdev_args), "%s,socket_id=%d",
+ temp_str, socket_id);
+ RTE_LOG(DEBUG, USER1, "vdev_args: %s\n", vdev_args);
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD),
+ vdev_args);
+ TEST_ASSERT(ret == 0,
+ "Failed to create instance %u of"
+ " pmd : %s",
+ i, RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD));
+ }
+ }
+#endif /* RTE_LIBRTE_PMD_CRYPTO_SCHEDULER */
+
+ nb_devs = rte_cryptodev_count();
+ if (nb_devs < 1) {
+ RTE_LOG(WARNING, USER1, "No crypto devices found?\n");
+ return TEST_SKIPPED;
+ }
+
+ /* Create list of valid crypto devs */
+ for (i = 0; i < nb_devs; i++) {
+ rte_cryptodev_info_get(i, &info);
+ if (info.driver_id == gbl_driver_id)
+ ts_params->valid_devs[ts_params->valid_dev_count++] = i;
+ }
+
+ if (ts_params->valid_dev_count < 1)
+ return TEST_FAILED;
+
+ /* Set up all the qps on the first of the valid devices found */
+
+ dev_id = ts_params->valid_devs[0];
+
+ rte_cryptodev_info_get(dev_id, &info);
+
+ ts_params->conf.nb_queue_pairs = info.max_nb_queue_pairs;
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+ ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
+
+ unsigned int session_size =
+ rte_cryptodev_sym_get_private_session_size(dev_id);
+
+ /*
+ * Create mempool with maximum number of sessions * 2,
+ * to include the session headers
+ */
+ if (info.sym.max_nb_sessions != 0 &&
+ info.sym.max_nb_sessions < MAX_NB_SESSIONS) {
+ RTE_LOG(ERR, USER1, "Device does not support "
+ "at least %u sessions\n",
+ MAX_NB_SESSIONS);
+ return TEST_FAILED;
+ }
+
+ ts_params->session_mpool = rte_cryptodev_sym_session_pool_create(
+ "test_sess_mp", MAX_NB_SESSIONS, 0, 0, 0,
+ SOCKET_ID_ANY);
+ TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
+ "session mempool allocation failed");
+
+ ts_params->session_priv_mpool = rte_mempool_create(
+ "test_sess_mp_priv",
+ MAX_NB_SESSIONS,
+ session_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+ TEST_ASSERT_NOT_NULL(ts_params->session_priv_mpool,
+ "session mempool allocation failed");
+
+
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(dev_id,
+ &ts_params->conf),
+ "Failed to configure cryptodev %u with %u qps",
+ dev_id, ts_params->conf.nb_queue_pairs);
+
+ ts_params->qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT;
+ ts_params->qp_conf.mp_session = ts_params->session_mpool;
+ ts_params->qp_conf.mp_session_private = ts_params->session_priv_mpool;
+
+ for (qp_id = 0; qp_id < info.max_nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ dev_id, qp_id, &ts_params->qp_conf,
+ rte_cryptodev_socket_id(dev_id)),
+ "Failed to setup queue pair %u on cryptodev %u",
+ qp_id, dev_id);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+ if (ts_params->mbuf_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+ }
+
+ if (ts_params->op_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_OP_POOL count %u\n",
+ rte_mempool_avail_count(ts_params->op_mpool));
+ }
+
+ /* Free session mempools */
+ if (ts_params->session_priv_mpool != NULL) {
+ rte_mempool_free(ts_params->session_priv_mpool);
+ ts_params->session_priv_mpool = NULL;
+ }
+
+ if (ts_params->session_mpool != NULL) {
+ rte_mempool_free(ts_params->session_mpool);
+ ts_params->session_mpool = NULL;
+ }
+}
+
+static int
+ut_setup(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ uint16_t qp_id;
+
+ /* Clear unit test parameters before running test */
+ memset(ut_params, 0, sizeof(*ut_params));
+
+ /* Reconfigure device to default parameters */
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+ ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
+ ts_params->qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT;
+ ts_params->qp_conf.mp_session = ts_params->session_mpool;
+ ts_params->qp_conf.mp_session_private = ts_params->session_priv_mpool;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed to configure cryptodev %u",
+ ts_params->valid_devs[0]);
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs ; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id,
+ &ts_params->qp_conf,
+ rte_cryptodev_socket_id(ts_params->valid_devs[0])),
+ "Failed to setup queue pair %u on cryptodev %u",
+ qp_id, ts_params->valid_devs[0]);
+ }
+
+
+ rte_cryptodev_stats_reset(ts_params->valid_devs[0]);
+
+ /* Start the device */
+ TEST_ASSERT_SUCCESS(rte_cryptodev_start(ts_params->valid_devs[0]),
+ "Failed to start cryptodev %u",
+ ts_params->valid_devs[0]);
+
+ return TEST_SUCCESS;
+}
+
+static void
+ut_teardown(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ struct rte_cryptodev_stats stats;
+
+ /* free crypto session structure */
+#ifdef RTE_LIBRTE_SECURITY
+ if (ut_params->type == RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL) {
+ if (ut_params->sec_session) {
+ rte_security_session_destroy(rte_cryptodev_get_sec_ctx
+ (ts_params->valid_devs[0]),
+ ut_params->sec_session);
+ ut_params->sec_session = NULL;
+ }
+ } else
+#endif
+ {
+ if (ut_params->sess) {
+ rte_cryptodev_sym_session_clear(
+ ts_params->valid_devs[0],
+ ut_params->sess);
+ rte_cryptodev_sym_session_free(ut_params->sess);
+ ut_params->sess = NULL;
+ }
+ }
+
+ /* free crypto operation structure */
+ if (ut_params->op)
+ rte_crypto_op_free(ut_params->op);
+
+ /*
+ * free mbuf - both obuf and ibuf are usually the same,
+ * so check if they point at the same address is necessary,
+ * to avoid freeing the mbuf twice.
+ */
+ if (ut_params->obuf) {
+ rte_pktmbuf_free(ut_params->obuf);
+ if (ut_params->ibuf == ut_params->obuf)
+ ut_params->ibuf = 0;
+ ut_params->obuf = 0;
+ }
+ if (ut_params->ibuf) {
+ rte_pktmbuf_free(ut_params->ibuf);
+ ut_params->ibuf = 0;
+ }
+
+ if (ts_params->mbuf_pool != NULL)
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+
+ rte_cryptodev_stats_get(ts_params->valid_devs[0], &stats);
+
+ /* Stop the device */
+ rte_cryptodev_stop(ts_params->valid_devs[0]);
+}
+
+static int
+test_device_configure_invalid_dev_id(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint16_t dev_id, num_devs = 0;
+
+ TEST_ASSERT((num_devs = rte_cryptodev_count()) >= 1,
+ "Need at least %d devices for test", 1);
+
+ /* valid dev_id values */
+ dev_id = ts_params->valid_devs[ts_params->valid_dev_count - 1];
+
+ /* Stop the device in case it's started so it can be configured */
+ rte_cryptodev_stop(dev_id);
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(dev_id, &ts_params->conf),
+ "Failed test for rte_cryptodev_configure: "
+ "invalid dev_num %u", dev_id);
+
+ /* invalid dev_id values */
+ dev_id = num_devs;
+
+ TEST_ASSERT_FAIL(rte_cryptodev_configure(dev_id, &ts_params->conf),
+ "Failed test for rte_cryptodev_configure: "
+ "invalid dev_num %u", dev_id);
+
+ dev_id = 0xff;
+
+ TEST_ASSERT_FAIL(rte_cryptodev_configure(dev_id, &ts_params->conf),
+ "Failed test for rte_cryptodev_configure:"
+ "invalid dev_num %u", dev_id);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_device_configure_invalid_queue_pair_ids(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint16_t orig_nb_qps = ts_params->conf.nb_queue_pairs;
+
+ /* Stop the device in case it's started so it can be configured */
+ rte_cryptodev_stop(ts_params->valid_devs[0]);
+
+ /* valid - max value queue pairs */
+ ts_params->conf.nb_queue_pairs = orig_nb_qps;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed to configure cryptodev: dev_id %u, qp_id %u",
+ ts_params->valid_devs[0], ts_params->conf.nb_queue_pairs);
+
+ /* valid - one queue pairs */
+ ts_params->conf.nb_queue_pairs = 1;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed to configure cryptodev: dev_id %u, qp_id %u",
+ ts_params->valid_devs[0],
+ ts_params->conf.nb_queue_pairs);
+
+
+ /* invalid - zero queue pairs */
+ ts_params->conf.nb_queue_pairs = 0;
+
+ TEST_ASSERT_FAIL(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed test for rte_cryptodev_configure, dev_id %u,"
+ " invalid qps: %u",
+ ts_params->valid_devs[0],
+ ts_params->conf.nb_queue_pairs);
+
+
+ /* invalid - max value supported by field queue pairs */
+ ts_params->conf.nb_queue_pairs = UINT16_MAX;
+
+ TEST_ASSERT_FAIL(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed test for rte_cryptodev_configure, dev_id %u,"
+ " invalid qps: %u",
+ ts_params->valid_devs[0],
+ ts_params->conf.nb_queue_pairs);
+
+
+ /* invalid - max value + 1 queue pairs */
+ ts_params->conf.nb_queue_pairs = orig_nb_qps + 1;
+
+ TEST_ASSERT_FAIL(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed test for rte_cryptodev_configure, dev_id %u,"
+ " invalid qps: %u",
+ ts_params->valid_devs[0],
+ ts_params->conf.nb_queue_pairs);
+
+ /* revert to original testsuite value */
+ ts_params->conf.nb_queue_pairs = orig_nb_qps;
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_queue_pair_descriptor_setup(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_qp_conf qp_conf = {
+ .nb_descriptors = MAX_NUM_OPS_INFLIGHT
+ };
+ uint16_t qp_id;
+
+ /* Stop the device in case it's started so it can be configured */
+ rte_cryptodev_stop(ts_params->valid_devs[0]);
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed to configure cryptodev %u",
+ ts_params->valid_devs[0]);
+
+ /*
+ * Test various ring sizes on this device. memzones can't be
+ * freed so are re-used if ring is released and re-created.
+ */
+ qp_conf.nb_descriptors = MIN_NUM_OPS_INFLIGHT; /* min size*/
+ qp_conf.mp_session = ts_params->session_mpool;
+ qp_conf.mp_session_private = ts_params->session_priv_mpool;
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id, &qp_conf,
+ rte_cryptodev_socket_id(
+ ts_params->valid_devs[0])),
+ "Failed test for "
+ "rte_cryptodev_queue_pair_setup: num_inflights "
+ "%u on qp %u on cryptodev %u",
+ qp_conf.nb_descriptors, qp_id,
+ ts_params->valid_devs[0]);
+ }
+
+ qp_conf.nb_descriptors = (uint32_t)(MAX_NUM_OPS_INFLIGHT / 2);
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id, &qp_conf,
+ rte_cryptodev_socket_id(
+ ts_params->valid_devs[0])),
+ "Failed test for"
+ " rte_cryptodev_queue_pair_setup: num_inflights"
+ " %u on qp %u on cryptodev %u",
+ qp_conf.nb_descriptors, qp_id,
+ ts_params->valid_devs[0]);
+ }
+
+ qp_conf.nb_descriptors = MAX_NUM_OPS_INFLIGHT; /* valid */
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id, &qp_conf,
+ rte_cryptodev_socket_id(
+ ts_params->valid_devs[0])),
+ "Failed test for "
+ "rte_cryptodev_queue_pair_setup: num_inflights"
+ " %u on qp %u on cryptodev %u",
+ qp_conf.nb_descriptors, qp_id,
+ ts_params->valid_devs[0]);
+ }
+
+ qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT;
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id, &qp_conf,
+ rte_cryptodev_socket_id(
+ ts_params->valid_devs[0])),
+ "Failed test for"
+ " rte_cryptodev_queue_pair_setup:"
+ "num_inflights %u on qp %u on cryptodev %u",
+ qp_conf.nb_descriptors, qp_id,
+ ts_params->valid_devs[0]);
+ }
+
+ /* test invalid queue pair id */
+ qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT; /*valid */
+
+ qp_id = ts_params->conf.nb_queue_pairs; /*invalid */
+
+ TEST_ASSERT_FAIL(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0],
+ qp_id, &qp_conf,
+ rte_cryptodev_socket_id(ts_params->valid_devs[0])),
+ "Failed test for rte_cryptodev_queue_pair_setup:"
+ "invalid qp %u on cryptodev %u",
+ qp_id, ts_params->valid_devs[0]);
+
+ qp_id = 0xffff; /*invalid*/
+
+ TEST_ASSERT_FAIL(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0],
+ qp_id, &qp_conf,
+ rte_cryptodev_socket_id(ts_params->valid_devs[0])),
+ "Failed test for rte_cryptodev_queue_pair_setup:"
+ "invalid qp %u on cryptodev %u",
+ qp_id, ts_params->valid_devs[0]);
+
+ return TEST_SUCCESS;
+}
+
+/* ***** Plaintext data for tests ***** */
+
+const char catch_22_quote_1[] =
+ "There was only one catch and that was Catch-22, which "
+ "specified that a concern for one's safety in the face of "
+ "dangers that were real and immediate was the process of a "
+ "rational mind. Orr was crazy and could be grounded. All he "
+ "had to do was ask; and as soon as he did, he would no longer "
+ "be crazy and would have to fly more missions. Orr would be "
+ "crazy to fly more missions and sane if he didn't, but if he "
+ "was sane he had to fly them. If he flew them he was crazy "
+ "and didn't have to; but if he didn't want to he was sane and "
+ "had to. Yossarian was moved very deeply by the absolute "
+ "simplicity of this clause of Catch-22 and let out a "
+ "respectful whistle. \"That's some catch, that Catch-22\", he "
+ "observed. \"It's the best there is,\" Doc Daneeka agreed.";
+
+const char catch_22_quote[] =
+ "What a lousy earth! He wondered how many people were "
+ "destitute that same night even in his own prosperous country, "
+ "how many homes were shanties, how many husbands were drunk "
+ "and wives socked, and how many children were bullied, abused, "
+ "or abandoned. How many families hungered for food they could "
+ "not afford to buy? How many hearts were broken? How many "
+ "suicides would take place that same night, how many people "
+ "would go insane? How many cockroaches and landlords would "
+ "triumph? How many winners were losers, successes failures, "
+ "and rich men poor men? How many wise guys were stupid? How "
+ "many happy endings were unhappy endings? How many honest men "
+ "were liars, brave men cowards, loyal men traitors, how many "
+ "sainted men were corrupt, how many people in positions of "
+ "trust had sold their souls to bodyguards, how many had never "
+ "had souls? How many straight-and-narrow paths were crooked "
+ "paths? How many best families were worst families and how "
+ "many good people were bad people? When you added them all up "
+ "and then subtracted, you might be left with only the children, "
+ "and perhaps with Albert Einstein and an old violinist or "
+ "sculptor somewhere.";
+
+#define QUOTE_480_BYTES (480)
+#define QUOTE_512_BYTES (512)
+#define QUOTE_768_BYTES (768)
+#define QUOTE_1024_BYTES (1024)
+
+
+
+/* ***** SHA1 Hash Tests ***** */
+
+#define HMAC_KEY_LENGTH_SHA1 (DIGEST_BYTE_LENGTH_SHA1)
+
+static uint8_t hmac_sha1_key[] = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD };
+
+/* ***** SHA224 Hash Tests ***** */
+
+#define HMAC_KEY_LENGTH_SHA224 (DIGEST_BYTE_LENGTH_SHA224)
+
+
+/* ***** AES-CBC Cipher Tests ***** */
+
+#define CIPHER_KEY_LENGTH_AES_CBC (16)
+#define CIPHER_IV_LENGTH_AES_CBC (CIPHER_KEY_LENGTH_AES_CBC)
+
+static uint8_t aes_cbc_key[] = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A };
+
+static uint8_t aes_cbc_iv[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
+
+
+/* ***** AES-CBC / HMAC-SHA1 Hash Tests ***** */
+
+static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_ciphertext[] = {
+ 0x8B, 0x4D, 0xDA, 0x1B, 0xCF, 0x04, 0xA0, 0x31,
+ 0xB4, 0xBF, 0xBD, 0x68, 0x43, 0x20, 0x7E, 0x76,
+ 0xB1, 0x96, 0x8B, 0xA2, 0x7C, 0xA2, 0x83, 0x9E,
+ 0x39, 0x5A, 0x2F, 0x7E, 0x92, 0xB4, 0x48, 0x1A,
+ 0x3F, 0x6B, 0x5D, 0xDF, 0x52, 0x85, 0x5F, 0x8E,
+ 0x42, 0x3C, 0xFB, 0xE9, 0x1A, 0x24, 0xD6, 0x08,
+ 0xDD, 0xFD, 0x16, 0xFB, 0xE9, 0x55, 0xEF, 0xF0,
+ 0xA0, 0x8D, 0x13, 0xAB, 0x81, 0xC6, 0x90, 0x01,
+ 0xB5, 0x18, 0x84, 0xB3, 0xF6, 0xE6, 0x11, 0x57,
+ 0xD6, 0x71, 0xC6, 0x3C, 0x3F, 0x2F, 0x33, 0xEE,
+ 0x24, 0x42, 0x6E, 0xAC, 0x0B, 0xCA, 0xEC, 0xF9,
+ 0x84, 0xF8, 0x22, 0xAA, 0x60, 0xF0, 0x32, 0xA9,
+ 0x75, 0x75, 0x3B, 0xCB, 0x70, 0x21, 0x0A, 0x8D,
+ 0x0F, 0xE0, 0xC4, 0x78, 0x2B, 0xF8, 0x97, 0xE3,
+ 0xE4, 0x26, 0x4B, 0x29, 0xDA, 0x88, 0xCD, 0x46,
+ 0xEC, 0xAA, 0xF9, 0x7F, 0xF1, 0x15, 0xEA, 0xC3,
+ 0x87, 0xE6, 0x31, 0xF2, 0xCF, 0xDE, 0x4D, 0x80,
+ 0x70, 0x91, 0x7E, 0x0C, 0xF7, 0x26, 0x3A, 0x92,
+ 0x4F, 0x18, 0x83, 0xC0, 0x8F, 0x59, 0x01, 0xA5,
+ 0x88, 0xD1, 0xDB, 0x26, 0x71, 0x27, 0x16, 0xF5,
+ 0xEE, 0x10, 0x82, 0xAC, 0x68, 0x26, 0x9B, 0xE2,
+ 0x6D, 0xD8, 0x9A, 0x80, 0xDF, 0x04, 0x31, 0xD5,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x61, 0x1C, 0x42, 0x10, 0x76,
+ 0x73, 0x02, 0x42, 0xC9, 0x23, 0x18, 0x8E, 0xB4,
+ 0x6F, 0xB4, 0xA3, 0x54, 0x6E, 0x88, 0x3B, 0x62,
+ 0x7C, 0x02, 0x8D, 0x4C, 0x9F, 0xC8, 0x45, 0xF4,
+ 0xC9, 0xDE, 0x4F, 0xEB, 0x22, 0x83, 0x1B, 0xE4,
+ 0x49, 0x37, 0xE4, 0xAD, 0xE7, 0xCD, 0x21, 0x54,
+ 0xBC, 0x1C, 0xC2, 0x04, 0x97, 0xB4, 0x10, 0x61,
+ 0xF0, 0xE4, 0xEF, 0x27, 0x63, 0x3A, 0xDA, 0x91,
+ 0x41, 0x25, 0x62, 0x1C, 0x5C, 0xB6, 0x38, 0x4A,
+ 0x88, 0x71, 0x59, 0x5A, 0x8D, 0xA0, 0x09, 0xAF,
+ 0x72, 0x94, 0xD7, 0x79, 0x5C, 0x60, 0x7C, 0x8F,
+ 0x4C, 0xF5, 0xD9, 0xA1, 0x39, 0x6D, 0x81, 0x28,
+ 0xEF, 0x13, 0x28, 0xDF, 0xF5, 0x3E, 0xF7, 0x8E,
+ 0x09, 0x9C, 0x78, 0x18, 0x79, 0xB8, 0x68, 0xD7,
+ 0xA8, 0x29, 0x62, 0xAD, 0xDE, 0xE1, 0x61, 0x76,
+ 0x1B, 0x05, 0x16, 0xCD, 0xBF, 0x02, 0x8E, 0xA6,
+ 0x43, 0x6E, 0x92, 0x55, 0x4F, 0x60, 0x9C, 0x03,
+ 0xB8, 0x4F, 0xA3, 0x02, 0xAC, 0xA8, 0xA7, 0x0C,
+ 0x1E, 0xB5, 0x6B, 0xF8, 0xC8, 0x4D, 0xDE, 0xD2,
+ 0xB0, 0x29, 0x6E, 0x40, 0xE6, 0xD6, 0xC9, 0xE6,
+ 0xB9, 0x0F, 0xB6, 0x63, 0xF5, 0xAA, 0x2B, 0x96,
+ 0xA7, 0x16, 0xAC, 0x4E, 0x0A, 0x33, 0x1C, 0xA6,
+ 0xE6, 0xBD, 0x8A, 0xCF, 0x40, 0xA9, 0xB2, 0xFA,
+ 0x63, 0x27, 0xFD, 0x9B, 0xD9, 0xFC, 0xD5, 0x87,
+ 0x8D, 0x4C, 0xB6, 0xA4, 0xCB, 0xE7, 0x74, 0x55,
+ 0xF4, 0xFB, 0x41, 0x25, 0xB5, 0x4B, 0x0A, 0x1B,
+ 0xB1, 0xD6, 0xB7, 0xD9, 0x47, 0x2A, 0xC3, 0x98,
+ 0x6A, 0xC4, 0x03, 0x73, 0x1F, 0x93, 0x6E, 0x53,
+ 0x19, 0x25, 0x64, 0x15, 0x83, 0xF9, 0x73, 0x2A,
+ 0x74, 0xB4, 0x93, 0x69, 0xC4, 0x72, 0xFC, 0x26,
+ 0xA2, 0x9F, 0x43, 0x45, 0xDD, 0xB9, 0xEF, 0x36,
+ 0xC8, 0x3A, 0xCD, 0x99, 0x9B, 0x54, 0x1A, 0x36,
+ 0xC1, 0x59, 0xF8, 0x98, 0xA8, 0xCC, 0x28, 0x0D,
+ 0x73, 0x4C, 0xEE, 0x98, 0xCB, 0x7C, 0x58, 0x7E,
+ 0x20, 0x75, 0x1E, 0xB7, 0xC9, 0xF8, 0xF2, 0x0E,
+ 0x63, 0x9E, 0x05, 0x78, 0x1A, 0xB6, 0xA8, 0x7A,
+ 0xF9, 0x98, 0x6A, 0xA6, 0x46, 0x84, 0x2E, 0xF6,
+ 0x4B, 0xDC, 0x9B, 0x8F, 0x9B, 0x8F, 0xEE, 0xB4,
+ 0xAA, 0x3F, 0xEE, 0xC0, 0x37, 0x27, 0x76, 0xC7,
+ 0x95, 0xBB, 0x26, 0x74, 0x69, 0x12, 0x7F, 0xF1,
+ 0xBB, 0xFF, 0xAE, 0xB5, 0x99, 0x6E, 0xCB, 0x0C
+};
+
+static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest[] = {
+ 0x9a, 0x4f, 0x88, 0x1b, 0xb6, 0x8f, 0xd8, 0x60,
+ 0x42, 0x1a, 0x7d, 0x3d, 0xf5, 0x82, 0x80, 0xf1,
+ 0x18, 0x8c, 0x1d, 0x32
+};
+
+
+/* Multisession Vector context Test */
+/*Begin Session 0 */
+static uint8_t ms_aes_cbc_key0[] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static uint8_t ms_aes_cbc_iv0[] = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const uint8_t ms_aes_cbc_cipher0[] = {
+ 0x3C, 0xE4, 0xEE, 0x42, 0xB6, 0x9B, 0xC3, 0x38,
+ 0x5F, 0xAD, 0x54, 0xDC, 0xA8, 0x32, 0x81, 0xDC,
+ 0x7A, 0x6F, 0x85, 0x58, 0x07, 0x35, 0xED, 0xEB,
+ 0xAD, 0x79, 0x79, 0x96, 0xD3, 0x0E, 0xA6, 0xD9,
+ 0xAA, 0x86, 0xA4, 0x8F, 0xB5, 0xD6, 0x6E, 0x6D,
+ 0x0C, 0x91, 0x2F, 0xC4, 0x67, 0x98, 0x0E, 0xC4,
+ 0x8D, 0x83, 0x68, 0x69, 0xC4, 0xD3, 0x94, 0x34,
+ 0xC4, 0x5D, 0x60, 0x55, 0x22, 0x87, 0x8F, 0x6F,
+ 0x17, 0x8E, 0x75, 0xE4, 0x02, 0xF5, 0x1B, 0x99,
+ 0xC8, 0x39, 0xA9, 0xAB, 0x23, 0x91, 0x12, 0xED,
+ 0x08, 0xE7, 0xD9, 0x25, 0x89, 0x24, 0x4F, 0x8D,
+ 0x68, 0xF3, 0x10, 0x39, 0x0A, 0xEE, 0x45, 0x24,
+ 0xDF, 0x7A, 0x9D, 0x00, 0x25, 0xE5, 0x35, 0x71,
+ 0x4E, 0x40, 0x59, 0x6F, 0x0A, 0x13, 0xB3, 0x72,
+ 0x1D, 0x98, 0x63, 0x94, 0x89, 0xA5, 0x39, 0x8E,
+ 0xD3, 0x9C, 0x8A, 0x7F, 0x71, 0x2F, 0xC7, 0xCD,
+ 0x81, 0x05, 0xDC, 0xC0, 0x8D, 0xCE, 0x6D, 0x18,
+ 0x30, 0xC4, 0x72, 0x51, 0xF0, 0x27, 0xC8, 0xF6,
+ 0x60, 0x5B, 0x7C, 0xB2, 0xE3, 0x49, 0x0C, 0x29,
+ 0xC6, 0x9F, 0x39, 0x57, 0x80, 0x55, 0x24, 0x2C,
+ 0x9B, 0x0F, 0x5A, 0xB3, 0x89, 0x55, 0x31, 0x96,
+ 0x0D, 0xCD, 0xF6, 0x51, 0x03, 0x2D, 0x89, 0x26,
+ 0x74, 0x44, 0xD6, 0xE8, 0xDC, 0xEA, 0x44, 0x55,
+ 0x64, 0x71, 0x9C, 0x9F, 0x5D, 0xBA, 0x39, 0x46,
+ 0xA8, 0x17, 0xA1, 0x9C, 0x52, 0x9D, 0xBC, 0x6B,
+ 0x4A, 0x98, 0xE6, 0xEA, 0x33, 0xEC, 0x58, 0xB4,
+ 0x43, 0xF0, 0x32, 0x45, 0xA4, 0xC1, 0x55, 0xB7,
+ 0x5D, 0xB5, 0x59, 0xB2, 0xE3, 0x96, 0xFF, 0xA5,
+ 0xAF, 0xE1, 0x86, 0x1B, 0x42, 0xE6, 0x3B, 0xA0,
+ 0x90, 0x4A, 0xE8, 0x8C, 0x21, 0x7F, 0x36, 0x1E,
+ 0x5B, 0x65, 0x25, 0xD1, 0xC1, 0x5A, 0xCA, 0x3D,
+ 0x10, 0xED, 0x2D, 0x79, 0xD0, 0x0F, 0x58, 0x44,
+ 0x69, 0x81, 0xF5, 0xD4, 0xC9, 0x0F, 0x90, 0x76,
+ 0x1F, 0x54, 0xD2, 0xD5, 0x97, 0xCE, 0x2C, 0xE3,
+ 0xEF, 0xF4, 0xB7, 0xC6, 0x3A, 0x87, 0x7F, 0x83,
+ 0x2A, 0xAF, 0xCD, 0x90, 0x12, 0xA7, 0x7D, 0x85,
+ 0x1D, 0x62, 0xD3, 0x85, 0x25, 0x05, 0xDB, 0x45,
+ 0x92, 0xA3, 0xF6, 0xA2, 0xA8, 0x41, 0xE4, 0x25,
+ 0x86, 0x87, 0x67, 0x24, 0xEC, 0x89, 0x23, 0x2A,
+ 0x9B, 0x20, 0x4D, 0x93, 0xEE, 0xE2, 0x2E, 0xC1,
+ 0x0B, 0x15, 0x33, 0xCF, 0x00, 0xD1, 0x1A, 0xDA,
+ 0x93, 0xFD, 0x28, 0x21, 0x5B, 0xCF, 0xD1, 0xF3,
+ 0x5A, 0x81, 0xBA, 0x82, 0x5E, 0x2F, 0x61, 0xB4,
+ 0x05, 0x71, 0xB5, 0xF4, 0x39, 0x3C, 0x1F, 0x60,
+ 0x00, 0x7A, 0xC4, 0xF8, 0x35, 0x20, 0x6C, 0x3A,
+ 0xCC, 0x03, 0x8F, 0x7B, 0xA2, 0xB6, 0x65, 0x8A,
+ 0xB6, 0x5F, 0xFD, 0x25, 0xD3, 0x5F, 0x92, 0xF9,
+ 0xAE, 0x17, 0x9B, 0x5E, 0x6E, 0x9A, 0xE4, 0x55,
+ 0x10, 0x25, 0x07, 0xA4, 0xAF, 0x21, 0x69, 0x13,
+ 0xD8, 0xFA, 0x31, 0xED, 0xF7, 0xA7, 0xA7, 0x3B,
+ 0xB8, 0x96, 0x8E, 0x10, 0x86, 0x74, 0xD8, 0xB1,
+ 0x34, 0x9E, 0x9B, 0x6A, 0x26, 0xA8, 0xD4, 0xD0,
+ 0xB5, 0xF6, 0xDE, 0xE7, 0xCA, 0x06, 0xDC, 0xA3,
+ 0x6F, 0xEE, 0x6B, 0x1E, 0xB5, 0x30, 0x99, 0x23,
+ 0xF9, 0x76, 0xF0, 0xA0, 0xCF, 0x3B, 0x94, 0x7B,
+ 0x19, 0x8D, 0xA5, 0x0C, 0x18, 0xA6, 0x1D, 0x07,
+ 0x89, 0xBE, 0x5B, 0x61, 0xE5, 0xF1, 0x42, 0xDB,
+ 0xD4, 0x2E, 0x02, 0x1F, 0xCE, 0xEF, 0x92, 0xB1,
+ 0x1B, 0x56, 0x50, 0xF2, 0x16, 0xE5, 0xE7, 0x4F,
+ 0xFD, 0xBB, 0x3E, 0xD2, 0xFC, 0x3C, 0xC6, 0x0F,
+ 0xF9, 0x12, 0x4E, 0xCB, 0x1E, 0x0C, 0x15, 0x84,
+ 0x2A, 0x14, 0x8A, 0x02, 0xE4, 0x7E, 0x95, 0x5B,
+ 0x86, 0xDB, 0x9B, 0x62, 0x5B, 0x19, 0xD2, 0x17,
+ 0xFA, 0x13, 0xBB, 0x6B, 0x3F, 0x45, 0x9F, 0xBF
+};
+
+
+static uint8_t ms_hmac_key0[] = {
+ 0xFF, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+};
+
+static const uint8_t ms_hmac_digest0[] = {
+ 0x43, 0x52, 0xED, 0x34, 0xAB, 0x36, 0xB2, 0x51,
+ 0xFB, 0xA3, 0xA6, 0x7C, 0x38, 0xFC, 0x42, 0x8F,
+ 0x57, 0x64, 0xAB, 0x81, 0xA7, 0x89, 0xB7, 0x6C,
+ 0xA0, 0xDC, 0xB9, 0x4D, 0xC4, 0x30, 0xF9, 0xD4,
+ 0x10, 0x82, 0x55, 0xD0, 0xAB, 0x32, 0xFB, 0x56,
+ 0x0D, 0xE4, 0x68, 0x3D, 0x76, 0xD0, 0x7B, 0xE4,
+ 0xA6, 0x2C, 0x34, 0x9E, 0x8C, 0x41, 0xF8, 0x23,
+ 0x28, 0x1B, 0x3A, 0x90, 0x26, 0x34, 0x47, 0x90
+ };
+
+/* End Session 0 */
+/* Begin session 1 */
+
+static uint8_t ms_aes_cbc_key1[] = {
+ 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static uint8_t ms_aes_cbc_iv1[] = {
+ 0xf1, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const uint8_t ms_aes_cbc_cipher1[] = {
+ 0x5A, 0x7A, 0x67, 0x5D, 0xB8, 0xE1, 0xDC, 0x71,
+ 0x39, 0xA8, 0x74, 0x93, 0x9C, 0x4C, 0xFE, 0x23,
+ 0x61, 0xCD, 0xA4, 0xB3, 0xD9, 0xCE, 0x99, 0x09,
+ 0x2A, 0x23, 0xF3, 0x29, 0xBF, 0x4C, 0xB4, 0x6A,
+ 0x1B, 0x6B, 0x73, 0x4D, 0x48, 0x0C, 0xCF, 0x6C,
+ 0x5E, 0x34, 0x9E, 0x7F, 0xBC, 0x8F, 0xCC, 0x8F,
+ 0x75, 0x1D, 0x3D, 0x77, 0x10, 0x76, 0xC8, 0xB9,
+ 0x99, 0x6F, 0xD6, 0x56, 0x75, 0xA9, 0xB2, 0x66,
+ 0xC2, 0x24, 0x2B, 0x9C, 0xFE, 0x40, 0x8E, 0x43,
+ 0x20, 0x97, 0x1B, 0xFA, 0xD0, 0xCF, 0x04, 0xAB,
+ 0xBB, 0xF6, 0x5D, 0xF5, 0xA0, 0x19, 0x7C, 0x23,
+ 0x5D, 0x80, 0x8C, 0x49, 0xF6, 0x76, 0x88, 0x29,
+ 0x27, 0x4C, 0x59, 0x2B, 0x43, 0xA6, 0xB2, 0x26,
+ 0x27, 0x78, 0xBE, 0x1B, 0xE1, 0x4F, 0x5A, 0x1F,
+ 0xFC, 0x68, 0x08, 0xE7, 0xC4, 0xD1, 0x34, 0x68,
+ 0xB7, 0x13, 0x14, 0x41, 0x62, 0x6B, 0x1F, 0x77,
+ 0x0C, 0x68, 0x1D, 0x0D, 0xED, 0x89, 0xAA, 0xD8,
+ 0x97, 0x02, 0xBA, 0x5E, 0xD4, 0x84, 0x25, 0x97,
+ 0x03, 0xA5, 0xA6, 0x13, 0x66, 0x02, 0xF4, 0xC3,
+ 0xF3, 0xD3, 0xCC, 0x95, 0xC3, 0x87, 0x46, 0x90,
+ 0x1F, 0x6E, 0x14, 0xA8, 0x00, 0xF2, 0x6F, 0xD5,
+ 0xA1, 0xAD, 0xD5, 0x40, 0xA2, 0x0F, 0x32, 0x7E,
+ 0x99, 0xA3, 0xF5, 0x53, 0xC3, 0x26, 0xA1, 0x45,
+ 0x01, 0x88, 0x57, 0x84, 0x3E, 0x7B, 0x4E, 0x0B,
+ 0x3C, 0xB5, 0x3E, 0x9E, 0xE9, 0x78, 0x77, 0xC5,
+ 0xC0, 0x89, 0xA8, 0xF8, 0xF1, 0xA5, 0x2D, 0x5D,
+ 0xF9, 0xC6, 0xFB, 0xCB, 0x05, 0x23, 0xBD, 0x6E,
+ 0x5E, 0x14, 0xC6, 0x57, 0x73, 0xCF, 0x98, 0xBD,
+ 0x10, 0x8B, 0x18, 0xA6, 0x01, 0x5B, 0x13, 0xAE,
+ 0x8E, 0xDE, 0x1F, 0xB5, 0xB7, 0x40, 0x6C, 0xC1,
+ 0x1E, 0xA1, 0x19, 0x20, 0x9E, 0x95, 0xE0, 0x2F,
+ 0x1C, 0xF5, 0xD9, 0xD0, 0x2B, 0x1E, 0x82, 0x25,
+ 0x62, 0xB4, 0xEB, 0xA1, 0x1F, 0xCE, 0x44, 0xA1,
+ 0xCB, 0x92, 0x01, 0x6B, 0xE4, 0x26, 0x23, 0xE3,
+ 0xC5, 0x67, 0x35, 0x55, 0xDA, 0xE5, 0x27, 0xEE,
+ 0x8D, 0x12, 0x84, 0xB7, 0xBA, 0xA7, 0x1C, 0xD6,
+ 0x32, 0x3F, 0x67, 0xED, 0xFB, 0x5B, 0x8B, 0x52,
+ 0x46, 0x8C, 0xF9, 0x69, 0xCD, 0xAE, 0x79, 0xAA,
+ 0x37, 0x78, 0x49, 0xEB, 0xC6, 0x8E, 0x76, 0x63,
+ 0x84, 0xFF, 0x9D, 0x22, 0x99, 0x51, 0xB7, 0x5E,
+ 0x83, 0x4C, 0x8B, 0xDF, 0x5A, 0x07, 0xCC, 0xBA,
+ 0x42, 0xA5, 0x98, 0xB6, 0x47, 0x0E, 0x66, 0xEB,
+ 0x23, 0x0E, 0xBA, 0x44, 0xA8, 0xAA, 0x20, 0x71,
+ 0x79, 0x9C, 0x77, 0x5F, 0xF5, 0xFE, 0xEC, 0xEF,
+ 0xC6, 0x64, 0x3D, 0x84, 0xD0, 0x2B, 0xA7, 0x0A,
+ 0xC3, 0x72, 0x5B, 0x9C, 0xFA, 0xA8, 0x87, 0x95,
+ 0x94, 0x11, 0x38, 0xA7, 0x1E, 0x58, 0xE3, 0x73,
+ 0xC6, 0xC9, 0xD1, 0x7B, 0x92, 0xDB, 0x0F, 0x49,
+ 0x74, 0xC2, 0xA2, 0x0E, 0x35, 0x57, 0xAC, 0xDB,
+ 0x9A, 0x1C, 0xCF, 0x5A, 0x32, 0x3E, 0x26, 0x9B,
+ 0xEC, 0xB3, 0xEF, 0x9C, 0xFE, 0xBE, 0x52, 0xAC,
+ 0xB1, 0x29, 0xDD, 0xFD, 0x07, 0xE2, 0xEE, 0xED,
+ 0xE4, 0x46, 0x37, 0xFE, 0xD1, 0xDC, 0xCD, 0x02,
+ 0xF9, 0x31, 0xB0, 0xFB, 0x36, 0xB7, 0x34, 0xA4,
+ 0x76, 0xE8, 0x57, 0xBF, 0x99, 0x92, 0xC7, 0xAF,
+ 0x98, 0x10, 0xE2, 0x70, 0xCA, 0xC9, 0x2B, 0x82,
+ 0x06, 0x96, 0x88, 0x0D, 0xB3, 0xAC, 0x9E, 0x6D,
+ 0x43, 0xBC, 0x5B, 0x31, 0xCF, 0x65, 0x8D, 0xA6,
+ 0xC7, 0xFE, 0x73, 0xE1, 0x54, 0xF7, 0x10, 0xF9,
+ 0x86, 0xF7, 0xDF, 0xA1, 0xA1, 0xD8, 0xAE, 0x35,
+ 0xB3, 0x90, 0xDC, 0x6F, 0x43, 0x7A, 0x8B, 0xE0,
+ 0xFE, 0x8F, 0x33, 0x4D, 0x29, 0x6C, 0x45, 0x53,
+ 0x73, 0xDD, 0x21, 0x0B, 0x85, 0x30, 0xB5, 0xA5,
+ 0xF3, 0x5D, 0xEC, 0x79, 0x61, 0x9D, 0x9E, 0xB3
+
+};
+
+static uint8_t ms_hmac_key1[] = {
+ 0xFE, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+};
+
+static const uint8_t ms_hmac_digest1[] = {
+ 0xCE, 0x6E, 0x5F, 0x77, 0x96, 0x9A, 0xB1, 0x69,
+ 0x2D, 0x5E, 0xF3, 0x2F, 0x32, 0x10, 0xCB, 0x50,
+ 0x0E, 0x09, 0x56, 0x25, 0x07, 0x34, 0xC9, 0x20,
+ 0xEC, 0x13, 0x43, 0x23, 0x5C, 0x08, 0x8B, 0xCD,
+ 0xDC, 0x86, 0x8C, 0xEE, 0x0A, 0x95, 0x2E, 0xB9,
+ 0x8C, 0x7B, 0x02, 0x7A, 0xD4, 0xE1, 0x49, 0xB4,
+ 0x45, 0xB5, 0x52, 0x37, 0xC6, 0xFF, 0xFE, 0xAA,
+ 0x0A, 0x87, 0xB8, 0x51, 0xF9, 0x2A, 0x01, 0x8F
+};
+/* End Session 1 */
+/* Begin Session 2 */
+static uint8_t ms_aes_cbc_key2[] = {
+ 0xff, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static uint8_t ms_aes_cbc_iv2[] = {
+ 0xff, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static const uint8_t ms_aes_cbc_cipher2[] = {
+ 0xBB, 0x3C, 0x68, 0x25, 0xFD, 0xB6, 0xA2, 0x91,
+ 0x20, 0x56, 0xF6, 0x30, 0x35, 0xFC, 0x9E, 0x97,
+ 0xF2, 0x90, 0xFC, 0x7E, 0x3E, 0x0A, 0x75, 0xC8,
+ 0x4C, 0xF2, 0x2D, 0xAC, 0xD3, 0x93, 0xF0, 0xC5,
+ 0x14, 0x88, 0x8A, 0x23, 0xC2, 0x59, 0x9A, 0x98,
+ 0x4B, 0xD5, 0x2C, 0xDA, 0x43, 0xA9, 0x34, 0x69,
+ 0x7C, 0x6D, 0xDB, 0xDC, 0xCB, 0xC0, 0xA0, 0x09,
+ 0xA7, 0x86, 0x16, 0x4B, 0xBF, 0xA8, 0xB6, 0xCF,
+ 0x7F, 0x74, 0x1F, 0x22, 0xF0, 0xF6, 0xBB, 0x44,
+ 0x8B, 0x4C, 0x9E, 0x23, 0xF8, 0x9F, 0xFC, 0x5B,
+ 0x9E, 0x9C, 0x2A, 0x79, 0x30, 0x8F, 0xBF, 0xA9,
+ 0x68, 0xA1, 0x20, 0x71, 0x7C, 0x77, 0x22, 0x34,
+ 0x07, 0xCD, 0xC6, 0xF6, 0x50, 0x0A, 0x08, 0x99,
+ 0x17, 0x98, 0xE3, 0x93, 0x8A, 0xB0, 0xEE, 0xDF,
+ 0xC2, 0xBA, 0x3B, 0x44, 0x73, 0xDF, 0xDD, 0xDC,
+ 0x14, 0x4D, 0x3B, 0xBB, 0x5E, 0x58, 0xC1, 0x26,
+ 0xA7, 0xAE, 0x47, 0xF3, 0x24, 0x6D, 0x4F, 0xD3,
+ 0x6E, 0x3E, 0x33, 0xE6, 0x7F, 0xCA, 0x50, 0xAF,
+ 0x5D, 0x3D, 0xA0, 0xDD, 0xC9, 0xF3, 0x30, 0xD3,
+ 0x6E, 0x8B, 0x2E, 0x12, 0x24, 0x34, 0xF0, 0xD3,
+ 0xC7, 0x8D, 0x23, 0x29, 0xAA, 0x05, 0xE1, 0xFA,
+ 0x2E, 0xF6, 0x8D, 0x37, 0x86, 0xC0, 0x6D, 0x13,
+ 0x2D, 0x98, 0xF3, 0x52, 0x39, 0x22, 0xCE, 0x38,
+ 0xC2, 0x1A, 0x72, 0xED, 0xFB, 0xCC, 0xE4, 0x71,
+ 0x5A, 0x0C, 0x0D, 0x09, 0xF8, 0xE8, 0x1B, 0xBC,
+ 0x53, 0xC8, 0xD8, 0x8F, 0xE5, 0x98, 0x5A, 0xB1,
+ 0x06, 0xA6, 0x5B, 0xE6, 0xA2, 0x88, 0x21, 0x9E,
+ 0x36, 0xC0, 0x34, 0xF9, 0xFB, 0x3B, 0x0A, 0x22,
+ 0x00, 0x00, 0x39, 0x48, 0x8D, 0x23, 0x74, 0x62,
+ 0x72, 0x91, 0xE6, 0x36, 0xAA, 0x77, 0x9C, 0x72,
+ 0x9D, 0xA8, 0xC3, 0xA9, 0xD5, 0x44, 0x72, 0xA6,
+ 0xB9, 0x28, 0x8F, 0x64, 0x4C, 0x8A, 0x64, 0xE6,
+ 0x4E, 0xFA, 0xEF, 0x87, 0xDE, 0x7B, 0x22, 0x44,
+ 0xB0, 0xDF, 0x2E, 0x5F, 0x0B, 0xA5, 0xF2, 0x24,
+ 0x07, 0x5C, 0x2D, 0x39, 0xB7, 0x3D, 0x8A, 0xE5,
+ 0x0E, 0x9D, 0x4E, 0x50, 0xED, 0x03, 0x99, 0x8E,
+ 0xF0, 0x06, 0x55, 0x4E, 0xA2, 0x24, 0xE7, 0x17,
+ 0x46, 0xDF, 0x6C, 0xCD, 0xC6, 0x44, 0xE8, 0xF9,
+ 0xB9, 0x1B, 0x36, 0xF6, 0x7F, 0x10, 0xA4, 0x7D,
+ 0x90, 0xBD, 0xE4, 0xAA, 0xD6, 0x9E, 0x18, 0x9D,
+ 0x22, 0x35, 0xD6, 0x55, 0x54, 0xAA, 0xF7, 0x22,
+ 0xA3, 0x3E, 0xEF, 0xC8, 0xA2, 0x34, 0x8D, 0xA9,
+ 0x37, 0x63, 0xA6, 0xC3, 0x57, 0xCB, 0x0C, 0x49,
+ 0x7D, 0x02, 0xBE, 0xAA, 0x13, 0x75, 0xB7, 0x4E,
+ 0x52, 0x62, 0xA5, 0xC2, 0x33, 0xC7, 0x6C, 0x1B,
+ 0xF6, 0x34, 0xF6, 0x09, 0xA5, 0x0C, 0xC7, 0xA2,
+ 0x61, 0x48, 0x62, 0x7D, 0x17, 0x15, 0xE3, 0x95,
+ 0xC8, 0x63, 0xD2, 0xA4, 0x43, 0xA9, 0x49, 0x07,
+ 0xB2, 0x3B, 0x2B, 0x62, 0x7D, 0xCB, 0x51, 0xB3,
+ 0x25, 0x33, 0x47, 0x0E, 0x14, 0x67, 0xDC, 0x6A,
+ 0x9B, 0x51, 0xAC, 0x9D, 0x8F, 0xA2, 0x2B, 0x57,
+ 0x8C, 0x5C, 0x5F, 0x76, 0x23, 0x92, 0x0F, 0x84,
+ 0x46, 0x0E, 0x40, 0x85, 0x38, 0x60, 0xFA, 0x61,
+ 0x20, 0xC5, 0xE3, 0xF1, 0x70, 0xAC, 0x1B, 0xBF,
+ 0xC4, 0x2B, 0xC5, 0x67, 0xD1, 0x43, 0xC5, 0x17,
+ 0x74, 0x71, 0x69, 0x6F, 0x82, 0x89, 0x19, 0x8A,
+ 0x70, 0x43, 0x92, 0x01, 0xC4, 0x63, 0x7E, 0xB1,
+ 0x59, 0x4E, 0xCD, 0xEA, 0x93, 0xA4, 0x52, 0x53,
+ 0x9B, 0x61, 0x5B, 0xD2, 0x3E, 0x19, 0x39, 0xB7,
+ 0x32, 0xEA, 0x8E, 0xF8, 0x1D, 0x76, 0x5C, 0xB2,
+ 0x73, 0x2D, 0x91, 0xC0, 0x18, 0xED, 0x25, 0x2A,
+ 0x53, 0x64, 0xF0, 0x92, 0x31, 0x55, 0x21, 0xA8,
+ 0x24, 0xA9, 0xD1, 0x02, 0xF6, 0x6C, 0x2B, 0x70,
+ 0xA9, 0x59, 0xC1, 0xD6, 0xC3, 0x57, 0x5B, 0x92
+};
+
+static uint8_t ms_hmac_key2[] = {
+ 0xFC, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+};
+
+static const uint8_t ms_hmac_digest2[] = {
+ 0xA5, 0x0F, 0x9C, 0xFB, 0x08, 0x62, 0x59, 0xFF,
+ 0x80, 0x2F, 0xEB, 0x4B, 0xE1, 0x46, 0x21, 0xD6,
+ 0x02, 0x98, 0xF2, 0x8E, 0xF4, 0xEC, 0xD4, 0x77,
+ 0x86, 0x4C, 0x31, 0x28, 0xC8, 0x25, 0x80, 0x27,
+ 0x3A, 0x72, 0x5D, 0x6A, 0x56, 0x8A, 0xD3, 0x82,
+ 0xB0, 0xEC, 0x31, 0x6D, 0x8B, 0x6B, 0xB4, 0x24,
+ 0xE7, 0x62, 0xC1, 0x52, 0xBC, 0x14, 0x1B, 0x8E,
+ 0xEC, 0x9A, 0xF1, 0x47, 0x80, 0xD2, 0xB0, 0x59
+};
+
+/* End Session 2 */
+
+
+static int
+test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data and space for digest */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ catch_22_quote, QUOTE_512_BYTES, 0);
+
+ ut_params->digest = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ DIGEST_BYTE_LENGTH_SHA1);
+ TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+ ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = CIPHER_IV_LENGTH_AES_CBC;
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA1;
+ ut_params->auth_xform.auth.key.data = hmac_sha1_key;
+ ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ /* Generate crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* Set crypto operation authentication parameters */
+ sym_op->auth.digest.data = ut_params->digest;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, QUOTE_512_BYTES);
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = QUOTE_512_BYTES;
+
+ /* Copy IV at the end of the crypto operation */
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ aes_cbc_iv, CIPHER_IV_LENGTH_AES_CBC);
+
+ /* Set crypto operation cipher parameters */
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = QUOTE_512_BYTES;
+
+ /* Process crypto operation */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op),
+ "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ /* Validate obuf */
+ uint8_t *ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_src,
+ uint8_t *);
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(ciphertext,
+ catch_22_quote_2_512_bytes_AES_CBC_ciphertext,
+ QUOTE_512_BYTES,
+ "ciphertext data not as expected");
+
+ uint8_t *digest = ciphertext + QUOTE_512_BYTES;
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(digest,
+ catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest,
+ gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD)) ?
+ TRUNCATED_DIGEST_BYTE_LENGTH_SHA1 :
+ DIGEST_BYTE_LENGTH_SHA1,
+ "Generated digest data not as expected");
+
+ return TEST_SUCCESS;
+}
+
+/* ***** AES-CBC / HMAC-SHA512 Hash Tests ***** */
+
+#define HMAC_KEY_LENGTH_SHA512 (DIGEST_BYTE_LENGTH_SHA512)
+
+static uint8_t hmac_sha512_key[] = {
+ 0x42, 0x1a, 0x7d, 0x3d, 0xf5, 0x82, 0x80, 0xf1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9a, 0xaf, 0x88, 0x1b, 0xb6, 0x8f, 0xf8, 0x60,
+ 0xa2, 0x5a, 0x7f, 0x3f, 0xf4, 0x72, 0x70, 0xf1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3a, 0x75, 0x61, 0x5C, 0xa2, 0x10, 0x76,
+ 0x9a, 0xaf, 0x77, 0x5b, 0xb6, 0x7f, 0xf7, 0x60 };
+
+static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA512_digest[] = {
+ 0x5D, 0x54, 0x66, 0xC1, 0x6E, 0xBC, 0x04, 0xB8,
+ 0x46, 0xB8, 0x08, 0x6E, 0xE0, 0xF0, 0x43, 0x48,
+ 0x37, 0x96, 0x9C, 0xC6, 0x9C, 0xC2, 0x1E, 0xE8,
+ 0xF2, 0x0C, 0x0B, 0xEF, 0x86, 0xA2, 0xE3, 0x70,
+ 0x95, 0xC8, 0xB3, 0x06, 0x47, 0xA9, 0x90, 0xE8,
+ 0xA0, 0xC6, 0x72, 0x69, 0x05, 0xC0, 0x0D, 0x0E,
+ 0x21, 0x96, 0x65, 0x93, 0x74, 0x43, 0x2A, 0x1D,
+ 0x2E, 0xBF, 0xC2, 0xC2, 0xEE, 0xCC, 0x2F, 0x0A };
+
+
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(
+ struct crypto_unittest_params *ut_params,
+ uint8_t *cipher_key,
+ uint8_t *hmac_key);
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_sym_session *sess,
+ struct crypto_unittest_params *ut_params,
+ struct crypto_testsuite_params *ts_params,
+ const uint8_t *cipher,
+ const uint8_t *digest,
+ const uint8_t *iv);
+
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(
+ struct crypto_unittest_params *ut_params,
+ uint8_t *cipher_key,
+ uint8_t *hmac_key)
+{
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ ut_params->cipher_xform.cipher.key.data = cipher_key;
+ ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = CIPHER_IV_LENGTH_AES_CBC;
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
+ ut_params->auth_xform.auth.key.data = hmac_key;
+ ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA512;
+ ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA512;
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_sym_session *sess,
+ struct crypto_unittest_params *ut_params,
+ struct crypto_testsuite_params *ts_params,
+ const uint8_t *cipher,
+ const uint8_t *digest,
+ const uint8_t *iv)
+{
+ /* Generate test mbuf data and digest */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ (const char *)
+ cipher,
+ QUOTE_512_BYTES, 0);
+
+ ut_params->digest = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ DIGEST_BYTE_LENGTH_SHA512);
+ TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
+
+ rte_memcpy(ut_params->digest,
+ digest,
+ DIGEST_BYTE_LENGTH_SHA512);
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ rte_crypto_op_attach_sym_session(ut_params->op, sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ sym_op->auth.digest.data = ut_params->digest;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, QUOTE_512_BYTES);
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = QUOTE_512_BYTES;
+
+ /* Copy IV at the end of the crypto operation */
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ iv, CIPHER_IV_LENGTH_AES_CBC);
+
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = QUOTE_512_BYTES;
+
+ /* Process crypto operation */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op),
+ "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ ut_params->obuf = ut_params->op->sym->m_src;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ rte_pktmbuf_mtod(ut_params->obuf, uint8_t *),
+ catch_22_quote,
+ QUOTE_512_BYTES,
+ "Plaintext data not as expected");
+
+ /* Validate obuf */
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "Digest verification failed");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_blockcipher(enum blockcipher_test_type test_type)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ int status;
+
+ status = test_blockcipher_all_tests(ts_params->mbuf_pool,
+ ts_params->op_mpool,
+ ts_params->session_mpool, ts_params->session_priv_mpool,
+ ts_params->valid_devs[0],
+ test_type);
+
+ if (status == -ENOTSUP)
+ return status;
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_cipheronly_all(void)
+{
+ return test_blockcipher(BLKCIPHER_AES_CIPHERONLY_TYPE);
+}
+
+static int
+test_AES_docsis_all(void)
+{
+ return test_blockcipher(BLKCIPHER_AES_DOCSIS_TYPE);
+}
+
+static int
+test_DES_docsis_all(void)
+{
+ return test_blockcipher(BLKCIPHER_DES_DOCSIS_TYPE);
+}
+
+static int
+test_DES_cipheronly_all(void)
+{
+ return test_blockcipher(BLKCIPHER_DES_CIPHERONLY_TYPE);
+}
+
+static int
+test_authonly_all(void)
+{
+ return test_blockcipher(BLKCIPHER_AUTHONLY_TYPE);
+}
+
+static int
+test_AES_chain_all(void)
+{
+ return test_blockcipher(BLKCIPHER_AES_CHAIN_TYPE);
+}
+
+static int
+test_3DES_chain_all(void)
+{
+ return test_blockcipher(BLKCIPHER_3DES_CHAIN_TYPE);
+}
+
+static int
+test_3DES_cipheronly_all(void)
+{
+ return test_blockcipher(BLKCIPHER_3DES_CIPHERONLY_TYPE);
+}
+
+/* ***** SNOW 3G Tests ***** */
+static int
+create_wireless_algo_hash_session(uint8_t dev_id,
+ const uint8_t *key, const uint8_t key_len,
+ const uint8_t iv_len, const uint8_t auth_len,
+ enum rte_crypto_auth_operation op,
+ enum rte_crypto_auth_algorithm algo)
+{
+ uint8_t hash_key[key_len];
+ int status;
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(hash_key, key, key_len);
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.op = op;
+ ut_params->auth_xform.auth.algo = algo;
+ ut_params->auth_xform.auth.key.length = key_len;
+ ut_params->auth_xform.auth.key.data = hash_key;
+ ut_params->auth_xform.auth.digest_length = auth_len;
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET;
+ ut_params->auth_xform.auth.iv.length = iv_len;
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_EQUAL(status, 0, "session init failed");
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+ return 0;
+}
+
+static int
+create_wireless_algo_cipher_session(uint8_t dev_id,
+ enum rte_crypto_cipher_operation op,
+ enum rte_crypto_cipher_algorithm algo,
+ const uint8_t *key, const uint8_t key_len,
+ uint8_t iv_len)
+{
+ uint8_t cipher_key[key_len];
+ int status;
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(cipher_key, key, key_len);
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+
+ ut_params->cipher_xform.cipher.algo = algo;
+ ut_params->cipher_xform.cipher.op = op;
+ ut_params->cipher_xform.cipher.key.data = cipher_key;
+ ut_params->cipher_xform.cipher.key.length = key_len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = iv_len;
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Create Crypto session */
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_EQUAL(status, 0, "session init failed");
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+ return 0;
+}
+
+static int
+create_wireless_algo_cipher_operation(const uint8_t *iv, uint8_t iv_len,
+ unsigned int cipher_len,
+ unsigned int cipher_offset)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* iv */
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ iv, iv_len);
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = cipher_offset;
+ return 0;
+}
+
+static int
+create_wireless_algo_cipher_operation_oop(const uint8_t *iv, uint8_t iv_len,
+ unsigned int cipher_len,
+ unsigned int cipher_offset)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+ sym_op->m_dst = ut_params->obuf;
+
+ /* iv */
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ iv, iv_len);
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = cipher_offset;
+ return 0;
+}
+
+static int
+create_wireless_algo_cipher_auth_session(uint8_t dev_id,
+ enum rte_crypto_cipher_operation cipher_op,
+ enum rte_crypto_auth_operation auth_op,
+ enum rte_crypto_auth_algorithm auth_algo,
+ enum rte_crypto_cipher_algorithm cipher_algo,
+ const uint8_t *key, uint8_t key_len,
+ uint8_t auth_iv_len, uint8_t auth_len,
+ uint8_t cipher_iv_len)
+
+{
+ uint8_t cipher_auth_key[key_len];
+ int status;
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(cipher_auth_key, key, key_len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.auth.algo = auth_algo;
+ ut_params->auth_xform.auth.key.length = key_len;
+ /* Hash key = cipher key */
+ ut_params->auth_xform.auth.key.data = cipher_auth_key;
+ ut_params->auth_xform.auth.digest_length = auth_len;
+ /* Auth IV will be after cipher IV */
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET + cipher_iv_len;
+ ut_params->auth_xform.auth.iv.length = auth_iv_len;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ ut_params->cipher_xform.cipher.algo = cipher_algo;
+ ut_params->cipher_xform.cipher.op = cipher_op;
+ ut_params->cipher_xform.cipher.key.data = cipher_auth_key;
+ ut_params->cipher_xform.cipher.key.length = key_len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = cipher_iv_len;
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ if (status == -ENOTSUP)
+ return status;
+
+ TEST_ASSERT_EQUAL(status, 0, "session init failed");
+ return 0;
+}
+
+static int
+create_wireless_cipher_auth_session(uint8_t dev_id,
+ enum rte_crypto_cipher_operation cipher_op,
+ enum rte_crypto_auth_operation auth_op,
+ enum rte_crypto_auth_algorithm auth_algo,
+ enum rte_crypto_cipher_algorithm cipher_algo,
+ const struct wireless_test_data *tdata)
+{
+ const uint8_t key_len = tdata->key.len;
+ uint8_t cipher_auth_key[key_len];
+ int status;
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ const uint8_t *key = tdata->key.data;
+ const uint8_t auth_len = tdata->digest.len;
+ uint8_t cipher_iv_len = tdata->cipher_iv.len;
+ uint8_t auth_iv_len = tdata->auth_iv.len;
+
+ memcpy(cipher_auth_key, key, key_len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.auth.algo = auth_algo;
+ ut_params->auth_xform.auth.key.length = key_len;
+ /* Hash key = cipher key */
+ ut_params->auth_xform.auth.key.data = cipher_auth_key;
+ ut_params->auth_xform.auth.digest_length = auth_len;
+ /* Auth IV will be after cipher IV */
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET + cipher_iv_len;
+ ut_params->auth_xform.auth.iv.length = auth_iv_len;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ ut_params->cipher_xform.cipher.algo = cipher_algo;
+ ut_params->cipher_xform.cipher.op = cipher_op;
+ ut_params->cipher_xform.cipher.key.data = cipher_auth_key;
+ ut_params->cipher_xform.cipher.key.length = key_len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = cipher_iv_len;
+
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ if (status == -ENOTSUP)
+ return status;
+
+ TEST_ASSERT_EQUAL(status, 0, "session init failed");
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+ return 0;
+}
+
+static int
+create_zuc_cipher_auth_encrypt_generate_session(uint8_t dev_id,
+ const struct wireless_test_data *tdata)
+{
+ return create_wireless_cipher_auth_session(dev_id,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE, RTE_CRYPTO_AUTH_ZUC_EIA3,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3, tdata);
+}
+
+static int
+create_wireless_algo_auth_cipher_session(uint8_t dev_id,
+ enum rte_crypto_cipher_operation cipher_op,
+ enum rte_crypto_auth_operation auth_op,
+ enum rte_crypto_auth_algorithm auth_algo,
+ enum rte_crypto_cipher_algorithm cipher_algo,
+ const uint8_t *key, const uint8_t key_len,
+ uint8_t auth_iv_len, uint8_t auth_len,
+ uint8_t cipher_iv_len)
+{
+ uint8_t auth_cipher_key[key_len];
+ int status;
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(auth_cipher_key, key, key_len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+ ut_params->auth_xform.auth.algo = auth_algo;
+ ut_params->auth_xform.auth.key.length = key_len;
+ ut_params->auth_xform.auth.key.data = auth_cipher_key;
+ ut_params->auth_xform.auth.digest_length = auth_len;
+ /* Auth IV will be after cipher IV */
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET + cipher_iv_len;
+ ut_params->auth_xform.auth.iv.length = auth_iv_len;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+ ut_params->cipher_xform.cipher.algo = cipher_algo;
+ ut_params->cipher_xform.cipher.op = cipher_op;
+ ut_params->cipher_xform.cipher.key.data = auth_cipher_key;
+ ut_params->cipher_xform.cipher.key.length = key_len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = cipher_iv_len;
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ if (cipher_op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
+ ut_params->auth_xform.next = NULL;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+
+ } else
+ status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ if (status == -ENOTSUP)
+ return status;
+
+ TEST_ASSERT_EQUAL(status, 0, "session init failed");
+
+ return 0;
+}
+
+static int
+create_wireless_algo_hash_operation(const uint8_t *auth_tag,
+ unsigned int auth_tag_len,
+ const uint8_t *iv, unsigned int iv_len,
+ unsigned int data_pad_len,
+ enum rte_crypto_auth_operation op,
+ unsigned int auth_len, unsigned int auth_offset)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* iv */
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ iv, iv_len);
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, auth_tag_len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+ ut_params->digest = sym_op->auth.digest.data;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, data_pad_len);
+ if (op == RTE_CRYPTO_AUTH_OP_GENERATE)
+ memset(sym_op->auth.digest.data, 0, auth_tag_len);
+ else
+ rte_memcpy(sym_op->auth.digest.data, auth_tag, auth_tag_len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ auth_tag_len);
+
+ sym_op->auth.data.length = auth_len;
+ sym_op->auth.data.offset = auth_offset;
+
+ return 0;
+}
+
+static int
+create_wireless_cipher_hash_operation(const struct wireless_test_data *tdata,
+ enum rte_crypto_auth_operation op)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ const uint8_t *auth_tag = tdata->digest.data;
+ const unsigned int auth_tag_len = tdata->digest.len;
+ unsigned int plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ unsigned int data_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ const uint8_t *cipher_iv = tdata->cipher_iv.data;
+ const uint8_t cipher_iv_len = tdata->cipher_iv.len;
+ const uint8_t *auth_iv = tdata->auth_iv.data;
+ const uint8_t auth_iv_len = tdata->auth_iv.len;
+ const unsigned int cipher_len = tdata->validCipherLenInBits.len;
+ const unsigned int auth_len = tdata->validAuthLenInBits.len;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, auth_tag_len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+ ut_params->digest = sym_op->auth.digest.data;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, data_pad_len);
+ if (op == RTE_CRYPTO_AUTH_OP_GENERATE)
+ memset(sym_op->auth.digest.data, 0, auth_tag_len);
+ else
+ rte_memcpy(sym_op->auth.digest.data, auth_tag, auth_tag_len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ auth_tag_len);
+
+ /* Copy cipher and auth IVs at the end of the crypto operation */
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op, uint8_t *,
+ IV_OFFSET);
+ rte_memcpy(iv_ptr, cipher_iv, cipher_iv_len);
+ iv_ptr += cipher_iv_len;
+ rte_memcpy(iv_ptr, auth_iv, auth_iv_len);
+
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = 0;
+ sym_op->auth.data.length = auth_len;
+ sym_op->auth.data.offset = 0;
+
+ return 0;
+}
+
+static int
+create_zuc_cipher_hash_generate_operation(
+ const struct wireless_test_data *tdata)
+{
+ return create_wireless_cipher_hash_operation(tdata,
+ RTE_CRYPTO_AUTH_OP_GENERATE);
+}
+
+static int
+create_wireless_algo_cipher_hash_operation(const uint8_t *auth_tag,
+ const unsigned auth_tag_len,
+ const uint8_t *auth_iv, uint8_t auth_iv_len,
+ unsigned data_pad_len,
+ enum rte_crypto_auth_operation op,
+ const uint8_t *cipher_iv, uint8_t cipher_iv_len,
+ const unsigned cipher_len, const unsigned cipher_offset,
+ const unsigned auth_len, const unsigned auth_offset)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ enum rte_crypto_cipher_algorithm cipher_algo =
+ ut_params->cipher_xform.cipher.algo;
+ enum rte_crypto_auth_algorithm auth_algo =
+ ut_params->auth_xform.auth.algo;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, auth_tag_len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+ ut_params->digest = sym_op->auth.digest.data;
+
+ if (rte_pktmbuf_is_contiguous(ut_params->ibuf)) {
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, data_pad_len);
+ } else {
+ struct rte_mbuf *m = ut_params->ibuf;
+ unsigned int offset = data_pad_len;
+
+ while (offset > m->data_len && m->next != NULL) {
+ offset -= m->data_len;
+ m = m->next;
+ }
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ m, offset);
+ }
+
+ if (op == RTE_CRYPTO_AUTH_OP_GENERATE)
+ memset(sym_op->auth.digest.data, 0, auth_tag_len);
+ else
+ rte_memcpy(sym_op->auth.digest.data, auth_tag, auth_tag_len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ auth_tag_len);
+
+ /* Copy cipher and auth IVs at the end of the crypto operation */
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op, uint8_t *,
+ IV_OFFSET);
+ rte_memcpy(iv_ptr, cipher_iv, cipher_iv_len);
+ iv_ptr += cipher_iv_len;
+ rte_memcpy(iv_ptr, auth_iv, auth_iv_len);
+
+ if (cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) {
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = cipher_offset;
+ } else {
+ sym_op->cipher.data.length = cipher_len >> 3;
+ sym_op->cipher.data.offset = cipher_offset >> 3;
+ }
+
+ if (auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) {
+ sym_op->auth.data.length = auth_len;
+ sym_op->auth.data.offset = auth_offset;
+ } else {
+ sym_op->auth.data.length = auth_len >> 3;
+ sym_op->auth.data.offset = auth_offset >> 3;
+ }
+
+ return 0;
+}
+
+static int
+create_wireless_algo_auth_cipher_operation(
+ const uint8_t *auth_tag, unsigned int auth_tag_len,
+ const uint8_t *cipher_iv, uint8_t cipher_iv_len,
+ const uint8_t *auth_iv, uint8_t auth_iv_len,
+ unsigned int data_pad_len,
+ unsigned int cipher_len, unsigned int cipher_offset,
+ unsigned int auth_len, unsigned int auth_offset,
+ uint8_t op_mode, uint8_t do_sgl, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ enum rte_crypto_cipher_algorithm cipher_algo =
+ ut_params->cipher_xform.cipher.algo;
+ enum rte_crypto_auth_algorithm auth_algo =
+ ut_params->auth_xform.auth.algo;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation mbufs */
+ sym_op->m_src = ut_params->ibuf;
+ if (op_mode == OUT_OF_PLACE)
+ sym_op->m_dst = ut_params->obuf;
+
+ /* digest */
+ if (!do_sgl) {
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(
+ (op_mode == IN_PLACE ?
+ ut_params->ibuf : ut_params->obuf),
+ uint8_t *, data_pad_len);
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ (op_mode == IN_PLACE ?
+ ut_params->ibuf : ut_params->obuf),
+ data_pad_len);
+ memset(sym_op->auth.digest.data, 0, auth_tag_len);
+ } else {
+ uint16_t remaining_off = (auth_offset >> 3) + (auth_len >> 3);
+ struct rte_mbuf *sgl_buf = (op_mode == IN_PLACE ?
+ sym_op->m_src : sym_op->m_dst);
+ while (remaining_off >= rte_pktmbuf_data_len(sgl_buf)) {
+ remaining_off -= rte_pktmbuf_data_len(sgl_buf);
+ sgl_buf = sgl_buf->next;
+ }
+ sym_op->auth.digest.data = rte_pktmbuf_mtod_offset(sgl_buf,
+ uint8_t *, remaining_off);
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(sgl_buf,
+ remaining_off);
+ memset(sym_op->auth.digest.data, 0, remaining_off);
+ while (sgl_buf->next != NULL) {
+ memset(rte_pktmbuf_mtod(sgl_buf, uint8_t *),
+ 0, rte_pktmbuf_data_len(sgl_buf));
+ sgl_buf = sgl_buf->next;
+ }
+ }
+
+ /* Copy digest for the verification */
+ if (verify)
+ memcpy(sym_op->auth.digest.data, auth_tag, auth_tag_len);
+
+ /* Copy cipher and auth IVs at the end of the crypto operation */
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(
+ ut_params->op, uint8_t *, IV_OFFSET);
+
+ rte_memcpy(iv_ptr, cipher_iv, cipher_iv_len);
+ iv_ptr += cipher_iv_len;
+ rte_memcpy(iv_ptr, auth_iv, auth_iv_len);
+
+ if (cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+ cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+ cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) {
+ sym_op->cipher.data.length = cipher_len;
+ sym_op->cipher.data.offset = cipher_offset;
+ } else {
+ sym_op->cipher.data.length = cipher_len >> 3;
+ sym_op->cipher.data.offset = cipher_offset >> 3;
+ }
+
+ if (auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+ auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+ auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) {
+ sym_op->auth.data.length = auth_len;
+ sym_op->auth.data.offset = auth_offset;
+ } else {
+ sym_op->auth.data.length = auth_len >> 3;
+ sym_op->auth.data.offset = auth_offset >> 3;
+ }
+
+ return 0;
+}
+
+static int
+test_snow3g_authentication(const struct snow3g_hash_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ uint8_t *plaintext;
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA) &&
+ ((tdata->validAuthLenInBits.len % 8) != 0)) {
+ printf("Device doesn't support NON-Byte Aligned Data.\n");
+ return -ENOTSUP;
+ }
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_hash_session(ts_params->valid_devs[0],
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ RTE_CRYPTO_AUTH_SNOW3G_UIA2);
+ if (retval < 0)
+ return retval;
+
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_hash_operation(NULL, tdata->digest.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ plaintext_pad_len, RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->validAuthLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ ut_params->obuf = ut_params->op->sym->m_src;
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "SNOW 3G Generated auth tag not as expected");
+
+ return 0;
+}
+
+static int
+test_snow3g_authentication_verify(const struct snow3g_hash_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ uint8_t *plaintext;
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA) &&
+ ((tdata->validAuthLenInBits.len % 8) != 0)) {
+ printf("Device doesn't support NON-Byte Aligned Data.\n");
+ return -ENOTSUP;
+ }
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_hash_session(ts_params->valid_devs[0],
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ RTE_CRYPTO_AUTH_SNOW3G_UIA2);
+ if (retval < 0)
+ return retval;
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_hash_operation(tdata->digest.data,
+ tdata->digest.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ plaintext_pad_len,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ tdata->validAuthLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_src;
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ if (ut_params->op->status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+ return 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int
+test_kasumi_authentication(const struct kasumi_hash_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ uint8_t *plaintext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_KASUMI_F9;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_hash_session(ts_params->valid_devs[0],
+ tdata->key.data, tdata->key.len,
+ 0, tdata->digest.len,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ RTE_CRYPTO_AUTH_KASUMI_F9);
+ if (retval < 0)
+ return retval;
+
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_hash_operation(NULL, tdata->digest.len,
+ NULL, 0,
+ plaintext_pad_len, RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->plaintext.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ ut_params->obuf = ut_params->op->sym->m_src;
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_KASUMI_F9,
+ "KASUMI Generated auth tag not as expected");
+
+ return 0;
+}
+
+static int
+test_kasumi_authentication_verify(const struct kasumi_hash_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ uint8_t *plaintext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_KASUMI_F9;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_hash_session(ts_params->valid_devs[0],
+ tdata->key.data, tdata->key.len,
+ 0, tdata->digest.len,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ RTE_CRYPTO_AUTH_KASUMI_F9);
+ if (retval < 0)
+ return retval;
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_hash_operation(tdata->digest.data,
+ tdata->digest.len,
+ NULL, 0,
+ plaintext_pad_len,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ tdata->plaintext.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_src;
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ if (ut_params->op->status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+ return 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int
+test_snow3g_hash_generate_test_case_1(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_1);
+}
+
+static int
+test_snow3g_hash_generate_test_case_2(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_2);
+}
+
+static int
+test_snow3g_hash_generate_test_case_3(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_3);
+}
+
+static int
+test_snow3g_hash_generate_test_case_4(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_4);
+}
+
+static int
+test_snow3g_hash_generate_test_case_5(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_5);
+}
+
+static int
+test_snow3g_hash_generate_test_case_6(void)
+{
+ return test_snow3g_authentication(&snow3g_hash_test_case_6);
+}
+
+static int
+test_snow3g_hash_verify_test_case_1(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_1);
+
+}
+
+static int
+test_snow3g_hash_verify_test_case_2(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_2);
+}
+
+static int
+test_snow3g_hash_verify_test_case_3(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_3);
+}
+
+static int
+test_snow3g_hash_verify_test_case_4(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_4);
+}
+
+static int
+test_snow3g_hash_verify_test_case_5(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_5);
+}
+
+static int
+test_snow3g_hash_verify_test_case_6(void)
+{
+ return test_snow3g_authentication_verify(&snow3g_hash_test_case_6);
+}
+
+static int
+test_kasumi_hash_generate_test_case_1(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_1);
+}
+
+static int
+test_kasumi_hash_generate_test_case_2(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_2);
+}
+
+static int
+test_kasumi_hash_generate_test_case_3(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_3);
+}
+
+static int
+test_kasumi_hash_generate_test_case_4(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_4);
+}
+
+static int
+test_kasumi_hash_generate_test_case_5(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_5);
+}
+
+static int
+test_kasumi_hash_generate_test_case_6(void)
+{
+ return test_kasumi_authentication(&kasumi_hash_test_case_6);
+}
+
+static int
+test_kasumi_hash_verify_test_case_1(void)
+{
+ return test_kasumi_authentication_verify(&kasumi_hash_test_case_1);
+}
+
+static int
+test_kasumi_hash_verify_test_case_2(void)
+{
+ return test_kasumi_authentication_verify(&kasumi_hash_test_case_2);
+}
+
+static int
+test_kasumi_hash_verify_test_case_3(void)
+{
+ return test_kasumi_authentication_verify(&kasumi_hash_test_case_3);
+}
+
+static int
+test_kasumi_hash_verify_test_case_4(void)
+{
+ return test_kasumi_authentication_verify(&kasumi_hash_test_case_4);
+}
+
+static int
+test_kasumi_hash_verify_test_case_5(void)
+{
+ return test_kasumi_authentication_verify(&kasumi_hash_test_case_5);
+}
+
+static int
+test_kasumi_encryption(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext + (tdata->validCipherOffsetInBits.len >> 3);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ const uint8_t *reference_ciphertext = tdata->ciphertext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ reference_ciphertext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+
+ uint8_t buffer[10000];
+ const uint8_t *ciphertext;
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10, 0);
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+ tdata->validCipherOffsetInBits.len >> 3,
+ plaintext_len, buffer);
+
+ /* Validate obuf */
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ const uint8_t *reference_ciphertext = tdata->ciphertext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ reference_ciphertext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+static int
+test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext + (tdata->validCipherOffsetInBits.len >> 3);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ const uint8_t *reference_ciphertext = tdata->ciphertext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ reference_ciphertext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+
+ const uint8_t *ciphertext;
+ uint8_t buffer[2048];
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10, 0);
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 3, 0);
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_pad_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+ tdata->validCipherOffsetInBits.len >> 3,
+ plaintext_pad_len, buffer);
+
+ const uint8_t *reference_ciphertext = tdata->ciphertext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ reference_ciphertext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+ return 0;
+}
+
+
+static int
+test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *ciphertext, *plaintext;
+ unsigned ciphertext_pad_len;
+ unsigned ciphertext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 8);
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, ciphertext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ plaintext = ciphertext + (tdata->validCipherOffsetInBits.len >> 3);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, ciphertext_len);
+
+ const uint8_t *reference_plaintext = tdata->plaintext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ reference_plaintext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Plaintext data not as expected");
+ return 0;
+}
+
+static int
+test_kasumi_decryption(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *ciphertext, *plaintext;
+ unsigned ciphertext_pad_len;
+ unsigned ciphertext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 8);
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, ciphertext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->ciphertext.len,
+ tdata->validCipherOffsetInBits.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ plaintext = ciphertext + (tdata->validCipherOffsetInBits.len >> 3);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, ciphertext_len);
+
+ const uint8_t *reference_plaintext = tdata->plaintext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ reference_plaintext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Plaintext data not as expected");
+ return 0;
+}
+
+static int
+test_snow3g_encryption(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+ return 0;
+}
+
+
+static int
+test_snow3g_encryption_oop(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *plaintext, *ciphertext;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+ return 0;
+}
+
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ uint8_t buffer[10000];
+ const uint8_t *ciphertext;
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10, 0);
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 3, 0);
+
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+
+ return 0;
+}
+
+/* Shift right a buffer by "offset" bits, "offset" < 8 */
+static void
+buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
+{
+ uint8_t curr_byte, prev_byte;
+ uint32_t length_in_bytes = ceil_byte_length(length + offset);
+ uint8_t lower_byte_mask = (1 << offset) - 1;
+ unsigned i;
+
+ prev_byte = buffer[0];
+ buffer[0] >>= offset;
+
+ for (i = 1; i < length_in_bytes; i++) {
+ curr_byte = buffer[i];
+ buffer[i] = ((prev_byte & lower_byte_mask) << (8 - offset)) |
+ (curr_byte >> offset);
+ prev_byte = curr_byte;
+ }
+}
+
+static int
+test_snow3g_encryption_offset_oop(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *plaintext, *ciphertext;
+ int retval;
+ uint32_t plaintext_len;
+ uint32_t plaintext_pad_len;
+ uint8_t extra_offset = 4;
+ uint8_t *expected_ciphertext_shifted;
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA) &&
+ ((tdata->validDataLenInBits.len % 8) != 0)) {
+ printf("Device doesn't support NON-Byte Aligned Data.\n");
+ return -ENOTSUP;
+ }
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len + extra_offset);
+ /*
+ * Append data which is padded to a
+ * multiple of the algorithms block size
+ */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ plaintext = (uint8_t *) rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+
+ memcpy(plaintext, tdata->plaintext.data, (tdata->plaintext.len >> 3));
+ buffer_shift_right(plaintext, tdata->plaintext.len, extra_offset);
+
+#ifdef RTE_APP_TEST_DEBUG
+ rte_hexdump(stdout, "plaintext:", plaintext, tdata->plaintext.len);
+#endif
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ extra_offset);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+#ifdef RTE_APP_TEST_DEBUG
+ rte_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+#endif
+
+ expected_ciphertext_shifted = rte_malloc(NULL, plaintext_len, 8);
+
+ TEST_ASSERT_NOT_NULL(expected_ciphertext_shifted,
+ "failed to reserve memory for ciphertext shifted\n");
+
+ memcpy(expected_ciphertext_shifted, tdata->ciphertext.data,
+ ceil_byte_length(tdata->ciphertext.len));
+ buffer_shift_right(expected_ciphertext_shifted, tdata->ciphertext.len,
+ extra_offset);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT_OFFSET(
+ ciphertext,
+ expected_ciphertext_shifted,
+ tdata->validDataLenInBits.len,
+ extra_offset,
+ "SNOW 3G Ciphertext data not as expected");
+ return 0;
+}
+
+static int test_snow3g_decryption(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned ciphertext_pad_len;
+ unsigned ciphertext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, ciphertext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ tdata->cipher.offset_bits);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ plaintext = ciphertext;
+
+ debug_hexdump(stdout, "plaintext:", plaintext, ciphertext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(plaintext,
+ tdata->plaintext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Plaintext data not as expected");
+ return 0;
+}
+
+static int test_snow3g_decryption_oop(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned ciphertext_pad_len;
+ unsigned ciphertext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer");
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer");
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, ciphertext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_operation_oop(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ plaintext = ciphertext;
+
+ debug_hexdump(stdout, "plaintext:", plaintext, ciphertext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(plaintext,
+ tdata->plaintext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Plaintext data not as expected");
+ return 0;
+}
+
+static int
+test_zuc_cipher_auth(const struct wireless_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA) &&
+ ((tdata->validAuthLenInBits.len % 8 != 0) ||
+ (tdata->validDataLenInBits.len % 8 != 0))) {
+ printf("Device doesn't support NON-Byte Aligned Data.\n");
+ return -ENOTSUP;
+ }
+
+ /* Check if device supports ZUC EEA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_ZUC_EEA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Check if device supports ZUC EIA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_ZUC_EIA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create ZUC session */
+ retval = create_zuc_cipher_auth_encrypt_generate_session(
+ ts_params->valid_devs[0],
+ tdata);
+ if (retval < 0)
+ return retval;
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create ZUC operation */
+ retval = create_zuc_cipher_hash_generate_operation(tdata);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_src;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ 4,
+ "ZUC Generated auth tag not as expected");
+ return 0;
+}
+
+static int
+test_snow3g_cipher_auth(const struct snow3g_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_cipher_auth_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_cipher_hash_operation(tdata->digest.data,
+ tdata->digest.len, tdata->auth_iv.data,
+ tdata->auth_iv.len,
+ plaintext_pad_len, RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->validCipherLenInBits.len,
+ 0,
+ tdata->validAuthLenInBits.len,
+ 0
+ );
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->obuf = ut_params->op->sym->m_src;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "SNOW 3G Generated auth tag not as expected");
+ return 0;
+}
+
+static int
+test_snow3g_auth_cipher(const struct snow3g_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext = NULL, *ciphertext = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == OUT_OF_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ if (op_mode == OUT_OF_PLACE)
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ if (op_mode == OUT_OF_PLACE)
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ if (verify) {
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+ }
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->cipher.offset_bits,
+ tdata->validAuthLenInBits.len,
+ tdata->auth.offset_bits,
+ op_mode, 0, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ plaintext = ciphertext +
+ (tdata->cipher.offset_bits >> 3);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes);
+
+ debug_hexdump(stdout, "digest:", ut_params->digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:", tdata->digest.data,
+ tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "SNOW 3G Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "SNOW 3G Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_snow3g_auth_cipher_sgl(const struct snow3g_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ const uint8_t *plaintext = NULL;
+ const uint8_t *ciphertext = NULL;
+ const uint8_t *digest = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+ uint8_t buffer[10000];
+ uint8_t digest_buffer[10000];
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == IN_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create SNOW 3G session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ if (op_mode == OUT_OF_PLACE) {
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+ }
+
+ if (verify) {
+ pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+ tdata->ciphertext.data);
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Create SNOW 3G operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->cipher.offset_bits,
+ tdata->validAuthLenInBits.len,
+ tdata->auth.offset_bits,
+ op_mode, 1, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ ciphertext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ if (ut_params->obuf)
+ digest = rte_pktmbuf_read(ut_params->obuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+ else
+ digest = rte_pktmbuf_read(ut_params->ibuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+
+ debug_hexdump(stdout, "digest:", digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest.data, tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "SNOW 3G Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "SNOW 3G Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "SNOW 3G Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_kasumi_auth_cipher(const struct kasumi_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext = NULL, *ciphertext = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_KASUMI_F9;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == OUT_OF_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_KASUMI_F9,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ 0, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ if (op_mode == OUT_OF_PLACE)
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ if (op_mode == OUT_OF_PLACE)
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ if (verify) {
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ NULL, 0,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->validCipherOffsetInBits.len,
+ tdata->validAuthLenInBits.len,
+ 0,
+ op_mode, 0, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ plaintext = ciphertext;
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ ut_params->digest = rte_pktmbuf_mtod(
+ ut_params->obuf, uint8_t *) +
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes);
+
+ debug_hexdump(stdout, "digest:", ut_params->digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest.data, tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "KASUMI Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len >> 3,
+ "KASUMI Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_KASUMI_F9,
+ "KASUMI Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_kasumi_auth_cipher_sgl(const struct kasumi_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ const uint8_t *plaintext = NULL;
+ const uint8_t *ciphertext = NULL;
+ const uint8_t *digest = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+ uint8_t buffer[10000];
+ uint8_t digest_buffer[10000];
+
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_KASUMI_F9;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == IN_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_KASUMI_F9,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ 0, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ if (op_mode == OUT_OF_PLACE) {
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+ }
+
+ if (verify) {
+ pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+ tdata->ciphertext.data);
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ NULL, 0,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->validCipherOffsetInBits.len,
+ tdata->validAuthLenInBits.len,
+ 0,
+ op_mode, 1, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ ciphertext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ if (ut_params->obuf)
+ digest = rte_pktmbuf_read(ut_params->obuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+ else
+ digest = rte_pktmbuf_read(ut_params->ibuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+
+ debug_hexdump(stdout, "digest:", digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest.data, tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "KASUMI Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_KASUMI_F9,
+ "KASUMI Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_kasumi_cipher_auth(const struct kasumi_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_KASUMI_F9;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_KASUMI_F8;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create KASUMI session */
+ retval = create_wireless_algo_cipher_auth_session(
+ ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ RTE_CRYPTO_AUTH_KASUMI_F9,
+ RTE_CRYPTO_CIPHER_KASUMI_F8,
+ tdata->key.data, tdata->key.len,
+ 0, tdata->digest.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create KASUMI operation */
+ retval = create_wireless_algo_cipher_hash_operation(tdata->digest.data,
+ tdata->digest.len, NULL, 0,
+ plaintext_pad_len, RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ RTE_ALIGN_CEIL(tdata->validCipherLenInBits.len, 8),
+ tdata->validCipherOffsetInBits.len,
+ tdata->validAuthLenInBits.len,
+ 0
+ );
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ if (ut_params->op->sym->m_dst)
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ else
+ ut_params->obuf = ut_params->op->sym->m_src;
+
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->obuf, uint8_t *,
+ tdata->validCipherOffsetInBits.len >> 3);
+
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ const uint8_t *reference_ciphertext = tdata->ciphertext.data +
+ (tdata->validCipherOffsetInBits.len >> 3);
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ reference_ciphertext,
+ tdata->validCipherLenInBits.len,
+ "KASUMI Ciphertext data not as expected");
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "KASUMI Generated auth tag not as expected");
+ return 0;
+}
+
+static int
+test_zuc_encryption(const struct wireless_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext, *ciphertext;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ /* Check if device supports ZUC EEA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_ZUC_EEA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* Clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len,
+ tdata->plaintext.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validCipherLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+ return 0;
+}
+
+static int
+test_zuc_encryption_sgl(const struct wireless_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ const uint8_t *ciphertext;
+ uint8_t ciphertext_buffer[2048];
+ struct rte_cryptodev_info dev_info;
+
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ /* Check if device supports ZUC EEA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_ZUC_EEA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+ /* Append data which is padded to a multiple */
+ /* of the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 10, 0);
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ tdata->key.data, tdata->key.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ /* Clear mbuf payload */
+
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_cipher_operation(tdata->cipher_iv.data,
+ tdata->cipher_iv.len, tdata->plaintext.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = ut_params->op->sym->m_dst;
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf,
+ 0, plaintext_len, ciphertext_buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+ 0, plaintext_len, ciphertext_buffer);
+
+ /* Validate obuf */
+ debug_hexdump(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validCipherLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+
+ return 0;
+}
+
+static int
+test_zuc_authentication(const struct wireless_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ unsigned plaintext_pad_len;
+ unsigned plaintext_len;
+ uint8_t *plaintext;
+
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA) &&
+ (tdata->validAuthLenInBits.len % 8 != 0)) {
+ printf("Device doesn't support NON-Byte Aligned Data.\n");
+ return -ENOTSUP;
+ }
+
+ /* Check if device supports ZUC EIA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_ZUC_EIA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_hash_session(ts_params->valid_devs[0],
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ RTE_CRYPTO_AUTH_ZUC_EIA3);
+ if (retval < 0)
+ return retval;
+
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ /* Append data which is padded to a multiple of */
+ /* the algorithms block size */
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_hash_operation(NULL, tdata->digest.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ plaintext_pad_len, RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->validAuthLenInBits.len,
+ 0);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ ut_params->obuf = ut_params->op->sym->m_src;
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + plaintext_pad_len;
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ tdata->digest.len,
+ "ZUC Generated auth tag not as expected");
+
+ return 0;
+}
+
+static int
+test_zuc_auth_cipher(const struct wireless_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext = NULL, *ciphertext = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ /* Check if device supports ZUC EIA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_ZUC_EIA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ if (op_mode == IN_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_ZUC_EIA3,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ if (op_mode == OUT_OF_PLACE)
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ if (op_mode == OUT_OF_PLACE)
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ if (verify) {
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->validCipherOffsetInBits.len,
+ tdata->validAuthLenInBits.len,
+ 0,
+ op_mode, 0, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ plaintext = ciphertext;
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ ut_params->digest = rte_pktmbuf_mtod(
+ ut_params->obuf, uint8_t *) +
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes);
+
+ debug_hexdump(stdout, "digest:", ut_params->digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest.data, tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "ZUC Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len >> 3,
+ "ZUC Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_KASUMI_F9,
+ "ZUC Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_zuc_auth_cipher_sgl(const struct wireless_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ const uint8_t *plaintext = NULL;
+ const uint8_t *ciphertext = NULL;
+ const uint8_t *digest = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+ uint8_t buffer[10000];
+ uint8_t digest_buffer[10000];
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ /* Check if device supports ZUC EIA3 */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_ZUC_EIA3;
+
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == IN_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create ZUC session */
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ (verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
+ : RTE_CRYPTO_CIPHER_OP_ENCRYPT),
+ (verify ? RTE_CRYPTO_AUTH_OP_VERIFY
+ : RTE_CRYPTO_AUTH_OP_GENERATE),
+ RTE_CRYPTO_AUTH_ZUC_EIA3,
+ RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ tdata->key.data, tdata->key.len,
+ tdata->auth_iv.len, tdata->digest.len,
+ tdata->cipher_iv.len);
+
+ if (retval < 0)
+ return retval;
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ if (op_mode == OUT_OF_PLACE) {
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+ }
+
+ if (verify) {
+ pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+ tdata->ciphertext.data);
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Create ZUC operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest.data, tdata->digest.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ NULL, 0,
+ (tdata->digest.offset_bytes == 0 ?
+ (verify ? ciphertext_pad_len : plaintext_pad_len)
+ : tdata->digest.offset_bytes),
+ tdata->validCipherLenInBits.len,
+ tdata->validCipherOffsetInBits.len,
+ tdata->validAuthLenInBits.len,
+ 0,
+ op_mode, 1, verify);
+
+ if (retval < 0)
+ return retval;
+
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len >> 3) - tdata->digest.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ ciphertext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data, tdata->ciphertext.len >> 3);
+
+ if (ut_params->obuf)
+ digest = rte_pktmbuf_read(ut_params->obuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+ else
+ digest = rte_pktmbuf_read(ut_params->ibuf,
+ (tdata->digest.offset_bytes == 0 ?
+ plaintext_pad_len : tdata->digest.offset_bytes),
+ tdata->digest.len, digest_buffer);
+
+ debug_hexdump(stdout, "digest:", digest,
+ tdata->digest.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest.data, tdata->digest.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len >> 3,
+ "ZUC Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLenInBits.len,
+ "ZUC Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ digest,
+ tdata->digest.data,
+ DIGEST_BYTE_LENGTH_KASUMI_F9,
+ "ZUC Generated auth tag not as expected");
+ }
+ return 0;
+}
+
+static int
+test_kasumi_encryption_test_case_1(void)
+{
+ return test_kasumi_encryption(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+ return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_encryption_test_case_1_oop(void)
+{
+ return test_kasumi_encryption_oop(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+ return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_encryption_test_case_2(void)
+{
+ return test_kasumi_encryption(&kasumi_test_case_2);
+}
+
+static int
+test_kasumi_encryption_test_case_3(void)
+{
+ return test_kasumi_encryption(&kasumi_test_case_3);
+}
+
+static int
+test_kasumi_encryption_test_case_4(void)
+{
+ return test_kasumi_encryption(&kasumi_test_case_4);
+}
+
+static int
+test_kasumi_encryption_test_case_5(void)
+{
+ return test_kasumi_encryption(&kasumi_test_case_5);
+}
+
+static int
+test_kasumi_decryption_test_case_1(void)
+{
+ return test_kasumi_decryption(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_decryption_test_case_1_oop(void)
+{
+ return test_kasumi_decryption_oop(&kasumi_test_case_1);
+}
+
+static int
+test_kasumi_decryption_test_case_2(void)
+{
+ return test_kasumi_decryption(&kasumi_test_case_2);
+}
+
+static int
+test_kasumi_decryption_test_case_3(void)
+{
+ return test_kasumi_decryption(&kasumi_test_case_3);
+}
+
+static int
+test_kasumi_decryption_test_case_4(void)
+{
+ return test_kasumi_decryption(&kasumi_test_case_4);
+}
+
+static int
+test_kasumi_decryption_test_case_5(void)
+{
+ return test_kasumi_decryption(&kasumi_test_case_5);
+}
+static int
+test_snow3g_encryption_test_case_1(void)
+{
+ return test_snow3g_encryption(&snow3g_test_case_1);
+}
+
+static int
+test_snow3g_encryption_test_case_1_oop(void)
+{
+ return test_snow3g_encryption_oop(&snow3g_test_case_1);
+}
+
+static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+ return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
+test_snow3g_encryption_test_case_1_offset_oop(void)
+{
+ return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
+}
+
+static int
+test_snow3g_encryption_test_case_2(void)
+{
+ return test_snow3g_encryption(&snow3g_test_case_2);
+}
+
+static int
+test_snow3g_encryption_test_case_3(void)
+{
+ return test_snow3g_encryption(&snow3g_test_case_3);
+}
+
+static int
+test_snow3g_encryption_test_case_4(void)
+{
+ return test_snow3g_encryption(&snow3g_test_case_4);
+}
+
+static int
+test_snow3g_encryption_test_case_5(void)
+{
+ return test_snow3g_encryption(&snow3g_test_case_5);
+}
+
+static int
+test_snow3g_decryption_test_case_1(void)
+{
+ return test_snow3g_decryption(&snow3g_test_case_1);
+}
+
+static int
+test_snow3g_decryption_test_case_1_oop(void)
+{
+ return test_snow3g_decryption_oop(&snow3g_test_case_1);
+}
+
+static int
+test_snow3g_decryption_test_case_2(void)
+{
+ return test_snow3g_decryption(&snow3g_test_case_2);
+}
+
+static int
+test_snow3g_decryption_test_case_3(void)
+{
+ return test_snow3g_decryption(&snow3g_test_case_3);
+}
+
+static int
+test_snow3g_decryption_test_case_4(void)
+{
+ return test_snow3g_decryption(&snow3g_test_case_4);
+}
+
+static int
+test_snow3g_decryption_test_case_5(void)
+{
+ return test_snow3g_decryption(&snow3g_test_case_5);
+}
+
+/*
+ * Function prepares snow3g_hash_test_data from snow3g_test_data.
+ * Pattern digest from snow3g_test_data must be allocated as
+ * 4 last bytes in plaintext.
+ */
+static void
+snow3g_hash_test_vector_setup(const struct snow3g_test_data *pattern,
+ struct snow3g_hash_test_data *output)
+{
+ if ((pattern != NULL) && (output != NULL)) {
+ output->key.len = pattern->key.len;
+
+ memcpy(output->key.data,
+ pattern->key.data, pattern->key.len);
+
+ output->auth_iv.len = pattern->auth_iv.len;
+
+ memcpy(output->auth_iv.data,
+ pattern->auth_iv.data, pattern->auth_iv.len);
+
+ output->plaintext.len = pattern->plaintext.len;
+
+ memcpy(output->plaintext.data,
+ pattern->plaintext.data, pattern->plaintext.len >> 3);
+
+ output->digest.len = pattern->digest.len;
+
+ memcpy(output->digest.data,
+ &pattern->plaintext.data[pattern->digest.offset_bytes],
+ pattern->digest.len);
+
+ output->validAuthLenInBits.len =
+ pattern->validAuthLenInBits.len;
+ }
+}
+
+/*
+ * Test case verify computed cipher and digest from snow3g_test_case_7 data.
+ */
+static int
+test_snow3g_decryption_with_digest_test_case_1(void)
+{
+ struct snow3g_hash_test_data snow3g_hash_data;
+
+ /*
+ * Function prepare data for hash veryfication test case.
+ * Digest is allocated in 4 last bytes in plaintext, pattern.
+ */
+ snow3g_hash_test_vector_setup(&snow3g_test_case_7, &snow3g_hash_data);
+
+ return test_snow3g_decryption(&snow3g_test_case_7) &
+ test_snow3g_authentication_verify(&snow3g_hash_data);
+}
+
+static int
+test_snow3g_cipher_auth_test_case_1(void)
+{
+ return test_snow3g_cipher_auth(&snow3g_test_case_3);
+}
+
+static int
+test_snow3g_auth_cipher_test_case_1(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_1, IN_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_test_case_2(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_2, IN_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_test_case_2_oop(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_2, OUT_OF_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_part_digest_enc(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ IN_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_part_digest_enc_oop(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ OUT_OF_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_test_case_3_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_test_case_3, IN_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_test_case_3_oop_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_test_case_3, OUT_OF_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_part_digest_enc_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ IN_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_part_digest_enc_oop_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ OUT_OF_PLACE, 0);
+}
+
+static int
+test_snow3g_auth_cipher_verify_test_case_1(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_1, IN_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_test_case_2(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_2, IN_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_test_case_2_oop(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_test_case_2, OUT_OF_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_part_digest_enc(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ IN_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_part_digest_enc_oop(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ OUT_OF_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_test_case_3_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_test_case_3, IN_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_test_case_3_oop_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_test_case_3, OUT_OF_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_part_digest_enc_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ IN_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_verify_part_digest_enc_oop_sgl(void)
+{
+ return test_snow3g_auth_cipher_sgl(
+ &snow3g_auth_cipher_partial_digest_encryption,
+ OUT_OF_PLACE, 1);
+}
+
+static int
+test_snow3g_auth_cipher_with_digest_test_case_1(void)
+{
+ return test_snow3g_auth_cipher(
+ &snow3g_test_case_7, IN_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_test_case_1(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_test_case_3, IN_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_test_case_2(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_auth_cipher_test_case_2, IN_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_test_case_2_oop(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_auth_cipher_test_case_2, OUT_OF_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_test_case_2_sgl(void)
+{
+ return test_kasumi_auth_cipher_sgl(
+ &kasumi_auth_cipher_test_case_2, IN_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_test_case_2_oop_sgl(void)
+{
+ return test_kasumi_auth_cipher_sgl(
+ &kasumi_auth_cipher_test_case_2, OUT_OF_PLACE, 0);
+}
+
+static int
+test_kasumi_auth_cipher_verify_test_case_1(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_test_case_3, IN_PLACE, 1);
+}
+
+static int
+test_kasumi_auth_cipher_verify_test_case_2(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_auth_cipher_test_case_2, IN_PLACE, 1);
+}
+
+static int
+test_kasumi_auth_cipher_verify_test_case_2_oop(void)
+{
+ return test_kasumi_auth_cipher(
+ &kasumi_auth_cipher_test_case_2, OUT_OF_PLACE, 1);
+}
+
+static int
+test_kasumi_auth_cipher_verify_test_case_2_sgl(void)
+{
+ return test_kasumi_auth_cipher_sgl(
+ &kasumi_auth_cipher_test_case_2, IN_PLACE, 1);
+}
+
+static int
+test_kasumi_auth_cipher_verify_test_case_2_oop_sgl(void)
+{
+ return test_kasumi_auth_cipher_sgl(
+ &kasumi_auth_cipher_test_case_2, OUT_OF_PLACE, 1);
+}
+
+static int
+test_kasumi_cipher_auth_test_case_1(void)
+{
+ return test_kasumi_cipher_auth(&kasumi_test_case_6);
+}
+
+static int
+test_zuc_encryption_test_case_1(void)
+{
+ return test_zuc_encryption(&zuc_test_case_cipher_193b);
+}
+
+static int
+test_zuc_encryption_test_case_2(void)
+{
+ return test_zuc_encryption(&zuc_test_case_cipher_800b);
+}
+
+static int
+test_zuc_encryption_test_case_3(void)
+{
+ return test_zuc_encryption(&zuc_test_case_cipher_1570b);
+}
+
+static int
+test_zuc_encryption_test_case_4(void)
+{
+ return test_zuc_encryption(&zuc_test_case_cipher_2798b);
+}
+
+static int
+test_zuc_encryption_test_case_5(void)
+{
+ return test_zuc_encryption(&zuc_test_case_cipher_4019b);
+}
+
+static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+ return test_zuc_encryption_sgl(&zuc_test_case_cipher_193b);
+}
+
+static int
+test_zuc_hash_generate_test_case_1(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_1b);
+}
+
+static int
+test_zuc_hash_generate_test_case_2(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_90b);
+}
+
+static int
+test_zuc_hash_generate_test_case_3(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_577b);
+}
+
+static int
+test_zuc_hash_generate_test_case_4(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_2079b);
+}
+
+static int
+test_zuc_hash_generate_test_case_5(void)
+{
+ return test_zuc_authentication(&zuc_test_auth_5670b);
+}
+
+static int
+test_zuc_hash_generate_test_case_6(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_128b);
+}
+
+static int
+test_zuc_hash_generate_test_case_7(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_2080b);
+}
+
+static int
+test_zuc_hash_generate_test_case_8(void)
+{
+ return test_zuc_authentication(&zuc_test_case_auth_584b);
+}
+
+static int
+test_zuc_cipher_auth_test_case_1(void)
+{
+ return test_zuc_cipher_auth(&zuc_test_case_cipher_200b_auth_200b);
+}
+
+static int
+test_zuc_cipher_auth_test_case_2(void)
+{
+ return test_zuc_cipher_auth(&zuc_test_case_cipher_800b_auth_120b);
+}
+
+static int
+test_zuc_auth_cipher_test_case_1(void)
+{
+ return test_zuc_auth_cipher(
+ &zuc_auth_cipher_test_case_1, IN_PLACE, 0);
+}
+
+static int
+test_zuc_auth_cipher_test_case_1_oop(void)
+{
+ return test_zuc_auth_cipher(
+ &zuc_auth_cipher_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_zuc_auth_cipher_test_case_1_sgl(void)
+{
+ return test_zuc_auth_cipher_sgl(
+ &zuc_auth_cipher_test_case_1, IN_PLACE, 0);
+}
+
+static int
+test_zuc_auth_cipher_test_case_1_oop_sgl(void)
+{
+ return test_zuc_auth_cipher_sgl(
+ &zuc_auth_cipher_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_zuc_auth_cipher_verify_test_case_1(void)
+{
+ return test_zuc_auth_cipher(
+ &zuc_auth_cipher_test_case_1, IN_PLACE, 1);
+}
+
+static int
+test_zuc_auth_cipher_verify_test_case_1_oop(void)
+{
+ return test_zuc_auth_cipher(
+ &zuc_auth_cipher_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_zuc_auth_cipher_verify_test_case_1_sgl(void)
+{
+ return test_zuc_auth_cipher_sgl(
+ &zuc_auth_cipher_test_case_1, IN_PLACE, 1);
+}
+
+static int
+test_zuc_auth_cipher_verify_test_case_1_oop_sgl(void)
+{
+ return test_zuc_auth_cipher_sgl(
+ &zuc_auth_cipher_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_mixed_check_if_unsupported(const struct mixed_cipher_auth_test_data *tdata)
+{
+ uint8_t dev_id = testsuite_params.valid_devs[0];
+
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+
+ /* Check if device supports particular cipher algorithm */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = tdata->cipher_algo;
+ if (rte_cryptodev_sym_capability_get(dev_id, &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Check if device supports particular hash algorithm */
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = tdata->auth_algo;
+ if (rte_cryptodev_sym_capability_get(dev_id, &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ return 0;
+}
+
+static int
+test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *plaintext = NULL, *ciphertext = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_crypto_op *op;
+
+ /* Check if device supports particular algorithms separately */
+ if (test_mixed_check_if_unsupported(tdata))
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+
+ /* Create the session */
+ if (verify)
+ retval = create_wireless_algo_cipher_auth_session(
+ ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ tdata->auth_algo,
+ tdata->cipher_algo,
+ tdata->auth_key.data, tdata->auth_key.len,
+ tdata->auth_iv.len, tdata->digest_enc.len,
+ tdata->cipher_iv.len);
+ else
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->auth_algo,
+ tdata->cipher_algo,
+ tdata->auth_key.data, tdata->auth_key.len,
+ tdata->auth_iv.len, tdata->digest_enc.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ if (op_mode == OUT_OF_PLACE)
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ if (op_mode == OUT_OF_PLACE)
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len_bits);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len_bits);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ if (verify) {
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ ciphertext_pad_len);
+ memcpy(ciphertext, tdata->ciphertext.data, ciphertext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, ciphertext_pad_len);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+ if (op_mode == OUT_OF_PLACE)
+ rte_pktmbuf_append(ut_params->obuf, plaintext_pad_len);
+ debug_hexdump(stdout, "plaintext:", plaintext, plaintext_len);
+ }
+
+ /* Create the operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest_enc.data, tdata->digest_enc.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ (tdata->digest_enc.offset == 0 ?
+ plaintext_pad_len
+ : tdata->digest_enc.offset),
+ tdata->validCipherLen.len_bits,
+ tdata->cipher.offset_bits,
+ tdata->validAuthLen.len_bits,
+ tdata->auth.offset_bits,
+ op_mode, 0, verify);
+
+ if (retval < 0)
+ return retval;
+
+ op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ /* Check if the op failed because the device doesn't */
+ /* support this particular combination of algorithms */
+ if (op == NULL && ut_params->op->status ==
+ RTE_CRYPTO_OP_STATUS_INVALID_SESSION) {
+ printf("Device doesn't support this mixed combination. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+ ut_params->op = op;
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ plaintext = ciphertext +
+ (tdata->cipher.offset_bits >> 3);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ tdata->plaintext.len_bits >> 3);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ tdata->plaintext.len_bits >> 3);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_mtod(ut_params->obuf,
+ uint8_t *);
+ else
+ ciphertext = plaintext;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data,
+ tdata->ciphertext.len_bits >> 3);
+
+ ut_params->digest = rte_pktmbuf_mtod(ut_params->obuf, uint8_t *)
+ + (tdata->digest_enc.offset == 0 ?
+ plaintext_pad_len : tdata->digest_enc.offset);
+
+ debug_hexdump(stdout, "digest:", ut_params->digest,
+ tdata->digest_enc.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest_enc.data,
+ tdata->digest_enc.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len_bits >> 3,
+ "Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLen.len_bits,
+ "Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ut_params->digest,
+ tdata->digest_enc.data,
+ DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
+ "Generated auth tag not as expected");
+ }
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ return 0;
+}
+
+static int
+test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
+ uint8_t op_mode, uint8_t verify)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ const uint8_t *plaintext = NULL;
+ const uint8_t *ciphertext = NULL;
+ const uint8_t *digest = NULL;
+ unsigned int plaintext_pad_len;
+ unsigned int plaintext_len;
+ unsigned int ciphertext_pad_len;
+ unsigned int ciphertext_len;
+ uint8_t buffer[10000];
+ uint8_t digest_buffer[10000];
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_crypto_op *op;
+
+ /* Check if device supports particular algorithms */
+ if (test_mixed_check_if_unsupported(tdata))
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (op_mode == IN_PLACE) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT)) {
+ printf("Device doesn't support out-of-place scatter-gather "
+ "in both input and output mbufs.\n");
+ return -ENOTSUP;
+ }
+ if (!(feat_flags & RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED)) {
+ printf("Device doesn't support digest encrypted.\n");
+ return -ENOTSUP;
+ }
+ }
+
+ /* Create the session */
+ if (verify)
+ retval = create_wireless_algo_cipher_auth_session(
+ ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ tdata->auth_algo,
+ tdata->cipher_algo,
+ tdata->auth_key.data, tdata->auth_key.len,
+ tdata->auth_iv.len, tdata->digest_enc.len,
+ tdata->cipher_iv.len);
+ else
+ retval = create_wireless_algo_auth_cipher_session(
+ ts_params->valid_devs[0],
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata->auth_algo,
+ tdata->cipher_algo,
+ tdata->auth_key.data, tdata->auth_key.len,
+ tdata->auth_iv.len, tdata->digest_enc.len,
+ tdata->cipher_iv.len);
+ if (retval < 0)
+ return retval;
+
+ ciphertext_len = ceil_byte_length(tdata->ciphertext.len_bits);
+ plaintext_len = ceil_byte_length(tdata->plaintext.len_bits);
+ ciphertext_pad_len = RTE_ALIGN_CEIL(ciphertext_len, 16);
+ plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+ ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ ciphertext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ if (op_mode == OUT_OF_PLACE) {
+ ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+ plaintext_pad_len, 15, 0);
+ TEST_ASSERT_NOT_NULL(ut_params->obuf,
+ "Failed to allocate output buffer in mempool");
+ }
+
+ if (verify) {
+ pktmbuf_write(ut_params->ibuf, 0, ciphertext_len,
+ tdata->ciphertext.data);
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ } else {
+ pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+ tdata->plaintext.data);
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ plaintext_len);
+ }
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Create the operation */
+ retval = create_wireless_algo_auth_cipher_operation(
+ tdata->digest_enc.data, tdata->digest_enc.len,
+ tdata->cipher_iv.data, tdata->cipher_iv.len,
+ tdata->auth_iv.data, tdata->auth_iv.len,
+ (tdata->digest_enc.offset == 0 ?
+ plaintext_pad_len
+ : tdata->digest_enc.offset),
+ tdata->validCipherLen.len_bits,
+ tdata->cipher.offset_bits,
+ tdata->validAuthLen.len_bits,
+ tdata->auth.offset_bits,
+ op_mode, 1, verify);
+
+ if (retval < 0)
+ return retval;
+
+ op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ /* Check if the op failed because the device doesn't */
+ /* support this particular combination of algorithms */
+ if (op == NULL && ut_params->op->status ==
+ RTE_CRYPTO_OP_STATUS_INVALID_SESSION) {
+ printf("Device doesn't support this mixed combination. "
+ "Test Skipped.\n");
+ return -ENOTSUP;
+ }
+
+ ut_params->op = op;
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+ ut_params->obuf = (op_mode == IN_PLACE ?
+ ut_params->op->sym->m_src : ut_params->op->sym->m_dst);
+
+ if (verify) {
+ if (ut_params->obuf)
+ plaintext = rte_pktmbuf_read(ut_params->obuf, 0,
+ plaintext_len, buffer);
+ else
+ plaintext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ plaintext_len, buffer);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ (tdata->plaintext.len_bits >> 3) -
+ tdata->digest_enc.len);
+ debug_hexdump(stdout, "plaintext expected:",
+ tdata->plaintext.data,
+ (tdata->plaintext.len_bits >> 3) -
+ tdata->digest_enc.len);
+ } else {
+ if (ut_params->obuf)
+ ciphertext = rte_pktmbuf_read(ut_params->obuf, 0,
+ ciphertext_len, buffer);
+ else
+ ciphertext = rte_pktmbuf_read(ut_params->ibuf, 0,
+ ciphertext_len, buffer);
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ ciphertext_len);
+ debug_hexdump(stdout, "ciphertext expected:",
+ tdata->ciphertext.data,
+ tdata->ciphertext.len_bits >> 3);
+
+ if (ut_params->obuf)
+ digest = rte_pktmbuf_read(ut_params->obuf,
+ (tdata->digest_enc.offset == 0 ?
+ plaintext_pad_len :
+ tdata->digest_enc.offset),
+ tdata->digest_enc.len, digest_buffer);
+ else
+ digest = rte_pktmbuf_read(ut_params->ibuf,
+ (tdata->digest_enc.offset == 0 ?
+ plaintext_pad_len :
+ tdata->digest_enc.offset),
+ tdata->digest_enc.len, digest_buffer);
+
+ debug_hexdump(stdout, "digest:", digest,
+ tdata->digest_enc.len);
+ debug_hexdump(stdout, "digest expected:",
+ tdata->digest_enc.data, tdata->digest_enc.len);
+ }
+
+ /* Validate obuf */
+ if (verify) {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len_bits >> 3,
+ "Plaintext data not as expected");
+ } else {
+ TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->validDataLen.len_bits,
+ "Ciphertext data not as expected");
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ digest,
+ tdata->digest_enc.data,
+ tdata->digest_enc.len,
+ "Generated auth tag not as expected");
+ }
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ return 0;
+}
+
+/** AUTH AES CMAC + CIPHER AES CTR */
+
+static int
+test_aes_cmac_aes_ctr_digest_enc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, IN_PLACE, 0);
+}
+
+static int
+test_aes_cmac_aes_ctr_digest_enc_test_case_1_oop(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_aes_cmac_aes_ctr_digest_enc_test_case_1_sgl(void)
+{
+ return test_mixed_auth_cipher_sgl(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, IN_PLACE, 0);
+}
+
+static int
+test_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl(void)
+{
+ return test_mixed_auth_cipher_sgl(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, IN_PLACE, 1);
+}
+
+static int
+test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_sgl(void)
+{
+ return test_mixed_auth_cipher_sgl(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, IN_PLACE, 1);
+}
+
+static int
+test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl(void)
+{
+ return test_mixed_auth_cipher_sgl(
+ &auth_aes_cmac_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+/** MIXED AUTH + CIPHER */
+
+static int
+test_auth_zuc_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_zuc_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_snow_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_zuc_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_snow_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_zuc_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_zuc_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_aes_ctr_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_null_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_null_test_case_1(void)
+{
+ return test_mixed_auth_cipher(
+ &auth_aes_cmac_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
+/* ***** AEAD algorithm Tests ***** */
+
+static int
+create_aead_session(uint8_t dev_id, enum rte_crypto_aead_algorithm algo,
+ enum rte_crypto_aead_operation op,
+ const uint8_t *key, const uint8_t key_len,
+ const uint16_t aad_len, const uint8_t auth_len,
+ uint8_t iv_len)
+{
+ uint8_t aead_key[key_len];
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(aead_key, key, key_len);
+
+ /* Setup AEAD Parameters */
+ ut_params->aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ ut_params->aead_xform.next = NULL;
+ ut_params->aead_xform.aead.algo = algo;
+ ut_params->aead_xform.aead.op = op;
+ ut_params->aead_xform.aead.key.data = aead_key;
+ ut_params->aead_xform.aead.key.length = key_len;
+ ut_params->aead_xform.aead.iv.offset = IV_OFFSET;
+ ut_params->aead_xform.aead.iv.length = iv_len;
+ ut_params->aead_xform.aead.digest_length = auth_len;
+ ut_params->aead_xform.aead.aad_length = aad_len;
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->aead_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ return 0;
+}
+
+static int
+create_aead_xform(struct rte_crypto_op *op,
+ enum rte_crypto_aead_algorithm algo,
+ enum rte_crypto_aead_operation aead_op,
+ uint8_t *key, const uint8_t key_len,
+ const uint8_t aad_len, const uint8_t auth_len,
+ uint8_t iv_len)
+{
+ TEST_ASSERT_NOT_NULL(rte_crypto_op_sym_xforms_alloc(op, 1),
+ "failed to allocate space for crypto transform");
+
+ struct rte_crypto_sym_op *sym_op = op->sym;
+
+ /* Setup AEAD Parameters */
+ sym_op->xform->type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ sym_op->xform->next = NULL;
+ sym_op->xform->aead.algo = algo;
+ sym_op->xform->aead.op = aead_op;
+ sym_op->xform->aead.key.data = key;
+ sym_op->xform->aead.key.length = key_len;
+ sym_op->xform->aead.iv.offset = IV_OFFSET;
+ sym_op->xform->aead.iv.length = iv_len;
+ sym_op->xform->aead.digest_length = auth_len;
+ sym_op->xform->aead.aad_length = aad_len;
+
+ debug_hexdump(stdout, "key:", key, key_len);
+
+ return 0;
+}
+
+static int
+create_aead_operation(enum rte_crypto_aead_operation op,
+ const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ uint8_t *plaintext, *ciphertext;
+ unsigned int aad_pad_len, plaintext_pad_len;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* Append aad data */
+ if (tdata->algo == RTE_CRYPTO_AEAD_AES_CCM) {
+ aad_pad_len = RTE_ALIGN_CEIL(tdata->aad.len + 18, 16);
+ sym_op->aead.aad.data = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ aad_pad_len);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.aad.data,
+ "no room to append aad");
+
+ sym_op->aead.aad.phys_addr =
+ rte_pktmbuf_iova(ut_params->ibuf);
+ /* Copy AAD 18 bytes after the AAD pointer, according to the API */
+ memcpy(sym_op->aead.aad.data + 18, tdata->aad.data, tdata->aad.len);
+ debug_hexdump(stdout, "aad:", sym_op->aead.aad.data,
+ tdata->aad.len);
+
+ /* Append IV at the end of the crypto operation*/
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op,
+ uint8_t *, IV_OFFSET);
+
+ /* Copy IV 1 byte after the IV pointer, according to the API */
+ rte_memcpy(iv_ptr + 1, tdata->iv.data, tdata->iv.len);
+ debug_hexdump(stdout, "iv:", iv_ptr,
+ tdata->iv.len);
+ } else {
+ aad_pad_len = RTE_ALIGN_CEIL(tdata->aad.len, 16);
+ sym_op->aead.aad.data = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ aad_pad_len);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.aad.data,
+ "no room to append aad");
+
+ sym_op->aead.aad.phys_addr =
+ rte_pktmbuf_iova(ut_params->ibuf);
+ memcpy(sym_op->aead.aad.data, tdata->aad.data, tdata->aad.len);
+ debug_hexdump(stdout, "aad:", sym_op->aead.aad.data,
+ tdata->aad.len);
+
+ /* Append IV at the end of the crypto operation*/
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op,
+ uint8_t *, IV_OFFSET);
+
+ if (tdata->iv.len == 0) {
+ rte_memcpy(iv_ptr, tdata->iv.data, AES_GCM_J0_LENGTH);
+ debug_hexdump(stdout, "iv:", iv_ptr,
+ AES_GCM_J0_LENGTH);
+ } else {
+ rte_memcpy(iv_ptr, tdata->iv.data, tdata->iv.len);
+ debug_hexdump(stdout, "iv:", iv_ptr,
+ tdata->iv.len);
+ }
+ }
+
+ /* Append plaintext/ciphertext */
+ if (op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+
+ memcpy(plaintext, tdata->plaintext.data, tdata->plaintext.len);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ tdata->plaintext.len);
+
+ if (ut_params->obuf) {
+ ciphertext = (uint8_t *)rte_pktmbuf_append(
+ ut_params->obuf,
+ plaintext_pad_len + aad_pad_len);
+ TEST_ASSERT_NOT_NULL(ciphertext,
+ "no room to append ciphertext");
+
+ memset(ciphertext + aad_pad_len, 0,
+ tdata->ciphertext.len);
+ }
+ } else {
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->ciphertext.len, 16);
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ TEST_ASSERT_NOT_NULL(ciphertext,
+ "no room to append ciphertext");
+
+ memcpy(ciphertext, tdata->ciphertext.data,
+ tdata->ciphertext.len);
+ debug_hexdump(stdout, "ciphertext:", ciphertext,
+ tdata->ciphertext.len);
+
+ if (ut_params->obuf) {
+ plaintext = (uint8_t *)rte_pktmbuf_append(
+ ut_params->obuf,
+ plaintext_pad_len + aad_pad_len);
+ TEST_ASSERT_NOT_NULL(plaintext,
+ "no room to append plaintext");
+
+ memset(plaintext + aad_pad_len, 0,
+ tdata->plaintext.len);
+ }
+ }
+
+ /* Append digest data */
+ if (op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
+ sym_op->aead.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->obuf ? ut_params->obuf :
+ ut_params->ibuf,
+ tdata->auth_tag.len);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.digest.data,
+ "no room to append digest");
+ memset(sym_op->aead.digest.data, 0, tdata->auth_tag.len);
+ sym_op->aead.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->obuf ? ut_params->obuf :
+ ut_params->ibuf,
+ plaintext_pad_len +
+ aad_pad_len);
+ } else {
+ sym_op->aead.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, tdata->auth_tag.len);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.digest.data,
+ "no room to append digest");
+ sym_op->aead.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf,
+ plaintext_pad_len + aad_pad_len);
+
+ rte_memcpy(sym_op->aead.digest.data, tdata->auth_tag.data,
+ tdata->auth_tag.len);
+ debug_hexdump(stdout, "digest:",
+ sym_op->aead.digest.data,
+ tdata->auth_tag.len);
+ }
+
+ sym_op->aead.data.length = tdata->plaintext.len;
+ sym_op->aead.data.offset = aad_pad_len;
+
+ return 0;
+}
+
+static int
+test_authenticated_encryption(const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *ciphertext, *auth_tag;
+ uint16_t plaintext_pad_len;
+ uint32_t i;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *capability;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ capability = rte_cryptodev_sym_capability_get(
+ ts_params->valid_devs[0], &cap_idx);
+ if (capability == NULL)
+ return -ENOTSUP;
+ if (rte_cryptodev_sym_capability_check_aead(
+ capability, tdata->key.len, tdata->auth_tag.len,
+ tdata->aad.len, tdata->iv.len))
+ return -ENOTSUP;
+
+ /* Create AEAD session */
+ retval = create_aead_session(ts_params->valid_devs[0],
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_ENCRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ if (tdata->aad.len > MBUF_SIZE) {
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->large_mbuf_pool);
+ /* Populate full size of add data */
+ for (i = 32; i < MAX_AAD_LENGTH; i += 32)
+ memcpy(&tdata->aad.data[i], &tdata->aad.data[0], 32);
+ } else
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_ENCRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ /* Process crypto operation */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_aead_op(ts_params->valid_devs[0], ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+
+ if (ut_params->op->sym->m_dst) {
+ ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_dst,
+ uint8_t *);
+ auth_tag = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_dst,
+ uint8_t *, plaintext_pad_len);
+ } else {
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_src,
+ uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+ auth_tag = ciphertext + plaintext_pad_len;
+ }
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, tdata->ciphertext.len);
+ debug_hexdump(stdout, "auth tag:", auth_tag, tdata->auth_tag.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len,
+ "Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->auth_tag.data,
+ tdata->auth_tag.len,
+ "Generated auth tag not as expected");
+
+ return 0;
+
+}
+
+#ifdef RTE_LIBRTE_SECURITY
+/* Basic algorithm run function for async inplace mode.
+ * Creates a session from input parameters and runs one operation
+ * on input_vec. Checks the output of the crypto operation against
+ * output_vec.
+ */
+static int
+test_pdcp_proto(int i, int oop,
+ enum rte_crypto_cipher_operation opc,
+ enum rte_crypto_auth_operation opa,
+ uint8_t *input_vec,
+ unsigned int input_vec_len,
+ uint8_t *output_vec,
+ unsigned int output_vec_len)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *plaintext;
+ int ret = TEST_SUCCESS;
+ struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+ rte_cryptodev_get_sec_ctx(
+ ts_params->valid_devs[0]);
+
+ /* Verify the capabilities */
+ struct rte_security_capability_idx sec_cap_idx;
+
+ sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+ sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_PDCP;
+ sec_cap_idx.pdcp.domain = pdcp_test_params[i].domain;
+ if (rte_security_capability_get(ctx, &sec_cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ input_vec_len);
+ memcpy(plaintext, input_vec, input_vec_len);
+
+ /* Out of place support */
+ if (oop) {
+ /*
+ * For out-op-place we need to alloc another mbuf
+ */
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ rte_pktmbuf_append(ut_params->obuf, output_vec_len);
+ }
+
+ /* Set crypto type as IPSEC */
+ ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.cipher.algo = pdcp_test_params[i].cipher_alg;
+ ut_params->cipher_xform.cipher.op = opc;
+ ut_params->cipher_xform.cipher.key.data = pdcp_test_crypto_key[i];
+ ut_params->cipher_xform.cipher.key.length =
+ pdcp_test_params[i].cipher_key_len;
+ ut_params->cipher_xform.cipher.iv.length = 0;
+
+ /* Setup HMAC Parameters if ICV header is required */
+ if (pdcp_test_params[i].auth_alg != 0) {
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+ ut_params->auth_xform.auth.algo = pdcp_test_params[i].auth_alg;
+ ut_params->auth_xform.auth.op = opa;
+ ut_params->auth_xform.auth.key.data = pdcp_test_auth_key[i];
+ ut_params->auth_xform.auth.key.length =
+ pdcp_test_params[i].auth_key_len;
+
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+ } else {
+ ut_params->cipher_xform.next = NULL;
+ }
+
+ struct rte_security_session_conf sess_conf = {
+ .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ {.pdcp = {
+ .bearer = pdcp_test_bearer[i],
+ .domain = pdcp_test_params[i].domain,
+ .pkt_dir = pdcp_test_packet_direction[i],
+ .sn_size = pdcp_test_data_sn_size[i],
+ .hfn = pdcp_test_hfn[i],
+ .hfn_threshold = pdcp_test_hfn_threshold[i],
+ } },
+ .crypto_xform = &ut_params->cipher_xform
+ };
+
+ /* Create security session */
+ ut_params->sec_session = rte_security_session_create(ctx,
+ &sess_conf, ts_params->session_priv_mpool);
+
+ if (!ut_params->sec_session) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__, "Failed to allocate session");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ /* Generate crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ if (!ut_params->op) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__,
+ "Failed to allocate symmetric crypto operation struct");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+ /* set crypto operation source mbuf */
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ if (oop)
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ if (process_crypto_request(ts_params->valid_devs[0], ut_params->op)
+ == NULL) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__,
+ "failed to process sym crypto op");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__, "crypto op processing failed");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ /* Validate obuf */
+ uint8_t *ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_src,
+ uint8_t *);
+ if (oop) {
+ ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_dst,
+ uint8_t *);
+ }
+
+ if (memcmp(ciphertext, output_vec, output_vec_len)) {
+ printf("\n=======PDCP TestCase #%d failed: Data Mismatch ", i);
+ rte_hexdump(stdout, "encrypted", ciphertext, output_vec_len);
+ rte_hexdump(stdout, "reference", output_vec, output_vec_len);
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+on_err:
+ rte_crypto_op_free(ut_params->op);
+ ut_params->op = NULL;
+
+ if (ut_params->sec_session)
+ rte_security_session_destroy(ctx, ut_params->sec_session);
+ ut_params->sec_session = NULL;
+
+ rte_pktmbuf_free(ut_params->ibuf);
+ ut_params->ibuf = NULL;
+ if (oop) {
+ rte_pktmbuf_free(ut_params->obuf);
+ ut_params->obuf = NULL;
+ }
+
+ return ret;
+}
+
+static int
+test_pdcp_proto_SGL(int i, int oop,
+ enum rte_crypto_cipher_operation opc,
+ enum rte_crypto_auth_operation opa,
+ uint8_t *input_vec,
+ unsigned int input_vec_len,
+ uint8_t *output_vec,
+ unsigned int output_vec_len,
+ uint32_t fragsz,
+ uint32_t fragsz_oop)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *plaintext;
+ struct rte_mbuf *buf, *buf_oop = NULL;
+ int ret = TEST_SUCCESS;
+ int to_trn = 0;
+ int to_trn_tbl[16];
+ int segs = 1;
+ unsigned int trn_data = 0;
+ struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+ rte_cryptodev_get_sec_ctx(
+ ts_params->valid_devs[0]);
+
+ /* Verify the capabilities */
+ struct rte_security_capability_idx sec_cap_idx;
+
+ sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+ sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_PDCP;
+ sec_cap_idx.pdcp.domain = pdcp_test_params[i].domain;
+ if (rte_security_capability_get(ctx, &sec_cap_idx) == NULL)
+ return -ENOTSUP;
+
+ if (fragsz > input_vec_len)
+ fragsz = input_vec_len;
+
+ uint16_t plaintext_len = fragsz;
+ uint16_t frag_size_oop = fragsz_oop ? fragsz_oop : fragsz;
+
+ if (fragsz_oop > output_vec_len)
+ frag_size_oop = output_vec_len;
+
+ int ecx = 0;
+ if (input_vec_len % fragsz != 0) {
+ if (input_vec_len / fragsz + 1 > 16)
+ return 1;
+ } else if (input_vec_len / fragsz > 16)
+ return 1;
+
+ /* Out of place support */
+ if (oop) {
+ /*
+ * For out-op-place we need to alloc another mbuf
+ */
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ rte_pktmbuf_append(ut_params->obuf, frag_size_oop);
+ buf_oop = ut_params->obuf;
+ }
+
+ /* Generate test mbuf data */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_len);
+ memcpy(plaintext, input_vec, plaintext_len);
+ trn_data += plaintext_len;
+
+ buf = ut_params->ibuf;
+
+ /*
+ * Loop until no more fragments
+ */
+
+ while (trn_data < input_vec_len) {
+ ++segs;
+ to_trn = (input_vec_len - trn_data < fragsz) ?
+ (input_vec_len - trn_data) : fragsz;
+
+ to_trn_tbl[ecx++] = to_trn;
+
+ buf->next = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf = buf->next;
+
+ memset(rte_pktmbuf_mtod(buf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(buf));
+
+ /* OOP */
+ if (oop && !fragsz_oop) {
+ buf_oop->next =
+ rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf_oop = buf_oop->next;
+ memset(rte_pktmbuf_mtod(buf_oop, uint8_t *),
+ 0, rte_pktmbuf_tailroom(buf_oop));
+ rte_pktmbuf_append(buf_oop, to_trn);
+ }
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(buf,
+ to_trn);
+
+ memcpy(plaintext, input_vec + trn_data, to_trn);
+ trn_data += to_trn;
+ }
+
+ ut_params->ibuf->nb_segs = segs;
+
+ segs = 1;
+ if (fragsz_oop && oop) {
+ to_trn = 0;
+ ecx = 0;
+
+ trn_data = frag_size_oop;
+ while (trn_data < output_vec_len) {
+ ++segs;
+ to_trn =
+ (output_vec_len - trn_data <
+ frag_size_oop) ?
+ (output_vec_len - trn_data) :
+ frag_size_oop;
+
+ to_trn_tbl[ecx++] = to_trn;
+
+ buf_oop->next =
+ rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf_oop = buf_oop->next;
+ memset(rte_pktmbuf_mtod(buf_oop, uint8_t *),
+ 0, rte_pktmbuf_tailroom(buf_oop));
+ rte_pktmbuf_append(buf_oop, to_trn);
+
+ trn_data += to_trn;
+ }
+ ut_params->obuf->nb_segs = segs;
+ }
+
+ ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.cipher.algo = pdcp_test_params[i].cipher_alg;
+ ut_params->cipher_xform.cipher.op = opc;
+ ut_params->cipher_xform.cipher.key.data = pdcp_test_crypto_key[i];
+ ut_params->cipher_xform.cipher.key.length =
+ pdcp_test_params[i].cipher_key_len;
+ ut_params->cipher_xform.cipher.iv.length = 0;
+
+ /* Setup HMAC Parameters if ICV header is required */
+ if (pdcp_test_params[i].auth_alg != 0) {
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+ ut_params->auth_xform.auth.algo = pdcp_test_params[i].auth_alg;
+ ut_params->auth_xform.auth.op = opa;
+ ut_params->auth_xform.auth.key.data = pdcp_test_auth_key[i];
+ ut_params->auth_xform.auth.key.length =
+ pdcp_test_params[i].auth_key_len;
+
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+ } else {
+ ut_params->cipher_xform.next = NULL;
+ }
+
+ struct rte_security_session_conf sess_conf = {
+ .action_type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ {.pdcp = {
+ .bearer = pdcp_test_bearer[i],
+ .domain = pdcp_test_params[i].domain,
+ .pkt_dir = pdcp_test_packet_direction[i],
+ .sn_size = pdcp_test_data_sn_size[i],
+ .hfn = pdcp_test_hfn[i],
+ .hfn_threshold = pdcp_test_hfn_threshold[i],
+ } },
+ .crypto_xform = &ut_params->cipher_xform
+ };
+
+ /* Create security session */
+ ut_params->sec_session = rte_security_session_create(ctx,
+ &sess_conf, ts_params->session_priv_mpool);
+
+ if (!ut_params->sec_session) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__, "Failed to allocate session");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ /* Generate crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ if (!ut_params->op) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__,
+ "Failed to allocate symmetric crypto operation struct");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+ /* set crypto operation source mbuf */
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ if (oop)
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ if (process_crypto_request(ts_params->valid_devs[0], ut_params->op)
+ == NULL) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__,
+ "failed to process sym crypto op");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ printf("TestCase %s()-%d line %d failed %s: ",
+ __func__, i, __LINE__, "crypto op processing failed");
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ /* Validate obuf */
+ uint8_t *ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_src,
+ uint8_t *);
+ if (oop) {
+ ciphertext = rte_pktmbuf_mtod(ut_params->op->sym->m_dst,
+ uint8_t *);
+ }
+ if (fragsz_oop)
+ fragsz = frag_size_oop;
+ if (memcmp(ciphertext, output_vec, fragsz)) {
+ printf("\n=======PDCP TestCase #%d failed: Data Mismatch ", i);
+ rte_hexdump(stdout, "encrypted", ciphertext, fragsz);
+ rte_hexdump(stdout, "reference", output_vec, fragsz);
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+
+ buf = ut_params->op->sym->m_src->next;
+ if (oop)
+ buf = ut_params->op->sym->m_dst->next;
+
+ unsigned int off = fragsz;
+
+ ecx = 0;
+ while (buf) {
+ ciphertext = rte_pktmbuf_mtod(buf,
+ uint8_t *);
+ if (memcmp(ciphertext, output_vec + off, to_trn_tbl[ecx])) {
+ printf("\n=======PDCP TestCase #%d failed: Data Mismatch ", i);
+ rte_hexdump(stdout, "encrypted", ciphertext, to_trn_tbl[ecx]);
+ rte_hexdump(stdout, "reference", output_vec + off,
+ to_trn_tbl[ecx]);
+ ret = TEST_FAILED;
+ goto on_err;
+ }
+ off += to_trn_tbl[ecx++];
+ buf = buf->next;
+ }
+on_err:
+ rte_crypto_op_free(ut_params->op);
+ ut_params->op = NULL;
+
+ if (ut_params->sec_session)
+ rte_security_session_destroy(ctx, ut_params->sec_session);
+ ut_params->sec_session = NULL;
+
+ rte_pktmbuf_free(ut_params->ibuf);
+ ut_params->ibuf = NULL;
+ if (oop) {
+ rte_pktmbuf_free(ut_params->obuf);
+ ut_params->obuf = NULL;
+ }
+
+ return ret;
+}
+
+int
+test_pdcp_proto_cplane_encap(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i]+4);
+}
+
+int
+test_pdcp_proto_uplane_encap(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i]);
+
+}
+
+int
+test_pdcp_proto_uplane_encap_with_int(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i] + 4);
+}
+
+int
+test_pdcp_proto_cplane_decap(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i] + 4,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i]);
+}
+
+int
+test_pdcp_proto_uplane_decap(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i]);
+}
+
+int
+test_pdcp_proto_uplane_decap_with_int(int i)
+{
+ return test_pdcp_proto(i, 0,
+ RTE_CRYPTO_CIPHER_OP_DECRYPT,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i] + 4,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i]);
+}
+
+static int
+test_PDCP_PROTO_SGL_in_place_32B(void)
+{
+ /* i can be used for running any PDCP case
+ * In this case it is uplane 12-bit AES-SNOW DL encap
+ */
+ int i = PDCP_UPLANE_12BIT_OFFSET + AES_ENC + SNOW_AUTH + DOWNLINK;
+ return test_pdcp_proto_SGL(i, IN_PLACE,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i]+4,
+ 32, 0);
+}
+static int
+test_PDCP_PROTO_SGL_oop_32B_128B(void)
+{
+ /* i can be used for running any PDCP case
+ * In this case it is uplane 18-bit NULL-NULL DL encap
+ */
+ int i = PDCP_UPLANE_18BIT_OFFSET + NULL_ENC + NULL_AUTH + DOWNLINK;
+ return test_pdcp_proto_SGL(i, OUT_OF_PLACE,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i]+4,
+ 32, 128);
+}
+static int
+test_PDCP_PROTO_SGL_oop_32B_40B(void)
+{
+ /* i can be used for running any PDCP case
+ * In this case it is uplane 18-bit AES DL encap
+ */
+ int i = PDCP_UPLANE_OFFSET + AES_ENC + EIGHTEEN_BIT_SEQ_NUM_OFFSET
+ + DOWNLINK;
+ return test_pdcp_proto_SGL(i, OUT_OF_PLACE,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i],
+ 32, 40);
+}
+static int
+test_PDCP_PROTO_SGL_oop_128B_32B(void)
+{
+ /* i can be used for running any PDCP case
+ * In this case it is cplane 12-bit AES-ZUC DL encap
+ */
+ int i = PDCP_CPLANE_LONG_SN_OFFSET + AES_ENC + ZUC_AUTH + DOWNLINK;
+ return test_pdcp_proto_SGL(i, OUT_OF_PLACE,
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ RTE_CRYPTO_AUTH_OP_GENERATE,
+ pdcp_test_data_in[i],
+ pdcp_test_data_in_len[i],
+ pdcp_test_data_out[i],
+ pdcp_test_data_in_len[i]+4,
+ 128, 32);
+}
+
+static int
+test_PDCP_PROTO_all(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_info dev_info;
+ int status;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
+ return -ENOTSUP;
+
+ status = test_PDCP_PROTO_cplane_encap_all();
+ status += test_PDCP_PROTO_cplane_decap_all();
+ status += test_PDCP_PROTO_uplane_encap_all();
+ status += test_PDCP_PROTO_uplane_decap_all();
+ status += test_PDCP_PROTO_SGL_in_place_32B();
+ status += test_PDCP_PROTO_SGL_oop_32B_128B();
+ status += test_PDCP_PROTO_SGL_oop_32B_40B();
+ status += test_PDCP_PROTO_SGL_oop_128B_32B();
+
+ if (status)
+ return TEST_FAILED;
+ else
+ return TEST_SUCCESS;
+}
+#endif
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_1(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_1);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_2(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_2);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_3(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_3);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_4(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_4);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_5(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_5);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_6(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_6);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_7(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_7);
+}
+
+static int
+test_AES_GCM_authenticated_encryption_test_case_8(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_8);
+}
+
+static int
+test_AES_GCM_J0_authenticated_encryption_test_case_1(void)
+{
+ return test_authenticated_encryption(&gcm_J0_test_case_1);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_1(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_1);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_2(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_2);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_3(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_3);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_4(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_4);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_5(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_5);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_6(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_6);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_192_7(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_192_7);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_1(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_1);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_2(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_2);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_3(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_3);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_4(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_4);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_5(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_5);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_6(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_6);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_256_7(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_256_7);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_aad_1(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_aad_1);
+}
+
+static int
+test_AES_GCM_auth_encryption_test_case_aad_2(void)
+{
+ return test_authenticated_encryption(&gcm_test_case_aad_2);
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_iv_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.iv.data[0] += 1;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_in_data_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.plaintext.data[0] += 1;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_out_data_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.ciphertext.data[0] += 1;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_aad_len_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.aad.len += 1;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_aad_corrupt(void)
+{
+ struct aead_test_data tdata;
+ uint8_t aad[gcm_test_case_7.aad.len];
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ memcpy(aad, gcm_test_case_7.aad.data, gcm_test_case_7.aad.len);
+ aad[0] += 1;
+ tdata.aad.data = aad;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_encryption_fail_tag_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.auth_tag.data[0] += 1;
+ res = test_authenticated_encryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "encryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_authenticated_decryption(const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext;
+ uint32_t i;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *capability;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ capability = rte_cryptodev_sym_capability_get(
+ ts_params->valid_devs[0], &cap_idx);
+ if (capability == NULL)
+ return -ENOTSUP;
+ if (rte_cryptodev_sym_capability_check_aead(
+ capability, tdata->key.len, tdata->auth_tag.len,
+ tdata->aad.len, tdata->iv.len))
+ return -ENOTSUP;
+
+ /* Create AEAD session */
+ retval = create_aead_session(ts_params->valid_devs[0],
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_DECRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ /* alloc mbuf and set payload */
+ if (tdata->aad.len > MBUF_SIZE) {
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->large_mbuf_pool);
+ /* Populate full size of add data */
+ for (i = 32; i < MAX_AAD_LENGTH; i += 32)
+ memcpy(&tdata->aad.data[i], &tdata->aad.data[0], 32);
+ } else
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_DECRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ /* Process crypto operation */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_aead_op(ts_params->valid_devs[0], ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ if (ut_params->op->sym->m_dst)
+ plaintext = rte_pktmbuf_mtod(ut_params->op->sym->m_dst,
+ uint8_t *);
+ else
+ plaintext = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_src,
+ uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, tdata->ciphertext.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len,
+ "Plaintext data not as expected");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "Authentication failed");
+
+ return 0;
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_1(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_1);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_2(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_2);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_3(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_3);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_4(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_4);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_5(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_5);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_6(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_6);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_7(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_7);
+}
+
+static int
+test_AES_GCM_authenticated_decryption_test_case_8(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_8);
+}
+
+static int
+test_AES_GCM_J0_authenticated_decryption_test_case_1(void)
+{
+ return test_authenticated_decryption(&gcm_J0_test_case_1);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_1(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_1);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_2(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_2);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_3(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_3);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_4(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_4);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_5(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_5);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_6(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_6);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_192_7(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_192_7);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_1(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_1);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_2(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_2);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_3(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_3);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_4(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_4);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_5(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_5);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_6(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_6);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_256_7(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_256_7);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_aad_1(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_aad_1);
+}
+
+static int
+test_AES_GCM_auth_decryption_test_case_aad_2(void)
+{
+ return test_authenticated_decryption(&gcm_test_case_aad_2);
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_iv_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.iv.data[0] += 1;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "decryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_in_data_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ RTE_LOG(INFO, USER1, "This is a negative test, errors are expected\n");
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.plaintext.data[0] += 1;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "decryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_out_data_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.ciphertext.data[0] += 1;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "decryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_aad_len_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.aad.len += 1;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "decryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_aad_corrupt(void)
+{
+ struct aead_test_data tdata;
+ uint8_t aad[gcm_test_case_7.aad.len];
+ int res;
+
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ memcpy(aad, gcm_test_case_7.aad.data, gcm_test_case_7.aad.len);
+ aad[0] += 1;
+ tdata.aad.data = aad;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "decryption not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_AES_GCM_auth_decryption_fail_tag_corrupt(void)
+{
+ struct aead_test_data tdata;
+ int res;
+
+ memcpy(&tdata, &gcm_test_case_7, sizeof(struct aead_test_data));
+ tdata.auth_tag.data[0] += 1;
+ res = test_authenticated_decryption(&tdata);
+ if (res == -ENOTSUP)
+ return res;
+ TEST_ASSERT_EQUAL(res, TEST_FAILED, "authentication not failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_authenticated_encryption_oop(const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *ciphertext, *auth_tag;
+ uint16_t plaintext_pad_len;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* not supported with CPU crypto */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Create AEAD session */
+ retval = create_aead_session(ts_params->valid_devs[0],
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_ENCRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_ENCRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->obuf, uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+ auth_tag = ciphertext + plaintext_pad_len;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, tdata->ciphertext.len);
+ debug_hexdump(stdout, "auth tag:", auth_tag, tdata->auth_tag.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len,
+ "Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->auth_tag.data,
+ tdata->auth_tag.len,
+ "Generated auth tag not as expected");
+
+ return 0;
+
+}
+
+static int
+test_AES_GCM_authenticated_encryption_oop_test_case_1(void)
+{
+ return test_authenticated_encryption_oop(&gcm_test_case_5);
+}
+
+static int
+test_authenticated_decryption_oop(const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* not supported with CPU crypto */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Create AEAD session */
+ retval = create_aead_session(ts_params->valid_devs[0],
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_DECRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+ memset(rte_pktmbuf_mtod(ut_params->obuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->obuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_DECRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ plaintext = rte_pktmbuf_mtod_offset(ut_params->obuf, uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, tdata->ciphertext.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len,
+ "Plaintext data not as expected");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "Authentication failed");
+ return 0;
+}
+
+static int
+test_AES_GCM_authenticated_decryption_oop_test_case_1(void)
+{
+ return test_authenticated_decryption_oop(&gcm_test_case_5);
+}
+
+static int
+test_authenticated_encryption_sessionless(
+ const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *ciphertext, *auth_tag;
+ uint16_t plaintext_pad_len;
+ uint8_t key[tdata->key.len + 1];
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
+ printf("Device doesn't support Sessionless ops.\n");
+ return -ENOTSUP;
+ }
+
+ /* not supported with CPU crypto */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_ENCRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ /* Create GCM xform */
+ memcpy(key, tdata->key.data, tdata->key.len);
+ retval = create_aead_xform(ut_params->op,
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_ENCRYPT,
+ key, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ TEST_ASSERT_EQUAL(ut_params->op->sess_type,
+ RTE_CRYPTO_OP_SESSIONLESS,
+ "crypto op session type not sessionless");
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op status not success");
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+ auth_tag = ciphertext + plaintext_pad_len;
+
+ debug_hexdump(stdout, "ciphertext:", ciphertext, tdata->ciphertext.len);
+ debug_hexdump(stdout, "auth tag:", auth_tag, tdata->auth_tag.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data,
+ tdata->ciphertext.len,
+ "Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->auth_tag.data,
+ tdata->auth_tag.len,
+ "Generated auth tag not as expected");
+
+ return 0;
+
+}
+
+static int
+test_AES_GCM_authenticated_encryption_sessionless_test_case_1(void)
+{
+ return test_authenticated_encryption_sessionless(
+ &gcm_test_case_5);
+}
+
+static int
+test_authenticated_decryption_sessionless(
+ const struct aead_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+ uint8_t *plaintext;
+ uint8_t key[tdata->key.len + 1];
+ struct rte_cryptodev_info dev_info;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
+ printf("Device doesn't support Sessionless ops.\n");
+ return -ENOTSUP;
+ }
+
+ /* not supported with CPU crypto */
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* alloc mbuf and set payload */
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ /* Create AEAD operation */
+ retval = create_aead_operation(RTE_CRYPTO_AEAD_OP_DECRYPT, tdata);
+ if (retval < 0)
+ return retval;
+
+ /* Create AEAD xform */
+ memcpy(key, tdata->key.data, tdata->key.len);
+ retval = create_aead_xform(ut_params->op,
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_DECRYPT,
+ key, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ TEST_ASSERT_EQUAL(ut_params->op->sess_type,
+ RTE_CRYPTO_OP_SESSIONLESS,
+ "crypto op session type not sessionless");
+
+ /* Process crypto operation */
+ TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op status not success");
+
+ plaintext = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ ut_params->op->sym->cipher.data.offset);
+
+ debug_hexdump(stdout, "plaintext:", plaintext, tdata->ciphertext.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ plaintext,
+ tdata->plaintext.data,
+ tdata->plaintext.len,
+ "Plaintext data not as expected");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "Authentication failed");
+ return 0;
+}
+
+static int
+test_AES_GCM_authenticated_decryption_sessionless_test_case_1(void)
+{
+ return test_authenticated_decryption_sessionless(
+ &gcm_test_case_5);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_128_1(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_128_1);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_128_2(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_128_2);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_128_3(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_128_3);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_128_1(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_128_1);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_128_2(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_128_2);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_128_3(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_128_3);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_192_1(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_192_1);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_192_2(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_192_2);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_192_3(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_192_3);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_192_1(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_192_1);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_192_2(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_192_2);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_192_3(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_192_3);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_256_1(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_256_1);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_256_2(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_256_2);
+}
+
+static int
+test_AES_CCM_authenticated_encryption_test_case_256_3(void)
+{
+ return test_authenticated_encryption(&ccm_test_case_256_3);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_256_1(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_256_1);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_256_2(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_256_2);
+}
+
+static int
+test_AES_CCM_authenticated_decryption_test_case_256_3(void)
+{
+ return test_authenticated_decryption(&ccm_test_case_256_3);
+}
+
+static int
+test_stats(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_stats stats;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ if (rte_cryptodev_stats_get(ts_params->valid_devs[0], &stats)
+ == -ENOTSUP)
+ return -ENOTSUP;
+
+ rte_cryptodev_stats_reset(ts_params->valid_devs[0]);
+ TEST_ASSERT((rte_cryptodev_stats_get(ts_params->valid_devs[0] + 600,
+ &stats) == -ENODEV),
+ "rte_cryptodev_stats_get invalid dev failed");
+ TEST_ASSERT((rte_cryptodev_stats_get(ts_params->valid_devs[0], 0) != 0),
+ "rte_cryptodev_stats_get invalid Param failed");
+
+ /* Test expected values */
+ ut_setup();
+ test_AES_CBC_HMAC_SHA1_encrypt_digest();
+ ut_teardown();
+ TEST_ASSERT_SUCCESS(rte_cryptodev_stats_get(ts_params->valid_devs[0],
+ &stats),
+ "rte_cryptodev_stats_get failed");
+ TEST_ASSERT((stats.enqueued_count == 1),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+ TEST_ASSERT((stats.dequeued_count == 1),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+ TEST_ASSERT((stats.enqueue_err_count == 0),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+ TEST_ASSERT((stats.dequeue_err_count == 0),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+
+ /* invalid device but should ignore and not reset device stats*/
+ rte_cryptodev_stats_reset(ts_params->valid_devs[0] + 300);
+ TEST_ASSERT_SUCCESS(rte_cryptodev_stats_get(ts_params->valid_devs[0],
+ &stats),
+ "rte_cryptodev_stats_get failed");
+ TEST_ASSERT((stats.enqueued_count == 1),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+
+ /* check that a valid reset clears stats */
+ rte_cryptodev_stats_reset(ts_params->valid_devs[0]);
+ TEST_ASSERT_SUCCESS(rte_cryptodev_stats_get(ts_params->valid_devs[0],
+ &stats),
+ "rte_cryptodev_stats_get failed");
+ TEST_ASSERT((stats.enqueued_count == 0),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+ TEST_ASSERT((stats.dequeued_count == 0),
+ "rte_cryptodev_stats_get returned unexpected enqueued stat");
+
+ return TEST_SUCCESS;
+}
+
+static int MD5_HMAC_create_session(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ enum rte_crypto_auth_operation op,
+ const struct HMAC_MD5_vector *test_case)
+{
+ uint8_t key[64];
+
+ memcpy(key, test_case->key.data, test_case->key.len);
+
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+ ut_params->auth_xform.auth.op = op;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_MD5_HMAC;
+
+ ut_params->auth_xform.auth.digest_length = MD5_DIGEST_LEN;
+ ut_params->auth_xform.auth.key.length = test_case->key.len;
+ ut_params->auth_xform.auth.key.data = key;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ if (ut_params->sess == NULL)
+ return TEST_FAILED;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ return 0;
+}
+
+static int MD5_HMAC_create_op(struct crypto_unittest_params *ut_params,
+ const struct HMAC_MD5_vector *test_case,
+ uint8_t **plaintext)
+{
+ uint16_t plaintext_pad_len;
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(test_case->plaintext.len,
+ 16);
+
+ *plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ memcpy(*plaintext, test_case->plaintext.data,
+ test_case->plaintext.len);
+
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, MD5_DIGEST_LEN);
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append digest");
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, plaintext_pad_len);
+
+ if (ut_params->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ rte_memcpy(sym_op->auth.digest.data, test_case->auth_tag.data,
+ test_case->auth_tag.len);
+ }
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = test_case->plaintext.len;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ return 0;
+}
+
+static int
+test_MD5_HMAC_generate(const struct HMAC_MD5_vector *test_case)
+{
+ uint16_t plaintext_pad_len;
+ uint8_t *plaintext, *auth_tag;
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_MD5_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ if (MD5_HMAC_create_session(ts_params, ut_params,
+ RTE_CRYPTO_AUTH_OP_GENERATE, test_case))
+ return TEST_FAILED;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(test_case->plaintext.len,
+ 16);
+
+ if (MD5_HMAC_create_op(ut_params, test_case, &plaintext))
+ return TEST_FAILED;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op),
+ "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ if (ut_params->op->sym->m_dst) {
+ auth_tag = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_dst,
+ uint8_t *, plaintext_pad_len);
+ } else {
+ auth_tag = plaintext + plaintext_pad_len;
+ }
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ test_case->auth_tag.data,
+ test_case->auth_tag.len,
+ "HMAC_MD5 generated tag not as expected");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_MD5_HMAC_verify(const struct HMAC_MD5_vector *test_case)
+{
+ uint8_t *plaintext;
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_MD5_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ if (MD5_HMAC_create_session(ts_params, ut_params,
+ RTE_CRYPTO_AUTH_OP_VERIFY, test_case)) {
+ return TEST_FAILED;
+ }
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ if (MD5_HMAC_create_op(ut_params, test_case, &plaintext))
+ return TEST_FAILED;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op),
+ "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "HMAC_MD5 crypto op processing failed");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_MD5_HMAC_generate_case_1(void)
+{
+ return test_MD5_HMAC_generate(&HMAC_MD5_test_case_1);
+}
+
+static int
+test_MD5_HMAC_verify_case_1(void)
+{
+ return test_MD5_HMAC_verify(&HMAC_MD5_test_case_1);
+}
+
+static int
+test_MD5_HMAC_generate_case_2(void)
+{
+ return test_MD5_HMAC_generate(&HMAC_MD5_test_case_2);
+}
+
+static int
+test_MD5_HMAC_verify_case_2(void)
+{
+ return test_MD5_HMAC_verify(&HMAC_MD5_test_case_2);
+}
+
+static int
+test_multi_session(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_session **sessions;
+
+ uint16_t i;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SHA512_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(ut_params,
+ aes_cbc_key, hmac_sha512_key);
+
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ sessions = rte_malloc(NULL,
+ (sizeof(struct rte_cryptodev_sym_session *) *
+ MAX_NB_SESSIONS) + 1, 0);
+
+ /* Create multiple crypto sessions*/
+ for (i = 0; i < MAX_NB_SESSIONS; i++) {
+
+ sessions[i] = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ sessions[i], &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(sessions[i],
+ "Session creation failed at session number %u",
+ i);
+
+ /* Attempt to send a request on each session */
+ TEST_ASSERT_SUCCESS( test_AES_CBC_HMAC_SHA512_decrypt_perform(
+ sessions[i],
+ ut_params,
+ ts_params,
+ catch_22_quote_2_512_bytes_AES_CBC_ciphertext,
+ catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA512_digest,
+ aes_cbc_iv),
+ "Failed to perform decrypt on request number %u.", i);
+ /* free crypto operation structure */
+ if (ut_params->op)
+ rte_crypto_op_free(ut_params->op);
+
+ /*
+ * free mbuf - both obuf and ibuf are usually the same,
+ * so check if they point at the same address is necessary,
+ * to avoid freeing the mbuf twice.
+ */
+ if (ut_params->obuf) {
+ rte_pktmbuf_free(ut_params->obuf);
+ if (ut_params->ibuf == ut_params->obuf)
+ ut_params->ibuf = 0;
+ ut_params->obuf = 0;
+ }
+ if (ut_params->ibuf) {
+ rte_pktmbuf_free(ut_params->ibuf);
+ ut_params->ibuf = 0;
+ }
+ }
+
+ /* Next session create should fail */
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ sessions[i], &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NULL(sessions[i],
+ "Session creation succeeded unexpectedly!");
+
+ for (i = 0; i < MAX_NB_SESSIONS; i++) {
+ rte_cryptodev_sym_session_clear(ts_params->valid_devs[0],
+ sessions[i]);
+ rte_cryptodev_sym_session_free(sessions[i]);
+ }
+
+ rte_free(sessions);
+
+ return TEST_SUCCESS;
+}
+
+struct multi_session_params {
+ struct crypto_unittest_params ut_params;
+ uint8_t *cipher_key;
+ uint8_t *hmac_key;
+ const uint8_t *cipher;
+ const uint8_t *digest;
+ uint8_t *iv;
+};
+
+#define MB_SESSION_NUMBER 3
+
+static int
+test_multi_session_random_usage(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_session **sessions;
+ uint32_t i, j;
+ struct multi_session_params ut_paramz[] = {
+
+ {
+ .cipher_key = ms_aes_cbc_key0,
+ .hmac_key = ms_hmac_key0,
+ .cipher = ms_aes_cbc_cipher0,
+ .digest = ms_hmac_digest0,
+ .iv = ms_aes_cbc_iv0
+ },
+ {
+ .cipher_key = ms_aes_cbc_key1,
+ .hmac_key = ms_hmac_key1,
+ .cipher = ms_aes_cbc_cipher1,
+ .digest = ms_hmac_digest1,
+ .iv = ms_aes_cbc_iv1
+ },
+ {
+ .cipher_key = ms_aes_cbc_key2,
+ .hmac_key = ms_hmac_key2,
+ .cipher = ms_aes_cbc_cipher2,
+ .digest = ms_hmac_digest2,
+ .iv = ms_aes_cbc_iv2
+ },
+
+ };
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_SHA512_HMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+
+ sessions = rte_malloc(NULL,
+ (sizeof(struct rte_cryptodev_sym_session *)
+ * MAX_NB_SESSIONS) + 1, 0);
+
+ for (i = 0; i < MB_SESSION_NUMBER; i++) {
+ sessions[i] = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_memcpy(&ut_paramz[i].ut_params, &unittest_params,
+ sizeof(struct crypto_unittest_params));
+
+ test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(
+ &ut_paramz[i].ut_params,
+ ut_paramz[i].cipher_key, ut_paramz[i].hmac_key);
+
+ /* Create multiple crypto sessions*/
+ rte_cryptodev_sym_session_init(
+ ts_params->valid_devs[0],
+ sessions[i],
+ &ut_paramz[i].ut_params.auth_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(sessions[i],
+ "Session creation failed at session number %u",
+ i);
+
+ }
+
+ srand(time(NULL));
+ for (i = 0; i < 40000; i++) {
+
+ j = rand() % MB_SESSION_NUMBER;
+
+ TEST_ASSERT_SUCCESS(
+ test_AES_CBC_HMAC_SHA512_decrypt_perform(
+ sessions[j],
+ &ut_paramz[j].ut_params,
+ ts_params, ut_paramz[j].cipher,
+ ut_paramz[j].digest,
+ ut_paramz[j].iv),
+ "Failed to perform decrypt on request number %u.", i);
+
+ if (ut_paramz[j].ut_params.op)
+ rte_crypto_op_free(ut_paramz[j].ut_params.op);
+
+ /*
+ * free mbuf - both obuf and ibuf are usually the same,
+ * so check if they point at the same address is necessary,
+ * to avoid freeing the mbuf twice.
+ */
+ if (ut_paramz[j].ut_params.obuf) {
+ rte_pktmbuf_free(ut_paramz[j].ut_params.obuf);
+ if (ut_paramz[j].ut_params.ibuf
+ == ut_paramz[j].ut_params.obuf)
+ ut_paramz[j].ut_params.ibuf = 0;
+ ut_paramz[j].ut_params.obuf = 0;
+ }
+ if (ut_paramz[j].ut_params.ibuf) {
+ rte_pktmbuf_free(ut_paramz[j].ut_params.ibuf);
+ ut_paramz[j].ut_params.ibuf = 0;
+ }
+ }
+
+ for (i = 0; i < MB_SESSION_NUMBER; i++) {
+ rte_cryptodev_sym_session_clear(ts_params->valid_devs[0],
+ sessions[i]);
+ rte_cryptodev_sym_session_free(sessions[i]);
+ }
+
+ rte_free(sessions);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_null_cipher_only_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data and space for digest */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ catch_22_quote, QUOTE_512_BYTES, 0);
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = QUOTE_512_BYTES;
+
+ /* Process crypto operation */
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "no crypto operation returned");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto operation processing failed");
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ rte_pktmbuf_mtod(ut_params->op->sym->m_src, uint8_t *),
+ catch_22_quote,
+ QUOTE_512_BYTES,
+ "Ciphertext data not as expected");
+
+ return TEST_SUCCESS;
+}
+uint8_t orig_data[] = {0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab};
+static int
+test_null_auth_only_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *digest;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data and space for digest */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ catch_22_quote, QUOTE_512_BYTES, 0);
+
+ /* create a pointer for digest, but don't expect anything to be written
+ * here in a NULL auth algo so no mbuf append done.
+ */
+ digest = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ QUOTE_512_BYTES);
+ /* prefill the memory pointed to by digest */
+ memcpy(digest, orig_data, sizeof(orig_data));
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_NULL;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ sym_op->m_src = ut_params->ibuf;
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = QUOTE_512_BYTES;
+ sym_op->auth.digest.data = digest;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(ut_params->ibuf,
+ QUOTE_512_BYTES);
+
+ /* Process crypto operation */
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "no crypto operation returned");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto operation processing failed");
+ /* Make sure memory pointed to by digest hasn't been overwritten */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ orig_data,
+ digest,
+ sizeof(orig_data),
+ "Memory at digest ptr overwritten unexpectedly");
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+test_null_cipher_auth_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *digest;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data and space for digest */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ catch_22_quote, QUOTE_512_BYTES, 0);
+
+ /* create a pointer for digest, but don't expect anything to be written
+ * here in a NULL auth algo so no mbuf append done.
+ */
+ digest = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ QUOTE_512_BYTES);
+ /* prefill the memory pointed to by digest */
+ memcpy(digest, orig_data, sizeof(orig_data));
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_NULL;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ sym_op->m_src = ut_params->ibuf;
+
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = QUOTE_512_BYTES;
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = QUOTE_512_BYTES;
+ sym_op->auth.digest.data = digest;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(ut_params->ibuf,
+ QUOTE_512_BYTES);
+
+ /* Process crypto operation */
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "no crypto operation returned");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto operation processing failed");
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ rte_pktmbuf_mtod(ut_params->op->sym->m_src, uint8_t *),
+ catch_22_quote,
+ QUOTE_512_BYTES,
+ "Ciphertext data not as expected");
+ /* Make sure memory pointed to by digest hasn't been overwritten */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ orig_data,
+ digest,
+ sizeof(orig_data),
+ "Memory at digest ptr overwritten unexpectedly");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_null_auth_cipher_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ uint8_t *digest;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_NULL;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Generate test mbuf data */
+ ut_params->ibuf = setup_test_string(ts_params->mbuf_pool,
+ catch_22_quote, QUOTE_512_BYTES, 0);
+
+ /* create a pointer for digest, but don't expect anything to be written
+ * here in a NULL auth algo so no mbuf append done.
+ */
+ digest = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ QUOTE_512_BYTES);
+ /* prefill the memory pointed to by digest */
+ memcpy(digest, orig_data, sizeof(orig_data));
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_NULL;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ sym_op->m_src = ut_params->ibuf;
+
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = QUOTE_512_BYTES;
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = QUOTE_512_BYTES;
+ sym_op->auth.digest.data = digest;
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(ut_params->ibuf,
+ QUOTE_512_BYTES);
+
+ /* Process crypto operation */
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_NULL(ut_params->op, "no crypto operation returned");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto operation processing failed");
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ rte_pktmbuf_mtod(ut_params->op->sym->m_src, uint8_t *),
+ catch_22_quote,
+ QUOTE_512_BYTES,
+ "Ciphertext data not as expected");
+ /* Make sure memory pointed to by digest hasn't been overwritten */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ orig_data,
+ digest,
+ sizeof(orig_data),
+ "Memory at digest ptr overwritten unexpectedly");
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+test_null_invalid_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ int ret;
+
+ /* This test is for NULL PMD only */
+ if (gbl_driver_id != rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD)))
+ return -ENOTSUP;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ ret = rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT(ret < 0,
+ "Session creation succeeded unexpectedly");
+
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ ret = rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT(ret < 0,
+ "Session creation succeeded unexpectedly");
+
+ return TEST_SUCCESS;
+}
+
+
+#define NULL_BURST_LENGTH (32)
+
+static int
+test_null_burst_operation(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ unsigned i, burst_len = NULL_BURST_LENGTH;
+
+ struct rte_crypto_op *burst[NULL_BURST_LENGTH] = { NULL };
+ struct rte_crypto_op *burst_dequeued[NULL_BURST_LENGTH] = { NULL };
+
+ /* This test is for NULL PMD only */
+ if (gbl_driver_id != rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD)))
+ return -ENOTSUP;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ /* Setup HMAC Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_NULL;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ /* Create Crypto session*/
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess, &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ TEST_ASSERT_EQUAL(rte_crypto_op_bulk_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC, burst, burst_len),
+ burst_len, "failed to generate burst of crypto ops");
+
+ /* Generate an operation for each mbuf in burst */
+ for (i = 0; i < burst_len; i++) {
+ struct rte_mbuf *m = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ TEST_ASSERT_NOT_NULL(m, "Failed to allocate mbuf");
+
+ unsigned *data = (unsigned *)rte_pktmbuf_append(m,
+ sizeof(unsigned));
+ *data = i;
+
+ rte_crypto_op_attach_sym_session(burst[i], ut_params->sess);
+
+ burst[i]->sym->m_src = m;
+ }
+
+ /* Process crypto operation */
+ TEST_ASSERT_EQUAL(rte_cryptodev_enqueue_burst(ts_params->valid_devs[0],
+ 0, burst, burst_len),
+ burst_len,
+ "Error enqueuing burst");
+
+ TEST_ASSERT_EQUAL(rte_cryptodev_dequeue_burst(ts_params->valid_devs[0],
+ 0, burst_dequeued, burst_len),
+ burst_len,
+ "Error dequeuing burst");
+
+
+ for (i = 0; i < burst_len; i++) {
+ TEST_ASSERT_EQUAL(
+ *rte_pktmbuf_mtod(burst[i]->sym->m_src, uint32_t *),
+ *rte_pktmbuf_mtod(burst_dequeued[i]->sym->m_src,
+ uint32_t *),
+ "data not as expected");
+
+ rte_pktmbuf_free(burst[i]->sym->m_src);
+ rte_crypto_op_free(burst[i]);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+generate_gmac_large_plaintext(uint8_t *data)
+{
+ uint16_t i;
+
+ for (i = 32; i < GMAC_LARGE_PLAINTEXT_LENGTH; i += 32)
+ memcpy(&data[i], &data[0], 32);
+}
+
+static int
+create_gmac_operation(enum rte_crypto_auth_operation op,
+ const struct gmac_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ struct rte_crypto_sym_op *sym_op;
+
+ uint32_t plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ sym_op = ut_params->op->sym;
+
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, tdata->gmac_tag.len);
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append digest");
+
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, plaintext_pad_len);
+
+ if (op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+ rte_memcpy(sym_op->auth.digest.data, tdata->gmac_tag.data,
+ tdata->gmac_tag.len);
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ tdata->gmac_tag.len);
+ }
+
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op,
+ uint8_t *, IV_OFFSET);
+
+ rte_memcpy(iv_ptr, tdata->iv.data, tdata->iv.len);
+
+ debug_hexdump(stdout, "iv:", iv_ptr, tdata->iv.len);
+
+ sym_op->cipher.data.length = 0;
+ sym_op->cipher.data.offset = 0;
+
+ sym_op->auth.data.offset = 0;
+ sym_op->auth.data.length = tdata->plaintext.len;
+
+ return 0;
+}
+
+static int create_gmac_session(uint8_t dev_id,
+ const struct gmac_test_data *tdata,
+ enum rte_crypto_auth_operation auth_op)
+{
+ uint8_t auth_key[tdata->key.len];
+
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ memcpy(auth_key, tdata->key.data, tdata->key.len);
+
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.next = NULL;
+
+ ut_params->auth_xform.auth.algo = RTE_CRYPTO_AUTH_AES_GMAC;
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.auth.digest_length = tdata->gmac_tag.len;
+ ut_params->auth_xform.auth.key.length = tdata->key.len;
+ ut_params->auth_xform.auth.key.data = auth_key;
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET;
+ ut_params->auth_xform.auth.iv.length = tdata->iv.len;
+
+
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ return 0;
+}
+
+static int
+test_AES_GMAC_authentication(const struct gmac_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ int retval;
+
+ uint8_t *auth_tag, *plaintext;
+ uint16_t plaintext_pad_len;
+
+ TEST_ASSERT_NOT_EQUAL(tdata->gmac_tag.len, 0,
+ "No GMAC length in the source data");
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_AES_GMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ retval = create_gmac_session(ts_params->valid_devs[0],
+ tdata, RTE_CRYPTO_AUTH_OP_GENERATE);
+
+ if (retval < 0)
+ return retval;
+
+ if (tdata->plaintext.len > MBUF_SIZE)
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->large_mbuf_pool);
+ else
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+ /*
+ * Runtime generate the large plain text instead of use hard code
+ * plain text vector. It is done to avoid create huge source file
+ * with the test vector.
+ */
+ if (tdata->plaintext.len == GMAC_LARGE_PLAINTEXT_LENGTH)
+ generate_gmac_large_plaintext(tdata->plaintext.data);
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+
+ memcpy(plaintext, tdata->plaintext.data, tdata->plaintext.len);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ tdata->plaintext.len);
+
+ retval = create_gmac_operation(RTE_CRYPTO_AUTH_OP_GENERATE,
+ tdata);
+
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ if (ut_params->op->sym->m_dst) {
+ auth_tag = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_dst,
+ uint8_t *, plaintext_pad_len);
+ } else {
+ auth_tag = plaintext + plaintext_pad_len;
+ }
+
+ debug_hexdump(stdout, "auth tag:", auth_tag, tdata->gmac_tag.len);
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->gmac_tag.data,
+ tdata->gmac_tag.len,
+ "GMAC Generated auth tag not as expected");
+
+ return 0;
+}
+
+static int
+test_AES_GMAC_authentication_test_case_1(void)
+{
+ return test_AES_GMAC_authentication(&gmac_test_case_1);
+}
+
+static int
+test_AES_GMAC_authentication_test_case_2(void)
+{
+ return test_AES_GMAC_authentication(&gmac_test_case_2);
+}
+
+static int
+test_AES_GMAC_authentication_test_case_3(void)
+{
+ return test_AES_GMAC_authentication(&gmac_test_case_3);
+}
+
+static int
+test_AES_GMAC_authentication_test_case_4(void)
+{
+ return test_AES_GMAC_authentication(&gmac_test_case_4);
+}
+
+static int
+test_AES_GMAC_authentication_verify(const struct gmac_test_data *tdata)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ int retval;
+ uint32_t plaintext_pad_len;
+ uint8_t *plaintext;
+
+ TEST_ASSERT_NOT_EQUAL(tdata->gmac_tag.len, 0,
+ "No GMAC length in the source data");
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = RTE_CRYPTO_AUTH_AES_GMAC;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ retval = create_gmac_session(ts_params->valid_devs[0],
+ tdata, RTE_CRYPTO_AUTH_OP_VERIFY);
+
+ if (retval < 0)
+ return retval;
+
+ if (tdata->plaintext.len > MBUF_SIZE)
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->large_mbuf_pool);
+ else
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(tdata->plaintext.len, 16);
+
+ /*
+ * Runtime generate the large plain text instead of use hard code
+ * plain text vector. It is done to avoid create huge source file
+ * with the test vector.
+ */
+ if (tdata->plaintext.len == GMAC_LARGE_PLAINTEXT_LENGTH)
+ generate_gmac_large_plaintext(tdata->plaintext.data);
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_pad_len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+
+ memcpy(plaintext, tdata->plaintext.data, tdata->plaintext.len);
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ tdata->plaintext.len);
+
+ retval = create_gmac_operation(RTE_CRYPTO_AUTH_OP_VERIFY,
+ tdata);
+
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ return 0;
+
+}
+
+static int
+test_AES_GMAC_authentication_verify_test_case_1(void)
+{
+ return test_AES_GMAC_authentication_verify(&gmac_test_case_1);
+}
+
+static int
+test_AES_GMAC_authentication_verify_test_case_2(void)
+{
+ return test_AES_GMAC_authentication_verify(&gmac_test_case_2);
+}
+
+static int
+test_AES_GMAC_authentication_verify_test_case_3(void)
+{
+ return test_AES_GMAC_authentication_verify(&gmac_test_case_3);
+}
+
+static int
+test_AES_GMAC_authentication_verify_test_case_4(void)
+{
+ return test_AES_GMAC_authentication_verify(&gmac_test_case_4);
+}
+
+struct test_crypto_vector {
+ enum rte_crypto_cipher_algorithm crypto_algo;
+ unsigned int cipher_offset;
+ unsigned int cipher_len;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len;
+ } cipher_key;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len;
+ } iv;
+
+ struct {
+ const uint8_t *data;
+ unsigned int len;
+ } plaintext;
+
+ struct {
+ const uint8_t *data;
+ unsigned int len;
+ } ciphertext;
+
+ enum rte_crypto_auth_algorithm auth_algo;
+ unsigned int auth_offset;
+
+ struct {
+ uint8_t data[128];
+ unsigned int len;
+ } auth_key;
+
+ struct {
+ const uint8_t *data;
+ unsigned int len;
+ } aad;
+
+ struct {
+ uint8_t data[128];
+ unsigned int len;
+ } digest;
+};
+
+static const struct test_crypto_vector
+hmac_sha1_test_crypto_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .plaintext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0xC4, 0xB7, 0x0E, 0x6B, 0xDE, 0xD1, 0xE7, 0x77,
+ 0x7E, 0x2E, 0x8F, 0xFC, 0x48, 0x39, 0x46, 0x17,
+ 0x3F, 0x91, 0x64, 0x59
+ },
+ .len = 20
+ }
+};
+
+static const struct test_crypto_vector
+aes128_gmac_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_GMAC,
+ .plaintext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B
+ },
+ .len = 12
+ },
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0xCA, 0x00, 0x99, 0x8B, 0x30, 0x7E, 0x74, 0x56,
+ 0x32, 0xA7, 0x87, 0xB5, 0xE9, 0xB2, 0x34, 0x5A
+ },
+ .len = 16
+ }
+};
+
+static const struct test_crypto_vector
+aes128cbc_hmac_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_offset = 0,
+ .cipher_len = 512,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_offset = 0,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x9A, 0x4F, 0x88, 0x1B, 0xB6, 0x8F, 0xD8, 0x60,
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0x18, 0x8C, 0x1D, 0x32
+ },
+ .len = 20
+ }
+};
+
+static const struct test_crypto_vector
+aes128cbc_hmac_sha1_aad_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_offset = 12,
+ .cipher_len = 496,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc_aad,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_offset = 0,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x1F, 0x6A, 0xD2, 0x8B, 0x4B, 0xB3, 0xC0, 0x9E,
+ 0x86, 0x9B, 0x3A, 0xF2, 0x00, 0x5B, 0x4F, 0x08,
+ 0x62, 0x8D, 0x62, 0x65
+ },
+ .len = 20
+ }
+};
+
+static void
+data_corruption(uint8_t *data)
+{
+ data[0] += 1;
+}
+
+static void
+tag_corruption(uint8_t *data, unsigned int tag_offset)
+{
+ data[tag_offset] += 1;
+}
+
+static int
+create_auth_session(struct crypto_unittest_params *ut_params,
+ uint8_t dev_id,
+ const struct test_crypto_vector *reference,
+ enum rte_crypto_auth_operation auth_op)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t auth_key[reference->auth_key.len + 1];
+
+ memcpy(auth_key, reference->auth_key.data, reference->auth_key.len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.next = NULL;
+ ut_params->auth_xform.auth.algo = reference->auth_algo;
+ ut_params->auth_xform.auth.key.length = reference->auth_key.len;
+ ut_params->auth_xform.auth.key.data = auth_key;
+ ut_params->auth_xform.auth.digest_length = reference->digest.len;
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ return 0;
+}
+
+static int
+create_auth_cipher_session(struct crypto_unittest_params *ut_params,
+ uint8_t dev_id,
+ const struct test_crypto_vector *reference,
+ enum rte_crypto_auth_operation auth_op,
+ enum rte_crypto_cipher_operation cipher_op)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t cipher_key[reference->cipher_key.len + 1];
+ uint8_t auth_key[reference->auth_key.len + 1];
+
+ memcpy(cipher_key, reference->cipher_key.data,
+ reference->cipher_key.len);
+ memcpy(auth_key, reference->auth_key.data, reference->auth_key.len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.op = auth_op;
+ ut_params->auth_xform.auth.algo = reference->auth_algo;
+ ut_params->auth_xform.auth.key.length = reference->auth_key.len;
+ ut_params->auth_xform.auth.key.data = auth_key;
+ ut_params->auth_xform.auth.digest_length = reference->digest.len;
+
+ if (reference->auth_algo == RTE_CRYPTO_AUTH_AES_GMAC) {
+ ut_params->auth_xform.auth.iv.offset = IV_OFFSET;
+ ut_params->auth_xform.auth.iv.length = reference->iv.len;
+ } else {
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+ ut_params->cipher_xform.cipher.algo = reference->crypto_algo;
+ ut_params->cipher_xform.cipher.op = cipher_op;
+ ut_params->cipher_xform.cipher.key.data = cipher_key;
+ ut_params->cipher_xform.cipher.key.length = reference->cipher_key.len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = reference->iv.len;
+ }
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ return 0;
+}
+
+static int
+create_auth_operation(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int auth_generate)
+{
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, reference->digest.len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, reference->plaintext.len);
+
+ if (auth_generate)
+ memset(sym_op->auth.digest.data, 0, reference->digest.len);
+ else
+ memcpy(sym_op->auth.digest.data,
+ reference->digest.data,
+ reference->digest.len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ reference->digest.len);
+
+ sym_op->auth.data.length = reference->plaintext.len;
+ sym_op->auth.data.offset = 0;
+
+ return 0;
+}
+
+static int
+create_auth_GMAC_operation(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int auth_generate)
+{
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, reference->digest.len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, reference->ciphertext.len);
+
+ if (auth_generate)
+ memset(sym_op->auth.digest.data, 0, reference->digest.len);
+ else
+ memcpy(sym_op->auth.digest.data,
+ reference->digest.data,
+ reference->digest.len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ reference->digest.len);
+
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ reference->iv.data, reference->iv.len);
+
+ sym_op->cipher.data.length = 0;
+ sym_op->cipher.data.offset = 0;
+
+ sym_op->auth.data.length = reference->plaintext.len;
+ sym_op->auth.data.offset = 0;
+
+ return 0;
+}
+
+static int
+create_cipher_auth_operation(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int auth_generate)
+{
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate pktmbuf offload");
+
+ /* Set crypto operation data parameters */
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ /* set crypto operation source mbuf */
+ sym_op->m_src = ut_params->ibuf;
+
+ /* digest */
+ sym_op->auth.digest.data = (uint8_t *)rte_pktmbuf_append(
+ ut_params->ibuf, reference->digest.len);
+
+ TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
+ "no room to append auth tag");
+
+ sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+ ut_params->ibuf, reference->ciphertext.len);
+
+ if (auth_generate)
+ memset(sym_op->auth.digest.data, 0, reference->digest.len);
+ else
+ memcpy(sym_op->auth.digest.data,
+ reference->digest.data,
+ reference->digest.len);
+
+ debug_hexdump(stdout, "digest:",
+ sym_op->auth.digest.data,
+ reference->digest.len);
+
+ rte_memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET),
+ reference->iv.data, reference->iv.len);
+
+ sym_op->cipher.data.length = reference->cipher_len;
+ sym_op->cipher.data.offset = reference->cipher_offset;
+
+ sym_op->auth.data.length = reference->plaintext.len;
+ sym_op->auth.data.offset = reference->auth_offset;
+
+ return 0;
+}
+
+static int
+create_auth_verify_operation(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return create_auth_operation(ts_params, ut_params, reference, 0);
+}
+
+static int
+create_auth_verify_GMAC_operation(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return create_auth_GMAC_operation(ts_params, ut_params, reference, 0);
+}
+
+static int
+create_cipher_auth_verify_operation(struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return create_cipher_auth_operation(ts_params, ut_params, reference, 0);
+}
+
+static int
+test_authentication_verify_fail_when_data_corruption(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int data_corrupted)
+{
+ int retval;
+
+ uint8_t *plaintext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = reference->auth_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create session */
+ retval = create_auth_session(ut_params,
+ ts_params->valid_devs[0],
+ reference,
+ RTE_CRYPTO_AUTH_OP_VERIFY);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ reference->plaintext.len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+ memcpy(plaintext, reference->plaintext.data, reference->plaintext.len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ reference->plaintext.len);
+
+ /* Create operation */
+ retval = create_auth_verify_operation(ts_params, ut_params, reference);
+
+ if (retval < 0)
+ return retval;
+
+ if (data_corrupted)
+ data_corruption(plaintext);
+ else
+ tag_corruption(plaintext, reference->plaintext.len);
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "authentication not failed");
+ } else {
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
+ }
+
+ return 0;
+}
+
+static int
+test_authentication_verify_GMAC_fail_when_corruption(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int data_corrupted)
+{
+ int retval;
+ uint8_t *plaintext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = reference->auth_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create session */
+ retval = create_auth_cipher_session(ut_params,
+ ts_params->valid_devs[0],
+ reference,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ RTE_CRYPTO_CIPHER_OP_DECRYPT);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ reference->plaintext.len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+ memcpy(plaintext, reference->plaintext.data, reference->plaintext.len);
+
+ debug_hexdump(stdout, "plaintext:", plaintext,
+ reference->plaintext.len);
+
+ /* Create operation */
+ retval = create_auth_verify_GMAC_operation(ts_params,
+ ut_params,
+ reference);
+
+ if (retval < 0)
+ return retval;
+
+ if (data_corrupted)
+ data_corruption(plaintext);
+ else
+ tag_corruption(plaintext, reference->aad.len);
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "authentication not failed");
+ } else {
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
+ }
+
+ return 0;
+}
+
+static int
+test_authenticated_decryption_fail_when_corruption(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference,
+ unsigned int data_corrupted)
+{
+ int retval;
+
+ uint8_t *ciphertext;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = reference->auth_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = reference->crypto_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create session */
+ retval = create_auth_cipher_session(ut_params,
+ ts_params->valid_devs[0],
+ reference,
+ RTE_CRYPTO_AUTH_OP_VERIFY,
+ RTE_CRYPTO_CIPHER_OP_DECRYPT);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ reference->ciphertext.len);
+ TEST_ASSERT_NOT_NULL(ciphertext, "no room to append ciphertext");
+ memcpy(ciphertext, reference->ciphertext.data,
+ reference->ciphertext.len);
+
+ /* Create operation */
+ retval = create_cipher_auth_verify_operation(ts_params,
+ ut_params,
+ reference);
+
+ if (retval < 0)
+ return retval;
+
+ if (data_corrupted)
+ data_corruption(ciphertext);
+ else
+ tag_corruption(ciphertext, reference->ciphertext.len);
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO) {
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "authentication not failed");
+ } else {
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+ TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
+ }
+
+ return 0;
+}
+
+static int
+test_authenticated_encryt_with_esn(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ int retval;
+
+ uint8_t *authciphertext, *plaintext, *auth_tag;
+ uint16_t plaintext_pad_len;
+ uint8_t cipher_key[reference->cipher_key.len + 1];
+ uint8_t auth_key[reference->auth_key.len + 1];
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = reference->auth_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = reference->crypto_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create session */
+ memcpy(cipher_key, reference->cipher_key.data,
+ reference->cipher_key.len);
+ memcpy(auth_key, reference->auth_key.data, reference->auth_key.len);
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.cipher.algo = reference->crypto_algo;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ ut_params->cipher_xform.cipher.key.data = cipher_key;
+ ut_params->cipher_xform.cipher.key.length = reference->cipher_key.len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = reference->iv.len;
+
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ ut_params->auth_xform.auth.algo = reference->auth_algo;
+ ut_params->auth_xform.auth.key.length = reference->auth_key.len;
+ ut_params->auth_xform.auth.key.data = auth_key;
+ ut_params->auth_xform.auth.digest_length = reference->digest.len;
+ ut_params->auth_xform.next = NULL;
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess,
+ &ut_params->cipher_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ reference->plaintext.len);
+ TEST_ASSERT_NOT_NULL(plaintext, "no room to append plaintext");
+ memcpy(plaintext, reference->plaintext.data, reference->plaintext.len);
+
+ /* Create operation */
+ retval = create_cipher_auth_operation(ts_params,
+ ut_params,
+ reference, 0);
+
+ if (retval < 0)
+ return retval;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ ut_params->op = process_crypto_request(
+ ts_params->valid_devs[0], ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "no crypto operation returned");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+ plaintext_pad_len = RTE_ALIGN_CEIL(reference->plaintext.len, 16);
+
+ authciphertext = rte_pktmbuf_mtod_offset(ut_params->ibuf, uint8_t *,
+ ut_params->op->sym->auth.data.offset);
+ auth_tag = authciphertext + plaintext_pad_len;
+ debug_hexdump(stdout, "ciphertext:", authciphertext,
+ reference->ciphertext.len);
+ debug_hexdump(stdout, "auth tag:", auth_tag, reference->digest.len);
+
+ /* Validate obuf */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ authciphertext,
+ reference->ciphertext.data,
+ reference->ciphertext.len,
+ "Ciphertext data not as expected");
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ reference->digest.data,
+ reference->digest.len,
+ "Generated digest not as expected");
+
+ return TEST_SUCCESS;
+
+}
+
+static int
+test_authenticated_decrypt_with_esn(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ int retval;
+
+ uint8_t *ciphertext;
+ uint8_t cipher_key[reference->cipher_key.len + 1];
+ uint8_t auth_key[reference->auth_key.len + 1];
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = reference->auth_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = reference->crypto_algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* Create session */
+ memcpy(cipher_key, reference->cipher_key.data,
+ reference->cipher_key.len);
+ memcpy(auth_key, reference->auth_key.data, reference->auth_key.len);
+
+ /* Setup Authentication Parameters */
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ ut_params->auth_xform.auth.algo = reference->auth_algo;
+ ut_params->auth_xform.auth.key.length = reference->auth_key.len;
+ ut_params->auth_xform.auth.key.data = auth_key;
+ ut_params->auth_xform.auth.digest_length = reference->digest.len;
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+ /* Setup Cipher Parameters */
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.next = NULL;
+ ut_params->cipher_xform.cipher.algo = reference->crypto_algo;
+ ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ ut_params->cipher_xform.cipher.key.data = cipher_key;
+ ut_params->cipher_xform.cipher.key.length = reference->cipher_key.len;
+ ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ ut_params->cipher_xform.cipher.iv.length = reference->iv.len;
+
+ /* Create Crypto session*/
+ ut_params->sess = rte_cryptodev_sym_session_create(
+ ts_params->session_mpool);
+
+ rte_cryptodev_sym_session_init(ts_params->valid_devs[0],
+ ut_params->sess,
+ &ut_params->auth_xform,
+ ts_params->session_priv_mpool);
+
+ TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+ "Failed to allocate input buffer in mempool");
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ reference->ciphertext.len);
+ TEST_ASSERT_NOT_NULL(ciphertext, "no room to append ciphertext");
+ memcpy(ciphertext, reference->ciphertext.data,
+ reference->ciphertext.len);
+
+ /* Create operation */
+ retval = create_cipher_auth_verify_operation(ts_params,
+ ut_params,
+ reference);
+
+ if (retval < 0)
+ return retval;
+
+ if (gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_crypt_auth_op(ts_params->valid_devs[0],
+ ut_params->op);
+ else
+ ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op);
+
+ TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
+ TEST_ASSERT_EQUAL(ut_params->op->status,
+ RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing passed");
+
+ ut_params->obuf = ut_params->op->sym->m_src;
+ TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+
+ return 0;
+}
+
+static int
+create_aead_operation_SGL(enum rte_crypto_aead_operation op,
+ const struct aead_test_data *tdata,
+ void *digest_mem, uint64_t digest_phys)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+
+ const unsigned int auth_tag_len = tdata->auth_tag.len;
+ const unsigned int iv_len = tdata->iv.len;
+ unsigned int aad_len = tdata->aad.len;
+ unsigned int aad_len_pad = 0;
+
+ /* Generate Crypto op data structure */
+ ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(ut_params->op,
+ "Failed to allocate symmetric crypto operation struct");
+
+ struct rte_crypto_sym_op *sym_op = ut_params->op->sym;
+
+ sym_op->aead.digest.data = digest_mem;
+
+ TEST_ASSERT_NOT_NULL(sym_op->aead.digest.data,
+ "no room to append digest");
+
+ sym_op->aead.digest.phys_addr = digest_phys;
+
+ if (op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
+ rte_memcpy(sym_op->aead.digest.data, tdata->auth_tag.data,
+ auth_tag_len);
+ debug_hexdump(stdout, "digest:",
+ sym_op->aead.digest.data,
+ auth_tag_len);
+ }
+
+ /* Append aad data */
+ if (tdata->algo == RTE_CRYPTO_AEAD_AES_CCM) {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op,
+ uint8_t *, IV_OFFSET);
+
+ /* Copy IV 1 byte after the IV pointer, according to the API */
+ rte_memcpy(iv_ptr + 1, tdata->iv.data, iv_len);
+
+ aad_len = RTE_ALIGN_CEIL(aad_len + 18, 16);
+
+ sym_op->aead.aad.data = (uint8_t *)rte_pktmbuf_prepend(
+ ut_params->ibuf, aad_len);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.aad.data,
+ "no room to prepend aad");
+ sym_op->aead.aad.phys_addr = rte_pktmbuf_iova(
+ ut_params->ibuf);
+
+ memset(sym_op->aead.aad.data, 0, aad_len);
+ /* Copy AAD 18 bytes after the AAD pointer, according to the API */
+ rte_memcpy(sym_op->aead.aad.data, tdata->aad.data, aad_len);
+
+ debug_hexdump(stdout, "iv:", iv_ptr, iv_len);
+ debug_hexdump(stdout, "aad:",
+ sym_op->aead.aad.data, aad_len);
+ } else {
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(ut_params->op,
+ uint8_t *, IV_OFFSET);
+
+ rte_memcpy(iv_ptr, tdata->iv.data, iv_len);
+
+ aad_len_pad = RTE_ALIGN_CEIL(aad_len, 16);
+
+ sym_op->aead.aad.data = (uint8_t *)rte_pktmbuf_prepend(
+ ut_params->ibuf, aad_len_pad);
+ TEST_ASSERT_NOT_NULL(sym_op->aead.aad.data,
+ "no room to prepend aad");
+ sym_op->aead.aad.phys_addr = rte_pktmbuf_iova(
+ ut_params->ibuf);
+
+ memset(sym_op->aead.aad.data, 0, aad_len);
+ rte_memcpy(sym_op->aead.aad.data, tdata->aad.data, aad_len);
+
+ debug_hexdump(stdout, "iv:", iv_ptr, iv_len);
+ debug_hexdump(stdout, "aad:",
+ sym_op->aead.aad.data, aad_len);
+ }
+
+ sym_op->aead.data.length = tdata->plaintext.len;
+ sym_op->aead.data.offset = aad_len_pad;
+
+ return 0;
+}
+
+#define SGL_MAX_NO 16
+
+static int
+test_authenticated_encryption_SGL(const struct aead_test_data *tdata,
+ const int oop, uint32_t fragsz, uint32_t fragsz_oop)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct crypto_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf *buf, *buf_oop = NULL, *buf_last_oop = NULL;
+ int retval;
+ int to_trn = 0;
+ int to_trn_tbl[SGL_MAX_NO];
+ int segs = 1;
+ unsigned int trn_data = 0;
+ uint8_t *plaintext, *ciphertext, *auth_tag;
+ struct rte_cryptodev_info dev_info;
+
+ /* Verify the capabilities */
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+ cap_idx.algo.aead = tdata->algo;
+ if (rte_cryptodev_sym_capability_get(ts_params->valid_devs[0],
+ &cap_idx) == NULL)
+ return -ENOTSUP;
+
+ /* OOP not supported with CPU crypto */
+ if (oop && gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ return -ENOTSUP;
+
+ /* Detailed check for the particular SGL support flag */
+ rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+ if (!oop) {
+ unsigned int sgl_in = fragsz < tdata->plaintext.len;
+ if (sgl_in && (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_IN_PLACE_SGL)))
+ return -ENOTSUP;
+ } else {
+ unsigned int sgl_in = fragsz < tdata->plaintext.len;
+ unsigned int sgl_out = (fragsz_oop ? fragsz_oop : fragsz) <
+ tdata->plaintext.len;
+ if (sgl_in && !sgl_out) {
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT))
+ return -ENOTSUP;
+ } else if (!sgl_in && sgl_out) {
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT))
+ return -ENOTSUP;
+ } else if (sgl_in && sgl_out) {
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT))
+ return -ENOTSUP;
+ }
+ }
+
+ if (fragsz > tdata->plaintext.len)
+ fragsz = tdata->plaintext.len;
+
+ uint16_t plaintext_len = fragsz;
+ uint16_t frag_size_oop = fragsz_oop ? fragsz_oop : fragsz;
+
+ if (fragsz_oop > tdata->plaintext.len)
+ frag_size_oop = tdata->plaintext.len;
+
+ int ecx = 0;
+ void *digest_mem = NULL;
+
+ uint32_t prepend_len = RTE_ALIGN_CEIL(tdata->aad.len, 16);
+
+ if (tdata->plaintext.len % fragsz != 0) {
+ if (tdata->plaintext.len / fragsz + 1 > SGL_MAX_NO)
+ return 1;
+ } else {
+ if (tdata->plaintext.len / fragsz > SGL_MAX_NO)
+ return 1;
+ }
+
+ /*
+ * For out-op-place we need to alloc another mbuf
+ */
+ if (oop) {
+ ut_params->obuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ rte_pktmbuf_append(ut_params->obuf,
+ frag_size_oop + prepend_len);
+ buf_oop = ut_params->obuf;
+ }
+
+ /* Create AEAD session */
+ retval = create_aead_session(ts_params->valid_devs[0],
+ tdata->algo,
+ RTE_CRYPTO_AEAD_OP_ENCRYPT,
+ tdata->key.data, tdata->key.len,
+ tdata->aad.len, tdata->auth_tag.len,
+ tdata->iv.len);
+ if (retval < 0)
+ return retval;
+
+ ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+
+ /* clear mbuf payload */
+ memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(ut_params->ibuf));
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ plaintext_len);
+
+ memcpy(plaintext, tdata->plaintext.data, plaintext_len);
+
+ trn_data += plaintext_len;
+
+ buf = ut_params->ibuf;
+
+ /*
+ * Loop until no more fragments
+ */
+
+ while (trn_data < tdata->plaintext.len) {
+ ++segs;
+ to_trn = (tdata->plaintext.len - trn_data < fragsz) ?
+ (tdata->plaintext.len - trn_data) : fragsz;
+
+ to_trn_tbl[ecx++] = to_trn;
+
+ buf->next = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf = buf->next;
+
+ memset(rte_pktmbuf_mtod(buf, uint8_t *), 0,
+ rte_pktmbuf_tailroom(buf));
+
+ /* OOP */
+ if (oop && !fragsz_oop) {
+ buf_last_oop = buf_oop->next =
+ rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf_oop = buf_oop->next;
+ memset(rte_pktmbuf_mtod(buf_oop, uint8_t *),
+ 0, rte_pktmbuf_tailroom(buf_oop));
+ rte_pktmbuf_append(buf_oop, to_trn);
+ }
+
+ plaintext = (uint8_t *)rte_pktmbuf_append(buf,
+ to_trn);
+
+ memcpy(plaintext, tdata->plaintext.data + trn_data,
+ to_trn);
+ trn_data += to_trn;
+ if (trn_data == tdata->plaintext.len) {
+ if (oop) {
+ if (!fragsz_oop)
+ digest_mem = rte_pktmbuf_append(buf_oop,
+ tdata->auth_tag.len);
+ } else
+ digest_mem = (uint8_t *)rte_pktmbuf_append(buf,
+ tdata->auth_tag.len);
+ }
+ }
+
+ uint64_t digest_phys = 0;
+
+ ut_params->ibuf->nb_segs = segs;
+
+ segs = 1;
+ if (fragsz_oop && oop) {
+ to_trn = 0;
+ ecx = 0;
+
+ if (frag_size_oop == tdata->plaintext.len) {
+ digest_mem = rte_pktmbuf_append(ut_params->obuf,
+ tdata->auth_tag.len);
+
+ digest_phys = rte_pktmbuf_iova_offset(
+ ut_params->obuf,
+ tdata->plaintext.len + prepend_len);
+ }
+
+ trn_data = frag_size_oop;
+ while (trn_data < tdata->plaintext.len) {
+ ++segs;
+ to_trn =
+ (tdata->plaintext.len - trn_data <
+ frag_size_oop) ?
+ (tdata->plaintext.len - trn_data) :
+ frag_size_oop;
+
+ to_trn_tbl[ecx++] = to_trn;
+
+ buf_last_oop = buf_oop->next =
+ rte_pktmbuf_alloc(ts_params->mbuf_pool);
+ buf_oop = buf_oop->next;
+ memset(rte_pktmbuf_mtod(buf_oop, uint8_t *),
+ 0, rte_pktmbuf_tailroom(buf_oop));
+ rte_pktmbuf_append(buf_oop, to_trn);
+
+ trn_data += to_trn;
+
+ if (trn_data == tdata->plaintext.len) {
+ digest_mem = rte_pktmbuf_append(buf_oop,
+ tdata->auth_tag.len);
+ }
+ }
+
+ ut_params->obuf->nb_segs = segs;
+ }
+
+ /*
+ * Place digest at the end of the last buffer
+ */
+ if (!digest_phys)
+ digest_phys = rte_pktmbuf_iova(buf) + to_trn;
+ if (oop && buf_last_oop)
+ digest_phys = rte_pktmbuf_iova(buf_last_oop) + to_trn;
+
+ if (!digest_mem && !oop) {
+ digest_mem = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+ + tdata->auth_tag.len);
+ digest_phys = rte_pktmbuf_iova_offset(ut_params->ibuf,
+ tdata->plaintext.len);
+ }
+
+ /* Create AEAD operation */
+ retval = create_aead_operation_SGL(RTE_CRYPTO_AEAD_OP_ENCRYPT,
+ tdata, digest_mem, digest_phys);
+
+ if (retval < 0)
+ return retval;
+
+ rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+ ut_params->op->sym->m_src = ut_params->ibuf;
+ if (oop)
+ ut_params->op->sym->m_dst = ut_params->obuf;
+
+ /* Process crypto operation */
+ if (oop == IN_PLACE &&
+ gbl_action_type == RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO)
+ process_cpu_aead_op(ts_params->valid_devs[0], ut_params->op);
+ else
+ TEST_ASSERT_NOT_NULL(
+ process_crypto_request(ts_params->valid_devs[0],
+ ut_params->op), "failed to process sym crypto op");
+
+ TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+ "crypto op processing failed");
+
+
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_src,
+ uint8_t *, prepend_len);
+ if (oop) {
+ ciphertext = rte_pktmbuf_mtod_offset(ut_params->op->sym->m_dst,
+ uint8_t *, prepend_len);
+ }
+
+ if (fragsz_oop)
+ fragsz = fragsz_oop;
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data,
+ fragsz,
+ "Ciphertext data not as expected");
+
+ buf = ut_params->op->sym->m_src->next;
+ if (oop)
+ buf = ut_params->op->sym->m_dst->next;
+
+ unsigned int off = fragsz;
+
+ ecx = 0;
+ while (buf) {
+ ciphertext = rte_pktmbuf_mtod(buf,
+ uint8_t *);
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ ciphertext,
+ tdata->ciphertext.data + off,
+ to_trn_tbl[ecx],
+ "Ciphertext data not as expected");
+
+ off += to_trn_tbl[ecx++];
+ buf = buf->next;
+ }
+
+ auth_tag = digest_mem;
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(
+ auth_tag,
+ tdata->auth_tag.data,
+ tdata->auth_tag.len,
+ "Generated auth tag not as expected");
+
+ return 0;
+}
+
+static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_400B(void)
+{
+ return test_authenticated_encryption_SGL(
+ &gcm_test_case_SGL_1, OUT_OF_PLACE, 400, 400);
+}
+
+static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_1500B_2000B(void)
+{
+ return test_authenticated_encryption_SGL(
+ &gcm_test_case_SGL_1, OUT_OF_PLACE, 1500, 2000);
+}
+
+static int
+test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg(void)
+{
+ return test_authenticated_encryption_SGL(
+ &gcm_test_case_8, OUT_OF_PLACE, 400,
+ gcm_test_case_8.plaintext.len);
+}
+
+static int
+test_AES_GCM_auth_encrypt_SGL_in_place_1500B(void)
+{
+ /* This test is not for OPENSSL PMD */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD)))
+ return -ENOTSUP;
+
+ return test_authenticated_encryption_SGL(
+ &gcm_test_case_SGL_1, IN_PLACE, 1500, 0);
+}
+
+static int
+test_authentication_verify_fail_when_data_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authentication_verify_fail_when_data_corruption(
+ ts_params, ut_params, reference, 1);
+}
+
+static int
+test_authentication_verify_fail_when_tag_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authentication_verify_fail_when_data_corruption(
+ ts_params, ut_params, reference, 0);
+}
+
+static int
+test_authentication_verify_GMAC_fail_when_data_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authentication_verify_GMAC_fail_when_corruption(
+ ts_params, ut_params, reference, 1);
+}
+
+static int
+test_authentication_verify_GMAC_fail_when_tag_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authentication_verify_GMAC_fail_when_corruption(
+ ts_params, ut_params, reference, 0);
+}
+
+static int
+test_authenticated_decryption_fail_when_data_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authenticated_decryption_fail_when_corruption(
+ ts_params, ut_params, reference, 1);
+}
+
+static int
+test_authenticated_decryption_fail_when_tag_corrupted(
+ struct crypto_testsuite_params *ts_params,
+ struct crypto_unittest_params *ut_params,
+ const struct test_crypto_vector *reference)
+{
+ return test_authenticated_decryption_fail_when_corruption(
+ ts_params, ut_params, reference, 0);
+}
+
+static int
+authentication_verify_HMAC_SHA1_fail_data_corrupt(void)
+{
+ return test_authentication_verify_fail_when_data_corrupted(
+ &testsuite_params, &unittest_params,
+ &hmac_sha1_test_crypto_vector);
+}
+
+static int
+authentication_verify_HMAC_SHA1_fail_tag_corrupt(void)
+{
+ return test_authentication_verify_fail_when_tag_corrupted(
+ &testsuite_params, &unittest_params,
+ &hmac_sha1_test_crypto_vector);
+}
+
+static int
+authentication_verify_AES128_GMAC_fail_data_corrupt(void)
+{
+ return test_authentication_verify_GMAC_fail_when_data_corrupted(
+ &testsuite_params, &unittest_params,
+ &aes128_gmac_test_vector);
+}
+
+static int
+authentication_verify_AES128_GMAC_fail_tag_corrupt(void)
+{
+ return test_authentication_verify_GMAC_fail_when_tag_corrupted(
+ &testsuite_params, &unittest_params,
+ &aes128_gmac_test_vector);
+}
+
+static int
+auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt(void)
+{
+ return test_authenticated_decryption_fail_when_data_corrupted(
+ &testsuite_params,
+ &unittest_params,
+ &aes128cbc_hmac_sha1_test_vector);
+}
+
+static int
+auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt(void)
+{
+ return test_authenticated_decryption_fail_when_tag_corrupted(
+ &testsuite_params,
+ &unittest_params,
+ &aes128cbc_hmac_sha1_test_vector);
+}
+
+static int
+auth_encrypt_AES128CBC_HMAC_SHA1_esn_check(void)
+{
+ return test_authenticated_encryt_with_esn(
+ &testsuite_params,
+ &unittest_params,
+ &aes128cbc_hmac_sha1_aad_test_vector);
+}
+
+static int
+auth_decrypt_AES128CBC_HMAC_SHA1_esn_check(void)
+{
+ return test_authenticated_decrypt_with_esn(
+ &testsuite_params,
+ &unittest_params,
+ &aes128cbc_hmac_sha1_aad_test_vector);
+}
+
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+
+/* global AESNI slave IDs for the scheduler test */
+uint8_t aesni_ids[2];
+
+static int
+test_scheduler_attach_slave_op(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t sched_id = ts_params->valid_devs[0];
+ uint32_t nb_devs, i, nb_devs_attached = 0;
+ int ret;
+ char vdev_name[32];
+
+ /* create 2 AESNI_MB if necessary */
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD)));
+ if (nb_devs < 2) {
+ for (i = nb_devs; i < 2; i++) {
+ snprintf(vdev_name, sizeof(vdev_name), "%s_%u",
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD),
+ i);
+ ret = rte_vdev_init(vdev_name, NULL);
+
+ TEST_ASSERT(ret == 0,
+ "Failed to create instance %u of"
+ " pmd : %s",
+ i, RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
+ }
+ }
+
+ /* attach 2 AESNI_MB cdevs */
+ for (i = 0; i < rte_cryptodev_count() && nb_devs_attached < 2;
+ i++) {
+ struct rte_cryptodev_info info;
+ unsigned int session_size;
+
+ rte_cryptodev_info_get(i, &info);
+ if (info.driver_id != rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD)))
+ continue;
+
+ session_size = rte_cryptodev_sym_get_private_session_size(i);
+ /*
+ * Create the session mempool again, since now there are new devices
+ * to use the mempool.
+ */
+ if (ts_params->session_mpool) {
+ rte_mempool_free(ts_params->session_mpool);
+ ts_params->session_mpool = NULL;
+ }
+ if (ts_params->session_priv_mpool) {
+ rte_mempool_free(ts_params->session_priv_mpool);
+ ts_params->session_priv_mpool = NULL;
+ }
+
+ if (info.sym.max_nb_sessions != 0 &&
+ info.sym.max_nb_sessions < MAX_NB_SESSIONS) {
+ RTE_LOG(ERR, USER1,
+ "Device does not support "
+ "at least %u sessions\n",
+ MAX_NB_SESSIONS);
+ return TEST_FAILED;
+ }
+ /*
+ * Create mempool with maximum number of sessions,
+ * to include the session headers
+ */
+ if (ts_params->session_mpool == NULL) {
+ ts_params->session_mpool =
+ rte_cryptodev_sym_session_pool_create(
+ "test_sess_mp",
+ MAX_NB_SESSIONS, 0, 0, 0,
+ SOCKET_ID_ANY);
+ TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
+ "session mempool allocation failed");
+ }
+
+ /*
+ * Create mempool with maximum number of sessions,
+ * to include device specific session private data
+ */
+ if (ts_params->session_priv_mpool == NULL) {
+ ts_params->session_priv_mpool = rte_mempool_create(
+ "test_sess_mp_priv",
+ MAX_NB_SESSIONS,
+ session_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+
+ TEST_ASSERT_NOT_NULL(ts_params->session_priv_mpool,
+ "session mempool allocation failed");
+ }
+
+ ts_params->qp_conf.mp_session = ts_params->session_mpool;
+ ts_params->qp_conf.mp_session_private =
+ ts_params->session_priv_mpool;
+
+ ret = rte_cryptodev_scheduler_slave_attach(sched_id,
+ (uint8_t)i);
+
+ TEST_ASSERT(ret == 0,
+ "Failed to attach device %u of pmd : %s", i,
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
+
+ aesni_ids[nb_devs_attached] = (uint8_t)i;
+
+ nb_devs_attached++;
+ }
+
+ return 0;
+}
+
+static int
+test_scheduler_detach_slave_op(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t sched_id = ts_params->valid_devs[0];
+ uint32_t i;
+ int ret;
+
+ for (i = 0; i < 2; i++) {
+ ret = rte_cryptodev_scheduler_slave_detach(sched_id,
+ aesni_ids[i]);
+ TEST_ASSERT(ret == 0,
+ "Failed to detach device %u", aesni_ids[i]);
+ }
+
+ return 0;
+}
+
+static int
+test_scheduler_mode_op(enum rte_cryptodev_scheduler_mode scheduler_mode)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t sched_id = ts_params->valid_devs[0];
+ /* set mode */
+ return rte_cryptodev_scheduler_mode_set(sched_id,
+ scheduler_mode);
+}
+
+static int
+test_scheduler_mode_roundrobin_op(void)
+{
+ TEST_ASSERT(test_scheduler_mode_op(CDEV_SCHED_MODE_ROUNDROBIN) ==
+ 0, "Failed to set roundrobin mode");
+ return 0;
+
+}
+
+static int
+test_scheduler_mode_multicore_op(void)
+{
+ TEST_ASSERT(test_scheduler_mode_op(CDEV_SCHED_MODE_MULTICORE) ==
+ 0, "Failed to set multicore mode");
+
+ return 0;
+}
+
+static int
+test_scheduler_mode_failover_op(void)
+{
+ TEST_ASSERT(test_scheduler_mode_op(CDEV_SCHED_MODE_FAILOVER) ==
+ 0, "Failed to set failover mode");
+
+ return 0;
+}
+
+static int
+test_scheduler_mode_pkt_size_distr_op(void)
+{
+ TEST_ASSERT(test_scheduler_mode_op(CDEV_SCHED_MODE_PKT_SIZE_DISTR) ==
+ 0, "Failed to set pktsize mode");
+
+ return 0;
+}
+
+static struct unit_test_suite cryptodev_scheduler_testsuite = {
+ .suite_name = "Crypto Device Scheduler Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ /* Multi Core */
+ TEST_CASE_ST(NULL, NULL, test_scheduler_attach_slave_op),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_mode_multicore_op),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_detach_slave_op),
+
+ /* Round Robin */
+ TEST_CASE_ST(NULL, NULL, test_scheduler_attach_slave_op),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_mode_roundrobin_op),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_detach_slave_op),
+
+ /* Fail over */
+ TEST_CASE_ST(NULL, NULL, test_scheduler_attach_slave_op),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_mode_failover_op),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_detach_slave_op),
+
+ /* PKT SIZE */
+ TEST_CASE_ST(NULL, NULL, test_scheduler_attach_slave_op),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_mode_pkt_size_distr_op),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(NULL, NULL, test_scheduler_detach_slave_op),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+#endif /* RTE_LIBRTE_PMD_CRYPTO_SCHEDULER */
+
+static struct unit_test_suite cryptodev_testsuite = {
+ .suite_name = "Crypto Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_device_configure_invalid_dev_id),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_queue_pair_descriptor_setup),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_device_configure_invalid_queue_pair_ids),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_multi_session),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_multi_session_random_usage),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_invalid_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_null_burst_operation),
+
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_docsis_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_DES_docsis_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_stats),
+
+ /** AES CCM Authenticated Encryption 128 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_128_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_128_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_128_3),
+
+ /** AES CCM Authenticated Decryption 128 bits key*/
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_128_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_128_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_128_3),
+
+ /** AES CCM Authenticated Encryption 192 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_192_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_192_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_192_3),
+
+ /** AES CCM Authenticated Decryption 192 bits key*/
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_192_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_192_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_192_3),
+
+ /** AES CCM Authenticated Encryption 256 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_256_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_256_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_encryption_test_case_256_3),
+
+ /** AES CCM Authenticated Decryption 256 bits key*/
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_256_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_256_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_CCM_authenticated_decryption_test_case_256_3),
+
+ /** AES GCM Authenticated Encryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encrypt_SGL_in_place_1500B),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_400B),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encrypt_SGL_out_of_place_1500B_2000B),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_7),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_8),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_J0_authenticated_encryption_test_case_1),
+
+ /** AES GCM Authenticated Decryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_7),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_8),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_J0_authenticated_decryption_test_case_1),
+
+ /** AES GCM Authenticated Encryption 192 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_192_7),
+
+ /** AES GCM Authenticated Decryption 192 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_192_7),
+
+ /** AES GCM Authenticated Encryption 256 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_256_7),
+
+ /** AES GCM Authenticated Decryption 256 bits key */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_256_7),
+
+ /** AES GCM Authenticated Encryption big aad size */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_aad_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_test_case_aad_2),
+
+ /** AES GCM Authenticated Decryption big aad size */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_aad_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_test_case_aad_2),
+
+ /** Out of place tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_oop_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_oop_test_case_1),
+
+ /** Session-less tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_sessionless_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_sessionless_test_case_1),
+
+ /** AES GMAC Authentication */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_4),
+
+ /** SNOW 3G encrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_offset_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1_oop),
+
+ /** SNOW 3G generate auth, then encrypt (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_test_case_2_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_part_digest_enc),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_part_digest_enc_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_test_case_3_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_test_case_3_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_part_digest_enc_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_part_digest_enc_oop_sgl),
+
+ /** SNOW 3G decrypt (UEA2), then verify auth */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_test_case_2_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_part_digest_enc),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_part_digest_enc_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_test_case_3_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_test_case_3_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_part_digest_enc_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_verify_part_digest_enc_oop_sgl),
+
+ /** SNOW 3G decrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_with_digest_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_3),
+ /* Tests with buffers which length is not byte-aligned */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_3),
+ /* Tests with buffers which length is not byte-aligned */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_cipher_auth_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_auth_cipher_with_digest_test_case_1),
+
+ /** ZUC encrypt only (EEA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_6_sgl),
+
+ /** ZUC authenticate (EIA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_7),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_8),
+
+ /** ZUC alg-chain (EEA3/EIA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_cipher_auth_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_cipher_auth_test_case_2),
+
+ /** ZUC generate auth, then encrypt (EEA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_test_case_1_oop_sgl),
+
+ /** ZUC decrypt (EEA3), then verify auth */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_verify_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_verify_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_auth_cipher_verify_test_case_1_oop_sgl),
+
+ /** HMAC_MD5 Authentication */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_MD5_HMAC_generate_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_MD5_HMAC_verify_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_MD5_HMAC_generate_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_MD5_HMAC_verify_case_2),
+
+ /** KASUMI hash only (UIA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_6),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_5),
+
+ /** KASUMI encrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_5),
+
+ /** KASUMI decrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1_oop),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_cipher_auth_test_case_1),
+
+ /** KASUMI generate auth, then encrypt (F8) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_test_case_2_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_test_case_2_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_test_case_2_oop_sgl),
+
+ /** KASUMI decrypt (F8), then verify auth */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_verify_test_case_2_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_verify_test_case_2_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_auth_cipher_verify_test_case_2_oop_sgl),
+
+ /** ESN Testcase */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_encrypt_AES128CBC_HMAC_SHA1_esn_check),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decrypt_AES128CBC_HMAC_SHA1_esn_check),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_iv_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_in_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_out_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_aad_len_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_aad_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_encryption_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_iv_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_in_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_out_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_aad_len_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_aad_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_auth_decryption_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+
+ /** Mixed CIPHER + HASH algorithms */
+ /** AUTH AES CMAC + CIPHER AES CTR */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_aes_cmac_aes_ctr_digest_enc_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_aes_cmac_aes_ctr_digest_enc_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_aes_cmac_aes_ctr_digest_enc_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl),
+
+ /** AUTH ZUC + CIPHER SNOW3G */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_zuc_cipher_snow_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_zuc_cipher_snow_test_case_1),
+ /** AUTH AES CMAC + CIPHER SNOW3G */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_aes_cmac_cipher_snow_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_aes_cmac_cipher_snow_test_case_1),
+ /** AUTH ZUC + CIPHER AES CTR */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_zuc_cipher_aes_ctr_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_zuc_cipher_aes_ctr_test_case_1),
+ /** AUTH SNOW3G + CIPHER AES CTR */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_snow_cipher_aes_ctr_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_snow_cipher_aes_ctr_test_case_1),
+ /** AUTH SNOW3G + CIPHER ZUC */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_snow_cipher_zuc_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_snow_cipher_zuc_test_case_1),
+ /** AUTH AES CMAC + CIPHER ZUC */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_aes_cmac_cipher_zuc_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_aes_cmac_cipher_zuc_test_case_1),
+
+ /** AUTH NULL + CIPHER SNOW3G */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_null_cipher_snow_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_null_cipher_snow_test_case_1),
+ /** AUTH NULL + CIPHER ZUC */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_null_cipher_zuc_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_null_cipher_zuc_test_case_1),
+ /** AUTH SNOW3G + CIPHER NULL */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_snow_cipher_null_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_snow_cipher_null_test_case_1),
+ /** AUTH ZUC + CIPHER NULL */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_zuc_cipher_null_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_zuc_cipher_null_test_case_1),
+ /** AUTH NULL + CIPHER AES CTR */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_null_cipher_aes_ctr_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_null_cipher_aes_ctr_test_case_1),
+ /** AUTH AES CMAC + CIPHER NULL */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_auth_aes_cmac_cipher_null_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_verify_auth_aes_cmac_cipher_null_test_case_1),
+
+#ifdef RTE_LIBRTE_SECURITY
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_PDCP_PROTO_all),
+#endif
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_virtio_testsuite = {
+ .suite_name = "Crypto VIRTIO Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_caam_jr_testsuite = {
+ .suite_name = "Crypto CAAM JR Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_device_configure_invalid_dev_id),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_multi_session),
+
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_armv8_testsuite = {
+ .suite_name = "Crypto Device ARMv8 Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_mrvl_testsuite = {
+ .suite_name = "Crypto Device Marvell Component Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_multi_session),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_multi_session_random_usage),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_ccp_testsuite = {
+ .suite_name = "Crypto Device CCP Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_multi_session),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_multi_session_random_usage),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_octeontx_testsuite = {
+ .suite_name = "Crypto Device OCTEONTX Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+
+ /** AES GCM Authenticated Encryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_7),
+
+ /** AES GCM Authenticated Decryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_7),
+ /** AES GMAC Authentication */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_3),
+
+ /** SNOW 3G encrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop_sgl),
+
+ /** SNOW 3G decrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_3),
+
+ /** ZUC encrypt only (EEA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_6_sgl),
+
+ /** KASUMI encrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop_sgl),
+ /** KASUMI decrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1_oop),
+
+ /** KASUMI hash only (UIA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_5),
+
+ /** NULL tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_cipher_only_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_auth_only_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_cipher_auth_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_auth_cipher_operation),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_nitrox_testsuite = {
+ .suite_name = "Crypto NITROX Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_device_configure_invalid_dev_id),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_device_configure_invalid_queue_pair_ids),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_octeontx2_testsuite = {
+ .suite_name = "Crypto Device OCTEON TX2 Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_AES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_chain_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_3DES_cipheronly_all),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_authonly_all),
+
+ /** AES GCM Authenticated Encryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_encryption_test_case_7),
+
+ /** AES GCM Authenticated Decryption */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GCM_authenticated_decryption_test_case_7),
+ /** AES GMAC Authentication */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_AES_GMAC_authentication_verify_test_case_3),
+
+ /** SNOW 3G encrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_encryption_test_case_1_oop_sgl),
+
+ /** SNOW 3G decrypt only (UEA2) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_decryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_snow3g_hash_verify_test_case_3),
+
+ /** ZUC encrypt only (EEA3) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_zuc_encryption_test_case_6_sgl),
+
+ /** KASUMI encrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_sgl),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop_sgl),
+ /** KASUMI decrypt only (UEA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_5),
+
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_encryption_test_case_1_oop),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_decryption_test_case_1_oop),
+
+ /** KASUMI hash only (UIA1) */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_5),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_generate_test_case_6),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_1),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_2),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_3),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_4),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_kasumi_hash_verify_test_case_5),
+
+ /** NULL tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_cipher_only_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_auth_only_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_cipher_auth_operation),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_null_auth_cipher_operation),
+
+ /** Negative tests */
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ authentication_verify_AES128_GMAC_fail_tag_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_cryptodev_qat(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_QAT_SYM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "QAT PMD must be loaded. Check that both "
+ "CONFIG_RTE_LIBRTE_PMD_QAT and CONFIG_RTE_LIBRTE_PMD_QAT_SYM "
+ "are enabled in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_virtio(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_VIRTIO_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "VIRTIO PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_VIRTIO_CRYPTO is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_virtio_testsuite);
+}
+
+static int
+test_cryptodev_aesni_mb(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "AESNI MB PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_AESNI_MB is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_cpu_aesni_mb(void)
+{
+ int32_t rc;
+ enum rte_security_session_action_type at;
+
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "AESNI MB PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_AESNI_MB is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ at = gbl_action_type;
+ gbl_action_type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO;
+ rc = unit_test_suite_runner(&cryptodev_testsuite);
+ gbl_action_type = at;
+ return rc;
+}
+
+static int
+test_cryptodev_openssl(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OPENSSL PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OPENSSL is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_aesni_gcm(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "AESNI GCM PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_AESNI_GCM is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_cpu_aesni_gcm(void)
+{
+ int32_t rc;
+ enum rte_security_session_action_type at;
+
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_GCM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "AESNI GCM PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_AESNI_GCM is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ at = gbl_action_type;
+ gbl_action_type = RTE_SECURITY_ACTION_TYPE_CPU_CRYPTO;
+ rc = unit_test_suite_runner(&cryptodev_testsuite);
+ gbl_action_type = at;
+ return rc;
+}
+
+static int
+test_cryptodev_null(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "NULL PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_NULL is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_sw_snow3g(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SNOW3G_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "SNOW3G PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_SNOW3G is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_sw_kasumi(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_KASUMI_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "ZUC PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_KASUMI is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_sw_zuc(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ZUC_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "ZUC PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_ZUC is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_armv8(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "ARMV8 PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_ARMV8 is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_armv8_testsuite);
+}
+
+static int
+test_cryptodev_mrvl(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_MVSAM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "MVSAM PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_MVSAM_CRYPTO is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_mrvl_testsuite);
+}
+
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+
+static int
+test_cryptodev_scheduler(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_SCHEDULER_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "SCHEDULER PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_SCHEDULER is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ if (rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD)) == -1) {
+ RTE_LOG(ERR, USER1, "CONFIG_RTE_LIBRTE_PMD_AESNI_MB must be"
+ " enabled in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+}
+ return unit_test_suite_runner(&cryptodev_scheduler_testsuite);
+}
+
+REGISTER_TEST_COMMAND(cryptodev_scheduler_autotest, test_cryptodev_scheduler);
+
+#endif
+
+static int
+test_cryptodev_dpaa2_sec(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_DPAA2_SEC_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "DPAA2 SEC PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_DPAA2_SEC is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_dpaa_sec(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_DPAA_SEC_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "DPAA SEC PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_DPAA_SEC is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_SKIPPED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_testsuite);
+}
+
+static int
+test_cryptodev_ccp(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_CCP_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "CCP PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_CCP is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_ccp_testsuite);
+}
+
+static int
+test_cryptodev_octeontx(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OCTEONTX_SYM_PMD));
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OCTEONTX PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OCTEONTX_CRYPTO is "
+ "enabled in config file to run this "
+ "testsuite.\n");
+ return TEST_FAILED;
+ }
+ return unit_test_suite_runner(&cryptodev_octeontx_testsuite);
+}
+
+static int
+test_cryptodev_octeontx2(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OCTEONTX2_PMD));
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OCTEON TX2 PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_CRYPTO is "
+ "enabled in config file to run this "
+ "testsuite.\n");
+ return TEST_FAILED;
+ }
+ return unit_test_suite_runner(&cryptodev_octeontx2_testsuite);
+}
+
+static int
+test_cryptodev_caam_jr(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_CAAM_JR_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "CAAM_JR PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_CAAM_JR is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_caam_jr_testsuite);
+}
+
+static int
+test_cryptodev_nitrox(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NITROX_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "NITROX PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_NITROX is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_nitrox_testsuite);
+}
+
+REGISTER_TEST_COMMAND(cryptodev_qat_autotest, test_cryptodev_qat);
+REGISTER_TEST_COMMAND(cryptodev_aesni_mb_autotest, test_cryptodev_aesni_mb);
+REGISTER_TEST_COMMAND(cryptodev_cpu_aesni_mb_autotest,
+ test_cryptodev_cpu_aesni_mb);
+REGISTER_TEST_COMMAND(cryptodev_openssl_autotest, test_cryptodev_openssl);
+REGISTER_TEST_COMMAND(cryptodev_aesni_gcm_autotest, test_cryptodev_aesni_gcm);
+REGISTER_TEST_COMMAND(cryptodev_cpu_aesni_gcm_autotest,
+ test_cryptodev_cpu_aesni_gcm);
+REGISTER_TEST_COMMAND(cryptodev_null_autotest, test_cryptodev_null);
+REGISTER_TEST_COMMAND(cryptodev_sw_snow3g_autotest, test_cryptodev_sw_snow3g);
+REGISTER_TEST_COMMAND(cryptodev_sw_kasumi_autotest, test_cryptodev_sw_kasumi);
+REGISTER_TEST_COMMAND(cryptodev_sw_zuc_autotest, test_cryptodev_sw_zuc);
+REGISTER_TEST_COMMAND(cryptodev_sw_armv8_autotest, test_cryptodev_armv8);
+REGISTER_TEST_COMMAND(cryptodev_sw_mvsam_autotest, test_cryptodev_mrvl);
+REGISTER_TEST_COMMAND(cryptodev_dpaa2_sec_autotest, test_cryptodev_dpaa2_sec);
+REGISTER_TEST_COMMAND(cryptodev_dpaa_sec_autotest, test_cryptodev_dpaa_sec);
+REGISTER_TEST_COMMAND(cryptodev_ccp_autotest, test_cryptodev_ccp);
+REGISTER_TEST_COMMAND(cryptodev_virtio_autotest, test_cryptodev_virtio);
+REGISTER_TEST_COMMAND(cryptodev_octeontx_autotest, test_cryptodev_octeontx);
+REGISTER_TEST_COMMAND(cryptodev_octeontx2_autotest, test_cryptodev_octeontx2);
+REGISTER_TEST_COMMAND(cryptodev_caam_jr_autotest, test_cryptodev_caam_jr);
+REGISTER_TEST_COMMAND(cryptodev_nitrox_autotest, test_cryptodev_nitrox);
diff --git a/src/spdk/dpdk/app/test/test_cryptodev.h b/src/spdk/dpdk/app/test/test_cryptodev.h
new file mode 100644
index 000000000..41542e055
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev.h
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2017 Intel Corporation
+ */
+#ifndef TEST_CRYPTODEV_H_
+#define TEST_CRYPTODEV_H_
+
+#define HEX_DUMP 0
+
+#define FALSE 0
+#define TRUE 1
+
+#define MAX_NUM_OPS_INFLIGHT (4096)
+#define MIN_NUM_OPS_INFLIGHT (128)
+#define DEFAULT_NUM_OPS_INFLIGHT (128)
+
+#define MAX_NUM_QPS_PER_QAT_DEVICE (2)
+#define DEFAULT_NUM_QPS_PER_QAT_DEVICE (2)
+#define DEFAULT_BURST_SIZE (64)
+#define DEFAULT_NUM_XFORMS (2)
+#define NUM_MBUFS (8191)
+#define MBUF_CACHE_SIZE (256)
+#define MBUF_DATAPAYLOAD_SIZE (2048 + DIGEST_BYTE_LENGTH_SHA512)
+#define MBUF_SIZE (sizeof(struct rte_mbuf) + \
+ RTE_PKTMBUF_HEADROOM + MBUF_DATAPAYLOAD_SIZE)
+
+#define BYTE_LENGTH(x) (x/8)
+/* HASH DIGEST LENGTHS */
+#define DIGEST_BYTE_LENGTH_MD5 (BYTE_LENGTH(128))
+#define DIGEST_BYTE_LENGTH_SHA1 (BYTE_LENGTH(160))
+#define DIGEST_BYTE_LENGTH_SHA224 (BYTE_LENGTH(224))
+#define DIGEST_BYTE_LENGTH_SHA256 (BYTE_LENGTH(256))
+#define DIGEST_BYTE_LENGTH_SHA384 (BYTE_LENGTH(384))
+#define DIGEST_BYTE_LENGTH_SHA512 (BYTE_LENGTH(512))
+#define DIGEST_BYTE_LENGTH_AES_XCBC (BYTE_LENGTH(96))
+#define DIGEST_BYTE_LENGTH_SNOW3G_UIA2 (BYTE_LENGTH(32))
+#define DIGEST_BYTE_LENGTH_KASUMI_F9 (BYTE_LENGTH(32))
+#define AES_XCBC_MAC_KEY_SZ (16)
+#define DIGEST_BYTE_LENGTH_AES_GCM (BYTE_LENGTH(128))
+
+#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA1 (12)
+#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA224 (16)
+#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA256 (16)
+#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384 (24)
+#define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512 (32)
+
+#define MAXIMUM_IV_LENGTH (16)
+#define AES_GCM_J0_LENGTH (16)
+
+#define IV_OFFSET (sizeof(struct rte_crypto_op) + \
+ sizeof(struct rte_crypto_sym_op) + DEFAULT_NUM_XFORMS * \
+ sizeof(struct rte_crypto_sym_xform))
+
+#define CRYPTODEV_NAME_NULL_PMD crypto_null
+#define CRYPTODEV_NAME_AESNI_MB_PMD crypto_aesni_mb
+#define CRYPTODEV_NAME_AESNI_GCM_PMD crypto_aesni_gcm
+#define CRYPTODEV_NAME_OPENSSL_PMD crypto_openssl
+#define CRYPTODEV_NAME_QAT_SYM_PMD crypto_qat
+#define CRYPTODEV_NAME_QAT_ASYM_PMD crypto_qat_asym
+#define CRYPTODEV_NAME_SNOW3G_PMD crypto_snow3g
+#define CRYPTODEV_NAME_KASUMI_PMD crypto_kasumi
+#define CRYPTODEV_NAME_ZUC_PMD crypto_zuc
+#define CRYPTODEV_NAME_ARMV8_PMD crypto_armv8
+#define CRYPTODEV_NAME_DPAA_SEC_PMD crypto_dpaa_sec
+#define CRYPTODEV_NAME_DPAA2_SEC_PMD crypto_dpaa2_sec
+#define CRYPTODEV_NAME_SCHEDULER_PMD crypto_scheduler
+#define CRYPTODEV_NAME_MVSAM_PMD crypto_mvsam
+#define CRYPTODEV_NAME_CCP_PMD crypto_ccp
+#define CRYPTODEV_NAME_VIRTIO_PMD crypto_virtio
+#define CRYPTODEV_NAME_OCTEONTX_SYM_PMD crypto_octeontx
+#define CRYPTODEV_NAME_OCTEONTX2_PMD crypto_octeontx2
+#define CRYPTODEV_NAME_CAAM_JR_PMD crypto_caam_jr
+#define CRYPTODEV_NAME_NITROX_PMD crypto_nitrox_sym
+
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ * Destination mbuf
+ * @param offset
+ * Start offset in mbuf
+ * @param len
+ * Number of bytes to copy
+ * @param buffer
+ * Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t *buffer)
+{
+ int n = len;
+ int l;
+ struct rte_mbuf *m;
+ char *dst;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ l = m->data_len - offset;
+
+ /* copy data from first segment */
+ dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+ if (len <= l) {
+ rte_memcpy(dst, buffer, len);
+ return;
+ }
+
+ rte_memcpy(dst, buffer, l);
+ buffer += l;
+ n -= l;
+
+ for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+ dst = rte_pktmbuf_mtod(m, char *);
+ l = m->data_len;
+ if (n < l) {
+ rte_memcpy(dst, buffer, n);
+ return;
+ }
+ rte_memcpy(dst, buffer, l);
+ buffer += l;
+ n -= l;
+ }
+}
+
+static inline uint8_t *
+pktmbuf_mtod_offset(struct rte_mbuf *mbuf, int offset) {
+ struct rte_mbuf *m;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ if (m == NULL) {
+ printf("pktmbuf_mtod_offset: offset out of buffer\n");
+ return NULL;
+ }
+ return rte_pktmbuf_mtod_offset(m, uint8_t *, offset);
+}
+
+static inline rte_iova_t
+pktmbuf_iova_offset(struct rte_mbuf *mbuf, int offset) {
+ struct rte_mbuf *m;
+
+ for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+ offset -= m->data_len;
+
+ if (m == NULL) {
+ printf("pktmbuf_iova_offset: offset out of buffer\n");
+ return 0;
+ }
+ return rte_pktmbuf_iova_offset(m, offset);
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+ int nb_segs, uint8_t pattern) {
+
+ struct rte_mbuf *m = NULL, *mbuf = NULL;
+ uint8_t *dst;
+ int data_len = 0;
+ int i, size;
+ int t_len;
+
+ if (pkt_len < 1) {
+ printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+ return NULL;
+ }
+
+ if (nb_segs < 1) {
+ printf("Number of segments must be 1 or more (is %d)\n",
+ nb_segs);
+ return NULL;
+ }
+
+ t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+ size = pkt_len;
+
+ /* Create chained mbuf_src and fill it generated data */
+ for (i = 0; size > 0; i++) {
+
+ m = rte_pktmbuf_alloc(mbuf_pool);
+ if (i == 0)
+ mbuf = m;
+
+ if (m == NULL) {
+ printf("Cannot create segment for source mbuf");
+ goto fail;
+ }
+
+ /* Make sure if tailroom is zeroed */
+ memset(m->buf_addr, pattern, m->buf_len);
+
+ data_len = size > t_len ? t_len : size;
+ dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+ if (dst == NULL) {
+ printf("Cannot append %d bytes to the mbuf\n",
+ data_len);
+ goto fail;
+ }
+
+ if (mbuf != m)
+ rte_pktmbuf_chain(mbuf, m);
+
+ size -= data_len;
+
+ }
+ return mbuf;
+
+fail:
+ if (mbuf)
+ rte_pktmbuf_free(mbuf);
+ return NULL;
+}
+
+#endif /* TEST_CRYPTODEV_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_aead_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_aead_test_vectors.h
new file mode 100644
index 000000000..e62fdb254
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_aead_test_vectors.h
@@ -0,0 +1,3826 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_AEAD_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_AEAD_TEST_VECTORS_H_
+
+#define GMAC_LARGE_PLAINTEXT_LENGTH 65344
+#define MAX_AAD_LENGTH 65536
+#define GCM_LARGE_AAD_LENGTH 65296
+
+static uint8_t gcm_aad_zero_text[MAX_AAD_LENGTH] = { 0 };
+
+static uint8_t gcm_aad_text[MAX_AAD_LENGTH] = {
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
+ 0x00, 0xf1, 0xe2, 0xd3, 0xc4, 0xb5, 0xa6, 0x97,
+ 0x88, 0x79, 0x6a, 0x5b, 0x4c, 0x3d, 0x2e, 0x1f };
+
+static uint8_t ccm_aad_test_1[8] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+};
+
+static uint8_t ccm_aad_test_2[22] = {
+ 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C,
+ 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xAB, 0xAE,
+ 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00
+};
+
+struct aead_test_data {
+ enum rte_crypto_aead_algorithm algo;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned len;
+ } iv;
+
+ struct {
+ uint8_t *data;
+ unsigned len;
+ } aad;
+
+ struct {
+ uint8_t data[8096];
+ unsigned len;
+ } plaintext;
+
+ struct {
+ uint8_t data[8096];
+ unsigned len;
+ } ciphertext;
+
+ struct {
+ uint8_t data[16];
+ unsigned len;
+ } auth_tag;
+};
+
+struct gmac_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned len;
+ } iv;
+
+ struct {
+ uint8_t *data;
+ unsigned len;
+ } plaintext;
+
+ struct {
+ uint8_t data[16];
+ unsigned len;
+ } gmac_tag;
+
+};
+
+/** AES-GCM-128 Test Vectors */
+static const struct aead_test_data gcm_test_case_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0x00 },
+ .len = 0
+ },
+ .ciphertext = {
+ .data = {
+ 0x00
+ },
+ .len = 0
+ },
+ .auth_tag = {
+ .data = {
+ 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
+ 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 16
+ },
+ .ciphertext = {
+ .data = {
+ 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
+ 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 },
+ .len = 16
+ },
+ .auth_tag = {
+ .data = {
+ 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
+ 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_4 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xA2, 0xA4, 0x35, 0x75, 0xDC, 0xB0, 0x57, 0x74,
+ 0x07, 0x02, 0x30, 0xC2, 0xE7, 0x52, 0x02, 0x00
+ },
+ .len = 16
+ }
+
+};
+
+static const struct aead_test_data gcm_test_case_5 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xC5, 0x2D, 0xFB, 0x54, 0xAF, 0xBB, 0x07, 0xA1,
+ 0x9A, 0xFF, 0xBE, 0xE0, 0x61, 0x4C, 0xE7, 0xA5
+ },
+ .len = 16
+ }
+
+};
+
+static const struct aead_test_data gcm_test_case_6 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0x74, 0xFC, 0xFA, 0x29, 0x3E, 0x60, 0xCC, 0x66,
+ 0x09, 0xD6, 0xFD, 0x00, 0xC8, 0x86, 0xD5, 0x42
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_7 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xE9, 0xE4, 0xAB, 0x76, 0xB7, 0xFF, 0xEA, 0xDC,
+ 0x69, 0x79, 0x38, 0xA2, 0x0D, 0xCA, 0xF5, 0x92
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_8 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xC5, 0x34, 0x2E, 0x83, 0xEB, 0x4C, 0x02, 0x03,
+ 0xF7, 0xB2, 0x57, 0x35, 0x26, 0x81, 0x63, 0xAE,
+ 0x1F, 0xCD, 0x2D, 0x02, 0x91, 0x5A, 0xDB, 0x3A,
+ 0xF1, 0x38, 0xD8, 0x75, 0x86, 0x20, 0xCC, 0x1E,
+ 0xE6, 0xDC, 0xFF, 0xB5, 0xEA, 0x0E, 0x18, 0x7A,
+ 0x86, 0x6C, 0xAB, 0x39, 0x2D, 0x90, 0xAC, 0x77,
+ 0x5D, 0xED, 0x65, 0xB3, 0x05, 0x29, 0xBB, 0x09,
+ 0xD0, 0x21, 0x74, 0x6A, 0x67, 0x1C, 0x95, 0x42,
+ 0x55, 0xAD, 0xC8, 0x91, 0x28, 0xFE, 0x16, 0x9A,
+ 0xE1, 0xCB, 0xCD, 0x68, 0x3B, 0xDF, 0x3E, 0x3A,
+ 0x34, 0xFE, 0x9B, 0xFB, 0xF5, 0x15, 0x2A, 0x29,
+ 0x18, 0x99, 0x24, 0xBF, 0xB6, 0x43, 0xDB, 0xD1,
+ 0x69, 0x26, 0x1E, 0x31, 0x2C, 0x8C, 0x3C, 0x6B,
+ 0x7F, 0x06, 0xA6, 0x03, 0xE2, 0x1A, 0x50, 0xFE,
+ 0x7C, 0x69, 0xE5, 0x5F, 0x35, 0x93, 0xE9, 0x20,
+ 0x14, 0xB1, 0xCA, 0x61, 0xE7, 0x9C, 0x89, 0x08,
+ 0xD6, 0xB1, 0xC2, 0x63, 0x1B, 0x86, 0x5E, 0xF1,
+ 0xF5, 0x23, 0x0E, 0x9B, 0xE5, 0xBD, 0x5D, 0x04,
+ 0xF7, 0xEF, 0x8E, 0x46, 0xB0, 0x11, 0x4F, 0x69,
+ 0x62, 0x35, 0x51, 0xB7, 0x24, 0xA2, 0x31, 0xD0,
+ 0x32, 0x4E, 0xB8, 0x44, 0xC7, 0x59, 0xDE, 0x25,
+ 0xEA, 0x2D, 0x00, 0x0E, 0xF1, 0x07, 0xBA, 0xBB,
+ 0x9A, 0xBC, 0x4F, 0x57, 0xB7, 0x13, 0x57, 0xEF,
+ 0xD9, 0xF6, 0x80, 0x69, 0xEA, 0xE8, 0x47, 0x9C,
+ 0x51, 0x71, 0xE6, 0x8F, 0x69, 0x29, 0xB4, 0x60,
+ 0xE8, 0x50, 0xE5, 0xD0, 0x9B, 0xD2, 0x62, 0x6F,
+ 0x09, 0x5C, 0xD1, 0x4B, 0x85, 0xE2, 0xFD, 0xD3,
+ 0xEB, 0x28, 0x55, 0x77, 0x97, 0xCA, 0xD6, 0xA8,
+ 0xDC, 0x35, 0x68, 0xF7, 0x6A, 0xCF, 0x48, 0x3F,
+ 0x49, 0x31, 0x00, 0x65, 0xB7, 0x31, 0x1A, 0x49,
+ 0x75, 0xDE, 0xCE, 0x7F, 0x18, 0xB5, 0x31, 0x9A,
+ 0x64, 0x6D, 0xE5, 0x49, 0x1D, 0x6D, 0xF2, 0x21,
+ 0x9F, 0xF5, 0xFF, 0x7C, 0x41, 0x30, 0x33, 0x06,
+ 0x7B, 0xA4, 0xD8, 0x99, 0xF6, 0xCC, 0xDF, 0xC4,
+ 0x3F, 0xF3, 0xCD, 0xE7, 0x74, 0xC4, 0x4A, 0x19,
+ 0x5C, 0xCA, 0x42, 0x31, 0xF1, 0x3B, 0x65, 0x1C,
+ 0x3D, 0x56, 0x08, 0xBE, 0x15, 0x37, 0x23, 0x50,
+ 0xD6, 0xA3, 0x57, 0x64, 0x25, 0xBE, 0xDA, 0xC2,
+ 0x4E, 0xF5, 0x1A, 0xAD, 0x6F, 0x43, 0x78, 0x21,
+ 0xF9, 0x36, 0x39, 0x1F, 0x5F, 0xF7, 0x1B, 0xA0,
+ 0xEE, 0x8B, 0x4F, 0x8A, 0x9D, 0xD8, 0xED, 0x37,
+ 0xCE, 0x0D, 0x70, 0xE0, 0x3F, 0xE7, 0x11, 0x30,
+ 0x17, 0x1D, 0x03, 0x5E, 0xA0, 0x3D, 0x3F, 0x9E,
+ 0xF5, 0xD3, 0x74, 0x2E, 0xC1, 0xD6, 0xFF, 0xF7,
+ 0x2E, 0xE7, 0x80, 0x88, 0xCF, 0x0E, 0x7F, 0x12,
+ 0x71, 0x62, 0xC7, 0xF1, 0xC4, 0x2B, 0x64, 0x5D,
+ 0x1C, 0x9A, 0xB4, 0xCB, 0xB8, 0x24, 0xB3, 0x0B,
+ 0x33, 0xF2, 0x8A, 0x8F, 0x76, 0xC8, 0x81, 0xDA,
+ 0x1A, 0x10, 0xB5, 0xA9, 0xCD, 0xDC, 0x1A, 0x02,
+ 0xC1, 0xAE, 0x4F, 0x02, 0x1B, 0x13, 0x96, 0x5A,
+ 0x2E, 0x03, 0xA2, 0x68, 0xB2, 0x29, 0xAC, 0x28,
+ 0xB8, 0xDC, 0xD5, 0x27, 0x55, 0xEC, 0x43, 0xDC,
+ 0xB7, 0x49, 0x1D, 0xE1, 0x30, 0x25, 0x81, 0xA6,
+ 0x90, 0x1F, 0x75, 0xBA, 0x19, 0x1E, 0xF7, 0xC5,
+ 0x77, 0x35, 0xEE, 0x68, 0x71, 0x22, 0xA0, 0xB4,
+ 0xCC, 0x99, 0x86, 0x1B, 0x1B, 0xC8, 0x27, 0xFC,
+ 0x6D, 0x8D, 0xE7, 0x8B, 0xC3, 0x40, 0x3D, 0xA8,
+ 0xCB, 0x9B, 0xC4, 0x12, 0x07, 0xDD, 0xA1, 0x92,
+ 0xE5, 0x80, 0x7A, 0xF4, 0xDB, 0x4C, 0xE6, 0xEE,
+ 0xF9, 0xD5, 0x1C, 0x20, 0x18, 0xD3, 0x8F, 0xDF,
+ 0x1C, 0xD3, 0x51, 0x4E, 0x0E, 0xED, 0x06, 0x61,
+ 0xF7, 0xBA, 0x81, 0x3A, 0x2F, 0xEA, 0xED, 0x70,
+ 0xA9, 0xD9, 0x54, 0x4D, 0xFC, 0x1D, 0x19, 0xEA,
+ 0xA6, 0x39, 0x8C, 0x6C, 0x78, 0xA8, 0x05, 0xEB,
+ 0xF2, 0xB5, 0xDE, 0x06, 0x9D, 0x8A, 0x78, 0x2A,
+ 0xF5, 0x50, 0xA4, 0xBD, 0x9B, 0xDA, 0xCA, 0x66,
+ 0xC0, 0x23, 0xAB, 0xE8, 0x95, 0x7E, 0xC9, 0xD2,
+ 0x6F, 0x09, 0xF2, 0x9A, 0x17, 0x89, 0xDA, 0x47,
+ 0x65, 0x8C, 0x20, 0xFA, 0x4E, 0x86, 0x18, 0xEB,
+ 0x7C, 0x08, 0xEC, 0x8A, 0x05, 0x54, 0x96, 0xD2,
+ 0x7A, 0x8A, 0x81, 0x58, 0x75, 0x8C, 0x7B, 0x02,
+ 0xEE, 0x1F, 0x51, 0x88, 0xD0, 0xD1, 0x90, 0x99,
+ 0x0C, 0xAE, 0x51, 0x2E, 0x54, 0x3E, 0xB1, 0x7D,
+ 0xBC, 0xE8, 0x54, 0x93, 0x6D, 0x10, 0x3C, 0xC6,
+ 0x71, 0xF6, 0xF5, 0x0B, 0x07, 0x0A, 0x6E, 0x59,
+ 0x20, 0x45, 0x21, 0x7D, 0x37, 0x64, 0x92, 0x09,
+ 0xA7, 0xE2, 0x34, 0x6F, 0xFC, 0xCC, 0x66, 0x0E,
+ 0x88, 0x1B, 0x19, 0x86, 0x11, 0xD7, 0x81, 0x25,
+ 0xF1, 0x8A, 0x03, 0xB7, 0x7A, 0xF0, 0x98, 0x4A,
+ 0x5C, 0xA1, 0x6D, 0x85, 0xA4, 0x8C, 0x4B, 0x65,
+ 0x9F, 0x72, 0x64, 0x14, 0xBA, 0x74, 0xEE, 0xA3,
+ 0x88, 0xFE, 0x1B, 0xCF, 0x11, 0x4F, 0xD1, 0xAC,
+ 0xFA, 0x14, 0xC3, 0xA7, 0xDD, 0x06, 0x85, 0x4E,
+ 0x64, 0x06, 0x92, 0x9C, 0xDF, 0x06, 0x09, 0xF1,
+ 0x4D, 0xE8, 0xF8, 0x2F, 0x69, 0xB6, 0x8A, 0xAF,
+ 0x25, 0x21, 0xB5, 0x48, 0x59, 0xF8, 0x9D, 0x60,
+ 0xAE, 0x42, 0x11, 0x7A, 0x68, 0x4D, 0x7E, 0x76,
+ 0xB0, 0xD2, 0xE3, 0xD9, 0x24, 0x16, 0x20, 0x0A,
+ 0xEB, 0xE0, 0x68, 0xCB, 0xBC, 0xAB, 0x67, 0xE4,
+ 0xF3, 0x25, 0x1F, 0xD3, 0x85, 0xA7, 0x1D, 0x7E,
+ 0x3C, 0x63, 0xCB, 0xC2, 0x50, 0x90, 0x0F, 0x4B,
+ 0x6E, 0x68, 0x06, 0x84, 0x65, 0xF7, 0xD0, 0xD4,
+ 0x12, 0xED, 0xFA, 0xC9, 0x40, 0xE2, 0xC0, 0xC9,
+ 0x46, 0x22, 0x47, 0x5E, 0x6D, 0xC1, 0x63, 0xDB,
+ 0x51, 0x98, 0xDA, 0x1A, 0xC4, 0xB9, 0xED, 0xE9,
+ 0x09, 0xB9, 0xCF, 0x91, 0x04, 0x1C, 0x63, 0xD8,
+ 0xC5, 0xA5, 0xAE, 0x53, 0x7B, 0xA1, 0x29, 0x83,
+ 0x37, 0xFB, 0xBF, 0x96, 0xBB, 0x24, 0x3D, 0x77,
+ 0x8C, 0x0F, 0xB3, 0x4B, 0x66, 0x9C, 0x54, 0xBB,
+ 0xF6, 0xDD, 0xD1, 0xB4, 0xD2, 0xF6, 0xAA, 0xED,
+ 0x18, 0x56, 0x63, 0x3E, 0x0B, 0xCA, 0xAB, 0x70,
+ 0xBB, 0x63, 0xEA, 0xB1, 0x00, 0x65, 0x90, 0x18,
+ 0xB8, 0x63, 0xA2, 0xF2, 0xB6, 0x1E, 0x61, 0x7B,
+ 0xD5, 0x01, 0xD9, 0x4D, 0xC9, 0x9D, 0x99, 0xC1,
+ 0x57, 0x9D, 0x6F, 0xAE, 0x64, 0xE4, 0x0C, 0x7E,
+ 0xFA, 0x15, 0x5E, 0xB6, 0x43, 0xB8, 0x8B, 0x89,
+ 0x87, 0xCD, 0x4F, 0xAD, 0x30, 0x1E, 0xA5, 0x03,
+ 0x7A, 0xC2, 0x10, 0x42, 0x14, 0x88, 0xD6, 0x7A,
+ 0x6D, 0x56, 0x52, 0x2E, 0x8D, 0x1B, 0x5D, 0x36,
+ 0x27, 0xA0, 0x21, 0x4B, 0x64, 0xF0, 0xC5, 0x41,
+ 0xAD, 0x05, 0x4A, 0x24, 0xE4, 0x70, 0x88, 0x63,
+ 0x12, 0xD0, 0xBC, 0x05, 0x38, 0xD9, 0x41, 0x68,
+ 0x9F, 0x16, 0x9A, 0x54, 0x09, 0x21, 0x64, 0x36,
+ 0x63, 0x97, 0x3A, 0xB5, 0xE0, 0x25, 0x43, 0x8A,
+ 0x6A, 0x59, 0x97, 0xC1, 0x31, 0xA5, 0x66, 0xD2,
+ 0xF0, 0x1C, 0xDF, 0x97, 0x51, 0xD0, 0x61, 0xBA,
+ 0x55, 0x5F, 0xD7, 0x0D, 0xD4, 0x75, 0x8E, 0x79,
+ 0x04, 0x75, 0x00, 0xB9, 0xC0, 0x7A, 0x66, 0x05,
+ 0x9F, 0x2B, 0x44, 0x42, 0x75, 0x0F, 0xD5, 0x15,
+ 0xD6, 0x16, 0x8F, 0x6C, 0x6E, 0xD4, 0x37, 0xCF,
+ 0xB4, 0xDA, 0x93, 0x00, 0x11, 0xFB, 0xBE, 0xEE,
+ 0x3B, 0x6D, 0x1D, 0xBA, 0x33, 0xD1, 0x52, 0x8B,
+ 0x16, 0x39, 0x42, 0x27, 0xE6, 0x56, 0x4C, 0x41,
+ 0x91, 0xB0, 0x98, 0xAE, 0x9B, 0x2D, 0x9B, 0x23,
+ 0x80, 0x4C, 0xEA, 0x98, 0x57, 0x95, 0x28, 0x94,
+ 0x43, 0xD3, 0x88, 0x12, 0xDF, 0x89, 0x5A, 0x7B,
+ 0xC5, 0xCB, 0x36, 0x54, 0x65, 0x74, 0xB8, 0x4E,
+ 0xE2, 0x4D, 0x01, 0xD5, 0x9C, 0x82, 0xB9, 0x1A,
+ 0x09, 0xD2, 0xCE, 0x04, 0x36, 0xD8, 0x41, 0xAC,
+ 0x4C, 0xAD, 0xC6, 0x52, 0x91, 0x1A, 0x06, 0x6D,
+ 0xFC, 0xAB, 0x29, 0x93, 0x87, 0x88, 0xB9, 0x8C,
+ 0xFA, 0x57, 0x2B, 0x05, 0x03, 0xD0, 0x18, 0xED,
+ 0x7A, 0x7B, 0x81, 0x6A, 0x97, 0x65, 0x5B, 0x90,
+ 0xDE, 0xA9, 0xFC, 0x8F, 0xFC, 0xBB, 0x98, 0xD8,
+ 0xFA, 0x32, 0x3F, 0x3F, 0x7F, 0x74, 0x65, 0x38,
+ 0xC4, 0x28, 0xEC, 0x27, 0x1F, 0x28, 0x01, 0xB1,
+ 0xAF, 0x2B, 0x8A, 0x05, 0x38, 0x7B, 0x77, 0xC9,
+ 0x61, 0x77, 0x34, 0x2C, 0x22, 0xE5, 0xEB, 0xDC,
+ 0x9D, 0x18, 0x6E, 0x23, 0x25, 0x52, 0x69, 0xB7,
+ 0x05, 0xDB, 0x66, 0x5D, 0xEA, 0x76, 0x83, 0x82,
+ 0x97, 0x39, 0xAF, 0xC0, 0x50, 0x81, 0x18, 0x0D,
+ 0x22, 0xFA, 0xB7, 0x44, 0x5C, 0x3F, 0x69, 0xF3,
+ 0xAC, 0xC5, 0x63, 0x9F, 0xD8, 0x72, 0x7E, 0x9A,
+ 0xC2, 0xEB, 0x79, 0xD0, 0x74, 0x65, 0xE8, 0xCA,
+ 0xFD, 0xA8, 0x7D, 0x23, 0x07, 0x99, 0x3E, 0xAF,
+ 0xDB, 0x67, 0x10, 0xC0, 0xE5, 0x61, 0x77, 0xC6,
+ 0x8D, 0xC4, 0x0E, 0xAA, 0x55, 0xE3, 0xC0, 0xC7,
+ 0xA5, 0x36, 0x28, 0x61, 0xDB, 0x16, 0x96, 0x5E,
+ 0x01, 0x47, 0x82, 0xE3, 0xEB, 0x20, 0x3F, 0x10,
+ 0xFA, 0x5A, 0xBC, 0xD3, 0xF9, 0xCE, 0x04, 0x87,
+ 0x51, 0x07, 0xF9, 0xD0, 0xE7, 0x6D, 0xCB, 0xCC,
+ 0xC4, 0x15, 0x00, 0xE2, 0xDC, 0x8E, 0x7B, 0x5C,
+ 0x9A, 0xF2, 0x78, 0x70, 0x4D, 0xA1, 0xAA, 0xB5,
+ 0x13, 0xCC, 0x71, 0x66, 0x5A, 0x79, 0x13, 0x3B,
+ 0x12, 0xCD, 0x40, 0x30, 0x5A, 0x49, 0xD4, 0x20,
+ 0xED, 0xCF, 0x4A, 0x75, 0xE6, 0xD5, 0xDD, 0x0F,
+ 0xD4, 0xBE, 0x98, 0x9F, 0xD7, 0x1F, 0xC0, 0x02,
+ 0x31, 0xFA, 0x67, 0x37, 0x25, 0x86, 0x56, 0x85,
+ 0x2B, 0xA2, 0x57, 0xCD, 0x8E, 0x74, 0xE7, 0x69,
+ 0xEE, 0x33, 0x5A, 0x3F, 0xCD, 0x1E, 0xE3, 0xB9,
+ 0xAA, 0x52, 0xF5, 0x22, 0x4E, 0xE3, 0xFF, 0xC8,
+ 0xE3, 0x13, 0xA3, 0x9A, 0x63, 0x23, 0xC3, 0xD7,
+ 0xE5, 0x88, 0x3E, 0x0A, 0x4B, 0xA5, 0x01, 0xE6,
+ 0x13, 0xCF, 0xED, 0xEE, 0x2A, 0x58, 0x09, 0x3F,
+ 0x2F, 0x28, 0xE7, 0xC4, 0x6B, 0xEC, 0x49, 0x51,
+ 0x79, 0x8F, 0xD5, 0x19, 0x5D, 0xA5, 0x10, 0xCE,
+ 0x8E, 0xF6, 0x26, 0x78, 0x7A, 0xA8, 0x11, 0x52,
+ 0x5F, 0x97, 0x14, 0xC9, 0x29, 0x87, 0xB8, 0xA0,
+ 0x2D, 0xE6, 0xA7, 0x2A, 0xD4, 0xFF, 0xEB, 0xBA,
+ 0xFD, 0x58, 0x39, 0x33, 0xB1, 0xCE, 0x0E, 0x78,
+ 0x67, 0x1E, 0xA1, 0x92, 0x77, 0x63, 0xF8, 0xC0,
+ 0x02, 0x49, 0x73, 0xC0, 0xA1, 0x26, 0x83, 0x04,
+ 0x9A, 0x5D, 0x85, 0x68, 0x2A, 0x2F, 0xCB, 0x88,
+ 0x8D, 0x14, 0xB1, 0x33, 0xFA, 0xFB, 0xE9, 0x05,
+ 0xBE, 0x24, 0x1A, 0x6B, 0x29, 0x2B, 0x3F, 0x52,
+ 0x8F, 0xFB, 0xE6, 0x02, 0x77, 0x50, 0x71, 0xDB,
+ 0xE9, 0x92, 0x3F, 0xE1, 0x20, 0x62, 0x80, 0xAE,
+ 0xA4, 0x98, 0xC6, 0xCD, 0xE0, 0xB1, 0xC3, 0x33,
+ 0xB1, 0xC5, 0x91, 0x3C, 0x19, 0x34, 0xA8, 0xD9,
+ 0xB3, 0x25, 0x69, 0xE3, 0x9C, 0x5F, 0x78, 0xD0,
+ 0x83, 0x1F, 0xAB, 0x85, 0x13, 0x56, 0x69, 0xB5,
+ 0x06, 0x47, 0x62, 0x37, 0x27, 0x15, 0x14, 0x05,
+ 0x4A, 0xF4, 0x6A, 0x68, 0x2A, 0x6A, 0xC3, 0x5A,
+ 0xDF, 0xB5, 0xAE, 0x2F, 0x8D, 0x8F, 0x21, 0xDB,
+ 0x33, 0x00, 0x9B, 0xD4, 0xC4, 0x08, 0x3B, 0x81,
+ 0x63, 0x4C, 0xB0, 0x39, 0x4C, 0x0A, 0xD5, 0x71,
+ 0x3E, 0x5A, 0x50, 0x58, 0x9C, 0x07, 0x89, 0x79,
+ 0x79, 0x2F, 0x0B, 0xD9, 0x50, 0xBC, 0xCF, 0x46,
+ 0x7A, 0x68, 0x5C, 0xBF, 0x1E, 0x49, 0x77, 0x92,
+ 0x85, 0x11, 0x39, 0xA6, 0x2F, 0xDA, 0x7B, 0xFA,
+ 0x72, 0x87, 0x06, 0xCD, 0x84, 0x41, 0x20, 0x1B,
+ 0x66, 0x3F, 0x42, 0x0C, 0x9E, 0x19, 0xD3, 0x18,
+ 0x57, 0xA0, 0xEE, 0x16, 0x3A, 0xC7, 0xF9, 0xD3,
+ 0x8B, 0xC9, 0x24, 0x70, 0x70, 0x51, 0x7C, 0x06,
+ 0x68, 0xD3, 0x29, 0xC9, 0x85, 0x9A, 0x1C, 0xE6,
+ 0x8C, 0x17, 0xF4, 0x88, 0xDF, 0xEA, 0xFF, 0x44,
+ 0x8D, 0x54, 0xBE, 0x22, 0x07, 0xA5, 0x7C, 0x0C,
+ 0xF4, 0x8D, 0xB1, 0x0C, 0x07, 0xED, 0xBD, 0x28,
+ 0x19, 0xDA, 0x07, 0x71, 0xA8, 0xA1, 0xE0, 0xDD,
+ 0xEE, 0x08, 0x18, 0xA5, 0xBD, 0xDD, 0x32, 0x0B,
+ 0x70, 0x1C, 0xD9, 0xEE, 0x19, 0xC2, 0xAE, 0x5C,
+ 0xE3, 0x02, 0x74, 0x70, 0x96, 0x61, 0xB1, 0x73,
+ 0x3B, 0xD6, 0x74, 0xC0, 0x82, 0xA9, 0x1F, 0xE0,
+ 0xF1, 0x22, 0x50, 0xF3, 0x9F, 0xE5, 0x13, 0x92,
+ 0xFC, 0x0A, 0x1A, 0x3C, 0xB4, 0x46, 0xFB, 0x81,
+ 0x00, 0x84, 0xA4, 0x5E, 0x6B, 0x8C, 0x25, 0x6E,
+ 0xD7, 0xB7, 0x3B, 0x01, 0x65, 0xFB, 0x0B, 0x46,
+ 0x67, 0x27, 0x2D, 0x51, 0xAD, 0xB5, 0xE0, 0x85,
+ 0xC2, 0x95, 0xA3, 0xE3, 0x68, 0x4D, 0x9E, 0x8C,
+ 0x11, 0x53, 0xF0, 0xB2, 0x85, 0xFA, 0x52, 0x4E,
+ 0xEC, 0xF9, 0xB7, 0x3C, 0x89, 0x2C, 0x4D, 0x32,
+ 0x9A, 0xCB, 0x17, 0xF3, 0x16, 0xBF, 0x44, 0x40,
+ 0xE9, 0x5E, 0x51, 0x8C, 0x1E, 0x52, 0x0A, 0xC2,
+ 0xCD, 0xA5, 0xAA, 0x03, 0x27, 0xB0, 0x8F, 0x64,
+ 0xDB, 0xD7, 0x03, 0x01, 0x8A, 0x24, 0x28, 0x7E,
+ 0x53, 0x6F, 0x24, 0xFD, 0xAA, 0xE3, 0x78, 0xB6,
+ 0xA5, 0x5D, 0x5A, 0x67, 0x20, 0xE2, 0xBE, 0x3A,
+ 0x2B, 0xE7, 0x86, 0x11, 0xDD, 0x96, 0xCB, 0x09,
+ 0x65, 0xA0, 0x36, 0xF9, 0xB0, 0x20, 0x21, 0x8E,
+ 0xDB, 0xC0, 0x73, 0xC7, 0x79, 0xD8, 0xDA, 0xC2,
+ 0x66, 0x13, 0x64, 0x34, 0x0C, 0xE1, 0x22, 0x24,
+ 0x61, 0x67, 0x08, 0x39, 0x97, 0x3F, 0x33, 0x96,
+ 0xF2, 0x44, 0x18, 0x75, 0xBB, 0xF5, 0x6A, 0x5C,
+ 0x2C, 0xAE, 0x2A, 0x79, 0x3D, 0x47, 0x19, 0x53,
+ 0x50, 0x6C, 0x9F, 0xB3, 0x82, 0x55, 0x09, 0x78,
+ 0x7B, 0xAD, 0xBC, 0x05, 0x6F, 0xC8, 0x3D, 0xB6,
+ 0x7B, 0x30, 0xE6, 0xBB, 0x8B, 0xD0, 0x2F, 0xA6,
+ 0x15, 0xCC, 0x77, 0x8C, 0x21, 0xBA, 0x03, 0xED,
+ 0x56, 0x85, 0x82, 0x4F, 0x97, 0x8C, 0x59, 0x4F,
+ 0x53, 0x5A, 0xD2, 0x70, 0xD9, 0x07, 0xB3, 0xBD,
+ 0x1D, 0x3E, 0x97, 0xD4, 0x7D, 0x93, 0x35, 0xA4,
+ 0x82, 0x6E, 0xEA, 0x4B, 0xC8, 0x6C, 0xF5, 0xE6,
+ 0xEB, 0xAF, 0x11, 0xB0, 0xB4, 0x71, 0x8F, 0x7B,
+ 0xC4, 0x8C, 0xE2, 0x66, 0x51, 0x31, 0x99, 0x01,
+ 0x5B, 0xE7, 0x48, 0xF8, 0x4C, 0xE3, 0x9A, 0x77,
+ 0xF1, 0xC6, 0x09, 0xDE, 0x76, 0xD4, 0xE3, 0x5C,
+ 0xDF, 0xA3, 0xEC, 0x3C, 0x86, 0x7C, 0xA5, 0x3F,
+ 0x8D, 0x2A, 0xF3, 0x0B, 0x54, 0xB7, 0x54, 0xA2,
+ 0xC1, 0x69, 0xC0, 0x6F, 0x1C, 0x1C, 0x76, 0xD8,
+ 0x9F, 0x7A, 0x32, 0xB0, 0xA1, 0xA6, 0x9B, 0xB7,
+ 0x21, 0x56, 0x28, 0x2D, 0xB6, 0x97, 0x03, 0x5E,
+ 0x65, 0xE3, 0x74, 0x9A, 0x96, 0x7A, 0xF9, 0xF5,
+ 0xDD, 0x85, 0xCA, 0x4C, 0xB4, 0x03, 0x6A, 0xCD,
+ 0xB6, 0x01, 0xDC, 0x8B, 0xD8, 0x73, 0x8F, 0x4D,
+ 0x7F, 0xD6, 0x71, 0xEC, 0xD7, 0xC6, 0x0B, 0x5F,
+ 0x09, 0x21, 0xB2, 0x78, 0xA8, 0xAF, 0xAD, 0x2C,
+ 0xD4, 0x93, 0x9F, 0x71, 0xF7, 0x05, 0x89, 0x42,
+ 0xC9, 0x15, 0x6F, 0x2D, 0xE0, 0xBA, 0xC3, 0xD6,
+ 0xBF, 0xAC, 0xF8, 0x24, 0x58, 0x79, 0xA9, 0xC4,
+ 0xB4, 0x49, 0x3E, 0x0B, 0x9E, 0x5E, 0xE4, 0xA6,
+ 0x8B, 0xE8, 0xDE, 0xFB, 0x4A, 0xF1, 0x69, 0x9D,
+ 0x4F, 0x77, 0x83, 0x78, 0x55, 0x19, 0x42, 0x45,
+ 0xBF, 0xBD, 0xBD, 0x12, 0x0F, 0xEF, 0x8D, 0x04,
+ 0xD8, 0x5C, 0xF2, 0xC9, 0xF1, 0xA6, 0xE0, 0x3E,
+ 0x22, 0xA8, 0xA2, 0x5E, 0x66, 0xE9, 0xAB, 0xB4,
+ 0x71, 0xBE, 0x4B, 0x3F, 0xBE, 0xC4, 0xBA, 0x4A
+ },
+ .len = 2048
+ },
+ .ciphertext = {
+ .data = {
+ 0x5E, 0x86, 0x02, 0x64, 0x32, 0xBF, 0x70, 0xC2,
+ 0x19, 0x99, 0x7F, 0x47, 0x0D, 0xA4, 0x91, 0xA8,
+ 0x7A, 0xC0, 0xA5, 0x7E, 0xA8, 0x6C, 0x88, 0x00,
+ 0xEA, 0xB5, 0x96, 0x6B, 0x25, 0xBD, 0xE7, 0x42,
+ 0xDB, 0x35, 0xE7, 0x92, 0x2B, 0x00, 0x82, 0x35,
+ 0xD4, 0x2C, 0xCF, 0x47, 0xC8, 0xB2, 0xB3, 0x57,
+ 0xF7, 0x24, 0x83, 0x7F, 0xC5, 0x2E, 0xF1, 0xC9,
+ 0x57, 0x1A, 0xEF, 0xC2, 0x3A, 0x8C, 0x1E, 0x92,
+ 0x88, 0x05, 0xAF, 0x55, 0xE6, 0x0C, 0xA7, 0x6B,
+ 0x59, 0x62, 0x32, 0x21, 0xF1, 0xFF, 0xB5, 0x5B,
+ 0x22, 0x26, 0x6F, 0x0A, 0x36, 0xDC, 0x0D, 0x16,
+ 0x3B, 0x4E, 0x7C, 0xA3, 0x75, 0x30, 0x3F, 0xB0,
+ 0x99, 0x38, 0x42, 0x8E, 0x89, 0xA3, 0x7C, 0x99,
+ 0x2F, 0x0A, 0xA1, 0xC7, 0xFD, 0x2D, 0x21, 0x8F,
+ 0xBD, 0xD4, 0x11, 0xEA, 0x55, 0xF5, 0x6A, 0x50,
+ 0x90, 0x3B, 0x60, 0x57, 0xE1, 0x86, 0x1E, 0x50,
+ 0x28, 0x67, 0x3F, 0xD2, 0xF3, 0xBD, 0xFA, 0xEE,
+ 0xD6, 0x5A, 0x38, 0x30, 0xA3, 0xDD, 0x78, 0xC4,
+ 0x37, 0x59, 0x52, 0xC0, 0x92, 0x54, 0xC7, 0x53,
+ 0xF0, 0xE6, 0xA9, 0x63, 0x1F, 0x9B, 0x97, 0xFB,
+ 0x40, 0x23, 0xFE, 0x52, 0x6A, 0xF0, 0x3A, 0x94,
+ 0xEB, 0x6A, 0x9E, 0x8F, 0xC5, 0x05, 0x9C, 0x04,
+ 0x1B, 0x00, 0x34, 0x96, 0x12, 0xDA, 0x60, 0xC6,
+ 0xAA, 0x1A, 0x3E, 0xEB, 0x70, 0x17, 0x10, 0xBC,
+ 0xF5, 0xC2, 0xE2, 0x71, 0xF3, 0xB8, 0x1D, 0xCE,
+ 0x47, 0x94, 0x21, 0x71, 0x34, 0x8C, 0xCC, 0xDD,
+ 0x27, 0xCE, 0x6F, 0x68, 0xFF, 0x91, 0x4E, 0xC4,
+ 0xA0, 0xCA, 0xB0, 0x4F, 0x17, 0x53, 0x73, 0x92,
+ 0x6C, 0xA8, 0x16, 0x06, 0xE3, 0xD9, 0x92, 0x99,
+ 0xBE, 0xB0, 0x7D, 0x56, 0xF2, 0x72, 0x30, 0xDA,
+ 0xC4, 0x4E, 0xF4, 0xA6, 0x8F, 0xD2, 0xC7, 0x8A,
+ 0xA2, 0xFC, 0xF5, 0x63, 0x17, 0x48, 0x56, 0x4D,
+ 0xBE, 0x94, 0xFE, 0xF5, 0xB1, 0xA9, 0x96, 0xAB,
+ 0x3F, 0x2D, 0xD4, 0x15, 0xEE, 0x4F, 0xFA, 0x2C,
+ 0xBE, 0x91, 0xB7, 0xBC, 0x18, 0xC8, 0xDB, 0x02,
+ 0x20, 0x29, 0xF1, 0xC1, 0x88, 0x8C, 0x8D, 0xD1,
+ 0xB3, 0x4E, 0x93, 0x96, 0xDD, 0x22, 0xAB, 0x55,
+ 0xB5, 0x9F, 0x8B, 0x20, 0xAE, 0xC6, 0x0E, 0x26,
+ 0xC6, 0xFE, 0x2D, 0x5F, 0x95, 0x89, 0x06, 0x15,
+ 0x3D, 0x88, 0x16, 0xEC, 0x9B, 0x4A, 0x1B, 0x5D,
+ 0x2E, 0xB2, 0x13, 0x56, 0x9F, 0x33, 0xB3, 0x45,
+ 0xBF, 0x5F, 0x25, 0x7E, 0x75, 0x22, 0xD2, 0xE6,
+ 0x9F, 0xAC, 0x2D, 0xFD, 0x99, 0xC2, 0x9B, 0xFC,
+ 0xD7, 0x7A, 0x9B, 0x05, 0x30, 0x0F, 0xB7, 0x4A,
+ 0xFE, 0x24, 0xDD, 0x39, 0x9B, 0xBB, 0x2F, 0xDD,
+ 0xF9, 0xFB, 0xCA, 0x6C, 0x87, 0xBA, 0x73, 0xD4,
+ 0x85, 0x7B, 0xB2, 0x6F, 0x5C, 0xD8, 0xFB, 0xE9,
+ 0x41, 0x24, 0x3A, 0x3B, 0x4F, 0x91, 0x77, 0xA2,
+ 0x35, 0x78, 0xE5, 0x4C, 0xFE, 0x8B, 0x04, 0x03,
+ 0xD3, 0x84, 0xA9, 0x1C, 0xA7, 0x7C, 0x45, 0x13,
+ 0x7D, 0xC5, 0x0A, 0x2F, 0x02, 0xF8, 0x56, 0xD5,
+ 0x5F, 0x35, 0xED, 0x06, 0xBF, 0x67, 0xBA, 0x51,
+ 0x02, 0x95, 0x36, 0xF2, 0x9A, 0xBA, 0x9D, 0xF6,
+ 0xD6, 0x77, 0x50, 0xC9, 0xFC, 0x1E, 0x32, 0xB5,
+ 0x2F, 0xEA, 0x3C, 0x76, 0xB4, 0xE1, 0xCC, 0x42,
+ 0xEB, 0x71, 0x79, 0xD3, 0x7D, 0xB7, 0xC0, 0x88,
+ 0x25, 0x81, 0xE8, 0xC0, 0xB8, 0x38, 0x7E, 0x7B,
+ 0xFD, 0x18, 0xAB, 0x08, 0xB2, 0x71, 0xA5, 0xAD,
+ 0xA7, 0xBE, 0x48, 0x5F, 0x86, 0xE2, 0x41, 0x3D,
+ 0x7C, 0x37, 0x7A, 0xAB, 0xDB, 0xE0, 0x3B, 0x3D,
+ 0xB6, 0xE8, 0x23, 0x7C, 0xF1, 0x8F, 0xBA, 0xB7,
+ 0xE9, 0x78, 0x0B, 0xCA, 0x67, 0xA8, 0x10, 0x36,
+ 0xEB, 0x72, 0xED, 0xDD, 0xF0, 0x5C, 0x74, 0x8E,
+ 0xE5, 0x2A, 0xAE, 0x6E, 0xC4, 0xF1, 0xFC, 0xD8,
+ 0xEE, 0x56, 0x07, 0x88, 0x02, 0xDC, 0x9D, 0xB7,
+ 0xF9, 0x13, 0xE1, 0xE1, 0x9D, 0x89, 0x26, 0x0B,
+ 0x23, 0x74, 0x4A, 0x43, 0xAA, 0xA0, 0xA8, 0x97,
+ 0x85, 0x15, 0x58, 0xAB, 0x2B, 0xB5, 0xDA, 0x1A,
+ 0xBA, 0x29, 0x62, 0xCF, 0xDD, 0xA3, 0xBA, 0x9D,
+ 0x7D, 0x83, 0xA5, 0x18, 0xD4, 0x03, 0x0F, 0x61,
+ 0x9F, 0xB1, 0x7E, 0xEC, 0xD2, 0x6E, 0xAF, 0xCF,
+ 0x1E, 0xC1, 0x88, 0x97, 0x99, 0xD6, 0xBF, 0x47,
+ 0xB9, 0x0A, 0x69, 0x11, 0x3A, 0x55, 0x8B, 0x1D,
+ 0x2D, 0xFF, 0x78, 0xC8, 0xDE, 0x82, 0x29, 0xD6,
+ 0x08, 0x3C, 0xC4, 0xCB, 0x2F, 0x01, 0xD0, 0xE8,
+ 0xB1, 0x75, 0x5E, 0x23, 0xE0, 0x37, 0x7C, 0x1C,
+ 0xB6, 0xD9, 0x47, 0xDE, 0x23, 0x87, 0xD3, 0x68,
+ 0x47, 0x46, 0x78, 0xF3, 0xBF, 0x54, 0xA3, 0xB9,
+ 0x54, 0xD5, 0xC5, 0x0A, 0x7C, 0x92, 0x2A, 0xC2,
+ 0x14, 0x76, 0xA6, 0x5C, 0x6D, 0x0B, 0x94, 0x56,
+ 0x00, 0x6B, 0x5C, 0x27, 0xDE, 0x77, 0x9B, 0xF1,
+ 0xB1, 0x8C, 0xA7, 0x49, 0x77, 0xFC, 0x4E, 0x29,
+ 0x23, 0x8F, 0x2F, 0xF7, 0x83, 0x8D, 0x36, 0xD9,
+ 0xAB, 0x0E, 0x78, 0xF5, 0x90, 0x05, 0xB9, 0x79,
+ 0x70, 0x88, 0x59, 0x6F, 0xE2, 0xC5, 0xD7, 0x80,
+ 0x95, 0x04, 0x29, 0xE0, 0xFA, 0x37, 0xE8, 0x8B,
+ 0xC5, 0x21, 0x51, 0x1A, 0x62, 0xCE, 0x93, 0xAF,
+ 0x1A, 0xFE, 0xC3, 0x6F, 0x86, 0x94, 0x5E, 0x13,
+ 0xA6, 0x9A, 0x26, 0xF0, 0xB5, 0x7C, 0x41, 0x9A,
+ 0x80, 0xB8, 0x84, 0x5A, 0x55, 0xA9, 0xB0, 0x6A,
+ 0xFA, 0xEB, 0x46, 0x32, 0x0B, 0xE2, 0x9C, 0x65,
+ 0x86, 0x11, 0x39, 0x7E, 0xAF, 0x93, 0x19, 0x09,
+ 0x70, 0x40, 0x80, 0x14, 0xBA, 0x1D, 0xB3, 0x62,
+ 0x5B, 0xF3, 0x9A, 0x21, 0x98, 0x7E, 0x63, 0xB6,
+ 0x1A, 0xBD, 0x65, 0x98, 0x35, 0x2A, 0xA9, 0x76,
+ 0x29, 0x59, 0x84, 0x25, 0x81, 0xB8, 0xDE, 0x25,
+ 0x32, 0x10, 0x50, 0xB7, 0xD3, 0xB3, 0x69, 0xC8,
+ 0xE1, 0x33, 0xCB, 0x9E, 0x9C, 0x7A, 0x7C, 0xD2,
+ 0x6C, 0x92, 0x97, 0xA9, 0xFA, 0xAF, 0x30, 0xBA,
+ 0x9A, 0xB3, 0x3D, 0x9A, 0xE5, 0x0A, 0x9B, 0x8D,
+ 0x89, 0xE2, 0x2B, 0xB8, 0xBC, 0xF0, 0x23, 0xFF,
+ 0x7B, 0x0D, 0x00, 0x36, 0xEE, 0x79, 0xCB, 0xA5,
+ 0x70, 0x4C, 0x66, 0x02, 0x79, 0x2E, 0x5B, 0x83,
+ 0xCE, 0x55, 0x8B, 0x89, 0xD6, 0xE3, 0x71, 0x63,
+ 0xBC, 0xB1, 0x5F, 0x67, 0xB4, 0x7E, 0x05, 0x0D,
+ 0xAC, 0x6D, 0x4E, 0x2C, 0xA5, 0xF4, 0x47, 0x89,
+ 0xAC, 0x5E, 0xBE, 0x2F, 0xFC, 0x9B, 0x2F, 0x0B,
+ 0xBE, 0x63, 0x54, 0x97, 0xBB, 0x23, 0x27, 0xCD,
+ 0xB9, 0xB2, 0x28, 0x0D, 0xA4, 0x78, 0x2C, 0xAB,
+ 0xD1, 0xC9, 0x94, 0x40, 0x54, 0xF2, 0x35, 0x61,
+ 0x49, 0x01, 0x87, 0x55, 0xA5, 0xB5, 0x1E, 0x84,
+ 0x92, 0x9E, 0xC1, 0xA4, 0x0B, 0x66, 0x2B, 0xF8,
+ 0xAF, 0xC3, 0x1E, 0xAF, 0x66, 0x3F, 0x6F, 0x5F,
+ 0x70, 0xEC, 0x25, 0x29, 0xE4, 0x65, 0xB2, 0x04,
+ 0x47, 0xF6, 0x3C, 0xB5, 0x5F, 0x66, 0x9F, 0xA4,
+ 0x1B, 0xFC, 0xA2, 0xD5, 0x3E, 0x84, 0xBA, 0x88,
+ 0x0D, 0xF1, 0x6A, 0xF2, 0xF6, 0x1D, 0xF1, 0xA3,
+ 0x45, 0xB2, 0x51, 0xD8, 0xA2, 0x8F, 0x55, 0xA6,
+ 0x89, 0xC4, 0x15, 0xD5, 0x73, 0xA8, 0xB1, 0x31,
+ 0x66, 0x9E, 0xC1, 0x43, 0xE1, 0x5D, 0x4E, 0x04,
+ 0x84, 0x8F, 0xF2, 0xBC, 0xE1, 0x4E, 0x4D, 0x60,
+ 0x81, 0xCA, 0x53, 0x34, 0x95, 0x17, 0x3B, 0xAE,
+ 0x8F, 0x95, 0xA7, 0xC6, 0x47, 0xC6, 0xAC, 0x32,
+ 0x12, 0x39, 0xCA, 0xEF, 0xE0, 0x07, 0xBF, 0x17,
+ 0x4F, 0xDC, 0x1B, 0x4E, 0x3C, 0x84, 0xF1, 0x9F,
+ 0x43, 0x70, 0x19, 0xE6, 0xF3, 0x8B, 0x8B, 0x5D,
+ 0xDB, 0xD2, 0x9D, 0xD4, 0xB2, 0x30, 0x45, 0x55,
+ 0xA2, 0x67, 0xA2, 0x76, 0x4A, 0x74, 0xAD, 0x88,
+ 0x71, 0xE6, 0x3E, 0x13, 0x06, 0x30, 0x17, 0xE1,
+ 0xEF, 0xAC, 0x71, 0xFB, 0x43, 0xCD, 0xF6, 0xFA,
+ 0x0E, 0x4C, 0x4E, 0x16, 0xF6, 0x6A, 0x09, 0x86,
+ 0x6B, 0xEA, 0x47, 0x6C, 0x70, 0xE7, 0xAD, 0xA2,
+ 0xE0, 0xFD, 0x7F, 0xF0, 0x5C, 0x21, 0x53, 0x0F,
+ 0x28, 0xA1, 0x43, 0xE1, 0x06, 0xCA, 0x0B, 0x31,
+ 0x88, 0x22, 0xA6, 0xE6, 0x34, 0x5B, 0xE6, 0xCF,
+ 0x25, 0x81, 0x63, 0xFF, 0x78, 0x66, 0x85, 0x19,
+ 0xE2, 0x0A, 0x7E, 0x81, 0x8A, 0x17, 0x1A, 0x18,
+ 0x8A, 0x5F, 0x5D, 0x9E, 0x82, 0x13, 0x10, 0xB9,
+ 0xD3, 0xE6, 0x93, 0x1C, 0xE4, 0x2C, 0xCB, 0x49,
+ 0x1E, 0xB6, 0x36, 0x13, 0xBF, 0x28, 0xEE, 0xCC,
+ 0x49, 0xF5, 0x79, 0xFC, 0x20, 0x65, 0xBD, 0xE8,
+ 0xF0, 0x1B, 0x4E, 0xC0, 0x0D, 0x3E, 0x89, 0x91,
+ 0xCC, 0x64, 0x10, 0xC0, 0x2A, 0x2B, 0xA3, 0xFA,
+ 0x60, 0x3D, 0xC3, 0x52, 0x2F, 0x93, 0xDE, 0xB7,
+ 0x6E, 0x8A, 0xDF, 0x6C, 0x08, 0xCC, 0x8B, 0x3B,
+ 0xC8, 0x50, 0xEF, 0x58, 0x64, 0x9A, 0x3D, 0x16,
+ 0x70, 0x94, 0x11, 0xD8, 0x94, 0x2B, 0x70, 0x91,
+ 0x10, 0x70, 0x88, 0xF0, 0x40, 0x75, 0x9A, 0x2B,
+ 0x39, 0xA1, 0x27, 0x3F, 0x2E, 0x91, 0xEA, 0xA1,
+ 0xCC, 0x12, 0xC1, 0x7F, 0x73, 0x8C, 0x5C, 0x6B,
+ 0xFC, 0xC5, 0x6A, 0x1C, 0x05, 0xF1, 0x3D, 0x30,
+ 0x82, 0x4A, 0x65, 0x35, 0xCE, 0x80, 0x10, 0xBB,
+ 0x41, 0x94, 0xFB, 0x84, 0x80, 0x7B, 0x91, 0xC4,
+ 0x4D, 0xA3, 0x5F, 0xB9, 0xFB, 0xF9, 0xC9, 0x1D,
+ 0x4F, 0x99, 0x1C, 0x1F, 0x47, 0x44, 0x89, 0x0E,
+ 0xED, 0x6D, 0xB5, 0x85, 0x41, 0x94, 0xEF, 0xF9,
+ 0x2E, 0xA0, 0xC8, 0xCA, 0xFB, 0x44, 0x02, 0xC6,
+ 0xBF, 0x96, 0x87, 0x80, 0x1D, 0xEF, 0x2A, 0x81,
+ 0xAB, 0xB2, 0x56, 0xDF, 0x54, 0x8B, 0xAB, 0xAF,
+ 0xFE, 0x18, 0x8C, 0xAA, 0xD4, 0x00, 0x17, 0xBE,
+ 0xCF, 0x06, 0xE5, 0xA6, 0xBF, 0x5A, 0x52, 0x3B,
+ 0x4E, 0xF5, 0x65, 0x60, 0x95, 0xDE, 0x8A, 0x25,
+ 0x88, 0xA5, 0x24, 0x96, 0x29, 0x13, 0x0D, 0x19,
+ 0x45, 0x95, 0x91, 0x08, 0xD2, 0x9C, 0x4C, 0x34,
+ 0x42, 0xF0, 0xA5, 0x72, 0xEB, 0xFB, 0x5E, 0xAA,
+ 0x68, 0x80, 0x82, 0xAC, 0x34, 0xAD, 0x89, 0xF6,
+ 0xAF, 0x54, 0x82, 0xCF, 0x98, 0x8C, 0x75, 0x63,
+ 0x8D, 0xBD, 0x1C, 0x2A, 0xD7, 0x00, 0xA7, 0x8E,
+ 0xB9, 0x33, 0xB6, 0x3B, 0x95, 0x9A, 0x59, 0x1D,
+ 0x3F, 0x23, 0x6B, 0x18, 0xF8, 0x4F, 0x1A, 0x8D,
+ 0xC0, 0x26, 0x9F, 0x87, 0x61, 0xB6, 0xC6, 0x60,
+ 0x38, 0x22, 0x73, 0x1C, 0x99, 0x23, 0xEF, 0xD9,
+ 0xFD, 0xCB, 0x54, 0x74, 0xBB, 0x77, 0x14, 0xA3,
+ 0xA9, 0xE6, 0x7C, 0x7E, 0x03, 0x3A, 0x13, 0x6E,
+ 0x1D, 0x6F, 0x64, 0xB3, 0xFA, 0xFB, 0x52, 0xDE,
+ 0xDF, 0x08, 0xFB, 0x6F, 0xC5, 0xFA, 0x51, 0x6A,
+ 0x69, 0x29, 0x9B, 0x96, 0xE8, 0x16, 0xC8, 0xD1,
+ 0xE4, 0x19, 0xBD, 0x14, 0x74, 0x27, 0xE7, 0x10,
+ 0xF0, 0xC3, 0xE2, 0xA7, 0x60, 0x48, 0xBF, 0xDD,
+ 0xC4, 0x0D, 0xD0, 0xF2, 0xEF, 0xA6, 0xC9, 0xA2,
+ 0x73, 0xD1, 0xCF, 0x41, 0xE1, 0x3B, 0xE5, 0x49,
+ 0x91, 0x5D, 0x09, 0xFD, 0x1D, 0x95, 0x29, 0xDB,
+ 0x52, 0x48, 0xEB, 0xF5, 0x1D, 0xF8, 0x06, 0x67,
+ 0x75, 0xF2, 0x57, 0xA4, 0x20, 0x60, 0xEA, 0xB0,
+ 0x85, 0x93, 0x7C, 0xDD, 0x52, 0x01, 0xD4, 0x57,
+ 0xA8, 0x31, 0x2D, 0xF9, 0x0A, 0xD2, 0x2A, 0xD1,
+ 0x34, 0x18, 0x35, 0x16, 0xB6, 0x8B, 0x0F, 0x0B,
+ 0xCF, 0x50, 0x80, 0xFE, 0x76, 0xCC, 0x4F, 0x30,
+ 0x98, 0x19, 0x16, 0x3D, 0x01, 0xEA, 0x8D, 0x8A,
+ 0x3D, 0xDC, 0xFB, 0x1F, 0x77, 0x8D, 0x72, 0x76,
+ 0x02, 0x3C, 0x5D, 0xEE, 0x55, 0x13, 0x5B, 0x6E,
+ 0x5A, 0x2D, 0xD5, 0x77, 0xD7, 0x01, 0x84, 0x7D,
+ 0x21, 0x8C, 0xDD, 0x94, 0x7D, 0x31, 0x3D, 0xF0,
+ 0xE7, 0x28, 0xF5, 0x72, 0x36, 0x60, 0xE0, 0x59,
+ 0x5F, 0xFE, 0x38, 0xF8, 0x2F, 0xDB, 0x9E, 0x55,
+ 0x5A, 0xD6, 0xBA, 0x6C, 0x87, 0xF3, 0xC0, 0x76,
+ 0x5F, 0xA3, 0x0A, 0xC3, 0xA3, 0x8D, 0x0E, 0x52,
+ 0xA8, 0xDA, 0x26, 0x3A, 0xF9, 0x3E, 0x36, 0xB1,
+ 0x06, 0xF8, 0x20, 0x2D, 0x1C, 0x0B, 0x93, 0xBB,
+ 0xD3, 0x64, 0x77, 0xCE, 0x11, 0xFC, 0xA2, 0x0E,
+ 0x1B, 0x5B, 0x9E, 0x13, 0x9F, 0x20, 0x8B, 0xAA,
+ 0xCD, 0x72, 0xD7, 0xA6, 0xF3, 0x1E, 0x4F, 0x72,
+ 0xC6, 0x49, 0x0F, 0x7B, 0xF0, 0x4C, 0x61, 0x1F,
+ 0x43, 0x0D, 0x4F, 0x0D, 0x33, 0x13, 0xED, 0x63,
+ 0xE5, 0xDB, 0x71, 0xAB, 0xA4, 0x83, 0xEF, 0xDC,
+ 0x86, 0x9D, 0x4B, 0xBD, 0x1B, 0x8A, 0xFE, 0x39,
+ 0xA8, 0x8B, 0xBA, 0x4C, 0x85, 0x28, 0xFC, 0xB3,
+ 0x62, 0x85, 0xD2, 0xF0, 0x38, 0xD0, 0x4B, 0xA4,
+ 0xD1, 0x3B, 0xD4, 0xD0, 0x2C, 0x78, 0x6C, 0x6A,
+ 0xC2, 0x64, 0x2C, 0x31, 0x4A, 0xD8, 0x69, 0x24,
+ 0xED, 0x77, 0x7D, 0x68, 0x9A, 0xA1, 0x78, 0x81,
+ 0xD9, 0x7E, 0x6C, 0xFE, 0x0A, 0x0D, 0x76, 0xF7,
+ 0x4B, 0x58, 0xE7, 0xC9, 0xB5, 0x11, 0x07, 0x87,
+ 0x88, 0x6A, 0x9F, 0x3D, 0xE0, 0xEE, 0xCC, 0x60,
+ 0x6B, 0x6B, 0xE6, 0xB5, 0x54, 0x8B, 0x32, 0x1F,
+ 0x04, 0x1D, 0x0E, 0x9E, 0xFA, 0x6D, 0xB0, 0xE0,
+ 0x6D, 0xF9, 0x79, 0xB4, 0xAB, 0x5E, 0xDF, 0x23,
+ 0x7F, 0x95, 0xAD, 0x80, 0x17, 0x23, 0x90, 0x1F,
+ 0xF0, 0xC3, 0xD9, 0x2D, 0xAC, 0x3F, 0x63, 0xF5,
+ 0x77, 0xC5, 0x05, 0xAC, 0x06, 0xB6, 0xA1, 0xB4,
+ 0xA2, 0x40, 0xB3, 0x99, 0x34, 0x7D, 0x31, 0xD4,
+ 0xB1, 0xD4, 0xC1, 0xBB, 0x71, 0x1E, 0xDA, 0x3F,
+ 0xA9, 0x12, 0x68, 0xFA, 0x5B, 0x20, 0x24, 0x6D,
+ 0x4D, 0x72, 0x43, 0x18, 0xBF, 0x66, 0x71, 0x69,
+ 0x26, 0x7D, 0x77, 0x78, 0xF8, 0xE5, 0x20, 0xAE,
+ 0x56, 0x6C, 0x0F, 0x72, 0x94, 0x42, 0x85, 0x4F,
+ 0xE4, 0xFB, 0x32, 0x26, 0x1B, 0x1C, 0x6E, 0x0B,
+ 0xF0, 0xB8, 0x58, 0x00, 0xD2, 0x36, 0x64, 0xAD,
+ 0xA9, 0x00, 0xCE, 0x35, 0x3C, 0x88, 0x79, 0x94,
+ 0x0C, 0x0C, 0x9B, 0xF2, 0xDA, 0xBD, 0xCA, 0x93,
+ 0x37, 0x26, 0xD3, 0x08, 0x54, 0xD2, 0x0D, 0xBC,
+ 0x5D, 0x43, 0x5F, 0xCF, 0x28, 0xB5, 0xAA, 0x15,
+ 0x28, 0x46, 0x45, 0x6B, 0xE8, 0xDF, 0xE8, 0xCE,
+ 0x8F, 0xC0, 0x1A, 0x53, 0x63, 0x3B, 0x53, 0x75,
+ 0xDD, 0x43, 0x1F, 0x07, 0x0A, 0xD5, 0xA1, 0x2A,
+ 0x6E, 0x28, 0xE1, 0xD7, 0xD0, 0x09, 0xCF, 0x62,
+ 0xC1, 0x5F, 0x21, 0xDB, 0xC5, 0x40, 0x99, 0x48,
+ 0x87, 0x6E, 0x11, 0xF5, 0x5A, 0x4E, 0xBC, 0xF9,
+ 0xA8, 0x02, 0x7C, 0x47, 0x39, 0xA5, 0xD8, 0x52,
+ 0xB1, 0x80, 0xDC, 0xFE, 0x08, 0x4B, 0x5D, 0x09,
+ 0xDE, 0x06, 0xF3, 0x2A, 0xAD, 0x14, 0x76, 0x40,
+ 0x2F, 0x82, 0x28, 0x6A, 0xB6, 0x43, 0xEF, 0x71,
+ 0x63, 0xC2, 0x56, 0xEB, 0x3B, 0x4B, 0x52, 0x2F,
+ 0x93, 0xD3, 0x18, 0x3E, 0x18, 0xA8, 0xF7, 0x58,
+ 0xFC, 0x8B, 0x3D, 0x4D, 0x4B, 0x72, 0xBD, 0xF7,
+ 0x04, 0xC9, 0xB8, 0xD7, 0x6C, 0x8C, 0x67, 0xBB,
+ 0x4C, 0x9B, 0x57, 0xF7, 0x22, 0x4E, 0x41, 0xB6,
+ 0xFD, 0xD9, 0xF8, 0x41, 0x62, 0x0F, 0xFF, 0xAA,
+ 0xC6, 0x87, 0x95, 0xFF, 0xFD, 0x58, 0xD9, 0xB2,
+ 0xBA, 0x47, 0x61, 0x24, 0xEA, 0x92, 0x6E, 0x74,
+ 0xB3, 0xDA, 0xE5, 0x83, 0x99, 0x24, 0xB1, 0x71,
+ 0x2A, 0x33, 0xB2, 0xD5, 0x8F, 0xF0, 0x32, 0xCE,
+ 0x37, 0xCF, 0xC7, 0x1C, 0xE8, 0xDE, 0x46, 0x78,
+ 0x96, 0x97, 0xF6, 0x73, 0x90, 0xE5, 0x71, 0x05,
+ 0xEA, 0x0D, 0xC2, 0x1D, 0x9E, 0x43, 0x34, 0xBC,
+ 0x8F, 0x45, 0xE5, 0x08, 0xCA, 0x20, 0x0C, 0x84
+ },
+ .len = 2048
+ },
+ .auth_tag = {
+ .data = {
+ 0xD0, 0x62, 0x1F, 0x20, 0x1C, 0xE8, 0xDD, 0x36,
+ 0x00, 0x74, 0xF6, 0xD7, 0xFD, 0x2C, 0xA0, 0xAF
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_J0_test_case_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88, 0x00, 0x00, 0x00, 0x01 },
+ .len = 0
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
+ 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
+ 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
+ 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
+ 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
+ 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
+ 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
+ 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ .len = 16
+ }
+};
+
+/** AES-GCM-192 Test Vectors */
+static const struct aead_test_data gcm_test_case_192_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = { 0x00 },
+ .len = 0
+ },
+ .ciphertext = {
+ .data = { 0x00 },
+ .len = 0
+ },
+ .auth_tag = {
+ .data = {
+ 0xCD, 0x33, 0xB2, 0x8A, 0xC7, 0x73, 0xF7, 0x4B,
+ 0xA0, 0x0E, 0xD1, 0xF3, 0x12, 0x57, 0x24, 0x35
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .ciphertext = {
+ .data = {
+ 0x98, 0xE7, 0x24, 0x7C, 0x07, 0xF0, 0xFE, 0x41,
+ 0x1C, 0x26, 0x7E, 0x43, 0x84, 0xB0, 0xF6, 0x00
+ },
+ .len = 16
+ },
+ .auth_tag = {
+ .data = {
+ 0x2F, 0xF5, 0x8D, 0x80, 0x03, 0x39, 0x27, 0xAB,
+ 0x8E, 0xF4, 0xD4, 0x58, 0x75, 0x14, 0xF0, 0xFB
+
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
+ 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE, 0xDB, 0xAD,
+ 0xDE, 0xCA, 0xF8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
+ 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
+ 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
+ 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
+ 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
+ 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
+ 0xBA, 0x63, 0x7B, 0x39, 0x1A, 0xAF, 0xD2, 0x55
+ },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x39, 0x80, 0xCA, 0x0B, 0x3C, 0x00, 0xE8, 0x41,
+ 0xEB, 0x06, 0xFA, 0xC4, 0x87, 0x2A, 0x27, 0x57,
+ 0x85, 0x9E, 0x1C, 0xEA, 0xA6, 0xEF, 0xD9, 0x84,
+ 0x62, 0x85, 0x93, 0xB4, 0x0C, 0xA1, 0xE1, 0x9C,
+ 0x7D, 0x77, 0x3D, 0x00, 0xC1, 0x44, 0xC5, 0x25,
+ 0xAC, 0x61, 0x9D, 0x18, 0xC8, 0x4A, 0x3F, 0x47,
+ 0x18, 0xE2, 0x44, 0x8B, 0x2F, 0xE3, 0x24, 0xD9,
+ 0xCC, 0xDA, 0x27, 0x10, 0xAC, 0xAD, 0xE2, 0x56
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x99, 0x24, 0xA7, 0xC8, 0x58, 0x73, 0x36, 0xBF,
+ 0xB1, 0x18, 0x02, 0x4D, 0xB8, 0x67, 0x4A, 0x14
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_4 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
+ 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE, 0xDB, 0xAD,
+ 0xDE, 0xCA, 0xF8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
+ 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
+ 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
+ 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
+ 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
+ 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
+ 0xBA, 0x63, 0x7B, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x39, 0x80, 0xCA, 0x0B, 0x3C, 0x00, 0xE8, 0x41,
+ 0xEB, 0x06, 0xFA, 0xC4, 0x87, 0x2A, 0x27, 0x57,
+ 0x85, 0x9E, 0x1C, 0xEA, 0xA6, 0xEF, 0xD9, 0x84,
+ 0x62, 0x85, 0x93, 0xB4, 0x0C, 0xA1, 0xE1, 0x9C,
+ 0x7D, 0x77, 0x3D, 0x00, 0xC1, 0x44, 0xC5, 0x25,
+ 0xAC, 0x61, 0x9D, 0x18, 0xC8, 0x4A, 0x3F, 0x47,
+ 0x18, 0xE2, 0x44, 0x8B, 0x2F, 0xE3, 0x24, 0xD9,
+ 0xCC, 0xDA, 0x27, 0x10
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0x57, 0x5F, 0x03, 0xA0, 0x8D, 0x8F, 0x40, 0x26,
+ 0xE5, 0x64, 0x1F, 0x5B, 0x5C, 0xC2, 0xFD, 0x4B
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_5 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
+ 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE, 0xDB, 0xAD,
+ 0xDE, 0xCA, 0xF8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
+ 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
+ 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
+ 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
+ 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
+ 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
+ 0xBA, 0x63, 0x7B, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x39, 0x80, 0xCA, 0x0B, 0x3C, 0x00, 0xE8, 0x41,
+ 0xEB, 0x06, 0xFA, 0xC4, 0x87, 0x2A, 0x27, 0x57,
+ 0x85, 0x9E, 0x1C, 0xEA, 0xA6, 0xEF, 0xD9, 0x84,
+ 0x62, 0x85, 0x93, 0xB4, 0x0C, 0xA1, 0xE1, 0x9C,
+ 0x7D, 0x77, 0x3D, 0x00, 0xC1, 0x44, 0xC5, 0x25,
+ 0xAC, 0x61, 0x9D, 0x18, 0xC8, 0x4A, 0x3F, 0x47,
+ 0x18, 0xE2, 0x44, 0x8B, 0x2F, 0xE3, 0x24, 0xD9,
+ 0xCC, 0xDA, 0x27, 0x10
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xB6, 0x35, 0x56, 0xE7, 0xBA, 0x46, 0xA3, 0x38,
+ 0xED, 0xAD, 0x79, 0x9F, 0xB3, 0x5B, 0x34, 0xA8
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_6 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
+ 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE, 0xDB, 0xAD,
+ 0xDE, 0xCA, 0xF8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
+ 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
+ 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
+ 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
+ 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
+ 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
+ 0xBA, 0x63, 0x7B, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x39, 0x80, 0xCA, 0x0B, 0x3C, 0x00, 0xE8, 0x41,
+ 0xEB, 0x06, 0xFA, 0xC4, 0x87, 0x2A, 0x27, 0x57,
+ 0x85, 0x9E, 0x1C, 0xEA, 0xA6, 0xEF, 0xD9, 0x84,
+ 0x62, 0x85, 0x93, 0xB4, 0x0C, 0xA1, 0xE1, 0x9C,
+ 0x7D, 0x77, 0x3D, 0x00, 0xC1, 0x44, 0xC5, 0x25,
+ 0xAC, 0x61, 0x9D, 0x18, 0xC8, 0x4A, 0x3F, 0x47,
+ 0x18, 0xE2, 0x44, 0x8B, 0x2F, 0xE3, 0x24, 0xD9,
+ 0xCC, 0xDA, 0x27, 0x10
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xCA, 0x8A, 0x8A, 0x91, 0x5A, 0xF9, 0x76, 0xE3,
+ 0xFF, 0x2C, 0xE4, 0x7D, 0xE5, 0x62, 0x75, 0x18
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_192_7 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C,
+ 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE, 0xDB, 0xAD,
+ 0xDE, 0xCA, 0xF8, 0x88
+ },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5,
+ 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
+ 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA,
+ 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
+ 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
+ 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57,
+ 0xBA, 0x63, 0x7B, 0x39
+ },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x39, 0x80, 0xCA, 0x0B, 0x3C, 0x00, 0xE8, 0x41,
+ 0xEB, 0x06, 0xFA, 0xC4, 0x87, 0x2A, 0x27, 0x57,
+ 0x85, 0x9E, 0x1C, 0xEA, 0xA6, 0xEF, 0xD9, 0x84,
+ 0x62, 0x85, 0x93, 0xB4, 0x0C, 0xA1, 0xE1, 0x9C,
+ 0x7D, 0x77, 0x3D, 0x00, 0xC1, 0x44, 0xC5, 0x25,
+ 0xAC, 0x61, 0x9D, 0x18, 0xC8, 0x4A, 0x3F, 0x47,
+ 0x18, 0xE2, 0x44, 0x8B, 0x2F, 0xE3, 0x24, 0xD9,
+ 0xCC, 0xDA, 0x27, 0x10
+ },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xC2, 0xD8, 0x4C, 0x6B, 0xA8, 0x3B, 0xA5, 0x6B,
+ 0x18, 0x9F, 0xE6, 0xEF, 0x66, 0x24, 0xDD, 0xDA
+ },
+ .len = 16
+ }
+};
+
+/** AES-GCM-256 Test Vectors */
+static const struct aead_test_data gcm_test_case_256_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = { 0x00 },
+ .len = 0
+ },
+ .ciphertext = {
+ .data = { 0x00 },
+ .len = 0
+ },
+ .auth_tag = {
+ .data = {
+ 0x53, 0x0F, 0x8A, 0xFB, 0xC7, 0x45, 0x36, 0xB9,
+ 0xA9, 0x63, 0xB4, 0xF1, 0xC4, 0xCB, 0x73, 0x8B },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_256_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ .len = 16
+ },
+ .ciphertext = {
+ .data = {
+ 0xCE, 0xA7, 0x40, 0x3D, 0x4D, 0x60, 0x6B, 0x6E,
+ 0x07, 0x4E, 0xC5, 0xD3, 0xBA, 0xF3, 0x9D, 0x18 },
+ .len = 16
+ },
+ .auth_tag = {
+ .data = {
+ 0xD0, 0xD1, 0xC8, 0xA7, 0x99, 0x99, 0x6B, 0xF0,
+ 0x26, 0x5B, 0x98, 0xB5, 0xD4, 0x8A, 0xB9, 0x19 },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_256_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E, 0xF0, 0x68, 0xE1, 0x3E },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x64, 0xAF, 0x1D, 0xFB, 0xE8, 0x0D, 0x37, 0xD8,
+ 0x92, 0xC3, 0xB9, 0x1D, 0xD3, 0x08, 0xAB, 0xFC },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_256_4 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0x63, 0x16, 0x91, 0xAE, 0x17, 0x05, 0x5E, 0xA6,
+ 0x6D, 0x0A, 0x51, 0xE2, 0x50, 0x21, 0x85, 0x4A },
+ .len = 16
+ }
+
+};
+
+static const struct aead_test_data gcm_test_case_256_5 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0xA7, 0x99, 0xAC, 0xB8, 0x27, 0xDA, 0xB1, 0x82,
+ 0x79, 0xFD, 0x83, 0x73, 0x52, 0x4D, 0xDB, 0xF1 },
+ .len = 16
+ }
+
+};
+
+static const struct aead_test_data gcm_test_case_256_6 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0x5D, 0xA5, 0x0E, 0x53, 0x64, 0x7F, 0x3F, 0xAE,
+ 0x1A, 0x1F, 0xC0, 0xB0, 0xD8, 0xBE, 0xF2, 0x64 },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_256_7 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = 12
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39 },
+ .len = 60
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E },
+ .len = 60
+ },
+ .auth_tag = {
+ .data = {
+ 0x4E, 0xD0, 0x91, 0x95, 0x83, 0xA9, 0x38, 0x72,
+ 0x09, 0xA9, 0xCE, 0x5F, 0x89, 0x06, 0x4E, 0xC8 },
+ .len = 16
+ }
+};
+
+/** variable AAD AES-GCM-128 Test Vectors */
+static const struct aead_test_data gcm_test_case_aad_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = GCM_LARGE_AAD_LENGTH
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1E, 0xC2, 0x21, 0x77, 0x74, 0x24,
+ 0x4B, 0x72, 0x21, 0xB7, 0x84, 0xD0, 0xD4, 0x9C,
+ 0xE3, 0xAA, 0x21, 0x2F, 0x2C, 0x02, 0xA4, 0xE0,
+ 0x35, 0xC1, 0x7E, 0x23, 0x29, 0xAC, 0xA1, 0x2E,
+ 0x21, 0xD5, 0x14, 0xB2, 0x54, 0x66, 0x93, 0x1C,
+ 0x7D, 0x8F, 0x6A, 0x5A, 0xAC, 0x84, 0xAA, 0x05,
+ 0x1B, 0xA3, 0x0B, 0x39, 0x6A, 0x0A, 0xAC, 0x97,
+ 0x3D, 0x58, 0xE0, 0x91, 0x47, 0x3F, 0x59, 0x85
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0xCA, 0x70, 0xAF, 0x96, 0xA8, 0x5D, 0x40, 0x47,
+ 0x0C, 0x3C, 0x48, 0xF5, 0xF0, 0xF5, 0xA5, 0x7D
+ },
+ .len = 16
+ }
+};
+
+/** variable AAD AES-GCM-256 Test Vectors */
+static const struct aead_test_data gcm_test_case_aad_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_text,
+ .len = GCM_LARGE_AAD_LENGTH
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
+ .len = 64
+ },
+ .ciphertext = {
+ .data = {
+ 0x05, 0xA2, 0x39, 0xA5, 0xE1, 0x1A, 0x74, 0xEA,
+ 0x6B, 0x2A, 0x55, 0xF6, 0xD7, 0x88, 0x44, 0x7E,
+ 0x93, 0x7E, 0x23, 0x64, 0x8D, 0xF8, 0xD4, 0x04,
+ 0x3B, 0x40, 0xEF, 0x6D, 0x7C, 0x6B, 0xF3, 0xB9,
+ 0x50, 0x15, 0x97, 0x5D, 0xB8, 0x28, 0xA1, 0xD5,
+ 0x22, 0xDE, 0x36, 0x26, 0xD0, 0x6A, 0x7A, 0xC0,
+ 0xB5, 0x14, 0x36, 0xAF, 0x3A, 0xC6, 0x50, 0xAB,
+ 0xFA, 0x47, 0xC8, 0x2E, 0xF0, 0x68, 0xE1, 0x3E
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0xBA, 0x06, 0xDA, 0xA1, 0x91, 0xE1, 0xFE, 0x22,
+ 0x59, 0xDA, 0x67, 0xAF, 0x9D, 0xA5, 0x43, 0x94
+ },
+ .len = 16
+ }
+};
+
+/** GMAC Test Vectors */
+static uint8_t gmac_plaintext[GMAC_LARGE_PLAINTEXT_LENGTH] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
+};
+
+static const struct gmac_test_data gmac_test_case_1 = {
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .plaintext = {
+ .data = gmac_plaintext,
+ .len = 160
+ },
+ .gmac_tag = {
+ .data = {
+ 0x4C, 0x0C, 0x4F, 0x47, 0x2D, 0x78, 0xF6, 0xD8,
+ 0x03, 0x53, 0x20, 0x2F, 0x1A, 0xDF, 0x90, 0xD0
+ },
+ .len = 16
+ },
+};
+
+static const struct gmac_test_data gmac_test_case_2 = {
+ .key = {
+ .data = {
+ 0xaa, 0x74, 0x0a, 0xbf, 0xad, 0xcd, 0xa7, 0x79,
+ 0x22, 0x0d, 0x3b, 0x40, 0x6c, 0x5d, 0x7e, 0xc0,
+ 0x9a, 0x77, 0xfe, 0x9d, 0x94, 0x10, 0x45, 0x39,
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0xab, 0x22, 0x65, 0xb4, 0xc1, 0x68, 0x95,
+ 0x55, 0x61, 0xf0, 0x43, 0x15, },
+ .len = 12
+ },
+ .plaintext = {
+ .data = gmac_plaintext,
+ .len = 80
+ },
+ .gmac_tag = {
+ .data = {
+ 0xCF, 0x82, 0x80, 0x64, 0x02, 0x46, 0xF4, 0xFB,
+ 0x33, 0xAE, 0x1D, 0x90, 0xEA, 0x48, 0x83, 0xDB
+ },
+ .len = 16
+ },
+};
+
+static const struct gmac_test_data gmac_test_case_3 = {
+ .key = {
+ .data = {
+ 0xb5, 0x48, 0xe4, 0x93, 0x4f, 0x5c, 0x64, 0xd3,
+ 0xc0, 0xf0, 0xb7, 0x8f, 0x7b, 0x4d, 0x88, 0x24,
+ 0xaa, 0xc4, 0x6b, 0x3c, 0x8d, 0x2c, 0xc3, 0x5e,
+ 0xe4, 0xbf, 0xb2, 0x54, 0xe4, 0xfc, 0xba, 0xf7,
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x2e, 0xed, 0xe1, 0xdc, 0x64, 0x47, 0xc7,
+ 0xaf, 0xc4, 0x41, 0x53, 0x58,
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = gmac_plaintext,
+ .len = 65
+ },
+ .gmac_tag = {
+ .data = {
+ 0x77, 0x46, 0x0D, 0x6F, 0xB1, 0x87, 0xDB, 0xA9,
+ 0x46, 0xAD, 0xCD, 0xFB, 0xB7, 0xF9, 0x13, 0xA1
+ },
+ .len = 16
+ },
+};
+
+/******* GCM PERF VECTORS ***********/
+
+struct cryptodev_perf_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned len;
+ } iv;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } aad;
+
+ struct {
+ uint8_t data[2048];
+ unsigned len;
+ } plaintext;
+
+ struct {
+ uint8_t data[2048];
+ unsigned len;
+ } ciphertext;
+
+ struct {
+ uint8_t data[16];
+ unsigned len;
+ } auth_tag;
+
+ struct {
+ uint32_t size;
+ uint8_t data[16];
+ unsigned len;
+ } auth_tags[7];
+
+};
+
+/* 2048B */
+static const struct cryptodev_perf_test_data AES_GCM_128_12IV_0AAD = {
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = { 0 },
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55
+ },
+ .len = 2048
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1E, 0xC2, 0x21, 0x77, 0x74, 0x24,
+ 0x4B, 0x72, 0x21, 0xB7, 0x84, 0xD0, 0xD4, 0x9C,
+ 0xE3, 0xAA, 0x21, 0x2F, 0x2C, 0x02, 0xA4, 0xE0,
+ 0x35, 0xC1, 0x7E, 0x23, 0x29, 0xAC, 0xA1, 0x2E,
+ 0x21, 0xD5, 0x14, 0xB2, 0x54, 0x66, 0x93, 0x1C,
+ 0x7D, 0x8F, 0x6A, 0x5A, 0xAC, 0x84, 0xAA, 0x05,
+ 0x1B, 0xA3, 0x0B, 0x39, 0x6A, 0x0A, 0xAC, 0x97,
+ 0x3D, 0x58, 0xE0, 0x91, 0x47, 0x3F, 0x59, 0x85,
+ 0x04, 0x99, 0x55, 0xE1, 0x36, 0x76, 0xB7, 0x14,
+ 0x1D, 0xF0, 0xF6, 0x8C, 0x65, 0xD5, 0xAD, 0xFB,
+ 0x90, 0x7F, 0x5D, 0xA2, 0xD6, 0xFD, 0xD0, 0xE5,
+ 0x0D, 0x9B, 0x68, 0x21, 0x49, 0x42, 0x6E, 0x13,
+ 0xEC, 0x22, 0x50, 0x2A, 0x30, 0x47, 0x49, 0xA1,
+ 0x7F, 0xC3, 0x09, 0xE0, 0x56, 0x91, 0xC4, 0x54,
+ 0x70, 0xD7, 0x19, 0x40, 0xCA, 0x6B, 0x65, 0x27,
+ 0x3E, 0xE9, 0xD1, 0x0F, 0x1C, 0xB5, 0x45, 0x0D,
+ 0x27, 0xE7, 0xCF, 0x94, 0x10, 0xBF, 0xA2, 0xFA,
+ 0x86, 0x20, 0x3F, 0x6E, 0xE9, 0x95, 0x03, 0x5A,
+ 0x46, 0x11, 0x75, 0xD5, 0x37, 0x71, 0x7F, 0xE0,
+ 0xBC, 0x9F, 0xC8, 0xE9, 0xB1, 0x08, 0x2C, 0x59,
+ 0x6E, 0x51, 0x4A, 0x83, 0x38, 0xC1, 0xED, 0xE2,
+ 0x2E, 0x88, 0x90, 0xA5, 0x7D, 0xA4, 0x93, 0x9A,
+ 0x30, 0xD6, 0x96, 0x34, 0x0F, 0xC4, 0xD1, 0x7E,
+ 0xC9, 0x8F, 0xC5, 0xBB, 0x80, 0x50, 0x85, 0x75,
+ 0x7D, 0x82, 0x36, 0xDB, 0x62, 0x15, 0xAF, 0x4B,
+ 0x0A, 0x9D, 0xCD, 0x64, 0x00, 0xAB, 0x88, 0x28,
+ 0xA8, 0x35, 0x17, 0x70, 0x6F, 0x47, 0x44, 0xCD,
+ 0x65, 0xAE, 0xD5, 0x05, 0x0A, 0xA8, 0x2F, 0x48,
+ 0xAC, 0xA1, 0x72, 0x64, 0x1C, 0x7E, 0xD3, 0xF5,
+ 0xD8, 0x4E, 0x73, 0x17, 0x0C, 0xE5, 0x9F, 0xB6,
+ 0x00, 0xFA, 0xD7, 0x2C, 0x3D, 0x6A, 0x10, 0x47,
+ 0x7C, 0xF2, 0x6B, 0x13, 0x10, 0x8A, 0x76, 0x39,
+ 0xF8, 0x50, 0x33, 0xAC, 0x08, 0x1D, 0xA3, 0x48,
+ 0xE1, 0xD0, 0x05, 0x49, 0xB7, 0x76, 0x03, 0x72,
+ 0x07, 0xC5, 0xD3, 0x08, 0x79, 0x38, 0x66, 0xC1,
+ 0x52, 0xAF, 0x83, 0xCD, 0xF3, 0x86, 0x62, 0xBF,
+ 0x92, 0x24, 0x97, 0xBD, 0x5D, 0x7D, 0x81, 0x56,
+ 0x4C, 0xF3, 0xD2, 0x60, 0xC2, 0xDE, 0x61, 0xC1,
+ 0x39, 0x61, 0xDA, 0x07, 0x50, 0xC7, 0x98, 0x63,
+ 0x7E, 0xDD, 0x54, 0xCA, 0xDE, 0x12, 0xD2, 0xA8,
+ 0x19, 0x08, 0x6E, 0xF9, 0xFA, 0x6F, 0x58, 0x97,
+ 0xD4, 0x0B, 0x5C, 0x5B, 0xE5, 0x30, 0xE5, 0x4C,
+ 0x0E, 0x16, 0x87, 0xF0, 0x2C, 0xCB, 0x53, 0xB8,
+ 0x0C, 0xE5, 0xDF, 0x16, 0x7B, 0xE8, 0xC2, 0xCF,
+ 0xCC, 0xFF, 0x51, 0x24, 0xC1, 0xDD, 0x59, 0x9C,
+ 0xA7, 0x56, 0x03, 0xB9, 0x0A, 0x37, 0xA2, 0xAC,
+ 0x28, 0x8B, 0xEB, 0x51, 0x4E, 0xF1, 0xAE, 0xB5,
+ 0xC8, 0xB5, 0xCB, 0x8D, 0x23, 0xF6, 0x24, 0x2D,
+ 0xF6, 0x59, 0x62, 0xC0, 0xCB, 0xD3, 0x18, 0xE4,
+ 0xB7, 0x73, 0xEF, 0xDB, 0x13, 0x9A, 0xF5, 0xD3,
+ 0xD5, 0x61, 0x01, 0x14, 0xA5, 0xE5, 0x0D, 0x27,
+ 0xC9, 0xA5, 0x08, 0x1C, 0x60, 0xBA, 0x73, 0xFF,
+ 0xA9, 0xE0, 0x27, 0x86, 0x3F, 0xF7, 0x15, 0x03,
+ 0x69, 0xA7, 0x2B, 0x57, 0xAC, 0xA6, 0x70, 0x55,
+ 0xE9, 0xB5, 0x3F, 0xEB, 0x6F, 0xCE, 0x8A, 0xA1,
+ 0x9D, 0x8B, 0x84, 0xF1, 0x7C, 0xD0, 0x35, 0x21,
+ 0x91, 0x3D, 0x3D, 0x6E, 0x83, 0xFC, 0x45, 0x36,
+ 0x93, 0xDA, 0x66, 0xDF, 0x1A, 0x59, 0x22, 0xA5,
+ 0xC4, 0x99, 0x9B, 0xF8, 0x48, 0x9A, 0x50, 0x09,
+ 0xAB, 0xAE, 0x56, 0xB6, 0x49, 0x02, 0x3E, 0x90,
+ 0xB6, 0x07, 0x7E, 0xA7, 0x6A, 0x0A, 0xB5, 0x85,
+ 0x31, 0x0D, 0x84, 0xD4, 0x01, 0xE4, 0x48, 0x63,
+ 0xF3, 0xC1, 0x54, 0x65, 0xA6, 0x4C, 0x8B, 0x33,
+ 0xF9, 0x70, 0x59, 0x3B, 0xA6, 0xF6, 0x2B, 0x66,
+ 0xC5, 0xD2, 0xEB, 0xAB, 0x67, 0xD2, 0xE3, 0x78,
+ 0xA9, 0x1A, 0x4C, 0x99, 0xA9, 0xA6, 0xCA, 0xF7,
+ 0x65, 0xF0, 0x48, 0xF8, 0x2A, 0xEA, 0x96, 0x9F,
+ 0xC4, 0x50, 0x9A, 0x0C, 0xB6, 0x0D, 0x8A, 0x2F,
+ 0xC3, 0x99, 0x4E, 0xA0, 0x06, 0x4D, 0xAB, 0x25,
+ 0x2E, 0x44, 0x47, 0xB6, 0x98, 0xF1, 0x2C, 0x96,
+ 0x54, 0x51, 0x12, 0x41, 0x0D, 0xEF, 0x32, 0x9A,
+ 0x4A, 0xBD, 0xA2, 0x26, 0x53, 0xA8, 0xFD, 0x8B,
+ 0x6C, 0x95, 0x0A, 0x1A, 0x96, 0xEF, 0x3C, 0x85,
+ 0x34, 0x4E, 0x25, 0x9E, 0x1C, 0x67, 0x33, 0x8A,
+ 0xFF, 0x6D, 0x98, 0x93, 0x3D, 0x3F, 0x49, 0x6B,
+ 0xBF, 0x7C, 0x4F, 0x63, 0x5D, 0x62, 0x64, 0x67,
+ 0x0D, 0x07, 0x7F, 0x24, 0x4A, 0x23, 0xBC, 0x35,
+ 0xE0, 0x92, 0x6F, 0x51, 0xE7, 0x25, 0x97, 0xB9,
+ 0x14, 0x35, 0x2B, 0x48, 0xAC, 0x6F, 0x54, 0xDF,
+ 0xF2, 0xB4, 0xB0, 0xE0, 0xD3, 0x28, 0x0D, 0x66,
+ 0x46, 0x28, 0x0A, 0x16, 0x9C, 0x87, 0x73, 0xB7,
+ 0x9C, 0x2B, 0xB5, 0x43, 0xC9, 0x46, 0xB9, 0x1F,
+ 0x5F, 0x3C, 0x45, 0x03, 0x4B, 0xBF, 0x44, 0x4D,
+ 0xE1, 0x44, 0xDA, 0x54, 0xC5, 0x32, 0x3A, 0xFA,
+ 0x21, 0x5C, 0xAD, 0xD5, 0x1E, 0x1B, 0x54, 0x7C,
+ 0x9F, 0xEA, 0x92, 0x8C, 0xEA, 0x69, 0xC0, 0xCE,
+ 0xDA, 0x09, 0xAD, 0x95, 0xA0, 0x8E, 0x0B, 0x8E,
+ 0x10, 0x4F, 0x5B, 0x8F, 0xB8, 0x2D, 0xAC, 0x4C,
+ 0x94, 0x4B, 0x7C, 0x1E, 0xF1, 0x53, 0x20, 0x9B,
+ 0xD6, 0xC4, 0x92, 0x4C, 0x7F, 0xFB, 0x8B, 0x8E,
+ 0x40, 0x2F, 0x24, 0xA3, 0x4E, 0x46, 0x64, 0xF4,
+ 0xC6, 0x35, 0x0F, 0xC7, 0x40, 0x55, 0x43, 0xAF,
+ 0x7E, 0x91, 0x76, 0x48, 0x6F, 0x97, 0x7A, 0xF8,
+ 0x32, 0x1E, 0xD3, 0x5B, 0xBC, 0x19, 0xB5, 0x48,
+ 0xFA, 0x4F, 0x52, 0x77, 0x5B, 0x9E, 0xA2, 0xC8,
+ 0x9A, 0x83, 0x30, 0x8D, 0x9F, 0x0B, 0x6F, 0xA8,
+ 0x2E, 0x84, 0xCC, 0xC1, 0x50, 0x96, 0x46, 0xAE,
+ 0x73, 0x91, 0x7D, 0xCD, 0x88, 0xAB, 0x67, 0x3F,
+ 0x66, 0x3A, 0x8D, 0xB1, 0x89, 0x07, 0x93, 0xDB,
+ 0x42, 0x22, 0xDC, 0x13, 0xBD, 0xCD, 0xBB, 0x12,
+ 0x8D, 0x88, 0x44, 0x13, 0x22, 0x52, 0x81, 0xDC,
+ 0xEF, 0xA1, 0xE4, 0xA3, 0xA7, 0xBA, 0xEE, 0x98,
+ 0x79, 0x45, 0x29, 0x05, 0x65, 0x3D, 0xDC, 0xAF,
+ 0xA1, 0x37, 0x29, 0xFD, 0x05, 0xD1, 0x3A, 0xF7,
+ 0x32, 0x1D, 0x02, 0xEC, 0x28, 0x1E, 0x0F, 0x96,
+ 0xF3, 0x21, 0x19, 0x5F, 0x49, 0xB9, 0xEA, 0x9A,
+ 0xAD, 0x34, 0x58, 0xD1, 0xD9, 0xB1, 0x7D, 0xD2,
+ 0xEA, 0xED, 0x74, 0xE8, 0x25, 0x9A, 0x7B, 0xC5,
+ 0xC8, 0xD8, 0x76, 0xB6, 0xBC, 0x0B, 0x78, 0xCE,
+ 0xD9, 0xA6, 0xBB, 0x2F, 0x79, 0xA4, 0x45, 0x05,
+ 0x55, 0x6E, 0x20, 0x84, 0xEB, 0xC8, 0x70, 0xB0,
+ 0x3A, 0x2D, 0x06, 0x98, 0x29, 0x10, 0xB8, 0xC5,
+ 0xE9, 0xE4, 0xB6, 0xDE, 0x97, 0x9A, 0x0D, 0x8C,
+ 0xB6, 0x22, 0x16, 0x59, 0xAB, 0xB5, 0xD7, 0x14,
+ 0xAB, 0x08, 0x02, 0x27, 0x7B, 0xF7, 0x0E, 0xAC,
+ 0xC5, 0xAC, 0x4D, 0x7F, 0xE5, 0x65, 0x51, 0x40,
+ 0x44, 0x92, 0xB1, 0x6A, 0xB7, 0x00, 0x76, 0x89,
+ 0x6E, 0x08, 0x5F, 0x45, 0x2B, 0x53, 0x86, 0x86,
+ 0xA7, 0x85, 0xBC, 0x62, 0xAC, 0xAA, 0x82, 0x73,
+ 0x0A, 0xEB, 0x35, 0x16, 0x95, 0x26, 0xAB, 0x9E,
+ 0xE9, 0x64, 0x53, 0x99, 0x08, 0x31, 0xF5, 0x6B,
+ 0x1F, 0xFE, 0x47, 0x4B, 0x09, 0x33, 0x4F, 0xBF,
+ 0x1F, 0x0B, 0x4C, 0xB2, 0xB4, 0xA4, 0x17, 0xA9,
+ 0xAD, 0xC5, 0x62, 0x7C, 0xF1, 0x1B, 0xAE, 0x46,
+ 0xD3, 0xAC, 0xFD, 0x43, 0xFE, 0x79, 0xD0, 0x58,
+ 0x2F, 0x6C, 0x9F, 0xD0, 0x65, 0xA4, 0x64, 0x03,
+ 0xAF, 0x73, 0x46, 0x75, 0x7D, 0x49, 0x1B, 0x4C,
+ 0xFA, 0x49, 0xD8, 0x9A, 0xCC, 0x59, 0xC6, 0xC7,
+ 0xA1, 0x05, 0xC2, 0x32, 0xC8, 0x6C, 0x50, 0xA8,
+ 0x06, 0x58, 0xBE, 0x6C, 0x7D, 0x22, 0xD6, 0x0D,
+ 0x74, 0x40, 0xCE, 0xD6, 0x64, 0xD6, 0x47, 0xD0,
+ 0xBF, 0xF1, 0x5C, 0x54, 0xF9, 0x06, 0x3F, 0x3D,
+ 0x86, 0xBA, 0xF2, 0x0F, 0x5E, 0x2C, 0x01, 0xCC,
+ 0xD9, 0xC7, 0xB1, 0x4A, 0xB3, 0xD7, 0x26, 0xCC,
+ 0xC3, 0x7A, 0x74, 0x2C, 0xE1, 0x22, 0x65, 0xA0,
+ 0x5B, 0xCA, 0xF4, 0xE1, 0x7D, 0xE1, 0x56, 0xFD,
+ 0x94, 0x10, 0xC6, 0xA1, 0x4A, 0xE8, 0x6B, 0x34,
+ 0x4E, 0x71, 0x60, 0x77, 0x0F, 0x03, 0xDD, 0xFF,
+ 0xC8, 0x59, 0x54, 0x6C, 0xD4, 0x4A, 0x55, 0x24,
+ 0x35, 0x21, 0x60, 0x73, 0xDF, 0x6F, 0xE7, 0x3C,
+ 0xC2, 0xF0, 0xDA, 0xA9, 0xE5, 0x8C, 0xAC, 0xB6,
+ 0xFD, 0x2E, 0xF7, 0xA0, 0x18, 0xA7, 0x55, 0x47,
+ 0xD1, 0xCB, 0x9E, 0xAA, 0x58, 0x54, 0x3B, 0x37,
+ 0x18, 0xB5, 0xC1, 0xBB, 0x41, 0x59, 0xE4, 0x28,
+ 0x4A, 0x13, 0x90, 0x6A, 0xF7, 0xD1, 0xB3, 0x71,
+ 0xB6, 0x6E, 0xF6, 0x5D, 0x2E, 0x0E, 0x6C, 0x4A,
+ 0x7B, 0xF7, 0xB6, 0x21, 0xD4, 0xFC, 0x47, 0x8C,
+ 0x9B, 0x0A, 0x90, 0xAC, 0x11, 0x52, 0x86, 0x07,
+ 0x24, 0xDA, 0xA9, 0x49, 0x50, 0xD9, 0xDC, 0xE2,
+ 0x19, 0x87, 0x73, 0x88, 0xC3, 0xE4, 0xED, 0xC9,
+ 0x1C, 0xA8, 0x7E, 0x39, 0x48, 0x91, 0x10, 0xAB,
+ 0xFC, 0x3C, 0x1E, 0xEE, 0x08, 0xA1, 0xB9, 0xB2,
+ 0x02, 0x57, 0xB1, 0xD1, 0x35, 0x5E, 0x3D, 0x94,
+ 0xFB, 0x36, 0x27, 0x1A, 0x0E, 0x75, 0xFC, 0xBC,
+ 0xDB, 0xF3, 0xF5, 0x7C, 0x08, 0x39, 0xAA, 0xF4,
+ 0x2E, 0xEE, 0xCF, 0xCD, 0x2D, 0x70, 0xB8, 0x84,
+ 0xE6, 0x22, 0x5C, 0xC0, 0xB9, 0x33, 0xCB, 0x97,
+ 0xA1, 0xA3, 0xEE, 0x93, 0x71, 0xCF, 0xC9, 0x21,
+ 0x31, 0x7A, 0xEC, 0xE7, 0x70, 0xF2, 0xAA, 0x91,
+ 0xAA, 0x48, 0xAD, 0xAC, 0x03, 0xB1, 0x26, 0x52,
+ 0xBC, 0x65, 0x22, 0xA1, 0x09, 0x3D, 0xAB, 0x16,
+ 0x08, 0xBF, 0xCF, 0x3F, 0x59, 0x08, 0x6F, 0x68,
+ 0xEB, 0x8A, 0xB3, 0xCF, 0x77, 0x82, 0xFB, 0x25,
+ 0x78, 0x16, 0x4C, 0xDB, 0x72, 0xF5, 0xCF, 0x79,
+ 0x71, 0xE4, 0x4E, 0x23, 0x15, 0x7F, 0x1E, 0xA8,
+ 0x3E, 0xC0, 0x59, 0x91, 0x20, 0xAE, 0x2C, 0x1D,
+ 0x90, 0xC8, 0x49, 0x42, 0x48, 0x29, 0x82, 0x66,
+ 0x68, 0x49, 0x73, 0xDA, 0xE4, 0x28, 0xCD, 0x7B,
+ 0x4D, 0xE4, 0x23, 0x34, 0xB9, 0xE1, 0xB4, 0x42,
+ 0x67, 0x22, 0x5B, 0xEE, 0xE6, 0x74, 0x32, 0x6F,
+ 0x21, 0x9F, 0x97, 0x46, 0x03, 0xE1, 0xC9, 0x7A,
+ 0x14, 0x27, 0x30, 0xE1, 0xB2, 0x34, 0xE6, 0xAF,
+ 0x7B, 0xAA, 0xDD, 0x89, 0x04, 0x30, 0xD6, 0x78,
+ 0x0B, 0x3D, 0xC3, 0x69, 0xB0, 0x67, 0x4F, 0x4E,
+ 0x12, 0x21, 0x93, 0x2D, 0x79, 0xDD, 0x8B, 0xDB,
+ 0xEA, 0x90, 0x66, 0x54, 0xA8, 0x05, 0xF2, 0xE4,
+ 0x59, 0x8A, 0x96, 0x52, 0x30, 0xF0, 0x4E, 0x9A,
+ 0xE5, 0xD8, 0x72, 0x1C, 0x3B, 0x63, 0x02, 0xB9,
+ 0xC7, 0xA1, 0xDA, 0xC8, 0x6C, 0x48, 0xE0, 0xDE,
+ 0x59, 0x64, 0x89, 0x2C, 0xF9, 0xC8, 0x3B, 0x00,
+ 0xEC, 0xF2, 0x68, 0x51, 0x67, 0x05, 0x85, 0xAF,
+ 0xB8, 0xD5, 0x65, 0xEE, 0x73, 0x26, 0x88, 0xFB,
+ 0xA9, 0xD6, 0x6C, 0x68, 0x9D, 0x9F, 0x23, 0x6A,
+ 0x10, 0x24, 0x82, 0xB2, 0xB7, 0x40, 0x19, 0x3E,
+ 0x6F, 0xA2, 0xD5, 0x2C, 0x6E, 0x8D, 0xE9, 0x33,
+ 0x6E, 0x24, 0x94, 0x05, 0xE9, 0x2D, 0xD9, 0x3A,
+ 0x8C, 0xE5, 0xCC, 0x1D, 0x3F, 0xB8, 0x71, 0xA8,
+ 0x98, 0x33, 0xBB, 0x1A, 0xAC, 0x41, 0x0A, 0x04,
+ 0xFE, 0x4D, 0x46, 0x17, 0x8A, 0xCB, 0xF3, 0x4B,
+ 0x97, 0x02, 0xCC, 0x9D, 0x11, 0xF1, 0xBC, 0xA9,
+ 0xC1, 0xD1, 0xB6, 0xD6, 0x7B, 0x5F, 0x9D, 0x22,
+ 0x86, 0x71, 0xEC, 0x42, 0x53, 0xB7, 0x85, 0x30,
+ 0xAF, 0x1D, 0x01, 0xA7, 0xBF, 0x72, 0xC2, 0xC6,
+ 0xC9, 0xB8, 0xD8, 0xC7, 0xE9, 0xC4, 0xBA, 0xC5,
+ 0xB1, 0x8A, 0xB8, 0x62, 0xBF, 0x75, 0x75, 0x69,
+ 0xF8, 0x8D, 0x7E, 0xD9, 0xD2, 0x28, 0xB5, 0x40,
+ 0xCE, 0xCB, 0xB8, 0x74, 0x31, 0x40, 0x7B, 0x0D,
+ 0x73, 0x98, 0x99, 0x12, 0xB7, 0x75, 0x3E, 0xBC,
+ 0xAE, 0x48, 0xCA, 0xA9, 0x1E, 0xA7, 0x95, 0x31,
+ 0x87, 0x0F, 0x14, 0x52, 0xB6, 0x8E, 0x42, 0x50,
+ 0xB2, 0x76, 0x75, 0xD8, 0x7E, 0x66, 0x23, 0x13,
+ 0x8B, 0x29, 0xAA, 0x13, 0xCA, 0x8A, 0xD8, 0x9B,
+ 0x7B, 0x38, 0xD2, 0xE8, 0x67, 0xD1, 0x89, 0x25,
+ 0x9C, 0x63, 0x2F, 0xC3, 0x26, 0xC7, 0x74, 0x83,
+ 0x05, 0xED, 0x67, 0x02, 0x85, 0xAD, 0x1D, 0x0E,
+ 0xA9, 0xD6, 0xE1, 0xC7, 0x39, 0xA0, 0x6E, 0x72,
+ 0xCE, 0x56, 0x6C, 0xB8, 0x4A, 0xDE, 0x11, 0xA2,
+ 0xBF, 0xC1, 0x84, 0x98, 0x8F, 0xCA, 0x79, 0x74,
+ 0xCA, 0x9F, 0x45, 0x16, 0xBC, 0xB1, 0xF4, 0x03,
+ 0x76, 0x6E, 0xD5, 0x46, 0x60, 0xD7, 0x1D, 0xF0,
+ 0x87, 0x29, 0x63, 0x07, 0x06, 0xB9, 0xC2, 0x69,
+ 0x6D, 0xF9, 0x4B, 0x30, 0x96, 0x83, 0xB8, 0xC5,
+ 0xBE, 0x3A, 0xBA, 0xD0, 0x3E, 0x2B, 0x04, 0x16,
+ 0x6A, 0x00, 0x3B, 0x1A, 0x8E, 0xF8, 0xF6, 0x21,
+ 0x01, 0xD6, 0x08, 0x41, 0x74, 0xA2, 0xFC, 0x36,
+ 0xED, 0x11, 0x51, 0x5A, 0x4A, 0x21, 0x1A, 0x03,
+ 0x11, 0x95, 0x11, 0xF6, 0x73, 0x38, 0x67, 0xFC,
+ 0xF1, 0x2B, 0x22, 0x54, 0x65, 0x40, 0x7D, 0x8C,
+ 0x13, 0xC4, 0x46, 0x87, 0x09, 0x2B, 0xB5, 0xA1,
+ 0x82, 0x49, 0x46, 0x56, 0xF5, 0x5F, 0xF1, 0x04,
+ 0xD8, 0x6F, 0xDB, 0x38, 0xAD, 0xF4, 0x1A, 0xA3,
+ 0xFF, 0x7C, 0xC7, 0xA6, 0xAF, 0x87, 0x5C, 0x8C,
+ 0xEA, 0x3C, 0x9D, 0x7A, 0x4A, 0xD8, 0xA8, 0x66,
+ 0xDB, 0xBF, 0x12, 0x58, 0x98, 0x8E, 0xBA, 0x6F,
+ 0xAF, 0x20, 0xDA, 0xEE, 0x82, 0x34, 0x2F, 0x33,
+ 0x88, 0x98, 0xBA, 0xB2, 0x54, 0x7F, 0x9E, 0x63,
+ 0x19, 0x6C, 0x7D, 0xCE, 0x85, 0xF8, 0xB6, 0x77,
+ 0xCB, 0x38, 0x1F, 0xB1, 0x79, 0xBD, 0xED, 0x32,
+ 0xE3, 0xB9, 0x40, 0xEF, 0x3E, 0x6C, 0x29, 0x88,
+ 0x70, 0x99, 0x47, 0xA6, 0x4A, 0x1C, 0xCC, 0x0B,
+ 0x9B, 0x72, 0xA9, 0x29, 0x83, 0x4C, 0xDE, 0x4F,
+ 0x65, 0x4E, 0xCE, 0xBD, 0xFA, 0x76, 0x8D, 0xA6,
+ 0x1A, 0xD8, 0x66, 0xFE, 0xA4, 0x2A, 0x61, 0x50,
+ 0xEE, 0x15, 0xF1, 0xF0, 0x9D, 0xFF, 0xEC, 0xEE,
+ 0x00, 0x03, 0xFE, 0xAC, 0x53, 0x02, 0xCC, 0x87,
+ 0xB1, 0xA2, 0xD8, 0x34, 0x2C, 0xEC, 0xA6, 0x4C,
+ 0x02, 0xC0, 0xC1, 0x72, 0xD6, 0x54, 0x35, 0x24,
+ 0x25, 0x8B, 0xEC, 0xDA, 0x47, 0x5F, 0x5D, 0x7E,
+ 0xD8, 0x01, 0x51, 0xDD, 0x8F, 0xB4, 0x48, 0xDD,
+ 0x94, 0x99, 0x95, 0x77, 0xB3, 0x42, 0x14, 0xEB,
+ 0x26, 0x61, 0xE9, 0x22, 0xE3, 0x07, 0x73, 0xFB,
+ 0xEF, 0x38, 0x55, 0x35, 0x8F, 0xCC, 0x30, 0x1E,
+ 0x38, 0xE0, 0x35, 0xF4, 0x9A, 0x7C, 0xCF, 0x38,
+ 0x0B, 0x9E, 0xF4, 0x88, 0x4A, 0xEA, 0xF2, 0x67,
+ 0x9F, 0x61, 0x40, 0x34, 0x09, 0xDC, 0xBF, 0xFB,
+ 0x22, 0x27, 0x04, 0x8B, 0x8D, 0x85, 0x7F, 0xB2,
+ 0x29, 0x62, 0x25, 0x73, 0x7F, 0x46, 0x2E, 0xA3,
+ 0x8E, 0xAF, 0xEC, 0x55, 0x98, 0x1A, 0xEE, 0x29,
+ 0xA0, 0x1A, 0x5F, 0xFE, 0x5D, 0xA5, 0x76, 0x93,
+ 0xAB, 0x57, 0x56, 0xEA, 0xDB, 0x39, 0xAC, 0x48,
+ 0xBE, 0x95, 0x92, 0x2B, 0xC6, 0xE1, 0x2F, 0x36,
+ 0x4B, 0x08, 0x01, 0x90, 0x50, 0xD8, 0xFA, 0xF9,
+ 0x94, 0x4E, 0x76, 0x9B, 0x72, 0x59, 0xC2, 0x2F,
+ 0x61, 0x04, 0x0A, 0x9E, 0x28, 0xE5, 0x24, 0x1E,
+ 0x79, 0xCF, 0x8D, 0xB6, 0x52, 0xA7, 0x79, 0x5F,
+ 0x44, 0x98, 0xD5, 0x0E, 0x6E, 0x4B, 0x64, 0x9B,
+ },
+ .len = 2048
+ },
+ .auth_tags[0] = {
+ .size = 64,
+ .data = { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
+ 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
+ .len = 16
+ },
+ .auth_tags[1] = {
+ .size = 128,
+ .data = { 0xE9, 0xA9, 0x75, 0xB6, 0xEF, 0x6F, 0x8C, 0xF1,
+ 0xB3, 0xA9, 0x19, 0xA4, 0xAE, 0x66, 0xBD, 0x9E },
+ .len = 16
+ },
+ .auth_tags[2] = {
+ .size = 256,
+ .data = { 0x29, 0xC3, 0x18, 0x96, 0x54, 0xCB, 0xF5, 0xAA,
+ 0x4E, 0x62, 0xB6, 0xFF, 0x45, 0xA6, 0x18, 0x0C },
+ .len = 16
+ },
+ .auth_tags[3] = {
+ .size = 512,
+ .data = { 0x3B, 0xD7, 0xC3, 0x5F, 0xE4, 0x1B, 0xC2, 0xBC,
+ 0xE9, 0xAC, 0xF2, 0xCE, 0xA7, 0x7B, 0x1D, 0x70 },
+ .len = 16
+ },
+ .auth_tags[4] = {
+ .size = 1024,
+ .data = { 0xCC, 0xBB, 0xBC, 0xCF, 0x86, 0x01, 0x4D, 0x93,
+ 0x4B, 0x68, 0x55, 0x19, 0xA1, 0x40, 0xCD, 0xEA },
+ .len = 16
+ },
+ .auth_tags[5] = {
+ .size = 1536,
+ .data = { 0x67, 0x31, 0x11, 0xA2, 0x58, 0xB5, 0x1C, 0x23,
+ 0xC0, 0x41, 0x05, 0x30, 0xC6, 0xBA, 0xFA, 0x88 },
+ .len = 16
+ },
+ .auth_tags[6] = {
+ .size = 2048,
+ .data = { 0x03, 0x9C, 0x6B, 0xB9, 0x57, 0xBF, 0x6E, 0x86,
+ 0x3A, 0x09, 0x5F, 0x08, 0xA9, 0xE4, 0xF2, 0x1F },
+ .len = 16
+ },
+ .auth_tag = {
+ .data = {
+ 0x03, 0x9C, 0x6B, 0xB9, 0x57, 0xBF, 0x6E, 0x86,
+ 0x3A, 0x09, 0x5F, 0x08, 0xA9, 0xE4, 0xF2, 0x1F
+ },
+ .len = 16
+ },
+};
+
+static const struct gmac_test_data gmac_test_case_4 = {
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = gmac_plaintext,
+ .len = GMAC_LARGE_PLAINTEXT_LENGTH
+ },
+ .gmac_tag = {
+ .data = {
+ 0x3f, 0x07, 0xcb, 0xb9, 0x86, 0x3a, 0xea, 0xc2,
+ 0x2f, 0x3a, 0x2a, 0x93, 0xd8, 0x09, 0x6b, 0xda
+ },
+ .len = 16
+ }
+};
+
+static const struct aead_test_data gcm_test_case_SGL_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .key = {
+ .data = {
+ 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ .len = 12
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x54,
+ 0xd7, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9c,
+ 0xd8, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
+ 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9b,
+ 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+ 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
+ 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
+ 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
+ 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
+
+ },
+ .len = 3120
+ },
+ .ciphertext = {
+ .data = {
+ 0x42, 0x83, 0x1E, 0xC2, 0x21, 0x77, 0x74, 0x24,
+ 0x4B, 0x72, 0x21, 0xB7, 0x84, 0xD0, 0xD4, 0x9C,
+ 0xE3, 0xAA, 0x21, 0x2F, 0x2C, 0x02, 0xA4, 0xE0,
+ 0x35, 0xC1, 0x7E, 0x23, 0x29, 0xAC, 0xA1, 0x2E,
+ 0x21, 0xD5, 0x14, 0xB2, 0x54, 0x66, 0x93, 0x1C,
+ 0x7D, 0x8F, 0x6A, 0x5A, 0xAC, 0x84, 0xAA, 0x05,
+ 0x1B, 0xA3, 0x0B, 0x39, 0x6A, 0x0A, 0xAC, 0x97,
+ 0x3D, 0x58, 0xE0, 0x91, 0x47, 0x3F, 0x59, 0x85,
+ 0x05, 0x99, 0x55, 0xE1, 0x36, 0x76, 0xB7, 0x14,
+ 0x1D, 0xF0, 0xF6, 0x8C, 0x65, 0xD5, 0xAD, 0xFA,
+ 0x90, 0x7F, 0x5D, 0xA2, 0xD6, 0xFD, 0xD0, 0xE5,
+ 0x0D, 0x9B, 0x68, 0x21, 0x49, 0x42, 0x6E, 0x13,
+ 0xEC, 0x22, 0x50, 0x2A, 0x30, 0x47, 0x49, 0xA1,
+ 0x7F, 0xC3, 0x09, 0xE0, 0x56, 0x91, 0xC4, 0x54,
+ 0x70, 0xD7, 0x19, 0x40, 0xCA, 0x6B, 0x65, 0x27,
+ 0x3E, 0xE9, 0xD1, 0x0F, 0x1C, 0xB5, 0x45, 0x0C,
+ 0x29, 0xE7, 0xCF, 0x94, 0x10, 0xBF, 0xA2, 0xFA,
+ 0x86, 0x20, 0x3F, 0x6E, 0xE9, 0x95, 0x03, 0x5C,
+ 0x46, 0x11, 0x75, 0xD5, 0x37, 0x71, 0x7F, 0xE0,
+ 0xBC, 0x9F, 0xC8, 0xE9, 0xB1, 0x08, 0x2C, 0x59,
+ 0x6E, 0x51, 0x4A, 0x83, 0x38, 0xC1, 0xED, 0xE2,
+ 0x2E, 0x88, 0x90, 0xA5, 0x7D, 0xA4, 0x93, 0x9A,
+ 0x30, 0xD6, 0x96, 0x34, 0x0F, 0xC4, 0xD1, 0x7E,
+ 0xC9, 0x8F, 0xC5, 0xBB, 0x80, 0x50, 0x85, 0x73,
+ 0x8B, 0x7C, 0x0A, 0xDA, 0xD3, 0x37, 0x1C, 0x8B,
+ 0x1E, 0xAE, 0x29, 0x54, 0x05, 0x53, 0x48, 0xE5,
+ 0x94, 0xF1, 0xC5, 0x1A, 0x60, 0xDC, 0x61, 0x43,
+ 0xCD, 0x45, 0x4C, 0x6B, 0x95, 0xAD, 0x52, 0xE0,
+ 0x9E, 0xD1, 0x4E, 0xCC, 0x03, 0x27, 0x50, 0xD4,
+ 0xEB, 0xBD, 0x71, 0xA6, 0xD0, 0x2B, 0x23, 0xC0,
+ 0x9E, 0x5F, 0x34, 0xFD, 0xDE, 0xC1, 0x43, 0x35,
+ 0x77, 0xFB, 0xFD, 0xDF, 0xA0, 0x28, 0x42, 0x3B,
+ 0x0F, 0x2D, 0x31, 0xB4, 0x7A, 0xA8, 0x2F, 0xDF,
+ 0x58, 0xB5, 0x00, 0x19, 0x8D, 0xEB, 0x2C, 0xBB,
+ 0xAE, 0xAD, 0x74, 0x7F, 0x25, 0xAA, 0x24, 0x3E,
+ 0xCD, 0x89, 0x5E, 0x05, 0xD3, 0xBA, 0x0E, 0x9A,
+ 0x34, 0x7B, 0xE0, 0x11, 0xD2, 0xBA, 0x5A, 0x51,
+ 0xB4, 0x0D, 0xEE, 0x61, 0x73, 0xFC, 0xD2, 0x01,
+ 0x2D, 0x52, 0x3E, 0x37, 0x55, 0x3F, 0x58, 0xA8,
+ 0x1C, 0x8F, 0x1D, 0xD6, 0x3C, 0x39, 0x06, 0x18,
+ 0x65, 0x60, 0x55, 0x19, 0xAD, 0x1E, 0x78, 0xE9,
+ 0xF7, 0xF5, 0xFC, 0xCD, 0x5F, 0xF1, 0x34, 0x0C,
+ 0xA6, 0xFD, 0x1E, 0x9E, 0xB3, 0xCE, 0x2E, 0x10,
+ 0xFB, 0x98, 0xDD, 0x0E, 0x09, 0x5D, 0x4E, 0x58,
+ 0x75, 0x9A, 0x54, 0x74, 0xFB, 0x40, 0x76, 0x55,
+ 0x0E, 0x3E, 0xA4, 0xCE, 0x56, 0xA5, 0xE0, 0x53,
+ 0xB7, 0xAD, 0x36, 0x99, 0x6E, 0xCD, 0xC2, 0x90,
+ 0x6E, 0xEA, 0xBC, 0x21, 0xAC, 0x31, 0xFF, 0x2B,
+ 0x00, 0xA7, 0x5E, 0xC1, 0x7A, 0xF1, 0xAB, 0x24,
+ 0xA3, 0x40, 0x0B, 0xEB, 0x16, 0x62, 0x35, 0x1E,
+ 0xE9, 0xA5, 0xD3, 0x7E, 0xAA, 0x7E, 0x28, 0xA8,
+ 0x3F, 0xD8, 0x0A, 0x04, 0x12, 0x0F, 0xFF, 0x68,
+ 0x10, 0x85, 0x22, 0xD6, 0x05, 0x6A, 0x3A, 0xCB,
+ 0xC0, 0xCF, 0x8C, 0x20, 0xF0, 0x34, 0x32, 0xAA,
+ 0x76, 0x93, 0xE2, 0x23, 0x4F, 0xF2, 0xE6, 0x84,
+ 0x3B, 0xD4, 0xF3, 0x5D, 0xF3, 0x17, 0xEE, 0x27,
+ 0x67, 0xC3, 0x01, 0x6F, 0x32, 0xDE, 0xF6, 0xF6,
+ 0x87, 0xE9, 0x82, 0xEF, 0x1F, 0xA1, 0xE2, 0x68,
+ 0xF8, 0x5D, 0x49, 0x92, 0x47, 0x01, 0x75, 0x87,
+ 0x52, 0xD3, 0x54, 0xAE, 0x3B, 0xB7, 0xB2, 0x07,
+ 0x0F, 0x62, 0x7B, 0xF7, 0x50, 0x97, 0x9A, 0x4A,
+ 0x98, 0x65, 0x23, 0xA3, 0x5D, 0x76, 0x0A, 0x9C,
+ 0x6C, 0xE7, 0x89, 0xAD, 0x86, 0x70, 0xE7, 0x16,
+ 0x5F, 0x2F, 0x2E, 0x97, 0x29, 0x31, 0xF0, 0x60,
+ 0x33, 0x2C, 0xD7, 0xAA, 0xD6, 0xF0, 0x50, 0xB8,
+ 0xBD, 0x29, 0xA8, 0xA9, 0xAC, 0x5E, 0x0A, 0x3A,
+ 0x59, 0x34, 0x9A, 0x92, 0x25, 0x71, 0xB3, 0x16,
+ 0xC5, 0xD3, 0xA4, 0x15, 0x75, 0x9A, 0xB5, 0x78,
+ 0x6E, 0xCF, 0xAF, 0xC0, 0x39, 0x28, 0x44, 0x21,
+ 0xBB, 0xE8, 0x32, 0xAB, 0xCB, 0xF8, 0x4B, 0xE7,
+ 0x63, 0x9C, 0x56, 0xE7, 0xB2, 0xD6, 0x23, 0x17,
+ 0xDE, 0x92, 0xE9, 0x22, 0xC3, 0x36, 0xA5, 0xAC,
+ 0xA9, 0x98, 0x34, 0xAA, 0xFB, 0x03, 0x33, 0x33,
+ 0xBE, 0xD8, 0x22, 0x7F, 0xFA, 0x34, 0xA0, 0x35,
+ 0xC8, 0xA0, 0xDC, 0x35, 0x82, 0x06, 0x58, 0xE6,
+ 0xBF, 0x7C, 0x4F, 0x63, 0x5D, 0x62, 0x64, 0x67,
+ 0x0D, 0x07, 0x7F, 0x24, 0x4A, 0x23, 0xBC, 0x35,
+ 0xE0, 0x92, 0x6F, 0x51, 0xE7, 0x25, 0x97, 0xB9,
+ 0x14, 0x35, 0x2B, 0x48, 0xAC, 0x6F, 0x54, 0xDF,
+ 0xF2, 0xB4, 0xB0, 0xE0, 0xD3, 0x28, 0x0D, 0x67,
+ 0x48, 0x28, 0x0A, 0x16, 0x9C, 0x87, 0x73, 0xB7,
+ 0x9C, 0x2B, 0xB5, 0x43, 0xC9, 0x46, 0xB9, 0x19,
+ 0x01, 0xAA, 0xDE, 0x75, 0xA6, 0x0F, 0xB5, 0x72,
+ 0x6A, 0x51, 0xE3, 0xAC, 0xE0, 0xF6, 0x96, 0x13,
+ 0xBB, 0xC7, 0x08, 0x13, 0x9E, 0x47, 0xAA, 0xF5,
+ 0x9E, 0x69, 0xAC, 0x95, 0x29, 0xFE, 0xFF, 0x99,
+ 0xB2, 0x52, 0x72, 0x45, 0xF2, 0x07, 0xEB, 0x3C,
+ 0x0F, 0x75, 0x29, 0x73, 0x0D, 0x77, 0x58, 0x83,
+ 0xCB, 0xDD, 0xE7, 0x68, 0x1C, 0xE3, 0xD1, 0xA4,
+ 0x5D, 0xD1, 0xAB, 0xB4, 0x5A, 0x3F, 0x27, 0x66,
+ 0xDA, 0xB4, 0x81, 0x65, 0xCE, 0x1A, 0x9A, 0x7D,
+ 0xC7, 0xB6, 0x31, 0xDE, 0x83, 0xC2, 0x7C, 0xF8,
+ 0xD3, 0xC7, 0x97, 0x28, 0x50, 0xF2, 0x95, 0xFC,
+ 0xA7, 0xB2, 0xA6, 0x46, 0xEF, 0x10, 0xD2, 0x38,
+ 0x93, 0x14, 0x8D, 0xA7, 0x09, 0x17, 0x42, 0x7A,
+ 0x85, 0xB9, 0x42, 0x71, 0x2A, 0x51, 0x9B, 0x66,
+ 0x71, 0x12, 0x57, 0xB7, 0xBD, 0x26, 0xB7, 0x91,
+ 0xF8, 0x84, 0x44, 0x35, 0xAD, 0x6F, 0xCB, 0xD7,
+ 0xFC, 0xA1, 0x28, 0x77, 0x09, 0x5B, 0x6D, 0x52,
+ 0x43, 0xA1, 0xE2, 0x0A, 0x7E, 0x5A, 0x84, 0x45,
+ 0x20, 0xDE, 0xA5, 0x73, 0x1D, 0x37, 0x6E, 0xD8,
+ 0x7A, 0x0D, 0x91, 0xBE, 0xF4, 0xB3, 0x89, 0xE9,
+ 0x1F, 0x1E, 0xF6, 0xD5, 0x37, 0xB4, 0x3C, 0x1D,
+ 0xBE, 0x0D, 0x5B, 0x01, 0xB0, 0x8B, 0xCE, 0x3E,
+ 0x6D, 0x8B, 0x99, 0x9A, 0xC5, 0xAE, 0xFE, 0xA9,
+ 0x78, 0x34, 0x20, 0xA7, 0x6C, 0x7D, 0x46, 0x72,
+ 0x37, 0xAF, 0xFD, 0x17, 0x59, 0xED, 0x83, 0x5B,
+ 0xEB, 0x6E, 0x4A, 0xF1, 0xE6, 0x0D, 0x44, 0x92,
+ 0x65, 0x8E, 0x97, 0xD6, 0x83, 0x6E, 0x97, 0xCA,
+ 0x4C, 0x0A, 0xCE, 0x32, 0x2A, 0xAD, 0x22, 0x73,
+ 0xCB, 0xCB, 0xC3, 0x55, 0x08, 0x63, 0x23, 0xC2,
+ 0x31, 0x24, 0x90, 0x54, 0x99, 0xB2, 0x8C, 0xC7,
+ 0x8A, 0xB6, 0xFF, 0xC2, 0x75, 0xB1, 0xD9, 0x3D,
+ 0x95, 0xDC, 0xB6, 0xCF, 0x11, 0x74, 0x06, 0x54,
+ 0x03, 0xE3, 0x9B, 0x49, 0xE4, 0xF2, 0x73, 0x04,
+ 0xF7, 0xDC, 0x71, 0xD7, 0xFA, 0x3C, 0xD2, 0x61,
+ 0x77, 0x61, 0xB3, 0xDB, 0x6B, 0xCE, 0xCA, 0xFF,
+ 0xF0, 0xAD, 0xBC, 0x94, 0xC8, 0xF8, 0xD5, 0xF4,
+ 0x38, 0xA3, 0x61, 0xAA, 0x8C, 0x96, 0xEE, 0x56,
+ 0xAC, 0xB4, 0x42, 0xBA, 0x1A, 0xE1, 0x70, 0x98,
+ 0x1F, 0x9A, 0x6F, 0x98, 0xB9, 0x13, 0x46, 0xAB,
+ 0x0B, 0xCD, 0xA3, 0x7B, 0x0C, 0xCB, 0x8F, 0x72,
+ 0x23, 0xCF, 0x9E, 0xD8, 0xBB, 0x3F, 0x32, 0x27,
+ 0x54, 0xB8, 0x60, 0x64, 0x83, 0xAE, 0x22, 0xD1,
+ 0x6A, 0xC9, 0xF8, 0x13, 0xC4, 0xE4, 0xFF, 0x97,
+ 0xD8, 0x92, 0xA3, 0xD1, 0xD4, 0x86, 0xD7, 0xC3,
+ 0xBB, 0x40, 0xA2, 0x45, 0x78, 0xB1, 0xDB, 0x80,
+ 0xC6, 0x8D, 0x0A, 0xF0, 0xC3, 0xC2, 0xE3, 0x48,
+ 0xA1, 0x05, 0xC2, 0x32, 0xC8, 0x6C, 0x50, 0xA8,
+ 0x06, 0x58, 0xBE, 0x6C, 0x7D, 0x22, 0xD6, 0x0D,
+ 0x74, 0x40, 0xCE, 0xD6, 0x64, 0xD6, 0x47, 0xD0,
+ 0xBF, 0xF1, 0x5C, 0x54, 0xF9, 0x06, 0x3F, 0x3D,
+ 0x86, 0xBA, 0xF2, 0x0F, 0x5E, 0x2C, 0x01, 0xCC,
+ 0xD9, 0xC7, 0xB1, 0x4A, 0xB3, 0xD7, 0x26, 0xCC,
+ 0xC3, 0x7A, 0x74, 0x2C, 0xE1, 0x22, 0x65, 0xA0,
+ 0x5B, 0xCA, 0xF4, 0xE1, 0x7D, 0xE1, 0x56, 0xFD,
+ 0x95, 0x10, 0xC6, 0xA1, 0x4A, 0xE8, 0x6B, 0x34,
+ 0x4E, 0x71, 0x60, 0x77, 0x0F, 0x03, 0xDD, 0xFE,
+ 0xC8, 0x59, 0x54, 0x6C, 0xD4, 0x4A, 0x55, 0x24,
+ 0x35, 0x21, 0x60, 0x73, 0xDF, 0x6F, 0xE7, 0x3C,
+ 0xC2, 0xF0, 0xDA, 0xA9, 0xE5, 0x8C, 0xAC, 0xB6,
+ 0xFD, 0x2E, 0xF7, 0xA0, 0x18, 0xA7, 0x55, 0x47,
+ 0xD1, 0xCB, 0x9E, 0xAA, 0x58, 0x54, 0x3B, 0x37,
+ 0x18, 0xB5, 0xC1, 0xBB, 0x41, 0x59, 0xE4, 0x29,
+ 0x44, 0x13, 0x90, 0x6A, 0xF7, 0xD1, 0xB3, 0x71,
+ 0xB6, 0x6E, 0xF6, 0x5D, 0x2E, 0x0E, 0x6C, 0x4C,
+ 0x7B, 0xF7, 0xB6, 0x21, 0xD4, 0xFC, 0x47, 0x8C,
+ 0x9B, 0x0A, 0x90, 0xAC, 0x11, 0x52, 0x86, 0x07,
+ 0x24, 0xDA, 0xA9, 0x49, 0x50, 0xD9, 0xDC, 0xE2,
+ 0x19, 0x87, 0x73, 0x88, 0xC3, 0xE4, 0xED, 0xC9,
+ 0x1C, 0xA8, 0x7E, 0x39, 0x48, 0x91, 0x10, 0xAB,
+ 0xFC, 0x3C, 0x1E, 0xEE, 0x08, 0xA1, 0xB9, 0xB4,
+ 0xF4, 0xA9, 0x8D, 0xD0, 0x84, 0x7C, 0x8E, 0x54,
+ 0xEF, 0x05, 0xC3, 0x2A, 0x0B, 0x8D, 0x3C, 0x71,
+ 0xE7, 0x37, 0x27, 0x16, 0x07, 0xA2, 0x8F, 0x7A,
+ 0x86, 0x05, 0x56, 0xA3, 0xB2, 0x75, 0xC5, 0x2C,
+ 0xD4, 0x52, 0x60, 0x68, 0xA6, 0x6A, 0x48, 0xB6,
+ 0x92, 0x50, 0xEC, 0x22, 0xAD, 0x01, 0x75, 0x57,
+ 0xAF, 0xDF, 0x0F, 0x36, 0x93, 0x59, 0xF9, 0xE3,
+ 0xA1, 0x41, 0x3B, 0x60, 0xB3, 0x13, 0x12, 0x50,
+ 0x4B, 0x18, 0x20, 0xB9, 0x7B, 0x88, 0x27, 0x81,
+ 0xB1, 0xDA, 0xCA, 0x6F, 0x63, 0x95, 0x40, 0xA1,
+ 0x42, 0xE2, 0x14, 0xB8, 0x2B, 0x10, 0xB9, 0xDA,
+ 0xE7, 0x30, 0x91, 0x13, 0x52, 0xC9, 0xA3, 0x5C,
+ 0xD7, 0xBB, 0x39, 0x8F, 0x9A, 0xB8, 0xC5, 0xAF,
+ 0xC6, 0x3E, 0x65, 0x90, 0x91, 0x8C, 0x9F, 0xDD,
+ 0x84, 0xFB, 0xAD, 0x72, 0x4D, 0xD1, 0x42, 0xAD,
+ 0x0A, 0x1B, 0x3A, 0xC6, 0x06, 0x03, 0x19, 0xCB,
+ 0x31, 0x8C, 0x18, 0xD4, 0xEE, 0x90, 0x94, 0x3C,
+ 0x44, 0xDC, 0xFB, 0x78, 0x5C, 0xB5, 0xE3, 0x2F,
+ 0x89, 0x74, 0x0E, 0x28, 0x9C, 0xE4, 0xB4, 0xD2,
+ 0xE3, 0x5A, 0x32, 0xF9, 0xC0, 0x81, 0x6A, 0x38,
+ 0xC2, 0xCF, 0xD8, 0xD9, 0x3E, 0xAD, 0xF9, 0xB1,
+ 0xA2, 0x55, 0x64, 0x1E, 0xEC, 0xF5, 0x0D, 0xB1,
+ 0x8D, 0x07, 0x4E, 0xE5, 0x59, 0xE1, 0xE7, 0xFE,
+ 0x4C, 0xCF, 0x11, 0xF8, 0x27, 0xC2, 0x29, 0xE2,
+ 0xAF, 0x74, 0xAA, 0x53, 0x81, 0xD2, 0xFD, 0x5A,
+ 0xF1, 0xEB, 0x96, 0x2C, 0x3E, 0x9B, 0xC2, 0x74,
+ 0xFB, 0x65, 0x08, 0xA2, 0x63, 0xD3, 0xC5, 0x51,
+ 0xAF, 0x19, 0x8B, 0x34, 0x8B, 0x7D, 0xB7, 0x97,
+ 0x55, 0x97, 0x6D, 0x01, 0x5D, 0x98, 0xAA, 0x67,
+ 0x11, 0xBD, 0xC2, 0x99, 0x2F, 0xB4, 0xCA, 0x04,
+ 0x36, 0xF0, 0xB1, 0xA0, 0xBD, 0xA3, 0x4F, 0x4F,
+ 0xB6, 0x7B, 0xF5, 0x1E, 0x38, 0x87, 0xC2, 0x38,
+ 0x99, 0x5C, 0xE9, 0x2D, 0xDF, 0xAF, 0x5A, 0xF3,
+ 0x7A, 0x17, 0x70, 0x35, 0xEC, 0xD5, 0x19, 0xF7,
+ 0xB0, 0x21, 0x1E, 0x77, 0x30, 0x23, 0x54, 0x26,
+ 0x61, 0x4E, 0xB9, 0x02, 0xDE, 0xF4, 0x86, 0x93,
+ 0x47, 0x28, 0x43, 0x47, 0xB0, 0x56, 0xDC, 0x84,
+ 0x3E, 0x6A, 0x6B, 0xEA, 0x4D, 0x63, 0xFE, 0x56,
+ 0x5E, 0xF7, 0x6B, 0x1E, 0x5B, 0x63, 0xF1, 0x07,
+ 0x20, 0x2E, 0x9B, 0xEE, 0xDC, 0x70, 0x5E, 0x36,
+ 0x59, 0xE3, 0x3D, 0xA6, 0x0E, 0x50, 0x71, 0x06,
+ 0xDD, 0x8B, 0x3C, 0xF7, 0xEC, 0x3C, 0x7A, 0x08,
+ 0x8D, 0x4E, 0x6A, 0x08, 0xB0, 0xEE, 0x50, 0xE0,
+ 0xF9, 0x0E, 0x40, 0xC0, 0x11, 0xBF, 0x8A, 0x17,
+ 0x63, 0x9D, 0x59, 0x14, 0x0E, 0x25, 0x94, 0x09,
+ 0xE6, 0x34, 0xEC, 0x0F, 0xE4, 0x7C, 0x59, 0xCD,
+ 0x99, 0x85, 0x8E, 0x0F, 0xA1, 0x9E, 0x84, 0xBC,
+ 0x13, 0x20, 0x5F, 0x56, 0x26, 0x10, 0x1A, 0x77,
+ 0x77, 0x7B, 0x4B, 0x68, 0x13, 0x8A, 0x2C, 0xA5,
+ 0x01, 0xBF, 0xAD, 0xF2, 0x2C, 0xD9, 0x4B, 0x24,
+ 0x4C, 0xF5, 0x96, 0x4E, 0xD8, 0xE8, 0x98, 0xA8,
+ 0x9C, 0x63, 0x2F, 0xC3, 0x26, 0xC7, 0x74, 0x83,
+ 0x05, 0xED, 0x67, 0x02, 0x85, 0xAD, 0x1D, 0x0E,
+ 0xA9, 0xD6, 0xE1, 0xC7, 0x39, 0xA0, 0x6E, 0x72,
+ 0xCE, 0x56, 0x6C, 0xB8, 0x4A, 0xDE, 0x11, 0xA2,
+ 0xBF, 0xC1, 0x84, 0x98, 0x8F, 0xCA, 0x79, 0x75,
+ 0xC4, 0x9F, 0x45, 0x16, 0xBC, 0xB1, 0xF4, 0x03,
+ 0x76, 0x6E, 0xD5, 0x46, 0x60, 0xD7, 0x1D, 0xF6,
+ 0xD9, 0xBF, 0xF8, 0x71, 0xEB, 0x09, 0x33, 0x56,
+ 0xE6, 0xEC, 0x72, 0xC8, 0xB3, 0x47, 0x14, 0x2C,
+ 0x24, 0xA1, 0x1F, 0x16, 0xBE, 0x77, 0xFA, 0x9F,
+ 0x6B, 0x83, 0x05, 0x03, 0x4D, 0x6F, 0xC9, 0x76,
+ 0x69, 0x8D, 0xD7, 0x91, 0x26, 0x2B, 0x1C, 0x84,
+ 0xF2, 0x2B, 0x23, 0xA6, 0xFF, 0x7B, 0xEE, 0xCC,
+ 0x4E, 0x03, 0x8A, 0x80, 0x9E, 0x88, 0x96, 0xC3,
+ 0x7A, 0x3E, 0x1B, 0xAC, 0x40, 0x84, 0xD1, 0x64,
+ 0x89, 0x5F, 0xE3, 0x41, 0x89, 0x77, 0x4B, 0x28,
+ 0x83, 0xCA, 0x78, 0x4F, 0x36, 0xC8, 0xCE, 0x53,
+ 0x75, 0x39, 0x3A, 0x58, 0x92, 0x91, 0xF5, 0xA7,
+ 0x6A, 0xD0, 0xB2, 0xBB, 0xFC, 0x8E, 0x3B, 0xFC,
+ 0x83, 0x67, 0x42, 0xAA, 0x18, 0x51, 0x48, 0xD4,
+ 0xC4, 0x85, 0x60, 0xA4, 0x2D, 0xD4, 0x4E, 0xA1,
+ 0xF0, 0xB6, 0x41, 0x98, 0x6F, 0x84, 0xDE, 0x0C,
+ 0x03, 0x8D, 0x83, 0x4A, 0x71, 0xBB, 0x32, 0x8B,
+ 0x83, 0xF7, 0xD8, 0x08, 0x05, 0xA4, 0x48, 0xFE,
+ 0xCA, 0xBB, 0x21, 0xA8, 0xBA, 0x2A, 0xD2, 0x65,
+ 0x4E, 0xEF, 0xA1, 0x8F, 0x01, 0x09, 0xC6, 0x8C,
+ 0xE5, 0x35, 0x32, 0xBB, 0x19, 0x15, 0xAB, 0x7A,
+ 0xFD, 0x29, 0x76, 0xF9, 0xD1, 0xC5, 0x3E, 0xFD,
+ 0x7A, 0x74, 0xBC, 0x41, 0x4F, 0x2C, 0x79, 0x6F,
+ 0x45, 0x4E, 0xFD, 0x88, 0x49, 0x9A, 0x90, 0x6F,
+ 0x65, 0x00, 0xC8, 0x08, 0xB8, 0x3B, 0x40, 0x06,
+ 0x9A, 0x98, 0x5B, 0x6A, 0xD3, 0x5E, 0x32, 0x0E,
+ 0xB0, 0x21, 0xE6, 0x2D, 0xEF, 0x7B, 0x99, 0x1B,
+ 0xAF, 0x96, 0x20, 0x12, 0xE9, 0x31, 0xDA, 0x20,
+ 0xB0, 0x27, 0x99, 0xC7, 0x14, 0x56, 0x3A, 0x08,
+ 0x46, 0xA4, 0xB2, 0x0C, 0x6C, 0x1F, 0x1B, 0xAF,
+ 0x9F, 0x90, 0x03, 0xBB, 0x03, 0xE0, 0x20, 0xE9,
+ 0x45, 0x33, 0xA0, 0x3E, 0x01, 0x2C, 0xA7, 0x4A,
+ 0xCC, 0xC6, 0xF5, 0xA3, 0x35, 0x0D, 0xE1, 0x5E,
+ 0x90, 0x0B, 0xAC, 0x9A, 0x05, 0x79, 0xB2, 0x90,
+ 0x39, 0xEE, 0xC8, 0x20, 0x55, 0xB3, 0x71, 0x46,
+ 0xAC, 0x92, 0x42, 0x85, 0xD5, 0x12, 0x03, 0x8D,
+ 0xBC, 0x82, 0xE7, 0x5A, 0x6E, 0x2E, 0x2C, 0xC0,
+ 0xB6, 0x44, 0xF8, 0xBB, 0x5F, 0x7A, 0x42, 0x86,
+ 0x28, 0xF0, 0x9B, 0xF9, 0x17, 0xDD, 0x35, 0x2F,
+ 0x56, 0xE4, 0x63, 0xFF, 0xEC, 0x87, 0xC5, 0x53,
+ 0xBF, 0x64, 0xB2, 0xDA, 0xDE, 0xC1, 0x6C, 0x85,
+ 0x82, 0x51, 0x40, 0x41, 0xC9, 0x7A, 0x0A, 0xB8,
+ 0xB2, 0x75, 0x03, 0x88, 0x22, 0x6D, 0x76, 0x6E,
+ 0x2D, 0x2B, 0x73, 0xCB, 0x48, 0xC4, 0xED, 0xE0,
+ 0x96, 0xFA, 0x36, 0x9F, 0x99, 0xC7, 0x97, 0xDE,
+ 0x6D, 0xFC, 0x69, 0x86, 0x57, 0x5F, 0xB9, 0x93,
+ 0x78, 0x5C, 0x07, 0x64, 0x61, 0xD0, 0x41, 0x14,
+ 0x32, 0xED, 0xC0, 0xE4, 0xAC, 0xFC, 0x10, 0x0D,
+ 0xAF, 0xEE, 0xDA, 0xB3, 0x6D, 0xB8, 0x7C, 0x10,
+ 0xD5, 0x3B, 0x88, 0xE1, 0x15, 0xE1, 0xA4, 0x27,
+ 0xFE, 0xEE, 0x0A, 0xC8, 0x95, 0xCF, 0xCA, 0x99,
+ 0x98, 0x1D, 0xF3, 0x0E, 0xB8, 0x03, 0xD5, 0x51,
+ 0x4B, 0x56, 0xB9, 0x07, 0x85, 0x58, 0x17, 0x51,
+ 0x16, 0xC4, 0x86, 0xBB, 0xD3, 0x50, 0x01, 0x0E,
+ 0x7B, 0x9C, 0xEF, 0xF0, 0x28, 0x4A, 0xD7, 0x3D,
+ 0x1E, 0x3A, 0xBB, 0xCF, 0x2C, 0x90, 0x12, 0x2A,
+ 0xB3, 0x90, 0x72, 0xE3, 0x93, 0x81, 0xE8, 0xA4,
+ 0xEF, 0x8F, 0xD9, 0x45, 0x4F, 0xB1, 0xD0, 0x21,
+ 0xDA, 0x20, 0x5C, 0xE9, 0x41, 0x41, 0x4E, 0x48,
+ 0x95, 0x4D, 0x5A, 0xB3, 0xE5, 0x8B, 0xFC, 0xDE,
+ 0xB9, 0x7B, 0x93, 0xBE, 0xA2, 0x74, 0x1B, 0xFA,
+ 0xED, 0xCC, 0x0E, 0xDD, 0x96, 0x13, 0x2C, 0xAC,
+ 0xDE, 0x2B, 0x2D, 0x8A, 0x30, 0x5A, 0xB8, 0x4B,
+ 0x08, 0x2C, 0x74, 0xF7, 0xB4, 0x45, 0xD3, 0xA5,
+ 0x62, 0x87, 0xCA, 0x16, 0xEB, 0x49, 0x46, 0x0C,
+ 0x87, 0x7F, 0x11, 0x1D, 0x22, 0x66, 0x0A, 0x38,
+ 0x90, 0x3A, 0x31, 0x38, 0x73, 0xB2, 0xD5, 0x5E,
+ 0x06, 0xC4, 0x1E, 0x3D, 0xB7, 0x52, 0xB8, 0xE5,
+ 0xC0, 0xF9, 0x72, 0xBC, 0x7A, 0x8A, 0xD3, 0xB4,
+ 0x1D, 0xA9, 0x93, 0x3B, 0x7E, 0xFF, 0x8E, 0xA0,
+ 0x96, 0x52, 0xE9, 0x9E, 0x60, 0x4C, 0x02, 0x90,
+ 0xE5, 0x46, 0x92, 0xB3, 0xB8, 0x24, 0xE9, 0xD0,
+ 0xCE, 0xD3, 0x0B, 0xCD, 0x8B, 0xE8, 0x72, 0xEA,
+ 0x6E, 0xBF, 0x2B, 0x99, 0x6F, 0xC0, 0x65, 0xE8,
+ 0x92, 0x30, 0x03, 0x28, 0xA9, 0xB0, 0xA7, 0x03,
+ 0x92, 0x2C, 0xC8, 0x38, 0x8C, 0x38, 0x56, 0xEE,
+ 0xDB, 0x39, 0xBD, 0x7E, 0xE9, 0x8D, 0xDB, 0xC1,
+ 0xD5, 0x71, 0xC7, 0x84, 0xF3, 0xB2, 0x23, 0x22,
+ 0xB5, 0x98, 0xB3, 0x36, 0xF1, 0xC4, 0xB1, 0xA4,
+ 0xF2, 0x84, 0x24, 0xE5, 0x97, 0x48, 0x34, 0x43,
+ 0xEF, 0xD9, 0xF4, 0x10, 0xE4, 0x13, 0xEE, 0x6C,
+ 0xE7, 0x5D, 0x9B, 0xBA, 0x35, 0xF5, 0x7D, 0xE5,
+ 0xBF, 0x8A, 0xCC, 0x3D, 0x28, 0xCF, 0xE8, 0x90,
+ 0xE3, 0xCF, 0x01, 0x69, 0xD7, 0xC0, 0xD2, 0x2C,
+ 0xC2, 0x9B, 0x89, 0xF2, 0xA9, 0x83, 0xA2, 0xA9,
+ 0x12, 0xAA, 0x56, 0xD8, 0xCB, 0xA5, 0x8B, 0x0A,
+ 0x03, 0xC1, 0xE1, 0x8E, 0x02, 0x36, 0x3D, 0x8F,
+ 0x58, 0x4D, 0xEB, 0x93, 0x91, 0xC6, 0xE7, 0x22,
+ 0xCE, 0xA8, 0x02, 0xD2, 0x82, 0x0D, 0x43, 0x4D,
+ 0x4E, 0x11, 0xF8, 0x7B, 0x45, 0xD0, 0x23, 0xF7,
+ 0x14, 0x35, 0x16, 0xA4, 0x0B, 0xAD, 0xFE, 0xE2,
+ 0x2B, 0xFD, 0xF7, 0x17, 0xA9, 0x93, 0x77, 0x82,
+ 0x45, 0x6E, 0x51, 0x1F, 0x5C, 0x2C, 0x5F, 0xFF,
+ 0x1A, 0xA3, 0x0E, 0x29, 0xA5, 0x1D, 0xFD, 0x0E,
+ 0xDD, 0x14, 0xF6, 0x69, 0x20, 0x15, 0xFD, 0xBB,
+ 0xF8, 0xAF, 0x3D, 0xF3, 0xCC, 0xB8, 0x7E, 0x64,
+ 0xED, 0x99, 0xF3, 0x1D, 0xFC, 0x96, 0xA2, 0x0A,
+ 0x9C, 0xC2, 0x9B, 0xD7, 0x03, 0xA6, 0x79, 0x3B,
+ 0x16, 0x0C, 0x6C, 0x5C, 0x2B, 0x61, 0x0E, 0x48,
+ 0x96, 0x5C, 0x46, 0x7F, 0xC3, 0xCD, 0x3C, 0x10,
+ 0x30, 0x8F, 0xC4, 0xB5, 0x92, 0x46, 0x1C, 0xDF,
+ 0x10, 0xEE, 0x43, 0x27, 0x42, 0x70, 0xD2, 0xC4,
+ 0x5E, 0x77, 0x78, 0x0E, 0x0E, 0xC3, 0x8B, 0x72,
+ 0xA0, 0xFC, 0x4C, 0x0F, 0x5D, 0xBE, 0xBE, 0x07,
+ 0x5B, 0x53, 0x38, 0xC8, 0x96, 0x82, 0x2D, 0x2D,
+ 0x8E, 0xA8, 0x6C, 0x68, 0x34, 0x42, 0x31, 0x90,
+ 0xD6, 0x4D, 0x29, 0xA9, 0x90, 0x95, 0x19, 0xD6,
+ 0x8F, 0x2F, 0xF4, 0xD3, 0x71, 0x21, 0xB7, 0x7D,
+ 0x51, 0xA6, 0x15, 0xE5, 0xDA, 0x08, 0x6A, 0x23,
+ 0xDE, 0x6C, 0xBA, 0xCF, 0x84, 0xF1, 0x47, 0x25,
+ 0x4A, 0xF1, 0x2F, 0x24, 0xED, 0x3B, 0xED, 0xF0,
+ 0xA7, 0x48, 0xAE, 0x58, 0x7F, 0x0B, 0x3B, 0x78,
+ 0xCE, 0x94, 0x32, 0x82, 0x63, 0x22, 0x67, 0xAA,
+ 0x45, 0x37, 0xCC, 0x43, 0xD5, 0x10, 0x59, 0x5B,
+ 0x09, 0xC6, 0x1C, 0x32, 0xCD, 0x19, 0xA2, 0x3C,
+ 0x2B, 0x84, 0x03, 0xD5, 0x97, 0x20, 0xE7, 0xFB,
+ 0x2D, 0x0A, 0x3C, 0x5C, 0xFD, 0x39, 0x9C, 0xDE,
+ 0x02, 0x3D, 0xC7, 0xDD, 0x51, 0xDE, 0x99, 0xB3,
+ 0x65, 0x00, 0x60, 0xCF, 0xAE, 0xCD, 0xE2, 0x83,
+ 0xD5, 0x36, 0x2C, 0x89, 0x28, 0x6D, 0xC3, 0x6A,
+ 0x80, 0xCD, 0x1A, 0xC3, 0x75, 0x11, 0x7E, 0x65,
+ 0x2A, 0x44, 0x9D, 0xB5, 0x12, 0x2A, 0x78, 0xD0,
+ 0x4D, 0xF8, 0x5E, 0xBF, 0xEC, 0x6B, 0x60, 0xD2,
+ 0x89, 0x92, 0x5E, 0x17, 0xDA, 0x33, 0x83, 0xDB,
+ 0xED, 0xF4, 0x5E, 0x82, 0xE9, 0x04, 0xD7, 0xE0,
+ 0xA4, 0x1B, 0xFE, 0x32, 0x93, 0x05, 0x2C, 0xCF,
+ 0xA2, 0xAE, 0x83, 0xCA, 0x2F, 0x5E, 0x47, 0x1C,
+ 0x85, 0x0D, 0x01, 0xE5, 0x44, 0x3D, 0xE4, 0x58,
+ 0x8E, 0xC0, 0x46, 0x05, 0x95, 0xBE, 0x59, 0xED,
+ 0x0F, 0x7B, 0xA1, 0xF7, 0xDB, 0x2C, 0x79, 0x86,
+ 0xE9, 0x54, 0x98, 0xA6, 0x2A, 0xD0, 0xFE, 0xC9,
+ 0x59, 0x1D, 0x31, 0xC6, 0x27, 0x83, 0x2C, 0x12,
+ 0x9C, 0xE1, 0x43, 0x3C, 0xEC, 0x65, 0x3B, 0xEF,
+ 0xFD, 0x92, 0xBC, 0x0E, 0x38, 0xBA, 0x56, 0x1C,
+ 0xC0, 0x81, 0x9E, 0xBE, 0x76, 0x59, 0x88, 0xA4,
+ 0x0C, 0x6B, 0xD9, 0x7C, 0xD6, 0x8C, 0x32, 0xCD,
+ 0x3F, 0xB6, 0xEF, 0xBF, 0xA6, 0xC7, 0xC9, 0xD3,
+ 0x02, 0xB0, 0x3B, 0xFF, 0xFC, 0x4A, 0x97, 0x14,
+ 0xFF, 0xF2, 0x48, 0xFE, 0x1B, 0xCE, 0x7D, 0x24,
+ 0xA1, 0xD6, 0x03, 0xB0, 0x2F, 0xAA, 0xF7, 0x71,
+ 0xC9, 0x0E, 0xCB, 0x57, 0xBA, 0xEF, 0xB5, 0x65,
+ 0xE1, 0x44, 0xE4, 0x6A, 0xEB, 0xE8, 0x2B, 0x8F,
+ 0x06, 0x23, 0x7A, 0xA9, 0x70, 0xAE, 0x48, 0x65,
+ 0x94, 0xEE, 0xA5, 0x94, 0x78, 0x7D, 0x09, 0xF8,
+ 0xB5, 0x4D, 0x64, 0x67, 0x10, 0x16, 0xA2, 0xFC,
+ 0x49, 0x93, 0x76, 0x71, 0xED, 0x56, 0x25, 0xB5,
+ 0x87, 0xE8, 0x84, 0x16, 0x55, 0xE1, 0x1E, 0x34,
+ 0xE3, 0xB2, 0x49, 0x8F, 0xDC, 0xDA, 0xC3, 0x17,
+ 0x82, 0x0E, 0x19, 0xD7, 0xE0, 0x09, 0xD7, 0xD9,
+ 0x59, 0x6B, 0x55, 0x60, 0x1C, 0x1B, 0x02, 0xE8,
+ 0xD1, 0x90, 0xF6, 0x3E, 0x94, 0x4A, 0x12, 0x0C,
+ 0xBB, 0x69, 0xFD, 0x7C, 0xA0, 0xDD, 0x5F, 0x93,
+ 0x9F, 0xFE, 0x2E, 0x79, 0xDB, 0xBE, 0x6F, 0x85,
+ 0xAD, 0x9B, 0xDE, 0xAA, 0x10, 0xCA, 0xDB, 0xF2,
+ 0xF9, 0xD0, 0x54, 0x15, 0x00, 0xF0, 0x6F, 0x86,
+ 0x16, 0xF6, 0xA8, 0xA4, 0x08, 0x7B, 0x50, 0xF1,
+ 0x35, 0xAC, 0xB6, 0xBB, 0x8B, 0xA0, 0x86, 0x3B,
+ 0x3B, 0xDA, 0x9F, 0x89, 0xB5, 0x9C, 0x44, 0x41,
+ 0x6A, 0xFD, 0x8A, 0x79, 0xA0, 0xFB, 0x7D, 0x1B,
+ 0xE8, 0xC4, 0xA7, 0x3F, 0x66, 0x97, 0xA9, 0xF8,
+ 0xEA, 0x0C, 0x30, 0x81, 0x63, 0xE4, 0xE3, 0x84,
+ 0x62, 0xC5, 0x19, 0xFB, 0x00, 0xD6, 0x72, 0xE6,
+ 0xC9, 0x6C, 0xDB, 0xEB, 0xF3, 0x6F, 0xDB, 0xE7,
+ 0x00, 0x53, 0xCE, 0x1D, 0xE5, 0xF5, 0x53, 0x18,
+ 0xE5, 0xAA, 0xDA, 0x90, 0x7B, 0xCB, 0x2B, 0x74,
+ 0xED, 0x70, 0xFE, 0x90, 0xA8, 0xC8, 0x80, 0x2B,
+ 0x93, 0x08, 0xDB, 0x6A, 0x0F, 0x3D, 0xA1, 0xFA,
+ 0xB6, 0x63, 0x18, 0xF8, 0x43, 0x68, 0x00, 0xD0,
+ 0x7A, 0x97, 0xCD, 0x5B, 0xB2, 0x84, 0x90, 0x06,
+ 0xB9, 0x81, 0xC5, 0x81, 0x05, 0x55, 0x8C, 0xC4,
+ 0x03, 0x89, 0xF5, 0x63, 0x87, 0x39, 0xEC, 0xD6,
+ 0x89, 0x01, 0xE7, 0x1C, 0x4C, 0xDF, 0x5D, 0x65,
+ 0xFE, 0x4B, 0x91, 0x04, 0x5B, 0x0E, 0x03, 0x38,
+ 0x2F, 0x21, 0xA8, 0x36, 0x58, 0x93, 0xAD, 0x1F,
+ 0xEB, 0xC3, 0x91, 0x90, 0x9B, 0x95, 0xCD, 0x53,
+ 0x81, 0xAA, 0xA9, 0x48, 0x4D, 0x2B, 0x22, 0xC7,
+ 0xBE, 0x1B, 0x38, 0x21, 0xA1, 0xFE, 0x23, 0xB4,
+ 0xAC, 0x66, 0x92, 0x9E, 0xF2, 0x27, 0xDC, 0x23,
+ 0x70, 0x6E, 0xBA, 0xF9, 0xED, 0x3B, 0xCE, 0x63,
+ 0xAD, 0x68, 0xF2, 0x80, 0xFA, 0x1B, 0x14, 0xB5,
+ 0xB4, 0x07, 0xE3, 0x5A, 0x81, 0x74, 0xE1, 0xF2,
+ },
+ .len = 3120
+ },
+ .auth_tag = {
+ .data = {
+ 0xEA, 0xE9, 0x10, 0xB6, 0xB7, 0xAB, 0xEA, 0x90,
+ 0x8A, 0xD5, 0x63, 0x88, 0xDB, 0x2B, 0x8F, 0x23,
+ },
+ .len = 16
+ }
+};
+
+/** AES-CCM-128 Test Vectors */
+static const struct aead_test_data ccm_test_case_128_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
+ },
+ .len = 7
+ },
+ .aad = {
+ .data = ccm_aad_test_1,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x20, 0x21, 0x22, 0x23
+ },
+ .len = 4
+ },
+ .ciphertext = {
+ .data = {
+ 0x71, 0x62, 0x01, 0x5B
+ },
+ .len = 4
+ },
+ .auth_tag = {
+ .data = {
+ 0x4D, 0xAC, 0x25, 0x5D
+ },
+ .len = 4
+ }
+};
+
+static const struct aead_test_data ccm_test_case_128_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = ccm_aad_test_2,
+ .len = 22
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0xF3, 0xD0, 0xA2, 0xFE, 0x9A, 0x3D, 0xBF, 0x23,
+ 0x42, 0xA6, 0x43, 0xE4, 0x32, 0x46, 0xE8, 0x0C,
+ 0x3C, 0x04, 0xD0, 0x19
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0x78, 0x45, 0xCE, 0x0B, 0x16, 0xF9, 0x76, 0x23
+ },
+ .len = 8
+ }
+};
+
+static const struct aead_test_data ccm_test_case_128_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0xF3, 0xD0, 0xA2, 0xFE, 0x9A, 0x3D, 0xBF, 0x23,
+ 0x42, 0xA6, 0x43, 0xE4, 0x32, 0x46, 0xE8, 0x0C,
+ 0x3C, 0x04, 0xD0, 0x19
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0x41, 0x83, 0x21, 0x89, 0xA3, 0xD3, 0x1B, 0x43
+ },
+ .len = 8
+ }
+};
+
+/** AES-CCM-192 Test Vectors */
+static const struct aead_test_data ccm_test_case_192_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
+ },
+ .len = 7
+ },
+ .aad = {
+ .data = ccm_aad_test_1,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x20, 0x21, 0x22, 0x23
+ },
+ .len = 4
+ },
+ .ciphertext = {
+ .data = {
+ 0x18, 0xEE, 0x17, 0x30
+ },
+ .len = 4
+ },
+ .auth_tag = {
+ .data = {
+ 0xC8, 0xC3, 0x26, 0xD5
+ },
+ .len = 4
+ }
+};
+
+static const struct aead_test_data ccm_test_case_192_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = ccm_aad_test_2,
+ .len = 22
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0x41, 0xC6, 0x2D, 0xD5, 0x31, 0xF2, 0xD5, 0xC8,
+ 0xCC, 0x57, 0x01, 0x2E, 0x7E, 0x2B, 0xF1, 0x26,
+ 0x6A, 0xC7, 0xCB, 0xA5
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0x77, 0xA3, 0x41, 0xD5, 0x2A, 0xE3, 0x25, 0x37
+ },
+ .len = 8
+ }
+};
+
+static const struct aead_test_data ccm_test_case_192_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0x41, 0xC6, 0x2D, 0xD5, 0x31, 0xF2, 0xD5, 0xC8,
+ 0xCC, 0x57, 0x01, 0x2E, 0x7E, 0x2B, 0xF1, 0x26,
+ 0x6A, 0xC7, 0xCB, 0xA5
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0x84, 0x72, 0x6E, 0xE7, 0x8E, 0x8E, 0x3A, 0xC6
+ },
+ .len = 8
+ }
+};
+
+/** AES-CCM-256 Test Vectors */
+static const struct aead_test_data ccm_test_case_256_1 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
+ },
+ .len = 7
+ },
+ .aad = {
+ .data = ccm_aad_test_1,
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x20, 0x21, 0x22, 0x23
+ },
+ .len = 4
+ },
+ .ciphertext = {
+ .data = {
+ 0x8A, 0xB1, 0xA8, 0x74
+ },
+ .len = 4
+ },
+ .auth_tag = {
+ .data = {
+ 0x95, 0xFC, 0x08, 0x20
+ },
+ .len = 4
+ }
+};
+
+static const struct aead_test_data ccm_test_case_256_2 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = ccm_aad_test_2,
+ .len = 22
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0x25, 0x82, 0x89, 0x09, 0x3E, 0x39, 0x1F, 0x16,
+ 0xD2, 0x82, 0x3D, 0xF6, 0xCE, 0x97, 0x72, 0x07,
+ 0xEC, 0x23, 0x17, 0x98
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0xAB, 0x02, 0xE9, 0xD1, 0x16, 0x69, 0xED, 0x0A
+ },
+ .len = 8
+ }
+};
+
+static const struct aead_test_data ccm_test_case_256_3 = {
+ .algo = RTE_CRYPTO_AEAD_AES_CCM,
+ .key = {
+ .data = {
+ 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85,
+ 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5,
+ 0x03, 0x97, 0x76, 0xE7, 0x0C
+ },
+ .len = 13
+ },
+ .aad = {
+ .data = gcm_aad_zero_text,
+ .len = 0
+ },
+ .plaintext = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE,
+ 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB,
+ 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .ciphertext = {
+ .data = {
+ 0x25, 0x82, 0x89, 0x09, 0x3E, 0x39, 0x1F, 0x16,
+ 0xD2, 0x82, 0x3D, 0xF6, 0xCE, 0x97, 0x72, 0x07,
+ 0xEC, 0x23, 0x17, 0x98
+ },
+ .len = 20
+ },
+ .auth_tag = {
+ .data = {
+ 0x15, 0x80, 0xC4, 0xC9, 0x3F, 0xAB, 0x2A, 0xFD
+ },
+ .len = 8
+ }
+};
+#endif /* TEST_CRYPTODEV_AEAD_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_aes_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_aes_test_vectors.h
new file mode 100644
index 000000000..3c38eeeef
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_aes_test_vectors.h
@@ -0,0 +1,2298 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2019 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_AES_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_AES_TEST_VECTORS_H_
+
+/* test vectors */
+static const uint8_t plaintext_aes128ctr[] = {
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const uint8_t ciphertext64_aes128ctr[] = {
+ 0x87, 0x4D, 0x61, 0x91, 0xB6, 0x20, 0xE3, 0x26,
+ 0x1B, 0xEF, 0x68, 0x64, 0x99, 0x0D, 0xB6, 0xCE,
+ 0x98, 0x06, 0xF6, 0x6B, 0x79, 0x70, 0xFD, 0xFF,
+ 0x86, 0x17, 0x18, 0x7B, 0xB9, 0xFF, 0xFD, 0xFF,
+ 0x5A, 0xE4, 0xDF, 0x3E, 0xDB, 0xD5, 0xD3, 0x5E,
+ 0x5B, 0x4F, 0x09, 0x02, 0x0D, 0xB0, 0x3E, 0xAB,
+ 0x1E, 0x03, 0x1D, 0xDA, 0x2F, 0xBE, 0x03, 0xD1,
+ 0x79, 0x21, 0x70, 0xA0, 0xF3, 0x00, 0x9C, 0xEE
+};
+
+static const uint8_t ciphertext64_aes128ctr_IV_12bytes[] = {
+ 0x28, 0x80, 0x28, 0xC7, 0x15, 0x99, 0xC5, 0xA8,
+ 0xDD, 0x53, 0xC2, 0x67, 0x1B, 0x86, 0xB8, 0x13,
+ 0xAB, 0x25, 0x39, 0x7A, 0xD2, 0x1F, 0x8B, 0x4B,
+ 0x94, 0x89, 0x2B, 0x65, 0xCF, 0x89, 0x1E, 0xDD,
+ 0xD4, 0x7C, 0xFD, 0x8D, 0x0E, 0xCD, 0x23, 0xA4,
+ 0xEB, 0x8C, 0x05, 0x58, 0x45, 0x4A, 0x63, 0x44,
+ 0x11, 0x42, 0x07, 0x17, 0xB4, 0xD2, 0xCC, 0x75,
+ 0xB7, 0x23, 0x99, 0xA9, 0xC5, 0x89, 0x7F, 0x66
+};
+
+static const uint8_t plaintext_aes_docsis_bpi_cfb[] = {
+ 0x00, 0x01, 0x02, 0x88, 0xEE, 0x59, 0x7E
+};
+
+static const uint8_t ciphertext_aes_docsis_bpi_cfb[] = {
+ 0xFC, 0x68, 0xA3, 0x55, 0x60, 0x37, 0xDC
+};
+
+static const uint8_t ciphertext_aes256_docsis_bpi_cfb[] = {
+ 0xE3, 0x75, 0xF2, 0x30, 0x1F, 0x75, 0x9A
+};
+
+static const uint8_t plaintext_aes_docsis_bpi_cbc_cfb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x91,
+ 0xD2, 0xD1, 0x9F
+};
+
+static const uint8_t ciphertext_aes_docsis_bpi_cbc_cfb[] = {
+ 0x9D, 0xD1, 0x67, 0x4B, 0xBA, 0x61, 0x10, 0x1B,
+ 0x56, 0x75, 0x64, 0x74, 0x36, 0x4F, 0x10, 0x1D,
+ 0x44, 0xD4, 0x73
+};
+
+static const uint8_t ciphertext_aes256_docsis_bpi_cbc_cfb[] = {
+ 0xD1, 0x28, 0x73, 0x1F, 0xB5, 0x28, 0xB5, 0x18,
+ 0xAB, 0x51, 0xAB, 0xC8, 0x98, 0x3D, 0xD1, 0xEE,
+ 0xE4, 0x43, 0x59
+};
+
+static const uint8_t plaintext_aes192ctr[] = {
+ 0x01, 0x0F, 0x10, 0x1F, 0x20, 0x1C, 0x0E, 0xB8,
+ 0xFB, 0x5C, 0xCD, 0xCC, 0x1F, 0xF9, 0xAF, 0x0B,
+ 0x95, 0x03, 0x74, 0x99, 0x49, 0xE7, 0x62, 0x55,
+ 0xDA, 0xEA, 0x13, 0x20, 0x1D, 0xC6, 0xCC, 0xCC,
+ 0xD1, 0x70, 0x75, 0x47, 0x02, 0x2F, 0xFB, 0x86,
+ 0xBB, 0x6B, 0x23, 0xD2, 0xC9, 0x74, 0xD7, 0x7B,
+ 0x08, 0x03, 0x3B, 0x79, 0x39, 0xBB, 0x91, 0x29,
+ 0xDA, 0x14, 0x39, 0x8D, 0xFF, 0x81, 0x50, 0x96,
+};
+
+static const uint8_t ciphertext64_aes192ctr[] = {
+ 0x4A, 0x6C, 0xC8, 0xCC, 0x96, 0x2A, 0x13, 0x84,
+ 0x1C, 0x36, 0x88, 0xE9, 0xE5, 0x94, 0x70, 0xB2,
+ 0x14, 0x5B, 0x13, 0x80, 0xEA, 0xD8, 0x8D, 0x37,
+ 0xFD, 0x70, 0xA8, 0x83, 0xE8, 0x2B, 0x88, 0x1E,
+ 0xBA, 0x94, 0x3F, 0xF6, 0xB3, 0x1F, 0xDE, 0x34,
+ 0xF3, 0x5B, 0x80, 0xE9, 0xAB, 0xF5, 0x1C, 0x29,
+ 0xB6, 0xD9, 0x76, 0x2B, 0x06, 0xC6, 0x74, 0xF1,
+ 0x59, 0x5E, 0x9E, 0xA5, 0x7B, 0x2D, 0xD7, 0xF0
+};
+
+static const uint8_t ciphertext64_aes192ctr_IV_12bytes[] = {
+ 0x67, 0x65, 0xa9, 0xee, 0xfd, 0x31, 0x62, 0xfc,
+ 0xad, 0xfd, 0xc7, 0x25, 0xb7, 0x25, 0x16, 0xbe,
+ 0x25, 0xce, 0xc0, 0x1d, 0xda, 0xa9, 0xd3, 0xda,
+ 0x1b, 0x7d, 0x68, 0x6a, 0x6f, 0x06, 0xea, 0x47,
+ 0xa0, 0xe0, 0x15, 0xf4, 0xbd, 0x1b, 0x70, 0x34,
+ 0xd4, 0x6d, 0x1c, 0x84, 0x17, 0x91, 0x46, 0x0c,
+ 0xe8, 0xbc, 0x7a, 0xfb, 0x9f, 0x2a, 0x8f, 0xb4,
+ 0xd4, 0xf3, 0x6e, 0x5b, 0x75, 0xa0, 0xce, 0x32
+};
+
+static const uint8_t plaintext_aes256ctr[] = {
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const uint8_t ciphertext64_aes256ctr[] = {
+ 0x60, 0x1E, 0xC3, 0x13, 0x77, 0x57, 0x89, 0xA5,
+ 0xB7, 0xA7, 0xF5, 0x04, 0xBB, 0xF3, 0xD2, 0x28,
+ 0xF4, 0x43, 0xE3, 0xCA, 0x4D, 0x62, 0xB5, 0x9A,
+ 0xCA, 0x84, 0xE9, 0x90, 0xCA, 0xCA, 0xF5, 0xC5,
+ 0x2B, 0x09, 0x30, 0xDA, 0xA2, 0x3D, 0xE9, 0x4C,
+ 0xE8, 0x70, 0x17, 0xBA, 0x2D, 0x84, 0x98, 0x8D,
+ 0xDF, 0xC9, 0xC5, 0x8D, 0xB6, 0x7A, 0xAD, 0xA6,
+ 0x13, 0xC2, 0xDD, 0x08, 0x45, 0x79, 0x41, 0xA6
+};
+
+static const uint8_t ciphertext64_aes256ctr_IV_12bytes[] = {
+ 0x7B, 0x7A, 0x7D, 0x83, 0x85, 0xF8, 0x81, 0xF3,
+ 0x32, 0x33, 0xD9, 0xFB, 0x04, 0x73, 0xD4, 0x2F,
+ 0x70, 0xDE, 0x90, 0x3E, 0xD0, 0xA9, 0x93, 0x8A,
+ 0x91, 0xF3, 0xB5, 0x29, 0x4D, 0x2A, 0x74, 0xD0,
+ 0xDC, 0x4E, 0x5C, 0x9B, 0x97, 0x24, 0xD8, 0x02,
+ 0xFE, 0xAB, 0x38, 0xE8, 0x73, 0x51, 0x29, 0x7E,
+ 0xF1, 0xF9, 0x40, 0x78, 0xB1, 0x04, 0x7A, 0x78,
+ 0x61, 0x07, 0x47, 0xE6, 0x8C, 0x0F, 0xA8, 0x76
+};
+
+static const uint8_t plaintext_aes_common[] = {
+ "What a lousy earth! He wondered how many people "
+ "were destitute that same night even in his own "
+ "prosperous country, how many homes were "
+ "shanties, how many husbands were drunk and "
+ "wives socked, and how many children were "
+ "bullied, abused, or abandoned. How many "
+ "families hungered for food they could not "
+ "afford to buy? How many hearts were broken? How "
+ "many suicides would take place that same night, "
+ "how many people would go insane? How many "
+ "cockroaches and landlords would triumph? How "
+ "many winners were losers, successes failures, "
+ "and rich men poor men? How many wise guys were "
+ "stupid? How many happy endings were unhappy "
+ "endings? How many honest men were liars, brave "
+ "men cowards, loyal men traitors, how many "
+ "sainted men were corrupt, how many people in "
+ "positions of trust had sold their souls to "
+ "bodyguards, how many had never had souls? How "
+ "many straight-and-narrow paths were crooked "
+ "paths? How many best families were worst "
+ "families and how many good people were bad "
+ "people? When you added them all up and then "
+ "subtracted, you might be left with only the "
+ "children, and perhaps with Albert Einstein and "
+ "an old violinist or sculptor somewhere."
+};
+
+static const uint8_t ciphertext512_aes128cbc[] = {
+ 0x8B, 0x4D, 0xDA, 0x1B, 0xCF, 0x04, 0xA0, 0x31,
+ 0xB4, 0xBF, 0xBD, 0x68, 0x43, 0x20, 0x7E, 0x76,
+ 0xB1, 0x96, 0x8B, 0xA2, 0x7C, 0xA2, 0x83, 0x9E,
+ 0x39, 0x5A, 0x2F, 0x7E, 0x92, 0xB4, 0x48, 0x1A,
+ 0x3F, 0x6B, 0x5D, 0xDF, 0x52, 0x85, 0x5F, 0x8E,
+ 0x42, 0x3C, 0xFB, 0xE9, 0x1A, 0x24, 0xD6, 0x08,
+ 0xDD, 0xFD, 0x16, 0xFB, 0xE9, 0x55, 0xEF, 0xF0,
+ 0xA0, 0x8D, 0x13, 0xAB, 0x81, 0xC6, 0x90, 0x01,
+ 0xB5, 0x18, 0x84, 0xB3, 0xF6, 0xE6, 0x11, 0x57,
+ 0xD6, 0x71, 0xC6, 0x3C, 0x3F, 0x2F, 0x33, 0xEE,
+ 0x24, 0x42, 0x6E, 0xAC, 0x0B, 0xCA, 0xEC, 0xF9,
+ 0x84, 0xF8, 0x22, 0xAA, 0x60, 0xF0, 0x32, 0xA9,
+ 0x75, 0x75, 0x3B, 0xCB, 0x70, 0x21, 0x0A, 0x8D,
+ 0x0F, 0xE0, 0xC4, 0x78, 0x2B, 0xF8, 0x97, 0xE3,
+ 0xE4, 0x26, 0x4B, 0x29, 0xDA, 0x88, 0xCD, 0x46,
+ 0xEC, 0xAA, 0xF9, 0x7F, 0xF1, 0x15, 0xEA, 0xC3,
+ 0x87, 0xE6, 0x31, 0xF2, 0xCF, 0xDE, 0x4D, 0x80,
+ 0x70, 0x91, 0x7E, 0x0C, 0xF7, 0x26, 0x3A, 0x92,
+ 0x4F, 0x18, 0x83, 0xC0, 0x8F, 0x59, 0x01, 0xA5,
+ 0x88, 0xD1, 0xDB, 0x26, 0x71, 0x27, 0x16, 0xF5,
+ 0xEE, 0x10, 0x82, 0xAC, 0x68, 0x26, 0x9B, 0xE2,
+ 0x6D, 0xD8, 0x9A, 0x80, 0xDF, 0x04, 0x31, 0xD5,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x61, 0x1C, 0x42, 0x10, 0x76,
+ 0x73, 0x02, 0x42, 0xC9, 0x23, 0x18, 0x8E, 0xB4,
+ 0x6F, 0xB4, 0xA3, 0x54, 0x6E, 0x88, 0x3B, 0x62,
+ 0x7C, 0x02, 0x8D, 0x4C, 0x9F, 0xC8, 0x45, 0xF4,
+ 0xC9, 0xDE, 0x4F, 0xEB, 0x22, 0x83, 0x1B, 0xE4,
+ 0x49, 0x37, 0xE4, 0xAD, 0xE7, 0xCD, 0x21, 0x54,
+ 0xBC, 0x1C, 0xC2, 0x04, 0x97, 0xB4, 0x10, 0x61,
+ 0xF0, 0xE4, 0xEF, 0x27, 0x63, 0x3A, 0xDA, 0x91,
+ 0x41, 0x25, 0x62, 0x1C, 0x5C, 0xB6, 0x38, 0x4A,
+ 0x88, 0x71, 0x59, 0x5A, 0x8D, 0xA0, 0x09, 0xAF,
+ 0x72, 0x94, 0xD7, 0x79, 0x5C, 0x60, 0x7C, 0x8F,
+ 0x4C, 0xF5, 0xD9, 0xA1, 0x39, 0x6D, 0x81, 0x28,
+ 0xEF, 0x13, 0x28, 0xDF, 0xF5, 0x3E, 0xF7, 0x8E,
+ 0x09, 0x9C, 0x78, 0x18, 0x79, 0xB8, 0x68, 0xD7,
+ 0xA8, 0x29, 0x62, 0xAD, 0xDE, 0xE1, 0x61, 0x76,
+ 0x1B, 0x05, 0x16, 0xCD, 0xBF, 0x02, 0x8E, 0xA6,
+ 0x43, 0x6E, 0x92, 0x55, 0x4F, 0x60, 0x9C, 0x03,
+ 0xB8, 0x4F, 0xA3, 0x02, 0xAC, 0xA8, 0xA7, 0x0C,
+ 0x1E, 0xB5, 0x6B, 0xF8, 0xC8, 0x4D, 0xDE, 0xD2,
+ 0xB0, 0x29, 0x6E, 0x40, 0xE6, 0xD6, 0xC9, 0xE6,
+ 0xB9, 0x0F, 0xB6, 0x63, 0xF5, 0xAA, 0x2B, 0x96,
+ 0xA7, 0x16, 0xAC, 0x4E, 0x0A, 0x33, 0x1C, 0xA6,
+ 0xE6, 0xBD, 0x8A, 0xCF, 0x40, 0xA9, 0xB2, 0xFA,
+ 0x63, 0x27, 0xFD, 0x9B, 0xD9, 0xFC, 0xD5, 0x87,
+ 0x8D, 0x4C, 0xB6, 0xA4, 0xCB, 0xE7, 0x74, 0x55,
+ 0xF4, 0xFB, 0x41, 0x25, 0xB5, 0x4B, 0x0A, 0x1B,
+ 0xB1, 0xD6, 0xB7, 0xD9, 0x47, 0x2A, 0xC3, 0x98,
+ 0x6A, 0xC4, 0x03, 0x73, 0x1F, 0x93, 0x6E, 0x53,
+ 0x19, 0x25, 0x64, 0x15, 0x83, 0xF9, 0x73, 0x2A,
+ 0x74, 0xB4, 0x93, 0x69, 0xC4, 0x72, 0xFC, 0x26,
+ 0xA2, 0x9F, 0x43, 0x45, 0xDD, 0xB9, 0xEF, 0x36,
+ 0xC8, 0x3A, 0xCD, 0x99, 0x9B, 0x54, 0x1A, 0x36,
+ 0xC1, 0x59, 0xF8, 0x98, 0xA8, 0xCC, 0x28, 0x0D,
+ 0x73, 0x4C, 0xEE, 0x98, 0xCB, 0x7C, 0x58, 0x7E,
+ 0x20, 0x75, 0x1E, 0xB7, 0xC9, 0xF8, 0xF2, 0x0E,
+ 0x63, 0x9E, 0x05, 0x78, 0x1A, 0xB6, 0xA8, 0x7A,
+ 0xF9, 0x98, 0x6A, 0xA6, 0x46, 0x84, 0x2E, 0xF6,
+ 0x4B, 0xDC, 0x9B, 0x8F, 0x9B, 0x8F, 0xEE, 0xB4,
+ 0xAA, 0x3F, 0xEE, 0xC0, 0x37, 0x27, 0x76, 0xC7,
+ 0x95, 0xBB, 0x26, 0x74, 0x69, 0x12, 0x7F, 0xF1,
+ 0xBB, 0xFF, 0xAE, 0xB5, 0x99, 0x6E, 0xCB, 0x0C
+};
+
+/* NULL cipher NULL auth 8-byte multiple test vector */
+static const struct blockcipher_test_data null_test_data_chain_x8_multiple = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .iv = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/* NULL cipher NULL auth 4-byte multiple test vector */
+static const struct blockcipher_test_data null_test_data_chain_x4_multiple = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .iv = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes128ctr,
+ .len = 20
+ },
+ .ciphertext = {
+ .data = plaintext_aes128ctr,
+ .len = 20
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/* NULL cipher NULL auth 1-byte multiple test vector */
+static const struct blockcipher_test_data null_test_data_chain_x1_multiple = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .iv = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes128ctr,
+ .len = 21
+ },
+ .ciphertext = {
+ .data = plaintext_aes128ctr,
+ .len = 21
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+static const uint8_t ciphertext512_aes128cbc_aad[] = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x6D, 0x70, 0xB4, 0xAD,
+ 0x09, 0x7C, 0xD7, 0x52, 0xD6, 0xF2, 0xBF, 0xD1,
+ 0x9D, 0x79, 0xC6, 0xB6, 0x8F, 0x94, 0xEB, 0xD8,
+ 0xBA, 0x5E, 0x01, 0x49, 0x7D, 0xB3, 0xC5, 0xFE,
+ 0x18, 0xF4, 0xE3, 0x60, 0x8C, 0x84, 0x68, 0x13,
+ 0x33, 0x06, 0x85, 0x60, 0xD3, 0xE7, 0x8A, 0xB5,
+ 0x23, 0xA2, 0xDE, 0x52, 0x5C, 0xB6, 0x26, 0x37,
+ 0xBB, 0x23, 0x8A, 0x38, 0x07, 0x85, 0xB6, 0x2E,
+ 0xC3, 0x69, 0x57, 0x79, 0x6B, 0xE4, 0xD7, 0x86,
+ 0x23, 0x72, 0x4C, 0x65, 0x49, 0x08, 0x1E, 0xF3,
+ 0xCC, 0x71, 0x4C, 0x45, 0x97, 0x03, 0xBC, 0xA0,
+ 0x9D, 0xF0, 0x4F, 0x5D, 0xEC, 0x40, 0x6C, 0xC6,
+ 0x52, 0xC0, 0x9D, 0x1C, 0xDC, 0x8B, 0xC2, 0xFA,
+ 0x35, 0xA7, 0x3A, 0x00, 0x04, 0x1C, 0xA6, 0x91,
+ 0x5D, 0xEB, 0x07, 0xA1, 0xB9, 0x3E, 0xD1, 0xB6,
+ 0xCA, 0x96, 0xEC, 0x71, 0xF7, 0x7D, 0xB6, 0x09,
+ 0x3D, 0x19, 0x6E, 0x75, 0x03, 0xC3, 0x1A, 0x4E,
+ 0x5B, 0x4D, 0xEA, 0xD9, 0x92, 0x96, 0x01, 0xFB,
+ 0xA3, 0xC2, 0x6D, 0xC4, 0x17, 0x6B, 0xB4, 0x3B,
+ 0x1E, 0x87, 0x54, 0x26, 0x95, 0x63, 0x07, 0x73,
+ 0xB6, 0xBA, 0x52, 0xD7, 0xA7, 0xD0, 0x9C, 0x75,
+ 0x8A, 0xCF, 0xC4, 0x3C, 0x4A, 0x55, 0x0E, 0x53,
+ 0xEC, 0xE0, 0x31, 0x51, 0xB7, 0xB7, 0xD2, 0xB4,
+ 0xF3, 0x2B, 0x70, 0x6D, 0x15, 0x9E, 0x57, 0x30,
+ 0x72, 0xE5, 0xA4, 0x71, 0x5F, 0xA4, 0xE8, 0x7C,
+ 0x46, 0x58, 0x36, 0x71, 0x91, 0x55, 0xAA, 0x99,
+ 0x3B, 0x3F, 0xF6, 0xA2, 0x9D, 0x27, 0xBF, 0xC2,
+ 0x62, 0x2C, 0x85, 0xB7, 0x51, 0xDD, 0xFD, 0x7B,
+ 0x8B, 0xB5, 0xDD, 0x2A, 0x73, 0xF8, 0x93, 0x9A,
+ 0x3F, 0xAD, 0x1D, 0xF0, 0x46, 0xD1, 0x76, 0x83,
+ 0x71, 0x4E, 0xD3, 0x0D, 0x64, 0x8C, 0xC3, 0xE6,
+ 0x03, 0xED, 0xE8, 0x53, 0x23, 0x1A, 0xC7, 0x86,
+ 0xEB, 0x87, 0xD6, 0x78, 0xF9, 0xFB, 0x9C, 0x1D,
+ 0xE7, 0x4E, 0xC0, 0x70, 0x27, 0x7A, 0x43, 0xE2,
+ 0x5D, 0xA4, 0x10, 0x40, 0xBE, 0x61, 0x0D, 0x2B,
+ 0x25, 0x08, 0x75, 0x91, 0xB5, 0x5A, 0x26, 0xC8,
+ 0x32, 0xA7, 0xC6, 0x88, 0xBF, 0x75, 0x94, 0xCC,
+ 0x58, 0xA4, 0xFE, 0x2F, 0xF7, 0x5C, 0xD2, 0x36,
+ 0x66, 0x55, 0xF0, 0xEA, 0xF5, 0x64, 0x43, 0xE7,
+ 0x6D, 0xE0, 0xED, 0xA1, 0x10, 0x0A, 0x84, 0x07,
+ 0x11, 0x88, 0xFA, 0xA1, 0xD3, 0xA0, 0x00, 0x5D,
+ 0xEB, 0xB5, 0x62, 0x01, 0x72, 0xC1, 0x9B, 0x39,
+ 0x0B, 0xD3, 0xAF, 0x04, 0x19, 0x42, 0xEC, 0xFF,
+ 0x4B, 0xB3, 0x5E, 0x87, 0x27, 0xE4, 0x26, 0x57,
+ 0x76, 0xCD, 0x36, 0x31, 0x5B, 0x94, 0x74, 0xFF,
+ 0x33, 0x91, 0xAA, 0xD1, 0x45, 0x34, 0xC2, 0x11,
+ 0xF0, 0x35, 0x44, 0xC9, 0xD5, 0xA2, 0x5A, 0xC2,
+ 0xE9, 0x9E, 0xCA, 0xE2, 0x6F, 0xD2, 0x40, 0xB4,
+ 0x93, 0x42, 0x78, 0x20, 0x92, 0x88, 0xC7, 0x16,
+ 0xCF, 0x15, 0x54, 0x7B, 0xE1, 0x46, 0x38, 0x69,
+ 0xB8, 0xE4, 0xF1, 0x81, 0xF0, 0x08, 0x6F, 0x92,
+ 0x6D, 0x1A, 0xD9, 0x93, 0xFA, 0xD7, 0x35, 0xFE,
+ 0x7F, 0x59, 0x43, 0x1D, 0x3A, 0x3B, 0xFC, 0xD0,
+ 0x14, 0x95, 0x1E, 0xB2, 0x04, 0x08, 0x4F, 0xC6,
+ 0xEA, 0xE8, 0x22, 0xF3, 0xD7, 0x66, 0x93, 0xAA,
+ 0xFD, 0xA0, 0xFE, 0x03, 0x96, 0x54, 0x78, 0x35,
+ 0x18, 0xED, 0xB7, 0x2F, 0x40, 0xE3, 0x8E, 0x22,
+ 0xC6, 0xDA, 0xB0, 0x8E, 0xA0, 0xA1, 0x62, 0x03,
+ 0x63, 0x34, 0x11, 0xF5, 0x9E, 0xAA, 0x6B, 0xC4,
+ 0x14, 0x75, 0x4C, 0xF4, 0xD8, 0xD9, 0xF1, 0x76,
+ 0xE3, 0xD3, 0x55, 0xCE, 0x22, 0x7D, 0x4A, 0xB7,
+ 0xBB, 0x7F, 0x4F, 0x09, 0x88, 0x70, 0x6E, 0x09,
+ 0x84, 0x6B, 0x24, 0x19, 0x2C, 0x20, 0x73, 0x75
+};
+
+/* AES128-CTR-SHA1 test vector */
+static const struct blockcipher_test_data aes_test_data_1 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes128ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes128ctr,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x9B, 0x6F, 0x0C, 0x43, 0xF5, 0xC1, 0x3E, 0xB0,
+ 0xB1, 0x70, 0xB8, 0x2B, 0x33, 0x09, 0xD2, 0xB2,
+ 0x56, 0x20, 0xFB, 0xFE
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/** AES-192-CTR XCBC test vector */
+static const struct blockcipher_test_data aes_test_data_2 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xCB, 0xC5, 0xED, 0x5B, 0xE7, 0x7C, 0xBD, 0x8C,
+ 0x50, 0xD9, 0x30, 0xF2, 0xB5, 0x6A, 0x0E, 0x5F,
+ 0xAA, 0xAE, 0xAD, 0xA2, 0x1F, 0x49, 0x52, 0xD4
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x3F, 0x69, 0xA8, 0xCD, 0xE8, 0xF0, 0xEF, 0x40,
+ 0xB8, 0x7A, 0x4B, 0xED, 0x2B, 0xAF, 0xBF, 0x57
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes192ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes192ctr,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+ .auth_key = {
+ .data = {
+ 0x87, 0x61, 0x54, 0x53, 0xC4, 0x6D, 0xDD, 0x51,
+ 0xE1, 0x9F, 0x86, 0x64, 0x39, 0x0A, 0xE6, 0x59
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0xCA, 0x33, 0xB3, 0x3B, 0x16, 0x94, 0xAA, 0x55,
+ 0x36, 0x6B, 0x45, 0x46
+ },
+ .len = 12,
+ .truncated_len = 12
+ }
+};
+
+/** AES-256-CTR SHA1 test vector */
+static const struct blockcipher_test_data aes_test_data_3 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes256ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes256ctr,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x3B, 0x1A, 0x9D, 0x82, 0x35, 0xD5, 0xDD, 0x64,
+ 0xCC, 0x1B, 0xA9, 0xC0, 0xEB, 0xE9, 0x42, 0x16,
+ 0xE7, 0x87, 0xA3, 0xEF
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/* AES128-CTR-SHA1 test vector (12-byte IV) */
+static const struct blockcipher_test_data aes_test_data_1_IV_12_bytes = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = plaintext_aes128ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes128ctr_IV_12bytes,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x5C, 0x34, 0x6B, 0xE4, 0x9A, 0x7F, 0x4A, 0xC3,
+ 0x82, 0xBE, 0xA0, 0x12, 0xD1, 0xF0, 0x15, 0xFA,
+ 0xCF, 0xC8, 0x7F, 0x60
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/** AES-192-CTR XCBC test vector (12-byte IV) */
+static const struct blockcipher_test_data aes_test_data_2_IV_12_bytes = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xCB, 0xC5, 0xED, 0x5B, 0xE7, 0x7C, 0xBD, 0x8C,
+ 0x50, 0xD9, 0x30, 0xF2, 0xB5, 0x6A, 0x0E, 0x5F,
+ 0xAA, 0xAE, 0xAD, 0xA2, 0x1F, 0x49, 0x52, 0xD4
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x3F, 0x69, 0xA8, 0xCD, 0xE8, 0xF0, 0xEF, 0x40,
+ 0xB8, 0x7A, 0x4B, 0xED
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = plaintext_aes192ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes192ctr_IV_12bytes,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+ .auth_key = {
+ .data = {
+ 0x87, 0x61, 0x54, 0x53, 0xC4, 0x6D, 0xDD, 0x51,
+ 0xE1, 0x9F, 0x86, 0x64, 0x39, 0x0A, 0xE6, 0x59
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0x0C, 0xA1, 0xA5, 0xAF, 0x3E, 0x41, 0xD2, 0xF4,
+ 0x4C, 0x4C, 0xAB, 0x13
+ },
+ .len = 12,
+ .truncated_len = 12
+ }
+};
+
+/** AES-256-CTR SHA1 test vector (12-byte IV) */
+static const struct blockcipher_test_data aes_test_data_3_IV_12_bytes = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ 0xF8, 0xF9, 0xFA, 0xFB
+ },
+ .len = 12
+ },
+ .plaintext = {
+ .data = plaintext_aes256ctr,
+ .len = 64
+ },
+ .ciphertext = {
+ .data = ciphertext64_aes256ctr_IV_12bytes,
+ .len = 64
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x57, 0x9A, 0x52, 0x6E, 0x31, 0x17, 0x57, 0x49,
+ 0xE7, 0xA1, 0x88, 0x6C, 0x2E, 0x36, 0x67, 0x63,
+ 0x3F, 0x2D, 0xA3, 0xEF
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+/** AES-128-CBC SHA1 test vector */
+static const struct blockcipher_test_data aes_test_data_4 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x9A, 0x4F, 0x88, 0x1B, 0xB6, 0x8F, 0xD8, 0x60,
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0x18, 0x8C, 0x1D, 0x32
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/** AES-128-CBC SHA256 test vector */
+static const struct blockcipher_test_data aes_test_data_5 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x61, 0x1C, 0x42, 0x10, 0x76,
+ 0x9A, 0x4F, 0x88, 0x1B, 0xB6, 0x8F, 0xD8, 0x60
+ },
+ .len = 32
+ },
+ .digest = {
+ .data = {
+ 0xC8, 0x57, 0x57, 0x31, 0x03, 0xE0, 0x03, 0x55,
+ 0x07, 0xC8, 0x9E, 0x7F, 0x48, 0x9A, 0x61, 0x9A,
+ 0x68, 0xEE, 0x03, 0x0E, 0x71, 0x75, 0xC7, 0xF4,
+ 0x2E, 0x45, 0x26, 0x32, 0x7C, 0x12, 0x15, 0x15
+ },
+ .len = 32,
+ .truncated_len = 16
+ }
+};
+
+/** AES-128-CBC SHA512 test vector */
+static const struct blockcipher_test_data aes_test_data_6 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+ },
+ .len = 64
+ },
+ .digest = {
+ .data = {
+ 0x5D, 0x54, 0x66, 0xC1, 0x6E, 0xBC, 0x04, 0xB8,
+ 0x46, 0xB8, 0x08, 0x6E, 0xE0, 0xF0, 0x43, 0x48,
+ 0x37, 0x96, 0x9C, 0xC6, 0x9C, 0xC2, 0x1E, 0xE8,
+ 0xF2, 0x0C, 0x0B, 0xEF, 0x86, 0xA2, 0xE3, 0x70,
+ 0x95, 0xC8, 0xB3, 0x06, 0x47, 0xA9, 0x90, 0xE8,
+ 0xA0, 0xC6, 0x72, 0x69, 0x05, 0xC0, 0x0D, 0x0E,
+ 0x21, 0x96, 0x65, 0x93, 0x74, 0x43, 0x2A, 0x1D,
+ 0x2E, 0xBF, 0xC2, 0xC2, 0xEE, 0xCC, 0x2F, 0x0A
+ },
+ .len = 64,
+ .truncated_len = 32
+ }
+};
+
+/** AES-128-CBC XCBC test vector */
+static const struct blockcipher_test_data aes_test_data_7 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+ .auth_key = {
+ .data = {
+ 0x87, 0x61, 0x54, 0x53, 0xC4, 0x6D, 0xDD, 0x51,
+ 0xE1, 0x9F, 0x86, 0x64, 0x39, 0x0A, 0xE6, 0x59
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0xE0, 0xAC, 0x9A, 0xC4, 0x22, 0x64, 0x35, 0x89,
+ 0x77, 0x1D, 0x8B, 0x75
+ },
+ .len = 12,
+ .truncated_len = 12
+ }
+};
+
+/** AES-128-CBC SHA224 test vector */
+static const struct blockcipher_test_data aes_test_data_8 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+ },
+ .len = 64
+ },
+ .digest = {
+ .data = {
+ 0xA3, 0xCA, 0xC7, 0x1D, 0xA8, 0x61, 0x30, 0x98,
+ 0x3B, 0x8F, 0x01, 0x19, 0xAE, 0x8D, 0xBD, 0x34,
+ 0x40, 0x63, 0xA8, 0x2F, 0xDF, 0x85, 0x2B, 0x7F,
+ 0x63, 0x7C, 0xDD, 0xB7
+ },
+ .len = 28,
+ .truncated_len = 14
+ }
+};
+
+/** AES-128-CBC SHA384 test vector */
+static const struct blockcipher_test_data aes_test_data_9 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60,
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x65, 0x1C, 0x42, 0x50, 0x76,
+ 0x9A, 0xAF, 0x88, 0x1B, 0xB6, 0x8F, 0xF8, 0x60,
+ 0xA2, 0x5A, 0x7F, 0x3F, 0xF4, 0x72, 0x70, 0xF1,
+ 0xF5, 0x35, 0x4C, 0x3B, 0xDD, 0x90, 0x65, 0xB0,
+ 0x47, 0x3A, 0x75, 0x61, 0x5C, 0xA2, 0x10, 0x76,
+ 0x9A, 0xAF, 0x77, 0x5B, 0xB6, 0x7F, 0xF7, 0x60
+ },
+ .len = 128
+ },
+ .digest = {
+ .data = {
+ 0x23, 0x60, 0xC8, 0xB1, 0x2D, 0x6C, 0x1E, 0x72,
+ 0x25, 0xAB, 0xF9, 0xC3, 0x9A, 0xA9, 0x4F, 0x8C,
+ 0x56, 0x38, 0x65, 0x0E, 0x74, 0xD5, 0x45, 0x9D,
+ 0xA3, 0xFD, 0x7E, 0x6D, 0x9E, 0x74, 0x88, 0x9D,
+ 0xA7, 0x12, 0x9D, 0xD8, 0x81, 0x3C, 0x86, 0x2F,
+ 0x4D, 0xF9, 0x6F, 0x0A, 0xB0, 0xC9, 0xEB, 0x0B
+ },
+ .len = 48,
+ .truncated_len = 24
+ }
+};
+
+static const uint8_t ciphertext512_aes192cbc[] = {
+ 0x45, 0xEE, 0x9A, 0xEA, 0x3C, 0x03, 0xFC, 0x4C,
+ 0x84, 0x36, 0xB0, 0xDA, 0xB0, 0xDC, 0xF3, 0x5B,
+ 0x75, 0xA7, 0xBE, 0x0E, 0xC0, 0x8D, 0x6C, 0xF8,
+ 0xC1, 0x0F, 0xD0, 0x35, 0x1D, 0x82, 0xAE, 0x7C,
+ 0x57, 0xC5, 0x7A, 0x55, 0x87, 0x1B, 0xD4, 0x03,
+ 0x0A, 0x64, 0xC9, 0xE0, 0xF4, 0xC7, 0x6F, 0x57,
+ 0x52, 0xC6, 0x73, 0xBA, 0x84, 0x0B, 0x5B, 0x89,
+ 0x21, 0xD2, 0x9B, 0x88, 0x68, 0xF5, 0xA9, 0x7F,
+ 0x3F, 0x49, 0xEB, 0xF4, 0xD4, 0x52, 0xD2, 0x64,
+ 0x80, 0xB2, 0x53, 0xDA, 0x19, 0xF6, 0x10, 0x24,
+ 0x23, 0x26, 0x7A, 0x7C, 0x07, 0x57, 0x4B, 0x0E,
+ 0x58, 0x49, 0x61, 0xD1, 0xDC, 0x9A, 0x32, 0x6B,
+ 0x0F, 0x43, 0x9E, 0x4D, 0xB4, 0x07, 0x4E, 0xB3,
+ 0x51, 0x74, 0xDE, 0x29, 0xBC, 0x98, 0xF9, 0xDF,
+ 0x78, 0x9A, 0x18, 0x9C, 0xD6, 0x7A, 0x55, 0x7C,
+ 0xE6, 0x1D, 0x5C, 0x1A, 0x99, 0xD2, 0xC3, 0x7B,
+ 0x9F, 0x96, 0x74, 0x2D, 0xE0, 0xEF, 0xD1, 0xE3,
+ 0x08, 0x9F, 0xAF, 0xE6, 0xED, 0xCA, 0xE1, 0xEA,
+ 0x23, 0x6F, 0x7C, 0x81, 0xA8, 0xC0, 0x5B, 0x8B,
+ 0x53, 0x90, 0x51, 0x2D, 0x0F, 0xF6, 0x7D, 0xA7,
+ 0x1C, 0xBD, 0x83, 0x84, 0x54, 0xA4, 0x15, 0xFB,
+ 0x3E, 0x25, 0xA7, 0x3A, 0x0A, 0x73, 0xD9, 0x88,
+ 0x6F, 0x80, 0x78, 0x95, 0x7F, 0x60, 0xAA, 0x86,
+ 0x8A, 0xFC, 0xDF, 0xC1, 0xCB, 0xDE, 0xBB, 0x25,
+ 0x52, 0x20, 0xC6, 0x79, 0xD4, 0x0F, 0x25, 0xE7,
+ 0xDB, 0xB2, 0x17, 0xA4, 0x6F, 0x3C, 0x6F, 0x91,
+ 0xF6, 0x44, 0x1E, 0xB6, 0x85, 0xBC, 0x7A, 0x14,
+ 0x10, 0x72, 0xBD, 0x16, 0x63, 0x39, 0x9E, 0x7B,
+ 0x84, 0x5B, 0x17, 0x61, 0xB1, 0x5D, 0x82, 0x0B,
+ 0x6D, 0x37, 0xD7, 0x79, 0xB8, 0x24, 0x91, 0x30,
+ 0x82, 0x91, 0x02, 0xB1, 0x18, 0x4B, 0xE0, 0xF4,
+ 0x13, 0x1B, 0xB2, 0x4C, 0xDA, 0xB8, 0x99, 0x96,
+ 0x83, 0x2F, 0xBE, 0x53, 0x8D, 0xDE, 0xFA, 0xAD,
+ 0xF6, 0x5C, 0xDB, 0xE5, 0x66, 0x26, 0x8F, 0x13,
+ 0x2B, 0x76, 0x47, 0x73, 0xDE, 0x1A, 0x74, 0xA6,
+ 0x30, 0xAF, 0x42, 0xA0, 0xE5, 0xD2, 0x8F, 0xC2,
+ 0xED, 0x3E, 0x9E, 0x29, 0x54, 0x3C, 0xDE, 0x9F,
+ 0x5D, 0x30, 0x2B, 0x63, 0xFB, 0xE3, 0xB1, 0x07,
+ 0xEE, 0x74, 0x4A, 0xAF, 0xB1, 0x20, 0x8D, 0xEC,
+ 0xE6, 0x78, 0x16, 0x8D, 0xA4, 0x6E, 0x34, 0x7D,
+ 0x47, 0xFB, 0x0B, 0xC1, 0x32, 0xD7, 0x0D, 0x6C,
+ 0x6F, 0x93, 0x9C, 0x5E, 0xEF, 0x1F, 0x9C, 0x45,
+ 0x80, 0x6B, 0x74, 0xA6, 0x81, 0xF2, 0xF6, 0xFA,
+ 0xAA, 0x9D, 0x4F, 0xCA, 0xB5, 0x90, 0x59, 0xB0,
+ 0x3B, 0xF2, 0xF0, 0x75, 0xFD, 0x8A, 0xD8, 0x97,
+ 0x65, 0x88, 0x56, 0x4C, 0x44, 0xDF, 0x73, 0xF7,
+ 0x56, 0x9C, 0x48, 0x7E, 0xB0, 0x1F, 0x1D, 0x7D,
+ 0x6A, 0x11, 0xF5, 0xC2, 0xF4, 0x17, 0xEF, 0x58,
+ 0xD8, 0x2A, 0xAF, 0x56, 0x2F, 0xCF, 0xEC, 0xA4,
+ 0x58, 0x8B, 0x60, 0xCE, 0xD4, 0x0F, 0x9C, 0x21,
+ 0xEC, 0x3E, 0x74, 0x7B, 0x81, 0x3D, 0x69, 0xC6,
+ 0x5E, 0x12, 0x83, 0xE9, 0xEF, 0x81, 0x58, 0x36,
+ 0x6A, 0x60, 0x0F, 0x54, 0x28, 0x11, 0xF9, 0x64,
+ 0x36, 0xAD, 0x79, 0xF5, 0x1C, 0x74, 0xD0, 0xC3,
+ 0x7B, 0x61, 0xE1, 0x92, 0xB0, 0x13, 0x91, 0x87,
+ 0x32, 0x1F, 0xF2, 0x5A, 0xDA, 0x25, 0x69, 0xEB,
+ 0xD7, 0x32, 0x7F, 0xF5, 0x23, 0x21, 0x54, 0x47,
+ 0x7B, 0x1B, 0x33, 0xB0, 0x3D, 0xF6, 0xE2, 0x7E,
+ 0x3E, 0xA2, 0x9E, 0xCA, 0x48, 0x0B, 0x4A, 0x29,
+ 0x81, 0xD4, 0x4E, 0xD5, 0x69, 0xFB, 0xCD, 0x37,
+ 0x8A, 0xC1, 0x5B, 0x50, 0xFF, 0xB5, 0x7D, 0x43,
+ 0x0F, 0xAE, 0xA6, 0xC2, 0xE5, 0x8F, 0x45, 0xB2,
+ 0x85, 0x99, 0x02, 0xA2, 0x9B, 0xBE, 0x90, 0x43,
+ 0x4F, 0x2F, 0x50, 0xE2, 0x77, 0x62, 0xD9, 0xCC
+};
+
+/** AES-192-CBC test vector */
+static const struct blockcipher_test_data aes_test_data_10 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes192cbc,
+ .len = 512
+ }
+};
+
+static const uint8_t ciphertext512_aes256cbc[] = {
+ 0xF3, 0xDD, 0xF0, 0x0B, 0xFF, 0xA2, 0x6A, 0x04,
+ 0xBE, 0xDA, 0x52, 0xA6, 0xFE, 0x6B, 0xA6, 0xA7,
+ 0x48, 0x1D, 0x7D, 0x98, 0x65, 0xDB, 0xEF, 0x06,
+ 0x26, 0xB5, 0x8E, 0xEB, 0x05, 0x0E, 0x77, 0x98,
+ 0x17, 0x8E, 0xD0, 0xD4, 0x7B, 0x92, 0x8F, 0x5C,
+ 0xD0, 0x74, 0x5C, 0xA8, 0x4B, 0x54, 0xB6, 0x2F,
+ 0x83, 0x72, 0x2C, 0xFF, 0x72, 0xE9, 0xE4, 0x15,
+ 0x4C, 0x32, 0xAF, 0xC8, 0xC9, 0x89, 0x3C, 0x6E,
+ 0x31, 0xD5, 0xC0, 0x16, 0xC0, 0x31, 0x7D, 0x11,
+ 0xAB, 0xCB, 0xDE, 0xD2, 0xD6, 0xAA, 0x76, 0x5E,
+ 0xBA, 0xF6, 0xE2, 0x92, 0xCB, 0x86, 0x07, 0xFA,
+ 0xD4, 0x9E, 0x83, 0xED, 0xFD, 0xB8, 0x70, 0x54,
+ 0x6B, 0xBE, 0xEC, 0x72, 0xDD, 0x28, 0x5E, 0x95,
+ 0x78, 0xA5, 0x28, 0x43, 0x3D, 0x6D, 0xB1, 0xD9,
+ 0x69, 0x1F, 0xC9, 0x66, 0x0E, 0x32, 0x44, 0x08,
+ 0xD2, 0xAE, 0x2C, 0x43, 0xF2, 0xD0, 0x7D, 0x26,
+ 0x70, 0xE5, 0xA1, 0xCA, 0x37, 0xE9, 0x7D, 0xC7,
+ 0xA3, 0xFA, 0x81, 0x91, 0x64, 0xAA, 0x64, 0x91,
+ 0x9A, 0x95, 0x2D, 0xC9, 0xF9, 0xCE, 0xFE, 0x9F,
+ 0xC4, 0xD8, 0x81, 0xBE, 0x57, 0x84, 0xC5, 0x02,
+ 0xDB, 0x30, 0xC1, 0xD9, 0x0E, 0xA0, 0xA6, 0x00,
+ 0xD6, 0xF3, 0x52, 0x7E, 0x0D, 0x23, 0x6B, 0x2B,
+ 0x34, 0x99, 0x1F, 0x70, 0x27, 0x6D, 0x58, 0x84,
+ 0x93, 0x77, 0xB8, 0x3E, 0xF1, 0x71, 0x58, 0x42,
+ 0x8B, 0x2B, 0xC8, 0x6D, 0x05, 0x84, 0xFF, 0x4E,
+ 0x85, 0xEF, 0x4A, 0x9D, 0x91, 0x6A, 0xD5, 0xE1,
+ 0xAF, 0x01, 0xEB, 0x83, 0x8F, 0x23, 0x7C, 0x7F,
+ 0x12, 0x91, 0x05, 0xF0, 0x4E, 0xD9, 0x17, 0x62,
+ 0x75, 0xBB, 0xAC, 0x97, 0xEE, 0x3B, 0x4E, 0xC7,
+ 0xE5, 0x92, 0xF8, 0x9D, 0x4C, 0xF9, 0xEE, 0x55,
+ 0x18, 0xBB, 0xCC, 0xB4, 0xF2, 0x59, 0xB9, 0xFC,
+ 0x7A, 0x0F, 0x98, 0xD4, 0x8B, 0xFE, 0xF7, 0x83,
+ 0x46, 0xE2, 0x83, 0x33, 0x3E, 0x95, 0x8D, 0x17,
+ 0x1E, 0x85, 0xF8, 0x8C, 0x51, 0xB0, 0x6C, 0xB5,
+ 0x5E, 0x95, 0xBA, 0x4B, 0x69, 0x1B, 0x48, 0x69,
+ 0x0B, 0x8F, 0xA5, 0x18, 0x13, 0xB9, 0x77, 0xD1,
+ 0x80, 0x32, 0x32, 0x6D, 0x53, 0xA1, 0x95, 0x40,
+ 0x96, 0x8A, 0xCC, 0xA3, 0x69, 0xF8, 0x9F, 0xB5,
+ 0x8E, 0xD2, 0x68, 0x07, 0x4F, 0xA7, 0xEC, 0xF8,
+ 0x20, 0x21, 0x58, 0xF8, 0xD8, 0x9E, 0x5F, 0x40,
+ 0xBA, 0xB9, 0x76, 0x57, 0x3B, 0x17, 0xAD, 0xEE,
+ 0xCB, 0xDF, 0x07, 0xC1, 0xDF, 0x66, 0xA8, 0x0D,
+ 0xC2, 0xCE, 0x8F, 0x79, 0xC3, 0x32, 0xE0, 0x8C,
+ 0xFE, 0x5A, 0xF3, 0x55, 0x27, 0x73, 0x6F, 0xA1,
+ 0x54, 0xC6, 0xFC, 0x28, 0x9D, 0xBE, 0x97, 0xB9,
+ 0x54, 0x97, 0x72, 0x3A, 0x61, 0xAF, 0x6F, 0xDE,
+ 0xF8, 0x0E, 0xBB, 0x6B, 0x96, 0x84, 0xDD, 0x9B,
+ 0x62, 0xBA, 0x47, 0xB5, 0xC9, 0x3B, 0x4E, 0x8C,
+ 0x78, 0x2A, 0xCC, 0x0A, 0x69, 0x54, 0x25, 0x5E,
+ 0x8B, 0xAC, 0x56, 0xD9, 0xFE, 0x48, 0xBA, 0xCE,
+ 0xA9, 0xCE, 0xA6, 0x1D, 0xBF, 0x3E, 0x3C, 0x66,
+ 0x40, 0x71, 0x79, 0xAD, 0x5B, 0x26, 0xAD, 0xBE,
+ 0x58, 0x13, 0x64, 0x60, 0x7C, 0x05, 0xFC, 0xE3,
+ 0x51, 0x7A, 0xF2, 0xCC, 0x54, 0x16, 0x2C, 0xA4,
+ 0xCE, 0x5F, 0x59, 0x12, 0x77, 0xEB, 0xD9, 0x23,
+ 0xE3, 0x86, 0xFB, 0xD7, 0x48, 0x76, 0x9D, 0xE3,
+ 0x89, 0x87, 0x39, 0xFA, 0x7B, 0x21, 0x0B, 0x76,
+ 0xB2, 0xED, 0x1C, 0x27, 0x4B, 0xD5, 0x27, 0x05,
+ 0x8C, 0x7D, 0x58, 0x6C, 0xCA, 0xA5, 0x54, 0x9A,
+ 0x0F, 0xCB, 0xE9, 0x88, 0x31, 0xAD, 0x49, 0xEE,
+ 0x38, 0xFB, 0xC9, 0xFB, 0xB4, 0x7A, 0x00, 0x58,
+ 0x20, 0x32, 0xD3, 0x53, 0x5A, 0xDD, 0x74, 0x95,
+ 0x60, 0x59, 0x09, 0xAE, 0x7E, 0xEC, 0x74, 0xA3,
+ 0xB7, 0x1C, 0x6D, 0xF2, 0xAE, 0x79, 0xA4, 0x7C
+};
+
+/** AES-256-CBC test vector */
+static const struct blockcipher_test_data aes_test_data_11 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0,
+ 0x37, 0x07, 0xB8, 0x23, 0xA2, 0xA3, 0xB5, 0x8D
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes256cbc,
+ .len = 512
+ }
+};
+
+/** AES-128-CBC SHA256 HMAC test vector (160 bytes) */
+static const struct blockcipher_test_data aes_test_data_12 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 160
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 160
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .auth_key = {
+ .data = {
+ 0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+ 0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+ 0x58, 0x34, 0x85, 0x61, 0x1C, 0x42, 0x10, 0x76,
+ 0x9A, 0x4F, 0x88, 0x1B, 0xB6, 0x8F, 0xD8, 0x60
+ },
+ .len = 32
+ },
+ .digest = {
+ .data = {
+ 0x92, 0xEC, 0x65, 0x9A, 0x52, 0xCC, 0x50, 0xA5,
+ 0xEE, 0x0E, 0xDF, 0x1E, 0xA4, 0xC9, 0xC1, 0x04,
+ 0xD5, 0xDC, 0x78, 0x90, 0xF4, 0xE3, 0x35, 0x62,
+ 0xAD, 0x95, 0x45, 0x28, 0x5C, 0xF8, 0x8C, 0x0B
+ },
+ .len = 32,
+ .truncated_len = 16
+ }
+};
+
+/** AES-128-CBC SHA1 HMAC test vector (160 bytes) */
+static const struct blockcipher_test_data aes_test_data_13 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 160
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 160
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x4F, 0x16, 0xEA, 0xF7, 0x4A, 0x88, 0xD3, 0xE0,
+ 0x0E, 0x12, 0x8B, 0xE7, 0x05, 0xD0, 0x86, 0x48,
+ 0x22, 0x43, 0x30, 0xA7
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+/** XTS-AES-128 test vector (2 keys * 128 bit) */
+static const uint8_t plaintext_aes128xts_16bytes[] = {
+ 0xEB, 0xAB, 0xCE, 0x95, 0xB1, 0x4D, 0x3C, 0x8D,
+ 0x6F, 0xB3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1C
+};
+static const uint8_t ciphertext_aes128xts_16bytes[] = {
+ 0x77, 0x8A, 0xE8, 0xB4, 0x3C, 0xB9, 0x8D, 0x5A,
+ 0x82, 0x50, 0x81, 0xD5, 0xBE, 0x47, 0x1C, 0x63
+};
+static const struct
+blockcipher_test_data aes_test_data_xts_key_32_pt_16 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_XTS,
+ .cipher_key = {
+ .data = {
+ 0xA1, 0xB9, 0x0C, 0xBA, 0x3F, 0x06, 0xAC, 0x35,
+ 0x3B, 0x2C, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62,
+ 0x09, 0x09, 0x23, 0x02, 0x6E, 0x91, 0x77, 0x18,
+ 0x15, 0xF2, 0x9D, 0xAB, 0x01, 0x93, 0x2F, 0x2F
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x4F, 0xAE, 0xF7, 0x11, 0x7C, 0xDA, 0x59, 0xC6,
+ 0x6E, 0x4B, 0x92, 0x01, 0x3E, 0x76, 0x8A, 0xD5
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes128xts_16bytes,
+ .len = 16
+ },
+ .ciphertext = {
+ .data = ciphertext_aes128xts_16bytes,
+ .len = 16
+ }
+};
+static const uint8_t plaintext_aes128xts_32bytes[] = {
+ 0xB0, 0x4D, 0x84, 0xDA, 0x85, 0x6B, 0x9A, 0x59,
+ 0xCE, 0x2D, 0x62, 0x67, 0x46, 0xF6, 0x89, 0xA8,
+ 0x05, 0x1D, 0xAC, 0xD6, 0xBC, 0xE3, 0xB9, 0x90,
+ 0xAA, 0x90, 0x1E, 0x40, 0x30, 0x64, 0x88, 0x79
+};
+static const uint8_t ciphertext_aes128xts_32bytes[] = {
+ 0xF9, 0x41, 0x03, 0x9E, 0xBA, 0xB8, 0xCA, 0xC3,
+ 0x9D, 0x59, 0x24, 0x7C, 0xBB, 0xCB, 0x4D, 0x81,
+ 0x6C, 0x72, 0x6D, 0xAE, 0xD1, 0x15, 0x77, 0x69,
+ 0x2C, 0x55, 0xE4, 0xAC, 0x6D, 0x3E, 0x68, 0x20
+};
+static const struct
+blockcipher_test_data aes_test_data_xts_key_32_pt_32 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_XTS,
+ .cipher_key = {
+ .data = {
+ 0x78, 0x3A, 0x83, 0xEC, 0x52, 0xA2, 0x74, 0x05,
+ 0xDF, 0xF9, 0xDE, 0x4C, 0x57, 0xF9, 0xC9, 0x79,
+ 0xB3, 0x60, 0xB6, 0xA5, 0xDF, 0x88, 0xD6, 0x7E,
+ 0xC1, 0xA0, 0x52, 0xE6, 0xF5, 0x82, 0xA7, 0x17
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x88, 0x6E, 0x97, 0x5B, 0x29, 0xBD, 0xF6, 0xF0,
+ 0xC0, 0x1B, 0xB4, 0x7F, 0x61, 0xF6, 0xF0, 0xF5
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes128xts_32bytes,
+ .len = 32
+ },
+ .ciphertext = {
+ .data = ciphertext_aes128xts_32bytes,
+ .len = 32
+ }
+};
+
+/** XTS-AES-256 test vector (2 keys * 256 bit) */
+/* Encryption */
+static const uint8_t plaintext_aes256xts_32bytes[] = {
+ 0x2E, 0xED, 0xEA, 0x52, 0xCD, 0x82, 0x15, 0xE1,
+ 0xAC, 0xC6, 0x47, 0xE8, 0x10, 0xBB, 0xC3, 0x64,
+ 0x2E, 0x87, 0x28, 0x7F, 0x8D, 0x2E, 0x57, 0xE3,
+ 0x6C, 0x0A, 0x24, 0xFB, 0xC1, 0x2A, 0x20, 0x2E
+};
+static const uint8_t ciphertext_aes256xts_32bytes[] = {
+ 0xCB, 0xAA, 0xD0, 0xE2, 0xF6, 0xCE, 0xA3, 0xF5,
+ 0x0B, 0x37, 0xF9, 0x34, 0xD4, 0x6A, 0x9B, 0x13,
+ 0x0B, 0x9D, 0x54, 0xF0, 0x7E, 0x34, 0xF3, 0x6A,
+ 0xF7, 0x93, 0xE8, 0x6F, 0x73, 0xC6, 0xD7, 0xDB
+};
+static const struct
+blockcipher_test_data aes_test_data_xts_key_64_pt_32 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_XTS,
+ .cipher_key = {
+ .data = {
+ 0x1E, 0xA6, 0x61, 0xC5, 0x8D, 0x94, 0x3A, 0x0E,
+ 0x48, 0x01, 0xE4, 0x2F, 0x4B, 0x09, 0x47, 0x14,
+ 0x9E, 0x7F, 0x9F, 0x8E, 0x3E, 0x68, 0xD0, 0xC7,
+ 0x50, 0x52, 0x10, 0xBD, 0x31, 0x1A, 0x0E, 0x7C,
+ 0xD6, 0xE1, 0x3F, 0xFD, 0xF2, 0x41, 0x8D, 0x8D,
+ 0x19, 0x11, 0xC0, 0x04, 0xCD, 0xA5, 0x8D, 0xA3,
+ 0xD6, 0x19, 0xB7, 0xE2, 0xB9, 0x14, 0x1E, 0x58,
+ 0x31, 0x8E, 0xEA, 0x39, 0x2C, 0xF4, 0x1B, 0x08
+ },
+ .len = 64
+ },
+ .iv = {
+ .data = {
+ 0xAD, 0xF8, 0xD9, 0x26, 0x27, 0x46, 0x4A, 0xD2,
+ 0xF0, 0x42, 0x8E, 0x84, 0xA9, 0xF8, 0x75, 0x64
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes256xts_32bytes,
+ .len = 32
+ },
+ .ciphertext = {
+ .data = ciphertext_aes256xts_32bytes,
+ .len = 32
+ }
+};
+static const uint8_t plaintext_aes256xts_48bytes[] = {
+ 0xBB, 0xB2, 0x34, 0xDB, 0x01, 0xBE, 0x79, 0xD3,
+ 0xDC, 0x7D, 0xCF, 0x49, 0xBC, 0x53, 0xB8, 0xEF,
+ 0xC6, 0x2F, 0xE7, 0x17, 0x94, 0x39, 0x06, 0x1D,
+ 0x73, 0xA6, 0xB2, 0x0E, 0xDB, 0x9B, 0x7D, 0xA0,
+ 0x45, 0x0B, 0x19, 0xF0, 0x20, 0x82, 0x02, 0x09,
+ 0xAF, 0xE0, 0x81, 0x12, 0xAE, 0x4A, 0xFD, 0xD3
+};
+static const uint8_t ciphertext_aes256xts_48bytes[] = {
+ 0xCB, 0xF6, 0x88, 0x48, 0xC4, 0x20, 0x49, 0xEF,
+ 0xB1, 0x46, 0xE2, 0xD1, 0xE4, 0x11, 0x5F, 0x62,
+ 0xE4, 0xFA, 0xA4, 0xEF, 0xFF, 0x19, 0x8F, 0x1A,
+ 0x0A, 0xA0, 0xC9, 0x8B, 0xA0, 0x2C, 0xC4, 0x4D,
+ 0xA3, 0x76, 0xD7, 0x62, 0xD6, 0x15, 0x1F, 0x23,
+ 0x45, 0x87, 0xBF, 0x12, 0x8B, 0x6A, 0x7F, 0xFA
+};
+static const struct
+blockcipher_test_data aes_test_data_xts_key_64_pt_48 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_XTS,
+ .cipher_key = {
+ .data = {
+ 0x7F, 0xB0, 0x92, 0x2F, 0xCE, 0x09, 0xED, 0xDD,
+ 0x36, 0x65, 0xA1, 0x1F, 0x52, 0x35, 0xD5, 0x1E,
+ 0xF7, 0x72, 0x06, 0xA7, 0xDE, 0x45, 0x47, 0x75,
+ 0xB6, 0x9D, 0xCC, 0x54, 0x59, 0xAC, 0xDB, 0x24,
+ 0xCC, 0xF0, 0x5C, 0x41, 0x5A, 0xF5, 0xAB, 0x8A,
+ 0x06, 0x62, 0x3D, 0x19, 0x8D, 0x5B, 0x91, 0x85,
+ 0x95, 0xA9, 0xDC, 0xAA, 0xF5, 0x39, 0x2E, 0xE7,
+ 0x17, 0xC1, 0x04, 0x7F, 0x2F, 0x08, 0xF6, 0x2B
+ },
+ .len = 64
+ },
+ .iv = {
+ .data = {
+ 0x8E, 0xA3, 0x63, 0x8B, 0x9D, 0x40, 0x62, 0xF1,
+ 0x69, 0x19, 0x6F, 0xF4, 0x55, 0x5A, 0xD0, 0xAF
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes256xts_48bytes,
+ .len = 48
+ },
+ .ciphertext = {
+ .data = ciphertext_aes256xts_48bytes,
+ .len = 48
+ }
+};
+
+/* AES-DOCSIS-BPI test vectors */
+
+/* Multiple of AES block size */
+static const struct blockcipher_test_data aes_test_data_docsis_1 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes128cbc,
+ .len = 512
+ }
+};
+
+/* Less than AES block size */
+static const struct blockcipher_test_data aes_test_data_docsis_2 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A,
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_docsis_bpi_cfb,
+ .len = 7
+ },
+ .ciphertext = {
+ .data = ciphertext_aes_docsis_bpi_cfb,
+ .len = 7
+ }
+};
+
+/* Not multiple of AES block size */
+static const struct blockcipher_test_data aes_test_data_docsis_3 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A,
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_docsis_bpi_cbc_cfb,
+ .len = 19
+ },
+ .ciphertext = {
+ .data = ciphertext_aes_docsis_bpi_cbc_cfb,
+ .len = 19
+ }
+};
+
+/* Multiple of AES 256 block size */
+static const struct blockcipher_test_data aes_test_data_docsis_4 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0,
+ 0x37, 0x07, 0xB8, 0x23, 0xA2, 0xA3, 0xB5, 0x8D
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_aes256cbc,
+ .len = 512
+ }
+};
+
+/* Less than AES 256 block size */
+static const struct blockcipher_test_data aes_test_data_docsis_5 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A,
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_docsis_bpi_cfb,
+ .len = 7
+ },
+ .ciphertext = {
+ .data = ciphertext_aes256_docsis_bpi_cfb,
+ .len = 7
+ }
+};
+
+/* Not multiple of AES 256 block size */
+static const struct blockcipher_test_data aes_test_data_docsis_6 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB,
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 32
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A,
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_docsis_bpi_cbc_cfb,
+ .len = 19
+ },
+ .ciphertext = {
+ .data = ciphertext_aes256_docsis_bpi_cbc_cfb,
+ .len = 19
+ }
+};
+
+static const uint8_t
+cipher_aescbc_offset_16[] = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+ 0x68, 0x2A, 0x6A, 0x82, 0xE0, 0x73, 0xC7, 0x51,
+ 0x81, 0xF4, 0x47, 0x27, 0x1A, 0xEF, 0x76, 0x15,
+ 0x1C, 0xE1, 0x38, 0x5F, 0xE1, 0x81, 0x77, 0xC7,
+ 0x8B, 0xF0, 0x69, 0xC3, 0x3C, 0x45, 0x1C, 0x0A,
+ 0xA3, 0x93, 0xBF, 0x60, 0x57, 0x88, 0xD2, 0xFF,
+ 0xE1, 0x8F, 0xC0, 0x64, 0x2C, 0x42, 0xC5, 0x22,
+ 0xE3, 0x5F, 0x71, 0x1F, 0xF7, 0x62, 0xA2, 0x7E,
+ 0x0D, 0x42, 0xD9, 0xE7, 0xF3, 0x10, 0xB0, 0xEE,
+};
+
+/** AES-128-CBC SHA1 OOP test vector for swapping src/dst */
+static const struct blockcipher_test_data aes_test_data_14 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = plaintext_aes_common,
+ .len = 80
+ },
+ .cipher_offset = 16,
+ .auth_offset = 0,
+ .ciphertext = {
+ .data = cipher_aescbc_offset_16,
+ .len = 80
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0xCC, 0x15, 0x83, 0xF7, 0x23, 0x87, 0x96, 0xA7,
+ 0x29, 0x34, 0x32, 0xE4, 0x4C, 0x06, 0xE8, 0xEB,
+ 0x70, 0x72, 0x4B, 0xAD
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+static const struct blockcipher_test_case aes_chain_test_cases[] = {
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify OOP Offset",
+ .test_data = &aes_test_data_14,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CTR HMAC-SHA1 Encryption Digest",
+ .test_data = &aes_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CTR HMAC-SHA1 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-192-CTR XCBC Encryption Digest",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-192-CTR XCBC Decryption Digest Verify",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-192-CTR XCBC Decryption Digest Verify "
+ "Scatter Gather",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-CTR HMAC-SHA1 Encryption Digest",
+ .test_data = &aes_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-256-CTR HMAC-SHA1 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "(short buffers)",
+ .test_data = &aes_test_data_13,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "Scatter Gather",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify Scatter Gather",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify (short buffers)",
+ .test_data = &aes_test_data_13,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA256 Encryption Digest",
+ .test_data = &aes_test_data_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA256 Encryption Digest "
+ "(short buffers)",
+ .test_data = &aes_test_data_12,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA256 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA256 Decryption Digest "
+ "Verify (short buffers)",
+ .test_data = &aes_test_data_12,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+ "Sessionless",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+ "Scatter Gather Sessionless",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+ BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
+ "Verify Scatter Gather",
+ .test_data = &aes_test_data_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC XCBC Encryption Digest",
+ .test_data = &aes_test_data_7,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC XCBC Decryption Digest Verify",
+ .test_data = &aes_test_data_7,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "OOP",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "OOP Offset",
+ .test_data = &aes_test_data_14,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify OOP",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA224 Encryption Digest",
+ .test_data = &aes_test_data_8,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA224 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_8,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA384 Encryption Digest",
+ .test_data = &aes_test_data_9,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA384 Decryption Digest "
+ "Verify",
+ .test_data = &aes_test_data_9,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+ "Sessionless",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
+ },
+ {
+ .test_descr =
+ "AES-128-CBC HMAC-SHA1 Decryption Digest "
+ "Verify Sessionless",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x8byte",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x8byte",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x8byte - OOP",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x8byte - OOP",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x4byte",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x4byte",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x4byte - OOP",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x4byte - OOP",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x1byte",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x1byte",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "NULL-CIPHER-NULL-AUTH encrypt & gen x1byte - OOP",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL-AUTH-NULL-CIPHER verify & decrypt x1byte - OOP",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+};
+
+static const struct blockcipher_test_case aes_cipheronly_test_cases[] = {
+ {
+ .test_descr = "AES-128-CBC Encryption",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-128-CBC Decryption",
+ .test_data = &aes_test_data_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-192-CBC Encryption",
+ .test_data = &aes_test_data_10,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-192-CBC Encryption Scater gather",
+ .test_data = &aes_test_data_10,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+ BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-192-CBC Decryption",
+ .test_data = &aes_test_data_10,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-192-CBC Decryption Scatter Gather",
+ .test_data = &aes_test_data_10,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+ },
+ {
+ .test_descr = "AES-256-CBC Encryption",
+ .test_data = &aes_test_data_11,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-CBC Decryption",
+ .test_data = &aes_test_data_11,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-CBC OOP Encryption",
+ .test_data = &aes_test_data_11,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-CBC OOP Decryption",
+ .test_data = &aes_test_data_11,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-128-CTR Encryption",
+ .test_data = &aes_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-128-CTR Decryption",
+ .test_data = &aes_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-192-CTR Encryption",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-192-CTR Decryption",
+ .test_data = &aes_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-CTR Encryption",
+ .test_data = &aes_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-CTR Decryption",
+ .test_data = &aes_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-128-CTR Encryption (12-byte IV)",
+ .test_data = &aes_test_data_1_IV_12_bytes,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-192-CTR Encryption (12-byte IV)",
+ .test_data = &aes_test_data_2_IV_12_bytes,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-CTR Encryption (12-byte IV)",
+ .test_data = &aes_test_data_3_IV_12_bytes,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-128-XTS Encryption (16-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_32_pt_16,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-128-XTS Decryption (16-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_32_pt_16,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-128-XTS Encryption (32-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_32_pt_32,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-128-XTS Decryption (32-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_32_pt_32,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-XTS Encryption (32-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_64_pt_32,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-XTS Decryption (32-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_64_pt_32,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-XTS Encryption (48-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_64_pt_48,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-XTS Decryption (48-byte plaintext)",
+ .test_data = &aes_test_data_xts_key_64_pt_48,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x8 - encryption",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x8 - decryption",
+ .test_data = &null_test_data_chain_x8_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x4 - encryption",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x4 - decryption",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x4 - encryption - OOP",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x4 - decryption - OOP",
+ .test_data = &null_test_data_chain_x4_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x1 - encryption",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "cipher-only - NULL algo - x1 - decryption",
+ .test_data = &null_test_data_chain_x1_multiple,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+};
+
+static const struct blockcipher_test_case aes_docsis_test_cases[] = {
+
+ {
+ .test_descr = "AES-DOCSIS-BPI Full Block Encryption",
+ .test_data = &aes_test_data_docsis_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI Runt Block Encryption",
+ .test_data = &aes_test_data_docsis_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI Uneven Encryption",
+ .test_data = &aes_test_data_docsis_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI Full Block Decryption",
+ .test_data = &aes_test_data_docsis_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI Runt Block Decryption",
+ .test_data = &aes_test_data_docsis_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI Uneven Decryption",
+ .test_data = &aes_test_data_docsis_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Full Block Encryption",
+ .test_data = &aes_test_data_docsis_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Runt Block Encryption",
+ .test_data = &aes_test_data_docsis_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Uneven Block Encryption",
+ .test_data = &aes_test_data_docsis_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Full Block Decryption",
+ .test_data = &aes_test_data_docsis_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Runt Block Decryption",
+ .test_data = &aes_test_data_docsis_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-DOCSIS-BPI OOP Uneven Block Decryption",
+ .test_data = &aes_test_data_docsis_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ /* AES 256 */
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Full Block Encryption",
+ .test_data = &aes_test_data_docsis_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Runt Block Encryption",
+ .test_data = &aes_test_data_docsis_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Uneven Encryption",
+ .test_data = &aes_test_data_docsis_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Full Block Decryption",
+ .test_data = &aes_test_data_docsis_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Runt Block Decryption",
+ .test_data = &aes_test_data_docsis_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI Uneven Decryption",
+ .test_data = &aes_test_data_docsis_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Full Block Encryption",
+ .test_data = &aes_test_data_docsis_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Runt Block Encryption",
+ .test_data = &aes_test_data_docsis_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Uneven Block Encryption",
+ .test_data = &aes_test_data_docsis_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Full Block Decryption",
+ .test_data = &aes_test_data_docsis_4,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Runt Block Decryption",
+ .test_data = &aes_test_data_docsis_5,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "AES-256-DOCSIS-BPI OOP Uneven Block Decryption",
+ .test_data = &aes_test_data_docsis_6,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+};
+#endif /* TEST_CRYPTODEV_AES_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_asym.c b/src/spdk/dpdk/app/test/test_cryptodev_asym.c
new file mode 100644
index 000000000..b8e050048
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_asym.c
@@ -0,0 +1,2404 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ * Copyright (c) 2019 Intel Corporation
+ */
+
+#include <rte_bus_vdev.h>
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_pause.h>
+
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_crypto.h>
+
+#include "test_cryptodev.h"
+#include "test_cryptodev_dh_test_vectors.h"
+#include "test_cryptodev_dsa_test_vectors.h"
+#include "test_cryptodev_ecdsa_test_vectors.h"
+#include "test_cryptodev_ecpm_test_vectors.h"
+#include "test_cryptodev_mod_test_vectors.h"
+#include "test_cryptodev_rsa_test_vectors.h"
+#include "test_cryptodev_asym_util.h"
+#include "test.h"
+
+#define TEST_NUM_BUFS 10
+#define TEST_NUM_SESSIONS 4
+
+#ifndef TEST_DATA_SIZE
+ #define TEST_DATA_SIZE 4096
+#endif
+#define ASYM_TEST_MSG_LEN 256
+#define TEST_VECTOR_SIZE 256
+
+static int gbl_driver_id;
+struct crypto_testsuite_params {
+ struct rte_mempool *op_mpool;
+ struct rte_mempool *session_mpool;
+ struct rte_cryptodev_config conf;
+ struct rte_cryptodev_qp_conf qp_conf;
+ uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
+ uint8_t valid_dev_count;
+};
+
+struct crypto_unittest_params {
+ struct rte_cryptodev_asym_session *sess;
+ struct rte_crypto_op *op;
+};
+
+union test_case_structure {
+ struct modex_test_data modex;
+ struct modinv_test_data modinv;
+ struct rsa_test_data_2 rsa_data;
+};
+
+struct test_cases_array {
+ uint32_t size;
+ const void *address[TEST_VECTOR_SIZE];
+};
+static struct test_cases_array test_vector = {0, { NULL } };
+
+static uint32_t test_index;
+
+static struct crypto_testsuite_params testsuite_params = { NULL };
+
+static int
+queue_ops_rsa_sign_verify(struct rte_cryptodev_asym_session *sess)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_op *op, *result_op;
+ struct rte_crypto_asym_op *asym_op;
+ uint8_t output_buf[TEST_DATA_SIZE];
+ int status = TEST_SUCCESS;
+
+ /* Set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1, "Failed to allocate asymmetric crypto "
+ "operation struct\n");
+ return TEST_FAILED;
+ }
+
+ asym_op = op->asym;
+
+ /* Compute sign on the test vector */
+ asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+
+ asym_op->rsa.message.data = rsaplaintext.data;
+ asym_op->rsa.message.length = rsaplaintext.len;
+ asym_op->rsa.sign.length = 0;
+ asym_op->rsa.sign.data = output_buf;
+ asym_op->rsa.pad = RTE_CRYPTO_RSA_PADDING_PKCS1_5;
+
+ debug_hexdump(stdout, "message", asym_op->rsa.message.data,
+ asym_op->rsa.message.length);
+
+ /* Attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1, "Error sending packet for sign\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1, "Failed to process sign op\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ debug_hexdump(stdout, "signed message", asym_op->rsa.sign.data,
+ asym_op->rsa.sign.length);
+ asym_op = result_op->asym;
+
+ /* Verify sign */
+ asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+ asym_op->rsa.pad = RTE_CRYPTO_RSA_PADDING_PKCS1_5;
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1, "Error sending packet for verify\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1, "Failed to process verify op\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ status = TEST_SUCCESS;
+ if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1, "Failed to process sign-verify op\n");
+ status = TEST_FAILED;
+ }
+
+error_exit:
+
+ rte_crypto_op_free(op);
+
+ return status;
+}
+
+static int
+queue_ops_rsa_enc_dec(struct rte_cryptodev_asym_session *sess)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_op *op, *result_op;
+ struct rte_crypto_asym_op *asym_op;
+ uint8_t cipher_buf[TEST_DATA_SIZE] = {0};
+ int ret, status = TEST_SUCCESS;
+
+ /* Set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1, "Failed to allocate asymmetric crypto "
+ "operation struct\n");
+ return TEST_FAILED;
+ }
+
+ asym_op = op->asym;
+
+ /* Compute encryption on the test vector */
+ asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_ENCRYPT;
+
+ asym_op->rsa.message.data = rsaplaintext.data;
+ asym_op->rsa.cipher.data = cipher_buf;
+ asym_op->rsa.cipher.length = 0;
+ asym_op->rsa.message.length = rsaplaintext.len;
+ asym_op->rsa.pad = RTE_CRYPTO_RSA_PADDING_PKCS1_5;
+
+ debug_hexdump(stdout, "message", asym_op->rsa.message.data,
+ asym_op->rsa.message.length);
+
+ /* Attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1, "Error sending packet for encryption\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1, "Failed to process encryption op\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ debug_hexdump(stdout, "encrypted message", asym_op->rsa.message.data,
+ asym_op->rsa.message.length);
+
+ /* Use the resulted output as decryption Input vector*/
+ asym_op = result_op->asym;
+ asym_op->rsa.message.length = 0;
+ asym_op->rsa.op_type = RTE_CRYPTO_ASYM_OP_DECRYPT;
+ asym_op->rsa.pad = RTE_CRYPTO_RSA_PADDING_PKCS1_5;
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1, "Error sending packet for decryption\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1, "Failed to process decryption op\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ status = TEST_SUCCESS;
+ ret = rsa_verify(&rsaplaintext, result_op);
+ if (ret)
+ status = TEST_FAILED;
+
+error_exit:
+
+ rte_crypto_op_free(op);
+
+ return status;
+}
+static int
+test_cryptodev_asym_ver(struct rte_crypto_op *op,
+ struct rte_crypto_asym_xform *xform_tc,
+ union test_case_structure *data_tc,
+ struct rte_crypto_op *result_op)
+{
+ int status = TEST_FAILED;
+ int ret = 0;
+ uint8_t *data_expected = NULL, *data_received = NULL;
+ size_t data_size = 0;
+
+ switch (data_tc->modex.xform_type) {
+ case RTE_CRYPTO_ASYM_XFORM_MODEX:
+ data_expected = data_tc->modex.reminder.data;
+ data_received = result_op->asym->modex.result.data;
+ data_size = result_op->asym->modex.result.length;
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_MODINV:
+ data_expected = data_tc->modinv.inverse.data;
+ data_received = result_op->asym->modinv.result.data;
+ data_size = result_op->asym->modinv.result.length;
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_RSA:
+ if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
+ data_size = xform_tc->rsa.n.length;
+ data_received = result_op->asym->rsa.cipher.data;
+ data_expected = data_tc->rsa_data.ct.data;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
+ data_size = xform_tc->rsa.n.length;
+ data_expected = data_tc->rsa_data.pt.data;
+ data_received = result_op->asym->rsa.message.data;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
+ data_size = xform_tc->rsa.n.length;
+ data_expected = data_tc->rsa_data.sign.data;
+ data_received = result_op->asym->rsa.sign.data;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
+ data_size = xform_tc->rsa.n.length;
+ data_expected = data_tc->rsa_data.pt.data;
+ data_received = result_op->asym->rsa.cipher.data;
+ }
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_DH:
+ case RTE_CRYPTO_ASYM_XFORM_DSA:
+ case RTE_CRYPTO_ASYM_XFORM_NONE:
+ case RTE_CRYPTO_ASYM_XFORM_UNSPECIFIED:
+ default:
+ break;
+ }
+ ret = memcmp(data_expected, data_received, data_size);
+ if (!ret && data_size)
+ status = TEST_SUCCESS;
+
+ return status;
+}
+
+static int
+test_cryptodev_asym_op(struct crypto_testsuite_params *ts_params,
+ union test_case_structure *data_tc,
+ char *test_msg, int sessionless, enum rte_crypto_asym_op_type type,
+ enum rte_crypto_rsa_priv_key_type key_type)
+{
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL;
+ struct rte_crypto_op *result_op = NULL;
+ struct rte_crypto_asym_xform xform_tc;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ struct rte_cryptodev_asym_capability_idx cap_idx;
+ const struct rte_cryptodev_asymmetric_xform_capability *capability;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ uint8_t input[TEST_DATA_SIZE] = {0};
+ uint8_t *result = NULL;
+
+ int status = TEST_SUCCESS;
+
+ xform_tc.next = NULL;
+ xform_tc.xform_type = data_tc->modex.xform_type;
+
+ cap_idx.type = xform_tc.xform_type;
+ capability = rte_cryptodev_asym_capability_get(dev_id, &cap_idx);
+
+ if (capability == NULL) {
+ RTE_LOG(INFO, USER1,
+ "Device doesn't support MODEX. Test Skipped\n");
+ return -ENOTSUP;
+ }
+
+ /* Generate crypto op data structure */
+ op = rte_crypto_op_alloc(ts_params->op_mpool,
+ RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+ if (!op) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ asym_op = op->asym;
+
+ switch (xform_tc.xform_type) {
+ case RTE_CRYPTO_ASYM_XFORM_MODEX:
+ result = rte_zmalloc(NULL, data_tc->modex.result_len, 0);
+ xform_tc.modex.modulus.data = data_tc->modex.modulus.data;
+ xform_tc.modex.modulus.length = data_tc->modex.modulus.len;
+ xform_tc.modex.exponent.data = data_tc->modex.exponent.data;
+ xform_tc.modex.exponent.length = data_tc->modex.exponent.len;
+ memcpy(input, data_tc->modex.base.data,
+ data_tc->modex.base.len);
+ asym_op->modex.base.data = input;
+ asym_op->modex.base.length = data_tc->modex.base.len;
+ asym_op->modex.result.data = result;
+ asym_op->modex.result.length = data_tc->modex.result_len;
+ if (rte_cryptodev_asym_xform_capability_check_modlen(capability,
+ xform_tc.modex.modulus.length)) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u "
+ "FAILED: %s", __LINE__,
+ "Invalid MODULUS length specified");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_MODINV:
+ result = rte_zmalloc(NULL, data_tc->modinv.result_len, 0);
+ xform_tc.modinv.modulus.data = data_tc->modinv.modulus.data;
+ xform_tc.modinv.modulus.length = data_tc->modinv.modulus.len;
+ memcpy(input, data_tc->modinv.base.data,
+ data_tc->modinv.base.len);
+ asym_op->modinv.base.data = input;
+ asym_op->modinv.base.length = data_tc->modinv.base.len;
+ asym_op->modinv.result.data = result;
+ asym_op->modinv.result.length = data_tc->modinv.result_len;
+ if (rte_cryptodev_asym_xform_capability_check_modlen(capability,
+ xform_tc.modinv.modulus.length)) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u "
+ "FAILED: %s", __LINE__,
+ "Invalid MODULUS length specified");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_RSA:
+ result = rte_zmalloc(NULL, data_tc->rsa_data.n.len, 0);
+ op->asym->rsa.op_type = type;
+ xform_tc.rsa.e.data = data_tc->rsa_data.e.data;
+ xform_tc.rsa.e.length = data_tc->rsa_data.e.len;
+ xform_tc.rsa.n.data = data_tc->rsa_data.n.data;
+ xform_tc.rsa.n.length = data_tc->rsa_data.n.len;
+
+ if (key_type == RTE_RSA_KEY_TYPE_EXP) {
+ xform_tc.rsa.d.data = data_tc->rsa_data.d.data;
+ xform_tc.rsa.d.length = data_tc->rsa_data.d.len;
+ } else {
+ xform_tc.rsa.qt.p.data = data_tc->rsa_data.p.data;
+ xform_tc.rsa.qt.p.length = data_tc->rsa_data.p.len;
+ xform_tc.rsa.qt.q.data = data_tc->rsa_data.q.data;
+ xform_tc.rsa.qt.q.length = data_tc->rsa_data.q.len;
+ xform_tc.rsa.qt.dP.data = data_tc->rsa_data.dP.data;
+ xform_tc.rsa.qt.dP.length = data_tc->rsa_data.dP.len;
+ xform_tc.rsa.qt.dQ.data = data_tc->rsa_data.dQ.data;
+ xform_tc.rsa.qt.dQ.length = data_tc->rsa_data.dQ.len;
+ xform_tc.rsa.qt.qInv.data = data_tc->rsa_data.qInv.data;
+ xform_tc.rsa.qt.qInv.length = data_tc->rsa_data.qInv.len;
+ }
+
+ xform_tc.rsa.key_type = key_type;
+ op->asym->rsa.pad = data_tc->rsa_data.padding;
+
+ if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_ENCRYPT) {
+ asym_op->rsa.message.data = data_tc->rsa_data.pt.data;
+ asym_op->rsa.message.length = data_tc->rsa_data.pt.len;
+ asym_op->rsa.cipher.data = result;
+ asym_op->rsa.cipher.length = data_tc->rsa_data.n.len;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_DECRYPT) {
+ asym_op->rsa.message.data = result;
+ asym_op->rsa.message.length = data_tc->rsa_data.n.len;
+ asym_op->rsa.cipher.data = data_tc->rsa_data.ct.data;
+ asym_op->rsa.cipher.length = data_tc->rsa_data.ct.len;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_SIGN) {
+ asym_op->rsa.sign.data = result;
+ asym_op->rsa.sign.length = data_tc->rsa_data.n.len;
+ asym_op->rsa.message.data = data_tc->rsa_data.pt.data;
+ asym_op->rsa.message.length = data_tc->rsa_data.pt.len;
+ } else if (op->asym->rsa.op_type == RTE_CRYPTO_ASYM_OP_VERIFY) {
+ asym_op->rsa.cipher.data = result;
+ asym_op->rsa.cipher.length = data_tc->rsa_data.n.len;
+ asym_op->rsa.sign.data = data_tc->rsa_data.sign.data;
+ asym_op->rsa.sign.length = data_tc->rsa_data.sign.len;
+ }
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_DH:
+ case RTE_CRYPTO_ASYM_XFORM_DSA:
+ case RTE_CRYPTO_ASYM_XFORM_NONE:
+ case RTE_CRYPTO_ASYM_XFORM_UNSPECIFIED:
+ default:
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u "
+ "FAILED: %s", __LINE__,
+ "Invalid ASYM algorithm specified");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (!sessionless) {
+ sess = rte_cryptodev_asym_session_create(ts_params->session_mpool);
+ if (!sess) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u "
+ "FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform_tc,
+ ts_params->session_mpool) < 0) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ rte_crypto_op_attach_asym_session(op, sess);
+ } else {
+ asym_op->xform = &xform_tc;
+ op->sess_type = RTE_CRYPTO_OP_SESSIONLESS;
+ }
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (test_cryptodev_asym_ver(op, &xform_tc, data_tc, result_op) != TEST_SUCCESS) {
+ snprintf(test_msg, ASYM_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Verification failed ");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (!sessionless)
+ snprintf(test_msg, ASYM_TEST_MSG_LEN, "PASS");
+ else
+ snprintf(test_msg, ASYM_TEST_MSG_LEN, "SESSIONLESS PASS");
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+
+ if (op != NULL)
+ rte_crypto_op_free(op);
+
+ if (result != NULL)
+ rte_free(result);
+
+ return status;
+}
+
+static int
+test_one_case(const void *test_case, int sessionless)
+{
+ int status = TEST_SUCCESS, i = 0;
+ char test_msg[ASYM_TEST_MSG_LEN + 1];
+
+ /* Map the case to union */
+ union test_case_structure tc;
+ memcpy(&tc, test_case, sizeof(tc));
+
+ if (tc.modex.xform_type == RTE_CRYPTO_ASYM_XFORM_MODEX
+ || tc.modex.xform_type == RTE_CRYPTO_ASYM_XFORM_MODINV) {
+ status = test_cryptodev_asym_op(&testsuite_params, &tc, test_msg,
+ sessionless, 0, 0);
+ printf(" %u) TestCase %s %s\n", test_index++,
+ tc.modex.description, test_msg);
+ } else {
+ for (i = 0; i < RTE_CRYPTO_ASYM_OP_LIST_END; i++) {
+ if (tc.modex.xform_type == RTE_CRYPTO_ASYM_XFORM_RSA) {
+ if (tc.rsa_data.op_type_flags & (1 << i)) {
+ if (tc.rsa_data.key_exp) {
+ status = test_cryptodev_asym_op(
+ &testsuite_params, &tc,
+ test_msg, sessionless, i,
+ RTE_RSA_KEY_TYPE_EXP);
+ }
+ if (status)
+ break;
+ if (tc.rsa_data.key_qt && (i ==
+ RTE_CRYPTO_ASYM_OP_DECRYPT ||
+ i == RTE_CRYPTO_ASYM_OP_SIGN)) {
+ status = test_cryptodev_asym_op(
+ &testsuite_params,
+ &tc, test_msg, sessionless, i,
+ RTE_RSA_KET_TYPE_QT);
+ }
+ if (status)
+ break;
+ }
+ }
+ }
+ printf(" %u) TestCase %s %s\n", test_index++,
+ tc.modex.description, test_msg);
+ }
+
+ return status;
+}
+
+static int
+load_test_vectors(void)
+{
+ uint32_t i = 0, v_size = 0;
+ /* Load MODEX vector*/
+ v_size = RTE_DIM(modex_test_case);
+ for (i = 0; i < v_size; i++) {
+ if (test_vector.size >= (TEST_VECTOR_SIZE)) {
+ RTE_LOG(DEBUG, USER1,
+ "TEST_VECTOR_SIZE too small\n");
+ return -1;
+ }
+ test_vector.address[test_vector.size] = &modex_test_case[i];
+ test_vector.size++;
+ }
+ /* Load MODINV vector*/
+ v_size = RTE_DIM(modinv_test_case);
+ for (i = 0; i < v_size; i++) {
+ if (test_vector.size >= (TEST_VECTOR_SIZE)) {
+ RTE_LOG(DEBUG, USER1,
+ "TEST_VECTOR_SIZE too small\n");
+ return -1;
+ }
+ test_vector.address[test_vector.size] = &modinv_test_case[i];
+ test_vector.size++;
+ }
+ /* Load RSA vector*/
+ v_size = RTE_DIM(rsa_test_case_list);
+ for (i = 0; i < v_size; i++) {
+ if (test_vector.size >= (TEST_VECTOR_SIZE)) {
+ RTE_LOG(DEBUG, USER1,
+ "TEST_VECTOR_SIZE too small\n");
+ return -1;
+ }
+ test_vector.address[test_vector.size] = &rsa_test_case_list[i];
+ test_vector.size++;
+ }
+ return 0;
+}
+
+static int
+test_one_by_one(void)
+{
+ int status = TEST_SUCCESS;
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint32_t i = 0;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_info dev_info;
+ int sessionless = 0;
+
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if ((dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_ASYM_SESSIONLESS)) {
+ sessionless = 1;
+ }
+
+ /* Go through all test cases */
+ test_index = 0;
+ for (i = 0; i < test_vector.size; i++) {
+ if (test_one_case(test_vector.address[i], 0) != TEST_SUCCESS)
+ status = TEST_FAILED;
+ }
+ if (sessionless) {
+ for (i = 0; i < test_vector.size; i++) {
+ if (test_one_case(test_vector.address[i], 1)
+ != TEST_SUCCESS)
+ status = TEST_FAILED;
+ }
+ }
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+ return status;
+}
+
+static int
+test_rsa_sign_verify(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_asym_session *sess;
+ struct rte_cryptodev_info dev_info;
+ int status = TEST_SUCCESS;
+
+ /* Test case supports op with exponent key only,
+ * Check in PMD feature flag for RSA exponent key type support.
+ */
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+ RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+ "exponent key type. Test Skipped\n");
+ return -ENOTSUP;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+
+ if (!sess) {
+ RTE_LOG(ERR, USER1, "Session creation failed for "
+ "sign_verify\n");
+ return TEST_FAILED;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &rsa_xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1, "Unable to config asym session for "
+ "sign_verify\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ status = queue_ops_rsa_sign_verify(sess);
+
+error_exit:
+
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_rsa_enc_dec(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_asym_session *sess;
+ struct rte_cryptodev_info dev_info;
+ int status = TEST_SUCCESS;
+
+ /* Test case supports op with exponent key only,
+ * Check in PMD feature flag for RSA exponent key type support.
+ */
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+ RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+ "exponent key type. Test skipped\n");
+ return -ENOTSUP;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+
+ if (!sess) {
+ RTE_LOG(ERR, USER1, "Session creation failed for enc_dec\n");
+ return TEST_FAILED;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &rsa_xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1, "Unable to config asym session for "
+ "enc_dec\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_rsa_sign_verify_crt(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_asym_session *sess;
+ struct rte_cryptodev_info dev_info;
+ int status = TEST_SUCCESS;
+
+ /* Test case supports op with quintuple format key only,
+ * Check im PMD feature flag for RSA quintuple key type support.
+ */
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+ RTE_LOG(INFO, USER1, "Device doesn't support sign op with "
+ "quintuple key type. Test skipped\n");
+ return -ENOTSUP;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+
+ if (!sess) {
+ RTE_LOG(ERR, USER1, "Session creation failed for "
+ "sign_verify_crt\n");
+ status = TEST_FAILED;
+ return status;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &rsa_xform_crt,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1, "Unable to config asym session for "
+ "sign_verify_crt\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ status = queue_ops_rsa_sign_verify(sess);
+
+error_exit:
+
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_rsa_enc_dec_crt(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_asym_session *sess;
+ struct rte_cryptodev_info dev_info;
+ int status = TEST_SUCCESS;
+
+ /* Test case supports op with quintuple format key only,
+ * Check in PMD feature flag for RSA quintuple key type support.
+ */
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+ RTE_LOG(INFO, USER1, "Device doesn't support decrypt op with "
+ "quintuple key type. Test skipped\n");
+ return -ENOTSUP;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+
+ if (!sess) {
+ RTE_LOG(ERR, USER1, "Session creation failed for "
+ "enc_dec_crt\n");
+ return TEST_FAILED;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &rsa_xform_crt,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1, "Unable to config asym session for "
+ "enc_dec_crt\n");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ status = queue_ops_rsa_enc_dec(sess);
+
+error_exit:
+
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+testsuite_setup(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
+ struct rte_cryptodev_info info;
+ int ret, dev_id = -1;
+ uint32_t i, nb_devs;
+ uint16_t qp_id;
+
+ memset(ts_params, 0, sizeof(*ts_params));
+
+ test_vector.size = 0;
+ load_test_vectors();
+
+ ts_params->op_mpool = rte_crypto_op_pool_create(
+ "CRYPTO_ASYM_OP_POOL",
+ RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+ TEST_NUM_BUFS, 0,
+ 0,
+ rte_socket_id());
+ if (ts_params->op_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create ASYM_CRYPTO_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ /* Create an OPENSSL device if required */
+ if (gbl_driver_id == rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD))) {
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD)));
+ if (nb_devs < 1) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD),
+ NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create "
+ "instance of pmd : %s",
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
+ }
+ }
+
+ /* Get list of valid crypto devs */
+ nb_devs = rte_cryptodev_devices_get(
+ rte_cryptodev_driver_name_get(gbl_driver_id),
+ valid_devs, RTE_CRYPTO_MAX_DEVS);
+ if (nb_devs < 1) {
+ RTE_LOG(ERR, USER1, "No crypto devices found?\n");
+ return TEST_FAILED;
+ }
+
+ /*
+ * Get first valid asymmetric device found in test suite param and
+ * break
+ */
+ for (i = 0; i < nb_devs ; i++) {
+ rte_cryptodev_info_get(valid_devs[i], &info);
+ if (info.feature_flags & RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO) {
+ dev_id = ts_params->valid_devs[0] = valid_devs[i];
+ break;
+ }
+ }
+
+ if (dev_id == -1) {
+ RTE_LOG(ERR, USER1, "Device doesn't support asymmetric. "
+ "Test skipped.\n");
+ return TEST_FAILED;
+ }
+
+ /* Set valid device count */
+ ts_params->valid_dev_count = nb_devs;
+
+ /* configure device with num qp */
+ ts_params->conf.nb_queue_pairs = info.max_nb_queue_pairs;
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+ ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY |
+ RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO;
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(dev_id,
+ &ts_params->conf),
+ "Failed to configure cryptodev %u with %u qps",
+ dev_id, ts_params->conf.nb_queue_pairs);
+
+ /* configure qp */
+ ts_params->qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT;
+ ts_params->qp_conf.mp_session = ts_params->session_mpool;
+ ts_params->qp_conf.mp_session_private = ts_params->session_mpool;
+ for (qp_id = 0; qp_id < info.max_nb_queue_pairs; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ dev_id, qp_id, &ts_params->qp_conf,
+ rte_cryptodev_socket_id(dev_id)),
+ "Failed to setup queue pair %u on cryptodev %u ASYM",
+ qp_id, dev_id);
+ }
+
+ /* setup asym session pool */
+ unsigned int session_size =
+ rte_cryptodev_asym_get_private_session_size(dev_id);
+ /*
+ * Create mempool with TEST_NUM_SESSIONS * 2,
+ * to include the session headers
+ */
+ ts_params->session_mpool = rte_mempool_create(
+ "test_asym_sess_mp",
+ TEST_NUM_SESSIONS * 2,
+ session_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+
+ TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
+ "session mempool allocation failed");
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+ if (ts_params->op_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_OP_POOL count %u\n",
+ rte_mempool_avail_count(ts_params->op_mpool));
+ }
+
+ /* Free session mempools */
+ if (ts_params->session_mpool != NULL) {
+ rte_mempool_free(ts_params->session_mpool);
+ ts_params->session_mpool = NULL;
+ }
+}
+
+static int
+ut_setup(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+ uint16_t qp_id;
+
+ /* Reconfigure device to default parameters */
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(ts_params->valid_devs[0],
+ &ts_params->conf),
+ "Failed to configure cryptodev %u",
+ ts_params->valid_devs[0]);
+
+ for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs ; qp_id++) {
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ ts_params->valid_devs[0], qp_id,
+ &ts_params->qp_conf,
+ rte_cryptodev_socket_id(ts_params->valid_devs[0])),
+ "Failed to setup queue pair %u on cryptodev %u",
+ qp_id, ts_params->valid_devs[0]);
+ }
+
+ rte_cryptodev_stats_reset(ts_params->valid_devs[0]);
+
+ /* Start the device */
+ TEST_ASSERT_SUCCESS(rte_cryptodev_start(ts_params->valid_devs[0]),
+ "Failed to start cryptodev %u",
+ ts_params->valid_devs[0]);
+
+ return TEST_SUCCESS;
+}
+
+static void
+ut_teardown(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_cryptodev_stats stats;
+
+ rte_cryptodev_stats_get(ts_params->valid_devs[0], &stats);
+
+ /* Stop the device */
+ rte_cryptodev_stop(ts_params->valid_devs[0]);
+}
+
+static inline void print_asym_capa(
+ const struct rte_cryptodev_asymmetric_xform_capability *capa)
+{
+ int i = 0;
+
+ printf("\nxform type: %s\n===================\n",
+ rte_crypto_asym_xform_strings[capa->xform_type]);
+ printf("operation supported -");
+
+ for (i = 0; i < RTE_CRYPTO_ASYM_OP_LIST_END; i++) {
+ /* check supported operations */
+ if (rte_cryptodev_asym_xform_capability_check_optype(capa, i))
+ printf(" %s",
+ rte_crypto_asym_op_strings[i]);
+ }
+ switch (capa->xform_type) {
+ case RTE_CRYPTO_ASYM_XFORM_RSA:
+ case RTE_CRYPTO_ASYM_XFORM_MODINV:
+ case RTE_CRYPTO_ASYM_XFORM_MODEX:
+ case RTE_CRYPTO_ASYM_XFORM_DH:
+ case RTE_CRYPTO_ASYM_XFORM_DSA:
+ printf(" modlen: min %d max %d increment %d",
+ capa->modlen.min,
+ capa->modlen.max,
+ capa->modlen.increment);
+ break;
+ case RTE_CRYPTO_ASYM_XFORM_ECDSA:
+ case RTE_CRYPTO_ASYM_XFORM_ECPM:
+ default:
+ break;
+ }
+ printf("\n");
+}
+
+static int
+test_capability(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_cryptodev_info dev_info;
+ const struct rte_cryptodev_capabilities *dev_capa;
+ int i = 0;
+ struct rte_cryptodev_asym_capability_idx idx;
+ const struct rte_cryptodev_asymmetric_xform_capability *capa;
+
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO)) {
+ RTE_LOG(INFO, USER1,
+ "Device doesn't support asymmetric. Test Skipped\n");
+ return TEST_SUCCESS;
+ }
+
+ /* print xform capability */
+ for (i = 0;
+ dev_info.capabilities[i].op != RTE_CRYPTO_OP_TYPE_UNDEFINED;
+ i++) {
+ dev_capa = &(dev_info.capabilities[i]);
+ if (dev_info.capabilities[i].op ==
+ RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
+ idx.type = dev_capa->asym.xform_capa.xform_type;
+
+ capa = rte_cryptodev_asym_capability_get(dev_id,
+ (const struct
+ rte_cryptodev_asym_capability_idx *) &idx);
+ print_asym_capa(capa);
+ }
+ }
+ return TEST_SUCCESS;
+}
+
+static int
+test_dh_gen_shared_sec(struct rte_crypto_asym_xform *xfrm)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ uint8_t output[TEST_DH_MOD_LEN];
+ struct rte_crypto_asym_xform xform = *xfrm;
+ uint8_t peer[] = "01234567890123456789012345678901234567890123456789";
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ /* set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ asym_op = op->asym;
+
+ /* Setup a xform and op to generate private key only */
+ xform.dh.type = RTE_CRYPTO_ASYM_OP_SHARED_SECRET_COMPUTE;
+ xform.next = NULL;
+ asym_op->dh.priv_key.data = dh_test_params.priv_key.data;
+ asym_op->dh.priv_key.length = dh_test_params.priv_key.length;
+ asym_op->dh.pub_key.data = (uint8_t *)peer;
+ asym_op->dh.pub_key.length = sizeof(peer);
+ asym_op->dh.shared_secret.data = output;
+ asym_op->dh.shared_secret.length = sizeof(output);
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ debug_hexdump(stdout, "shared secret:",
+ asym_op->dh.shared_secret.data,
+ asym_op->dh.shared_secret.length);
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+ return status;
+}
+
+static int
+test_dh_gen_priv_key(struct rte_crypto_asym_xform *xfrm)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ uint8_t output[TEST_DH_MOD_LEN];
+ struct rte_crypto_asym_xform xform = *xfrm;
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ /* set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ asym_op = op->asym;
+
+ /* Setup a xform and op to generate private key only */
+ xform.dh.type = RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE;
+ xform.next = NULL;
+ asym_op->dh.priv_key.data = output;
+ asym_op->dh.priv_key.length = sizeof(output);
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ debug_hexdump(stdout, "private key:",
+ asym_op->dh.priv_key.data,
+ asym_op->dh.priv_key.length);
+
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+
+ return status;
+}
+
+
+static int
+test_dh_gen_pub_key(struct rte_crypto_asym_xform *xfrm)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ uint8_t output[TEST_DH_MOD_LEN];
+ struct rte_crypto_asym_xform xform = *xfrm;
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ /* set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ asym_op = op->asym;
+ /* Setup a xform chain to generate public key
+ * using test private key
+ *
+ */
+ xform.dh.type = RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE;
+ xform.next = NULL;
+
+ asym_op->dh.pub_key.data = output;
+ asym_op->dh.pub_key.length = sizeof(output);
+ /* load pre-defined private key */
+ asym_op->dh.priv_key.data = rte_malloc(NULL,
+ dh_test_params.priv_key.length,
+ 0);
+ asym_op->dh.priv_key = dh_test_params.priv_key;
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ debug_hexdump(stdout, "pub key:",
+ asym_op->dh.pub_key.data, asym_op->dh.pub_key.length);
+
+ debug_hexdump(stdout, "priv key:",
+ asym_op->dh.priv_key.data, asym_op->dh.priv_key.length);
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+
+ return status;
+}
+
+static int
+test_dh_gen_kp(struct rte_crypto_asym_xform *xfrm)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ uint8_t out_pub_key[TEST_DH_MOD_LEN];
+ uint8_t out_prv_key[TEST_DH_MOD_LEN];
+ struct rte_crypto_asym_xform pub_key_xform;
+ struct rte_crypto_asym_xform xform = *xfrm;
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ asym_op = op->asym;
+ /* Setup a xform chain to generate
+ * private key first followed by
+ * public key
+ */xform.dh.type = RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE;
+ pub_key_xform.xform_type = RTE_CRYPTO_ASYM_XFORM_DH;
+ pub_key_xform.dh.type = RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE;
+ xform.next = &pub_key_xform;
+
+ asym_op->dh.pub_key.data = out_pub_key;
+ asym_op->dh.pub_key.length = sizeof(out_pub_key);
+ asym_op->dh.priv_key.data = out_prv_key;
+ asym_op->dh.priv_key.length = sizeof(out_prv_key);
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ debug_hexdump(stdout, "priv key:",
+ out_prv_key, asym_op->dh.priv_key.length);
+ debug_hexdump(stdout, "pub key:",
+ out_pub_key, asym_op->dh.pub_key.length);
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+
+ return status;
+}
+
+static int
+test_mod_inv(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ struct rte_cryptodev_asym_capability_idx cap_idx;
+ const struct rte_cryptodev_asymmetric_xform_capability *capability;
+ uint8_t input[TEST_DATA_SIZE] = {0};
+ int ret = 0;
+ uint8_t result[sizeof(mod_p)] = { 0 };
+
+ if (rte_cryptodev_asym_get_xform_enum(
+ &modinv_xform.xform_type, "modinv") < 0) {
+ RTE_LOG(ERR, USER1,
+ "Invalid ASYM algorithm specified\n");
+ return -1;
+ }
+
+ cap_idx.type = modinv_xform.xform_type;
+ capability = rte_cryptodev_asym_capability_get(dev_id,
+ &cap_idx);
+
+ if (capability == NULL) {
+ RTE_LOG(INFO, USER1,
+ "Device doesn't support MOD INV. Test Skipped\n");
+ return -ENOTSUP;
+ }
+
+ if (rte_cryptodev_asym_xform_capability_check_modlen(
+ capability,
+ modinv_xform.modinv.modulus.length)) {
+ RTE_LOG(ERR, USER1,
+ "Invalid MODULUS length specified\n");
+ return -ENOTSUP;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (!sess) {
+ RTE_LOG(ERR, USER1, "line %u "
+ "FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &modinv_xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* generate crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ asym_op = op->asym;
+ memcpy(input, base, sizeof(base));
+ asym_op->modinv.base.data = input;
+ asym_op->modinv.base.length = sizeof(base);
+ asym_op->modinv.result.data = result;
+ asym_op->modinv.result.length = sizeof(result);
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ ret = verify_modinv(mod_inv, result_op);
+ if (ret) {
+ RTE_LOG(ERR, USER1,
+ "operation verification failed\n");
+ status = TEST_FAILED;
+ }
+
+error_exit:
+ if (sess) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+
+ if (op)
+ rte_crypto_op_free(op);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_mod_exp(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ struct rte_cryptodev_asym_capability_idx cap_idx;
+ const struct rte_cryptodev_asymmetric_xform_capability *capability;
+ uint8_t input[TEST_DATA_SIZE] = {0};
+ int ret = 0;
+ uint8_t result[sizeof(mod_p)] = { 0 };
+
+ if (rte_cryptodev_asym_get_xform_enum(&modex_xform.xform_type,
+ "modexp")
+ < 0) {
+ RTE_LOG(ERR, USER1,
+ "Invalid ASYM algorithm specified\n");
+ return -1;
+ }
+
+ /* check for modlen capability */
+ cap_idx.type = modex_xform.xform_type;
+ capability = rte_cryptodev_asym_capability_get(dev_id, &cap_idx);
+
+ if (capability == NULL) {
+ RTE_LOG(INFO, USER1,
+ "Device doesn't support MOD EXP. Test Skipped\n");
+ return -ENOTSUP;
+ }
+
+ if (rte_cryptodev_asym_xform_capability_check_modlen(
+ capability, modex_xform.modex.modulus.length)) {
+ RTE_LOG(ERR, USER1,
+ "Invalid MODULUS length specified\n");
+ return -ENOTSUP;
+ }
+
+ /* generate crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (!sess) {
+ RTE_LOG(ERR, USER1,
+ "line %u "
+ "FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &modex_xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ asym_op = op->asym;
+ memcpy(input, base, sizeof(base));
+ asym_op->modex.base.data = input;
+ asym_op->modex.base.length = sizeof(base);
+ asym_op->modex.result.data = result;
+ asym_op->modex.result.length = sizeof(result);
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ ret = verify_modexp(mod_exp, result_op);
+ if (ret) {
+ RTE_LOG(ERR, USER1,
+ "operation verification failed\n");
+ status = TEST_FAILED;
+ }
+
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+
+ if (op != NULL)
+ rte_crypto_op_free(op);
+
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_dh_keygenration(void)
+{
+ int status;
+
+ debug_hexdump(stdout, "p:", dh_xform.dh.p.data, dh_xform.dh.p.length);
+ debug_hexdump(stdout, "g:", dh_xform.dh.g.data, dh_xform.dh.g.length);
+ debug_hexdump(stdout, "priv_key:", dh_test_params.priv_key.data,
+ dh_test_params.priv_key.length);
+
+ RTE_LOG(INFO, USER1,
+ "Test Public and Private key pair generation\n");
+
+ status = test_dh_gen_kp(&dh_xform);
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ RTE_LOG(INFO, USER1,
+ "Test Public Key Generation using pre-defined priv key\n");
+
+ status = test_dh_gen_pub_key(&dh_xform);
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ RTE_LOG(INFO, USER1,
+ "Test Private Key Generation only\n");
+
+ status = test_dh_gen_priv_key(&dh_xform);
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ RTE_LOG(INFO, USER1,
+ "Test shared secret compute\n");
+
+ status = test_dh_gen_shared_sec(&dh_xform);
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+ return status;
+}
+
+static int
+test_dsa_sign(void)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_asym_op *asym_op = NULL;
+ struct rte_crypto_op *op = NULL, *result_op = NULL;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ int status = TEST_SUCCESS;
+ uint8_t r[TEST_DH_MOD_LEN];
+ uint8_t s[TEST_DH_MOD_LEN];
+ uint8_t dgst[] = "35d81554afaad2cf18f3a1770d5fedc4ea5be344";
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ /* set up crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (!op) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate asymmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ asym_op = op->asym;
+
+ debug_hexdump(stdout, "p: ", dsa_xform.dsa.p.data,
+ dsa_xform.dsa.p.length);
+ debug_hexdump(stdout, "q: ", dsa_xform.dsa.q.data,
+ dsa_xform.dsa.q.length);
+ debug_hexdump(stdout, "g: ", dsa_xform.dsa.g.data,
+ dsa_xform.dsa.g.length);
+ debug_hexdump(stdout, "priv_key: ", dsa_xform.dsa.x.data,
+ dsa_xform.dsa.x.length);
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &dsa_xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "unabled to config sym session");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+ asym_op->dsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+ asym_op->dsa.message.data = dgst;
+ asym_op->dsa.message.length = sizeof(dgst);
+ asym_op->dsa.r.length = sizeof(r);
+ asym_op->dsa.r.data = r;
+ asym_op->dsa.s.length = sizeof(s);
+ asym_op->dsa.s.data = s;
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ asym_op = result_op->asym;
+
+ debug_hexdump(stdout, "r:",
+ asym_op->dsa.r.data, asym_op->dsa.r.length);
+ debug_hexdump(stdout, "s:",
+ asym_op->dsa.s.data, asym_op->dsa.s.length);
+
+ /* Test PMD DSA sign verification using signer public key */
+ asym_op->dsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+
+ /* copy signer public key */
+ asym_op->dsa.y.data = dsa_test_params.y.data;
+ asym_op->dsa.y.length = dsa_test_params.y.length;
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process asym crypto op");
+ status = TEST_FAILED;
+ }
+error_exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+ return status;
+}
+
+static int
+test_dsa(void)
+{
+ int status;
+ status = test_dsa_sign();
+ TEST_ASSERT_EQUAL(status, 0, "Test failed");
+ return status;
+}
+
+static int
+test_ecdsa_sign_verify(enum curve curve_id)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct crypto_testsuite_ecdsa_params input_params;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_op *result_op = NULL;
+ uint8_t output_buf_r[TEST_DATA_SIZE];
+ uint8_t output_buf_s[TEST_DATA_SIZE];
+ struct rte_crypto_asym_xform xform;
+ struct rte_crypto_asym_op *asym_op;
+ struct rte_cryptodev_info dev_info;
+ struct rte_crypto_op *op = NULL;
+ int status = TEST_SUCCESS, ret;
+
+ switch (curve_id) {
+ case SECP192R1:
+ input_params = ecdsa_param_secp192r1;
+ break;
+ case SECP224R1:
+ input_params = ecdsa_param_secp224r1;
+ break;
+ case SECP256R1:
+ input_params = ecdsa_param_secp256r1;
+ break;
+ case SECP384R1:
+ input_params = ecdsa_param_secp384r1;
+ break;
+ case SECP521R1:
+ input_params = ecdsa_param_secp521r1;
+ break;
+ default:
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Unsupported curve id\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ rte_cryptodev_info_get(dev_id, &dev_info);
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ /* Setup crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to allocate asymmetric crypto "
+ "operation struct\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+ asym_op = op->asym;
+
+ /* Setup asym xform */
+ xform.next = NULL;
+ xform.xform_type = RTE_CRYPTO_ASYM_XFORM_ECDSA;
+ xform.ec.curve_id = input_params.curve;
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Unable to config asym session\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ /* Attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ /* Compute sign */
+
+ /* Populate op with operational details */
+ op->asym->ecdsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+ op->asym->ecdsa.message.data = input_params.digest.data;
+ op->asym->ecdsa.message.length = input_params.digest.length;
+ op->asym->ecdsa.k.data = input_params.scalar.data;
+ op->asym->ecdsa.k.length = input_params.scalar.length;
+ op->asym->ecdsa.pkey.data = input_params.pkey.data;
+ op->asym->ecdsa.pkey.length = input_params.pkey.length;
+
+ /* Init out buf */
+ op->asym->ecdsa.r.data = output_buf_r;
+ op->asym->ecdsa.s.data = output_buf_s;
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Error sending packet for operation\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to process asym crypto op\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to process asym crypto op\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ asym_op = result_op->asym;
+
+ debug_hexdump(stdout, "r:",
+ asym_op->ecdsa.r.data, asym_op->ecdsa.r.length);
+ debug_hexdump(stdout, "s:",
+ asym_op->ecdsa.s.data, asym_op->ecdsa.s.length);
+
+ ret = verify_ecdsa_sign(input_params.sign_r.data,
+ input_params.sign_s.data, result_op);
+ if (ret) {
+ status = TEST_FAILED;
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "ECDSA sign failed.\n");
+ goto exit;
+ }
+
+ /* Verify sign */
+
+ /* Populate op with operational details */
+ op->asym->ecdsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+ op->asym->ecdsa.q.x.data = input_params.pubkey_qx.data;
+ op->asym->ecdsa.q.x.length = input_params.pubkey_qx.length;
+ op->asym->ecdsa.q.y.data = input_params.pubkey_qy.data;
+ op->asym->ecdsa.q.y.length = input_params.pubkey_qx.length;
+ op->asym->ecdsa.r.data = asym_op->ecdsa.r.data;
+ op->asym->ecdsa.r.length = asym_op->ecdsa.r.length;
+ op->asym->ecdsa.s.data = asym_op->ecdsa.s.data;
+ op->asym->ecdsa.s.length = asym_op->ecdsa.s.length;
+
+ /* Enqueue sign result for verify */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ status = TEST_FAILED;
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Error sending packet for operation\n");
+ goto exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ status = TEST_FAILED;
+ goto exit;
+ }
+ if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ status = TEST_FAILED;
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "ECDSA verify failed.\n");
+ goto exit;
+ }
+
+exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+ return status;
+};
+
+static int
+test_ecdsa_sign_verify_all_curve(void)
+{
+ int status, overall_status = TEST_SUCCESS;
+ enum curve curve_id;
+ int test_index = 0;
+ const char *msg;
+
+ for (curve_id = SECP192R1; curve_id < END_OF_CURVE_LIST; curve_id++) {
+ status = test_ecdsa_sign_verify(curve_id);
+ if (status == TEST_SUCCESS) {
+ msg = "succeeded";
+ } else {
+ msg = "failed";
+ overall_status = status;
+ }
+ printf(" %u) TestCase Sign/Veriy Curve %s %s\n",
+ test_index ++, curve[curve_id], msg);
+ }
+ return overall_status;
+}
+
+static int
+test_ecpm(enum curve curve_id)
+{
+ struct crypto_testsuite_params *ts_params = &testsuite_params;
+ struct rte_mempool *sess_mpool = ts_params->session_mpool;
+ struct rte_mempool *op_mpool = ts_params->op_mpool;
+ struct crypto_testsuite_ecpm_params input_params;
+ struct rte_cryptodev_asym_session *sess = NULL;
+ uint8_t dev_id = ts_params->valid_devs[0];
+ struct rte_crypto_op *result_op = NULL;
+ uint8_t output_buf_x[TEST_DATA_SIZE];
+ uint8_t output_buf_y[TEST_DATA_SIZE];
+ struct rte_crypto_asym_xform xform;
+ struct rte_crypto_asym_op *asym_op;
+ struct rte_cryptodev_info dev_info;
+ struct rte_crypto_op *op = NULL;
+ int status = TEST_SUCCESS, ret;
+
+ switch (curve_id) {
+ case SECP192R1:
+ input_params = ecpm_param_secp192r1;
+ break;
+ case SECP224R1:
+ input_params = ecpm_param_secp224r1;
+ break;
+ case SECP256R1:
+ input_params = ecpm_param_secp256r1;
+ break;
+ case SECP384R1:
+ input_params = ecpm_param_secp384r1;
+ break;
+ case SECP521R1:
+ input_params = ecpm_param_secp521r1;
+ break;
+ default:
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Unsupported curve id\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ rte_cryptodev_info_get(dev_id, &dev_info);
+
+ sess = rte_cryptodev_asym_session_create(sess_mpool);
+ if (sess == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Session creation failed\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ /* Setup crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+ if (op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to allocate asymmetric crypto "
+ "operation struct\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+ asym_op = op->asym;
+
+ /* Setup asym xform */
+ xform.next = NULL;
+ xform.xform_type = RTE_CRYPTO_ASYM_XFORM_ECPM;
+ xform.ec.curve_id = input_params.curve;
+
+ if (rte_cryptodev_asym_session_init(dev_id, sess, &xform,
+ sess_mpool) < 0) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Unable to config asym session\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ /* Attach asymmetric crypto session to crypto operations */
+ rte_crypto_op_attach_asym_session(op, sess);
+
+ /* Populate op with operational details */
+ op->asym->ecpm.p.x.data = input_params.gen_x.data;
+ op->asym->ecpm.p.x.length = input_params.gen_x.length;
+ op->asym->ecpm.p.y.data = input_params.gen_y.data;
+ op->asym->ecpm.p.y.length = input_params.gen_y.length;
+ op->asym->ecpm.scalar.data = input_params.privkey.data;
+ op->asym->ecpm.scalar.length = input_params.privkey.length;
+
+ /* Init out buf */
+ op->asym->ecpm.r.x.data = output_buf_x;
+ op->asym->ecpm.r.y.data = output_buf_y;
+
+ RTE_LOG(DEBUG, USER1, "Process ASYM operation\n");
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Error sending packet for operation\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &result_op, 1) == 0)
+ rte_pause();
+
+ if (result_op == NULL) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to process asym crypto op\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ if (result_op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "Failed to process asym crypto op\n");
+ status = TEST_FAILED;
+ goto exit;
+ }
+
+ asym_op = result_op->asym;
+
+ debug_hexdump(stdout, "r x:",
+ asym_op->ecpm.r.x.data, asym_op->ecpm.r.x.length);
+ debug_hexdump(stdout, "r y:",
+ asym_op->ecpm.r.y.data, asym_op->ecpm.r.y.length);
+
+ ret = verify_ecpm(input_params.pubkey_x.data,
+ input_params.pubkey_y.data, result_op);
+ if (ret) {
+ status = TEST_FAILED;
+ RTE_LOG(ERR, USER1,
+ "line %u FAILED: %s", __LINE__,
+ "EC Point Multiplication failed.\n");
+ goto exit;
+ }
+
+exit:
+ if (sess != NULL) {
+ rte_cryptodev_asym_session_clear(dev_id, sess);
+ rte_cryptodev_asym_session_free(sess);
+ }
+ if (op != NULL)
+ rte_crypto_op_free(op);
+ return status;
+}
+
+static int
+test_ecpm_all_curve(void)
+{
+ int status, overall_status = TEST_SUCCESS;
+ enum curve curve_id;
+ int test_index = 0;
+ const char *msg;
+
+ for (curve_id = SECP192R1; curve_id < END_OF_CURVE_LIST; curve_id++) {
+ status = test_ecpm(curve_id);
+ if (status == TEST_SUCCESS) {
+ msg = "succeeded";
+ } else {
+ msg = "failed";
+ overall_status = status;
+ }
+ printf(" %u) TestCase EC Point Mul Curve %s %s\n",
+ test_index ++, curve[curve_id], msg);
+ }
+ return overall_status;
+}
+
+static struct unit_test_suite cryptodev_openssl_asym_testsuite = {
+ .suite_name = "Crypto Device OPENSSL ASYM Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_capability),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_dsa),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_dh_keygenration),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_enc_dec),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_sign_verify),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_enc_dec_crt),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_sign_verify_crt),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_mod_inv),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_mod_exp),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_one_by_one),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_qat_asym_testsuite = {
+ .suite_name = "Crypto Device QAT ASYM Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_one_by_one),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite cryptodev_octeontx_asym_testsuite = {
+ .suite_name = "Crypto Device OCTEONTX ASYM Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown, test_capability),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_enc_dec_crt),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_rsa_sign_verify_crt),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_mod_exp),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ecdsa_sign_verify_all_curve),
+ TEST_CASE_ST(ut_setup, ut_teardown, test_ecpm_all_curve),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_cryptodev_openssl_asym(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OPENSSL_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OPENSSL PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OPENSSL is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_openssl_asym_testsuite);
+}
+
+static int
+test_cryptodev_qat_asym(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_QAT_ASYM_PMD));
+
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "QAT PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_QAT_ASYM is enabled "
+ "in config file to run this testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ return unit_test_suite_runner(&cryptodev_qat_asym_testsuite);
+}
+
+static int
+test_cryptodev_octeontx_asym(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OCTEONTX_SYM_PMD));
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OCTEONTX PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OCTEONTX_CRYPTO is "
+ "enabled in config file to run this "
+ "testsuite.\n");
+ return TEST_FAILED;
+ }
+ return unit_test_suite_runner(&cryptodev_octeontx_asym_testsuite);
+}
+
+static int
+test_cryptodev_octeontx2_asym(void)
+{
+ gbl_driver_id = rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_OCTEONTX2_PMD));
+ if (gbl_driver_id == -1) {
+ RTE_LOG(ERR, USER1, "OCTEONTX2 PMD must be loaded. Check if "
+ "CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_CRYPTO is "
+ "enabled in config file to run this "
+ "testsuite.\n");
+ return TEST_FAILED;
+ }
+
+ /* Use test suite registered for crypto_octeontx PMD */
+ return unit_test_suite_runner(&cryptodev_octeontx_asym_testsuite);
+}
+
+REGISTER_TEST_COMMAND(cryptodev_openssl_asym_autotest,
+ test_cryptodev_openssl_asym);
+
+REGISTER_TEST_COMMAND(cryptodev_qat_asym_autotest, test_cryptodev_qat_asym);
+
+REGISTER_TEST_COMMAND(cryptodev_octeontx_asym_autotest,
+ test_cryptodev_octeontx_asym);
+
+REGISTER_TEST_COMMAND(cryptodev_octeontx2_asym_autotest,
+ test_cryptodev_octeontx2_asym);
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_asym_util.h b/src/spdk/dpdk/app/test/test_cryptodev_asym_util.h
new file mode 100644
index 000000000..83dc265dd
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_asym_util.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ */
+
+#ifndef TEST_CRYPTODEV_ASYM_TEST_UTIL_H__
+#define TEST_CRYPTODEV_ASYM_TEST_UTIL_H__
+
+/* Below Apis compare resulted buffer to original test vector */
+
+static inline int rsa_verify(struct rsa_test_data *rsa_param,
+ struct rte_crypto_op *result_op)
+{
+ if (memcmp(rsa_param->data,
+ result_op->asym->rsa.message.data,
+ result_op->asym->rsa.message.length))
+ return -1;
+ return 0;
+}
+
+static inline int verify_modinv(uint8_t *mod_inv,
+ struct rte_crypto_op *result_op)
+{
+ if (memcmp(mod_inv, result_op->asym->modinv.result.data,
+ result_op->asym->modinv.result.length))
+ return -1;
+ return 0;
+}
+
+static inline int verify_modexp(uint8_t *mod_exp,
+ struct rte_crypto_op *result_op)
+{
+ if (memcmp(mod_exp, result_op->asym->modex.result.data,
+ result_op->asym->modex.result.length))
+ return -1;
+ return 0;
+}
+
+static inline int verify_ecdsa_sign(uint8_t *sign_r,
+ uint8_t *sign_s, struct rte_crypto_op *result_op)
+{
+ if (memcmp(sign_r, result_op->asym->ecdsa.r.data,
+ result_op->asym->ecdsa.r.length) ||
+ memcmp(sign_s, result_op->asym->ecdsa.s.data,
+ result_op->asym->ecdsa.s.length))
+ return -1;
+ return 0;
+}
+
+static inline int verify_ecpm(uint8_t *result_x, uint8_t *result_y,
+ struct rte_crypto_op *result_op)
+{
+ if (memcmp(result_x, result_op->asym->ecpm.r.x.data,
+ result_op->asym->ecpm.r.x.length) ||
+ memcmp(result_y, result_op->asym->ecpm.r.y.data,
+ result_op->asym->ecpm.r.y.length))
+ return -1;
+
+ return 0;
+}
+#endif /* TEST_CRYPTODEV_ASYM_TEST_UTIL_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.c b/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.c
new file mode 100644
index 000000000..642b54971
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.c
@@ -0,0 +1,793 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2017 Intel Corporation
+ */
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_pause.h>
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+
+#include "test.h"
+#include "test_cryptodev.h"
+#include "test_cryptodev_blockcipher.h"
+#include "test_cryptodev_aes_test_vectors.h"
+#include "test_cryptodev_des_test_vectors.h"
+#include "test_cryptodev_hash_test_vectors.h"
+
+static int
+verify_algo_support(const struct blockcipher_test_case *t,
+ const uint8_t dev_id, const uint32_t digest_len)
+{
+ int ret = 0;
+ const struct blockcipher_test_data *tdata = t->test_data;
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *capability;
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = tdata->crypto_algo;
+ capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ if (cap_idx.algo.cipher != RTE_CRYPTO_CIPHER_NULL)
+ ret = rte_cryptodev_sym_capability_check_cipher(capability,
+ tdata->cipher_key.len,
+ tdata->iv.len);
+ if (ret != 0)
+ return -1;
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = tdata->auth_algo;
+ capability = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
+ if (capability == NULL)
+ return -1;
+
+ if (cap_idx.algo.auth != RTE_CRYPTO_AUTH_NULL)
+ ret = rte_cryptodev_sym_capability_check_auth(capability,
+ tdata->auth_key.len,
+ digest_len,
+ 0);
+ if (ret != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_blockcipher_one_case(const struct blockcipher_test_case *t,
+ struct rte_mempool *mbuf_pool,
+ struct rte_mempool *op_mpool,
+ struct rte_mempool *sess_mpool,
+ struct rte_mempool *sess_priv_mpool,
+ uint8_t dev_id,
+ char *test_msg)
+{
+ struct rte_mbuf *ibuf = NULL;
+ struct rte_mbuf *obuf = NULL;
+ struct rte_mbuf *iobuf;
+ struct rte_crypto_sym_xform *cipher_xform = NULL;
+ struct rte_crypto_sym_xform *auth_xform = NULL;
+ struct rte_crypto_sym_xform *init_xform = NULL;
+ struct rte_crypto_sym_op *sym_op = NULL;
+ struct rte_crypto_op *op = NULL;
+ struct rte_cryptodev_info dev_info;
+ struct rte_cryptodev_sym_session *sess = NULL;
+
+ int status = TEST_SUCCESS;
+ const struct blockcipher_test_data *tdata = t->test_data;
+ uint8_t cipher_key[tdata->cipher_key.len];
+ uint8_t auth_key[tdata->auth_key.len];
+ uint32_t buf_len = tdata->ciphertext.len;
+ uint32_t digest_len = tdata->digest.len;
+ char *buf_p = NULL;
+ uint8_t src_pattern = 0xa5;
+ uint8_t dst_pattern = 0xb6;
+ uint8_t tmp_src_buf[MBUF_SIZE];
+ uint8_t tmp_dst_buf[MBUF_SIZE];
+
+ int nb_segs = 1;
+ uint32_t nb_iterates = 0;
+
+ rte_cryptodev_info_get(dev_id, &dev_info);
+ uint64_t feat_flags = dev_info.feature_flags;
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_SYM_SESSIONLESS)) {
+ printf("Device doesn't support sesionless operations "
+ "Test Skipped.\n");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "SKIPPED");
+ return 0;
+ }
+ }
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+ uint64_t oop_flag = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ if (!(feat_flags & oop_flag)) {
+ printf("Device doesn't support out-of-place "
+ "scatter-gather in input mbuf. "
+ "Test Skipped.\n");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "SKIPPED");
+ return 0;
+ }
+ } else {
+ if (!(feat_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)) {
+ printf("Device doesn't support in-place "
+ "scatter-gather mbufs. "
+ "Test Skipped.\n");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "SKIPPED");
+ return 0;
+ }
+ }
+
+ nb_segs = 3;
+ }
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ uint64_t oop_flags = RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
+ RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
+ RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
+ RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT;
+ if (!(feat_flags & oop_flags)) {
+ printf("Device doesn't support out-of-place operations."
+ "Test Skipped.\n");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "SKIPPED");
+ return 0;
+ }
+ }
+
+ if (tdata->cipher_key.len)
+ memcpy(cipher_key, tdata->cipher_key.data,
+ tdata->cipher_key.len);
+ if (tdata->auth_key.len)
+ memcpy(auth_key, tdata->auth_key.data,
+ tdata->auth_key.len);
+
+ /* Check if PMD is capable of performing that test */
+ if (verify_algo_support(t, dev_id, digest_len) < 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device does not support this algorithm."
+ "Test Skipped.\n");
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "SKIPPED");
+ return 0;
+ }
+
+ /* preparing data */
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
+ buf_len += digest_len;
+
+ /* for contiguous mbuf, nb_segs is 1 */
+ ibuf = create_segmented_mbuf(mbuf_pool,
+ tdata->ciphertext.len, nb_segs, src_pattern);
+ if (ibuf == NULL) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Cannot create source mbuf");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* only encryption requires plaintext.data input,
+ * decryption/(digest gen)/(digest verify) use ciphertext.data
+ * to be computed
+ */
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
+ pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+ tdata->plaintext.data);
+ else
+ pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+ tdata->ciphertext.data);
+
+ buf_p = rte_pktmbuf_append(ibuf, digest_len);
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+ rte_memcpy(buf_p, tdata->digest.data, digest_len);
+ else
+ memset(buf_p, 0, digest_len);
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ obuf = rte_pktmbuf_alloc(mbuf_pool);
+ if (!obuf) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__,
+ "Allocation of rte_mbuf failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
+
+ buf_p = rte_pktmbuf_append(obuf, buf_len);
+ if (!buf_p) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__,
+ "No room to append mbuf");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ memset(buf_p, 0, buf_len);
+ }
+
+ /* Generate Crypto op data structure */
+ op = rte_crypto_op_alloc(op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ if (!op) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to allocate symmetric crypto "
+ "operation struct");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ sym_op = op->sym;
+
+iterate:
+ if (nb_iterates) {
+ struct rte_mbuf *tmp_buf = ibuf;
+
+ ibuf = obuf;
+ obuf = tmp_buf;
+
+ rte_pktmbuf_reset(ibuf);
+ rte_pktmbuf_reset(obuf);
+
+ rte_pktmbuf_append(ibuf, tdata->ciphertext.len);
+
+ /* only encryption requires plaintext.data input,
+ * decryption/(digest gen)/(digest verify) use ciphertext.data
+ * to be computed
+ */
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
+ pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+ tdata->plaintext.data);
+ else
+ pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+ tdata->ciphertext.data);
+
+ buf_p = rte_pktmbuf_append(ibuf, digest_len);
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+ rte_memcpy(buf_p, tdata->digest.data, digest_len);
+ else
+ memset(buf_p, 0, digest_len);
+
+ memset(obuf->buf_addr, dst_pattern, obuf->buf_len);
+
+ buf_p = rte_pktmbuf_append(obuf, buf_len);
+ if (!buf_p) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__,
+ "No room to append mbuf");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ memset(buf_p, 0, buf_len);
+ }
+
+ sym_op->m_src = ibuf;
+
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ sym_op->m_dst = obuf;
+ iobuf = obuf;
+ } else {
+ sym_op->m_dst = NULL;
+ iobuf = ibuf;
+ }
+
+ /* sessionless op requires allocate xform using
+ * rte_crypto_op_sym_xforms_alloc(), otherwise rte_zmalloc()
+ * is used
+ */
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
+ uint32_t n_xforms = 0;
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
+ n_xforms++;
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
+ n_xforms++;
+
+ if (rte_crypto_op_sym_xforms_alloc(op, n_xforms)
+ == NULL) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__, "Failed to "
+ "allocate space for crypto transforms");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ } else {
+ cipher_xform = rte_zmalloc(NULL,
+ sizeof(struct rte_crypto_sym_xform), 0);
+
+ auth_xform = rte_zmalloc(NULL,
+ sizeof(struct rte_crypto_sym_xform), 0);
+
+ if (!cipher_xform || !auth_xform) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__, "Failed to "
+ "allocate memory for crypto transforms");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+
+ /* preparing xform, for sessioned op, init_xform is initialized
+ * here and later as param in rte_cryptodev_sym_session_create() call
+ */
+ if (t->op_mask == BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN) {
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
+ cipher_xform = op->sym->xform;
+ auth_xform = cipher_xform->next;
+ auth_xform->next = NULL;
+ } else {
+ cipher_xform->next = auth_xform;
+ auth_xform->next = NULL;
+ init_xform = cipher_xform;
+ }
+ } else if (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC) {
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) {
+ auth_xform = op->sym->xform;
+ cipher_xform = auth_xform->next;
+ cipher_xform->next = NULL;
+ } else {
+ auth_xform->next = cipher_xform;
+ cipher_xform->next = NULL;
+ init_xform = auth_xform;
+ }
+ } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_ENCRYPT) ||
+ (t->op_mask == BLOCKCIPHER_TEST_OP_DECRYPT)) {
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
+ cipher_xform = op->sym->xform;
+ else
+ init_xform = cipher_xform;
+ cipher_xform->next = NULL;
+ } else if ((t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_GEN) ||
+ (t->op_mask == BLOCKCIPHER_TEST_OP_AUTH_VERIFY)) {
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)
+ auth_xform = op->sym->xform;
+ else
+ init_xform = auth_xform;
+ auth_xform->next = NULL;
+ } else {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Unrecognized operation");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /*configure xforms & sym_op cipher and auth data*/
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform->cipher.algo = tdata->crypto_algo;
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT)
+ cipher_xform->cipher.op =
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ else
+ cipher_xform->cipher.op =
+ RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ cipher_xform->cipher.key.data = cipher_key;
+ cipher_xform->cipher.key.length = tdata->cipher_key.len;
+ cipher_xform->cipher.iv.offset = IV_OFFSET;
+
+ if (tdata->crypto_algo == RTE_CRYPTO_CIPHER_NULL)
+ cipher_xform->cipher.iv.length = 0;
+ else
+ cipher_xform->cipher.iv.length = tdata->iv.len;
+
+ sym_op->cipher.data.offset = tdata->cipher_offset;
+ sym_op->cipher.data.length = tdata->ciphertext.len -
+ tdata->cipher_offset;
+ rte_memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
+ tdata->iv.data,
+ tdata->iv.len);
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
+ uint32_t digest_offset = tdata->ciphertext.len;
+
+ auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ auth_xform->auth.algo = tdata->auth_algo;
+ auth_xform->auth.key.length = tdata->auth_key.len;
+ auth_xform->auth.key.data = auth_key;
+ auth_xform->auth.digest_length = digest_len;
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
+ auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ sym_op->auth.digest.data = pktmbuf_mtod_offset
+ (iobuf, digest_offset);
+ sym_op->auth.digest.phys_addr =
+ pktmbuf_iova_offset(iobuf,
+ digest_offset);
+ } else {
+ auth_xform->auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ sym_op->auth.digest.data = pktmbuf_mtod_offset
+ (sym_op->m_src, digest_offset);
+ sym_op->auth.digest.phys_addr =
+ pktmbuf_iova_offset(sym_op->m_src,
+ digest_offset);
+ }
+
+ sym_op->auth.data.offset = tdata->auth_offset;
+ sym_op->auth.data.length = tdata->ciphertext.len -
+ tdata->auth_offset;
+ }
+
+ /**
+ * Create session for sessioned op. For mbuf iteration test,
+ * skip the session creation for the second iteration.
+ */
+ if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS) &&
+ nb_iterates == 0) {
+ sess = rte_cryptodev_sym_session_create(sess_mpool);
+
+ status = rte_cryptodev_sym_session_init(dev_id, sess,
+ init_xform, sess_priv_mpool);
+ if (status == -ENOTSUP) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "UNSUPPORTED");
+ goto error_exit;
+ }
+ if (!sess || status < 0) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__,
+ "Session creation failed");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ /* attach symmetric crypto session to crypto operations */
+ rte_crypto_op_attach_sym_session(op, sess);
+ }
+
+ debug_hexdump(stdout, "m_src(before):",
+ sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
+ rte_memcpy(tmp_src_buf, sym_op->m_src->buf_addr,
+ sym_op->m_src->buf_len);
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ debug_hexdump(stdout, "m_dst(before):",
+ sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
+ rte_memcpy(tmp_dst_buf, sym_op->m_dst->buf_addr,
+ sym_op->m_dst->buf_len);
+ }
+
+ /* Process crypto operation */
+ if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Error sending packet for encryption");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ op = NULL;
+
+ while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
+ rte_pause();
+
+ if (!op) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: %s",
+ __LINE__, "Failed to process sym crypto op");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ debug_hexdump(stdout, "m_src(after):",
+ sym_op->m_src->buf_addr, sym_op->m_src->buf_len);
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP)
+ debug_hexdump(stdout, "m_dst(after):",
+ sym_op->m_dst->buf_addr, sym_op->m_dst->buf_len);
+
+ /* Verify results */
+ if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+ if ((t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY) &&
+ (op->status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED))
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: Digest verification failed "
+ "(0x%X)", __LINE__, op->status);
+ else
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: Operation failed "
+ "(0x%X)", __LINE__, op->status);
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ uint8_t buffer[2048];
+ const uint8_t *compare_ref;
+ uint32_t compare_len;
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+ compare_ref = tdata->ciphertext.data +
+ tdata->cipher_offset;
+ compare_len = tdata->ciphertext.len -
+ tdata->cipher_offset;
+ } else {
+ compare_ref = tdata->plaintext.data +
+ tdata->cipher_offset;
+ compare_len = tdata->plaintext.len -
+ tdata->cipher_offset;
+ }
+
+ if (memcmp(rte_pktmbuf_read(iobuf, tdata->cipher_offset,
+ compare_len, buffer), compare_ref,
+ compare_len)) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__,
+ "Crypto data not as expected");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN) {
+ uint8_t *auth_res = pktmbuf_mtod_offset(iobuf,
+ tdata->ciphertext.len);
+
+ if (memcmp(auth_res, tdata->digest.data, digest_len)) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
+ "FAILED: %s", __LINE__, "Generated "
+ "digest data not as expected");
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+
+ /* The only parts that should have changed in the buffer are
+ * plaintext/ciphertext and digest.
+ * In OOP only the dest buffer should change.
+ */
+ if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+ struct rte_mbuf *mbuf;
+ uint8_t value;
+ uint32_t head_unchanged_len, changed_len = 0;
+ uint32_t i;
+ uint32_t hdroom_used = 0, tlroom_used = 0;
+ uint32_t hdroom = 0;
+
+ mbuf = sym_op->m_src;
+ /*
+ * Crypto PMDs specify the headroom & tailroom it would use
+ * when processing the crypto operation. PMD is free to modify
+ * this space, and so the verification check should skip that
+ * block.
+ */
+ hdroom_used = dev_info.min_mbuf_headroom_req;
+ tlroom_used = dev_info.min_mbuf_tailroom_req;
+
+ /* Get headroom */
+ hdroom = rte_pktmbuf_headroom(mbuf);
+
+ head_unchanged_len = mbuf->buf_len;
+
+ for (i = 0; i < mbuf->buf_len; i++) {
+
+ /* Skip headroom used by PMD */
+ if (i == hdroom - hdroom_used)
+ i += hdroom_used;
+
+ /* Skip tailroom used by PMD */
+ if (i == (hdroom + mbuf->data_len))
+ i += tlroom_used;
+
+ value = *((uint8_t *)(mbuf->buf_addr)+i);
+ if (value != tmp_src_buf[i]) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: OOP src outer mbuf data (0x%x) not as expected (0x%x)",
+ __LINE__, value, tmp_src_buf[i]);
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+
+ mbuf = sym_op->m_dst;
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH) {
+ head_unchanged_len = hdroom + sym_op->auth.data.offset;
+ changed_len = sym_op->auth.data.length;
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
+ changed_len += digest_len;
+ } else {
+ /* cipher-only */
+ head_unchanged_len = hdroom +
+ sym_op->cipher.data.offset;
+ changed_len = sym_op->cipher.data.length;
+ }
+
+ for (i = 0; i < mbuf->buf_len; i++) {
+ if (i == head_unchanged_len)
+ i += changed_len;
+ value = *((uint8_t *)(mbuf->buf_addr)+i);
+ if (value != tmp_dst_buf[i]) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: OOP dst outer mbuf data "
+ "(0x%x) not as expected (0x%x)",
+ __LINE__, value, tmp_dst_buf[i]);
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+
+ if (!nb_iterates) {
+ nb_iterates++;
+ goto iterate;
+ }
+ } else {
+ /* In-place operation */
+ struct rte_mbuf *mbuf;
+ uint8_t value;
+ uint32_t head_unchanged_len = 0, changed_len = 0;
+ uint32_t i;
+ uint32_t hdroom_used = 0, tlroom_used = 0;
+ uint32_t hdroom = 0;
+
+ /*
+ * Crypto PMDs specify the headroom & tailroom it would use
+ * when processing the crypto operation. PMD is free to modify
+ * this space, and so the verification check should skip that
+ * block.
+ */
+ hdroom_used = dev_info.min_mbuf_headroom_req;
+ tlroom_used = dev_info.min_mbuf_tailroom_req;
+
+ mbuf = sym_op->m_src;
+
+ /* Get headroom */
+ hdroom = rte_pktmbuf_headroom(mbuf);
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+ head_unchanged_len = hdroom +
+ sym_op->cipher.data.offset;
+ changed_len = sym_op->cipher.data.length;
+ } else {
+ /* auth-only */
+ head_unchanged_len = hdroom +
+ sym_op->auth.data.offset +
+ sym_op->auth.data.length;
+ changed_len = 0;
+ }
+
+ if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_GEN)
+ changed_len += digest_len;
+
+ for (i = 0; i < mbuf->buf_len; i++) {
+
+ /* Skip headroom used by PMD */
+ if (i == hdroom - hdroom_used)
+ i += hdroom_used;
+
+ if (i == head_unchanged_len)
+ i += changed_len;
+
+ /* Skip tailroom used by PMD */
+ if (i == (hdroom + mbuf->data_len))
+ i += tlroom_used;
+
+ value = *((uint8_t *)(mbuf->buf_addr)+i);
+ if (value != tmp_src_buf[i]) {
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+ "line %u FAILED: outer mbuf data (0x%x) "
+ "not as expected (0x%x)",
+ __LINE__, value, tmp_src_buf[i]);
+ status = TEST_FAILED;
+ goto error_exit;
+ }
+ }
+ }
+
+ snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "PASS");
+
+error_exit:
+ if (!(t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SESSIONLESS)) {
+ if (sess) {
+ rte_cryptodev_sym_session_clear(dev_id, sess);
+ rte_cryptodev_sym_session_free(sess);
+ }
+ if (cipher_xform)
+ rte_free(cipher_xform);
+ if (auth_xform)
+ rte_free(auth_xform);
+ }
+
+ if (op)
+ rte_crypto_op_free(op);
+
+ if (obuf)
+ rte_pktmbuf_free(obuf);
+
+ if (ibuf)
+ rte_pktmbuf_free(ibuf);
+
+ return status;
+}
+
+int
+test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
+ struct rte_mempool *op_mpool,
+ struct rte_mempool *sess_mpool,
+ struct rte_mempool *sess_priv_mpool,
+ uint8_t dev_id,
+ enum blockcipher_test_type test_type)
+{
+ int status, overall_status = TEST_SUCCESS;
+ uint32_t i, test_index = 0;
+ char test_msg[BLOCKCIPHER_TEST_MSG_LEN + 1];
+ uint32_t n_test_cases = 0;
+ const struct blockcipher_test_case *tcs = NULL;
+
+ switch (test_type) {
+ case BLKCIPHER_AES_CHAIN_TYPE:
+ n_test_cases = sizeof(aes_chain_test_cases) /
+ sizeof(aes_chain_test_cases[0]);
+ tcs = aes_chain_test_cases;
+ break;
+ case BLKCIPHER_AES_CIPHERONLY_TYPE:
+ n_test_cases = sizeof(aes_cipheronly_test_cases) /
+ sizeof(aes_cipheronly_test_cases[0]);
+ tcs = aes_cipheronly_test_cases;
+ break;
+ case BLKCIPHER_AES_DOCSIS_TYPE:
+ n_test_cases = sizeof(aes_docsis_test_cases) /
+ sizeof(aes_docsis_test_cases[0]);
+ tcs = aes_docsis_test_cases;
+ break;
+ case BLKCIPHER_3DES_CHAIN_TYPE:
+ n_test_cases = sizeof(triple_des_chain_test_cases) /
+ sizeof(triple_des_chain_test_cases[0]);
+ tcs = triple_des_chain_test_cases;
+ break;
+ case BLKCIPHER_3DES_CIPHERONLY_TYPE:
+ n_test_cases = sizeof(triple_des_cipheronly_test_cases) /
+ sizeof(triple_des_cipheronly_test_cases[0]);
+ tcs = triple_des_cipheronly_test_cases;
+ break;
+ case BLKCIPHER_DES_CIPHERONLY_TYPE:
+ n_test_cases = sizeof(des_cipheronly_test_cases) /
+ sizeof(des_cipheronly_test_cases[0]);
+ tcs = des_cipheronly_test_cases;
+ break;
+ case BLKCIPHER_DES_DOCSIS_TYPE:
+ n_test_cases = sizeof(des_docsis_test_cases) /
+ sizeof(des_docsis_test_cases[0]);
+ tcs = des_docsis_test_cases;
+ break;
+ case BLKCIPHER_AUTHONLY_TYPE:
+ n_test_cases = sizeof(hash_test_cases) /
+ sizeof(hash_test_cases[0]);
+ tcs = hash_test_cases;
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < n_test_cases; i++) {
+ const struct blockcipher_test_case *tc = &tcs[i];
+
+ status = test_blockcipher_one_case(tc, mbuf_pool, op_mpool,
+ sess_mpool, sess_priv_mpool, dev_id,
+ test_msg);
+
+ printf(" %u) TestCase %s %s\n", test_index ++,
+ tc->test_descr, test_msg);
+
+ if (status != TEST_SUCCESS) {
+ if (overall_status == TEST_SUCCESS)
+ overall_status = status;
+
+ if (tc->feature_mask & BLOCKCIPHER_TEST_FEATURE_STOPPER)
+ break;
+ }
+ }
+
+ return overall_status;
+}
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.h b/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.h
new file mode 100644
index 000000000..899071684
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_blockcipher.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_BLOCKCIPHER_H_
+#define TEST_CRYPTODEV_BLOCKCIPHER_H_
+
+#ifndef BLOCKCIPHER_TEST_MSG_LEN
+#define BLOCKCIPHER_TEST_MSG_LEN 256
+#endif
+
+#define BLOCKCIPHER_TEST_OP_ENCRYPT 0x01
+#define BLOCKCIPHER_TEST_OP_DECRYPT 0x02
+#define BLOCKCIPHER_TEST_OP_AUTH_GEN 0x04
+#define BLOCKCIPHER_TEST_OP_AUTH_VERIFY 0x08
+
+#define BLOCKCIPHER_TEST_FEATURE_OOP 0x01
+#define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS 0x02
+#define BLOCKCIPHER_TEST_FEATURE_STOPPER 0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG 0x08 /* Scatter Gather */
+
+#define BLOCKCIPHER_TEST_OP_CIPHER (BLOCKCIPHER_TEST_OP_ENCRYPT | \
+ BLOCKCIPHER_TEST_OP_DECRYPT)
+
+#define BLOCKCIPHER_TEST_OP_AUTH (BLOCKCIPHER_TEST_OP_AUTH_GEN | \
+ BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+
+#define BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN (BLOCKCIPHER_TEST_OP_ENCRYPT | \
+ BLOCKCIPHER_TEST_OP_AUTH_GEN)
+
+#define BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC (BLOCKCIPHER_TEST_OP_DECRYPT | \
+ BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+
+enum blockcipher_test_type {
+ BLKCIPHER_AES_CHAIN_TYPE, /* use aes_chain_test_cases[] */
+ BLKCIPHER_AES_CIPHERONLY_TYPE, /* use aes_cipheronly_test_cases[] */
+ BLKCIPHER_AES_DOCSIS_TYPE, /* use aes_docsis_test_cases[] */
+ BLKCIPHER_3DES_CHAIN_TYPE, /* use triple_des_chain_test_cases[] */
+ BLKCIPHER_3DES_CIPHERONLY_TYPE, /* triple_des_cipheronly_test_cases[] */
+ BLKCIPHER_AUTHONLY_TYPE, /* use hash_test_cases[] */
+ BLKCIPHER_DES_CIPHERONLY_TYPE, /* use des_cipheronly_test_cases[] */
+ BLKCIPHER_DES_DOCSIS_TYPE /* use des_docsis_test_cases[] */
+};
+
+struct blockcipher_test_case {
+ const char *test_descr; /* test description */
+ const struct blockcipher_test_data *test_data;
+ uint8_t op_mask; /* operation mask */
+ uint8_t feature_mask;
+};
+
+struct blockcipher_test_data {
+ enum rte_crypto_cipher_algorithm crypto_algo;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len;
+ } cipher_key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned int len;
+ } iv;
+
+ struct {
+ const uint8_t *data;
+ unsigned int len;
+ } plaintext;
+
+ struct {
+ const uint8_t *data;
+ unsigned int len;
+ } ciphertext;
+
+ enum rte_crypto_auth_algorithm auth_algo;
+
+ struct {
+ uint8_t data[128];
+ unsigned int len;
+ } auth_key;
+
+ struct {
+ uint8_t data[128];
+ unsigned int len; /* for qat */
+ unsigned int truncated_len; /* for mb */
+ } digest;
+
+ unsigned int cipher_offset;
+ unsigned int auth_offset;
+};
+
+int
+test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
+ struct rte_mempool *op_mpool,
+ struct rte_mempool *sess_mpool,
+ struct rte_mempool *sess_priv_mpool,
+ uint8_t dev_id,
+ enum blockcipher_test_type test_type);
+
+#endif /* TEST_CRYPTODEV_BLOCKCIPHER_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_des_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_des_test_vectors.h
new file mode 100644
index 000000000..3ded90b6d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_des_test_vectors.h
@@ -0,0 +1,1189 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_DES_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_DES_TEST_VECTORS_H_
+
+static const uint8_t plaintext_des[] = {
+ "What a lousy earth! He wondered how many people "
+ "were destitute that same night even in his own "
+ "prosperous country, how many homes were "
+ "shanties, how many husbands were drunk and "
+ "wives socked, and how many children were "
+ "bullied, abused, or abandoned. How many "
+ "families hungered for food they could not "
+ "afford to buy? How many hearts were broken? How "
+ "many suicides would take place that same night, "
+ "how many people would go insane? How many "
+ "cockroaches and landlords would triumph? How "
+ "many winners were losers, successes failures, "
+ "and rich men poor men? How many wise guys were "
+ "stupid? How many happy endings were unhappy "
+ "endings? How many honest men were liars, brave "
+ "men cowards, loyal men traitors, how many "
+ "sainted men were corrupt, how many people in "
+ "positions of trust had sold their souls to "
+ "bodyguards, how many had never had souls? How "
+ "many straight-and-narrow paths were crooked "
+ "paths? How many best families were worst "
+ "families and how many good people were bad "
+ "people? When you added them all up and then "
+ "subtracted, you might be left with only the "
+ "children, and perhaps with Albert Einstein and "
+ "an old violinist or sculptor somewhere."
+};
+
+static const uint8_t ciphertext512_des128ctr[] = {
+ 0x13, 0x39, 0x3B, 0xBC, 0x1D, 0xE3, 0x23, 0x09,
+ 0x9B, 0x08, 0xD1, 0x09, 0x52, 0x93, 0x78, 0x29,
+ 0x11, 0x21, 0xBA, 0x01, 0x15, 0xCD, 0xEC, 0xAA,
+ 0x79, 0x77, 0x58, 0xAE, 0xAE, 0xBC, 0x97, 0x33,
+ 0x94, 0xA9, 0x2D, 0xC0, 0x0A, 0xA9, 0xA4, 0x4B,
+ 0x19, 0x07, 0x88, 0x06, 0x7E, 0x81, 0x0F, 0xB5,
+ 0x60, 0xCF, 0xA7, 0xC3, 0x2A, 0x43, 0xFF, 0x16,
+ 0x3A, 0x5F, 0x11, 0x2D, 0x11, 0x38, 0x37, 0x94,
+ 0x2A, 0xC8, 0x3D, 0x20, 0xBB, 0x93, 0x95, 0x54,
+ 0x12, 0xFF, 0x0C, 0x47, 0x89, 0x7D, 0x73, 0xD1,
+ 0x2E, 0x3A, 0x80, 0x52, 0xA8, 0x92, 0x93, 0x99,
+ 0x16, 0xB8, 0x12, 0x1B, 0x8B, 0xA8, 0xC1, 0x81,
+ 0x95, 0x18, 0x82, 0xD6, 0x5A, 0xA7, 0xFE, 0xCF,
+ 0xC4, 0xAC, 0x85, 0x91, 0x0C, 0x2F, 0x1D, 0x10,
+ 0x9A, 0x65, 0x07, 0xB0, 0x2E, 0x5A, 0x2D, 0x48,
+ 0x26, 0xF8, 0x17, 0x7A, 0x53, 0xD6, 0xB8, 0xDF,
+ 0xB1, 0x10, 0x48, 0x7E, 0x8F, 0xBE, 0x2E, 0xA1,
+ 0x0D, 0x9E, 0xA9, 0xF1, 0x3B, 0x3B, 0x33, 0xCD,
+ 0xDC, 0x52, 0x7E, 0xC0, 0x0E, 0xA0, 0xD8, 0xA7,
+ 0xC6, 0x34, 0x5A, 0xAA, 0x29, 0x8B, 0xA9, 0xAC,
+ 0x1F, 0x78, 0xAD, 0xEE, 0x34, 0x59, 0x30, 0xFB,
+ 0x2A, 0x20, 0x3D, 0x4D, 0x30, 0xA7, 0x7D, 0xD8,
+ 0xA0, 0xC6, 0xA2, 0xD3, 0x9A, 0xFB, 0x50, 0x97,
+ 0x4D, 0x25, 0xA2, 0x37, 0x51, 0x54, 0xB7, 0xEB,
+ 0xED, 0x77, 0xDB, 0x94, 0x35, 0x8B, 0x70, 0x95,
+ 0x4A, 0x00, 0xA7, 0xF1, 0x8A, 0x66, 0x0E, 0xC6,
+ 0x05, 0x7B, 0x69, 0x05, 0x42, 0x03, 0x96, 0x2C,
+ 0x55, 0x00, 0x1B, 0xC0, 0x19, 0x4D, 0x0D, 0x2E,
+ 0xF5, 0x81, 0x11, 0x64, 0xCA, 0xBB, 0xF2, 0x0F,
+ 0x9C, 0x60, 0xE2, 0xCC, 0x02, 0x6E, 0x83, 0xD5,
+ 0x24, 0xF4, 0x12, 0x0E, 0x6A, 0xEA, 0x4F, 0x6C,
+ 0x79, 0x69, 0x65, 0x67, 0xDB, 0xF7, 0xEA, 0x98,
+ 0x5D, 0x56, 0x98, 0xB7, 0x88, 0xE7, 0x23, 0xC9,
+ 0x17, 0x32, 0x92, 0x33, 0x5A, 0x0C, 0x15, 0x20,
+ 0x3B, 0x1C, 0xF9, 0x0F, 0x4D, 0xD1, 0xE8, 0xE6,
+ 0x9E, 0x5E, 0x24, 0x1B, 0xA4, 0xB8, 0xB9, 0xE9,
+ 0x2F, 0xFC, 0x89, 0xB4, 0xB9, 0xF4, 0xA6, 0xAD,
+ 0x55, 0xF4, 0xDF, 0x58, 0x63, 0x25, 0xE3, 0x41,
+ 0x70, 0xDF, 0x10, 0xE7, 0x13, 0x87, 0x8D, 0xB3,
+ 0x62, 0x4F, 0xF5, 0x86, 0x85, 0x8F, 0x59, 0xF0,
+ 0x21, 0x0E, 0x8F, 0x11, 0xAD, 0xBF, 0xDD, 0x61,
+ 0x68, 0x3F, 0x54, 0x57, 0x49, 0x38, 0xC8, 0x24,
+ 0x8E, 0x0A, 0xAC, 0xCA, 0x2C, 0x36, 0x3E, 0x5F,
+ 0x0A, 0xCE, 0xFD, 0x1A, 0x60, 0x63, 0x5A, 0xE6,
+ 0x06, 0x64, 0xB5, 0x94, 0x3C, 0xC9, 0xAF, 0x7C,
+ 0xCD, 0x49, 0x10, 0xCF, 0xAF, 0x0E, 0x2E, 0x79,
+ 0x27, 0xB2, 0x67, 0x02, 0xED, 0xEE, 0x80, 0x77,
+ 0x7C, 0x6D, 0x4B, 0xDB, 0xCF, 0x8D, 0x68, 0x00,
+ 0x2E, 0xD9, 0xF0, 0x8E, 0x08, 0xBF, 0xA6, 0x9B,
+ 0xFE, 0xA4, 0xFB, 0x19, 0x46, 0xAF, 0x1B, 0xA9,
+ 0xF8, 0x22, 0x81, 0x21, 0x97, 0xFC, 0xC0, 0x8A,
+ 0x26, 0x58, 0x13, 0x29, 0xB6, 0x69, 0x94, 0x4B,
+ 0xAB, 0xB3, 0x88, 0x0D, 0xA9, 0x48, 0x0E, 0xE8,
+ 0x70, 0xFC, 0xA1, 0x21, 0xC4, 0x2C, 0xE5, 0x99,
+ 0xB4, 0xF1, 0x6F, 0xB2, 0x4B, 0x4B, 0xCD, 0x48,
+ 0x15, 0x47, 0x2D, 0x72, 0x39, 0x99, 0x9D, 0x24,
+ 0x0C, 0x8B, 0xDC, 0xA1, 0xEE, 0xF6, 0xF4, 0x73,
+ 0xC3, 0xB8, 0x0C, 0x23, 0x0D, 0xA7, 0xC4, 0x7D,
+ 0x27, 0xE2, 0x14, 0x11, 0x53, 0x19, 0xE7, 0xCA,
+ 0x94, 0x4E, 0x0D, 0x2C, 0xF7, 0x36, 0x47, 0xDB,
+ 0x77, 0x3C, 0x22, 0xAC, 0xBE, 0xE1, 0x06, 0x55,
+ 0xE5, 0xDD, 0x8B, 0x65, 0xE8, 0xE9, 0x91, 0x52,
+ 0x59, 0x97, 0xFC, 0x8C, 0xEE, 0x96, 0x22, 0x60,
+ 0xEE, 0xBF, 0x82, 0xF0, 0xCA, 0x14, 0xF9, 0xD3
+};
+
+static const struct blockcipher_test_data
+triple_des128ctr_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128ctr,
+ .len = 512
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des128ctr_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128ctr,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1,
+ .digest = {
+ .data = {
+ 0xC3, 0x40, 0xD5, 0xD9, 0x8F, 0x8A, 0xC0, 0xF0,
+ 0x46, 0x28, 0x02, 0x01, 0xB5, 0xC1, 0x87, 0x4D,
+ 0xAC, 0xFE, 0x48, 0x76
+ },
+ .len = 20
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des128ctr_hmac_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128ctr,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0xF1, 0xC1, 0xDB, 0x4D, 0xFA, 0x7F, 0x2F, 0xE5,
+ 0xF8, 0x49, 0xEA, 0x1D, 0x7F, 0xCB, 0x42, 0x59,
+ 0xC4, 0x1E, 0xB1, 0x18
+ },
+ .len = 20
+ }
+};
+
+static const uint8_t ciphertext512_des192ctr[] = {
+ 0xFF, 0x32, 0x52, 0x97, 0x10, 0xBF, 0x0B, 0x10,
+ 0x68, 0x0F, 0x4F, 0x56, 0x8B, 0x2C, 0x7B, 0x8E,
+ 0x39, 0x1E, 0x1A, 0x2F, 0x83, 0xDE, 0x5E, 0x35,
+ 0xC8, 0x4B, 0xDF, 0xD5, 0xBC, 0x84, 0x50, 0x1A,
+ 0x02, 0xDF, 0xB3, 0x11, 0xE4, 0xDA, 0xB8, 0x0E,
+ 0x47, 0xC6, 0x0C, 0x51, 0x09, 0x62, 0x9C, 0x5D,
+ 0x71, 0x40, 0x49, 0xD8, 0x55, 0xBD, 0x7D, 0x90,
+ 0x71, 0xC5, 0xF7, 0x07, 0x6F, 0x08, 0x71, 0x2A,
+ 0xB1, 0x77, 0x9B, 0x0F, 0xA1, 0xB0, 0xD6, 0x10,
+ 0xB2, 0xE5, 0x31, 0xEC, 0x21, 0x13, 0x89, 0x2A,
+ 0x09, 0x7E, 0x30, 0xDB, 0xA0, 0xF0, 0xDC, 0xE4,
+ 0x74, 0x64, 0x39, 0xA3, 0xB0, 0xB1, 0x80, 0x66,
+ 0x52, 0xD4, 0x4E, 0xC9, 0x5A, 0x52, 0x6A, 0xC7,
+ 0xB5, 0x2B, 0x61, 0xD5, 0x17, 0xD5, 0xF3, 0xCC,
+ 0x41, 0x61, 0xD2, 0xA6, 0xF4, 0x51, 0x24, 0x3A,
+ 0x63, 0x5D, 0x23, 0xB1, 0xF0, 0x22, 0xE7, 0x45,
+ 0xFA, 0x5F, 0x7E, 0x99, 0x00, 0x11, 0x28, 0x35,
+ 0xA3, 0xF4, 0x61, 0x94, 0x0E, 0x98, 0xCE, 0x35,
+ 0xDD, 0x91, 0x1B, 0x0B, 0x4D, 0xEE, 0xFF, 0xFF,
+ 0x0B, 0xD4, 0xDC, 0x56, 0xFC, 0x71, 0xE9, 0xEC,
+ 0xE8, 0x36, 0x51, 0xF8, 0x8B, 0x6A, 0xE1, 0x8C,
+ 0x2B, 0x25, 0x91, 0x91, 0x9B, 0x92, 0x76, 0xB5,
+ 0x3D, 0x26, 0xA8, 0x53, 0xEA, 0x30, 0x5B, 0x4D,
+ 0xDA, 0x16, 0xDA, 0x7D, 0x04, 0x88, 0xF5, 0x22,
+ 0xA8, 0x0C, 0xB9, 0x41, 0xC7, 0x91, 0x64, 0x86,
+ 0x99, 0x7D, 0x18, 0xB9, 0x67, 0xA2, 0x6E, 0x05,
+ 0x1A, 0x82, 0x8F, 0xA2, 0xEB, 0x4D, 0x0B, 0x8C,
+ 0x88, 0x2D, 0xBA, 0x77, 0x87, 0x32, 0x50, 0x3C,
+ 0x4C, 0xD8, 0xD3, 0x50, 0x39, 0xFA, 0xDF, 0x48,
+ 0x3E, 0x30, 0xF5, 0x76, 0x06, 0xB0, 0x1A, 0x05,
+ 0x60, 0x2C, 0xD3, 0xA0, 0x63, 0x1A, 0x19, 0x2D,
+ 0x6B, 0x76, 0xF2, 0x31, 0x4C, 0xA7, 0xE6, 0x5C,
+ 0x1B, 0x23, 0x20, 0x41, 0x32, 0xE5, 0x83, 0x47,
+ 0x04, 0xB6, 0x3E, 0xE0, 0xFD, 0x49, 0x1E, 0x1B,
+ 0x75, 0x10, 0x11, 0x46, 0xE9, 0xF9, 0x96, 0x9A,
+ 0xD7, 0x59, 0xFE, 0x38, 0x31, 0xFE, 0x79, 0xC4,
+ 0xC8, 0x46, 0x88, 0xDE, 0x2E, 0xAE, 0x20, 0xED,
+ 0x77, 0x50, 0x40, 0x38, 0x26, 0xD3, 0x35, 0xF6,
+ 0x29, 0x55, 0x6A, 0x6B, 0x38, 0x69, 0xFE, 0x90,
+ 0x5B, 0xA7, 0xFA, 0x6B, 0x73, 0x4F, 0xB9, 0x5D,
+ 0xDC, 0x6F, 0x98, 0xC3, 0x6A, 0xC4, 0xB5, 0x09,
+ 0xC5, 0x84, 0xA5, 0x6A, 0x84, 0xA4, 0xB3, 0x8A,
+ 0x5F, 0xCA, 0x92, 0x64, 0x9E, 0xC3, 0x0F, 0x84,
+ 0x8B, 0x2D, 0x48, 0xC6, 0x67, 0xAE, 0x07, 0xE0,
+ 0x28, 0x38, 0x6D, 0xC4, 0x4D, 0x13, 0x87, 0xE0,
+ 0xB2, 0x2F, 0xAA, 0xC0, 0xCF, 0x68, 0xD7, 0x9C,
+ 0xB8, 0x07, 0xE4, 0x51, 0xD7, 0x75, 0x86, 0xFA,
+ 0x0C, 0x50, 0x74, 0x68, 0x00, 0x64, 0x2A, 0x27,
+ 0x59, 0xE9, 0x80, 0xEB, 0xC2, 0xA3, 0xFA, 0x58,
+ 0xCC, 0x03, 0xE7, 0x7B, 0x66, 0x53, 0xFF, 0x90,
+ 0xA0, 0x85, 0xE2, 0xF8, 0x82, 0xFE, 0xC6, 0x2B,
+ 0xFF, 0x5E, 0x70, 0x85, 0x34, 0xB7, 0x22, 0x38,
+ 0xDB, 0xBC, 0x15, 0x30, 0x59, 0xC1, 0x48, 0x42,
+ 0xE5, 0x38, 0x8D, 0x37, 0x59, 0xDB, 0xA3, 0x20,
+ 0x17, 0x36, 0x1D, 0x4B, 0xBF, 0x4E, 0xA4, 0x35,
+ 0xCC, 0xFE, 0xF5, 0x7A, 0x73, 0xB4, 0x6D, 0x20,
+ 0x1D, 0xC0, 0xE5, 0x21, 0x5C, 0xD2, 0x8A, 0x65,
+ 0x08, 0xB6, 0x63, 0xAC, 0x9A, 0x1E, 0x3F, 0x3C,
+ 0xAB, 0xB6, 0x6D, 0x34, 0xB2, 0x3A, 0x08, 0xDA,
+ 0x29, 0x63, 0xD1, 0xA4, 0x83, 0x52, 0xB0, 0x63,
+ 0x1B, 0x89, 0x35, 0x57, 0x59, 0x2C, 0x0F, 0x72,
+ 0x72, 0xFD, 0xA0, 0xAC, 0xDB, 0xB4, 0xA3, 0xA1,
+ 0x18, 0x10, 0x12, 0x97, 0x99, 0x63, 0x38, 0x98,
+ 0x96, 0xB5, 0x16, 0x07, 0x4E, 0xE9, 0x2C, 0x97
+};
+
+static const struct blockcipher_test_data
+triple_des192ctr_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192ctr,
+ .len = 512
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des192ctr_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192ctr,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1,
+ .digest = {
+ .data = {
+ 0xEA, 0x62, 0xB9, 0xB2, 0x78, 0x6C, 0x8E, 0xDB,
+ 0xA3, 0xB6, 0xFF, 0x23, 0x3A, 0x47, 0xD8, 0xC8,
+ 0xED, 0x5E, 0x20, 0x1D
+ },
+ .len = 20
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des192ctr_hmac_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192ctr,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x32, 0xD5, 0x19, 0x8F, 0x79, 0x3A, 0xAA, 0x7B,
+ 0x70, 0x67, 0x4E, 0x63, 0x88, 0xA3, 0x9A, 0x82,
+ 0x07, 0x33, 0x12, 0x94
+ },
+ .len = 20
+ }
+};
+
+static const uint8_t ciphertext512_des128cbc[] = {
+ 0x28, 0x2a, 0xff, 0x15, 0x5c, 0xdf, 0xd9, 0x6b,
+ 0x54, 0xbc, 0x7b, 0xfb, 0xc5, 0x64, 0x4d, 0xdd,
+ 0x3e, 0xf2, 0x9e, 0xb7, 0x53, 0x65, 0x37, 0x05,
+ 0xe0, 0xdf, 0xae, 0xf7, 0xc9, 0x27, 0xe4, 0xec,
+ 0x11, 0x27, 0xc2, 0x9e, 0x02, 0x4e, 0x03, 0x3b,
+ 0x33, 0xf2, 0x66, 0x08, 0x24, 0x5f, 0xab, 0xc2,
+ 0x7e, 0x21, 0x19, 0x5d, 0x51, 0xc3, 0xe2, 0x97,
+ 0x6f, 0x2e, 0xb4, 0xaa, 0x34, 0x70, 0x88, 0x78,
+ 0x4e, 0xe7, 0x3d, 0xe1, 0x9f, 0x87, 0x1c, 0x8b,
+ 0xac, 0x8d, 0xa1, 0x1a, 0xcd, 0xb0, 0xf8, 0xb6,
+ 0x24, 0x36, 0xe3, 0x8c, 0x07, 0xe7, 0xe4, 0x92,
+ 0x13, 0x86, 0x6f, 0x13, 0xec, 0x04, 0x5c, 0xe9,
+ 0xb9, 0xca, 0x45, 0x8a, 0x2c, 0x46, 0xda, 0x54,
+ 0x1d, 0xb5, 0x81, 0xb1, 0xcd, 0xf3, 0x7d, 0x11,
+ 0x6b, 0xb3, 0x0a, 0x45, 0xe5, 0x6e, 0x51, 0x3e,
+ 0x2c, 0xac, 0x7c, 0xbc, 0xa7, 0x7e, 0x22, 0x4d,
+ 0xe6, 0x02, 0xe3, 0x3f, 0x77, 0xd7, 0x73, 0x72,
+ 0x0e, 0xfb, 0x42, 0x85, 0x80, 0xdf, 0xa8, 0x91,
+ 0x60, 0x40, 0x48, 0xcd, 0x1b, 0xd9, 0xbf, 0x2f,
+ 0xf2, 0xdf, 0xd0, 0xbd, 0x3f, 0x82, 0xce, 0x15,
+ 0x9d, 0x6e, 0xc6, 0x59, 0x6f, 0x27, 0x0d, 0xf9,
+ 0x26, 0xe2, 0x11, 0x29, 0x50, 0xc3, 0x0a, 0xb7,
+ 0xde, 0x9d, 0xe9, 0x55, 0xa1, 0xe9, 0x01, 0x33,
+ 0x56, 0x51, 0xa7, 0x3a, 0x9e, 0x63, 0xc5, 0x08,
+ 0x01, 0x3b, 0x03, 0x4b, 0xc6, 0xc4, 0xa1, 0xc0,
+ 0xc0, 0xd0, 0x0e, 0x48, 0xe5, 0x4c, 0x55, 0x6b,
+ 0x4a, 0xc1, 0x0a, 0x24, 0x4b, 0xd0, 0x02, 0xf4,
+ 0x31, 0x63, 0x11, 0xbd, 0xa6, 0x1f, 0xf4, 0xae,
+ 0x23, 0x5a, 0x40, 0x7e, 0x0e, 0x4e, 0x63, 0x8b,
+ 0x66, 0x3d, 0x55, 0x46, 0x6e, 0x5c, 0x76, 0xa7,
+ 0x68, 0x31, 0xce, 0x5d, 0xca, 0xe2, 0xb4, 0xb0,
+ 0xc1, 0x1f, 0x66, 0x18, 0x75, 0x64, 0x73, 0xa9,
+ 0x9e, 0xd5, 0x0e, 0x0e, 0xf7, 0x77, 0x61, 0xf8,
+ 0x89, 0xc6, 0xcf, 0x0c, 0x41, 0xd3, 0x8f, 0xfd,
+ 0x22, 0x52, 0x4f, 0x94, 0x5c, 0x19, 0x11, 0x3a,
+ 0xb5, 0x63, 0xe8, 0x81, 0x33, 0x13, 0x54, 0x3c,
+ 0x93, 0x36, 0xb5, 0x5b, 0x51, 0xaf, 0x51, 0xa2,
+ 0x08, 0xae, 0x83, 0x15, 0x77, 0x07, 0x28, 0x0d,
+ 0x98, 0xe1, 0x2f, 0x69, 0x0e, 0xfb, 0x9a, 0x2e,
+ 0x27, 0x27, 0xb0, 0xd5, 0xce, 0xf8, 0x16, 0x55,
+ 0xfd, 0xaa, 0xd7, 0x1a, 0x1b, 0x2e, 0x4c, 0x86,
+ 0x7a, 0x6a, 0x90, 0xf7, 0x0a, 0x07, 0xd3, 0x81,
+ 0x4b, 0x75, 0x6a, 0x79, 0xdb, 0x63, 0x45, 0x0f,
+ 0x31, 0x7e, 0xd0, 0x2a, 0x14, 0xff, 0xee, 0xcc,
+ 0x97, 0x8a, 0x7d, 0x74, 0xbd, 0x9d, 0xaf, 0x00,
+ 0xdb, 0x7e, 0xf3, 0xe6, 0x22, 0x76, 0x77, 0x58,
+ 0xba, 0x1c, 0x06, 0x96, 0xfb, 0x6f, 0x41, 0x71,
+ 0x66, 0x98, 0xae, 0x31, 0x7d, 0x29, 0x18, 0x71,
+ 0x0e, 0xe4, 0x98, 0x7e, 0x59, 0x5a, 0xc9, 0x78,
+ 0x9c, 0xfb, 0x6c, 0x81, 0x44, 0xb4, 0x0f, 0x5e,
+ 0x18, 0x53, 0xb8, 0x6f, 0xbc, 0x3b, 0x15, 0xf0,
+ 0x10, 0xdd, 0x0d, 0x4b, 0x0a, 0x36, 0x0e, 0xb4,
+ 0x76, 0x0f, 0x16, 0xa7, 0x5c, 0x9d, 0xcf, 0xb0,
+ 0x6d, 0x38, 0x02, 0x07, 0x05, 0xe9, 0xe9, 0x46,
+ 0x08, 0xb8, 0x52, 0xd6, 0xd9, 0x4c, 0x81, 0x63,
+ 0x1d, 0xe2, 0x5b, 0xd0, 0xf6, 0x5e, 0x1e, 0x81,
+ 0x48, 0x08, 0x66, 0x3a, 0x85, 0xed, 0x65, 0xfe,
+ 0xe8, 0x05, 0x7a, 0xe1, 0xe6, 0x12, 0xf2, 0x52,
+ 0x83, 0xdd, 0x82, 0xbe, 0xf6, 0x34, 0x8a, 0x6f,
+ 0xc5, 0x83, 0xcd, 0x3f, 0xbe, 0x58, 0x8b, 0x11,
+ 0x78, 0xdc, 0x0c, 0x83, 0x72, 0x5d, 0x05, 0x2a,
+ 0x01, 0x29, 0xee, 0x48, 0x9a, 0x67, 0x00, 0x6e,
+ 0x14, 0x60, 0x2d, 0x00, 0x52, 0x87, 0x98, 0x5e,
+ 0x43, 0xfe, 0xf1, 0x10, 0x14, 0xf1, 0x91, 0xcc
+};
+
+
+static const uint8_t ciphertext512_des[] = {
+ 0x1A, 0x46, 0xDB, 0x69, 0x43, 0x45, 0x0F, 0x2F,
+ 0xDC, 0x27, 0xF9, 0x41, 0x0E, 0x01, 0x58, 0xB4,
+ 0x5E, 0xCC, 0x13, 0xF5, 0x92, 0x99, 0xE4, 0xF2,
+ 0xD5, 0xF9, 0x16, 0xFE, 0x0F, 0x7E, 0xDE, 0xA0,
+ 0xF5, 0x32, 0xFE, 0x20, 0x67, 0x93, 0xCA, 0xE1,
+ 0x8E, 0x4D, 0x72, 0xA3, 0x50, 0x72, 0x14, 0x15,
+ 0x70, 0xE7, 0xAB, 0x49, 0x25, 0x88, 0x0E, 0x01,
+ 0x5C, 0x52, 0x87, 0xE2, 0x27, 0xDC, 0xD4, 0xD1,
+ 0x14, 0x1B, 0x08, 0x9F, 0x42, 0x48, 0x93, 0xA9,
+ 0xD1, 0x2F, 0x2C, 0x69, 0x48, 0x16, 0x59, 0xCF,
+ 0x8B, 0xF6, 0x8B, 0xD9, 0x34, 0xD4, 0xD7, 0xE4,
+ 0xAE, 0x35, 0xFD, 0xDA, 0x73, 0xBE, 0xDC, 0x6B,
+ 0x10, 0x90, 0x75, 0x2D, 0x4C, 0x14, 0x37, 0x8B,
+ 0xC8, 0xC7, 0xDF, 0x6E, 0x6F, 0xED, 0xF3, 0xE3,
+ 0xD3, 0x21, 0x29, 0xCD, 0x06, 0xB6, 0x5B, 0xF4,
+ 0xB9, 0xBD, 0x77, 0xA2, 0xF7, 0x91, 0xF4, 0x95,
+ 0xF0, 0xE0, 0x62, 0x03, 0x46, 0xAE, 0x1B, 0xEB,
+ 0xE2, 0xA9, 0xCF, 0xB9, 0x0E, 0x3B, 0xB9, 0xDA,
+ 0x5C, 0x1B, 0x45, 0x3F, 0xDD, 0xCC, 0xCC, 0xB3,
+ 0xF0, 0xDD, 0x36, 0x26, 0x11, 0x57, 0x97, 0xA7,
+ 0xF6, 0xF4, 0xE1, 0x4F, 0xBB, 0x31, 0xBB, 0x07,
+ 0x4B, 0xA3, 0xB4, 0x83, 0xF9, 0x23, 0xA1, 0xCD,
+ 0x8C, 0x1C, 0x76, 0x92, 0x45, 0xA5, 0xEB, 0x7D,
+ 0xEB, 0x22, 0x88, 0xB1, 0x9F, 0xFB, 0xE9, 0x06,
+ 0x8F, 0x67, 0xA6, 0x8A, 0xB7, 0x0B, 0xCD, 0x8F,
+ 0x34, 0x40, 0x4F, 0x4F, 0xAD, 0xA0, 0xF2, 0xDC,
+ 0x2C, 0x53, 0xE1, 0xCA, 0xA5, 0x7A, 0x03, 0xEF,
+ 0x08, 0x00, 0xCC, 0x52, 0xA6, 0xAB, 0x56, 0xD2,
+ 0xF1, 0xCD, 0xC7, 0xED, 0xBE, 0xCB, 0x78, 0x37,
+ 0x4B, 0x61, 0xA9, 0xD2, 0x3C, 0x8D, 0xCC, 0xFD,
+ 0x21, 0xFD, 0x0F, 0xE4, 0x4E, 0x3D, 0x6F, 0x8F,
+ 0x2A, 0xEC, 0x69, 0xFA, 0x20, 0x50, 0x99, 0x35,
+ 0xA1, 0xCC, 0x3B, 0xFD, 0xD6, 0xAC, 0xE9, 0xBE,
+ 0x14, 0xF1, 0xBC, 0x71, 0x70, 0xFE, 0x13, 0xD1,
+ 0x48, 0xCC, 0xBE, 0x7B, 0xCB, 0xC0, 0x20, 0xD9,
+ 0x28, 0xD7, 0xD4, 0x0F, 0x66, 0x7A, 0x60, 0xAB,
+ 0x20, 0xA9, 0x23, 0x41, 0x03, 0x34, 0xC3, 0x63,
+ 0x91, 0x69, 0x02, 0xD5, 0xBC, 0x41, 0xDA, 0xA8,
+ 0xD1, 0x48, 0xC9, 0x8E, 0x4F, 0xCD, 0x0F, 0x21,
+ 0x5B, 0x4D, 0x5F, 0xF5, 0x1B, 0x2A, 0x44, 0x10,
+ 0x16, 0xA7, 0xFD, 0xC0, 0x55, 0xE1, 0x98, 0xBB,
+ 0x76, 0xB5, 0xAB, 0x39, 0x6B, 0x9B, 0xAB, 0x85,
+ 0x45, 0x4B, 0x9C, 0x64, 0x7D, 0x78, 0x3F, 0x61,
+ 0x22, 0xB1, 0xDE, 0x0E, 0x39, 0x2B, 0x21, 0x26,
+ 0xE2, 0x1D, 0x5A, 0xD7, 0xAC, 0xDF, 0xD4, 0x12,
+ 0x69, 0xD1, 0xE8, 0x9B, 0x1A, 0xCE, 0x6C, 0xA0,
+ 0x3B, 0x23, 0xDC, 0x03, 0x2B, 0x97, 0x16, 0xD0,
+ 0xD0, 0x46, 0x98, 0x36, 0x53, 0xCE, 0x88, 0x6E,
+ 0xCA, 0x2C, 0x15, 0x0E, 0x49, 0xED, 0xBE, 0xE5,
+ 0xBF, 0xBD, 0x7B, 0xC2, 0x21, 0xE1, 0x09, 0xFF,
+ 0x71, 0xA8, 0xBE, 0x8F, 0xB4, 0x1D, 0x25, 0x5C,
+ 0x37, 0xCA, 0x26, 0xD2, 0x1E, 0x63, 0xE1, 0x7F,
+ 0x0D, 0x89, 0x10, 0xEF, 0x78, 0xB0, 0xDB, 0xD0,
+ 0x72, 0x44, 0x60, 0x1D, 0xCF, 0x7C, 0x25, 0x1A,
+ 0xBB, 0xC3, 0x92, 0x53, 0x8E, 0x9F, 0x27, 0xC7,
+ 0xE8, 0x08, 0xFC, 0x5D, 0x50, 0x3E, 0xFC, 0xB0,
+ 0x00, 0xE2, 0x48, 0xB2, 0x4B, 0xF8, 0xF2, 0xE3,
+ 0xD3, 0x8B, 0x71, 0x64, 0xB8, 0xF0, 0x6E, 0x4A,
+ 0x23, 0xA0, 0xA4, 0x88, 0xA4, 0x36, 0x45, 0x6B,
+ 0x5A, 0xE7, 0x57, 0x65, 0xEA, 0xC9, 0xF8, 0xE8,
+ 0x7A, 0x80, 0x22, 0x67, 0x1A, 0x05, 0xF2, 0x78,
+ 0x81, 0x17, 0xCD, 0x87, 0xFB, 0x0D, 0x25, 0x84,
+ 0x49, 0x06, 0x25, 0xCE, 0xFC, 0x38, 0x06, 0x18,
+ 0x2E, 0x1D, 0xE1, 0x33, 0x97, 0xB6, 0x7E, 0xAB,
+};
+
+
+static const struct blockcipher_test_data
+triple_des128cbc_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128cbc,
+ .len = 512
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des128cbc_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1,
+ .digest = {
+ .data = {
+ 0x94, 0x45, 0x7B, 0xDF, 0xFE, 0x80, 0xB9, 0xA6,
+ 0xA0, 0x7A, 0xE8, 0x93, 0x40, 0x7B, 0x85, 0x02,
+ 0x1C, 0xD7, 0xE8, 0x87
+ },
+ .len = 20
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des128cbc_hmac_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+ },
+ .len = 16
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des128cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0x7E, 0xBA, 0xFF, 0x86, 0x8D, 0x65, 0xCD, 0x08,
+ 0x76, 0x34, 0x94, 0xE9, 0x9A, 0xCD, 0xB2, 0xBB,
+ 0xBF, 0x65, 0xF5, 0x42
+ },
+ .len = 20
+ }
+};
+
+static const uint8_t ciphertext512_des192cbc[] = {
+ 0xd0, 0xc9, 0xdc, 0x51, 0x29, 0x97, 0x03, 0x64,
+ 0xcd, 0x22, 0xba, 0x3d, 0x2b, 0xbc, 0x21, 0x37,
+ 0x7b, 0x1e, 0x29, 0x23, 0xeb, 0x51, 0x6e, 0xac,
+ 0xbe, 0x5b, 0xd3, 0x67, 0xe0, 0x3f, 0xc3, 0xb5,
+ 0xe3, 0x04, 0x17, 0x42, 0x2b, 0xaa, 0xdd, 0xd6,
+ 0x0e, 0x69, 0xd0, 0x8f, 0x8a, 0xfc, 0xb4, 0x55,
+ 0x67, 0x06, 0x51, 0xbb, 0x00, 0x57, 0xee, 0x95,
+ 0x28, 0x79, 0x3f, 0xd9, 0x97, 0x2b, 0xb0, 0x02,
+ 0x35, 0x08, 0xce, 0x7a, 0xc3, 0x43, 0x2c, 0x87,
+ 0xaa, 0x97, 0x6a, 0xad, 0xf0, 0x26, 0xea, 0x1d,
+ 0xbb, 0x08, 0xe9, 0x52, 0x11, 0xd3, 0xaf, 0x36,
+ 0x17, 0x14, 0x21, 0xb2, 0xbc, 0x42, 0x51, 0x33,
+ 0x27, 0x8c, 0xd8, 0x45, 0xb9, 0x76, 0xa0, 0x11,
+ 0x24, 0x34, 0xde, 0x4d, 0x13, 0x67, 0x1b, 0xc3,
+ 0x31, 0x12, 0x66, 0x56, 0x59, 0xd2, 0xb1, 0x8f,
+ 0xec, 0x1e, 0xc0, 0x10, 0x7a, 0x86, 0xb1, 0x60,
+ 0xc3, 0x01, 0xd6, 0xa8, 0x55, 0xad, 0x58, 0x63,
+ 0xca, 0x68, 0xa9, 0x33, 0xe3, 0x93, 0x90, 0x7d,
+ 0x8f, 0xca, 0xf8, 0x1c, 0xc2, 0x9e, 0xfb, 0xde,
+ 0x9c, 0xc7, 0xf2, 0x6c, 0xff, 0xcc, 0x39, 0x17,
+ 0x49, 0x33, 0x0d, 0x7c, 0xed, 0x07, 0x99, 0x91,
+ 0x91, 0x6c, 0x5f, 0x3f, 0x02, 0x09, 0xdc, 0x70,
+ 0xf9, 0x3b, 0x8d, 0xaa, 0xf4, 0xbc, 0x0e, 0xec,
+ 0xf2, 0x26, 0xfb, 0xb2, 0x1c, 0x31, 0xae, 0xc6,
+ 0x72, 0xe8, 0x0b, 0x75, 0x05, 0x57, 0x58, 0x98,
+ 0x92, 0x37, 0x27, 0x8e, 0x3b, 0x0c, 0x25, 0xfb,
+ 0xcf, 0x82, 0x02, 0xd5, 0x0b, 0x1f, 0x89, 0x49,
+ 0xcd, 0x0f, 0xa1, 0xa7, 0x08, 0x63, 0x56, 0xa7,
+ 0x1f, 0x80, 0x3a, 0xef, 0x24, 0x89, 0x57, 0x1a,
+ 0x02, 0xdc, 0x2e, 0x51, 0xbd, 0x4a, 0x10, 0x23,
+ 0xfc, 0x02, 0x1a, 0x3f, 0x34, 0xbf, 0x1c, 0x98,
+ 0x1a, 0x40, 0x0a, 0x96, 0x8e, 0x41, 0xd5, 0x09,
+ 0x55, 0x37, 0xe9, 0x25, 0x11, 0x83, 0xf8, 0xf3,
+ 0xd4, 0xb0, 0xdb, 0x16, 0xd7, 0x51, 0x7e, 0x94,
+ 0xf7, 0xb4, 0x26, 0xe0, 0xf4, 0x80, 0x01, 0x65,
+ 0x51, 0xeb, 0xbc, 0xb0, 0x65, 0x8f, 0xdd, 0xb5,
+ 0xf7, 0x00, 0xec, 0x40, 0xab, 0x7d, 0x96, 0xcc,
+ 0x8d, 0xec, 0x89, 0x80, 0x31, 0x39, 0xa2, 0x5c,
+ 0xb0, 0x55, 0x4c, 0xee, 0xdd, 0x15, 0x2b, 0xa9,
+ 0x86, 0x4e, 0x23, 0x14, 0x36, 0xc5, 0x57, 0xf5,
+ 0xe3, 0xe8, 0x89, 0xc9, 0xb7, 0xf8, 0xeb, 0x08,
+ 0xe5, 0x93, 0x12, 0x5c, 0x0f, 0x79, 0xa1, 0x86,
+ 0xe4, 0xc2, 0xeb, 0xa6, 0xa0, 0x50, 0x6a, 0xec,
+ 0xd3, 0xce, 0x50, 0x78, 0x4e, 0x4f, 0x93, 0xd8,
+ 0xdc, 0xb4, 0xec, 0x02, 0xe9, 0xbd, 0x17, 0x99,
+ 0x1e, 0x16, 0x4e, 0xd7, 0xb0, 0x07, 0x02, 0x55,
+ 0x63, 0x24, 0x4f, 0x7b, 0x8f, 0xc5, 0x7a, 0x12,
+ 0x29, 0xff, 0x5d, 0xc1, 0xe7, 0xae, 0x48, 0xc8,
+ 0x57, 0x53, 0xe7, 0xcd, 0x10, 0x6c, 0x19, 0xfc,
+ 0xcc, 0xb9, 0xb1, 0xbe, 0x48, 0x9f, 0x2d, 0x3f,
+ 0x39, 0x2e, 0xdd, 0x71, 0xde, 0x1b, 0x54, 0xee,
+ 0x7d, 0x94, 0x8f, 0x27, 0x23, 0xe9, 0x74, 0x92,
+ 0x14, 0x93, 0x84, 0x65, 0xc9, 0x22, 0x7c, 0xa8,
+ 0x1b, 0x72, 0x73, 0xb1, 0x23, 0xa0, 0x6b, 0xcc,
+ 0xb5, 0x22, 0x06, 0x15, 0xe5, 0x96, 0x03, 0x4a,
+ 0x52, 0x8d, 0x1d, 0xbf, 0x3e, 0x82, 0x45, 0x9c,
+ 0x75, 0x9e, 0xa9, 0x3a, 0x97, 0xb6, 0x5d, 0xc4,
+ 0x75, 0x67, 0xa1, 0xf3, 0x0f, 0x7a, 0xfd, 0x71,
+ 0x58, 0x04, 0xf9, 0xa7, 0xc2, 0x56, 0x74, 0x04,
+ 0x74, 0x68, 0x6d, 0x8a, 0xf6, 0x6c, 0x5d, 0xd8,
+ 0xb5, 0xed, 0x70, 0x23, 0x32, 0x4d, 0x75, 0x92,
+ 0x88, 0x7b, 0x39, 0x37, 0x02, 0x4b, 0xb2, 0x1c,
+ 0x1f, 0x7e, 0x5b, 0x1b, 0x10, 0xfc, 0x17, 0x21,
+ 0x66, 0x62, 0x63, 0xc2, 0xcd, 0x16, 0x96, 0x3e
+};
+
+static const struct blockcipher_test_data
+triple_des192cbc_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192cbc,
+ .len = 512
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des192cbc_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1,
+ .digest = {
+ .data = {
+ 0x53, 0x27, 0xC0, 0xE6, 0xD6, 0x1B, 0xD6, 0x45,
+ 0x94, 0x2D, 0xCE, 0x8B, 0x29, 0xA3, 0x52, 0x14,
+ 0xC1, 0x6B, 0x87, 0x99
+ },
+ .len = 20
+ }
+};
+
+static const struct blockcipher_test_data
+triple_des192cbc_hmac_sha1_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+ 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A,
+ 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0
+ },
+ .len = 24
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des192cbc,
+ .len = 512
+ },
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0xBA, 0xAC, 0x74, 0x19, 0x43, 0xB0, 0x72, 0xB8,
+ 0x08, 0xF5, 0x24, 0xC4, 0x09, 0xBD, 0x48, 0xC1,
+ 0x3C, 0x50, 0x1C, 0xDD
+ },
+ .len = 20
+ }
+};
+static const struct blockcipher_test_data
+triple_des64cbc_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_3DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2
+ },
+ .len = 8
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des,
+ .len = 512
+ },
+};
+
+static const struct blockcipher_test_data
+des_cbc_test_vector = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_DES_CBC,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2
+ },
+ .len = 8
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des,
+ .len = 512
+ },
+};
+
+static const struct blockcipher_test_case des_cipheronly_test_cases[] = {
+ {
+ .test_descr = "DES-CBC Encryption",
+ .test_data = &des_cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "DES-CBC Decryption",
+ .test_data = &des_cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+
+};
+
+/* DES-DOCSIS-BPI test vectors */
+
+static const uint8_t plaintext_des_docsis_bpi_cfb[] = {
+ 0x00, 0x01, 0x02, 0x88, 0xEE, 0x59, 0x7E
+};
+
+static const uint8_t ciphertext_des_docsis_bpi_cfb[] = {
+ 0x17, 0x86, 0xA8, 0x03, 0xA0, 0x85, 0x75
+};
+
+static const uint8_t plaintext_des_docsis_bpi_cbc_cfb[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x91,
+ 0xD2, 0xD1, 0x9F
+};
+
+static const uint8_t ciphertext_des_docsis_bpi_cbc_cfb[] = {
+ 0x0D, 0xDA, 0x5A, 0xCB, 0xD0, 0x5E, 0x55, 0x67,
+ 0x51, 0x47, 0x46, 0x86, 0x8A, 0x71, 0xE5, 0x77,
+ 0xEF, 0xAC, 0x88
+};
+
+/* Multiple of DES block size */
+static const struct blockcipher_test_data des_test_data_1 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2
+ },
+ .len = 8
+ },
+ .iv = {
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des,
+ .len = 512
+ },
+ .ciphertext = {
+ .data = ciphertext512_des,
+ .len = 512
+ },
+};
+
+/* Less than DES block size */
+static const struct blockcipher_test_data des_test_data_2 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 8
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des_docsis_bpi_cfb,
+ .len = 7
+ },
+ .ciphertext = {
+ .data = ciphertext_des_docsis_bpi_cfb,
+ .len = 7
+ }
+};
+
+/* Not multiple of DES block size */
+static const struct blockcipher_test_data des_test_data_3 = {
+ .crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+ .cipher_key = {
+ .data = {
+ 0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+ },
+ .len = 8
+ },
+ .iv = {
+ .data = {
+ 0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = plaintext_des_docsis_bpi_cbc_cfb,
+ .len = 19
+ },
+ .ciphertext = {
+ .data = ciphertext_des_docsis_bpi_cbc_cfb,
+ .len = 19
+ }
+};
+static const struct blockcipher_test_case des_docsis_test_cases[] = {
+ {
+ .test_descr = "DES-DOCSIS-BPI Full Block Encryption",
+ .test_data = &des_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI Runt Block Encryption",
+ .test_data = &des_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI Uneven Encryption",
+ .test_data = &des_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI Full Block Decryption",
+ .test_data = &des_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI Runt Block Decryption",
+ .test_data = &des_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI Uneven Decryption",
+ .test_data = &des_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Full Block Encryption",
+ .test_data = &des_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Runt Block Encryption",
+ .test_data = &des_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Uneven Encryption",
+ .test_data = &des_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Full Block Decryption",
+ .test_data = &des_test_data_1,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Runt Block Decryption",
+ .test_data = &des_test_data_2,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "DES-DOCSIS-BPI OOP Uneven Decryption",
+ .test_data = &des_test_data_3,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ }
+};
+
+static const struct blockcipher_test_case triple_des_chain_test_cases[] = {
+ {
+ .test_descr = "3DES-128-CBC HMAC-SHA1 Encryption Digest",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-128-CBC HMAC-SHA1 Decryption Digest Verify",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-128-CBC SHA1 Encryption Digest",
+ .test_data = &triple_des128cbc_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-128-CBC SHA1 Decryption Digest Verify",
+ .test_data = &triple_des128cbc_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-192-CBC HMAC-SHA1 Encryption Digest",
+ .test_data = &triple_des192cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-192-CBC HMAC-SHA1 Decryption Digest Verify",
+ .test_data = &triple_des192cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-192-CBC SHA1 Encryption Digest",
+ .test_data = &triple_des192cbc_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-192-CBC SHA1 Decryption Digest Verify",
+ .test_data = &triple_des192cbc_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-128-CTR HMAC-SHA1 Encryption Digest",
+ .test_data = &triple_des128ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-128-CTR HMAC-SHA1 Decryption Digest Verify",
+ .test_data = &triple_des128ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-128-CTR SHA1 Encryption Digest",
+ .test_data = &triple_des128ctr_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-128-CTR SHA1 Decryption Digest Verify",
+ .test_data = &triple_des128ctr_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-192-CTR HMAC-SHA1 Encryption Digest",
+ .test_data = &triple_des192ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-192-CTR HMAC-SHA1 Decryption Digest Verify",
+ .test_data = &triple_des192ctr_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-192-CTR SHA1 Encryption Digest",
+ .test_data = &triple_des192ctr_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ },
+ {
+ .test_descr = "3DES-192-CTR SHA1 Decryption Digest Verify",
+ .test_data = &triple_des192ctr_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ },
+ {
+ .test_descr = "3DES-128-CBC HMAC-SHA1 Encryption Digest OOP",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "3DES-128-CBC HMAC-SHA1 Decryption Digest"
+ " Verify OOP",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "3DES-128-CBC HMAC-SHA1 Encryption Digest"
+ " Sessionless",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
+ },
+ {
+ .test_descr =
+ "3DES-128-CBC HMAC-SHA1 Decryption Digest"
+ " Verify Sessionless",
+ .test_data = &triple_des128cbc_hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
+ },
+};
+
+static const struct blockcipher_test_case triple_des_cipheronly_test_cases[] = {
+ {
+ .test_descr = "3DES-64-CBC Encryption",
+ .test_data = &triple_des64cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "3DES-64-CBC Decryption",
+ .test_data = &triple_des64cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "3DES-128-CBC Encryption",
+ .test_data = &triple_des128cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "3DES-128-CBC Decryption",
+ .test_data = &triple_des128cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "3DES-192-CBC Encryption",
+ .test_data = &triple_des192cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "3DES-192-CBC Decryption",
+ .test_data = &triple_des192cbc_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "3DES-128-CTR Encryption",
+ .test_data = &triple_des128ctr_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "3DES-128-CTR Decryption",
+ .test_data = &triple_des128ctr_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ },
+ {
+ .test_descr = "3DES-192-CTR Encryption",
+ .test_data = &triple_des192ctr_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+ },
+ {
+ .test_descr = "3DES-192-CTR Decryption",
+ .test_data = &triple_des192ctr_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+ }
+};
+
+#endif /* TEST_CRYPTODEV_DES_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_dh_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_dh_test_vectors.h
new file mode 100644
index 000000000..fe7510dcd
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_dh_test_vectors.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ */
+
+#ifndef TEST_CRYPTODEV_DH_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_DH_TEST_VECTORS_H_
+
+#include "rte_crypto_asym.h"
+
+#define TEST_DATA_SIZE 4096
+#define TEST_DH_MOD_LEN 1024
+
+
+struct dh_test_param {
+ rte_crypto_param priv_key;
+};
+
+uint8_t dh_priv[] = {
+ 0x46, 0x3c, 0x7b, 0x43, 0xd1, 0xb8, 0xd4, 0x7a,
+ 0x56, 0x28, 0x85, 0x79, 0xcc, 0xd8, 0x90, 0x03,
+ 0x0c, 0x4b, 0xc6, 0xd3, 0x7f, 0xb3, 0x19, 0x84,
+ 0x8a, 0xc6, 0x0d, 0x24, 0x5e, 0xaa, 0x7e, 0x7a,
+ 0x73, 0x88, 0xa6, 0x47, 0x7c, 0x42, 0x78, 0x63,
+ 0x11, 0x12, 0xd3, 0xa0, 0xc5, 0xfe, 0xfd, 0xf2,
+ 0x9e, 0x17, 0x90, 0xe5, 0x6d, 0xcc, 0x20, 0x6f,
+ 0xe8, 0x82, 0x28, 0xbf, 0x5c, 0xe6, 0xd4, 0x86,
+ 0x5c, 0x35, 0x32, 0x97, 0xc2, 0x86, 0x1b, 0xc5,
+ 0x59, 0x1c, 0x0b, 0x1b, 0xec, 0x60, 0x3c, 0x1d,
+ 0x8d, 0x7f, 0xf0, 0xc7, 0x48, 0x3a, 0x51, 0x09,
+ 0xf2, 0x3e, 0x9e, 0x35, 0x74, 0x98, 0x4d, 0xad,
+ 0x39, 0xa7, 0xf2, 0xd2, 0xb4, 0x32, 0xd3, 0xc8,
+ 0xe9, 0x45, 0xbe, 0x56, 0xe7, 0x87, 0xe0, 0xa0,
+ 0x97, 0x6b, 0x5f, 0x99, 0x5e, 0x41, 0x59, 0x33,
+ 0x95, 0x64, 0x0d, 0xe9, 0x58, 0x5b, 0xa6, 0x38
+};
+
+uint8_t dh_p[] = {
+ 0xef, 0xee, 0x8c, 0x8b, 0x3f, 0x85, 0x95, 0xcd,
+ 0x4d, 0x68, 0x5d, 0x4a, 0x5d, 0x1f, 0x2a, 0x2e,
+ 0xdd, 0xcf, 0xef, 0x1b, 0x3b, 0xe9, 0x7b, 0x0c,
+ 0x13, 0xee, 0x76, 0xd5, 0x93, 0xca, 0x8b, 0xc8,
+ 0x0b, 0x97, 0x00, 0xec, 0x1f, 0x34, 0xa2, 0xce,
+ 0x83, 0x8d, 0x80, 0xea, 0xfe, 0x11, 0xed, 0x28,
+ 0xdd, 0x32, 0x22, 0x77, 0x96, 0x4e, 0xc5, 0xed,
+ 0xc8, 0x7a, 0x52, 0x10, 0x22, 0xcc, 0xb2, 0x4d,
+ 0xd3, 0xda, 0x03, 0xf5, 0x1e, 0xa8, 0x79, 0x23,
+ 0x8b, 0xe1, 0x78, 0x47, 0x07, 0x5b, 0x26, 0xbb,
+ 0x53, 0x46, 0x0b, 0x18, 0x5c, 0x07, 0x4e, 0xb6,
+ 0x76, 0xc9, 0xa8, 0xd5, 0x30, 0xa3, 0xbe, 0x8d,
+ 0xae, 0xcd, 0x34, 0x68, 0x62, 0x5f, 0xb9, 0x5c,
+ 0x34, 0x90, 0xf0, 0xda, 0x47, 0x86, 0x36, 0x04,
+ 0x28, 0xbc, 0x7d, 0xae, 0x9d, 0x4e, 0x61, 0x28,
+ 0x70, 0xdb, 0xa6, 0x55, 0x04, 0x46, 0x27, 0xe3
+};
+
+uint8_t dh_g[] = {0x02};
+
+struct dh_test_param dh_test_params = {
+ .priv_key = {
+ .data = dh_priv,
+ .length = sizeof(dh_priv)
+ }
+};
+
+struct rte_crypto_asym_xform dh_xform = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_DH,
+ .dh = {
+ .p = {
+ .data = dh_p,
+ .length = sizeof(dh_p)
+ },
+ .g = {
+ .data = dh_g,
+ .length = sizeof(dh_g)
+ },
+ }
+};
+
+#endif /* TEST_CRYPTODEV_DH_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_dsa_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_dsa_test_vectors.h
new file mode 100644
index 000000000..bbcb0d729
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_dsa_test_vectors.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ */
+
+#ifndef TEST_CRYPTODEV_DSA_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_DSA_TEST_VECTORS_H_
+
+#include "rte_crypto_asym.h"
+
+#define TEST_DATA_SIZE 4096
+
+
+struct dsa_test_param {
+ rte_crypto_param y;
+};
+
+static unsigned char dsa_x[] = {
+ 0xc5, 0x3e, 0xae, 0x6d, 0x45, 0x32, 0x31, 0x64,
+ 0xc7, 0xd0, 0x7a, 0xf5, 0x71, 0x57, 0x03, 0x74,
+ 0x4a, 0x63, 0xfc, 0x3a
+};
+
+uint8_t dsa_y[] = {
+ 0x31, 0x3f, 0xd9, 0xeb, 0xca, 0x91, 0x57, 0x4e,
+ 0x1c, 0x2e, 0xeb, 0xe1, 0x51, 0x7c, 0x57, 0xe0,
+ 0xc2, 0x1b, 0x02, 0x09, 0x87, 0x21, 0x40, 0xc5,
+ 0x32, 0x87, 0x61, 0xbb, 0xb2, 0x45, 0x0b, 0x33,
+ 0xf1, 0xb1, 0x8b, 0x40, 0x9c, 0xe9, 0xab, 0x7c,
+ 0x4c, 0xd8, 0xfd, 0xa3, 0x39, 0x1e, 0x8e, 0x34,
+ 0x86, 0x83, 0x57, 0xc1, 0x99, 0xe1, 0x6a, 0x6b,
+ 0x2e, 0xba, 0x06, 0xd6, 0x74, 0x9d, 0xef, 0x79,
+ 0x1d, 0x79, 0xe9, 0x5d, 0x3a, 0x4d, 0x09, 0xb2,
+ 0x4c, 0x39, 0x2a, 0xd8, 0x9d, 0xbf, 0x10, 0x09,
+ 0x95, 0xae, 0x19, 0xc0, 0x10, 0x62, 0x05, 0x6b,
+ 0xb1, 0x4b, 0xce, 0x00, 0x5e, 0x87, 0x31, 0xef,
+ 0xde, 0x17, 0x5f, 0x95, 0xb9, 0x75, 0x08, 0x9b,
+ 0xdc, 0xda, 0xea, 0x56, 0x2b, 0x32, 0x78, 0x6d,
+ 0x96, 0xf5, 0xa3, 0x1a, 0xed, 0xf7, 0x53, 0x64,
+ 0x00, 0x8a, 0xd4, 0xff, 0xfe, 0xbb, 0x97, 0x0b
+};
+
+static unsigned char dsa_p[] = {
+ 0xa8, 0xf9, 0xcd, 0x20, 0x1e, 0x5e, 0x35, 0xd8,
+ 0x92, 0xf8, 0x5f, 0x80, 0xe4, 0xdb, 0x25, 0x99,
+ 0xa5, 0x67, 0x6a, 0x3b, 0x1d, 0x4f, 0x19, 0x03,
+ 0x30, 0xed, 0x32, 0x56, 0xb2, 0x6d, 0x0e, 0x80,
+ 0xa0, 0xe4, 0x9a, 0x8f, 0xff, 0xaa, 0xad, 0x2a,
+ 0x24, 0xf4, 0x72, 0xd2, 0x57, 0x32, 0x41, 0xd4,
+ 0xd6, 0xd6, 0xc7, 0x48, 0x0c, 0x80, 0xb4, 0xc6,
+ 0x7b, 0xb4, 0x47, 0x9c, 0x15, 0xad, 0xa7, 0xea,
+ 0x84, 0x24, 0xd2, 0x50, 0x2f, 0xa0, 0x14, 0x72,
+ 0xe7, 0x60, 0x24, 0x17, 0x13, 0xda, 0xb0, 0x25,
+ 0xae, 0x1b, 0x02, 0xe1, 0x70, 0x3a, 0x14, 0x35,
+ 0xf6, 0x2d, 0xdf, 0x4e, 0xe4, 0xc1, 0xb6, 0x64,
+ 0x06, 0x6e, 0xb2, 0x2f, 0x2e, 0x3b, 0xf2, 0x8b,
+ 0xb7, 0x0a, 0x2a, 0x76, 0xe4, 0xfd, 0x5e, 0xbe,
+ 0x2d, 0x12, 0x29, 0x68, 0x1b, 0x5b, 0x06, 0x43,
+ 0x9a, 0xc9, 0xc7, 0xe9, 0xd8, 0xbd, 0xe2, 0x83
+};
+
+static unsigned char dsa_q[] = {
+ 0xf8, 0x5f, 0x0f, 0x83, 0xac, 0x4d, 0xf7, 0xea,
+ 0x0c, 0xdf, 0x8f, 0x46, 0x9b, 0xfe, 0xea, 0xea,
+ 0x14, 0x15, 0x64, 0x95
+};
+
+static unsigned char dsa_g[] = {
+ 0x2b, 0x31, 0x52, 0xff, 0x6c, 0x62, 0xf1, 0x46,
+ 0x22, 0xb8, 0xf4, 0x8e, 0x59, 0xf8, 0xaf, 0x46,
+ 0x88, 0x3b, 0x38, 0xe7, 0x9b, 0x8c, 0x74, 0xde,
+ 0xea, 0xe9, 0xdf, 0x13, 0x1f, 0x8b, 0x85, 0x6e,
+ 0x3a, 0xd6, 0xc8, 0x45, 0x5d, 0xab, 0x87, 0xcc,
+ 0x0d, 0xa8, 0xac, 0x97, 0x34, 0x17, 0xce, 0x4f,
+ 0x78, 0x78, 0x55, 0x7d, 0x6c, 0xdf, 0x40, 0xb3,
+ 0x5b, 0x4a, 0x0c, 0xa3, 0xeb, 0x31, 0x0c, 0x6a,
+ 0x95, 0xd6, 0x8c, 0xe2, 0x84, 0xad, 0x4e, 0x25,
+ 0xea, 0x28, 0x59, 0x16, 0x11, 0xee, 0x08, 0xb8,
+ 0x44, 0x4b, 0xd6, 0x4b, 0x25, 0xf3, 0xf7, 0xc5,
+ 0x72, 0x41, 0x0d, 0xdf, 0xb3, 0x9c, 0xc7, 0x28,
+ 0xb9, 0xc9, 0x36, 0xf8, 0x5f, 0x41, 0x91, 0x29,
+ 0x86, 0x99, 0x29, 0xcd, 0xb9, 0x09, 0xa6, 0xa3,
+ 0xa9, 0x9b, 0xbe, 0x08, 0x92, 0x16, 0x36, 0x81,
+ 0x71, 0xbd, 0x0b, 0xa8, 0x1d, 0xe4, 0xfe, 0x33
+};
+
+struct dsa_test_param dsa_test_params = {
+ .y = {
+ .data = dsa_y,
+ .length = sizeof(dsa_y)
+ }
+};
+
+struct rte_crypto_asym_xform dsa_xform = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_DSA,
+ .dsa = {
+ .p = {
+ .data = dsa_p,
+ .length = sizeof(dsa_p)
+ },
+ .q = {
+ .data = dsa_q,
+ .length = sizeof(dsa_q)
+ },
+ .g = {
+ .data = dsa_g,
+ .length = sizeof(dsa_g)
+ },
+ .x = {
+ .data = dsa_x,
+ .length = sizeof(dsa_x)
+ }
+
+ }
+};
+
+#endif /* TEST_CRYPTODEV_DSA_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_ecdsa_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_ecdsa_test_vectors.h
new file mode 100644
index 000000000..55fbda597
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_ecdsa_test_vectors.h
@@ -0,0 +1,505 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#ifndef __TEST_CRYPTODEV_ECDSA_TEST_VECTORS_H__
+#define __TEST_CRYPTODEV_ECDSA_TEST_VECTORS_H__
+
+#include "rte_crypto_asym.h"
+
+/* EC curve id */
+enum curve {
+ SECP192R1,
+ SECP224R1,
+ SECP256R1,
+ SECP384R1,
+ SECP521R1,
+ END_OF_CURVE_LIST
+};
+
+const char *curve[] = {"SECP192R1",
+ "SECP224R1",
+ "SECP256R1",
+ "SECP384R1",
+ "SECP521R1"};
+
+struct crypto_testsuite_ecdsa_params {
+ rte_crypto_param pubkey_qx;
+ rte_crypto_param pubkey_qy;
+ rte_crypto_param scalar;
+ rte_crypto_param digest;
+ rte_crypto_param sign_r;
+ rte_crypto_param sign_s;
+ rte_crypto_param pkey;
+ int curve;
+};
+
+/*
+ * Test vector reference:
+ * https://csrc.nist.gov/CSRC/media/Projects/
+ * Cryptographic-Algorithm-Validation-Program/
+ * documents/components/186-3ecdsasiggencomponenttestvectors.zip
+ */
+
+/* SECP192R1 (P-192 NIST) test vector */
+
+static uint8_t digest_secp192r1[] = {
+ 0x5a, 0xe8, 0x31, 0x7d, 0x34, 0xd1, 0xe5, 0x95,
+ 0xe3, 0xfa, 0x72, 0x47, 0xdb, 0x80, 0xc0, 0xaf,
+ 0x43, 0x20, 0xcc, 0xe1, 0x11, 0x6d, 0xe1, 0x87,
+ 0xf8, 0xf7, 0xe2, 0xe0, 0x99, 0xc0, 0xd8, 0xd0
+};
+
+static uint8_t pkey_secp192r1[] = {
+ 0x24, 0xed, 0xd2, 0x2f, 0x7d, 0xdd, 0x6f, 0xa5,
+ 0xbc, 0x61, 0xfc, 0x06, 0x53, 0x47, 0x9a, 0xa4,
+ 0x08, 0x09, 0xef, 0x86, 0x5c, 0xf2, 0x7a, 0x47
+};
+
+static uint8_t scalar_secp192r1[] = {
+ 0xa5, 0xc8, 0x17, 0xa2, 0x36, 0xa5, 0xf7, 0xfa,
+ 0xa3, 0x29, 0xb8, 0xec, 0xc3, 0xc5, 0x96, 0x68,
+ 0x7c, 0x71, 0xaa, 0xaf, 0x86, 0xc7, 0x70, 0x3e
+};
+
+static uint8_t pubkey_qx_secp192r1[] = {
+ 0x9b, 0xf1, 0x2d, 0x71, 0x74, 0xb7, 0x70, 0x8a,
+ 0x07, 0x6a, 0x38, 0xbc, 0x80, 0xaa, 0x28, 0x66,
+ 0x2f, 0x25, 0x1e, 0x2e, 0xd8, 0xd4, 0x14, 0xdc
+};
+
+static uint8_t pubkey_qy_secp192r1[] = {
+ 0x48, 0x54, 0xc8, 0xd0, 0x7d, 0xfc, 0x08, 0x82,
+ 0x4e, 0x9e, 0x47, 0x1c, 0xa2, 0xfe, 0xdc, 0xfc,
+ 0xff, 0x3d, 0xdc, 0xb0, 0x11, 0x57, 0x34, 0x98
+};
+
+static uint8_t sign_secp192r1_r[] = {
+ 0x35, 0x4a, 0xba, 0xec, 0xf4, 0x36, 0x1f, 0xea,
+ 0x90, 0xc2, 0x9b, 0x91, 0x99, 0x88, 0x2e, 0xdf,
+ 0x85, 0x73, 0xe6, 0x86, 0xa8, 0x13, 0xef, 0xf8
+};
+
+static uint8_t sign_secp192r1_s[] = {
+ 0x80, 0xf5, 0x00, 0x00, 0xac, 0x86, 0x11, 0x1c,
+ 0x9b, 0x30, 0x47, 0x38, 0x5a, 0x15, 0xd7, 0x8e,
+ 0x63, 0x2c, 0x58, 0xb7, 0x94, 0x9e, 0x82, 0xc1
+};
+
+/** ECDSA SECP192R1 elliptic curve param */
+
+struct crypto_testsuite_ecdsa_params ecdsa_param_secp192r1 = {
+ .pubkey_qx = {
+ .data = pubkey_qx_secp192r1,
+ .length = sizeof(pubkey_qx_secp192r1),
+ },
+ .pubkey_qy = {
+ .data = pubkey_qy_secp192r1,
+ .length = sizeof(pubkey_qy_secp192r1),
+ },
+ .scalar = {
+ .data = scalar_secp192r1,
+ .length = sizeof(scalar_secp192r1),
+ },
+ .digest = {
+ .data = digest_secp192r1,
+ .length = sizeof(digest_secp192r1),
+ },
+ .sign_r = {
+ .data = sign_secp192r1_r,
+ .length = sizeof(sign_secp192r1_r),
+ },
+ .sign_s = {
+ .data = sign_secp192r1_s,
+ .length = sizeof(sign_secp192r1_s),
+ },
+ .pkey = {
+ .data = pkey_secp192r1,
+ .length = sizeof(pkey_secp192r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP192R1
+};
+
+/* SECP224R1 (P-224 NIST) test vectors */
+
+static uint8_t digest_secp224r1[] = {
+ 0x00, 0xc6, 0xfc, 0x53, 0xc1, 0x98, 0x6d, 0x19,
+ 0xa8, 0xa8, 0xb5, 0x80, 0xee, 0x55, 0x3d, 0xc1,
+ 0x24, 0x07, 0x45, 0xd7, 0x60, 0x64, 0x7d, 0x1c,
+ 0x0a, 0xdf, 0x44, 0x2c, 0x13, 0x3c, 0x7f, 0x56
+};
+
+static uint8_t pkey_secp224r1[] = {
+ 0x88, 0x8f, 0xc9, 0x92, 0x89, 0x3b, 0xdd, 0x8a,
+ 0xa0, 0x2c, 0x80, 0x76, 0x88, 0x32, 0x60, 0x5d,
+ 0x02, 0x0b, 0x81, 0xae, 0x0b, 0x25, 0x47, 0x41,
+ 0x54, 0xec, 0x89, 0xaa
+};
+
+static uint8_t scalar_secp224r1[] = {
+ 0x06, 0xf7, 0xa5, 0x60, 0x07, 0x82, 0x54, 0x33,
+ 0xc4, 0xc6, 0x11, 0x53, 0xdf, 0x1a, 0x13, 0x5e,
+ 0xee, 0x2f, 0x38, 0xec, 0x68, 0x7b, 0x49, 0x2e,
+ 0xd4, 0x0d, 0x9c, 0x90
+};
+
+static uint8_t pubkey_qx_secp224r1[] = {
+ 0x4c, 0x74, 0x1e, 0x4d, 0x20, 0x10, 0x36, 0x70,
+ 0xb7, 0x16, 0x1a, 0xe7, 0x22, 0x71, 0x08, 0x21,
+ 0x55, 0x83, 0x84, 0x18, 0x08, 0x43, 0x35, 0x33,
+ 0x8a, 0xc3, 0x8f, 0xa4
+};
+
+static uint8_t pubkey_qy_secp224r1[] = {
+ 0xdb, 0x79, 0x19, 0x15, 0x1a, 0xc2, 0x85, 0x87,
+ 0xb7, 0x2b, 0xad, 0x7a, 0xb1, 0x80, 0xec, 0x8e,
+ 0x95, 0xab, 0x9e, 0x2c, 0x8d, 0x81, 0xd9, 0xb9,
+ 0xd7, 0xe2, 0xe3, 0x83
+};
+
+static uint8_t sign_secp224r1_r[] = {
+ 0x09, 0x09, 0xc9, 0xb9, 0xca, 0xe8, 0xd2, 0x79,
+ 0x0e, 0x29, 0xdb, 0x6a, 0xfd, 0xb4, 0x5c, 0x04,
+ 0xf5, 0xb0, 0x72, 0xc4, 0xc2, 0x04, 0x10, 0xc7,
+ 0xdc, 0x9b, 0x67, 0x72
+};
+
+static uint8_t sign_secp224r1_s[] = {
+ 0x29, 0x8f, 0x4f, 0xca, 0xe1, 0xfe, 0x27, 0x1d,
+ 0xa1, 0xe0, 0x34, 0x5d, 0x11, 0xd0, 0x7a, 0x1f,
+ 0xca, 0x43, 0xf5, 0x8a, 0xf4, 0xc1, 0x13, 0xb9,
+ 0x09, 0xee, 0xde, 0xa0
+};
+
+/** ECDSA SECP224R1 elliptic curve param */
+
+struct crypto_testsuite_ecdsa_params ecdsa_param_secp224r1 = {
+ .pubkey_qx = {
+ .data = pubkey_qx_secp224r1,
+ .length = sizeof(pubkey_qx_secp224r1),
+ },
+ .pubkey_qy = {
+ .data = pubkey_qy_secp224r1,
+ .length = sizeof(pubkey_qy_secp224r1),
+ },
+ .scalar = {
+ .data = scalar_secp224r1,
+ .length = sizeof(scalar_secp224r1),
+ },
+ .digest = {
+ .data = digest_secp224r1,
+ .length = sizeof(digest_secp224r1),
+ },
+ .sign_r = {
+ .data = sign_secp224r1_r,
+ .length = sizeof(sign_secp224r1_r),
+ },
+ .sign_s = {
+ .data = sign_secp224r1_s,
+ .length = sizeof(sign_secp224r1_s),
+ },
+ .pkey = {
+ .data = pkey_secp224r1,
+ .length = sizeof(pkey_secp224r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP224R1
+};
+
+/* SECP256R1 (P-256 NIST) test vectors */
+
+static uint8_t digest_secp256r1[] = {
+ 0x44, 0xac, 0xf6, 0xb7, 0xe3, 0x6c, 0x13, 0x42,
+ 0xc2, 0xc5, 0x89, 0x72, 0x04, 0xfe, 0x09, 0x50,
+ 0x4e, 0x1e, 0x2e, 0xfb, 0x1a, 0x90, 0x03, 0x77,
+ 0xdb, 0xc4, 0xe7, 0xa6, 0xa1, 0x33, 0xec, 0x56
+};
+
+static uint8_t pkey_secp256r1[] = {
+ 0x51, 0x9b, 0x42, 0x3d, 0x71, 0x5f, 0x8b, 0x58,
+ 0x1f, 0x4f, 0xa8, 0xee, 0x59, 0xf4, 0x77, 0x1a,
+ 0x5b, 0x44, 0xc8, 0x13, 0x0b, 0x4e, 0x3e, 0xac,
+ 0xca, 0x54, 0xa5, 0x6d, 0xda, 0x72, 0xb4, 0x64
+};
+
+static uint8_t scalar_secp256r1[] = {
+ 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61,
+ 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f,
+ 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33,
+ 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde
+};
+
+static uint8_t pubkey_qx_secp256r1[] = {
+ 0x1c, 0xcb, 0xe9, 0x1c, 0x07, 0x5f, 0xc7, 0xf4,
+ 0xf0, 0x33, 0xbf, 0xa2, 0x48, 0xdb, 0x8f, 0xcc,
+ 0xd3, 0x56, 0x5d, 0xe9, 0x4b, 0xbf, 0xb1, 0x2f,
+ 0x3c, 0x59, 0xff, 0x46, 0xc2, 0x71, 0xbf, 0x83
+};
+
+static uint8_t pubkey_qy_secp256r1[] = {
+ 0xce, 0x40, 0x14, 0xc6, 0x88, 0x11, 0xf9, 0xa2,
+ 0x1a, 0x1f, 0xdb, 0x2c, 0x0e, 0x61, 0x13, 0xe0,
+ 0x6d, 0xb7, 0xca, 0x93, 0xb7, 0x40, 0x4e, 0x78,
+ 0xdc, 0x7c, 0xcd, 0x5c, 0xa8, 0x9a, 0x4c, 0xa9
+};
+
+static uint8_t sign_secp256r1_r[] = {
+ 0xf3, 0xac, 0x80, 0x61, 0xb5, 0x14, 0x79, 0x5b,
+ 0x88, 0x43, 0xe3, 0xd6, 0x62, 0x95, 0x27, 0xed,
+ 0x2a, 0xfd, 0x6b, 0x1f, 0x6a, 0x55, 0x5a, 0x7a,
+ 0xca, 0xbb, 0x5e, 0x6f, 0x79, 0xc8, 0xc2, 0xac
+};
+
+static uint8_t sign_secp256r1_s[] = {
+ 0x8b, 0xf7, 0x78, 0x19, 0xca, 0x05, 0xa6, 0xb2,
+ 0x78, 0x6c, 0x76, 0x26, 0x2b, 0xf7, 0x37, 0x1c,
+ 0xef, 0x97, 0xb2, 0x18, 0xe9, 0x6f, 0x17, 0x5a,
+ 0x3c, 0xcd, 0xda, 0x2a, 0xcc, 0x05, 0x89, 0x03
+};
+
+/** ECDSA SECP256R1 elliptic curve param */
+
+struct crypto_testsuite_ecdsa_params ecdsa_param_secp256r1 = {
+ .pubkey_qx = {
+ .data = pubkey_qx_secp256r1,
+ .length = sizeof(pubkey_qx_secp256r1),
+ },
+ .pubkey_qy = {
+ .data = pubkey_qy_secp256r1,
+ .length = sizeof(pubkey_qy_secp256r1),
+ },
+ .scalar = {
+ .data = scalar_secp256r1,
+ .length = sizeof(scalar_secp256r1),
+ },
+ .digest = {
+ .data = digest_secp256r1,
+ .length = sizeof(digest_secp256r1),
+ },
+ .sign_r = {
+ .data = sign_secp256r1_r,
+ .length = sizeof(sign_secp256r1_r),
+ },
+ .sign_s = {
+ .data = sign_secp256r1_s,
+ .length = sizeof(sign_secp256r1_s),
+ },
+ .pkey = {
+ .data = pkey_secp256r1,
+ .length = sizeof(pkey_secp256r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP256R1
+};
+
+/* SECP384R1 (P-384 NIST) test vectors */
+
+static uint8_t digest_secp384r1[] = {
+ 0xbb, 0xbd, 0x0a, 0x5f, 0x64, 0x5d, 0x3f, 0xda,
+ 0x10, 0xe2, 0x88, 0xd1, 0x72, 0xb2, 0x99, 0x45,
+ 0x5f, 0x9d, 0xff, 0x00, 0xe0, 0xfb, 0xc2, 0x83,
+ 0x3e, 0x18, 0xcd, 0x01, 0x7d, 0x7f, 0x3e, 0xd1
+};
+
+static uint8_t pkey_secp384r1[] = {
+ 0xc6, 0x02, 0xbc, 0x74, 0xa3, 0x45, 0x92, 0xc3,
+ 0x11, 0xa6, 0x56, 0x96, 0x61, 0xe0, 0x83, 0x2c,
+ 0x84, 0xf7, 0x20, 0x72, 0x74, 0x67, 0x6c, 0xc4,
+ 0x2a, 0x89, 0xf0, 0x58, 0x16, 0x26, 0x30, 0x18,
+ 0x4b, 0x52, 0xf0, 0xd9, 0x9b, 0x85, 0x5a, 0x77,
+ 0x83, 0xc9, 0x87, 0x47, 0x6d, 0x7f, 0x9e, 0x6b
+};
+
+static uint8_t scalar_secp384r1[] = {
+ 0xc1, 0x0b, 0x5c, 0x25, 0xc4, 0x68, 0x3d, 0x0b,
+ 0x78, 0x27, 0xd0, 0xd8, 0x86, 0x97, 0xcd, 0xc0,
+ 0x93, 0x24, 0x96, 0xb5, 0x29, 0x9b, 0x79, 0x8c,
+ 0x0d, 0xd1, 0xe7, 0xaf, 0x6c, 0xc7, 0x57, 0xcc,
+ 0xb3, 0x0f, 0xcd, 0x3d, 0x36, 0xea, 0xd4, 0xa8,
+ 0x04, 0x87, 0x7e, 0x24, 0xf3, 0xa3, 0x24, 0x43
+};
+
+static uint8_t pubkey_qx_secp384r1[] = {
+ 0x04, 0x00, 0x19, 0x3b, 0x21, 0xf0, 0x7c, 0xd0,
+ 0x59, 0x82, 0x6e, 0x94, 0x53, 0xd3, 0xe9, 0x6d,
+ 0xd1, 0x45, 0x04, 0x1c, 0x97, 0xd4, 0x9f, 0xf6,
+ 0xb7, 0x04, 0x7f, 0x86, 0xbb, 0x0b, 0x04, 0x39,
+ 0xe9, 0x09, 0x27, 0x4c, 0xb9, 0xc2, 0x82, 0xbf,
+ 0xab, 0x88, 0x67, 0x4c, 0x07, 0x65, 0xbc, 0x75
+};
+
+static uint8_t pubkey_qy_secp384r1[] = {
+ 0xf7, 0x0d, 0x89, 0xc5, 0x2a, 0xcb, 0xc7, 0x04,
+ 0x68, 0xd2, 0xc5, 0xae, 0x75, 0xc7, 0x6d, 0x7f,
+ 0x69, 0xb7, 0x6a, 0xf6, 0x2d, 0xcf, 0x95, 0xe9,
+ 0x9e, 0xba, 0x5d, 0xd1, 0x1a, 0xdf, 0x8f, 0x42,
+ 0xec, 0x9a, 0x42, 0x5b, 0x0c, 0x5e, 0xc9, 0x8e,
+ 0x2f, 0x23, 0x4a, 0x92, 0x6b, 0x82, 0xa1, 0x47
+};
+
+static uint8_t sign_secp384r1_r[] = {
+ 0xb1, 0x1d, 0xb0, 0x0c, 0xda, 0xf5, 0x32, 0x86,
+ 0xd4, 0x48, 0x3f, 0x38, 0xcd, 0x02, 0x78, 0x59,
+ 0x48, 0x47, 0x7e, 0xd7, 0xeb, 0xc2, 0xad, 0x60,
+ 0x90, 0x54, 0x55, 0x1d, 0xa0, 0xab, 0x03, 0x59,
+ 0x97, 0x8c, 0x61, 0x85, 0x17, 0x88, 0xaa, 0x2e,
+ 0xc3, 0x26, 0x79, 0x46, 0xd4, 0x40, 0xe8, 0x78
+};
+
+static uint8_t sign_secp384r1_s[] = {
+ 0x16, 0x00, 0x78, 0x73, 0xc5, 0xb0, 0x60, 0x4c,
+ 0xe6, 0x81, 0x12, 0xa8, 0xfe, 0xe9, 0x73, 0xe8,
+ 0xe2, 0xb6, 0xe3, 0x31, 0x9c, 0x68, 0x3a, 0x76,
+ 0x2f, 0xf5, 0x06, 0x5a, 0x07, 0x65, 0x12, 0xd7,
+ 0xc9, 0x8b, 0x27, 0xe7, 0x4b, 0x78, 0x87, 0x67,
+ 0x10, 0x48, 0xac, 0x02, 0x7d, 0xf8, 0xcb, 0xf2
+};
+
+/** ECDSA SECP384R1 elliptic curve param */
+
+struct crypto_testsuite_ecdsa_params ecdsa_param_secp384r1 = {
+ .pubkey_qx = {
+ .data = pubkey_qx_secp384r1,
+ .length = sizeof(pubkey_qx_secp384r1),
+ },
+ .pubkey_qy = {
+ .data = pubkey_qy_secp384r1,
+ .length = sizeof(pubkey_qy_secp384r1),
+ },
+ .scalar = {
+ .data = scalar_secp384r1,
+ .length = sizeof(scalar_secp384r1),
+ },
+ .digest = {
+ .data = digest_secp384r1,
+ .length = sizeof(digest_secp384r1),
+ },
+ .sign_r = {
+ .data = sign_secp384r1_r,
+ .length = sizeof(sign_secp384r1_r),
+ },
+ .sign_s = {
+ .data = sign_secp384r1_s,
+ .length = sizeof(sign_secp384r1_s),
+ },
+ .pkey = {
+ .data = pkey_secp384r1,
+ .length = sizeof(pkey_secp384r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP384R1
+};
+
+/* SECP521R1 (P-521 NIST) test vectors */
+
+static uint8_t digest_secp521r1[] = {
+ 0x53, 0xe6, 0x53, 0x7c, 0xb6, 0xea, 0x68, 0xae,
+ 0x47, 0xa8, 0x16, 0x11, 0xc2, 0x27, 0x56, 0xd7,
+ 0x70, 0xd7, 0xa3, 0x7e, 0x33, 0x6c, 0x3a, 0xf0,
+ 0xb0, 0x81, 0x4b, 0x04, 0xfa, 0x39, 0x43, 0x4b
+};
+
+static uint8_t pkey_secp521r1[] = {
+ 0x01, 0xe8, 0xc0, 0x59, 0x96, 0xb8, 0x5e, 0x6f,
+ 0x3f, 0x87, 0x57, 0x12, 0xa0, 0x9c, 0x1b, 0x40,
+ 0x67, 0x2b, 0x5e, 0x7a, 0x78, 0xd5, 0x85, 0x2d,
+ 0xe0, 0x15, 0x85, 0xc5, 0xfb, 0x99, 0x0b, 0xf3,
+ 0x81, 0x2c, 0x32, 0x45, 0x53, 0x4a, 0x71, 0x43,
+ 0x89, 0xae, 0x90, 0x14, 0xd6, 0x77, 0xa4, 0x49,
+ 0xef, 0xd6, 0x58, 0x25, 0x4e, 0x61, 0x0d, 0xa8,
+ 0xe6, 0xca, 0xd3, 0x34, 0x14, 0xb9, 0xd3, 0x3e,
+ 0x0d, 0x7a
+};
+
+static uint8_t scalar_secp521r1[] = {
+ 0x00, 0xdc, 0x8d, 0xaa, 0xac, 0xdd, 0xb8, 0xfd,
+ 0x2f, 0xf5, 0xc3, 0x4a, 0x5c, 0xe1, 0x83, 0xa4,
+ 0x22, 0x61, 0xad, 0x3c, 0x64, 0xdb, 0xfc, 0x09,
+ 0x5e, 0x58, 0x92, 0x43, 0x64, 0xdc, 0x47, 0xea,
+ 0x1c, 0x05, 0xe2, 0x59, 0x9a, 0xae, 0x91, 0x7c,
+ 0x2c, 0x95, 0xf4, 0x7d, 0x6b, 0xb3, 0x7d, 0xa0,
+ 0x08, 0xaf, 0x9f, 0x55, 0x73, 0x0d, 0xdb, 0xe4,
+ 0xd8, 0xde, 0xd2, 0x4f, 0x9e, 0x8d, 0xaa, 0x46,
+ 0xdb, 0x6a
+};
+
+static uint8_t pubkey_qx_secp521r1[] = {
+ 0x00, 0x7d, 0x04, 0x2c, 0xa1, 0x94, 0x08, 0x52,
+ 0x4e, 0x68, 0xb9, 0x81, 0xf1, 0x41, 0x93, 0x51,
+ 0xe3, 0xb8, 0x47, 0x36, 0xc7, 0x7f, 0xe5, 0x8f,
+ 0xee, 0x7d, 0x11, 0x31, 0x7d, 0xf2, 0xe8, 0x50,
+ 0xd9, 0x60, 0xc7, 0xdd, 0x10, 0xd1, 0x0b, 0xa7,
+ 0x14, 0xc8, 0xa6, 0x09, 0xd1, 0x63, 0x50, 0x2b,
+ 0x79, 0xd6, 0x82, 0xe8, 0xbb, 0xec, 0xd4, 0xf5,
+ 0x25, 0x91, 0xd2, 0x74, 0x85, 0x33, 0xe4, 0x5a,
+ 0x86, 0x7a
+};
+
+static uint8_t pubkey_qy_secp521r1[] = {
+ 0x01, 0x97, 0xac, 0x64, 0x16, 0x11, 0x1c, 0xcf,
+ 0x98, 0x7d, 0x29, 0x04, 0x59, 0xeb, 0xc8, 0xad,
+ 0x9e, 0xc5, 0x6e, 0x49, 0x05, 0x9c, 0x99, 0x21,
+ 0x55, 0x53, 0x9a, 0x36, 0xa6, 0x26, 0x63, 0x1f,
+ 0x4a, 0x2d, 0x89, 0x16, 0x4b, 0x98, 0x51, 0x54,
+ 0xf2, 0xdd, 0xdc, 0x02, 0x81, 0xee, 0x5b, 0x51,
+ 0x78, 0x27, 0x1f, 0x3a, 0x76, 0xa0, 0x91, 0x4c,
+ 0x3f, 0xcd, 0x1f, 0x97, 0xbe, 0x8e, 0x83, 0x76,
+ 0xef, 0xb3
+};
+
+static uint8_t sign_secp521r1_r[] = {
+ 0x00, 0x9d, 0xd1, 0xf2, 0xa7, 0x16, 0x84, 0x3e,
+ 0xed, 0xec, 0x7a, 0x66, 0x45, 0xac, 0x83, 0x4d,
+ 0x43, 0x36, 0xe7, 0xb1, 0x8e, 0x35, 0x70, 0x1f,
+ 0x06, 0xca, 0xe9, 0xd6, 0xb2, 0x90, 0xd4, 0x14,
+ 0x91, 0x42, 0x47, 0x35, 0xf3, 0xb5, 0x7e, 0x82,
+ 0x9a, 0xd5, 0xde, 0x05, 0x5e, 0xae, 0xef, 0x17,
+ 0x78, 0xf0, 0x51, 0xc1, 0xee, 0x15, 0x2b, 0xf2,
+ 0x13, 0x1a, 0x08, 0x1e, 0x53, 0xdf, 0x2a, 0x56,
+ 0x7a, 0x8a
+};
+
+static uint8_t sign_secp521r1_s[] = {
+ 0x00, 0x21, 0x48, 0xe8, 0x42, 0x8d, 0x70, 0xa7,
+ 0x2b, 0xc9, 0xfa, 0x98, 0x6c, 0x38, 0xc2, 0xc9,
+ 0x7d, 0xed, 0xa0, 0x42, 0x0f, 0x22, 0x2f, 0x9d,
+ 0xc9, 0x9d, 0x32, 0xc0, 0xac, 0xba, 0x69, 0x9d,
+ 0xc7, 0xba, 0x0a, 0x2b, 0x79, 0xce, 0x59, 0x99,
+ 0xff, 0x61, 0xbd, 0x0b, 0x23, 0x3c, 0x74, 0x4a,
+ 0x89, 0x3b, 0xc1, 0x05, 0xbc, 0xa5, 0xc2, 0x35,
+ 0x42, 0x3e, 0x53, 0x16, 0x12, 0xda, 0x65, 0xd7,
+ 0x2e, 0x62
+};
+
+/** ECDSA SECP521R1 elliptic curve param */
+
+struct crypto_testsuite_ecdsa_params ecdsa_param_secp521r1 = {
+ .pubkey_qx = {
+ .data = pubkey_qx_secp521r1,
+ .length = sizeof(pubkey_qx_secp521r1),
+ },
+ .pubkey_qy = {
+ .data = pubkey_qy_secp521r1,
+ .length = sizeof(pubkey_qy_secp521r1),
+ },
+ .scalar = {
+ .data = scalar_secp521r1,
+ .length = sizeof(scalar_secp521r1),
+ },
+ .digest = {
+ .data = digest_secp521r1,
+ .length = sizeof(digest_secp521r1),
+ },
+ .sign_r = {
+ .data = sign_secp521r1_r,
+ .length = sizeof(sign_secp521r1_r),
+ },
+ .sign_s = {
+ .data = sign_secp521r1_s,
+ .length = sizeof(sign_secp521r1_s),
+ },
+ .pkey = {
+ .data = pkey_secp521r1,
+ .length = sizeof(pkey_secp521r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP521R1
+};
+
+#endif /* __TEST_CRYPTODEV_ECDSA_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_ecpm_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_ecpm_test_vectors.h
new file mode 100644
index 000000000..ade106c8b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_ecpm_test_vectors.h
@@ -0,0 +1,353 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) 2020 Marvell International Ltd.
+ */
+
+#ifndef __TEST_CRYPTODEV_ECPM_TEST_VECTORS_H__
+#define __TEST_CRYPTODEV_ECPM_TEST_VECTORS_H__
+
+#include "rte_crypto_asym.h"
+
+struct crypto_testsuite_ecpm_params {
+ rte_crypto_param gen_x;
+ rte_crypto_param gen_y;
+ rte_crypto_param privkey;
+ rte_crypto_param pubkey_x;
+ rte_crypto_param pubkey_y;
+ int curve;
+};
+
+/* SECP192R1 (P-192 NIST) test vectors */
+
+static uint8_t gen_x_secp192r1[] = {
+ 0x18, 0x8d, 0xa8, 0x0e, 0xb0, 0x30, 0x90, 0xf6,
+ 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00,
+ 0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12
+};
+
+static uint8_t gen_y_secp192r1[] = {
+ 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78,
+ 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, 0xcd, 0xd5,
+ 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11
+};
+
+static uint8_t privkey_secp192r1[] = {
+ 0x24, 0xed, 0xd2, 0x2f, 0x7d, 0xdd, 0x6f, 0xa5,
+ 0xbc, 0x61, 0xfc, 0x06, 0x53, 0x47, 0x9a, 0xa4,
+ 0x08, 0x09, 0xef, 0x86, 0x5c, 0xf2, 0x7a, 0x47
+};
+static uint8_t pubkey_x_secp192r1[] = {
+ 0x9b, 0xf1, 0x2d, 0x71, 0x74, 0xb7, 0x70, 0x8a,
+ 0x07, 0x6a, 0x38, 0xbc, 0x80, 0xaa, 0x28, 0x66,
+ 0x2f, 0x25, 0x1e, 0x2e, 0xd8, 0xd4, 0x14, 0xdc
+};
+
+static uint8_t pubkey_y_secp192r1[] = {
+ 0x48, 0x54, 0xc8, 0xd0, 0x7d, 0xfc, 0x08, 0x82,
+ 0x4e, 0x9e, 0x47, 0x1c, 0xa2, 0xfe, 0xdc, 0xfc,
+ 0xff, 0x3d, 0xdc, 0xb0, 0x11, 0x57, 0x34, 0x98
+};
+
+struct crypto_testsuite_ecpm_params ecpm_param_secp192r1 = {
+ .gen_x = {
+ .data = gen_x_secp192r1,
+ .length = sizeof(gen_x_secp192r1),
+ },
+ .gen_y = {
+ .data = gen_y_secp192r1,
+ .length = sizeof(gen_y_secp192r1),
+ },
+ .privkey = {
+ .data = privkey_secp192r1,
+ .length = sizeof(privkey_secp192r1),
+ },
+ .pubkey_x = {
+ .data = pubkey_x_secp192r1,
+ .length = sizeof(pubkey_x_secp192r1),
+ },
+ .pubkey_y = {
+ .data = pubkey_y_secp192r1,
+ .length = sizeof(pubkey_y_secp192r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP192R1
+};
+
+/* SECP224R1 (P-224 NIST) test vectors */
+
+static uint8_t gen_x_secp224r1[] = {
+ 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f,
+ 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
+ 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+ 0x11, 0x5c, 0x1d, 0x21
+};
+
+static uint8_t gen_y_secp224r1[] = {
+ 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
+ 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0,
+ 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
+ 0x85, 0x00, 0x7e, 0x34
+};
+
+static uint8_t privkey_secp224r1[] = {
+ 0x88, 0x8f, 0xc9, 0x92, 0x89, 0x3b, 0xdd, 0x8a,
+ 0xa0, 0x2c, 0x80, 0x76, 0x88, 0x32, 0x60, 0x5d,
+ 0x02, 0x0b, 0x81, 0xae, 0x0b, 0x25, 0x47, 0x41,
+ 0x54, 0xec, 0x89, 0xaa
+};
+
+static uint8_t pubkey_x_secp224r1[] = {
+ 0x4c, 0x74, 0x1e, 0x4d, 0x20, 0x10, 0x36, 0x70,
+ 0xb7, 0x16, 0x1a, 0xe7, 0x22, 0x71, 0x08, 0x21,
+ 0x55, 0x83, 0x84, 0x18, 0x08, 0x43, 0x35, 0x33,
+ 0x8a, 0xc3, 0x8f, 0xa4
+};
+
+static uint8_t pubkey_y_secp224r1[] = {
+ 0xdb, 0x79, 0x19, 0x15, 0x1a, 0xc2, 0x85, 0x87,
+ 0xb7, 0x2b, 0xad, 0x7a, 0xb1, 0x80, 0xec, 0x8e,
+ 0x95, 0xab, 0x9e, 0x2c, 0x8d, 0x81, 0xd9, 0xb9,
+ 0xd7, 0xe2, 0xe3, 0x83
+};
+
+struct crypto_testsuite_ecpm_params ecpm_param_secp224r1 = {
+ .gen_x = {
+ .data = gen_x_secp224r1,
+ .length = sizeof(gen_x_secp224r1),
+ },
+ .gen_y = {
+ .data = gen_y_secp224r1,
+ .length = sizeof(gen_y_secp224r1),
+ },
+ .privkey = {
+ .data = privkey_secp224r1,
+ .length = sizeof(privkey_secp224r1),
+ },
+ .pubkey_x = {
+ .data = pubkey_x_secp224r1,
+ .length = sizeof(pubkey_x_secp224r1),
+ },
+ .pubkey_y = {
+ .data = pubkey_y_secp224r1,
+ .length = sizeof(pubkey_y_secp224r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP224R1
+};
+
+/* SECP256R1 (P-256 NIST) test vectors */
+
+static uint8_t gen_x_secp256r1[] = {
+ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47,
+ 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
+ 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
+ 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96
+};
+
+static uint8_t gen_y_secp256r1[] = {
+ 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b,
+ 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
+ 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+ 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
+};
+
+static uint8_t pubkey_x_secp256r1[] = {
+ 0x06, 0x27, 0x5d, 0x38, 0x7b, 0x8f, 0xcd, 0x29,
+ 0x12, 0x02, 0xa5, 0xad, 0x72, 0x35, 0x55, 0xd4,
+ 0xe1, 0xca, 0xd6, 0x32, 0x91, 0xe7, 0x8c, 0xb7,
+ 0xf9, 0x85, 0xfe, 0xb5, 0xca, 0x61, 0xfd, 0xa7,
+};
+
+static uint8_t pubkey_y_secp256r1[] = {
+ 0x6d, 0x28, 0x17, 0x9c, 0x88, 0x2a, 0x06, 0x8c,
+ 0x85, 0x52, 0x44, 0xc1, 0x2f, 0xf6, 0x45, 0x80,
+ 0x63, 0x1c, 0x52, 0xe4, 0xa5, 0xf8, 0x21, 0x43,
+ 0xec, 0xeb, 0xe2, 0xbb, 0x39, 0xff, 0x1f, 0xd8
+};
+
+static uint8_t privkey_secp256r1[] = {
+ 0x36, 0xf7, 0xe3, 0x07, 0x84, 0xfa, 0xb5, 0x8d,
+ 0x8d, 0x1d, 0x00, 0x21, 0x8b, 0x59, 0xd1, 0x70,
+ 0x14, 0x94, 0x86, 0x69, 0xec, 0xd3, 0x99, 0xc8,
+ 0x7a, 0xf0, 0x2d, 0x05, 0xbf, 0x16, 0xed, 0x36
+};
+
+struct crypto_testsuite_ecpm_params ecpm_param_secp256r1 = {
+ .gen_x = {
+ .data = gen_x_secp256r1,
+ .length = sizeof(gen_x_secp256r1),
+ },
+ .gen_y = {
+ .data = gen_y_secp256r1,
+ .length = sizeof(gen_y_secp256r1),
+ },
+ .privkey = {
+ .data = privkey_secp256r1,
+ .length = sizeof(privkey_secp256r1),
+ },
+ .pubkey_x = {
+ .data = pubkey_x_secp256r1,
+ .length = sizeof(pubkey_x_secp256r1),
+ },
+ .pubkey_y = {
+ .data = pubkey_y_secp256r1,
+ .length = sizeof(pubkey_y_secp256r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP256R1
+};
+
+/* SECP384R1 (P-384 NIST) test vectors */
+
+static uint8_t gen_x_secp384r1[] = {
+ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37,
+ 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74,
+ 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+ 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38,
+ 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C,
+ 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7
+};
+
+static uint8_t gen_y_secp384r1[] = {
+ 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F,
+ 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29,
+ 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
+ 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0,
+ 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D,
+ 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F
+};
+
+static uint8_t privkey_secp384r1[] = {
+ 0xc6, 0x02, 0xbc, 0x74, 0xa3, 0x45, 0x92, 0xc3,
+ 0x11, 0xa6, 0x56, 0x96, 0x61, 0xe0, 0x83, 0x2c,
+ 0x84, 0xf7, 0x20, 0x72, 0x74, 0x67, 0x6c, 0xc4,
+ 0x2a, 0x89, 0xf0, 0x58, 0x16, 0x26, 0x30, 0x18,
+ 0x4b, 0x52, 0xf0, 0xd9, 0x9b, 0x85, 0x5a, 0x77,
+ 0x83, 0xc9, 0x87, 0x47, 0x6d, 0x7f, 0x9e, 0x6b
+};
+
+static uint8_t pubkey_x_secp384r1[] = {
+ 0x04, 0x00, 0x19, 0x3b, 0x21, 0xf0, 0x7c, 0xd0,
+ 0x59, 0x82, 0x6e, 0x94, 0x53, 0xd3, 0xe9, 0x6d,
+ 0xd1, 0x45, 0x04, 0x1c, 0x97, 0xd4, 0x9f, 0xf6,
+ 0xb7, 0x04, 0x7f, 0x86, 0xbb, 0x0b, 0x04, 0x39,
+ 0xe9, 0x09, 0x27, 0x4c, 0xb9, 0xc2, 0x82, 0xbf,
+ 0xab, 0x88, 0x67, 0x4c, 0x07, 0x65, 0xbc, 0x75
+};
+
+static uint8_t pubkey_y_secp384r1[] = {
+ 0xf7, 0x0d, 0x89, 0xc5, 0x2a, 0xcb, 0xc7, 0x04,
+ 0x68, 0xd2, 0xc5, 0xae, 0x75, 0xc7, 0x6d, 0x7f,
+ 0x69, 0xb7, 0x6a, 0xf6, 0x2d, 0xcf, 0x95, 0xe9,
+ 0x9e, 0xba, 0x5d, 0xd1, 0x1a, 0xdf, 0x8f, 0x42,
+ 0xec, 0x9a, 0x42, 0x5b, 0x0c, 0x5e, 0xc9, 0x8e,
+ 0x2f, 0x23, 0x4a, 0x92, 0x6b, 0x82, 0xa1, 0x47
+};
+
+struct crypto_testsuite_ecpm_params ecpm_param_secp384r1 = {
+ .gen_x = {
+ .data = gen_x_secp384r1,
+ .length = sizeof(gen_x_secp384r1),
+ },
+ .gen_y = {
+ .data = gen_y_secp384r1,
+ .length = sizeof(gen_y_secp384r1),
+ },
+ .privkey = {
+ .data = privkey_secp384r1,
+ .length = sizeof(privkey_secp384r1),
+ },
+ .pubkey_x = {
+ .data = pubkey_x_secp384r1,
+ .length = sizeof(pubkey_x_secp384r1),
+ },
+ .pubkey_y = {
+ .data = pubkey_y_secp384r1,
+ .length = sizeof(pubkey_y_secp384r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP384R1
+};
+
+/* SECP521R1 (P-521 NIST) test vectors */
+
+static uint8_t gen_x_secp521r1[] = {
+ 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04,
+ 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
+ 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
+ 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
+ 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
+ 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
+ 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a,
+ 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
+ 0xbd, 0x66
+};
+
+static uint8_t gen_y_secp521r1[] = {
+ 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b,
+ 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
+ 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+ 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
+ 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
+ 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+ 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72,
+ 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
+ 0x66, 0x50
+};
+
+static uint8_t privkey_secp521r1[] = {
+ 0x01, 0xe8, 0xc0, 0x59, 0x96, 0xb8, 0x5e, 0x6f,
+ 0x3f, 0x87, 0x57, 0x12, 0xa0, 0x9c, 0x1b, 0x40,
+ 0x67, 0x2b, 0x5e, 0x7a, 0x78, 0xd5, 0x85, 0x2d,
+ 0xe0, 0x15, 0x85, 0xc5, 0xfb, 0x99, 0x0b, 0xf3,
+ 0x81, 0x2c, 0x32, 0x45, 0x53, 0x4a, 0x71, 0x43,
+ 0x89, 0xae, 0x90, 0x14, 0xd6, 0x77, 0xa4, 0x49,
+ 0xef, 0xd6, 0x58, 0x25, 0x4e, 0x61, 0x0d, 0xa8,
+ 0xe6, 0xca, 0xd3, 0x34, 0x14, 0xb9, 0xd3, 0x3e,
+ 0x0d, 0x7a
+};
+
+static uint8_t pubkey_x_secp521r1[] = {
+ 0x00, 0x7d, 0x04, 0x2c, 0xa1, 0x94, 0x08, 0x52,
+ 0x4e, 0x68, 0xb9, 0x81, 0xf1, 0x41, 0x93, 0x51,
+ 0xe3, 0xb8, 0x47, 0x36, 0xc7, 0x7f, 0xe5, 0x8f,
+ 0xee, 0x7d, 0x11, 0x31, 0x7d, 0xf2, 0xe8, 0x50,
+ 0xd9, 0x60, 0xc7, 0xdd, 0x10, 0xd1, 0x0b, 0xa7,
+ 0x14, 0xc8, 0xa6, 0x09, 0xd1, 0x63, 0x50, 0x2b,
+ 0x79, 0xd6, 0x82, 0xe8, 0xbb, 0xec, 0xd4, 0xf5,
+ 0x25, 0x91, 0xd2, 0x74, 0x85, 0x33, 0xe4, 0x5a,
+ 0x86, 0x7a
+};
+
+static uint8_t pubkey_y_secp521r1[] = {
+ 0x01, 0x97, 0xac, 0x64, 0x16, 0x11, 0x1c, 0xcf,
+ 0x98, 0x7d, 0x29, 0x04, 0x59, 0xeb, 0xc8, 0xad,
+ 0x9e, 0xc5, 0x6e, 0x49, 0x05, 0x9c, 0x99, 0x21,
+ 0x55, 0x53, 0x9a, 0x36, 0xa6, 0x26, 0x63, 0x1f,
+ 0x4a, 0x2d, 0x89, 0x16, 0x4b, 0x98, 0x51, 0x54,
+ 0xf2, 0xdd, 0xdc, 0x02, 0x81, 0xee, 0x5b, 0x51,
+ 0x78, 0x27, 0x1f, 0x3a, 0x76, 0xa0, 0x91, 0x4c,
+ 0x3f, 0xcd, 0x1f, 0x97, 0xbe, 0x8e, 0x83, 0x76,
+ 0xef, 0xb3
+};
+
+struct crypto_testsuite_ecpm_params ecpm_param_secp521r1 = {
+ .gen_x = {
+ .data = gen_x_secp521r1,
+ .length = sizeof(gen_x_secp521r1),
+ },
+ .gen_y = {
+ .data = gen_y_secp521r1,
+ .length = sizeof(gen_y_secp521r1),
+ },
+ .privkey = {
+ .data = privkey_secp521r1,
+ .length = sizeof(privkey_secp521r1),
+ },
+ .pubkey_x = {
+ .data = pubkey_x_secp521r1,
+ .length = sizeof(pubkey_x_secp521r1),
+ },
+ .pubkey_y = {
+ .data = pubkey_y_secp521r1,
+ .length = sizeof(pubkey_y_secp521r1),
+ },
+ .curve = RTE_CRYPTO_EC_GROUP_SECP521R1
+};
+
+#endif /* __TEST_CRYPTODEV_ECPM_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_hash_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_hash_test_vectors.h
new file mode 100644
index 000000000..d11d7cee7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_hash_test_vectors.h
@@ -0,0 +1,582 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_HASH_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_HASH_TEST_VECTORS_H_
+
+#ifdef RTE_LIBRTE_PMD_AESNI_MB
+#include <intel-ipsec-mb.h>
+#endif
+
+static const uint8_t plaintext_hash[] = {
+ "What a lousy earth! He wondered how many people "
+ "were destitute that same night even in his own "
+ "prosperous country, how many homes were "
+ "shanties, how many husbands were drunk and "
+ "wives socked, and how many children were "
+ "bullied, abused, or abandoned. How many "
+ "families hungered for food they could not "
+ "afford to buy? How many hearts were broken? How "
+ "many suicides would take place that same night, "
+ "how many people would go insane? How many "
+ "cockroaches and landlords would triumph? How "
+ "many winners were losers, successes failures, "
+ "and rich men poor men? How many wise guys were "
+ "stupid? How many happy endings were unhappy "
+ "endings? How many honest men were liars, brave "
+ "men cowards, loyal men traitors, how many "
+ "sainted men were corrupt, how many people in "
+ "positions of trust had sold their souls to "
+ "bodyguards, how many had never had souls? How "
+ "many straight-and-narrow paths were crooked "
+ "paths? How many best families were worst "
+ "families and how many good people were bad "
+ "people? When you added them all up and then "
+ "subtracted, you might be left with only the "
+ "children, and perhaps with Albert Einstein and "
+ "an old violinist or sculptor somewhere."
+};
+
+static const struct blockcipher_test_data
+md5_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_MD5,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0xB3, 0xE6, 0xBB, 0x50, 0x41, 0x35, 0x3C, 0x6B,
+ 0x7A, 0xFF, 0xD2, 0x64, 0xAF, 0xD5, 0x1C, 0xB2
+ },
+ .len = 16
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_md5_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0x50, 0xE8, 0xDE, 0xC5, 0xC1, 0x76, 0xAC, 0xAE,
+ 0x15, 0x4A, 0xF1, 0x7F, 0x7E, 0x04, 0x42, 0x9B
+ },
+ .len = 16,
+ .truncated_len = 12
+ }
+};
+
+static const struct blockcipher_test_data
+sha1_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0xA2, 0x8D, 0x40, 0x78, 0xDD, 0x9F, 0xBB, 0xD5,
+ 0x35, 0x62, 0xFB, 0xFA, 0x93, 0xFD, 0x7D, 0x70,
+ 0xA6, 0x7D, 0x45, 0xCA
+ },
+ .len = 20,
+ .truncated_len = 20
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_sha1_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD
+ },
+ .len = 20
+ },
+ .digest = {
+ .data = {
+ 0xC4, 0xB7, 0x0E, 0x6B, 0xDE, 0xD1, 0xE7, 0x77,
+ 0x7E, 0x2E, 0x8F, 0xFC, 0x48, 0x39, 0x46, 0x17,
+ 0x3F, 0x91, 0x64, 0x59
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+static const struct blockcipher_test_data
+sha224_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA224,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0x91, 0xE7, 0xCD, 0x75, 0x14, 0x9C, 0xA9, 0xE9,
+ 0x2E, 0x46, 0x12, 0x20, 0x22, 0xF9, 0x68, 0x28,
+ 0x39, 0x26, 0xDF, 0xB5, 0x78, 0x62, 0xB2, 0x6E,
+ 0x5E, 0x8F, 0x25, 0x84
+ },
+ .len = 28,
+ .truncated_len = 28
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_sha224_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD, 0x26, 0xEB, 0xAB, 0x92,
+ 0xFB, 0xBF, 0xB0, 0x8C
+ },
+ .len = 28
+ },
+ .digest = {
+ .data = {
+ 0x70, 0x0F, 0x04, 0x4D, 0x22, 0x02, 0x7D, 0x31,
+ 0x36, 0xDA, 0x77, 0x19, 0xB9, 0x66, 0x37, 0x7B,
+ 0xF1, 0x8A, 0x63, 0xBB, 0x5D, 0x1D, 0xE3, 0x9F,
+ 0x92, 0xF6, 0xAA, 0x19
+ },
+ .len = 28,
+ .truncated_len = 14
+ }
+};
+
+static const struct blockcipher_test_data
+sha256_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA256,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0x7F, 0xF1, 0x0C, 0xF5, 0x90, 0x97, 0x19, 0x0F,
+ 0x00, 0xE4, 0x83, 0x01, 0xCA, 0x59, 0x00, 0x2E,
+ 0x1F, 0xC7, 0x84, 0xEE, 0x76, 0xA6, 0x39, 0x15,
+ 0x76, 0x2F, 0x87, 0xF9, 0x01, 0x06, 0xF3, 0xB7
+ },
+ .len = 32,
+ .truncated_len = 32
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_sha256_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD, 0x26, 0xEB, 0xAB, 0x92,
+ 0xFB, 0xBF, 0xB0, 0x8C, 0x29, 0x87, 0x90, 0xAC
+ },
+ .len = 32
+ },
+ .digest = {
+ .data = {
+ 0xAF, 0x8F, 0x70, 0x1B, 0x4B, 0xAF, 0x34, 0xCB,
+ 0x02, 0x24, 0x48, 0x45, 0x83, 0x52, 0x8F, 0x22,
+ 0x06, 0x4D, 0x64, 0x09, 0x0A, 0xCC, 0x02, 0x77,
+ 0x71, 0x83, 0x48, 0x71, 0x07, 0x02, 0x25, 0x17
+ },
+ .len = 32,
+ .truncated_len = 16
+ }
+};
+
+static const struct blockcipher_test_data
+sha384_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA384,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0x1D, 0xE7, 0x3F, 0x55, 0x86, 0xFE, 0x48, 0x9F,
+ 0xAC, 0xC6, 0x85, 0x32, 0xFA, 0x8E, 0xA6, 0x77,
+ 0x25, 0x84, 0xA5, 0x98, 0x8D, 0x0B, 0x80, 0xF4,
+ 0xEB, 0x2C, 0xFB, 0x6C, 0xEA, 0x7B, 0xFD, 0xD5,
+ 0xAD, 0x41, 0xAB, 0x15, 0xB0, 0x03, 0x15, 0xEC,
+ 0x9E, 0x3D, 0xED, 0xCB, 0x80, 0x7B, 0xF4, 0xB6
+ },
+ .len = 48,
+ .truncated_len = 48
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_sha384_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD, 0x26, 0xEB, 0xAB, 0x92,
+ 0xFB, 0xBF, 0xB0, 0x8C, 0x29, 0x87, 0x90, 0xAC,
+ 0x39, 0x8B, 0x5C, 0x49, 0x68, 0x1E, 0x3A, 0x05,
+ 0xCC, 0x68, 0x5C, 0x76, 0xCB, 0x3C, 0x71, 0x89
+ },
+ .len = 48
+ },
+ .digest = {
+ .data = {
+ 0xE2, 0x83, 0x18, 0x55, 0xB5, 0x8D, 0x94, 0x9B,
+ 0x01, 0xB6, 0xE2, 0x57, 0x7A, 0x62, 0xF5, 0xF4,
+ 0xAB, 0x39, 0xF3, 0x3C, 0x28, 0xA0, 0x0F, 0xCC,
+ 0xEE, 0x1C, 0xF1, 0xF8, 0x69, 0xF1, 0x24, 0x3B,
+ 0x10, 0x90, 0x0A, 0xE3, 0xF0, 0x59, 0xDD, 0xC0,
+ 0x6F, 0xE6, 0x8C, 0x84, 0xD5, 0x03, 0xF8, 0x9E
+ },
+ .len = 48,
+ .truncated_len = 24
+ }
+};
+
+static const struct blockcipher_test_data
+sha512_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA512,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .digest = {
+ .data = {
+ 0xB9, 0xBA, 0x28, 0x48, 0x3C, 0xC2, 0xD3, 0x65,
+ 0x4A, 0xD6, 0x00, 0x1D, 0xCE, 0x61, 0x64, 0x54,
+ 0x45, 0x8C, 0x64, 0x0E, 0xED, 0x0E, 0xD8, 0x1C,
+ 0x72, 0xCE, 0xD2, 0x44, 0x91, 0xC8, 0xEB, 0xC7,
+ 0x99, 0xC5, 0xCA, 0x89, 0x72, 0x64, 0x96, 0x41,
+ 0xC8, 0xEA, 0xB2, 0x4E, 0xD1, 0x21, 0x13, 0x49,
+ 0x64, 0x4E, 0x15, 0x68, 0x12, 0x67, 0x26, 0x0F,
+ 0x2C, 0x3C, 0x83, 0x25, 0x27, 0x86, 0xF0, 0xDB
+ },
+ .len = 64,
+ .truncated_len = 64
+ }
+};
+
+static const struct blockcipher_test_data
+hmac_sha512_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xDE, 0xF4, 0xDE, 0xAD, 0x26, 0xEB, 0xAB, 0x92,
+ 0xFB, 0xBF, 0xB0, 0x8C, 0x29, 0x87, 0x90, 0xAC,
+ 0x39, 0x8B, 0x5C, 0x49, 0x68, 0x1E, 0x3A, 0x05,
+ 0xCC, 0x68, 0x5C, 0x76, 0xCB, 0x3C, 0x71, 0x89,
+ 0xDE, 0xAA, 0x36, 0x44, 0x98, 0x93, 0x97, 0x1E,
+ 0x6D, 0x53, 0x83, 0x87, 0xB3, 0xB7, 0x56, 0x41
+ },
+ .len = 64
+ },
+ .digest = {
+ .data = {
+ 0xB8, 0x0B, 0x35, 0x97, 0x3F, 0x24, 0x3F, 0x05,
+ 0x2A, 0x7F, 0x2F, 0xD8, 0xD7, 0x56, 0x58, 0xAD,
+ 0x6F, 0x8D, 0x1F, 0x4C, 0x30, 0xF9, 0xA8, 0x29,
+ 0x7A, 0xE0, 0x8D, 0x88, 0xF5, 0x2E, 0x94, 0xF5,
+ 0x06, 0xF7, 0x5D, 0x57, 0x32, 0xA8, 0x49, 0x29,
+ 0xEA, 0x6B, 0x6D, 0x95, 0xBD, 0x76, 0xF5, 0x79,
+ 0x97, 0x37, 0x0F, 0xBE, 0xC2, 0x45, 0xA0, 0x87,
+ 0xAF, 0x24, 0x27, 0x0C, 0x78, 0xBA, 0xBE, 0x20
+ },
+ .len = 64,
+ .truncated_len = 32
+ }
+};
+
+static const struct blockcipher_test_data
+cmac_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0x4C, 0x77, 0x87, 0xA0, 0x78, 0x8E, 0xEA, 0x96,
+ 0xC1, 0xEB, 0x1E, 0x4E, 0x95, 0x8F, 0xED, 0x27
+ },
+ .len = 16,
+ .truncated_len = 16
+ }
+};
+
+static const struct blockcipher_test_data
+null_auth_test_vector = {
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .ciphertext = { /* arbitrary data - shouldn't be used */
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = { /* arbitrary data - shouldn't be used */
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 20,
+ .truncated_len = 12
+ }
+};
+
+static const struct blockcipher_test_data
+cmac_test_vector_12 = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .ciphertext = {
+ .data = plaintext_hash,
+ .len = 512
+ },
+ .auth_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {
+ 0x4C, 0x77, 0x87, 0xA0, 0x78, 0x8E, 0xEA, 0x96,
+ 0xC1, 0xEB, 0x1E, 0x4E, 0x95, 0x8F, 0xED, 0x27
+ },
+ .len = 12,
+ .truncated_len = 12
+ }
+};
+
+static const struct blockcipher_test_case hash_test_cases[] = {
+ {
+ .test_descr = "MD5 Digest",
+ .test_data = &md5_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "MD5 Digest Verify",
+ .test_data = &md5_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-MD5 Digest",
+ .test_data = &hmac_md5_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-MD5 Digest Verify",
+ .test_data = &hmac_md5_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "SHA1 Digest",
+ .test_data = &sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "SHA1 Digest Verify",
+ .test_data = &sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA1 Digest",
+ .test_data = &hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-SHA1 Digest Scatter Gather",
+ .test_data = &hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+ },
+ {
+ .test_descr = "HMAC-SHA1 Digest Verify",
+ .test_data = &hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA1 Digest Verify Scatter Gather",
+ .test_data = &hmac_sha1_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+ },
+ {
+ .test_descr = "SHA224 Digest",
+ .test_data = &sha224_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "SHA224 Digest Verify",
+ .test_data = &sha224_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA224 Digest",
+ .test_data = &hmac_sha224_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-SHA224 Digest Verify",
+ .test_data = &hmac_sha224_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "SHA256 Digest",
+ .test_data = &sha256_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "SHA256 Digest Verify",
+ .test_data = &sha256_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA256 Digest",
+ .test_data = &hmac_sha256_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-SHA256 Digest Verify",
+ .test_data = &hmac_sha256_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "SHA384 Digest",
+ .test_data = &sha384_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "SHA384 Digest Verify",
+ .test_data = &sha384_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA384 Digest",
+ .test_data = &hmac_sha384_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-SHA384 Digest Verify",
+ .test_data = &hmac_sha384_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "SHA512 Digest",
+ .test_data = &sha512_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "SHA512 Digest Verify",
+ .test_data = &sha512_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "HMAC-SHA512 Digest",
+ .test_data = &hmac_sha512_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "HMAC-SHA512 Digest Verify",
+ .test_data = &hmac_sha512_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "CMAC Digest 12B",
+ .test_data = &cmac_test_vector_12,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "CMAC Digest Verify 12B",
+ .test_data = &cmac_test_vector_12,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "CMAC Digest 16B",
+ .test_data = &cmac_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "CMAC Digest Verify 16B",
+ .test_data = &cmac_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "NULL algo - auth generate",
+ .test_data = &null_auth_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ },
+ {
+ .test_descr = "NULL algo - auth verify",
+ .test_data = &null_auth_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ },
+ {
+ .test_descr = "NULL algo - auth generate - OOP",
+ .test_data = &null_auth_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+ {
+ .test_descr = "NULL algo - auth verify - OOP",
+ .test_data = &null_auth_test_vector,
+ .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
+ .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
+ },
+
+};
+
+#endif /* TEST_CRYPTODEV_HASH_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_hmac_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_hmac_test_vectors.h
new file mode 100644
index 000000000..77153a5c1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_hmac_test_vectors.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Intel Corporation
+ */
+
+#ifndef APP_TEST_TEST_CRYPTODEV_HMAC_TEST_VECTORS_H_
+#define APP_TEST_TEST_CRYPTODEV_HMAC_TEST_VECTORS_H_
+
+/* *** MD5 test vectors *** */
+
+#define MD5_DIGEST_LEN 16
+
+struct HMAC_MD5_vector {
+ struct {
+ uint8_t data[64];
+ uint16_t len;
+ } key;
+
+ struct {
+ uint8_t data[1024];
+ uint16_t len;
+ } plaintext;
+
+ struct {
+ uint8_t data[16];
+ uint16_t len;
+ } auth_tag;
+};
+
+static const struct
+HMAC_MD5_vector HMAC_MD5_test_case_1 = {
+ .key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x87, 0x4D, 0x61, 0x91, 0xB6, 0x20, 0xE3, 0x26,
+ 0x1B, 0xEF, 0x68, 0x64, 0x99, 0x0D, 0xB6, 0xCE,
+ 0x98, 0x06, 0xF6, 0x6B, 0x79, 0x70, 0xFD, 0xFF,
+ 0x86, 0x17, 0x18, 0x7B, 0xB9, 0xFF, 0xFD, 0xFF,
+ 0x5A, 0xE4, 0xDF, 0x3E, 0xDB, 0xD5, 0xD3, 0x5E,
+ 0x5B, 0x4F, 0x09, 0x02, 0x0D, 0xB0, 0x3E, 0xAB,
+ 0x1E, 0x03, 0x1D, 0xDA, 0x2F, 0xBE, 0x03, 0xD1,
+ 0x79, 0x21, 0x70, 0xA0, 0xF3, 0x00, 0x9C, 0xEE
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x67, 0x83, 0xE1, 0x0F, 0xB0, 0xBF, 0x33, 0x49,
+ 0x22, 0x04, 0x89, 0xDF, 0x86, 0xD0, 0x5F, 0x0C
+ },
+ .len = MD5_DIGEST_LEN
+ }
+};
+
+static const struct
+HMAC_MD5_vector HMAC_MD5_test_case_2 = {
+ .key = {
+ .data = {
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+ 0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+ 0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD
+ },
+ .len = 32
+ },
+ .plaintext = {
+ .data = {
+ 0x87, 0x4D, 0x61, 0x91, 0xB6, 0x20, 0xE3, 0x26,
+ 0x1B, 0xEF, 0x68, 0x64, 0x99, 0x0D, 0xB6, 0xCE,
+ 0x98, 0x06, 0xF6, 0x6B, 0x79, 0x70, 0xFD, 0xFF,
+ 0x86, 0x17, 0x18, 0x7B, 0xB9, 0xFF, 0xFD, 0xFF,
+ 0x5A, 0xE4, 0xDF, 0x3E, 0xDB, 0xD5, 0xD3, 0x5E,
+ 0x5B, 0x4F, 0x09, 0x02, 0x0D, 0xB0, 0x3E, 0xAB,
+ 0x1E, 0x03, 0x1D, 0xDA, 0x2F, 0xBE, 0x03, 0xD1,
+ 0x79, 0x21, 0x70, 0xA0, 0xF3, 0x00, 0x9C, 0xEE
+ },
+ .len = 64
+ },
+ .auth_tag = {
+ .data = {
+ 0x39, 0x24, 0x70, 0x7A, 0x30, 0x38, 0x1E, 0x2B,
+ 0x9F, 0x6B, 0xD9, 0x3C, 0xAD, 0xC2, 0x73, 0x52
+ },
+ .len = MD5_DIGEST_LEN
+ }
+};
+
+#endif /* APP_TEST_TEST_CRYPTODEV_HMAC_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_kasumi_hash_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_kasumi_hash_test_vectors.h
new file mode 100644
index 000000000..5033d1830
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_kasumi_hash_test_vectors.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_KASUMI_HASH_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_KASUMI_HASH_TEST_VECTORS_H_
+
+struct kasumi_hash_test_data {
+ struct {
+ uint8_t data[16];
+ unsigned len;
+ } key;
+
+ /*
+ * Includes COUNT (4 bytes), FRESH (4 bytes), message
+ * and DIRECTION (1 bit), plus 1 0*, with enough 0s,
+ * so total length is multiple of 8 or 64 bits
+ */
+ struct {
+ uint8_t data[2056];
+ unsigned len; /* length must be in Bits */
+ } plaintext;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } digest;
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_1 = {
+ .key = {
+ .data = {
+ 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00,
+ 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0x6B, 0x22, 0x77, 0x37, 0x29, 0x6F, 0x39, 0x3C,
+ 0x80, 0x79, 0x35, 0x3E, 0xDC, 0x87, 0xE2, 0xE8,
+ 0x05, 0xD2, 0xEC, 0x49, 0xA4, 0xF2, 0xD8, 0xE2
+ },
+ .len = 256
+ },
+ .digest = {
+ .data = {0xF6, 0x3B, 0xD7, 0x2C},
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_2 = {
+ .key = {
+ .data = {
+ 0xD4, 0x2F, 0x68, 0x24, 0x28, 0x20, 0x1C, 0xAF,
+ 0xCD, 0x9F, 0x97, 0x94, 0x5E, 0x6D, 0xE7, 0xB7
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x3E, 0xDC, 0x87, 0xE2, 0xA4, 0xF2, 0xD8, 0xE2,
+ 0xB5, 0x92, 0x43, 0x84, 0x32, 0x8A, 0x4A, 0xE0,
+ 0x0B, 0x73, 0x71, 0x09, 0xF8, 0xB6, 0xC8, 0xDD,
+ 0x2B, 0x4D, 0xB6, 0x3D, 0xD5, 0x33, 0x98, 0x1C,
+ 0xEB, 0x19, 0xAA, 0xD5, 0x2A, 0x5B, 0x2B, 0xC3
+ },
+ .len = 320
+ },
+ .digest = {
+ .data = {0xA9, 0xDA, 0xF1, 0xFF},
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_3 = {
+ .key = {
+ .data = {
+ 0xFD, 0xB9, 0xCF, 0xDF, 0x28, 0x93, 0x6C, 0xC4,
+ 0x83, 0xA3, 0x18, 0x69, 0xD8, 0x1B, 0x8F, 0xAB
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x36, 0xAF, 0x61, 0x44, 0x98, 0x38, 0xF0, 0x3A,
+ 0x59, 0x32, 0xBC, 0x0A, 0xCE, 0x2B, 0x0A, 0xBA,
+ 0x33, 0xD8, 0xAC, 0x18, 0x8A, 0xC5, 0x4F, 0x34,
+ 0x6F, 0xAD, 0x10, 0xBF, 0x9D, 0xEE, 0x29, 0x20,
+ 0xB4, 0x3B, 0xD0, 0xC5, 0x3A, 0x91, 0x5C, 0xB7,
+ 0xDF, 0x6C, 0xAA, 0x72, 0x05, 0x3A, 0xBF, 0xF3,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 448
+ },
+ .digest = {
+ .data = {0x15, 0x37, 0xD3, 0x16},
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_4 = {
+ .key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09,
+ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 512
+ },
+ .digest = {
+ .data = {0xDD, 0x7D, 0xFA, 0xDD },
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_5 = {
+ .key = {
+ .data = {
+ 0xF4, 0xEB, 0xEC, 0x69, 0xE7, 0x3E, 0xAF, 0x2E,
+ 0xB2, 0xCF, 0x6A, 0xF4, 0xB3, 0x12, 0x0F, 0xFD
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x29, 0x6F, 0x39, 0x3C, 0x6B, 0x22, 0x77, 0x37,
+ 0x10, 0xBF, 0xFF, 0x83, 0x9E, 0x0C, 0x71, 0x65,
+ 0x8D, 0xBB, 0x2D, 0x17, 0x07, 0xE1, 0x45, 0x72,
+ 0x4F, 0x41, 0xC1, 0x6F, 0x48, 0xBF, 0x40, 0x3C,
+ 0x3B, 0x18, 0xE3, 0x8F, 0xD5, 0xD1, 0x66, 0x3B,
+ 0x6F, 0x6D, 0x90, 0x01, 0x93, 0xE3, 0xCE, 0xA8,
+ 0xBB, 0x4F, 0x1B, 0x4F, 0x5B, 0xE8, 0x22, 0x03,
+ 0x22, 0x32, 0xA7, 0x8D, 0x7D, 0x75, 0x23, 0x8D,
+ 0x5E, 0x6D, 0xAE, 0xCD, 0x3B, 0x43, 0x22, 0xCF,
+ 0x59, 0xBC, 0x7E, 0xA8, 0x4A, 0xB1, 0x88, 0x11,
+ 0xB5, 0xBF, 0xB7, 0xBC, 0x55, 0x3F, 0x4F, 0xE4,
+ 0x44, 0x78, 0xCE, 0x28, 0x7A, 0x14, 0x87, 0x99,
+ 0x90, 0xD1, 0x8D, 0x12, 0xCA, 0x79, 0xD2, 0xC8,
+ 0x55, 0x14, 0x90, 0x21, 0xCD, 0x5C, 0xE8, 0xCA,
+ 0x03, 0x71, 0xCA, 0x04, 0xFC, 0xCE, 0x14, 0x3E,
+ 0x3D, 0x7C, 0xFE, 0xE9, 0x45, 0x85, 0xB5, 0x88,
+ 0x5C, 0xAC, 0x46, 0x06, 0x8B, 0xC0, 0x00, 0x00
+ },
+ .len = 1088
+ },
+ .digest = {
+ .data = {0xC3, 0x83, 0x83, 0x9D},
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_6 = {
+ .key = {
+ .data = {
+ 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3,
+ 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2,
+ 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB,
+ 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11,
+ 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39,
+ 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39,
+ 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5,
+ 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF,
+ 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1,
+ 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72,
+ 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF,
+ 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF,
+ 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6,
+ 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A,
+ 0xC0
+ },
+ .len = 840
+ },
+ .digest = {
+ .data = {0x95, 0xAE, 0x41, 0xBA},
+ .len = 4
+ }
+};
+
+struct kasumi_hash_test_data kasumi_hash_test_case_7 = {
+ .key = {
+ .data = {
+ 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20,
+ 0x4E, 0xA5, 0xF1, 0x45, 0x10, 0x10, 0xD8, 0x52
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0xAD, 0x9C, 0x44, 0x1F, 0x89, 0x0B, 0x38, 0xC4,
+ 0x57, 0xA4, 0x9D, 0x42, 0x14, 0x07, 0xE8, 0xC0
+ },
+ .len = 192
+ },
+ .digest = {
+ .data = {0x87, 0x5F, 0xE4, 0x89},
+ .len = 4
+ }
+};
+#endif /* TEST_CRYPTODEV_KASUMI_HASH_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_kasumi_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_kasumi_test_vectors.h
new file mode 100644
index 000000000..f0a6d553d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_kasumi_test_vectors.h
@@ -0,0 +1,437 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_KASUMI_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_KASUMI_TEST_VECTORS_H_
+
+struct kasumi_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned int len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned int len;
+ } cipher_iv;
+
+ /*
+ * Data may include COUNT (4 bytes), FRESH (4 bytes),
+ * DIRECTION (1 bit), plus 1 0*, with enough 0s,
+ * so total length is multiple of 8 or 64 bits
+ */
+ struct {
+ uint8_t data[1024];
+ unsigned int len; /* length must be in Bits */
+ } plaintext;
+
+ struct {
+ unsigned int len;
+ } validDataLenInBits;
+
+ struct {
+ uint8_t data[1024];
+ unsigned int len; /* length must be in Bits */
+ } ciphertext;
+
+ struct {
+ unsigned int len;
+ } validCipherLenInBits;
+
+ struct {
+ unsigned int len;
+ } validCipherOffsetInBits;
+
+ /* Actual length of data to be hashed */
+ struct {
+ unsigned int len;
+ } validAuthLenInBits;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len;
+ unsigned int offset_bytes; /* offset must be in Bytes */
+ } digest;
+
+};
+
+struct kasumi_test_data kasumi_test_case_1 = {
+ .key = {
+ .data = {
+ 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00,
+ 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x72, 0xA4, 0xF2, 0x0F, 0x64, 0x00, 0x00, 0x00
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x7E, 0xC6, 0x12, 0x72, 0x74, 0x3B, 0xF1, 0x61,
+ 0x47, 0x26, 0x44, 0x6A, 0x6C, 0x38, 0xCE, 0xD1,
+ 0x66, 0xF6, 0xCA, 0x76, 0xEB, 0x54, 0x30, 0x04,
+ 0x42, 0x86, 0x34, 0x6C, 0xEF, 0x13, 0x0F, 0x92,
+ 0x92, 0x2B, 0x03, 0x45, 0x0D, 0x3A, 0x99, 0x75,
+ 0xE5, 0xBD, 0x2E, 0xA0, 0xEB, 0x55, 0xAD, 0x8E,
+ 0x1B, 0x19, 0x9E, 0x3E, 0xC4, 0x31, 0x60, 0x20,
+ 0xE9, 0xA1, 0xB2, 0x85, 0xE7, 0x62, 0x79, 0x53,
+ 0x59, 0xB7, 0xBD, 0xFD, 0x39, 0xBE, 0xF4, 0xB2,
+ 0x48, 0x45, 0x83, 0xD5, 0xAF, 0xE0, 0x82, 0xAE,
+ 0xE6, 0x38, 0xBF, 0x5F, 0xD5, 0xA6, 0x06, 0x19,
+ 0x39, 0x01, 0xA0, 0x8F, 0x4A, 0xB4, 0x1A, 0xAB,
+ 0x9B, 0x13, 0x48, 0x80
+ },
+ .len = 800
+ },
+ .ciphertext = {
+ .data = {
+ 0xD1, 0xE2, 0xDE, 0x70, 0xEE, 0xF8, 0x6C, 0x69,
+ 0x64, 0xFB, 0x54, 0x2B, 0xC2, 0xD4, 0x60, 0xAA,
+ 0xBF, 0xAA, 0x10, 0xA4, 0xA0, 0x93, 0x26, 0x2B,
+ 0x7D, 0x19, 0x9E, 0x70, 0x6F, 0xC2, 0xD4, 0x89,
+ 0x15, 0x53, 0x29, 0x69, 0x10, 0xF3, 0xA9, 0x73,
+ 0x01, 0x26, 0x82, 0xE4, 0x1C, 0x4E, 0x2B, 0x02,
+ 0xBE, 0x20, 0x17, 0xB7, 0x25, 0x3B, 0xBF, 0x93,
+ 0x09, 0xDE, 0x58, 0x19, 0xCB, 0x42, 0xE8, 0x19,
+ 0x56, 0xF4, 0xC9, 0x9B, 0xC9, 0x76, 0x5C, 0xAF,
+ 0x53, 0xB1, 0xD0, 0xBB, 0x82, 0x79, 0x82, 0x6A,
+ 0xDB, 0xBC, 0x55, 0x22, 0xE9, 0x15, 0xC1, 0x20,
+ 0xA6, 0x18, 0xA5, 0xA7, 0xF5, 0xE8, 0x97, 0x08,
+ 0x93, 0x39, 0x65, 0x0F
+ },
+ .len = 800
+ },
+ .validCipherLenInBits = {
+ .len = 798
+ },
+ .validCipherOffsetInBits = {
+ .len = 0
+ }
+};
+
+struct kasumi_test_data kasumi_test_case_2 = {
+ .key = {
+ .data = {
+ 0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A,
+ 0x7C, 0x36, 0xEA, 0x55, 0xE9, 0x60, 0x56, 0x95
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xE2, 0x8B, 0xCF, 0x7B, 0xC0, 0x00, 0x00, 0x00
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x10, 0x11, 0x12, 0x31, 0xE0, 0x60, 0x25, 0x3A,
+ 0x43, 0xFD, 0x3F, 0x57, 0xE3, 0x76, 0x07, 0xAB,
+ 0x28, 0x27, 0xB5, 0x99, 0xB6, 0xB1, 0xBB, 0xDA,
+ 0x37, 0xA8, 0xAB, 0xCC, 0x5A, 0x8C, 0x55, 0x0D,
+ 0x1B, 0xFB, 0x2F, 0x49, 0x46, 0x24, 0xFB, 0x50,
+ 0x36, 0x7F, 0xA3, 0x6C, 0xE3, 0xBC, 0x68, 0xF1,
+ 0x1C, 0xF9, 0x3B, 0x15, 0x10, 0x37, 0x6B, 0x02,
+ 0x13, 0x0F, 0x81, 0x2A, 0x9F, 0xA1, 0x69, 0xD8
+ },
+ .len = 512
+ },
+ .ciphertext = {
+ .data = {
+ 0x3D, 0xEA, 0xCC, 0x7C, 0x15, 0x82, 0x1C, 0xAA,
+ 0x89, 0xEE, 0xCA, 0xDE, 0x9B, 0x5B, 0xD3, 0x61,
+ 0x4B, 0xD0, 0xC8, 0x41, 0x9D, 0x71, 0x03, 0x85,
+ 0xDD, 0xBE, 0x58, 0x49, 0xEF, 0x1B, 0xAC, 0x5A,
+ 0xE8, 0xB1, 0x4A, 0x5B, 0x0A, 0x67, 0x41, 0x52,
+ 0x1E, 0xB4, 0xE0, 0x0B, 0xB9, 0xEC, 0xF3, 0xE9,
+ 0xF7, 0xCC, 0xB9, 0xCA, 0xE7, 0x41, 0x52, 0xD7,
+ 0xF4, 0xE2, 0xA0, 0x34, 0xB6, 0xEA, 0x00, 0xEC
+ },
+ .len = 512
+ },
+ .validCipherLenInBits = {
+ .len = 510
+ },
+ .validCipherOffsetInBits = {
+ .len = 0
+ }
+};
+
+struct kasumi_test_data kasumi_test_case_3 = {
+ .key = {
+ .data = {
+ 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20,
+ 0x4E, 0xA5, 0xF1, 0x45, 0x10, 0x10, 0xD8, 0x52
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0xAD, 0x9C, 0x44, 0x1F, 0x89, 0x0B, 0x38, 0xC4,
+ 0x57, 0xA4, 0x9D, 0x42, 0x14, 0x07, 0xE8, 0xC0
+ },
+ .len = 192
+ },
+ .ciphertext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0x9B, 0xC9, 0x2C, 0xA8, 0x03, 0xC6, 0x7B, 0x28,
+ 0xA1, 0x1A, 0x4B, 0xEE, 0x5A, 0x0C, 0x25, 0xC0
+ },
+ .len = 192
+ },
+ .validDataLenInBits = {
+ .len = 192
+ },
+ .validCipherLenInBits = {
+ .len = 120
+ },
+ .validAuthLenInBits = {
+ .len = 192
+ },
+ .validCipherOffsetInBits = {
+ .len = 64
+ },
+ .digest = {
+ .data = {0x87, 0x5F, 0xE4, 0x89},
+ .len = 4,
+ .offset_bytes = 0
+ }
+};
+
+struct kasumi_test_data kasumi_test_case_4 = {
+ .key = {
+ .data = {
+ 0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C,
+ 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x39, 0x8A, 0x59, 0xB4, 0x2C, 0x00, 0x00, 0x00,
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x1B, 0xA6, 0x82, 0x4C, 0x1B, 0xFB, 0x1A,
+ 0xB4, 0x85, 0x47, 0x20, 0x29, 0xB7, 0x1D, 0x80,
+ 0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC,
+ 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66, 0xB1, 0xF0
+ },
+ .len = 256
+ },
+ .ciphertext = {
+ .data = {
+ 0x5B, 0xB9, 0x43, 0x1B, 0xB1, 0xE9, 0x8B, 0xD1,
+ 0x1B, 0x93, 0xDB, 0x7C, 0x3D, 0x45, 0x13, 0x65,
+ 0x59, 0xBB, 0x86, 0xA2, 0x95, 0xAA, 0x20, 0x4E,
+ 0xCB, 0xEB, 0xF6, 0xF7, 0xA5, 0x10, 0x15, 0x10
+ },
+ .len = 256
+ },
+ .validCipherLenInBits = {
+ .len = 253
+ },
+ .validCipherOffsetInBits = {
+ .len = 0
+ }
+};
+
+struct kasumi_test_data kasumi_test_case_5 = {
+ .key = {
+ .data = {
+ 0x60, 0x90, 0xEA, 0xE0, 0x4C, 0x83, 0x70, 0x6E,
+ 0xEC, 0xBF, 0x65, 0x2B, 0xE8, 0xE3, 0x65, 0x66
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x72, 0xA4, 0xF2, 0x0F, 0x48, 0x00, 0x00, 0x00
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x40, 0x98, 0x1B, 0xA6, 0x82, 0x4C, 0x1B, 0xFB,
+ 0x42, 0x86, 0xB2, 0x99, 0x78, 0x3D, 0xAF, 0x44,
+ 0x2C, 0x09, 0x9F, 0x7A, 0xB0, 0xF5, 0x8D, 0x5C,
+ 0x8E, 0x46, 0xB1, 0x04, 0xF0, 0x8F, 0x01, 0xB4,
+ 0x1A, 0xB4, 0x85, 0x47, 0x20, 0x29, 0xB7, 0x1D,
+ 0x36, 0xBD, 0x1A, 0x3D, 0x90, 0xDC, 0x3A, 0x41,
+ 0xB4, 0x6D, 0x51, 0x67, 0x2A, 0xC4, 0xC9, 0x66,
+ 0x3A, 0x2B, 0xE0, 0x63, 0xDA, 0x4B, 0xC8, 0xD2,
+ 0x80, 0x8C, 0xE3, 0x3E, 0x2C, 0xCC, 0xBF, 0xC6,
+ 0x34, 0xE1, 0xB2, 0x59, 0x06, 0x08, 0x76, 0xA0,
+ 0xFB, 0xB5, 0xA4, 0x37, 0xEB, 0xCC, 0x8D, 0x31,
+ 0xC1, 0x9E, 0x44, 0x54, 0x31, 0x87, 0x45, 0xE3,
+ 0x98, 0x76, 0x45, 0x98, 0x7A, 0x98, 0x6F, 0x2C,
+ 0xB0
+ },
+ .len = 840
+ },
+ .ciphertext = {
+ .data = {
+ 0xDD, 0xB3, 0x64, 0xDD, 0x2A, 0xAE, 0xC2, 0x4D,
+ 0xFF, 0x29, 0x19, 0x57, 0xB7, 0x8B, 0xAD, 0x06,
+ 0x3A, 0xC5, 0x79, 0xCD, 0x90, 0x41, 0xBA, 0xBE,
+ 0x89, 0xFD, 0x19, 0x5C, 0x05, 0x78, 0xCB, 0x9F,
+ 0xDE, 0x42, 0x17, 0x56, 0x61, 0x78, 0xD2, 0x02,
+ 0x40, 0x20, 0x6D, 0x07, 0xCF, 0xA6, 0x19, 0xEC,
+ 0x05, 0x9F, 0x63, 0x51, 0x44, 0x59, 0xFC, 0x10,
+ 0xD4, 0x2D, 0xC9, 0x93, 0x4E, 0x56, 0xEB, 0xC0,
+ 0xCB, 0xC6, 0x0D, 0x4D, 0x2D, 0xF1, 0x74, 0x77,
+ 0x4C, 0xBD, 0xCD, 0x5D, 0xA4, 0xA3, 0x50, 0x31,
+ 0x7A, 0x7F, 0x12, 0xE1, 0x94, 0x94, 0x71, 0xF8,
+ 0xA2, 0x95, 0xF2, 0x72, 0xE6, 0x8F, 0xC0, 0x71,
+ 0x59, 0xB0, 0x7D, 0x8E, 0x2D, 0x26, 0xE4, 0x59,
+ 0x9E
+ },
+ .len = 840
+ },
+ .validCipherLenInBits = {
+ .len = 837
+ },
+ .validCipherOffsetInBits = {
+ .len = 0
+ }
+};
+
+struct kasumi_test_data kasumi_test_case_6 = {
+ .key = {
+ .data = {
+ 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20,
+ 0x4E, 0xA5, 0xF1, 0x45, 0x10, 0x10, 0xD8, 0x52
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0xAD, 0x9C, 0x44, 0x1F, 0x89, 0x0B, 0x38, 0xC4,
+ 0x57, 0xA4, 0x9D, 0x42, 0x14, 0x07, 0xE8, 0xC0
+ },
+ .len = 192
+ },
+ .ciphertext = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0x9B, 0xC9, 0x2C, 0xA8, 0x03, 0xC6, 0x7B, 0x28,
+ 0xA1, 0x1A, 0x4B, 0xEE, 0x5A, 0x0C, 0x25, 0xC0
+ },
+ .len = 192
+ },
+ .validDataLenInBits = {
+ .len = 192
+ },
+ .validCipherLenInBits = {
+ .len = 120
+ },
+ .validCipherOffsetInBits = {
+ .len = 64
+ },
+ .validAuthLenInBits = {
+ .len = 192
+ },
+ .digest = {
+ .data = {0x0F, 0xD2, 0xAA, 0xB5},
+ .len = 4,
+ .offset_bytes = 0
+ }
+};
+
+struct kasumi_test_data kasumi_auth_cipher_test_case_2 = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+ },
+ .len = 8
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A
+ },
+ .len = 128 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xFA, 0xC6, 0xA9, 0x09, 0x91, 0x74,
+ 0x35, 0xAA, 0x85, 0xB0, 0xE0, 0x07, 0x78, 0xDA,
+ 0x05, 0x88, 0x4E, 0x8D, 0xEC, 0x41, 0xF3, 0xBC,
+ 0x0D, 0x9F, 0xE3, 0xEF, 0x8E, 0x33, 0x22, 0xF3,
+ 0x15, 0x4B, 0x12, 0xC2, 0x22, 0x12, 0xD6, 0x46,
+ 0xD7, 0x27, 0x20, 0x1D, 0x50, 0x60, 0x9D, 0x42,
+ 0xF6, 0x73, 0xF5, 0x28, 0x88, 0xBE, 0x60, 0xEC,
+ 0x9C, 0x18, 0x81, 0xC4, 0x0A, 0xF4, 0xD5, 0x7A,
+ 0xB5, 0x3F, 0x1A, 0x79, 0xAB, 0x79, 0xDB, 0x24,
+ 0xF9, 0x6E, 0x86, 0x78, 0x10, 0x19, 0xAE, 0xD8,
+ 0xB2, 0xCA, 0x32, 0x8D, 0xD8, 0x28, 0x8B, 0x2F,
+ 0x5B, 0x3C, 0xE3, 0x7D, 0xD3, 0x70, 0x11, 0xDE,
+ 0x2C, 0xDC, 0xC1, 0xC6, 0xB6, 0xFD, 0xF3, 0x7D,
+ 0x38, 0x97, 0x8B, 0x81, 0x02, 0x88, 0x62, 0x3C,
+ 0x1E, 0x1A, 0x93, 0x21, 0xE3, 0x6D, 0xD7, 0x20,
+ 0x80, 0xA8, 0xDA, 0x18, 0x8F, 0x58, 0x0F, 0x4E
+ },
+ .len = 128 << 3
+ },
+ .validDataLenInBits = {
+ .len = 128 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 126 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 124 << 3
+ },
+ .validCipherOffsetInBits = {
+ .len = 2 << 3
+ },
+ .digest = {
+ .data = {0x8F, 0x58, 0x0F, 0x4E},
+ .len = 4,
+ .offset_bytes = 124
+ }
+};
+#endif /* TEST_CRYPTODEV_KASUMI_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_mixed_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_mixed_test_vectors.h
new file mode 100644
index 000000000..f50dcb045
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_mixed_test_vectors.h
@@ -0,0 +1,1488 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_MIXED_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_MIXED_TEST_VECTORS_H_
+
+struct mixed_cipher_auth_test_data {
+
+ enum rte_crypto_auth_algorithm auth_algo;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len; /* length must be in Bytes */
+ } auth_key;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len; /* length must be in Bytes */
+ } auth_iv;
+
+ struct {
+ unsigned int len_bits;
+ unsigned int offset_bits;
+ } auth;
+
+ enum rte_crypto_cipher_algorithm cipher_algo;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len; /* length must be in Bytes */
+ } cipher_key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned int len; /* length must be in Bytes */
+ } cipher_iv;
+
+ struct {
+ unsigned int len_bits;
+ unsigned int offset_bits;
+ } cipher;
+
+ struct {
+ uint8_t data[1024];
+ unsigned int len_bits;
+ } plaintext;
+
+ struct {
+ uint8_t data[1024];
+ unsigned int len_bits;
+ } ciphertext;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len; /* length must be in Bytes */
+ unsigned int offset; /* offset must be in Bytes */
+ } digest_enc;
+
+ struct {
+ unsigned int len_bits;
+ } validDataLen;
+
+ struct {
+ unsigned int len_bits;
+ } validCipherLen;
+
+ struct {
+ unsigned int len_bits;
+ } validAuthLen;
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_aes_ctr_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .auth_key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 124 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 126 << 3,
+ .offset_bits = 2 << 3,
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A
+ },
+ .len_bits = 124 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xC9, 0x79, 0xCA, 0xCB, 0xDF, 0x96,
+ 0x97, 0xA5, 0xB0, 0xFC, 0x56, 0xE9, 0xC4, 0xB4,
+ 0x32, 0x5F, 0x55, 0x59, 0xCF, 0x1A, 0xA5, 0xB5,
+ 0x63, 0xAC, 0x94, 0x87, 0x6F, 0xFB, 0x5A, 0x54,
+ 0x4E, 0xE2, 0x2B, 0x32, 0x04, 0x0C, 0xDF, 0x7D,
+ 0x58, 0x73, 0xCE, 0x64, 0x71, 0xEA, 0x31, 0x19,
+ 0xE1, 0x37, 0x9E, 0x89, 0x15, 0x1F, 0xDE, 0x99,
+ 0x17, 0x80, 0x2A, 0x95, 0xAB, 0x37, 0xDF, 0x01,
+ 0x7F, 0x3B, 0x17, 0x07, 0xFA, 0x93, 0xC9, 0xC8,
+ 0x6A, 0x1C, 0xE2, 0x34, 0x2F, 0x33, 0x59, 0xE4,
+ 0xE2, 0x56, 0x1A, 0x23, 0xCC, 0xCE, 0x29, 0x33,
+ 0xC7, 0xAF, 0x92, 0x28, 0x86, 0x5B, 0x91, 0x5B,
+ 0x0E, 0x4E, 0xFB, 0x3B, 0x9D, 0x9F, 0xDF, 0x16,
+ 0x79, 0x90, 0x86, 0xBA, 0x70, 0xD9, 0xF7, 0x9B,
+ 0xEC, 0x46, 0xA9, 0x98, 0x5A, 0xF1, 0x5A, 0x05,
+ 0x3E, 0xD9, 0xE5, 0x03, 0x5D, 0x41, 0xB4, 0xDF
+ },
+ .len_bits = 128 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x5D, 0x41, 0xB4, 0xDF,
+ },
+ .len = 4,
+ .offset = 124,
+ },
+ .validDataLen = {
+ .len_bits = 128 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 126 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 124 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_zuc_cipher_snow_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .auth_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 73 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .cipher_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 77 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+ 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+ 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+ 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+ 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+ 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+ 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+ 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+ 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+ 0x00
+ },
+ .len_bits = 73 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x18, 0x46, 0xE1, 0xC5, 0x2C, 0x85, 0x93, 0x22,
+ 0x84, 0x80, 0xD6, 0x84, 0x5C, 0x99, 0x55, 0xE0,
+ 0xD5, 0x02, 0x41, 0x74, 0x4A, 0xD2, 0x8E, 0x7E,
+ 0xB9, 0x79, 0xD3, 0xE5, 0x76, 0x75, 0xD5, 0x59,
+ 0x26, 0xD7, 0x06, 0x2D, 0xF4, 0x71, 0x26, 0x40,
+ 0xAC, 0x77, 0x62, 0xAC, 0x35, 0x0D, 0xC5, 0x35,
+ 0xF8, 0x03, 0x54, 0x52, 0x2E, 0xCA, 0x14, 0xD8,
+ 0x2E, 0x6C, 0x0E, 0x7A, 0x09, 0xE7, 0x20, 0xDD,
+ 0x7C, 0xE3, 0x28, 0x77, 0x53, 0x65, 0xBA, 0x54,
+ 0xE8, 0x25, 0x04, 0x52, 0xFD
+ },
+ .len_bits = 77 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x25, 0x04, 0x52, 0xFD
+ },
+ .len = 4,
+ .offset = 73,
+ },
+ .validDataLen = {
+ .len_bits = 77 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 77 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 73 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_snow_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .auth_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .auth = {
+ .len_bits = 512 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .cipher_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .cipher = {
+ .len_bits = 516 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+ 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+ 0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+ 0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+ 0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+ 0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+ 0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+ 0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+ 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+ 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+ 0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+ 0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+ 0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+ 0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+ 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+ 0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+ 0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+ 0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+ 0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+ 0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+ 0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+ 0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+ 0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+ 0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+ 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+ 0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+ 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+ 0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+ 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+ 0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+ 0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+ 0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+ 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+ 0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+ 0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+ 0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+ 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+ 0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+ 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+ 0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+ },
+ .len_bits = 512 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x8A, 0xA9, 0x74, 0x31, 0xB1, 0xF2, 0xAB, 0x00,
+ 0xD6, 0x3D, 0xFA, 0xBD, 0xD9, 0x65, 0x52, 0x80,
+ 0xB5, 0x98, 0x20, 0xFF, 0x8D, 0x1C, 0x0F, 0x53,
+ 0xDD, 0x79, 0xCC, 0x9D, 0x7A, 0x6D, 0x76, 0x06,
+ 0xB6, 0xF4, 0xAC, 0xDA, 0xF2, 0x24, 0x02, 0x58,
+ 0x5F, 0xE3, 0xD4, 0xF7, 0x0B, 0x3B, 0x1C, 0x4C,
+ 0x0B, 0x4C, 0xC7, 0x4D, 0x3D, 0xFA, 0x28, 0xD9,
+ 0xA0, 0x90, 0x3E, 0x91, 0xDC, 0xC4, 0xE1, 0x2E,
+ 0x7C, 0xB4, 0xBD, 0xE0, 0x9E, 0xC8, 0x33, 0x42,
+ 0x0E, 0x84, 0xEF, 0x3C, 0xF1, 0x8B, 0x2C, 0xBD,
+ 0x33, 0x70, 0x22, 0xBA, 0xD4, 0x0B, 0xB2, 0x83,
+ 0x7F, 0x27, 0x51, 0x92, 0xD1, 0x40, 0x1E, 0xCD,
+ 0x62, 0x0F, 0x61, 0x5F, 0xB4, 0xB1, 0x0D, 0x1A,
+ 0x16, 0x1B, 0xE8, 0xA8, 0x2B, 0x45, 0xBA, 0x56,
+ 0x30, 0xD0, 0xE3, 0xCA, 0x4D, 0x23, 0xA3, 0x38,
+ 0xD6, 0x2C, 0xE4, 0x8D, 0xFF, 0x23, 0x97, 0x9E,
+ 0xE9, 0xBD, 0x70, 0xAF, 0x6B, 0x68, 0xA7, 0x21,
+ 0x3C, 0xFB, 0xB2, 0x99, 0x4D, 0xE9, 0x70, 0x56,
+ 0x36, 0xB8, 0xD7, 0xE0, 0xEB, 0x62, 0xA1, 0x79,
+ 0xF9, 0xD6, 0xAD, 0x83, 0x75, 0x54, 0xF5, 0x45,
+ 0x82, 0xE8, 0xD6, 0xA9, 0x76, 0x11, 0xC7, 0x81,
+ 0x2C, 0xBA, 0x67, 0xB5, 0xDB, 0xE5, 0xF2, 0x6B,
+ 0x7D, 0x9F, 0x4E, 0xDC, 0xA1, 0x62, 0xF1, 0xF0,
+ 0xAD, 0xD4, 0x7A, 0xA3, 0xF3, 0x76, 0x29, 0xA4,
+ 0xB7, 0xF3, 0x31, 0x84, 0xE7, 0x1F, 0x0D, 0x01,
+ 0xBD, 0x46, 0x07, 0x51, 0x05, 0x76, 0xE2, 0x95,
+ 0xF8, 0x48, 0x18, 0x8A, 0x1E, 0x92, 0x8B, 0xBC,
+ 0x30, 0x05, 0xF5, 0xD6, 0x96, 0xEF, 0x78, 0xB6,
+ 0xF3, 0xEC, 0x4C, 0xB1, 0x88, 0x8B, 0x63, 0x40,
+ 0x07, 0x37, 0xB4, 0x1A, 0xBD, 0xE9, 0x38, 0xB4,
+ 0x31, 0x35, 0x9D, 0x0C, 0xF1, 0x24, 0x0E, 0xD2,
+ 0xAE, 0x39, 0xA6, 0x41, 0x3C, 0x91, 0x6A, 0x4B,
+ 0xEC, 0x46, 0x76, 0xB4, 0x15, 0xC3, 0x58, 0x96,
+ 0x69, 0x02, 0x21, 0x37, 0x65, 0xDF, 0xA6, 0x43,
+ 0x78, 0x81, 0x8B, 0x39, 0x37, 0xE3, 0xF3, 0xD9,
+ 0xA2, 0xAA, 0x3F, 0xA9, 0x21, 0x24, 0x93, 0x4A,
+ 0xB0, 0xDE, 0x22, 0x5F, 0xF8, 0xD3, 0xCC, 0x13,
+ 0x5C, 0xC2, 0x5C, 0x98, 0x6D, 0xFB, 0x34, 0x26,
+ 0xE2, 0xC9, 0x26, 0x23, 0x41, 0xAB, 0xC3, 0x8A,
+ 0xEC, 0x62, 0xA9, 0x5B, 0x51, 0xB9, 0x10, 0x9D,
+ 0xB1, 0xBB, 0xDE, 0x78, 0xDE, 0xE7, 0xF0, 0x9F,
+ 0x91, 0x6C, 0x4D, 0xFC, 0xB3, 0x9C, 0xFF, 0xA4,
+ 0x9D, 0xB8, 0xCD, 0xF6, 0xA8, 0x6A, 0xDB, 0x3B,
+ 0x82, 0xFE, 0xCD, 0x6B, 0x08, 0x0A, 0x5E, 0x76,
+ 0xE9, 0xB3, 0xA2, 0x78, 0x25, 0xDB, 0xB1, 0x76,
+ 0x42, 0x2C, 0xFB, 0x20, 0x87, 0x81, 0x76, 0x17,
+ 0x99, 0xFD, 0x56, 0x52, 0xE2, 0xB0, 0x8E, 0x1B,
+ 0x99, 0xB3, 0x6B, 0x16, 0xC5, 0x4F, 0x0D, 0xBB,
+ 0x0E, 0xB7, 0x54, 0x63, 0xD9, 0x67, 0xD9, 0x85,
+ 0x1F, 0xA8, 0xF0, 0xF0, 0xB0, 0x41, 0xDC, 0xBC,
+ 0x75, 0xEE, 0x23, 0x7D, 0x40, 0xCE, 0xB8, 0x0A,
+ 0x6D, 0xC1, 0xD7, 0xCB, 0xAE, 0xCE, 0x91, 0x9E,
+ 0x3E, 0x5A, 0x76, 0xF8, 0xC0, 0xF2, 0x7F, 0x0B,
+ 0xD2, 0x5F, 0x63, 0xBE, 0xB2, 0x81, 0x8E, 0x6D,
+ 0xB3, 0x6B, 0x67, 0x9D, 0xAC, 0xE2, 0xDB, 0x7C,
+ 0x11, 0x19, 0x55, 0x55, 0x11, 0xED, 0x7F, 0x4E,
+ 0x9E, 0x4B, 0x6E, 0x01, 0x74, 0x4A, 0xE8, 0x78,
+ 0xEC, 0xCD, 0xF7, 0xA2, 0x6E, 0xDB, 0xB6, 0x3B,
+ 0x4D, 0x2C, 0x09, 0x62, 0x57, 0x6E, 0x38, 0x8A,
+ 0x61, 0x17, 0x00, 0xE9, 0x86, 0x7F, 0x3D, 0x93,
+ 0xBC, 0xC3, 0x27, 0x90, 0x7E, 0x41, 0x81, 0xBA,
+ 0x74, 0x70, 0x19, 0xE8, 0xD2, 0x88, 0x61, 0xDF,
+ 0xB4, 0xED, 0xA4, 0x9D, 0x3D, 0xED, 0x95, 0x65,
+ 0xCA, 0xFF, 0x8D, 0x58, 0x63, 0x10, 0x9D, 0xBE,
+ 0x78, 0x81, 0x47, 0x38
+ },
+ .len_bits = 516 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x78, 0x81, 0x47, 0x38
+ },
+ .len = 4,
+ .offset = 512,
+ },
+ .validDataLen = {
+ .len_bits = 516 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 516 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 512 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_zuc_cipher_aes_ctr_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .auth_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 73 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 77 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+ 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+ 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+ 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+ 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+ 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+ 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+ 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+ 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+ 0x00
+ },
+ .len_bits = 73 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x53, 0x92, 0x9F, 0x88, 0x32, 0xA1, 0x6D, 0x66,
+ 0x00, 0x32, 0x29, 0xF9, 0x14, 0x75, 0x6D, 0xB3,
+ 0xEB, 0x64, 0x25, 0x09, 0xE1, 0x80, 0x31, 0x8C,
+ 0xF8, 0x47, 0x64, 0xAA, 0x07, 0x8E, 0x06, 0xBF,
+ 0x05, 0xD7, 0x43, 0xEE, 0xFF, 0x11, 0x33, 0x4A,
+ 0x82, 0xCF, 0x88, 0x6F, 0x33, 0xB2, 0xB5, 0x67,
+ 0x50, 0x0A, 0x74, 0x2D, 0xE4, 0x56, 0x40, 0x31,
+ 0xEE, 0xB3, 0x6C, 0x6E, 0x6A, 0x7B, 0x20, 0xBA,
+ 0x4E, 0x44, 0x34, 0xC8, 0x62, 0x21, 0x8C, 0x45,
+ 0xD7, 0x85, 0x44, 0xF4, 0x7E
+ },
+ .len_bits = 77 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x85, 0x44, 0xF4, 0x7E
+ },
+ .len = 4,
+ .offset = 73,
+ },
+ .validDataLen = {
+ .len_bits = 77 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 77 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 73 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_aes_ctr_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 52 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len_bits = 48 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x91, 0x96, 0x28, 0xB4, 0x89, 0x74, 0xF6, 0x5E,
+ 0x98, 0x58, 0xA1, 0xD3, 0x0E, 0xE3, 0xFC, 0x39,
+ 0xDB, 0x36, 0xE4, 0x97, 0x74, 0x5B, 0x5E, 0xD4,
+ 0x1B, 0x8A, 0xC5, 0x9D, 0xDF, 0x96, 0x97, 0x5F,
+ 0x58, 0x4A, 0x75, 0x74, 0x27, 0x07, 0xF3, 0x7F,
+ 0xCE, 0x2C, 0x4A, 0x6C, 0xE5, 0x19, 0xE7, 0x8B,
+ 0xF3, 0x21, 0x84, 0x6C
+ },
+ .len_bits = 52 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0xF3, 0x21, 0x84, 0x6C
+ },
+ .len = 4,
+ .offset = 48,
+ },
+ .validDataLen = {
+ .len_bits = 52 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 52 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 48 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_zuc_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 52 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len_bits = 48 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x52, 0x11, 0xCD, 0xFF, 0xF8, 0x88, 0x61, 0x1E,
+ 0xF5, 0xD2, 0x8E, 0xEB, 0x2A, 0x49, 0x18, 0x1F,
+ 0xF4, 0xDA, 0x8B, 0x19, 0x60, 0x0B, 0x92, 0x9E,
+ 0x79, 0x2A, 0x5B, 0x0B, 0x7E, 0xC6, 0x22, 0x36,
+ 0x74, 0xA4, 0x6C, 0xBC, 0xF5, 0x25, 0x69, 0xAE,
+ 0xDA, 0x04, 0xB9, 0xAF, 0x16, 0x42, 0x0F, 0xCB,
+ 0x3E, 0xC9, 0x49, 0xE9
+ },
+ .len_bits = 52 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x3E, 0xC9, 0x49, 0xE9
+ },
+ .len = 4,
+ .offset = 48,
+ },
+ .validDataLen = {
+ .len_bits = 52 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 52 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 48 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_zuc_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .auth_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .auth = {
+ .len_bits = 512 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .cipher_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .cipher = {
+ .len_bits = 516 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+ 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+ 0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+ 0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+ 0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+ 0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+ 0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+ 0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+ 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+ 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+ 0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+ 0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+ 0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+ 0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+ 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+ 0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+ 0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+ 0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+ 0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+ 0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+ 0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+ 0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+ 0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+ 0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+ 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+ 0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+ 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+ 0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+ 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+ 0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+ 0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+ 0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+ 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+ 0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+ 0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+ 0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+ 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+ 0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+ 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+ 0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+ },
+ .len_bits = 512 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x3C, 0x89, 0x1C, 0xE5, 0xB7, 0xDE, 0x61, 0x4D,
+ 0x05, 0x37, 0x3F, 0x40, 0xC9, 0xCF, 0x10, 0x07,
+ 0x7F, 0x18, 0xC5, 0x96, 0x21, 0xA9, 0xCF, 0xF5,
+ 0xBB, 0x9C, 0x22, 0x72, 0x00, 0xBE, 0xAC, 0x4B,
+ 0x55, 0x02, 0x19, 0x2B, 0x37, 0x64, 0x15, 0x6B,
+ 0x54, 0x74, 0xAE, 0x0F, 0xE7, 0x68, 0xB3, 0x92,
+ 0x17, 0x26, 0x75, 0xEE, 0x0B, 0xE9, 0x46, 0x3C,
+ 0x6E, 0x76, 0x52, 0x14, 0x2B, 0xD0, 0xB6, 0xD0,
+ 0x09, 0x07, 0x17, 0x12, 0x58, 0x61, 0xE8, 0x2A,
+ 0x7C, 0x55, 0x67, 0x66, 0x49, 0xD1, 0x4E, 0x2F,
+ 0x06, 0x96, 0x3A, 0xF7, 0x05, 0xE3, 0x65, 0x47,
+ 0x7C, 0xBB, 0x66, 0x25, 0xC4, 0x73, 0xB3, 0x7B,
+ 0x3D, 0x1D, 0x59, 0x54, 0x4E, 0x38, 0x9C, 0x4D,
+ 0x10, 0x4B, 0x49, 0xA4, 0x92, 0xC7, 0xD7, 0x17,
+ 0x6F, 0xC0, 0xEE, 0x8D, 0xBE, 0xA5, 0xE3, 0xB9,
+ 0xBA, 0x5E, 0x88, 0x36, 0x06, 0x19, 0xB7, 0x86,
+ 0x66, 0x19, 0x90, 0xC4, 0xAE, 0xB3, 0xFE, 0xA7,
+ 0xCF, 0x2A, 0xD8, 0x6C, 0x0E, 0xD5, 0x24, 0x2A,
+ 0x92, 0x93, 0xB9, 0x12, 0xCB, 0x50, 0x0A, 0x22,
+ 0xB0, 0x09, 0x06, 0x17, 0x85, 0xC9, 0x03, 0x70,
+ 0x18, 0xF2, 0xD5, 0x6A, 0x66, 0xC2, 0xB6, 0xC6,
+ 0xA5, 0xA3, 0x24, 0xEC, 0xB9, 0x07, 0xD5, 0x8A,
+ 0xA0, 0x44, 0x54, 0xD7, 0x21, 0x9F, 0x02, 0x83,
+ 0x78, 0x7B, 0x78, 0x9C, 0x97, 0x2A, 0x36, 0x51,
+ 0xAF, 0xE1, 0x79, 0x81, 0x07, 0x53, 0xE4, 0xA0,
+ 0xC7, 0xCF, 0x10, 0x7C, 0xB2, 0xE6, 0xA1, 0xFD,
+ 0x81, 0x0B, 0x96, 0x50, 0x5D, 0xFE, 0xB3, 0xC6,
+ 0x75, 0x00, 0x0C, 0x56, 0x83, 0x9B, 0x7B, 0xF4,
+ 0xE0, 0x3A, 0xC0, 0xE1, 0xA9, 0xEC, 0xAC, 0x47,
+ 0x24, 0xF5, 0x12, 0x1B, 0xD0, 0x28, 0x32, 0xE2,
+ 0x3B, 0x42, 0xC1, 0x5B, 0x98, 0x98, 0x78, 0x2D,
+ 0xC1, 0x69, 0x05, 0x37, 0x24, 0xF0, 0x73, 0xBA,
+ 0xBE, 0x57, 0xAC, 0x40, 0x9A, 0x91, 0x42, 0x49,
+ 0x31, 0x0F, 0xED, 0x45, 0xA8, 0x25, 0xFF, 0x1B,
+ 0xF4, 0x2F, 0x61, 0x7A, 0xB0, 0x60, 0xC6, 0x5E,
+ 0x0E, 0xF6, 0x96, 0x35, 0x90, 0xAF, 0x3B, 0x9D,
+ 0x4D, 0x6C, 0xE7, 0xF2, 0x4F, 0xC0, 0xBA, 0x57,
+ 0x92, 0x18, 0xB7, 0xF5, 0x1D, 0x06, 0x81, 0xF6,
+ 0xE3, 0xF4, 0x66, 0x8C, 0x33, 0x74, 0xBE, 0x64,
+ 0x8C, 0x18, 0xED, 0x7F, 0x68, 0x2A, 0xE4, 0xAF,
+ 0xF1, 0x02, 0x07, 0x51, 0x22, 0x96, 0xC8, 0x9E,
+ 0x23, 0x7F, 0x6A, 0xD7, 0x80, 0x0F, 0x2D, 0xFC,
+ 0xCC, 0xD0, 0x95, 0x86, 0x00, 0x2A, 0x77, 0xDD,
+ 0xA2, 0x60, 0x1E, 0x0F, 0x8E, 0x42, 0x44, 0x37,
+ 0x7E, 0x33, 0xC4, 0xE0, 0x04, 0x53, 0xF6, 0x3F,
+ 0xDD, 0x1D, 0x5E, 0x24, 0xDA, 0xAE, 0xEF, 0x06,
+ 0x06, 0x05, 0x13, 0x3A, 0x1E, 0xFF, 0xAD, 0xAD,
+ 0xEE, 0x0F, 0x6F, 0x05, 0xA5, 0xFB, 0x3B, 0xC3,
+ 0xDB, 0xA0, 0x20, 0xC1, 0x65, 0x8B, 0x39, 0xAB,
+ 0xC9, 0xEC, 0xA8, 0x31, 0x85, 0x6C, 0xD2, 0xE4,
+ 0x76, 0x77, 0x76, 0xD5, 0x81, 0x01, 0x73, 0x36,
+ 0x08, 0x8C, 0xC3, 0xD4, 0x70, 0x7A, 0xA3, 0xDF,
+ 0xAD, 0x3A, 0x00, 0x46, 0x88, 0x65, 0x10, 0xBE,
+ 0xD8, 0x1C, 0x19, 0x98, 0xE9, 0x29, 0xDD, 0x58,
+ 0x46, 0x31, 0xEB, 0x3D, 0xD0, 0x12, 0x02, 0x83,
+ 0x15, 0xDD, 0x70, 0x27, 0x0D, 0xB5, 0xBB, 0x0C,
+ 0xE3, 0xF1, 0x02, 0xF2, 0xD7, 0x1D, 0x17, 0x6D,
+ 0xDF, 0x2A, 0x42, 0x1F, 0x01, 0x5C, 0x68, 0xB1,
+ 0x64, 0x74, 0xCE, 0x74, 0xB1, 0x3C, 0x2F, 0x43,
+ 0x5F, 0xB7, 0x7E, 0x3E, 0x6F, 0xE3, 0xDC, 0x03,
+ 0xD9, 0x0C, 0xDD, 0x42, 0x65, 0x7F, 0xEA, 0x69,
+ 0x6F, 0xDB, 0xD7, 0xFB, 0xFF, 0x4D, 0xB4, 0x48,
+ 0xFE, 0x0F, 0x59, 0x24, 0x8F, 0x13, 0xA8, 0x60,
+ 0xF7, 0x13, 0xE5, 0xB1, 0x8D, 0xB7, 0x70, 0xEE,
+ 0x82, 0x8F, 0xCF, 0x7E
+ },
+ .len_bits = 516 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x82, 0x8F, 0xCF, 0x7E
+ },
+ .len = 4,
+ .offset = 512,
+ },
+ .validDataLen = {
+ .len_bits = 516 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 516 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 512 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_snow_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 44 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A,
+ },
+ .len_bits = 44 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x95, 0x2E, 0x5A, 0xE1, 0x50, 0xB8, 0x59, 0x2A,
+ 0x9B, 0xA0, 0x38, 0xA9, 0x8E, 0x2F, 0xED, 0xAB,
+ 0xFD, 0xC8, 0x3B, 0x47, 0x46, 0x0B, 0x50, 0x16,
+ 0xEC, 0x88, 0x45, 0xB6, 0x05, 0xC7, 0x54, 0xF8,
+ 0xBD, 0x91, 0xAA, 0xB6, 0xA4, 0xDC, 0x64, 0xB4,
+ 0xCB, 0xEB, 0x97, 0x06, 0x1C, 0xB5, 0x72, 0x34
+ },
+ .len_bits = 48 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x1C, 0xB5, 0x72, 0x34
+ },
+ .len = 4,
+ .offset = 44,
+ },
+ .validDataLen = {
+ .len_bits = 48 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 48 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 44 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_zuc_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 52 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len_bits = 48 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x52, 0x11, 0xCD, 0xFF, 0xF8, 0x88, 0x61, 0x1E,
+ 0xF5, 0xD2, 0x8E, 0xEB, 0x2A, 0x49, 0x18, 0x1F,
+ 0xF4, 0xDA, 0x8B, 0x19, 0x60, 0x0B, 0x92, 0x9E,
+ 0x79, 0x2A, 0x5B, 0x0B, 0x7E, 0xC6, 0x22, 0x36,
+ 0x74, 0xA4, 0x6C, 0xBC, 0xF5, 0x25, 0x69, 0xAE,
+ 0xDA, 0x04, 0xB9, 0xAF, 0x16, 0x42, 0x0F, 0xCB,
+ 0x06, 0x7C, 0x1D, 0x29
+ },
+ .len_bits = 52 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x06, 0x7C, 0x1D, 0x29
+ },
+ .len = 4,
+ .offset = 48,
+ },
+ .validDataLen = {
+ .len_bits = 52 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 52 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 48 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_null_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 52 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len_bits = 48 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09,
+ 0x38, 0xB5, 0x54, 0xC0
+ },
+ .len_bits = 52 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x38, 0xB5, 0x54, 0xC0
+ },
+ .len = 4,
+ .offset = 48,
+ },
+ .validDataLen = {
+ .len_bits = 52 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 52 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 48 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_zuc_cipher_null_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .auth_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 73 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 77 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+ 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+ 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+ 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+ 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+ 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+ 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+ 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+ 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+ 0x00
+ },
+ .len_bits = 73 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+ 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+ 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+ 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+ 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+ 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+ 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+ 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+ 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+ 0x00, 0x24, 0xa8, 0x42, 0xb3
+ },
+ .len_bits = 77 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x24, 0xa8, 0x42, 0xb3
+ },
+ .len = 4,
+ .offset = 73,
+ },
+ .validDataLen = {
+ .len_bits = 77 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 77 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 73 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_aes_ctr_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_NULL,
+ .auth_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .auth = {
+ .len_bits = 48 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+ .cipher_key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16,
+ },
+ .cipher = {
+ .len_bits = 52 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len_bits = 48 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x91, 0x96, 0x28, 0xB4, 0x89, 0x74, 0xF6, 0x5E,
+ 0x98, 0x58, 0xA1, 0xD3, 0x0E, 0xE3, 0xFC, 0x39,
+ 0xDB, 0x36, 0xE4, 0x97, 0x74, 0x5B, 0x5E, 0xD4,
+ 0x1B, 0x8A, 0xC5, 0x9D, 0xDF, 0x96, 0x97, 0x5F,
+ 0x58, 0x4A, 0x75, 0x74, 0x27, 0x07, 0xF3, 0x7F,
+ 0xCE, 0x2C, 0x4A, 0x6C, 0xE5, 0x19, 0xE7, 0x8B,
+ 0xCB, 0x94, 0xD0, 0xAC
+ },
+ .len_bits = 52 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0xCB, 0x94, 0xD0, 0xAC
+ },
+ .len = 4,
+ .offset = 48,
+ },
+ .validDataLen = {
+ .len_bits = 52 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 52 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 48 << 3,
+ }
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_null_test_case_1 = {
+ .auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+ .auth_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .auth_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .auth = {
+ .len_bits = 512 << 3,
+ .offset_bits = 0,
+ },
+ .cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+ .cipher_key = {
+ .data = {
+ 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ },
+ .len = 16,
+ },
+ .cipher_iv = {
+ .data = {
+ },
+ .len = 0,
+ },
+ .cipher = {
+ .len_bits = 516 << 3,
+ .offset_bits = 0,
+ },
+ .plaintext = {
+ .data = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+ 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+ 0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+ 0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+ 0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+ 0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+ 0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+ 0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+ 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+ 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+ 0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+ 0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+ 0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+ 0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+ 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+ 0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+ 0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+ 0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+ 0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+ 0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+ 0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+ 0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+ 0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+ 0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+ 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+ 0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+ 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+ 0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+ 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+ 0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+ 0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+ 0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+ 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+ 0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+ 0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+ 0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+ 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+ 0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+ 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+ 0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+ },
+ .len_bits = 512 << 3,
+ },
+ .ciphertext = {
+ .data = {
+ 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+ 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+ 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+ 0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+ 0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+ 0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+ 0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+ 0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+ 0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+ 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+ 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+ 0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+ 0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+ 0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+ 0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+ 0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+ 0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+ 0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+ 0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+ 0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+ 0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+ 0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+ 0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+ 0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+ 0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+ 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+ 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+ 0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+ 0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+ 0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+ 0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+ 0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+ 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+ 0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+ 0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+ 0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+ 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+ 0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+ 0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+ 0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+ 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+ 0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+ 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+ 0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+ 0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75,
+ 0x4C, 0x77, 0x87, 0xA0
+ },
+ .len_bits = 516 << 3,
+ },
+ .digest_enc = {
+ .data = {
+ 0x4C, 0x77, 0x87, 0xA0
+ },
+ .len = 4,
+ .offset = 512,
+ },
+ .validDataLen = {
+ .len_bits = 516 << 3,
+ },
+ .validCipherLen = {
+ .len_bits = 516 << 3,
+ },
+ .validAuthLen = {
+ .len_bits = 512 << 3,
+ }
+};
+
+#endif /* TEST_CRYPTODEV_MIXED_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_mod_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_mod_test_vectors.h
new file mode 100644
index 000000000..c66f4b18b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_mod_test_vectors.h
@@ -0,0 +1,1070 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ * Copyright (c) 2019 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_MOD_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_MOD_TEST_VECTORS_H_
+
+#define DATA_SIZE 512
+
+struct modex_test_data {
+ enum rte_crypto_asym_xform_type xform_type;
+ const char *description;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } base;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } exponent;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } modulus;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } reminder;
+ uint16_t result_len;
+};
+struct modinv_test_data {
+ enum rte_crypto_asym_xform_type xform_type;
+ const char *description;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } base;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } modulus;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } inverse;
+ uint16_t result_len;
+};
+
+static const struct
+modex_test_data modex_test_case[] = {
+{
+ .description = "Modular Exponentiation "
+ "(mod=128, base=20, exp=3, res=128)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85,
+ 0xAE, 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD,
+ 0xA8, 0xEB, 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .exponent = {
+ .data = {
+ 0x01, 0x00, 0x01
+ },
+ .len = 3
+ },
+ .reminder = {
+ .data = {
+ 0x2C, 0x60, 0x75, 0x45, 0x98, 0x9D, 0xE0, 0x72,
+ 0xA0, 0x9D, 0x3A, 0x9E, 0x03, 0x38, 0x73, 0x3C,
+ 0x31, 0x83, 0x04, 0xFE, 0x75, 0x43, 0xE6, 0x17,
+ 0x5C, 0x01, 0x29, 0x51, 0x69, 0x33, 0x62, 0x2D,
+ 0x78, 0xBE, 0xAE, 0xC4, 0xBC, 0xDE, 0x7E, 0x2C,
+ 0x77, 0x84, 0xF2, 0xC5, 0x14, 0xB5, 0x2F, 0xF7,
+ 0xC5, 0x94, 0xEF, 0x86, 0x75, 0x75, 0xB5, 0x11,
+ 0xE5, 0x0E, 0x0A, 0x29, 0x76, 0xE2, 0xEA, 0x32,
+ 0x0E, 0x43, 0x77, 0x7E, 0x2C, 0x27, 0xAC, 0x3B,
+ 0x86, 0xA5, 0xDB, 0xC9, 0x48, 0x40, 0xE8, 0x99,
+ 0x9A, 0x0A, 0x3D, 0xD6, 0x74, 0xFA, 0x2E, 0x2E,
+ 0x5B, 0xAF, 0x8C, 0x99, 0x44, 0x2A, 0x67, 0x38,
+ 0x27, 0x41, 0x59, 0x9D, 0xB8, 0x51, 0xC9, 0xF7,
+ 0x43, 0x61, 0x31, 0x6E, 0xF1, 0x25, 0x38, 0x7F,
+ 0xAE, 0xC6, 0xD0, 0xBB, 0x29, 0x76, 0x3F, 0x46,
+ 0x2E, 0x1B, 0xE4, 0x67, 0x71, 0xE3, 0x87, 0x5A
+ },
+ .len = 128
+ },
+ .modulus = {
+ .data = {
+ 0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00, 0x0a,
+ 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5, 0xce,
+ 0x47, 0x8a, 0xc3, 0x80, 0xf4, 0x7d, 0x4a, 0xa2,
+ 0x62, 0xfd, 0x61, 0x7f, 0xb5, 0xa8, 0xde, 0x0a,
+ 0x17, 0x97, 0xa0, 0xbf, 0xdf, 0x56, 0x5a, 0x3d,
+ 0x51, 0x56, 0x4f, 0x70, 0x70, 0x3f, 0x63, 0x6a,
+ 0x44, 0x5b, 0xad, 0x84, 0x0d, 0x3f, 0x27, 0x6e,
+ 0x3b, 0x34, 0x91, 0x60, 0x14, 0xb9, 0xaa, 0x72,
+ 0xfd, 0xa3, 0x64, 0xd2, 0x03, 0xa7, 0x53, 0x87,
+ 0x9e, 0x88, 0x0b, 0xc1, 0x14, 0x93, 0x1a, 0x62,
+ 0xff, 0xb1, 0x5d, 0x74, 0xcd, 0x59, 0x63, 0x18,
+ 0x11, 0x3d, 0x4f, 0xba, 0x75, 0xd4, 0x33, 0x4e,
+ 0x23, 0x6b, 0x7b, 0x57, 0x44, 0xe1, 0xd3, 0x03,
+ 0x13, 0xa6, 0xf0, 0x8b, 0x60, 0xb0, 0x9e, 0xee,
+ 0x75, 0x08, 0x9d, 0x71, 0x63, 0x13, 0xcb, 0xa6,
+ 0x81, 0x92, 0x14, 0x03, 0x22, 0x2d, 0xde, 0x55
+ },
+ .len = 128
+ },
+ .result_len = 128
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=60, base=50, exp=40, res=60)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0x4F, 0xD8, 0x5C, 0xDB, 0x6D, 0xA2, 0xFA, 0x35,
+ 0x9D, 0xD7, 0x97, 0x10, 0x4B, 0x71, 0x5F, 0x53,
+ 0xE1, 0xC7, 0x09, 0x74, 0x88, 0xC8, 0x9D, 0x03,
+ 0xC0, 0x70, 0xE0, 0xBE, 0xE3, 0xF2, 0x2C, 0x01,
+ 0x85, 0xA6, 0x4E, 0x28, 0x6E, 0xD3, 0xB5, 0x18,
+ 0x58, 0x69, 0x07, 0xDA, 0x3A, 0x1B, 0x35, 0xCE,
+ 0xE6, 0xFA
+ },
+ .len = 50
+ },
+ .exponent = {
+ .data = {
+ 0x30, 0xA5, 0xD5, 0xF0, 0x42, 0x03, 0xC3, 0x2D,
+ 0x2F, 0x58, 0xA8, 0x5C, 0x21, 0x88, 0xDE, 0x82,
+ 0x36, 0x44, 0xC1, 0x5A, 0x87, 0x2C, 0x33, 0x19,
+ 0x4E, 0xCE, 0x3F, 0x87, 0xFF, 0x98, 0x4B, 0xFC,
+ 0x15, 0xC0, 0xBE, 0x9E, 0x8F, 0xF0, 0x6A, 0x62
+ },
+ .len = 40
+ },
+ .reminder = {
+ .data = {
+ 0x59, 0x3D, 0x92, 0xE4, 0xE6, 0x9B, 0x5D, 0x97,
+ 0x21, 0xE6, 0x06, 0x60, 0x8B, 0x66, 0x8F, 0xF3,
+ 0x63, 0xAE, 0x3A, 0x64, 0x7F, 0xCA, 0xDE, 0x4A,
+ 0xE5, 0x49, 0xA2, 0x90, 0x0F, 0xAE, 0x13, 0x10,
+ 0xC2, 0x5B, 0x97, 0xED, 0x86, 0x97, 0x16, 0xE2,
+ 0x01, 0xF6, 0x7A, 0xF1, 0x7B, 0x4B, 0xC7, 0x7D,
+ 0x6B, 0xD7, 0x98, 0xE5, 0x9B, 0x75, 0x1A, 0x6B,
+ 0xD6, 0x6E, 0xA3, 0x4E
+ },
+ .len = 60
+ },
+ .modulus = {
+ .data = {
+ 0xF8, 0x04, 0x0D, 0xD5, 0x09, 0x6C, 0x78, 0x06,
+ 0x7D, 0x28, 0x77, 0xA4, 0x0E, 0xA5, 0x49, 0xE7,
+ 0x6D, 0xC9, 0x97, 0xD3, 0xC0, 0x7F, 0x82, 0xC6,
+ 0x75, 0x51, 0x72, 0xAF, 0x8C, 0x77, 0x97, 0xD0,
+ 0xA1, 0x85, 0x54, 0xC0, 0x78, 0x86, 0xD6, 0x40,
+ 0x7A, 0x6B, 0xB3, 0xD7, 0x07, 0xCA, 0x27, 0xA3,
+ 0x66, 0xB9, 0x98, 0x22, 0xC4, 0x54, 0x18, 0x07,
+ 0x65, 0x76, 0x0F, 0x5A
+ },
+ .len = 60
+ },
+ .result_len = 60
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=8, base=65, exp=17, res=8)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0x25, 0x74, 0x41, 0xCE, 0xFA, 0x5C, 0x07, 0x2A,
+ 0xD1, 0x74, 0xF3, 0x3D, 0xE1, 0xCC, 0xC3, 0x18,
+ 0x7E, 0x4A, 0x21, 0x9F, 0x97, 0xA3, 0x26, 0x85,
+ 0x85, 0xD9, 0x9B, 0xE3, 0xBA, 0xB3, 0x70, 0xC9,
+ 0x26, 0x68, 0xE4, 0xB7, 0x4C, 0x88, 0x48, 0xC1,
+ 0x6B, 0xC6, 0x3C, 0x00, 0x8C, 0x6B, 0xC6, 0x11,
+ 0xD0, 0xD6, 0x61, 0x5D, 0xEC, 0xAA, 0xBA, 0x3B,
+ 0x7D, 0xB3, 0x0D, 0x3F, 0xA5, 0x4D, 0xEE, 0xE4,
+ 0xAC
+ },
+ .len = 65
+ },
+ .exponent = {
+ .data = {
+ 0x1C, 0x54, 0x2F, 0xCA, 0xDE, 0x4F, 0x17, 0x38,
+ 0x69, 0x87, 0xB4, 0xFF, 0x3A, 0x6C, 0x82, 0x70,
+ 0x53
+ },
+ .len = 17
+ },
+ .reminder = {
+ .data = {
+ 0x52, 0x06, 0x1A, 0x35, 0x70, 0x33, 0x78, 0x45
+ },
+ .len = 8
+ },
+ .modulus = {
+ .data = {
+ 0x6B, 0x6D, 0xFA, 0xCB, 0x09, 0x5D, 0x9C, 0xFD
+ },
+ .len = 8
+ },
+ .result_len = 8
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=100, base=150, exp=192, res=100)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0xC1, 0xA1, 0x04, 0xE4, 0x4D, 0x4A, 0xD3, 0x5C,
+ 0xB3, 0xD0, 0x16, 0x51, 0xA7, 0xF4, 0x82, 0x6C,
+ 0x22, 0xDD, 0x4D, 0xAA, 0x70, 0x30, 0x25, 0xA7,
+ 0xFA, 0xA9, 0xF2, 0x20, 0x55, 0x9B, 0xEA, 0x26,
+ 0xF6, 0xB5, 0xF8, 0x9C, 0x46, 0x21, 0x85, 0x0E,
+ 0x38, 0x73, 0x01, 0xC6, 0x72, 0x67, 0x9B, 0x49,
+ 0xCE, 0x48, 0xB7, 0x4A, 0xEE, 0x08, 0x21, 0x26,
+ 0xF3, 0x21, 0x77, 0xE7, 0x3C, 0x77, 0xF4, 0x0A,
+ 0x82, 0xC8, 0x16, 0x94, 0x6C, 0xBF, 0xA8, 0xD8,
+ 0x8B, 0x7D, 0x27, 0x60, 0xAC, 0x06, 0x69, 0x7E,
+ 0x46, 0x2C, 0xE2, 0xD1, 0x13, 0x50, 0x7D, 0xCE,
+ 0x4D, 0xC4, 0x5D, 0x81, 0xFB, 0x6B, 0x11, 0x4A,
+ 0x2D, 0xA2, 0x03, 0x55, 0x77, 0x8C, 0x3D, 0xA1,
+ 0xAD, 0xBE, 0x9C, 0x72, 0xE5, 0xA5, 0xFB, 0x49,
+ 0x5F, 0x13, 0x48, 0xC7, 0xAC, 0xD1, 0x0F, 0x5E,
+ 0xDF, 0x9C, 0xC7, 0xF5, 0x19, 0xFD, 0xC5, 0x77,
+ 0x27, 0x8D, 0xC4, 0x1D, 0x90, 0x8C, 0x20, 0x96,
+ 0xC8, 0x6A, 0x0D, 0x2F, 0xE2, 0x8B, 0xB0, 0x58,
+ 0xF8, 0xC4, 0x31, 0x0A, 0x17, 0x11
+ },
+ .len = 150
+ },
+ .exponent = {
+ .data = {
+ 0xC6, 0x20, 0x99, 0xD9, 0xBC, 0xE2, 0xAD, 0x74,
+ 0x11, 0x6F, 0x74, 0x14, 0x72, 0xB8, 0x09, 0xCB,
+ 0x5C, 0x74, 0x11, 0x21, 0x17, 0x84, 0x02, 0xDC,
+ 0x70, 0x59, 0x20, 0x79, 0x40, 0x7B, 0x0E, 0x52,
+ 0xAD, 0x00, 0x38, 0x4F, 0x5A, 0xE5, 0x0D, 0x28,
+ 0xB5, 0xF8, 0xDC, 0x54, 0x92, 0xB2, 0xB0, 0xA8,
+ 0xE8, 0x35, 0x1B, 0x63, 0x0D, 0x6A, 0x50, 0x8D,
+ 0xE1, 0x3E, 0x7A, 0xDD, 0x42, 0x7A, 0xD0, 0xB4,
+ 0x9D, 0x63, 0x36, 0x03, 0xC0, 0x9B, 0xA0, 0x91,
+ 0x8B, 0xBC, 0x45, 0x53, 0x93, 0x2C, 0xFC, 0xDD,
+ 0x4F, 0xBD, 0x96, 0x0B, 0x63, 0xEB, 0xEF, 0x50,
+ 0xAC, 0x99, 0x45, 0xA7, 0x0D, 0xC6, 0xEA, 0x98,
+ 0xBC, 0xD7, 0x63, 0x56, 0x8C, 0x75, 0x68, 0xAE,
+ 0xF0, 0xB4, 0x66, 0xA0, 0x4D, 0xC5, 0x71, 0xB9,
+ 0x4E, 0xCB, 0xF6, 0xCA, 0xC9, 0x1B, 0x3B, 0x55,
+ 0x91, 0x39, 0x25, 0xBD, 0x98, 0xAA, 0xDA, 0xF2,
+ 0x8A, 0xCB, 0x8E, 0x56, 0x09, 0xBF, 0xC4, 0x1D,
+ 0xFA, 0x23, 0x48, 0xF6, 0x9A, 0xD2, 0xD3, 0x2B,
+ 0xED, 0x60, 0x9B, 0x4B, 0x63, 0xD8, 0x8C, 0x6A,
+ 0x28, 0xA3, 0x4C, 0x85, 0x43, 0x4D, 0x5C, 0x4A,
+ 0xA7, 0xA9, 0x9F, 0x7E, 0x13, 0x5B, 0x36, 0xED,
+ 0xD9, 0x53, 0xBE, 0x12, 0xFF, 0x17, 0x9F, 0x70,
+ 0xA4, 0xD2, 0x42, 0x72, 0x70, 0x51, 0x70, 0x3F,
+ 0x5A, 0xBA, 0x33, 0x0E, 0xBB, 0x4C, 0xA0, 0x4A
+ },
+ .len = 192
+ },
+ .reminder = {
+ .data = {
+ 0x07, 0x5E, 0x28, 0x4F, 0xD1, 0xEA, 0x5C, 0x1D,
+ 0xF8, 0xBF, 0x29, 0xF0, 0x63, 0xCC, 0xF7, 0x6D,
+ 0x99, 0x67, 0xCE, 0xE3, 0x05, 0x16, 0x16, 0x8C,
+ 0x3A, 0x07, 0xC0, 0x63, 0x70, 0xB9, 0x1A, 0x24,
+ 0xED, 0xE9, 0xF0, 0xEE, 0xD9, 0xAB, 0x18, 0xD4,
+ 0x59, 0xB4, 0xD2, 0x77, 0x44, 0x94, 0x72, 0xFE,
+ 0x19, 0x26, 0x50, 0x47, 0x77, 0xAD, 0x0A, 0x45,
+ 0x76, 0x4B, 0x22, 0xDB, 0x05, 0x13, 0x67, 0x40,
+ 0x9A, 0x36, 0x6C, 0x5E, 0xE8, 0xED, 0x40, 0x60,
+ 0x86, 0x40, 0x2F, 0x30, 0x9E, 0x4B, 0x61, 0x73,
+ 0x2E, 0x76, 0x8A, 0xB0, 0x49, 0x04, 0x1A, 0x82,
+ 0xB7, 0xEF, 0xB2, 0xB5, 0xB4, 0xE0, 0x87, 0xF0,
+ 0xB4, 0x53, 0xB2, 0xBE
+ },
+ .len = 100
+ },
+ .modulus = {
+ .data = {
+ 0x54, 0x58, 0x5C, 0xBA, 0xAE, 0xC1, 0xB4, 0x46,
+ 0x50, 0xAF, 0xD0, 0xA6, 0x03, 0x9D, 0x74, 0x84,
+ 0x6F, 0x89, 0x07, 0xA6, 0x63, 0xE7, 0x34, 0xB2,
+ 0x55, 0x0E, 0xD5, 0x42, 0xC9, 0xBF, 0xD1, 0x89,
+ 0x54, 0x0B, 0x76, 0xF7, 0x0E, 0xA1, 0x42, 0x02,
+ 0x72, 0xDC, 0x28, 0x5A, 0x68, 0x10, 0xA0, 0x84,
+ 0xA4, 0x72, 0x4D, 0x40, 0x69, 0xBC, 0x18, 0xC9,
+ 0x92, 0x69, 0xB8, 0x52, 0x2A, 0xB1, 0xA3, 0x43,
+ 0x80, 0xA9, 0x55, 0x78, 0xEA, 0xD9, 0x54, 0xF4,
+ 0x3A, 0xDD, 0x24, 0x4E, 0x22, 0x9D, 0x89, 0x40,
+ 0x8F, 0x50, 0xA5, 0xF5, 0x0F, 0xFA, 0x38, 0xBB,
+ 0xE8, 0xD7, 0x21, 0x6B, 0xEA, 0xB1, 0x28, 0x48,
+ 0xEB, 0x75, 0xB1, 0xC7
+ },
+ .len = 100
+ },
+ .result_len = 100
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=255, base=20, exp=10, res=255)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0xD8, 0x21, 0xD2, 0x76, 0xAE, 0x01, 0x62, 0xD8,
+ 0x8C, 0x80, 0x01, 0x25, 0xC7, 0xE8, 0x4E, 0x0F,
+ 0x7F, 0x23, 0xFE, 0xBB
+ },
+ .len = 20
+ },
+ .exponent = {
+ .data = {
+ 0xE5, 0xCE, 0x50, 0xE8, 0x97, 0x32, 0xFB, 0x5C,
+ 0xFC, 0x62
+ },
+ .len = 10
+ },
+ .reminder = {
+ .data = {
+ 0x1F, 0xA8, 0xAC, 0x32, 0x6C, 0x20, 0xBE, 0x1D,
+ 0x88, 0xE9, 0x94, 0x7E, 0xDE, 0xB5, 0x15, 0xA5,
+ 0xF3, 0x45, 0x77, 0xB3, 0x3E, 0xDD, 0xDD, 0xAE,
+ 0xEA, 0xAE, 0x32, 0x81, 0x37, 0xAE, 0x26, 0xC5,
+ 0x6F, 0x3A, 0x75, 0x1F, 0x4F, 0xA2, 0xA3, 0x8B,
+ 0xDC, 0x52, 0x3C, 0xD5, 0x42, 0x00, 0x58, 0x37,
+ 0xB3, 0x5B, 0xC9, 0x78, 0xFA, 0x48, 0xFE, 0x4B,
+ 0x81, 0xFB, 0x4C, 0x5D, 0x9F, 0x5E, 0x4F, 0x56,
+ 0x30, 0x79, 0x71, 0x1E, 0xC5, 0x8E, 0xC2, 0x2E,
+ 0x9D, 0x18, 0xD8, 0x34, 0x0E, 0xDB, 0xCB, 0x02,
+ 0xA7, 0x37, 0x00, 0x44, 0x57, 0x2A, 0x11, 0x85,
+ 0x81, 0x06, 0x28, 0xB4, 0x95, 0x79, 0xE2, 0x60,
+ 0x39, 0x66, 0x34, 0x2F, 0x19, 0xD4, 0x42, 0x70,
+ 0xA8, 0xE9, 0x51, 0xBC, 0xB4, 0x04, 0xD6, 0x4B,
+ 0xE1, 0x4A, 0xEE, 0x6F, 0x69, 0xD7, 0x82, 0x07,
+ 0x59, 0xD6, 0xB0, 0xAC, 0x22, 0x28, 0xB8, 0x70,
+ 0x5F, 0xD2, 0x0D, 0x15, 0x6D, 0xED, 0xEB, 0x8A,
+ 0xD5, 0x64, 0x16, 0x7C, 0x12, 0x25, 0x76, 0xFD,
+ 0x8A, 0x8D, 0xC5, 0xEA, 0xF8, 0xA9, 0x04, 0x65,
+ 0x58, 0x6D, 0x67, 0x2F, 0xA7, 0x3E, 0x2C, 0x96,
+ 0x55, 0x11, 0xAA, 0x10, 0xE0, 0x1B, 0x0F, 0x1C,
+ 0x89, 0x10, 0x7C, 0x63, 0xCB, 0x0B, 0xB8, 0x1C,
+ 0x49, 0x16, 0xC1, 0xB3, 0xA5, 0x57, 0x87, 0x4F,
+ 0x80, 0x8B, 0x18, 0xF0, 0x46, 0xCE, 0xE4, 0x95,
+ 0x2F, 0x9C, 0xE7, 0xB7, 0x40, 0x1C, 0xB4, 0xA3,
+ 0xD4, 0x30, 0x9C, 0xFD, 0x95, 0x35, 0x57, 0x10,
+ 0x50, 0x40, 0xDA, 0x47, 0x8E, 0x21, 0xAE, 0x05,
+ 0xF8, 0xA8, 0x72, 0xA5, 0x68, 0xE1, 0xA2, 0xAB,
+ 0x36, 0x0D, 0x4B, 0xDB, 0x7B, 0xBF, 0x7F, 0x51,
+ 0x51, 0xC9, 0xBB, 0x3F, 0xF7, 0x76, 0x45, 0x78,
+ 0xAC, 0x3F, 0x56, 0xF4, 0x27, 0x7E, 0xEF, 0x02,
+ 0xED, 0x41, 0x15, 0xDB, 0xE4, 0x81, 0x59
+ },
+ .len = 255
+ },
+ .modulus = {
+ .data = {
+ 0x71, 0x3C, 0x6C, 0x7A, 0x19, 0x31, 0xF8, 0x94,
+ 0xC9, 0xAA, 0x25, 0x69, 0xA7, 0xF2, 0x28, 0x70,
+ 0x84, 0x5D, 0xEC, 0x40, 0xC8, 0xF9, 0xC5, 0x79,
+ 0xF9, 0x87, 0xD1, 0xA0, 0xC1, 0x5A, 0x06, 0xE4,
+ 0x65, 0xB8, 0x29, 0x0B, 0x2B, 0xFE, 0x67, 0xF0,
+ 0x91, 0x96, 0xE1, 0xCD, 0x5A, 0xCE, 0x44, 0xA3,
+ 0x4F, 0xE8, 0xBE, 0xC6, 0xA3, 0x0A, 0xCB, 0xF5,
+ 0x7D, 0x8B, 0x9B, 0x2F, 0x4E, 0xC9, 0x54, 0x48,
+ 0xA4, 0xC2, 0x09, 0xCE, 0xA5, 0x93, 0x1F, 0x43,
+ 0xC2, 0xCE, 0xFB, 0xBB, 0x69, 0x29, 0x03, 0x74,
+ 0xD6, 0x25, 0x47, 0x6B, 0xAC, 0x4E, 0x44, 0x8C,
+ 0x39, 0x2F, 0xB2, 0xDD, 0x15, 0x1B, 0xA3, 0x3D,
+ 0xA4, 0x0C, 0xFF, 0xCB, 0x05, 0xC2, 0x81, 0x97,
+ 0x16, 0xE2, 0xAC, 0x8A, 0xF3, 0xED, 0x80, 0xA4,
+ 0xC5, 0xFC, 0xF5, 0x6C, 0x4B, 0xBB, 0x05, 0x91,
+ 0xD4, 0x0F, 0xDA, 0x70, 0x7C, 0x9A, 0xA1, 0x63,
+ 0x15, 0xEE, 0xBB, 0x17, 0xE6, 0x20, 0x50, 0x74,
+ 0x36, 0x9C, 0xA1, 0x10, 0x29, 0x22, 0xFB, 0x7E,
+ 0x2A, 0x08, 0xF3, 0x07, 0xEA, 0xCD, 0x2C, 0x50,
+ 0x18, 0x15, 0x66, 0x87, 0x74, 0x19, 0x11, 0x2B,
+ 0x77, 0x85, 0xA0, 0x57, 0xA7, 0xEB, 0x6E, 0x15,
+ 0x15, 0x0D, 0xA4, 0x18, 0x5D, 0x54, 0x13, 0xE3,
+ 0x33, 0x12, 0x8D, 0xA3, 0xEF, 0x54, 0xE6, 0x1E,
+ 0xDB, 0x8F, 0x3D, 0x02, 0x3C, 0xCB, 0x34, 0x93,
+ 0x31, 0x1D, 0x4D, 0x3E, 0x9C, 0x22, 0x04, 0xD1,
+ 0x19, 0x53, 0x45, 0xE5, 0xBF, 0xF8, 0x70, 0x1A,
+ 0xEA, 0x52, 0x93, 0x2A, 0x26, 0x8A, 0x1E, 0x47,
+ 0xCE, 0x83, 0x5B, 0x35, 0x9A, 0xD2, 0x75, 0xC6,
+ 0xC6, 0x20, 0x84, 0x9F, 0x74, 0x69, 0x69, 0xB8,
+ 0x29, 0xD8, 0xA4, 0x70, 0x91, 0x42, 0x06, 0x25,
+ 0x38, 0xCB, 0x42, 0x75, 0x52, 0xEF, 0xB8, 0x64,
+ 0x4F, 0xC5, 0x7C, 0xC4, 0x09, 0xDB, 0x12
+ },
+ .len = 255
+ },
+ .result_len = 255
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=112, base=257, exp=43, res=112)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0x53, 0x63, 0xB0, 0x3A, 0x30, 0xDE, 0x07, 0xBC,
+ 0xE4, 0x4B, 0x52, 0x37, 0x9C, 0xD8, 0x5A, 0xCD,
+ 0x03, 0xE1, 0xEA, 0x6D, 0xDE, 0x4C, 0x19, 0xE6,
+ 0xA2, 0x0F, 0xAE, 0x56, 0xCD, 0xB2, 0xB6, 0x5B,
+ 0x31, 0xF5, 0x41, 0x48, 0x8D, 0xA2, 0xC7, 0x0C,
+ 0x19, 0x32, 0x6D, 0x58, 0x10, 0xD5, 0xF0, 0x64,
+ 0xF9, 0xF5, 0xD7, 0xFE, 0x37, 0x4A, 0xD8, 0xE3,
+ 0xBF, 0xDF, 0xCB, 0x45, 0xD5, 0xBF, 0xB9, 0x2A,
+ 0x60, 0xF8, 0x52, 0xB0, 0xB5, 0x22, 0x76, 0xBD,
+ 0xD3, 0x0D, 0xD4, 0xE1, 0x42, 0xC4, 0x8C, 0x47,
+ 0x2D, 0x04, 0x25, 0x1B, 0xFB, 0x21, 0xFD, 0x80,
+ 0xC0, 0xCE, 0x9D, 0x32, 0x76, 0x8E, 0x18, 0x28,
+ 0xDC, 0x0F, 0x44, 0x37, 0xF8, 0x61, 0x45, 0x93,
+ 0xD3, 0x62, 0x21, 0xEE, 0x8B, 0x89, 0x8B, 0xAF,
+ 0x8B, 0xE9, 0xA5, 0xD2, 0x00, 0xF5, 0xFF, 0xE6,
+ 0xE0, 0x56, 0x9D, 0x41, 0x13, 0xBC, 0xD6, 0x6E,
+ 0xC9, 0xE8, 0xE8, 0xC7, 0x61, 0x00, 0x7D, 0x91,
+ 0x59, 0xAC, 0x6A, 0x24, 0x86, 0x3C, 0x50, 0xFB,
+ 0x49, 0xC4, 0xB9, 0x41, 0xCD, 0xF0, 0xD9, 0xE7,
+ 0xE1, 0x54, 0x3F, 0x17, 0x3B, 0xC7, 0x12, 0x20,
+ 0x6E, 0xC5, 0x80, 0x11, 0xA5, 0x78, 0x72, 0xCA,
+ 0xBC, 0x90, 0xB7, 0xC5, 0xFF, 0x78, 0xE5, 0x71,
+ 0x62, 0x4C, 0xCC, 0x6C, 0xEA, 0x76, 0xE3, 0xB6,
+ 0x00, 0x54, 0x31, 0x72, 0x5A, 0xFE, 0x14, 0xC3,
+ 0x60, 0x3A, 0x79, 0x97, 0x26, 0x87, 0x69, 0x8D,
+ 0x44, 0x8E, 0x8B, 0xE0, 0xBC, 0x5C, 0x9F, 0xDE,
+ 0xD0, 0x90, 0xA2, 0x85, 0xC8, 0x3E, 0x7E, 0xA0,
+ 0x42, 0xE2, 0x3B, 0xEE, 0x0C, 0x59, 0x1E, 0x72,
+ 0x62, 0xA5, 0xEE, 0x20, 0xE0, 0xFE, 0x0D, 0xD3,
+ 0x9F, 0xA9, 0x84, 0xBC, 0xD0, 0x6E, 0x5E, 0xC2,
+ 0x0B, 0xF2, 0xAE, 0xB6, 0xE6, 0xC6, 0x88, 0xF9,
+ 0x51, 0xF8, 0x02, 0x08, 0xC6, 0x99, 0x73, 0xF2,
+ 0x36
+ },
+ .len = 257
+ },
+ .exponent = {
+ .data = {
+ 0xCA, 0x5C, 0x73, 0xF7, 0x8B, 0x1F, 0x95, 0xE4,
+ 0x0E, 0x9B, 0x47, 0xDC, 0x03, 0x96, 0x75, 0xB4,
+ 0x48, 0x74, 0x73, 0xBE, 0xF8, 0x92, 0x80, 0xE4,
+ 0x93, 0x5D, 0x87, 0x7D, 0x74, 0xF7, 0x45, 0xEF,
+ 0x8E, 0x53, 0x9C, 0x03, 0xB0, 0xD6, 0xF3, 0xBF,
+ 0x86, 0xB2, 0xCD
+ },
+ .len = 43
+ },
+ .reminder = {
+ .data = {
+ 0x01, 0x0E, 0x8C, 0x1B, 0x19, 0xF6, 0xB0, 0x0D,
+ 0x8D, 0xFF, 0x12, 0x74, 0xF0, 0xD0, 0xB1, 0xA2,
+ 0x49, 0xA4, 0xA3, 0x9C, 0x4D, 0xFA, 0xA7, 0xB7,
+ 0x6E, 0x45, 0xCC, 0x0D, 0x75, 0xC7, 0xF7, 0x99,
+ 0x1F, 0x01, 0x44, 0x7B, 0xF2, 0xF9, 0x73, 0x67,
+ 0x75, 0xD9, 0x4C, 0x2F, 0xA9, 0xB4, 0x59, 0x9E,
+ 0xF9, 0x2C, 0xB9, 0x14, 0x5D, 0x5C, 0x18, 0x72,
+ 0xEC, 0x27, 0x1A, 0x2D, 0xFB, 0xDA, 0xEB, 0x2F,
+ 0x98, 0xA9, 0xC2, 0x01, 0x75, 0x7A, 0x27, 0x07,
+ 0x94, 0x71, 0x3F, 0x90, 0xDF, 0x56, 0x6F, 0x23,
+ 0x47, 0x12, 0xAD, 0x32, 0x7A, 0xBC, 0x91, 0x36,
+ 0x43, 0xD2, 0x88, 0x3D, 0x2C, 0x31, 0x85, 0xE6,
+ 0x22, 0x2E, 0xCF, 0x53, 0x87, 0x0D, 0xAE, 0x72,
+ 0x31, 0x21, 0x52, 0x0C, 0xDF, 0xAC, 0xEA, 0x57
+ },
+ .len = 112
+ },
+ .modulus = {
+ .data = {
+ 0x20, 0x7E, 0x78, 0xFC, 0x54, 0x40, 0x47, 0xED,
+ 0x7B, 0x26, 0x21, 0x94, 0x6D, 0x9C, 0xDC, 0xB7,
+ 0x7C, 0xB8, 0xDE, 0x57, 0x3C, 0x64, 0x47, 0x50,
+ 0xDB, 0x92, 0x0A, 0x5A, 0x85, 0x77, 0x84, 0xE3,
+ 0xC7, 0xEA, 0x33, 0xA2, 0x63, 0xDA, 0x63, 0xE3,
+ 0xDF, 0x07, 0x32, 0x85, 0xDC, 0xC3, 0xF0, 0x7C,
+ 0xD8, 0x44, 0xC4, 0xDE, 0x2C, 0xB7, 0x91, 0xAE,
+ 0xCD, 0xA2, 0xB3, 0x6B, 0x43, 0x04, 0x88, 0xBE,
+ 0x3B, 0x50, 0xE1, 0x88, 0xD0, 0x20, 0x04, 0x36,
+ 0xA4, 0xA0, 0xB0, 0x3B, 0x61, 0x9B, 0x83, 0xDB,
+ 0x05, 0x77, 0x5A, 0x5E, 0x87, 0xA6, 0xBE, 0x6A,
+ 0x2A, 0xB4, 0x30, 0x10, 0x8D, 0x3B, 0xBC, 0x84,
+ 0x9E, 0xB2, 0x21, 0x7E, 0xAC, 0x67, 0x94, 0x9F,
+ 0xF1, 0x32, 0x3C, 0xF0, 0x94, 0x83, 0xF8, 0x19
+ },
+ .len = 112
+ },
+ .result_len = 112
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=299, base=240, exp=321, res=299)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0xAF, 0xE4, 0xCF, 0x9F, 0x7C, 0x20, 0x72, 0xE9,
+ 0x50, 0x2E, 0xE5, 0xE4, 0xEF, 0x80, 0x28, 0xB3,
+ 0x3A, 0x92, 0xAC, 0xCD, 0xF1, 0x6B, 0x7D, 0x83,
+ 0x78, 0x4E, 0x9B, 0x30, 0x1E, 0xF4, 0x11, 0x15,
+ 0x49, 0xAC, 0x06, 0xA2, 0x92, 0xB9, 0x91, 0x1B,
+ 0xE8, 0xC8, 0xBC, 0x8A, 0x6F, 0xB2, 0xB8, 0x7C,
+ 0xC5, 0xD3, 0x68, 0x60, 0xA4, 0x37, 0x7A, 0x6E,
+ 0x3A, 0x1C, 0xAE, 0xAC, 0x70, 0x7B, 0x03, 0xE0,
+ 0xDC, 0x7D, 0x51, 0x2E, 0x04, 0xC1, 0xD4, 0xA8,
+ 0x5A, 0xE1, 0xE8, 0xAD, 0x83, 0x0C, 0x0C, 0x2D,
+ 0x93, 0x8A, 0x07, 0x25, 0xC6, 0xE1, 0xAB, 0xD7,
+ 0x2F, 0xC4, 0x14, 0x2E, 0x68, 0x89, 0xA7, 0xEA,
+ 0x4E, 0x7B, 0xC4, 0x05, 0xD4, 0xB7, 0xC1, 0x9B,
+ 0x9D, 0x8D, 0x58, 0x33, 0xE3, 0xB0, 0x58, 0xD8,
+ 0xCF, 0x6D, 0xA9, 0xC6, 0x96, 0xE3, 0x6E, 0xAA,
+ 0x23, 0x17, 0x19, 0x74, 0xE0, 0x7B, 0x50, 0x7A,
+ 0x57, 0x49, 0xFD, 0xFA, 0x3E, 0x7D, 0xF9, 0xB6,
+ 0x30, 0x5F, 0x1C, 0xE4, 0x5F, 0xC7, 0x3D, 0x5B,
+ 0x9E, 0xF5, 0xB6, 0x2F, 0xEA, 0xCF, 0x31, 0x35,
+ 0xC0, 0x60, 0xDE, 0x18, 0xC5, 0x0D, 0xBB, 0xC5,
+ 0xD1, 0x1D, 0x25, 0x7C, 0x8C, 0x35, 0x8A, 0x71,
+ 0xA8, 0x01, 0x9E, 0xEA, 0x8F, 0xD4, 0x5D, 0x52,
+ 0x86, 0xB7, 0x11, 0xC8, 0xF2, 0x97, 0xD0, 0x73,
+ 0x7C, 0xAB, 0xBB, 0xF4, 0x38, 0x4E, 0x48, 0xB5,
+ 0x70, 0x35, 0x2A, 0xC5, 0x14, 0x86, 0x2E, 0x64,
+ 0x91, 0x32, 0x37, 0x5E, 0x1A, 0x00, 0xAC, 0xF1,
+ 0xFC, 0x36, 0xEA, 0x7F, 0x50, 0xAF, 0x02, 0xEC,
+ 0x06, 0xE8, 0x55, 0x68, 0x0D, 0x9A, 0x58, 0x4D,
+ 0xBD, 0xB9, 0x62, 0x25, 0xAB, 0x94, 0xD7, 0x37,
+ 0xAD, 0xB4, 0x9F, 0xB4, 0x3A, 0x07, 0x45, 0x4B
+ },
+ .len = 240
+ },
+ .exponent = {
+ .data = {
+ 0xB1, 0xC2, 0x86, 0xFA, 0xE2, 0xF1, 0x71, 0x9C,
+ 0x61, 0x23, 0xAB, 0x37, 0xC6, 0x4F, 0x17, 0xFE,
+ 0x4D, 0xAC, 0x11, 0xD4, 0x36, 0xEE, 0xCB, 0xAE,
+ 0x46, 0x88, 0xA4, 0x92, 0x20, 0x6D, 0xDC, 0xF1,
+ 0xE4, 0x94, 0x72, 0x07, 0x64, 0x84, 0xF4, 0x83,
+ 0x31, 0x0C, 0x04, 0xF7, 0x5B, 0x68, 0xE6, 0x7A,
+ 0x6C, 0xCD, 0x6C, 0xBF, 0x03, 0x07, 0x5A, 0x91,
+ 0x37, 0x3A, 0x73, 0xFF, 0xB2, 0x11, 0x88, 0x39,
+ 0x19, 0xEB, 0x1C, 0x0E, 0x45, 0x99, 0xE6, 0x4E,
+ 0xE4, 0xB1, 0x57, 0xBE, 0xBE, 0x7A, 0xE8, 0x56,
+ 0x19, 0x92, 0xAC, 0xBD, 0x78, 0xCC, 0x54, 0xDC,
+ 0x2D, 0xE6, 0x7D, 0x61, 0xE1, 0x27, 0xA7, 0x43,
+ 0x46, 0x25, 0x51, 0x95, 0x47, 0xF6, 0xB1, 0x68,
+ 0x17, 0xE6, 0x21, 0xD4, 0x83, 0x1E, 0x32, 0xAF,
+ 0x22, 0xA4, 0x7D, 0x3D, 0x1F, 0xE6, 0x43, 0x96,
+ 0x64, 0xAB, 0xC5, 0x81, 0xBC, 0x79, 0x14, 0x54,
+ 0x02, 0x78, 0x79, 0x71, 0x58, 0xC2, 0x2E, 0x56,
+ 0x21, 0x6B, 0x40, 0xDB, 0x79, 0xD1, 0x80, 0x5D,
+ 0x61, 0xF0, 0x9F, 0x4A, 0xC3, 0x8F, 0xAC, 0x98,
+ 0x94, 0x88, 0x2C, 0xA5, 0xCB, 0x06, 0x47, 0x73,
+ 0x27, 0x71, 0xA8, 0x0C, 0xBD, 0xFD, 0x83, 0xBF,
+ 0xA2, 0xCC, 0x91, 0x63, 0x9D, 0xC5, 0x58, 0x50,
+ 0x53, 0x98, 0xA0, 0x5F, 0x0B, 0xDE, 0x15, 0x65,
+ 0xFB, 0x5D, 0xF1, 0x9C, 0xD0, 0xC3, 0x6B, 0x4D,
+ 0x31, 0x20, 0x2F, 0x4D, 0x4F, 0x9D, 0xEB, 0xCB,
+ 0xFC, 0xDA, 0x54, 0xC1, 0x57, 0x10, 0x0F, 0xFC,
+ 0xD2, 0xA7, 0x44, 0x0E, 0x89, 0x0D, 0x89, 0x56,
+ 0x1E, 0x40, 0x64, 0xFF, 0x9E, 0xB1, 0x5C, 0x9A,
+ 0x6E, 0xE5, 0xE9, 0x48, 0xAB, 0x27, 0x91, 0x9A,
+ 0x3B, 0x8D, 0xB6, 0xA0, 0xD6, 0xD8, 0x9B, 0xBD,
+ 0x0D, 0x1D, 0x90, 0xED, 0x54, 0xE1, 0x75, 0x5B,
+ 0x89, 0xE1, 0x0C, 0xC7, 0x42, 0xD7, 0x68, 0xCB,
+ 0x41, 0x59, 0xC1, 0x96, 0xD9, 0x77, 0x88, 0xF1,
+ 0x68, 0x90, 0xDA, 0xE0, 0xB7, 0x1E, 0x2C, 0xDB,
+ 0x27, 0x78, 0xC0, 0x15, 0x68, 0x9E, 0xF7, 0x48,
+ 0x45, 0xFC, 0x22, 0x5D, 0x2B, 0xFA, 0xC7, 0x81,
+ 0x26, 0x60, 0xF7, 0x50, 0xEE, 0xF9, 0x61, 0xF8,
+ 0x59, 0x28, 0x92, 0xEE, 0xD7, 0x92, 0x5F, 0x5E,
+ 0xA5, 0x5A, 0x4C, 0xC7, 0x89, 0x9B, 0x9F, 0x8F,
+ 0x01, 0x3B, 0x9D, 0x8D, 0xF8, 0x6B, 0xEE, 0x64,
+ 0x54
+ },
+ .len = 321
+ },
+ .reminder = {
+ .data = {
+ 0x4A, 0x18, 0x9C, 0xCB, 0x90, 0x71, 0x8E, 0xD3,
+ 0xCA, 0xEB, 0xF1, 0xE7, 0xE8, 0xB0, 0x19, 0x9C,
+ 0x05, 0x51, 0x29, 0x8C, 0xB9, 0x6D, 0x1B, 0x05,
+ 0xDC, 0x16, 0x91, 0x0E, 0x69, 0xF3, 0x76, 0x29,
+ 0x9D, 0x91, 0x21, 0x98, 0x56, 0x9A, 0x22, 0x20,
+ 0xDF, 0x75, 0x4D, 0x40, 0x51, 0x99, 0x6E, 0xEA,
+ 0x37, 0x22, 0xF4, 0x27, 0x04, 0x6E, 0xDC, 0xB2,
+ 0xF5, 0xF6, 0xF8, 0xD6, 0xA8, 0xB7, 0x2D, 0xB7,
+ 0x18, 0x44, 0xF7, 0x62, 0x91, 0x44, 0x97, 0x91,
+ 0x6C, 0x14, 0x7E, 0xEB, 0x00, 0xB0, 0x3F, 0x7D,
+ 0x7B, 0x4A, 0xD0, 0x04, 0xD2, 0xCC, 0x5A, 0x22,
+ 0xB5, 0x0E, 0xAB, 0x1A, 0xB0, 0xD7, 0x97, 0xDD,
+ 0xE5, 0x78, 0xA9, 0x97, 0xF4, 0xC7, 0xE0, 0x28,
+ 0x00, 0xF3, 0x48, 0xCA, 0x69, 0xD0, 0xE8, 0x43,
+ 0x12, 0x82, 0x24, 0xBA, 0x28, 0xBD, 0x8E, 0xCB,
+ 0xB1, 0x98, 0x08, 0xC5, 0x0F, 0xF2, 0xE9, 0xA2,
+ 0x6C, 0xCC, 0xA9, 0x21, 0xA6, 0x38, 0xAE, 0x88,
+ 0x35, 0x5E, 0xBB, 0xEF, 0x37, 0xAB, 0xDA, 0x07,
+ 0x5F, 0x0A, 0xB4, 0x29, 0x65, 0x24, 0x22, 0x6C,
+ 0x9E, 0xF5, 0x19, 0xA4, 0x8E, 0x5A, 0xFA, 0xFC,
+ 0x97, 0x8A, 0xE8, 0x2B, 0x6D, 0x4B, 0xD0, 0xFB,
+ 0x86, 0xB9, 0xE7, 0x2C, 0x08, 0x25, 0x17, 0x90,
+ 0x77, 0x54, 0xE0, 0xBA, 0x0F, 0x59, 0x6C, 0x8C,
+ 0x0E, 0xCF, 0x54, 0x55, 0x6C, 0xF1, 0x65, 0x48,
+ 0xCC, 0xF4, 0xAB, 0xA1, 0x91, 0x07, 0x29, 0xFC,
+ 0x46, 0xBC, 0x2C, 0x85, 0xA1, 0x0C, 0x8A, 0x77,
+ 0x7A, 0xC6, 0x01, 0x34, 0xCE, 0x92, 0x1D, 0x88,
+ 0x54, 0x23, 0x26, 0x9B, 0x6B, 0x80, 0x6D, 0x08,
+ 0x99, 0xAE, 0xC0, 0xF6, 0x45, 0x97, 0xAF, 0xCD,
+ 0x2F, 0x4A, 0x7E, 0xAB, 0xD8, 0x31, 0x48, 0xA1,
+ 0xEB, 0x5E, 0xD1, 0xC0, 0xE7, 0xD5, 0x37, 0x3D,
+ 0x03, 0xA3, 0x16, 0x09, 0xD4, 0xDE, 0xC3, 0x97,
+ 0x13, 0xB6, 0x67, 0x55, 0x8A, 0x71, 0x51, 0x66,
+ 0xF5, 0xA1, 0x3B, 0xE3, 0x49, 0x8D, 0x7C, 0x52,
+ 0xCD, 0xA7, 0x11, 0xDD, 0xE0, 0xA0, 0x5C, 0xD8,
+ 0xF8, 0xDF, 0x01, 0xC5, 0x61, 0x87, 0xB4, 0xDE,
+ 0x3E, 0x39, 0xED, 0xC3, 0x3F, 0x84, 0x70, 0x37,
+ 0xBA, 0xDB, 0x5B
+ },
+ .len = 299
+ },
+ .modulus = {
+ .data = {
+ 0x85, 0x04, 0x13, 0x7C, 0x4D, 0xBF, 0xC6, 0x25,
+ 0xD9, 0xAA, 0x1F, 0xED, 0x00, 0x69, 0xD7, 0x6C,
+ 0xB0, 0x46, 0x52, 0xA5, 0xF4, 0xF6, 0x55, 0x16,
+ 0x67, 0x52, 0x09, 0xF0, 0x28, 0xA7, 0x30, 0x22,
+ 0x34, 0xF1, 0xEA, 0xEB, 0x7C, 0x18, 0xEE, 0xAC,
+ 0x1A, 0xC1, 0xF5, 0x31, 0x7E, 0xA4, 0x4A, 0x0C,
+ 0xEA, 0xFE, 0x33, 0xDB, 0x49, 0x04, 0xFD, 0x33,
+ 0x3F, 0xB1, 0x41, 0x1F, 0xBD, 0x43, 0x71, 0xDE,
+ 0xB9, 0xA2, 0x4F, 0x20, 0x57, 0xAF, 0x27, 0x37,
+ 0x58, 0xA8, 0x51, 0x5D, 0x4E, 0xAB, 0x17, 0x1C,
+ 0x99, 0xD9, 0xB2, 0x0D, 0x21, 0xCA, 0x35, 0x52,
+ 0xF2, 0x4C, 0x7C, 0x79, 0x83, 0x2C, 0xF2, 0x87,
+ 0xC5, 0x58, 0x6E, 0x6E, 0x48, 0xFB, 0x32, 0x4D,
+ 0x1C, 0xDC, 0xE9, 0xDA, 0x9B, 0x77, 0x19, 0xD9,
+ 0x78, 0xE4, 0xF5, 0x3A, 0x49, 0x3D, 0x0D, 0x3D,
+ 0x10, 0x77, 0x0B, 0xC2, 0xE6, 0x66, 0x68, 0xFA,
+ 0x55, 0x99, 0x65, 0x5E, 0x55, 0x87, 0xCF, 0x3C,
+ 0x9C, 0x6C, 0x08, 0x09, 0x1F, 0x9C, 0xCB, 0x5E,
+ 0xE5, 0x19, 0x39, 0xA9, 0x2F, 0xF0, 0x49, 0x3D,
+ 0x7C, 0xB6, 0x7B, 0xA2, 0x93, 0xF1, 0x52, 0xD8,
+ 0x92, 0xDD, 0x56, 0x57, 0x8E, 0xE2, 0x5F, 0xA0,
+ 0x64, 0xB2, 0xC5, 0x0F, 0xB9, 0x89, 0xA6, 0x3F,
+ 0x54, 0x51, 0x2D, 0x01, 0x51, 0x78, 0x32, 0xE1,
+ 0xA7, 0x4D, 0x45, 0xC0, 0xD0, 0x6C, 0xE7, 0xCA,
+ 0xB2, 0x3F, 0x17, 0xD4, 0xB6, 0x58, 0x9B, 0xA8,
+ 0xBA, 0x2F, 0x3D, 0x1D, 0x6A, 0x73, 0x82, 0x2B,
+ 0x26, 0x2E, 0x7A, 0xEE, 0xEA, 0x41, 0x25, 0xFE,
+ 0xF0, 0xA2, 0x9C, 0x60, 0x35, 0xAD, 0x34, 0x30,
+ 0x55, 0x02, 0x6B, 0x06, 0xF4, 0xAD, 0x91, 0xA3,
+ 0xA2, 0x9C, 0x12, 0x8D, 0xDF, 0x2B, 0x3F, 0x0C,
+ 0x54, 0xCB, 0x98, 0xBA, 0xA1, 0x33, 0x70, 0xEF,
+ 0xF1, 0xEE, 0x15, 0xB7, 0xC6, 0x27, 0x47, 0x83,
+ 0x90, 0x58, 0x08, 0x16, 0x83, 0x94, 0xE9, 0x95,
+ 0x8B, 0x03, 0xD0, 0x3C, 0x45, 0xF8, 0x90, 0xC9,
+ 0xA7, 0x64, 0x76, 0xE8, 0x01, 0xA4, 0xA2, 0xAD,
+ 0x6F, 0x19, 0xCF, 0x38, 0x9A, 0xAB, 0x6E, 0xBE,
+ 0x79, 0xE4, 0x0F, 0xCE, 0x9C, 0x59, 0xF2, 0xF4,
+ 0x26, 0xAB, 0x0F
+ },
+ .len = 299
+ },
+ .result_len = 299
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=448, base=50, exp=40, res=448)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0x92, 0x45, 0x17, 0x7D, 0xD3, 0xF4, 0x2B, 0x93,
+ 0x8E, 0x1A, 0xFB, 0x1D, 0x13, 0x55, 0x53, 0x84,
+ 0x96, 0x3C, 0x39, 0xE0, 0xAF, 0x4A, 0xB4, 0xC9,
+ 0x16, 0x1F, 0xF4, 0x24, 0x65, 0xDD, 0xC3, 0x62,
+ 0x12, 0xAF, 0x86, 0x95, 0x0D, 0xDE, 0x28, 0x87,
+ 0x90, 0x11, 0xAA, 0x6E, 0x60, 0xCD, 0x54, 0xB7,
+ 0x48, 0x43
+ },
+ .len = 50
+ },
+ .exponent = {
+ .data = {
+ 0x22, 0xD9, 0x4D, 0x01, 0x2F, 0x50, 0x5D, 0xE1,
+ 0x01, 0xAA, 0xC6, 0xC6, 0xCD, 0x5D, 0x7E, 0x61,
+ 0x75, 0x0A, 0xDC, 0x06, 0x07, 0x4B, 0xBD, 0x29,
+ 0x33, 0x09, 0x91, 0xD4, 0x29, 0xEB, 0x52, 0x24,
+ 0x27, 0xC6, 0x83, 0x6D, 0x70, 0xA9, 0xC9, 0x11
+ },
+ .len = 40
+ },
+ .reminder = {
+ .data = {
+ 0x6B, 0x15, 0x66, 0xD3, 0x81, 0x3E, 0xCB, 0xA6,
+ 0xD8, 0x88, 0x9C, 0xFF, 0x8D, 0xBC, 0x91, 0x9F,
+ 0xDA, 0x09, 0x9E, 0x1B, 0xDB, 0x8A, 0x0F, 0xAC,
+ 0x19, 0x8E, 0xFE, 0x25, 0xA0, 0x66, 0x9D, 0x19,
+ 0x7C, 0xCB, 0x1D, 0xCF, 0x97, 0x41, 0xD2, 0x7A,
+ 0x0E, 0xAE, 0x8A, 0xD4, 0x24, 0x6D, 0xDF, 0xF4,
+ 0x0A, 0xCD, 0xE7, 0xF3, 0x21, 0x76, 0x22, 0xCA,
+ 0x31, 0x67, 0x91, 0x1B, 0x3A, 0x38, 0xAF, 0x03,
+ 0xA6, 0xFF, 0x34, 0xA2, 0x92, 0xC8, 0x70, 0xD4,
+ 0x86, 0xA5, 0x32, 0x57, 0xDC, 0xE5, 0xEB, 0xA5,
+ 0x33, 0xC2, 0x83, 0xC3, 0x33, 0xE8, 0x53, 0x8F,
+ 0x8A, 0xFA, 0xAE, 0xCF, 0x35, 0x6E, 0xD0, 0x5D,
+ 0xCF, 0xE4, 0x18, 0x2F, 0x6E, 0xEC, 0x9D, 0xE9,
+ 0x60, 0x27, 0xF7, 0x7A, 0xFD, 0x1D, 0xC3, 0x2C,
+ 0xE0, 0xDA, 0x7B, 0x18, 0xE0, 0x6A, 0x06, 0xE6,
+ 0xEE, 0xA3, 0x0C, 0x02, 0x98, 0xA5, 0x30, 0xA1,
+ 0x3F, 0x98, 0xCA, 0x06, 0xBD, 0x76, 0xDB, 0xCC,
+ 0xDF, 0x0B, 0x38, 0x43, 0x86, 0x11, 0xB8, 0xB7,
+ 0xC5, 0xC1, 0x74, 0x59, 0x63, 0xFF, 0x3C, 0xFC,
+ 0x14, 0xDF, 0xAD, 0xDD, 0x99, 0xCC, 0x48, 0xEA,
+ 0xCE, 0x75, 0x15, 0x1D, 0x8F, 0x63, 0x5B, 0x9D,
+ 0x97, 0x2E, 0x98, 0x7B, 0x7A, 0x07, 0xBB, 0x99,
+ 0x57, 0xF5, 0xC4, 0x4D, 0x11, 0x4C, 0x55, 0x08,
+ 0x5F, 0x2C, 0x25, 0x37, 0x83, 0x76, 0xD5, 0xCA,
+ 0x51, 0x5C, 0x86, 0xA4, 0xA1, 0x14, 0x2B, 0xBA,
+ 0xBD, 0x59, 0xBF, 0xE0, 0x41, 0xA9, 0x66, 0xD1,
+ 0x29, 0x4B, 0x04, 0xCA, 0xEE, 0x9A, 0x31, 0x5E,
+ 0xD9, 0x11, 0xEE, 0x1B, 0xB6, 0x09, 0x11, 0xA4,
+ 0xD8, 0x3A, 0x12, 0xF5, 0x9E, 0x79, 0x02, 0x64,
+ 0x8F, 0x18, 0x38, 0x5D, 0x19, 0x4D, 0x56, 0xA6,
+ 0x7A, 0xA6, 0xC0, 0x98, 0x13, 0x2F, 0x60, 0x73,
+ 0xD2, 0x8F, 0x70, 0x3D, 0x09, 0x42, 0xE9, 0xCC,
+ 0xFF, 0xA9, 0xF0, 0x82, 0xA2, 0x10, 0x1A, 0x26,
+ 0x91, 0xD6, 0x84, 0x24, 0x0A, 0x3A, 0xC6, 0x67,
+ 0x36, 0xCE, 0x9B, 0x4B, 0xF8, 0xF3, 0xCA, 0xB6,
+ 0x6C, 0x5F, 0x04, 0xE5, 0x74, 0xD8, 0x56, 0x42,
+ 0x7D, 0xD1, 0x5E, 0x8F, 0xA0, 0x9D, 0x66, 0x3B,
+ 0x13, 0x86, 0x9D, 0x84, 0x40, 0x74, 0x76, 0x00,
+ 0xCD, 0x40, 0x87, 0x58, 0x7C, 0x41, 0x8A, 0xE2,
+ 0xF8, 0xCB, 0x06, 0xCF, 0xCB, 0x0C, 0x78, 0x5D,
+ 0x6E, 0xAD, 0xE0, 0x1A, 0x54, 0xC3, 0x31, 0x5B,
+ 0xCF, 0xD0, 0x2D, 0x22, 0xA5, 0x84, 0x97, 0x20,
+ 0x4D, 0x13, 0x5F, 0xED, 0xFE, 0x01, 0xD8, 0x1A,
+ 0x79, 0xB5, 0x99, 0x03, 0x18, 0x55, 0xFB, 0xDD,
+ 0x5F, 0x6E, 0x85, 0xA2, 0x13, 0x28, 0x45, 0x29,
+ 0x25, 0x71, 0xC8, 0x53, 0x9B, 0x45, 0xA5, 0xD9,
+ 0x55, 0x8C, 0xC8, 0x93, 0x2B, 0xBC, 0x08, 0x8D,
+ 0x47, 0x90, 0x8F, 0x5E, 0x4B, 0xBC, 0xCE, 0xD1,
+ 0x51, 0x3B, 0xFB, 0x09, 0x4A, 0x72, 0x99, 0x0F,
+ 0xE2, 0x5F, 0x80, 0xF4, 0xE7, 0x6F, 0xD6, 0x08,
+ 0xD1, 0x79, 0xE8, 0x68, 0xFA, 0x29, 0x08, 0x4F,
+ 0x8B, 0x11, 0x12, 0x27, 0x97, 0x04, 0xC8, 0x7D,
+ 0xAB, 0x4D, 0xDA, 0x92, 0x29, 0x42, 0x7C, 0x3E,
+ 0x7D, 0x05, 0xEC, 0x1F, 0x4A, 0xA1, 0xBB, 0x3F,
+ 0x77, 0x3F, 0xEF, 0xC9, 0xAA, 0x63, 0xD5, 0x39,
+ 0xD5, 0x33, 0x0D, 0x28, 0xD0, 0x3C, 0x85, 0xC0
+ },
+ .len = 448
+ },
+ .modulus = {
+ .data = {
+ 0xBB, 0x97, 0x8A, 0xB6, 0x26, 0xD4, 0x0E, 0x70,
+ 0x21, 0xA6, 0x56, 0x71, 0xE5, 0xD8, 0x18, 0x21,
+ 0x64, 0x9F, 0x1B, 0x6F, 0x7C, 0x27, 0x72, 0xB8,
+ 0x39, 0xE5, 0x2A, 0x94, 0x76, 0x22, 0xB7, 0x68,
+ 0x57, 0x3A, 0x01, 0x54, 0xA8, 0x50, 0x41, 0xA1,
+ 0xAD, 0xD0, 0xC7, 0xDB, 0xAA, 0x76, 0x7F, 0x37,
+ 0xA9, 0x27, 0x22, 0x8D, 0xF0, 0x5C, 0x5A, 0xAC,
+ 0xFB, 0x82, 0x6A, 0x8E, 0x31, 0x51, 0x54, 0x7C,
+ 0xDB, 0x55, 0x9C, 0xBC, 0x82, 0x27, 0xF4, 0x0B,
+ 0x94, 0x74, 0xC8, 0x83, 0x80, 0x1C, 0xD8, 0xFF,
+ 0x50, 0xA2, 0xC9, 0xED, 0x2B, 0x98, 0x77, 0xF3,
+ 0x31, 0x81, 0x1C, 0x41, 0x8E, 0xAF, 0x87, 0xA2,
+ 0x02, 0xAC, 0x8B, 0x55, 0x01, 0x5C, 0x16, 0x11,
+ 0x63, 0x8C, 0xE2, 0x0D, 0x51, 0xD2, 0x4C, 0xD7,
+ 0xD4, 0x3D, 0xE4, 0x79, 0x1A, 0xA7, 0xC4, 0xBF,
+ 0x4E, 0x2A, 0xC9, 0x74, 0xD6, 0xD4, 0x90, 0x03,
+ 0x65, 0x7F, 0x54, 0x0F, 0xAC, 0x5F, 0x98, 0x2C,
+ 0x46, 0xC0, 0xD7, 0xE6, 0x75, 0x95, 0xC3, 0xEA,
+ 0x05, 0x3A, 0x03, 0x55, 0x43, 0xC7, 0xC2, 0xD1,
+ 0x11, 0xCD, 0x57, 0x37, 0x0D, 0x40, 0x87, 0xDF,
+ 0x7D, 0xC3, 0x04, 0x54, 0xDE, 0x1D, 0xAF, 0xB8,
+ 0x02, 0x50, 0x42, 0xFF, 0x9D, 0xFB, 0x13, 0xF7,
+ 0x25, 0x5A, 0x8B, 0xE3, 0x31, 0xA2, 0x64, 0xF8,
+ 0x94, 0x50, 0x18, 0xFB, 0xBB, 0xA2, 0xE9, 0x13,
+ 0x77, 0x6E, 0xE1, 0x6F, 0x9F, 0x06, 0x03, 0xEE,
+ 0x0D, 0x06, 0x6E, 0xF2, 0x9B, 0x15, 0x70, 0xDD,
+ 0x26, 0x7C, 0xB4, 0x5D, 0xD0, 0xE7, 0x77, 0xC4,
+ 0xB9, 0x88, 0x75, 0xB8, 0x73, 0xFC, 0xE9, 0xB7,
+ 0x11, 0x26, 0xAC, 0xDB, 0x97, 0x27, 0x18, 0x21,
+ 0x50, 0x7E, 0x46, 0xB2, 0xF1, 0x50, 0x40, 0xD9,
+ 0x8B, 0x63, 0xDB, 0x1A, 0x8E, 0x29, 0xBE, 0x1F,
+ 0x88, 0x35, 0xFD, 0x95, 0xC3, 0xA6, 0x80, 0xEB,
+ 0x73, 0xF7, 0x02, 0x02, 0xB0, 0xCA, 0x97, 0x2C,
+ 0x32, 0x44, 0xA9, 0xCA, 0x94, 0xC0, 0xB2, 0xD9,
+ 0x7C, 0xD9, 0x10, 0x62, 0x31, 0xC9, 0xFA, 0x5B,
+ 0x5C, 0x2C, 0xB6, 0x04, 0x5B, 0x7E, 0x86, 0xBB,
+ 0x49, 0x02, 0x16, 0x9E, 0x1E, 0x53, 0xBD, 0xC2,
+ 0xA9, 0xAA, 0x94, 0x39, 0xA1, 0xB2, 0x18, 0x17,
+ 0xB6, 0x2C, 0xF6, 0xFF, 0xC0, 0xD0, 0x2D, 0x4D,
+ 0xAA, 0x6C, 0xB5, 0xC8, 0x6A, 0xBE, 0x38, 0xE4,
+ 0x9F, 0xDC, 0x5C, 0x56, 0x56, 0x04, 0x32, 0x49,
+ 0x91, 0x17, 0x44, 0x6E, 0xB3, 0xF9, 0x8F, 0xDB,
+ 0xEA, 0x04, 0x4C, 0x67, 0xE6, 0xDA, 0x96, 0x2F,
+ 0x89, 0x2D, 0x54, 0xC3, 0xAD, 0x07, 0x6B, 0xA0,
+ 0x87, 0xF0, 0xCF, 0x4B, 0x43, 0x46, 0xCA, 0x06,
+ 0x48, 0x8D, 0x34, 0xC4, 0xD2, 0xD2, 0xA9, 0x16,
+ 0x13, 0xF5, 0x49, 0x44, 0x8C, 0xD9, 0x0C, 0x1E,
+ 0x79, 0x47, 0xFC, 0x4C, 0x37, 0x8E, 0xD1, 0xFD,
+ 0xB9, 0xE8, 0x6E, 0x1B, 0x8D, 0x68, 0xCC, 0x49,
+ 0x0D, 0x98, 0xB5, 0xD5, 0x22, 0x1C, 0xFC, 0xBA,
+ 0x7A, 0x74, 0x3D, 0xBD, 0xD9, 0xB3, 0x80, 0x58,
+ 0x4A, 0x05, 0x67, 0x9D, 0x59, 0xF4, 0xF7, 0x72,
+ 0x11, 0x3C, 0x67, 0x96, 0xE7, 0x0D, 0x8E, 0x73,
+ 0xD1, 0xEE, 0x00, 0x79, 0x98, 0x7A, 0x0E, 0xE0,
+ 0xA8, 0xEA, 0x7D, 0xF3, 0xDB, 0x0E, 0x62, 0x3E,
+ 0x66, 0x95, 0xED, 0xD5, 0x8C, 0x39, 0xF5, 0xAB
+ },
+ .len = 448
+ },
+ .result_len = 448
+},
+{
+ .description = "Modular Exponentiation "
+ "(mod=19, base=500, exp=35, res=19)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .base = {
+ .data = {
+ 0x42, 0xE5, 0x6F, 0xF7, 0xEF, 0x8F, 0xAB, 0x6F,
+ 0xF5, 0xE2, 0xD2, 0x97, 0x68, 0x0D, 0x52, 0xDD,
+ 0x3D, 0x62, 0xC4, 0xC4, 0xDE, 0xD2, 0x07, 0x50,
+ 0x1B, 0xA9, 0x5F, 0xAE, 0x42, 0xCB, 0x5E, 0x0B,
+ 0xC0, 0x41, 0xFE, 0xEF, 0x22, 0xA6, 0x4E, 0x35,
+ 0x80, 0x61, 0x22, 0x92, 0x65, 0x77, 0x45, 0x84,
+ 0x6C, 0x03, 0x7C, 0xEF, 0xC0, 0x49, 0x31, 0x87,
+ 0x86, 0x9B, 0x2E, 0x28, 0xA1, 0x55, 0x2D, 0x3C,
+ 0x68, 0x3D, 0x69, 0x0E, 0x98, 0xD6, 0x40, 0xFD,
+ 0x0B, 0x4C, 0x5F, 0xC7, 0x95, 0xF1, 0x53, 0x7C,
+ 0xCC, 0x12, 0x3F, 0x8C, 0x7A, 0x24, 0x73, 0xE7,
+ 0x33, 0x20, 0xBD, 0x0C, 0xD2, 0x9C, 0x12, 0x20,
+ 0xC0, 0xC0, 0xA9, 0x16, 0x7E, 0x6B, 0x1D, 0x1F,
+ 0xFE, 0x63, 0x8A, 0x22, 0x75, 0xDC, 0xF0, 0x0F,
+ 0x8E, 0xA4, 0x3C, 0xE3, 0x6B, 0xFA, 0x46, 0xBA,
+ 0xEB, 0x91, 0x31, 0x9D, 0x34, 0xED, 0xA0, 0xA6,
+ 0xA3, 0xAB, 0xA5, 0x2A, 0x10, 0x30, 0xF4, 0x6F,
+ 0x80, 0x25, 0xB0, 0xF5, 0x56, 0x76, 0xD3, 0xC5,
+ 0x10, 0x92, 0xCD, 0xEA, 0xC3, 0x9C, 0x52, 0x96,
+ 0xF1, 0xBD, 0x42, 0x53, 0xF3, 0xA9, 0x1F, 0xCB,
+ 0x53, 0x45, 0xF1, 0xF6, 0x5F, 0x98, 0xFC, 0x13,
+ 0xC9, 0xA8, 0x44, 0xC6, 0xD0, 0x78, 0xB6, 0x39,
+ 0x93, 0x02, 0xC6, 0xC9, 0x0F, 0xAF, 0xF9, 0x6D,
+ 0x91, 0x35, 0xC9, 0x26, 0x73, 0x11, 0xEB, 0xEE,
+ 0x52, 0x61, 0x6C, 0xC0, 0x7F, 0xFD, 0xD0, 0x77,
+ 0x9F, 0xC6, 0x0A, 0x05, 0x1B, 0x90, 0x61, 0x54,
+ 0x61, 0xFF, 0x1E, 0xBA, 0x1D, 0x2F, 0x25, 0xE9,
+ 0x85, 0x4C, 0xBA, 0xEF, 0x99, 0x95, 0x3C, 0xBB,
+ 0xA9, 0xCF, 0x0D, 0xBF, 0x2C, 0x86, 0xB0, 0x59,
+ 0xAA, 0x83, 0x29, 0x32, 0x24, 0x28, 0xC8, 0x53,
+ 0x28, 0x4C, 0xEB, 0x08, 0xFF, 0xC6, 0x25, 0xB7,
+ 0xFF, 0x18, 0xB0, 0x2C, 0xDD, 0xAE, 0xFB, 0xDB,
+ 0x54, 0xA2, 0x92, 0x27, 0x15, 0x0D, 0x6B, 0x50,
+ 0xFB, 0xEA, 0x2C, 0x1C, 0x6F, 0x91, 0x3C, 0x50,
+ 0x5A, 0xD8, 0x9B, 0x33, 0xED, 0x51, 0x5D, 0x7C,
+ 0x37, 0x01, 0xEF, 0x09, 0xEA, 0x59, 0x56, 0x8A,
+ 0x67, 0x21, 0x8C, 0x25, 0x00, 0x33, 0x24, 0x31,
+ 0xCB, 0xAA, 0x5A, 0xA4, 0xB1, 0x84, 0xDD, 0x89,
+ 0x3A, 0xFA, 0xD8, 0xAB, 0xEE, 0x3E, 0xC0, 0x0D,
+ 0xDA, 0x2C, 0x2A, 0x75, 0x13, 0xD7, 0x49, 0x5E,
+ 0x28, 0x2C, 0x24, 0xC6, 0x1E, 0xA0, 0xB3, 0x70,
+ 0xAD, 0x45, 0x8A, 0xF2, 0xD9, 0x38, 0x69, 0xD5,
+ 0x53, 0x30, 0xD8, 0x09, 0x09, 0xDE, 0x1F, 0x6C,
+ 0x36, 0x82, 0xD5, 0xEC, 0xA7, 0x7E, 0x37, 0x5F,
+ 0x7D, 0xF2, 0x85, 0x85, 0xF9, 0x0A, 0xC1, 0x13,
+ 0x86, 0x3C, 0xCD, 0xFE, 0x44, 0x46, 0x57, 0x5E,
+ 0x67, 0x39, 0x9D, 0x65, 0x74, 0xB9, 0x13, 0x5A,
+ 0x05, 0xC1, 0xEA, 0xB5, 0x10, 0x1D, 0x66, 0xFF,
+ 0xA0, 0x3D, 0x47, 0x27, 0x15, 0x66, 0x52, 0x19,
+ 0xFA, 0x95, 0xD0, 0x03, 0x67, 0xA8, 0x89, 0xAA,
+ 0x68, 0x04, 0x5F, 0xC4, 0x57, 0x1F, 0x6C, 0xF7,
+ 0xD2, 0xE2, 0xA3, 0xF3, 0x96, 0x70, 0x86, 0xC6,
+ 0xCB, 0x3D, 0x52, 0x66, 0x79, 0xED, 0xE6, 0x35,
+ 0x0A, 0xE8, 0xA8, 0x5A, 0xED, 0x41, 0xB0, 0xF0,
+ 0x89, 0xCC, 0x20, 0xDA, 0xB7, 0x48, 0x44, 0x64,
+ 0x69, 0xC9, 0x43, 0xE2, 0xBD, 0xD1, 0x17, 0xCF,
+ 0x25, 0x7C, 0x92, 0x0B, 0xFC, 0x71, 0x46, 0x67,
+ 0x1F, 0xF4, 0xA7, 0xFF, 0xD8, 0xA4, 0x5F, 0x4A,
+ 0x8A, 0x45, 0xBE, 0xDD, 0x89, 0xE2, 0x2A, 0xA7,
+ 0xBC, 0xE9, 0x84, 0x53, 0x9D, 0xF4, 0x39, 0xB7,
+ 0xDB, 0x3A, 0x17, 0xF7, 0x27, 0x39, 0xDF, 0x8A,
+ 0xF0, 0x72, 0xD6, 0x23, 0x1B, 0x1C, 0xD9, 0x48,
+ 0xF4, 0x2E, 0x54, 0xA3
+ },
+ .len = 500
+ },
+ .exponent = {
+ .data = {
+ 0xE7, 0xF1, 0x97, 0x29, 0x62, 0x0B, 0x99, 0x89,
+ 0x99, 0xC1, 0x63, 0xA2, 0xB7, 0x29, 0xAD, 0x0E,
+ 0x84, 0x3B, 0x86, 0x82, 0xC4, 0xDD, 0xC4, 0xE2,
+ 0xA7, 0xD4, 0xBA, 0x91, 0x2C, 0xB5, 0xD6, 0xD4,
+ 0x74, 0x1D, 0xE1
+ },
+ .len = 35
+ },
+ .reminder = {
+ .data = {
+ 0x67, 0x9F, 0xF7, 0x57, 0xD7, 0xF8, 0xF8, 0x90,
+ 0x4E, 0xB5, 0x34, 0xE8, 0xAF, 0x14, 0xC6, 0x94,
+ 0x5F, 0xA1, 0x03
+ },
+ .len = 19
+ },
+ .modulus = {
+ .data = {
+ 0x9C, 0xE7, 0xE7, 0x14, 0x6E, 0x07, 0x71, 0xD2,
+ 0xD1, 0xB3, 0x59, 0x9B, 0x63, 0xDB, 0x58, 0x8D,
+ 0x5E, 0x84, 0xA0
+ },
+ .len = 19
+ },
+ .result_len = 19
+}
+};
+
+static const struct
+modinv_test_data modinv_test_case[] = {
+{
+ .description = "Modular Inverse (mod=128, base=20, exp=3, inv=128)",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODINV,
+ .base = {
+ .data = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85,
+ 0xAE, 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD,
+ 0xA8, 0xEB, 0x7E, 0x78, 0xA0, 0x50
+ },
+ .len = 20
+ },
+ .inverse = {
+ .data = {
+ 0x52, 0xb1, 0xa3, 0x8c, 0xc5, 0x8a, 0xb9, 0x1f,
+ 0xb6, 0x82, 0xf5, 0x6a, 0x9a, 0xde, 0x8d, 0x2e,
+ 0x62, 0x4b, 0xac, 0x49, 0x21, 0x1d, 0x30, 0x4d,
+ 0x32, 0xac, 0x1f, 0x40, 0x6d, 0x52, 0xc7, 0x9b,
+ 0x6c, 0x0a, 0x82, 0x3a, 0x2c, 0xaf, 0x6b, 0x6d,
+ 0x17, 0xbe, 0x43, 0xed, 0x97, 0x78, 0xeb, 0x4c,
+ 0x92, 0x6f, 0xcf, 0xed, 0xb1, 0x09, 0xcb, 0x27,
+ 0xc2, 0xde, 0x62, 0xfd, 0x21, 0xe6, 0xbd, 0x4f,
+ 0xfe, 0x7a, 0x1b, 0x50, 0xfe, 0x10, 0x4a, 0xb0,
+ 0xb7, 0xcf, 0xdb, 0x7d, 0xca, 0xc2, 0xf0, 0x1c,
+ 0x39, 0x48, 0x6a, 0xb5, 0x4d, 0x8c, 0xfe, 0x63,
+ 0x91, 0x9c, 0x21, 0xc3, 0x0e, 0x76, 0xad, 0x44,
+ 0x8d, 0x54, 0x33, 0x99, 0xe1, 0x80, 0x19, 0xba,
+ 0xb5, 0xac, 0x7d, 0x9c, 0xce, 0x91, 0x2a, 0xd9,
+ 0x2c, 0xe1, 0x16, 0xd6, 0xd7, 0xcf, 0x9d, 0x05,
+ 0x9a, 0x66, 0x9a, 0x3a, 0xc1, 0xb8, 0x4b, 0xc3
+ },
+ .len = 128
+ },
+ .modulus = {
+ .data = {
+ 0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00, 0x0a,
+ 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5, 0xce,
+ 0x47, 0x8a, 0xc3, 0x80, 0xf4, 0x7d, 0x4a, 0xa2,
+ 0x62, 0xfd, 0x61, 0x7f, 0xb5, 0xa8, 0xde, 0x0a,
+ 0x17, 0x97, 0xa0, 0xbf, 0xdf, 0x56, 0x5a, 0x3d,
+ 0x51, 0x56, 0x4f, 0x70, 0x70, 0x3f, 0x63, 0x6a,
+ 0x44, 0x5b, 0xad, 0x84, 0x0d, 0x3f, 0x27, 0x6e,
+ 0x3b, 0x34, 0x91, 0x60, 0x14, 0xb9, 0xaa, 0x72,
+ 0xfd, 0xa3, 0x64, 0xd2, 0x03, 0xa7, 0x53, 0x87,
+ 0x9e, 0x88, 0x0b, 0xc1, 0x14, 0x93, 0x1a, 0x62,
+ 0xff, 0xb1, 0x5d, 0x74, 0xcd, 0x59, 0x63, 0x18,
+ 0x11, 0x3d, 0x4f, 0xba, 0x75, 0xd4, 0x33, 0x4e,
+ 0x23, 0x6b, 0x7b, 0x57, 0x44, 0xe1, 0xd3, 0x03,
+ 0x13, 0xa6, 0xf0, 0x8b, 0x60, 0xb0, 0x9e, 0xee,
+ 0x75, 0x08, 0x9d, 0x71, 0x63, 0x13, 0xcb, 0xa6,
+ 0x81, 0x92, 0x14, 0x03, 0x22, 0x2d, 0xde, 0x55
+ },
+ .len = 128
+ },
+ .result_len = 128
+}
+};
+
+/* modular operation test data */
+uint8_t base[] = {
+ 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85,
+ 0xAE, 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD,
+ 0xA8, 0xEB, 0x7E, 0x78, 0xA0, 0x50
+};
+
+uint8_t mod_p[] = {
+ 0x00, 0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00,
+ 0x0a, 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5,
+ 0xce, 0x47, 0x8a, 0xc3, 0x80, 0xf4, 0x7d, 0x4a,
+ 0xa2, 0x62, 0xfd, 0x61, 0x7f, 0xb5, 0xa8, 0xde,
+ 0x0a, 0x17, 0x97, 0xa0, 0xbf, 0xdf, 0x56, 0x5a,
+ 0x3d, 0x51, 0x56, 0x4f, 0x70, 0x70, 0x3f, 0x63,
+ 0x6a, 0x44, 0x5b, 0xad, 0x84, 0x0d, 0x3f, 0x27,
+ 0x6e, 0x3b, 0x34, 0x91, 0x60, 0x14, 0xb9, 0xaa,
+ 0x72, 0xfd, 0xa3, 0x64, 0xd2, 0x03, 0xa7, 0x53,
+ 0x87, 0x9e, 0x88, 0x0b, 0xc1, 0x14, 0x93, 0x1a,
+ 0x62, 0xff, 0xb1, 0x5d, 0x74, 0xcd, 0x59, 0x63,
+ 0x18, 0x11, 0x3d, 0x4f, 0xba, 0x75, 0xd4, 0x33,
+ 0x4e, 0x23, 0x6b, 0x7b, 0x57, 0x44, 0xe1, 0xd3,
+ 0x03, 0x13, 0xa6, 0xf0, 0x8b, 0x60, 0xb0, 0x9e,
+ 0xee, 0x75, 0x08, 0x9d, 0x71, 0x63, 0x13, 0xcb,
+ 0xa6, 0x81, 0x92, 0x14, 0x03, 0x22, 0x2d, 0xde,
+ 0x55
+};
+
+uint8_t mod_e[] = {0x01, 0x00, 0x01};
+
+/* Precomputed modular exponentiation for verification */
+uint8_t mod_exp[] = {
+ 0x2C, 0x60, 0x75, 0x45, 0x98, 0x9D, 0xE0, 0x72,
+ 0xA0, 0x9D, 0x3A, 0x9E, 0x03, 0x38, 0x73, 0x3C,
+ 0x31, 0x83, 0x04, 0xFE, 0x75, 0x43, 0xE6, 0x17,
+ 0x5C, 0x01, 0x29, 0x51, 0x69, 0x33, 0x62, 0x2D,
+ 0x78, 0xBE, 0xAE, 0xC4, 0xBC, 0xDE, 0x7E, 0x2C,
+ 0x77, 0x84, 0xF2, 0xC5, 0x14, 0xB5, 0x2F, 0xF7,
+ 0xC5, 0x94, 0xEF, 0x86, 0x75, 0x75, 0xB5, 0x11,
+ 0xE5, 0x0E, 0x0A, 0x29, 0x76, 0xE2, 0xEA, 0x32,
+ 0x0E, 0x43, 0x77, 0x7E, 0x2C, 0x27, 0xAC, 0x3B,
+ 0x86, 0xA5, 0xDB, 0xC9, 0x48, 0x40, 0xE8, 0x99,
+ 0x9A, 0x0A, 0x3D, 0xD6, 0x74, 0xFA, 0x2E, 0x2E,
+ 0x5B, 0xAF, 0x8C, 0x99, 0x44, 0x2A, 0x67, 0x38,
+ 0x27, 0x41, 0x59, 0x9D, 0xB8, 0x51, 0xC9, 0xF7,
+ 0x43, 0x61, 0x31, 0x6E, 0xF1, 0x25, 0x38, 0x7F,
+ 0xAE, 0xC6, 0xD0, 0xBB, 0x29, 0x76, 0x3F, 0x46,
+ 0x2E, 0x1B, 0xE4, 0x67, 0x71, 0xE3, 0x87, 0x5A
+};
+
+/* Precomputed modular inverse for verification */
+uint8_t mod_inv[] = {
+ 0x52, 0xb1, 0xa3, 0x8c, 0xc5, 0x8a, 0xb9, 0x1f,
+ 0xb6, 0x82, 0xf5, 0x6a, 0x9a, 0xde, 0x8d, 0x2e,
+ 0x62, 0x4b, 0xac, 0x49, 0x21, 0x1d, 0x30, 0x4d,
+ 0x32, 0xac, 0x1f, 0x40, 0x6d, 0x52, 0xc7, 0x9b,
+ 0x6c, 0x0a, 0x82, 0x3a, 0x2c, 0xaf, 0x6b, 0x6d,
+ 0x17, 0xbe, 0x43, 0xed, 0x97, 0x78, 0xeb, 0x4c,
+ 0x92, 0x6f, 0xcf, 0xed, 0xb1, 0x09, 0xcb, 0x27,
+ 0xc2, 0xde, 0x62, 0xfd, 0x21, 0xe6, 0xbd, 0x4f,
+ 0xfe, 0x7a, 0x1b, 0x50, 0xfe, 0x10, 0x4a, 0xb0,
+ 0xb7, 0xcf, 0xdb, 0x7d, 0xca, 0xc2, 0xf0, 0x1c,
+ 0x39, 0x48, 0x6a, 0xb5, 0x4d, 0x8c, 0xfe, 0x63,
+ 0x91, 0x9c, 0x21, 0xc3, 0x0e, 0x76, 0xad, 0x44,
+ 0x8d, 0x54, 0x33, 0x99, 0xe1, 0x80, 0x19, 0xba,
+ 0xb5, 0xac, 0x7d, 0x9c, 0xce, 0x91, 0x2a, 0xd9,
+ 0x2c, 0xe1, 0x16, 0xd6, 0xd7, 0xcf, 0x9d, 0x05,
+ 0x9a, 0x66, 0x9a, 0x3a, 0xc1, 0xb8, 0x4b, 0xc3
+};
+
+struct rte_crypto_asym_xform modex_xform = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODEX,
+ .modex = {
+ .modulus = {
+ .data = mod_p,
+ .length = sizeof(mod_p)
+ },
+ .exponent = {
+ .data = mod_e,
+ .length = sizeof(mod_e)
+ }
+ }
+};
+
+struct rte_crypto_asym_xform modinv_xform = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_MODINV,
+ .modinv = {
+ .modulus = {
+ .data = mod_p,
+ .length = sizeof(mod_p)
+ }
+ }
+};
+
+#endif /* TEST_CRYPTODEV_MOD_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_rsa_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_rsa_test_vectors.h
new file mode 100644
index 000000000..48a72e149
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_rsa_test_vectors.h
@@ -0,0 +1,407 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Cavium Networks
+ */
+
+#ifndef TEST_CRYPTODEV_RSA_TEST_VECTORS_H__
+#define TEST_CRYPTODEV_RSA_TEST_VECTORS_H__
+
+#include <stdint.h>
+
+#include "rte_crypto_asym.h"
+
+#define TEST_DATA_SIZE 4096
+
+struct rsa_test_data_2 {
+ enum rte_crypto_asym_xform_type xform_type;
+ const char *description;
+ uint64_t op_type_flags;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } pt;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } ct;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } sign;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } e;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } d;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } n;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } p;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } q;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } dP;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } dQ;
+ struct {
+ uint8_t data[DATA_SIZE];
+ uint16_t len;
+ } qInv;
+
+ uint16_t result_len;
+ enum rte_crypto_rsa_padding_type padding;
+ int key_exp;
+ int key_qt;
+};
+
+static const struct
+rsa_test_data_2 rsa_test_case_list[] = {
+ {
+ .description = "RSA Encryption Decryption "
+ "(n=128, pt=20, e=3) EXP, QT",
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+ .op_type_flags = 1UL << RTE_CRYPTO_ASYM_OP_ENCRYPT |
+ 1UL << RTE_CRYPTO_ASYM_OP_DECRYPT,
+ .pt = {
+ .data = {
+ 0x00, 0x02, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+ 0xbb, 0xbb, 0xbb, 0xbb, 0xf8, 0xba, 0x1a, 0x55,
+ 0xd0, 0x2f, 0x85, 0xae, 0x96, 0x7b, 0xb6, 0x2f,
+ 0xb6, 0xcd, 0xa8, 0xeb, 0x7e, 0x78, 0xa0, 0x50
+ },
+ .len = 128,
+ },
+ .ct = {
+ .data = {
+ 0x3D, 0x8D, 0x2F, 0x85, 0xC0, 0xB7, 0x21, 0x3E,
+ 0x5B, 0x4A, 0x96, 0xB2, 0x85, 0x35, 0xAF, 0x0C,
+ 0x62, 0xE9, 0x73, 0xEF, 0x77, 0x76, 0x19, 0xD5,
+ 0x92, 0xF7, 0x1D, 0xB0, 0x15, 0x69, 0x65, 0x82,
+ 0x32, 0x30, 0x4E, 0x29, 0xE7, 0x83, 0xAD, 0x23,
+ 0x66, 0xD9, 0x91, 0x9B, 0xFF, 0x01, 0x10, 0x3B,
+ 0xB2, 0xF8, 0x78, 0x14, 0xD2, 0x6E, 0x3C, 0x59,
+ 0x6E, 0x1A, 0x90, 0x3C, 0x5A, 0xB3, 0x0B, 0x60,
+ 0xE2, 0x71, 0xCC, 0xF5, 0x0C, 0x57, 0x19, 0x03,
+ 0x5B, 0x04, 0x46, 0x7E, 0x13, 0x5B, 0xFF, 0x2C,
+ 0x01, 0x19, 0x75, 0x86, 0x6A, 0xAE, 0x60, 0xFB,
+ 0x0A, 0x4C, 0x14, 0x1A, 0xBC, 0x0E, 0x86, 0xF1,
+ 0x13, 0x10, 0xB3, 0x03, 0x8E, 0x66, 0x6F, 0xA5,
+ 0x53, 0x80, 0x5A, 0x91, 0xE6, 0x7C, 0x3C, 0x38,
+ 0x15, 0xB6, 0x69, 0x3E, 0xF6, 0x54, 0xB0, 0x60,
+ 0x83, 0xE9, 0x2B, 0xF3, 0x26, 0x53, 0x3E, 0x11
+ },
+ .len = 128,
+ },
+ .e = {
+ .data = {
+ 0x01, 0x00, 0x01
+ },
+ .len = 3,
+ },
+ .d = {
+ .data = {
+ 0x24, 0xd7, 0xea, 0xf4, 0x7f, 0xe0, 0xca, 0x31,
+ 0x4d, 0xee, 0xc4, 0xa1, 0xbe, 0xab, 0x06, 0x61,
+ 0x32, 0xe7, 0x51, 0x46, 0x27, 0xdf, 0x72, 0xe9,
+ 0x6f, 0xa8, 0x4c, 0xd1, 0x26, 0xef, 0x65, 0xeb,
+ 0x67, 0xff, 0x5f, 0xa7, 0x3b, 0x25, 0xb9, 0x08,
+ 0x8e, 0xa0, 0x47, 0x56, 0xe6, 0x8e, 0xf9, 0xd3,
+ 0x18, 0x06, 0x3d, 0xc6, 0xb1, 0xf8, 0xdc, 0x1b,
+ 0x8d, 0xe5, 0x30, 0x54, 0x26, 0xac, 0x16, 0x3b,
+ 0x7b, 0xad, 0x46, 0x9e, 0x21, 0x6a, 0x57, 0xe6,
+ 0x81, 0x56, 0x1d, 0x2a, 0xc4, 0x39, 0x63, 0x67,
+ 0x81, 0x2c, 0xca, 0xcc, 0xf8, 0x42, 0x04, 0xbe,
+ 0xcf, 0x8f, 0x6c, 0x5b, 0x81, 0x46, 0xb9, 0xc7,
+ 0x62, 0x90, 0x87, 0x35, 0x03, 0x9b, 0x89, 0xcb,
+ 0x37, 0xbd, 0xf1, 0x1b, 0x99, 0xa1, 0x9a, 0x78,
+ 0xd5, 0x4c, 0xdd, 0x3f, 0x41, 0x0c, 0xb7, 0x1a,
+ 0xd9, 0x7b, 0x87, 0x5f, 0xbe, 0xb1, 0x83, 0x41
+ },
+ .len = 128,
+ },
+ .n = {
+ .data = {
+ 0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00, 0x0a,
+ 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5, 0xce,
+ 0x47, 0x8a, 0xc3, 0x80, 0xf4, 0x7d, 0x4a, 0xa2,
+ 0x62, 0xfd, 0x61, 0x7f, 0xb5, 0xa8, 0xde, 0x0a,
+ 0x17, 0x97, 0xa0, 0xbf, 0xdf, 0x56, 0x5a, 0x3d,
+ 0x51, 0x56, 0x4f, 0x70, 0x70, 0x3f, 0x63, 0x6a,
+ 0x44, 0x5b, 0xad, 0x84, 0x0d, 0x3f, 0x27, 0x6e,
+ 0x3b, 0x34, 0x91, 0x60, 0x14, 0xb9, 0xaa, 0x72,
+ 0xfd, 0xa3, 0x64, 0xd2, 0x03, 0xa7, 0x53, 0x87,
+ 0x9e, 0x88, 0x0b, 0xc1, 0x14, 0x93, 0x1a, 0x62,
+ 0xff, 0xb1, 0x5d, 0x74, 0xcd, 0x59, 0x63, 0x18,
+ 0x11, 0x3d, 0x4f, 0xba, 0x75, 0xd4, 0x33, 0x4e,
+ 0x23, 0x6b, 0x7b, 0x57, 0x44, 0xe1, 0xd3, 0x03,
+ 0x13, 0xa6, 0xf0, 0x8b, 0x60, 0xb0, 0x9e, 0xee,
+ 0x75, 0x08, 0x9d, 0x71, 0x63, 0x13, 0xcb, 0xa6,
+ 0x81, 0x92, 0x14, 0x03, 0x22, 0x2d, 0xde, 0x55
+ },
+ .len = 128,
+ },
+ .p = {
+ .data = {
+ 0xdc, 0xba, 0x00, 0x01, 0x57, 0x93, 0xe3, 0x05,
+ 0xed, 0x61, 0x9a, 0xa3, 0xaf, 0x6a, 0xd3, 0x47,
+ 0x8f, 0x2d, 0x1e, 0x7f, 0x4d, 0x60, 0xc8, 0x8d,
+ 0x34, 0xb8, 0x17, 0x84, 0xbc, 0xd4, 0xe9, 0x79,
+ 0x95, 0x75, 0x19, 0x37, 0xe0, 0xcc, 0xfe, 0x4c,
+ 0x5d, 0x49, 0x53, 0x61, 0x29, 0xf1, 0xdc, 0x82,
+ 0x03, 0x96, 0x7d, 0x95, 0x4f, 0xdd, 0x3c, 0x0a,
+ 0x64, 0x8a, 0x43, 0x2f, 0x95, 0x4a, 0xed, 0xdd
+ },
+ .len = 64,
+ },
+ .q = {
+ .data = {
+ 0xd0, 0x56, 0x7a, 0x0a, 0xd5, 0x95, 0xa4, 0x85,
+ 0x53, 0x35, 0xa1, 0x48, 0x07, 0x6a, 0x7c, 0x08,
+ 0xe0, 0xfd, 0x4b, 0x88, 0x77, 0xa6, 0x15, 0x23,
+ 0x0f, 0xbf, 0x14, 0x46, 0x11, 0xee, 0x95, 0xc7,
+ 0x5e, 0x77, 0x65, 0xa2, 0xb5, 0x50, 0xdf, 0x19,
+ 0x07, 0xc7, 0x72, 0xdb, 0x29, 0xf6, 0x54, 0x86,
+ 0xe1, 0xb3, 0x97, 0x0a, 0x28, 0x64, 0x3a, 0x38,
+ 0xa6, 0x7d, 0x13, 0xc3, 0x79, 0xaa, 0x56, 0xd9
+ },
+ .len = 64,
+ },
+ .dP = {
+ .data = {
+ 0xc5, 0x43, 0x0d, 0x82, 0x25, 0x8c, 0xab, 0x55,
+ 0xbe, 0xc2, 0x7d, 0xfb, 0x4f, 0x68, 0x3f, 0x0e,
+ 0x32, 0xec, 0xf5, 0xd6, 0x7b, 0x86, 0xc5, 0x75,
+ 0x3c, 0xea, 0x51, 0x4a, 0x75, 0xa0, 0x2a, 0x50,
+ 0x58, 0xbb, 0xe0, 0x1f, 0xca, 0x2e, 0x2a, 0x0e,
+ 0x81, 0x48, 0x68, 0xd5, 0xeb, 0x30, 0x96, 0x0b,
+ 0x33, 0xbd, 0xa8, 0xda, 0x6a, 0x17, 0xa3, 0xf2,
+ 0xfd, 0xcb, 0x7b, 0x23, 0xe9, 0x5e, 0x9f, 0x99
+ },
+ .len = 64,
+ },
+ .dQ = {
+ .data = {
+ 0xbe, 0xff, 0xf9, 0x05, 0x43, 0xc8, 0xdc, 0x3b,
+ 0x0b, 0x0d, 0x28, 0xde, 0x73, 0x46, 0x11, 0x8e,
+ 0xc6, 0x4e, 0x11, 0xd8, 0x7b, 0xf0, 0xfc, 0x81,
+ 0xd7, 0x66, 0xd3, 0xbc, 0x65, 0xa6, 0x39, 0x14,
+ 0xbd, 0xab, 0x72, 0xb7, 0x57, 0xc9, 0x5b, 0xaf,
+ 0x83, 0xed, 0x3b, 0x84, 0x68, 0x15, 0x18, 0x6b,
+ 0x4c, 0x32, 0xac, 0x6f, 0x38, 0x96, 0xa2, 0xb5,
+ 0xdb, 0x14, 0xe2, 0x70, 0x9c, 0x73, 0x29, 0x09
+ },
+ .len = 64,
+ },
+ .qInv = {
+ .data = {
+ 0x59, 0xbd, 0xb1, 0x37, 0xeb, 0x4e, 0xcf, 0x68,
+ 0xe7, 0x85, 0x91, 0xbb, 0xc0, 0xdb, 0x8e, 0x41,
+ 0x91, 0x4a, 0xc0, 0xb1, 0xc5, 0xe8, 0x91, 0xf6,
+ 0xc7, 0x5a, 0x98, 0x1a, 0x8a, 0x0f, 0x45, 0xb2,
+ 0x5b, 0xff, 0x7a, 0x2d, 0x98, 0x89, 0x55, 0xd9,
+ 0xbf, 0x6e, 0xdd, 0x2d, 0xd4, 0xe8, 0x0a, 0xaa,
+ 0xae, 0x2a, 0xc4, 0x16, 0xb5, 0xba, 0xe1, 0x69,
+ 0x71, 0x94, 0xdd, 0xa0, 0xf5, 0x1e, 0x6d, 0xcc
+ },
+ .len = 64,
+ },
+ .padding = RTE_CRYPTO_RSA_PADDING_NONE,
+ .key_exp = 1,
+ .key_qt = 1,
+ }
+};
+
+struct rsa_test_data {
+ uint8_t data[TEST_DATA_SIZE];
+ unsigned int len;
+};
+
+struct rsa_test_data rsaplaintext = {
+ .data = {
+ 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50
+ },
+ .len = 20
+};
+
+uint8_t rsa_n[] = {
+ 0xb3, 0xa1, 0xaf, 0xb7, 0x13, 0x08, 0x00,
+ 0x0a, 0x35, 0xdc, 0x2b, 0x20, 0x8d, 0xa1, 0xb5,
+ 0xce, 0x47, 0x8a, 0xc3, 0x80, 0xf4, 0x7d, 0x4a,
+ 0xa2, 0x62, 0xfd, 0x61, 0x7f, 0xb5, 0xa8, 0xde,
+ 0x0a, 0x17, 0x97, 0xa0, 0xbf, 0xdf, 0x56, 0x5a,
+ 0x3d, 0x51, 0x56, 0x4f, 0x70, 0x70, 0x3f, 0x63,
+ 0x6a, 0x44, 0x5b, 0xad, 0x84, 0x0d, 0x3f, 0x27,
+ 0x6e, 0x3b, 0x34, 0x91, 0x60, 0x14, 0xb9, 0xaa,
+ 0x72, 0xfd, 0xa3, 0x64, 0xd2, 0x03, 0xa7, 0x53,
+ 0x87, 0x9e, 0x88, 0x0b, 0xc1, 0x14, 0x93, 0x1a,
+ 0x62, 0xff, 0xb1, 0x5d, 0x74, 0xcd, 0x59, 0x63,
+ 0x18, 0x11, 0x3d, 0x4f, 0xba, 0x75, 0xd4, 0x33,
+ 0x4e, 0x23, 0x6b, 0x7b, 0x57, 0x44, 0xe1, 0xd3,
+ 0x03, 0x13, 0xa6, 0xf0, 0x8b, 0x60, 0xb0, 0x9e,
+ 0xee, 0x75, 0x08, 0x9d, 0x71, 0x63, 0x13, 0xcb,
+ 0xa6, 0x81, 0x92, 0x14, 0x03, 0x22, 0x2d, 0xde,
+ 0x55
+};
+
+uint8_t rsa_d[] = {
+ 0x24, 0xd7, 0xea, 0xf4, 0x7f, 0xe0, 0xca, 0x31,
+ 0x4d, 0xee, 0xc4, 0xa1, 0xbe, 0xab, 0x06, 0x61,
+ 0x32, 0xe7, 0x51, 0x46, 0x27, 0xdf, 0x72, 0xe9,
+ 0x6f, 0xa8, 0x4c, 0xd1, 0x26, 0xef, 0x65, 0xeb,
+ 0x67, 0xff, 0x5f, 0xa7, 0x3b, 0x25, 0xb9, 0x08,
+ 0x8e, 0xa0, 0x47, 0x56, 0xe6, 0x8e, 0xf9, 0xd3,
+ 0x18, 0x06, 0x3d, 0xc6, 0xb1, 0xf8, 0xdc, 0x1b,
+ 0x8d, 0xe5, 0x30, 0x54, 0x26, 0xac, 0x16, 0x3b,
+ 0x7b, 0xad, 0x46, 0x9e, 0x21, 0x6a, 0x57, 0xe6,
+ 0x81, 0x56, 0x1d, 0x2a, 0xc4, 0x39, 0x63, 0x67,
+ 0x81, 0x2c, 0xca, 0xcc, 0xf8, 0x42, 0x04, 0xbe,
+ 0xcf, 0x8f, 0x6c, 0x5b, 0x81, 0x46, 0xb9, 0xc7,
+ 0x62, 0x90, 0x87, 0x35, 0x03, 0x9b, 0x89, 0xcb,
+ 0x37, 0xbd, 0xf1, 0x1b, 0x99, 0xa1, 0x9a, 0x78,
+ 0xd5, 0x4c, 0xdd, 0x3f, 0x41, 0x0c, 0xb7, 0x1a,
+ 0xd9, 0x7b, 0x87, 0x5f, 0xbe, 0xb1, 0x83, 0x41
+};
+
+uint8_t rsa_e[] = {0x01, 0x00, 0x01};
+
+uint8_t rsa_p[] = {
+ 0xdc, 0xba, 0x00, 0x01, 0x57, 0x93, 0xe3, 0x05,
+ 0xed, 0x61, 0x9a, 0xa3, 0xaf, 0x6a, 0xd3, 0x47,
+ 0x8f, 0x2d, 0x1e, 0x7f, 0x4d, 0x60, 0xc8, 0x8d,
+ 0x34, 0xb8, 0x17, 0x84, 0xbc, 0xd4, 0xe9, 0x79,
+ 0x95, 0x75, 0x19, 0x37, 0xe0, 0xcc, 0xfe, 0x4c,
+ 0x5d, 0x49, 0x53, 0x61, 0x29, 0xf1, 0xdc, 0x82,
+ 0x03, 0x96, 0x7d, 0x95, 0x4f, 0xdd, 0x3c, 0x0a,
+ 0x64, 0x8a, 0x43, 0x2f, 0x95, 0x4a, 0xed, 0xdd
+};
+
+uint8_t rsa_q[] = {
+ 0xd0, 0x56, 0x7a, 0x0a, 0xd5, 0x95, 0xa4, 0x85,
+ 0x53, 0x35, 0xa1, 0x48, 0x07, 0x6a, 0x7c, 0x08,
+ 0xe0, 0xfd, 0x4b, 0x88, 0x77, 0xa6, 0x15, 0x23,
+ 0x0f, 0xbf, 0x14, 0x46, 0x11, 0xee, 0x95, 0xc7,
+ 0x5e, 0x77, 0x65, 0xa2, 0xb5, 0x50, 0xdf, 0x19,
+ 0x07, 0xc7, 0x72, 0xdb, 0x29, 0xf6, 0x54, 0x86,
+ 0xe1, 0xb3, 0x97, 0x0a, 0x28, 0x64, 0x3a, 0x38,
+ 0xa6, 0x7d, 0x13, 0xc3, 0x79, 0xaa, 0x56, 0xd9
+};
+
+uint8_t rsa_dP[] = {
+ 0xc5, 0x43, 0x0d, 0x82, 0x25, 0x8c, 0xab, 0x55,
+ 0xbe, 0xc2, 0x7d, 0xfb, 0x4f, 0x68, 0x3f, 0x0e,
+ 0x32, 0xec, 0xf5, 0xd6, 0x7b, 0x86, 0xc5, 0x75,
+ 0x3c, 0xea, 0x51, 0x4a, 0x75, 0xa0, 0x2a, 0x50,
+ 0x58, 0xbb, 0xe0, 0x1f, 0xca, 0x2e, 0x2a, 0x0e,
+ 0x81, 0x48, 0x68, 0xd5, 0xeb, 0x30, 0x96, 0x0b,
+ 0x33, 0xbd, 0xa8, 0xda, 0x6a, 0x17, 0xa3, 0xf2,
+ 0xfd, 0xcb, 0x7b, 0x23, 0xe9, 0x5e, 0x9f, 0x99
+};
+uint8_t rsa_dQ[] = {
+ 0xbe, 0xff, 0xf9, 0x05, 0x43, 0xc8, 0xdc, 0x3b,
+ 0x0b, 0x0d, 0x28, 0xde, 0x73, 0x46, 0x11, 0x8e,
+ 0xc6, 0x4e, 0x11, 0xd8, 0x7b, 0xf0, 0xfc, 0x81,
+ 0xd7, 0x66, 0xd3, 0xbc, 0x65, 0xa6, 0x39, 0x14,
+ 0xbd, 0xab, 0x72, 0xb7, 0x57, 0xc9, 0x5b, 0xaf,
+ 0x83, 0xed, 0x3b, 0x84, 0x68, 0x15, 0x18, 0x6b,
+ 0x4c, 0x32, 0xac, 0x6f, 0x38, 0x96, 0xa2, 0xb5,
+ 0xdb, 0x14, 0xe2, 0x70, 0x9c, 0x73, 0x29, 0x09
+};
+
+uint8_t rsa_qInv[] = {
+ 0x59, 0xbd, 0xb1, 0x37, 0xeb, 0x4e, 0xcf, 0x68,
+ 0xe7, 0x85, 0x91, 0xbb, 0xc0, 0xdb, 0x8e, 0x41,
+ 0x91, 0x4a, 0xc0, 0xb1, 0xc5, 0xe8, 0x91, 0xf6,
+ 0xc7, 0x5a, 0x98, 0x1a, 0x8a, 0x0f, 0x45, 0xb2,
+ 0x5b, 0xff, 0x7a, 0x2d, 0x98, 0x89, 0x55, 0xd9,
+ 0xbf, 0x6e, 0xdd, 0x2d, 0xd4, 0xe8, 0x0a, 0xaa,
+ 0xae, 0x2a, 0xc4, 0x16, 0xb5, 0xba, 0xe1, 0x69,
+ 0x71, 0x94, 0xdd, 0xa0, 0xf5, 0x1e, 0x6d, 0xcc
+};
+
+/** rsa xform using exponent key */
+struct rte_crypto_asym_xform rsa_xform = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+ .rsa = {
+ .n = {
+ .data = rsa_n,
+ .length = sizeof(rsa_n)
+ },
+ .e = {
+ .data = rsa_e,
+ .length = sizeof(rsa_e)
+ },
+ .key_type = RTE_RSA_KEY_TYPE_EXP,
+ .d = {
+ .data = rsa_d,
+ .length = sizeof(rsa_d)
+ }
+ }
+};
+
+/** rsa xform using quintuple key */
+struct rte_crypto_asym_xform rsa_xform_crt = {
+ .next = NULL,
+ .xform_type = RTE_CRYPTO_ASYM_XFORM_RSA,
+ .rsa = {
+ .n = {
+ .data = rsa_n,
+ .length = sizeof(rsa_n)
+ },
+ .e = {
+ .data = rsa_e,
+ .length = sizeof(rsa_e)
+ },
+ .key_type = RTE_RSA_KET_TYPE_QT,
+ .qt = {
+ .p = {
+ .data = rsa_p,
+ .length = sizeof(rsa_p)
+ },
+ .q = {
+ .data = rsa_q,
+ .length = sizeof(rsa_q)
+ },
+ .dP = {
+ .data = rsa_dP,
+ .length = sizeof(rsa_dP)
+ },
+ .dQ = {
+ .data = rsa_dQ,
+ .length = sizeof(rsa_dQ)
+ },
+ .qInv = {
+ .data = rsa_qInv,
+ .length = sizeof(rsa_qInv)
+ },
+ }
+ }
+};
+
+#endif /* TEST_CRYPTODEV_RSA_TEST_VECTORS_H__ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp.c b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp.c
new file mode 100644
index 000000000..30f3eb892
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp.c
@@ -0,0 +1,590 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (C) 2015-2016 Freescale Semiconductor,Inc.
+ * Copyright 2018-2019 NXP
+ */
+
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_pause.h>
+#include <rte_bus_vdev.h>
+#include <rte_byteorder.h>
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_security.h>
+
+#include <rte_lcore.h>
+#include "test.h"
+#include "test_cryptodev_security_pdcp_test_func.h"
+
+static int cplane_encap(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off,
+ enum auth_alg_off auth_alg_off)
+{
+ int i = 0;
+
+ switch (sn_size) {
+ case 5:
+ i = PDCP_CPLANE_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ case 12:
+ i = PDCP_CPLANE_LONG_SN_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ default:
+ printf("\nInvalid SN: %u for %s\n", sn_size, __func__);
+ }
+
+ return test_pdcp_proto_cplane_encap(i);
+}
+
+static int
+cplane_decap(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off,
+ enum auth_alg_off auth_alg_off)
+{
+ int i = 0;
+
+ switch (sn_size) {
+ case 5:
+ i = PDCP_CPLANE_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ case 12:
+ i = PDCP_CPLANE_LONG_SN_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ default:
+ printf("\nInvalid SN: %u for %s\n", sn_size, __func__);
+ }
+
+ return test_pdcp_proto_cplane_decap(i);
+}
+
+static int uplane_encap_no_integrity(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off)
+{
+ int i = PDCP_UPLANE_OFFSET + ((dir == 0) ? UPLINK : DOWNLINK) +
+ enc_alg_off;
+
+ switch (sn_size) {
+ case 7:
+ i += SHORT_SEQ_NUM_OFFSET;
+ break;
+ case 15:
+ i += FIFTEEN_BIT_SEQ_NUM_OFFSET;
+ break;
+ case 12:
+ i += LONG_SEQ_NUM_OFFSET;
+ break;
+ case 18:
+ i += EIGHTEEN_BIT_SEQ_NUM_OFFSET;
+ break;
+ default:
+ printf("\nInvalid SN: %u\n", sn_size);
+ }
+
+ return test_pdcp_proto_uplane_encap(i);
+}
+
+static int
+uplane_decap_no_integrity(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off)
+{
+ int i = PDCP_UPLANE_OFFSET + ((dir == 0) ? UPLINK : DOWNLINK) +
+ enc_alg_off;
+
+ switch (sn_size) {
+ case 7:
+ i += SHORT_SEQ_NUM_OFFSET;
+ break;
+ case 15:
+ i += FIFTEEN_BIT_SEQ_NUM_OFFSET;
+ break;
+ case 12:
+ i += LONG_SEQ_NUM_OFFSET;
+ break;
+ case 18:
+ i += EIGHTEEN_BIT_SEQ_NUM_OFFSET;
+ break;
+ default:
+ printf("\nInvalid SN: %u\n", sn_size);
+ }
+
+ return test_pdcp_proto_uplane_decap(i);
+}
+
+static int
+uplane_encap_with_integrity(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off,
+ enum auth_alg_off auth_alg_off)
+{
+ int i = 0;
+
+ switch (sn_size) {
+ case 12:
+ i = PDCP_UPLANE_12BIT_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ case 18:
+ i = PDCP_UPLANE_18BIT_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ default:
+ printf("\nInvalid SN: %u\n", sn_size);
+ }
+
+ return test_pdcp_proto_uplane_encap_with_int(i);
+}
+
+static int
+uplane_decap_with_integrity(uint32_t sn_size, uint8_t dir,
+ enum enc_alg_off enc_alg_off,
+ enum auth_alg_off auth_alg_off)
+{
+ int i = 0;
+
+ switch (sn_size) {
+ case 12:
+ i = PDCP_UPLANE_12BIT_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ case 18:
+ i = PDCP_UPLANE_18BIT_OFFSET + enc_alg_off +
+ auth_alg_off + ((dir == 0) ?
+ UPLINK : DOWNLINK);
+ break;
+ default:
+ printf("\nInvalid SN: %u\n", sn_size);
+ }
+
+ return test_pdcp_proto_uplane_decap_with_int(i);
+}
+
+#define TEST_PDCP_COUNT(func) do { \
+ if (func == TEST_SUCCESS) { \
+ printf("\t%d)", n++); \
+ printf(#func"-PASS\n"); \
+ i++; \
+ } else { \
+ printf("\t%d)", n++); \
+ printf("+++++ FAILED:" #func"\n"); \
+ } \
+} while (0)
+
+int
+test_PDCP_PROTO_cplane_encap_all(void)
+{
+ int i = 0, n = 0;
+
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(5, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ /* For 12-bit SN */
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, AES_ENC, SNOW_AUTH));
+
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_encap(12, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ if (n - i)
+ printf("## %s: %d passed out of %d\n", __func__, i, n);
+
+ return n - i;
+};
+
+int
+test_PDCP_PROTO_cplane_decap_all(void)
+{
+ int i = 0, n = 0;
+
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(5, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ /* C-plane 12-bit */
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, AES_ENC, SNOW_AUTH));
+
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(cplane_decap(12, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ if (n - i)
+ printf("## %s: %d passed out of %d\n", __func__, i, n);
+
+ return n - i;
+};
+
+int
+test_PDCP_PROTO_uplane_encap_all(void)
+{
+ int i = 0, n = 0;
+
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, DOWNLINK, NULL_ENC));
+
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, DOWNLINK, SNOW_ENC));
+
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, DOWNLINK, AES_ENC));
+
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(12, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(7, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(15, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_encap_no_integrity(18, DOWNLINK, ZUC_ENC));
+
+ /* For 12-bit SN with integrity */
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, NULL_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(12, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ /* For 18-bit SN with integrity */
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, NULL_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_encap_with_integrity(18, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ if (n - i)
+ printf("## %s: %d passed out of %d\n", __func__, i, n);
+
+ return n - i;
+};
+
+int
+test_PDCP_PROTO_uplane_decap_all(void)
+{
+ int i = 0, n = 0;
+
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, DOWNLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, UPLINK, NULL_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, DOWNLINK, NULL_ENC));
+
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, DOWNLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, UPLINK, SNOW_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, DOWNLINK, SNOW_ENC));
+
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, DOWNLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, UPLINK, AES_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, DOWNLINK, AES_ENC));
+
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(12, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(7, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(15, DOWNLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, UPLINK, ZUC_ENC));
+ TEST_PDCP_COUNT(uplane_decap_no_integrity(18, DOWNLINK, ZUC_ENC));
+
+ /* u-plane 12-bit with integrity */
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, NULL_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(12, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ /* u-plane 18-bit with integrity */
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, NULL_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, NULL_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, NULL_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, NULL_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, NULL_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, SNOW_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, SNOW_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, SNOW_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, SNOW_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, SNOW_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, AES_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, AES_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, AES_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, AES_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, AES_ENC, ZUC_AUTH));
+
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, ZUC_ENC, NULL_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, ZUC_ENC, SNOW_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, ZUC_ENC, AES_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, UPLINK, ZUC_ENC, ZUC_AUTH));
+ TEST_PDCP_COUNT(uplane_decap_with_integrity(18, DOWNLINK, ZUC_ENC, ZUC_AUTH));
+
+ if (n - i)
+ printf("## %s: %d passed out of %d\n", __func__, i, n);
+
+ return n - i;
+};
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_func.h b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_func.h
new file mode 100644
index 000000000..f3dc93e2f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_func.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 NXP
+ */
+
+#ifndef SECURITY_PDCP_TEST_FUNC_H_
+#define SECURITY_PDCP_TEST_FUNC_H_
+
+#define PDCP_CPLANE_OFFSET 0
+#define PDCP_CPLANE_LONG_SN_OFFSET 32
+#define PDCP_UPLANE_OFFSET 64
+#define LONG_SEQ_NUM_OFFSET 0
+#define SHORT_SEQ_NUM_OFFSET 2
+#define FIFTEEN_BIT_SEQ_NUM_OFFSET 4
+#define EIGHTEEN_BIT_SEQ_NUM_OFFSET 6
+#define UPLINK 0
+#define DOWNLINK 1
+/* key length(in bytes) for F8 */
+#define F8_KEY_LEN 16
+
+#define PDCP_UPLANE_12BIT_OFFSET (PDCP_UPLANE_OFFSET + 32)
+#define PDCP_UPLANE_18BIT_OFFSET (PDCP_UPLANE_12BIT_OFFSET + 32)
+
+enum enc_alg_off {
+ NULL_ENC = 0,
+ SNOW_ENC = 8,
+ AES_ENC = 16,
+ ZUC_ENC = 24
+};
+enum auth_alg_off {
+ NULL_AUTH = 0,
+ SNOW_AUTH = 2,
+ AES_AUTH = 4,
+ ZUC_AUTH = 6
+};
+
+int test_pdcp_proto_cplane_encap(int i);
+int test_pdcp_proto_uplane_encap(int i);
+int test_pdcp_proto_uplane_encap_with_int(int i);
+int test_pdcp_proto_cplane_decap(int i);
+int test_pdcp_proto_uplane_decap(int i);
+int test_pdcp_proto_uplane_decap_with_int(int i);
+
+int test_PDCP_PROTO_cplane_encap_all(void);
+int test_PDCP_PROTO_cplane_decap_all(void);
+int test_PDCP_PROTO_uplane_encap_all(void);
+int test_PDCP_PROTO_uplane_decap_all(void);
+
+#endif /* SECURITY_PDCP_TEST_FUNC_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_vectors.h
new file mode 100644
index 000000000..703076479
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_security_pdcp_test_vectors.h
@@ -0,0 +1,6323 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (C) 2015-2016 Freescale Semiconductor,Inc.
+ * Copyright 2018-2019 NXP
+ */
+
+#ifndef SECURITY_PDCP_TEST_VECTOR_H_
+#define SECURITY_PDCP_TEST_VECTOR_H_
+
+#include <rte_security.h>
+
+/*
+ * PDCP test vectors and related structures.
+ */
+enum pdcp_dir {
+ PDCP_DIR_UPLINK = 0,
+ PDCP_DIR_DOWNLINK = 1,
+ PDCP_DIR_INVALID
+};
+
+struct pdcp_test_param {
+ uint8_t type;
+ enum rte_security_pdcp_domain domain;
+ enum rte_crypto_cipher_algorithm cipher_alg;
+ uint8_t cipher_key_len;
+ enum rte_crypto_auth_algorithm auth_alg;
+ uint8_t auth_key_len;
+ const char *name;
+};
+
+static struct pdcp_test_param pdcp_test_params[] = {
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+
+ /* For 12-bit C-plane */
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with NULL encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with SNOW f8 encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with AES CTR encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and NULL integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and NULL integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and SNOW f9 integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and SNOW f9 integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and AES CMAC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and AES CMAC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and ZUC integrity Uplink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP Control Plane with ZUC encryption and ZUC integrity Downlink",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Uplink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Downlink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Uplink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Downlink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Uplink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Downlink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Uplink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Downlink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Uplink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Downlink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Uplink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Downlink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Uplink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Downlink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Uplink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Downlink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Uplink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Downlink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Uplink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Downlink with long sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Uplink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Downlink with short sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Uplink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Downlink with 15 bit sequence number",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = 0,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+
+ /********* 12-bit uplane with integrity **************************/
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and NULL integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and NULL integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and SNOW f9 integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and SNOW f9 integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and AES CMAC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and AES CMAC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and ZUC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and ZUC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and NULL integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and NULL integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and SNOW f9 integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and SNOW f9 integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and AES CMAC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and AES CMAC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and ZUC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and ZUC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and NULL integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and NULL integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and SNOW f9 integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and SNOW f9 integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and AES CMAC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and AES CMAC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and ZUC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and ZUC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and NULL integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and NULL integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and SNOW f9 integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and SNOW f9 integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and AES CMAC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and AES CMAC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and ZUC integrity Uplink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and ZUC integrity Downlink with 12 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ /********* 18-bit uplane with integrity **************************/
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and NULL integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and NULL integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and SNOW f9 integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and SNOW f9 integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and AES CMAC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and AES CMAC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and ZUC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with NULL encryption and ZUC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_NULL,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 0,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and NULL integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and NULL integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and SNOW f9 integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and SNOW f9 integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and AES CMAC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and AES CMAC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and ZUC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with SNOW f8 encryption and ZUC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and NULL integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and NULL integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and SNOW f9 integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and SNOW f9 integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and AES CMAC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and AES CMAC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and ZUC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with AES CTR encryption and ZUC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_AES_CTR,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and NULL integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and NULL integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_NULL,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 0,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and SNOW f9 integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and SNOW f9 integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and AES CMAC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and AES CMAC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_AES_CMAC,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and ZUC integrity Uplink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+ {
+ .name =
+ "PDCP User Plane with ZUC encryption and ZUC integrity Downlink with 18 bit SN",
+ .cipher_alg = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+ .auth_alg = RTE_CRYPTO_AUTH_ZUC_EIA3,
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ .cipher_key_len = 16,
+ .auth_key_len = 16,
+ },
+};
+
+static uint32_t pdcp_test_hfn[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x000fa557,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x000fa557,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x000fa557,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x000fa557,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x000fa557,
+
+ /* For 12-bit C-plane ***********************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x01,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x01,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x01,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x01,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x01,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x01,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x01,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x01,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x01,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x01,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x01,
+
+ /* 12-bit C-plane ends ***********************/
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. DL LONG SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/NULL enc. UL 18-bit SN */
+ 0x01,
+ /* User Plane w/NULL enc. DL 18-bit SN */
+ 0x01,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/SNOW f8 enc. UL 18-bit SN */
+ 0x01,
+ /* User Plane w/SNOW f8 enc. DL 18-bit SN */
+ 0x01,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/AES CTR enc. UL 18-bit SN */
+ 0x01,
+ /* User Plane w/AES CTR enc. DL 18-bit SN */
+ 0x01,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ 0x000fa557,
+ /* User Plane w/ZUC enc. UL 18-bit SN */
+ 0x01,
+ /* User Plane w/ZUC enc. DL 18-bit SN */
+ 0x01,
+
+ /********* 12-bit uplane with integrity **************************/
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ 0x01,
+
+ /********* 18-bit uplane with integrity **************************/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ 0x01,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ 0x01,
+};
+
+static uint32_t pdcp_test_hfn_threshold[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x000fa558,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x000fa558,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x000fa558,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x000fa558,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x000fa558,
+
+ /*********** For 12-bit C-plane ***********************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x70C0A,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x70C0A,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x70C0A,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x70C0A,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x70C0A,
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. DL LONG SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/NULL enc. UL 18-bit SN */
+ 0x00002195,
+ /* User Plane w/NULL enc. DL 18-bit SN */
+ 0x00002195,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/SNOW f8 enc. UL 18-bit SN */
+ 0x00000791,
+ /* User Plane w/SNOW f8 enc. DL 18-bit SN */
+ 0x00002195,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/AES CTR enc. UL 18-bit SN */
+ 0x00000791,
+ /* User Plane w/AES CTR enc. DL 18-bit SN */
+ 0x00002195,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ 0x000fa558,
+ /* User Plane w/ZUC enc. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/ZUC enc. DL for 18-bit SN*/
+ 0x00002195,
+
+ /*** u-plane with integrity for 12-bit SN ******/
+
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ 0x70C0A,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ 0x70C0A,
+
+ /*** u-plane with integrity for 18-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x00002195,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ 0x00000791,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ 0x00002195,
+};
+
+static uint8_t pdcp_test_bearer[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x03,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x03,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x03,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x03,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x03,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x03,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x03,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x03,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x03,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x03,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x03,
+
+ /************** For 12-bit C-plane ********************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 0x16,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 0x16,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 0x16,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 0x16,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 0x16,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 0x16,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 0x16,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 0x16,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 0x16,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 0x16,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 0x16,
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ 0x03,
+ /* User Plane w/NULL enc. DL LONG SN */
+ 0x03,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ 0x03,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ 0x03,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ 0x03,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ 0x03,
+ /* User Plane w/NULL enc. UL 18-bit SN */
+ 0x16,
+ /* User Plane w/NULL enc. DL 18-bit SN */
+ 0x16,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ 0x03,
+ /* User Plane w/SNOW f8 enc. UL 18-bit SN */
+ 0x0B,
+ /* User Plane w/SNOW f8 enc. DL 18-bit SN */
+ 0x16,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ 0x03,
+ /* User Plane w/AES CTR enc. UL 18-bit SN */
+ 0x0B,
+ /* User Plane w/AES CTR enc. DL 18-bit SN */
+ 0x16,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ 0x03,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ 0x03,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ 0x03,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ 0x03,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ 0x03,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ 0x03,
+ /* User Plane w/ZUC enc. UL 18-bit SN */
+ 0x0B,
+ /* User Plane w/ZUC enc. DL 18-bit SN */
+ 0x16,
+
+ /*** u-plane with integrity for 12-bit SN ******/
+
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ 0x16,
+
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ 0x16,
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ 0x16,
+
+ /*** u-plane with integrity for 18-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ 0x16,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ 0x0B,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ 0x16,
+
+};
+
+static uint8_t pdcp_test_packet_direction[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+
+ /***************** For 12-bit C-plane **********************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ PDCP_DIR_DOWNLINK,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ PDCP_DIR_UPLINK,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ PDCP_DIR_DOWNLINK,
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. DL LONG SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. UL 18-bit SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. DL 18-bit SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. UL 18-bit SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. DL 18-bit SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. UL 18-bit SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. DL 18-bit SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. UL for 18-bit SN */
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. DL for 18-bit SN */
+ PDCP_DIR_DOWNLINK,
+
+ /*** u-plane with integrity for 12-bit SN ******/
+
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ PDCP_DIR_DOWNLINK,
+
+ /*** u-plane with integrity for 18-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ PDCP_DIR_UPLINK,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ PDCP_DIR_DOWNLINK,
+
+};
+
+static uint8_t pdcp_test_data_sn_size[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 5,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 5,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 5,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 5,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 5,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 5,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 5,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 5,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 5,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 5,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 5,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 5,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 5,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 5,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 5,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 5,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 5,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 5,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 5,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 5,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 5,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 5,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 5,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 5,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 5,
+
+ /*************** 12 bit SN for C-plane **************************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 12,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 12,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 12,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 12,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 12,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 12,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 12,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 12,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 12,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 12,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 12,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 12,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 12,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 12,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 12,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 12,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 12,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 12,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 12,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 12,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 12,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 12,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 12,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 12,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 12,
+ /*************** 12 bit SN for C-plane end **************************/
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ 12,
+ /* User Plane w/NULL enc. DL LONG SN */
+ 12,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ 7,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ 7,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ 15,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ 15,
+ /* User Plane w/NULL enc. UL 18 BIT SN */
+ 18,
+ /* User Plane w/NULL enc. DL 18 BIT SN */
+ 18,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ 12,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ 12,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ 7,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ 7,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ 15,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ 15,
+ /* User Plane w/SNOW f8 enc. UL 18 BIT SN */
+ 18,
+ /* User Plane w/SNOW f8 enc. DL 18 BIT SN */
+ 18,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ 12,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ 12,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ 7,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ 7,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ 15,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ 15,
+ /* User Plane w/AES CTR enc. UL 18 BIT SN */
+ 18,
+ /* User Plane w/AES CTR enc. DL 18 BIT SN */
+ 18,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ 12,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ 12,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ 7,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ 7,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ 15,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ 15,
+ /* User Plane w/ZUC enc. UL 18 BIT SN */
+ 18,
+ /* User Plane w/ZUC enc. DL 18 BIT SN */
+ 18,
+
+ /*** u-plane with integrity for 12-bit SN ******/
+
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ 12,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ 12,
+
+ /*** u-plane with integrity for 18-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ 18,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ 18,
+};
+
+static uint8_t *pdcp_test_crypto_key[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+
+ /*********** C-plane 12-bit **************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ NULL,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ NULL,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ NULL,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ NULL,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ NULL,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ NULL,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ NULL,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ NULL,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. DL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. UL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. DL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/NULL enc. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/SNOW enc. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/SNOW enc. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/AES enc. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/AES enc. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. UL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. DL LONG SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ (uint8_t[]){0x5a, 0xcb, 0x1d, 0x64, 0x4c, 0x0d, 0x51, 0x20, 0x4e, 0xa5,
+ 0xf1, 0x45, 0x10, 0x10, 0xd8, 0x52},
+ /* User Plane w/ZUC enc. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/ZUC enc. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /******* u-plane for 12-bit SN ***********/
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+
+ /******* u-plane for 18-bit SN with integrity ***********/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x60, 0x4C, 0x8A, 0x22, 0x89, 0x56, 0x13, 0x51, 0x7D, 0x61,
+ 0xE5, 0xE0, 0x7B, 0x2B, 0xD0, 0x9E},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x40, 0x19, 0xE2, 0x99, 0x16, 0xC3, 0x7E, 0x9B, 0xA6, 0x8F,
+ 0x57, 0xBE, 0x97, 0xFD, 0x02, 0xCB},
+};
+
+static uint8_t *pdcp_test_auth_key[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0xc7, 0x36, 0xc6, 0xaa, 0xb2, 0x2b, 0xff, 0xf9, 0x1e, 0x26,
+ 0x98, 0xd2, 0xe2, 0x2a, 0xd5, 0x7e},
+
+ /********* 12-bit C-plane **********************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ NULL,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ NULL,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ NULL,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ NULL,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ NULL,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ NULL,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ NULL,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ NULL,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ NULL,
+ /* User Plane w/NULL enc. DL LONG SN */
+ NULL,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ NULL,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ NULL,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ NULL,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ NULL,
+ /* User Plane w/NULL enc. UL 18 BIT SN */
+ NULL,
+ /* User Plane w/NULL enc. DL 18 BIT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. UL 18 BIT SN */
+ NULL,
+ /* User Plane w/SNOW f8 enc. DL 18 BIT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ NULL,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ NULL,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. UL 18 BIT SN */
+ NULL,
+ /* User Plane w/AES CTR enc. DL 18 BIT SN */
+ NULL,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ NULL,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ NULL,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ NULL,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ NULL,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ NULL,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ NULL,
+ /* User Plane w/ZUC enc. UL 18 BIT SN */
+ NULL,
+ /* User Plane w/ZUC enc. DL 18 BIT SN */
+ NULL,
+
+ /***** u-plane with integrity for 12-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ NULL,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ NULL,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+
+ /***** u-plane with integrity for 18-bit SN ******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ NULL,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ NULL,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x1A, 0xEF, 0xBB, 0xFF, 0x00, 0xF5, 0x4B, 0x32, 0x87, 0xF9,
+ 0xDB, 0xE0, 0x31, 0x5F, 0x3A, 0x15},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0x4D, 0x4B, 0x2B, 0x1E, 0x39, 0x60, 0x0A, 0x98, 0xC1, 0x3C,
+ 0x98, 0x82, 0xDC, 0xB6, 0xC2, 0x36},
+};
+
+static uint8_t *pdcp_test_data_in[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+
+ /*************** 12-bit C-plane ****************/
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/NULL enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/SNOW enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/SNOW enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/AES enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/AES enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/ZUC enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/ZUC enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/ZUC enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+
+ /*************** u-plane with integrity for 12-bit SN *****/
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53,
+ 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB,
+ 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91,
+ 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0,
+ 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70,
+ 0x1B, 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+
+ /*************** u-plane with integrity for 18-bit SN *****/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69},
+};
+
+static uint32_t pdcp_test_data_in_len[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ 16,
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ 16,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ 16,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ 16,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ 16,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ 16,
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ 16,
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 16,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 16,
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 16,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 16,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 16,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 16,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 16,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 16,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 16,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 16,
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 16,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 16,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 16,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 16,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 16,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 16,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 16,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 16,
+
+ /****************** C-plane 12-bit SN ***********/
+ /* Control Plane w/NULL enc. + NULL int. UL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + NULL int. DL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + AES CMAC int. UL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + AES CMAC int. DL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + ZUC int. UL LONG SN */
+ 66,
+ /* Control Plane w/NULL enc. + ZUC int. DL LONG SN */
+ 66,
+
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL LONG SN */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL LONG SN */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL LONG SN */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL LONG SN */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL LONG SN */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ 66,
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ 66,
+
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ 66,
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ 66,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ 66,
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ 66,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ 66,
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ 66,
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ 66,
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ 66,
+
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ 66,
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ 66,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ 66,
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ 66,
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ 66,
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ 66,
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ 66,
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ 66,
+
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ 17,
+ /* User Plane w/NULL enc. DL LONG SN */
+ 17,
+ /* User Plane w/NULL enc. UL SHORT SN */
+ 16,
+ /* User Plane w/NULL enc. DL SHORT SN */
+ 16,
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ 17,
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ 17,
+ /* User Plane w/NULL enc. UL 18 BIT SN */
+ 71,
+ /* User Plane w/NULL enc. DL 18 BIT SN */
+ 71,
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ 17,
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ 17,
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ 16,
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ 16,
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ 17,
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ 17,
+ /* User Plane w/SNOW f8 enc. UL 18 BIT SN */
+ 71,
+ /* User Plane w/SNOW f8 enc. DL 18 BIT SN */
+ 71,
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ 17,
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ 17,
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ 16,
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ 16,
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ 17,
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ 17,
+ /* User Plane w/AES CTR enc. UL 18 BIT SN */
+ 71,
+ /* User Plane w/AES CTR enc. DL 18 BIT SN */
+ 71,
+ /* User Plane w/ZUC enc. UL LONG SN */
+ 17,
+ /* User Plane w/ZUC enc. DL LONG SN */
+ 17,
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ 16,
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ 16,
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ 17,
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ 17,
+ /* User Plane w/ZUC enc. UL 18 BIT SN */
+ 71,
+ /* User Plane w/ZUC enc. DL 18 BIT SN */
+ 71,
+
+ /***** u-plane with integrity for 12-bit SN *******/
+
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN */
+ 66,
+
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN */
+ 66,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN */
+ 66,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN */
+ 66,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN*/
+ 66,
+
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN*/
+ 66,
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN*/
+ 66,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN*/
+ 66,
+
+ /***** u-plane with integrity for 18-bit SN *******/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN */
+ 67,
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN*/
+ 67,
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN*/
+ 67,
+};
+
+static uint8_t *pdcp_test_data_out[] = {
+ /* Control Plane w/NULL enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x00, 0x00, 0x00, 0x00},
+ /* Control Plane w/NULL enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x00, 0x00, 0x00, 0x00},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x88, 0x7f, 0x4e, 0x59},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x9d, 0x9e, 0x45, 0x36},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0xf3, 0xdd, 0x01, 0xdf},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x5d, 0x8e, 0x5d, 0x05},
+ /* Control Plane w/NULL enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x18, 0xc3, 0x2e, 0x66},
+ /* Control Plane w/NULL enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8, 0x72, 0x44, 0xab, 0x64},
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0x39, 0xd1, 0x2b, 0xbd, 0x2a, 0x4c, 0x91, 0x59, 0xff,
+ 0xfa, 0xce, 0x68, 0xc0, 0x7c, 0x30, 0xd0, 0xc5, 0x08, 0x58},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0x26, 0xf3, 0x67, 0xf1, 0x42, 0x50, 0x1a, 0x85, 0x02,
+ 0xb9, 0x00, 0xa8, 0x9b, 0xcf, 0x06, 0xd1, 0x2c, 0x86, 0x7c},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0x39, 0xd1, 0x2b, 0xbd, 0x2a, 0x4c, 0x91, 0x59, 0xff,
+ 0xfa, 0xce, 0x68, 0xc0, 0x7c, 0x30, 0x58, 0xba, 0x46, 0x01},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0x26, 0xf3, 0x67, 0xf1, 0x42, 0x50, 0x1a, 0x85, 0x02,
+ 0xb9, 0x00, 0xa8, 0x9b, 0xcf, 0x06, 0x4c, 0xb2, 0xc3, 0x4a},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0x39, 0xd1, 0x2b, 0xbd, 0x2a, 0x4c, 0x91, 0x59, 0xff,
+ 0xfa, 0xce, 0x68, 0xc0, 0x7c, 0x30, 0x23, 0x18, 0x09, 0x87},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0x26, 0xf3, 0x67, 0xf1, 0x42, 0x50, 0x1a, 0x85, 0x02,
+ 0xb9, 0x00, 0xa8, 0x9b, 0xcf, 0x06, 0x8c, 0xa2, 0xdb, 0x79},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0x39, 0xd1, 0x2b, 0xbd, 0x2a, 0x4c, 0x91, 0x59, 0xff,
+ 0xfa, 0xce, 0x68, 0xc0, 0x7c, 0x30, 0xc8, 0x06, 0x26, 0x3e},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0x26, 0xf3, 0x67, 0xf1, 0x42, 0x50, 0x1a, 0x85, 0x02,
+ 0xb9, 0x00, 0xa8, 0x9b, 0xcf, 0x06, 0xa3, 0x68, 0x2d, 0x18},
+ /* Control Plane w/AES CTR enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0x2c, 0x59, 0x74, 0xab, 0xdc, 0xd8, 0x36, 0xf6, 0x1b,
+ 0x54, 0x8d, 0x46, 0x93, 0x1c, 0xff, 0x32, 0x4f, 0x1a, 0x6b},
+ /* Control Plane w/AES CTR enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0xf2, 0xb9, 0x9d, 0x96, 0x51, 0xcc, 0x1e, 0xe8, 0x55,
+ 0x3e, 0x98, 0xc5, 0x58, 0xec, 0x4c, 0x92, 0x40, 0x52, 0x8e},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0x2c, 0x59, 0x74, 0xab, 0xdc, 0xd8, 0x36, 0xf6, 0x1b,
+ 0x54, 0x8d, 0x46, 0x93, 0x1c, 0xff, 0xba, 0x30, 0x54, 0x32},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0xf2, 0xb9, 0x9d, 0x96, 0x51, 0xcc, 0x1e, 0xe8, 0x55,
+ 0x3e, 0x98, 0xc5, 0x58, 0xec, 0x4c, 0x0f, 0xde, 0x17, 0xb8},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0x2c, 0x59, 0x74, 0xab, 0xdc, 0xd8, 0x36, 0xf6, 0x1b,
+ 0x54, 0x8d, 0x46, 0x93, 0x1c, 0xff, 0xc1, 0x92, 0x1b, 0xb4},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0xf2, 0xb9, 0x9d, 0x96, 0x51, 0xcc, 0x1e, 0xe8, 0x55,
+ 0x3e, 0x98, 0xc5, 0x58, 0xec, 0x4c, 0xcf, 0xce, 0x0f, 0x8b},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0x2c, 0x59, 0x74, 0xab, 0xdc, 0xd8, 0x36, 0xf6, 0x1b,
+ 0x54, 0x8d, 0x46, 0x93, 0x1c, 0xff, 0x2a, 0x8c, 0x34, 0x0d},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0xf2, 0xb9, 0x9d, 0x96, 0x51, 0xcc, 0x1e, 0xe8, 0x55,
+ 0x3e, 0x98, 0xc5, 0x58, 0xec, 0x4c, 0xe0, 0x04, 0xf9, 0xea},
+ /* Control Plane w/ZUC enc. + NULL int. UL */
+ (uint8_t[]){0x8b, 0xa6, 0x23, 0xf8, 0xca, 0x98, 0x03, 0x33, 0x81, 0x8a,
+ 0x6b, 0xfe, 0x37, 0xf2, 0x20, 0xd6, 0x68, 0x82, 0xb9, 0x06},
+ /* Control Plane w/ZUC enc. + NULL int. DL */
+ (uint8_t[]){0x8b, 0x3b, 0x42, 0xfc, 0x73, 0x83, 0x09, 0xb1, 0x3f, 0x66,
+ 0x86, 0x3a, 0x5d, 0xe7, 0x47, 0xf4, 0x44, 0x81, 0x49, 0x0e},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL */
+ (uint8_t[]){0x8b, 0xa6, 0x23, 0xf8, 0xca, 0x98, 0x03, 0x33, 0x81, 0x8a,
+ 0x6b, 0xfe, 0x37, 0xf2, 0x20, 0xd6, 0xe0, 0xfd, 0xf7, 0x5f},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL */
+ (uint8_t[]){0x8b, 0x3b, 0x42, 0xfc, 0x73, 0x83, 0x09, 0xb1, 0x3f, 0x66,
+ 0x86, 0x3a, 0x5d, 0xe7, 0x47, 0xf4, 0xd9, 0x1f, 0x0c, 0x38},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL */
+ (uint8_t[]){0x8b, 0xa6, 0x23, 0xf8, 0xca, 0x98, 0x03, 0x33, 0x81, 0x8a,
+ 0x6b, 0xfe, 0x37, 0xf2, 0x20, 0xd6, 0x9b, 0x5f, 0xb8, 0xd9},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL */
+ (uint8_t[]){0x8b, 0x3b, 0x42, 0xfc, 0x73, 0x83, 0x09, 0xb1, 0x3f, 0x66,
+ 0x86, 0x3a, 0x5d, 0xe7, 0x47, 0xf4, 0x19, 0x0f, 0x14, 0x0b},
+ /* Control Plane w/ZUC enc. + ZUC int. UL */
+ (uint8_t[]){0x8b, 0xa6, 0x23, 0xf8, 0xca, 0x98, 0x03, 0x33, 0x81, 0x8a,
+ 0x6b, 0xfe, 0x37, 0xf2, 0x20, 0xd6, 0x70, 0x41, 0x97, 0x60},
+ /* Control Plane w/ZUC enc. + ZUC int. DL */
+ (uint8_t[]){0x8b, 0x3b, 0x42, 0xfc, 0x73, 0x83, 0x09, 0xb1, 0x3f, 0x66,
+ 0x86, 0x3a, 0x5d, 0xe7, 0x47, 0xf4, 0x36, 0xc5, 0xe2, 0x6a},
+
+ /************ C-plane 12-bit ****************************/
+ /* Control Plane w/NULL enc. + NULL int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + NULL int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* Control Plane w/NULL enc. + SNOW f9 int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x74, 0xB8, 0x27, 0x96},
+ /* Control Plane w/NULL enc. + SNOW f9 int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x97, 0x50, 0x3F, 0xF7},
+ /* Control Plane w/NULL enc. + AES CMAC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x3F, 0x71, 0x26, 0x2E},
+ /* Control Plane w/NULL enc. + AES CMAC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xE8, 0xBB, 0xE9, 0x36},
+ /* Control Plane w/NULL enc. + ZUC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x54, 0xEF, 0x25, 0xC3},
+ /* Control Plane w/NULL enc. + ZUC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x76, 0xD0, 0x5B, 0x2C},
+
+ /* Control Plane w/SNOW f8 enc. + NULL int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x12, 0x07, 0xAC, 0x93},
+ /* Control Plane w/SNOW f8 enc. + NULL int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0xDC, 0x32, 0x96, 0x65},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x66, 0xBF, 0x8B, 0x05},
+ /* Control Plane w/SNOW f8 enc. + SNOW f9 int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0x4B, 0x62, 0xA9, 0x92},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x2D, 0x76, 0x8A, 0xBD},
+ /* Control Plane w/SNOW f8 enc. + AES CMAC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0x34, 0x89, 0x7F, 0x53},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x46, 0xE8, 0x89, 0x50},
+ /* Control Plane w/SNOW f8 enc. + ZUC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0xAA, 0xE2, 0xCD, 0x49},
+
+ /* Control Plane w/AES CTR enc. + NULL int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0x86, 0x33, 0x3F, 0x3C},
+
+ /* Control Plane w/AES CTR enc. + NULL int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x87, 0x7A, 0x32, 0x1B},
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xF2, 0x8B, 0x18, 0xAA},
+
+ /* Control Plane w/AES CTR enc. + SNOW f9 int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x10, 0x2A, 0x0D, 0xEC},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xB9, 0x42, 0x19, 0x12},
+ /* Control Plane w/AES CTR enc. + AES CMAC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x6F, 0xC1, 0xDB, 0x2D},
+ /* Control Plane w/AES CTR enc. + ZUC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xD2, 0xDC, 0x1A, 0xFF},
+ /* Control Plane w/AES CTR enc. + ZUC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0xF1, 0xAA, 0x69, 0x37},
+ /* Control Plane w/ZUC enc. + NULL int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x1D, 0xCD, 0x3A, 0xE0},
+ /* Control Plane w/ZUC enc. + NULL int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x90, 0xF5, 0xBD, 0x56},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x69, 0x75, 0x1D, 0x76},
+ /* Control Plane w/ZUC enc. + SNOW f9 int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x07, 0xA5, 0x82, 0xA1},
+ /* Control Plane w/ZUC enc. + AES CMAC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x22, 0xBC, 0x1C, 0xCE},
+ /* Control Plane w/ZUC enc. + AES CMAC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x78, 0x4E, 0x54, 0x60},
+ /* Control Plane w/ZUC enc. + ZUC int. UL LONG SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x49, 0x22, 0x1F, 0x23},
+ /* Control Plane w/ZUC enc. + ZUC int. DL LONG SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0xE6, 0x25, 0xE6, 0x7A},
+
+ /* User Plane w/NULL enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4, 0x57,
+ 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xad, 0x9c, 0x44, 0x1f, 0x89, 0x0b, 0x38, 0xc4,
+ 0x57, 0xa4, 0x9d, 0x42, 0x14, 0x07, 0xe8},
+ /* User Plane w/NULL enc. UL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/NULL enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/SNOW f8 enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0x7a, 0xe0, 0x00, 0x07, 0x2a, 0xa6, 0xef, 0xdc,
+ 0x75, 0xef, 0x2e, 0x27, 0x0f, 0x69, 0x3d},
+ /* User Plane w/SNOW f8 enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0x7e, 0xbb, 0x80, 0x20, 0xba, 0xef, 0xe7, 0xf7,
+ 0xef, 0x69, 0x51, 0x85, 0x09, 0xa5, 0xab},
+ /* User Plane w/SNOW f8 enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0x80, 0xcf, 0xe5, 0x27, 0xe2, 0x88, 0x2a, 0xac, 0xc5,
+ 0xaf, 0x49, 0x9b, 0x3e, 0x48, 0x89},
+ /* User Plane w/SNOW f8 enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xe2, 0x51, 0x58, 0x88, 0xff, 0x1a, 0x00, 0xe4, 0x67,
+ 0x05, 0x46, 0x24, 0x2f, 0x07, 0xb7},
+ /* User Plane w/SNOW f8 enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xbe, 0x72, 0x05, 0x78, 0x92, 0xec, 0xb1, 0x4f,
+ 0xdd, 0x5d, 0xfc, 0x60, 0x2c, 0x9a, 0x85},
+ /* User Plane w/SNOW f8 enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0x0b, 0x50, 0xf3, 0xff, 0x37, 0xe3, 0x6b, 0xaf,
+ 0x08, 0xd8, 0xf6, 0x1f, 0xca, 0x6f, 0xbc},
+ /* User Plane w/SNOW enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x9A, 0xAF, 0x1D, 0x21, 0x2F, 0x48, 0xB2, 0x30,
+ 0xCF, 0xBB, 0x8A, 0x2C, 0xB7, 0x57, 0xB6, 0x27, 0x89, 0x0D, 0x91,
+ 0x03, 0x2C, 0x2B, 0x8D, 0x29, 0x4A, 0xBD, 0x8D, 0x48, 0xD2, 0x69,
+ 0x37, 0xB1, 0xA1, 0x97, 0x12, 0xBD, 0x0A, 0x91, 0x4D, 0xEB, 0x76,
+ 0xC8, 0x96, 0x7A, 0x0A, 0x25, 0x08, 0xEB, 0x41, 0x30, 0x00, 0x33,
+ 0xC7, 0xFF, 0x33, 0x4E, 0xC1, 0xFE, 0x5C, 0x0F, 0x15, 0xE7, 0x9F,
+ 0x31, 0x55, 0xDA, 0x18, 0x4D},
+ /* User Plane w/SNOW enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x22, 0x2D, 0x15, 0xBA, 0x95, 0xAC, 0x47, 0x5A,
+ 0xE3, 0x90, 0x82, 0xEA, 0xC2, 0x93, 0x80, 0x23, 0xE9, 0xAC, 0xEA, 0x5D,
+ 0xAA, 0x70, 0x42, 0x04, 0x7C, 0xE6, 0xA6, 0x1D, 0x91, 0xAE, 0x2E, 0x43,
+ 0x60, 0x39, 0x23, 0x06, 0xD2, 0x31, 0x73, 0x98, 0xF0, 0x61, 0x47, 0xB5,
+ 0xC4, 0xB0, 0xB8, 0x31, 0x50, 0x9E, 0x37, 0x15, 0x0E, 0x0D, 0x29, 0x9D,
+ 0xB3, 0x78, 0xFB, 0x9D, 0x5C, 0x90, 0xF8, 0x80, 0x53, 0x93, 0xEF, 0x7C},
+ /* User Plane w/AES CTR enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xde, 0x0a, 0x59, 0xca, 0x7d, 0x93, 0xa3, 0xb5,
+ 0xd2, 0x88, 0xb3, 0x04, 0xa2, 0x12, 0x09},
+ /* User Plane w/AES CTR enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0x69, 0x92, 0x25, 0xd8, 0xe9, 0xd5, 0xe9, 0x53,
+ 0x60, 0x49, 0x9f, 0xe9, 0x8f, 0xbe, 0x6a},
+ /* User Plane w/AES CTR enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0x0f, 0xa1, 0xf2, 0x56, 0x6e, 0xee, 0x62, 0x1c, 0x62,
+ 0x06, 0x7e, 0x38, 0x4a, 0x02, 0xa4},
+ /* User Plane w/AES CTR enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0x00, 0x8d, 0x50, 0x80, 0x30, 0xda, 0xc7, 0x14, 0xc5,
+ 0xe0, 0xc8, 0xfb, 0x83, 0xd0, 0x73},
+ /* User Plane w/AES CTR enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xa1, 0x2e, 0xa3, 0x64, 0xa9, 0x81, 0xbc, 0xd3,
+ 0x6f, 0xef, 0xee, 0x30, 0x71, 0x23, 0x85},
+ /* User Plane w/AES CTR enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xc7, 0xf2, 0x23, 0xb3, 0xbe, 0xc0, 0xdf, 0xc5,
+ 0xed, 0x37, 0x35, 0x7c, 0x66, 0xa3, 0xf9},
+ /* User Plane w/AES enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xBF, 0x31, 0x94, 0xCF, 0x6E, 0x99, 0x84, 0x08,
+ 0xF1, 0x90, 0xC2, 0x22, 0xD0, 0xD2, 0x3D, 0x44, 0x75, 0x7F, 0xC5, 0x0F,
+ 0xAC, 0x7C, 0x18, 0x46, 0xA5, 0x3E, 0x2F, 0x0F, 0x26, 0x9E, 0x5A, 0x49,
+ 0xF7, 0xCB, 0x70, 0x17, 0xBC, 0x01, 0x1D, 0xA3, 0x65, 0x0E, 0x4B, 0x53,
+ 0x14, 0x73, 0x76, 0xDE, 0x54, 0xA0, 0xF9, 0x4C, 0xC2, 0x8F, 0x02, 0x88,
+ 0x36, 0xC7, 0xC4, 0x5A, 0x57, 0x7D, 0xA1, 0x0D, 0xC1, 0x66, 0x96, 0xC8},
+ /* User Plane w/AES enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x01, 0x0D, 0x4B, 0x5E, 0xD3, 0xCE, 0x96, 0xE1,
+ 0x9A, 0x9D, 0xB3, 0x01, 0xD6, 0x40, 0x50, 0x00, 0x6C, 0x63, 0xFD, 0x37,
+ 0xD9, 0xBB, 0x3B, 0x76, 0xE5, 0x7D, 0x3C, 0xFC, 0xE3, 0x9D, 0x45, 0x4A,
+ 0x07, 0x14, 0xD3, 0x14, 0xBC, 0x7E, 0x57, 0xAB, 0xB0, 0x8D, 0x8F, 0x42,
+ 0x39, 0x22, 0xB2, 0xF6, 0x5F, 0xBD, 0x58, 0xE3, 0xE0, 0xDB, 0xD5, 0x7F,
+ 0xFB, 0x78, 0x95, 0xE1, 0x5E, 0x36, 0xF8, 0x52, 0x98, 0x15, 0x68, 0x35},
+ /* User Plane w/ZUC enc. UL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0xfb, 0xb6, 0x0e, 0x81, 0xa1, 0x9e, 0xc8, 0xeb,
+ 0x90, 0xa8, 0xc7, 0x0e, 0x27, 0xcb, 0xb0},
+ /* User Plane w/ZUC enc. DL LONG SN */
+ (uint8_t[]){0x8b, 0x26, 0x2f, 0x5d, 0xa4, 0x82, 0xfb, 0xce, 0x1f, 0x3a,
+ 0xb5, 0x66, 0x60, 0x40, 0x65, 0x2b, 0x40},
+ /* User Plane w/ZUC enc. UL SHORT SN */
+ (uint8_t[]){0x8b, 0xcb, 0x75, 0x03, 0xd5, 0xed, 0xea, 0x73, 0x39, 0xf5,
+ 0x07, 0x03, 0x04, 0x51, 0xc9, 0x5e},
+ /* User Plane w/ZUC enc. DL SHORT SN */
+ (uint8_t[]){0x8b, 0xe9, 0xd2, 0x49, 0x7f, 0xfd, 0x98, 0x9f, 0xc4, 0x6a,
+ 0xcb, 0xe6, 0x4e, 0x21, 0x33, 0xd2},
+ /* User Plane w/ZUC enc. UL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0x01, 0x0a, 0xba, 0x79, 0xf8, 0xe5, 0x9f, 0x22,
+ 0x37, 0xab, 0x5c, 0x7e, 0xad, 0xd6, 0x6b},
+ /* User Plane w/ZUC enc. DL 15 BIT SN */
+ (uint8_t[]){0x8b, 0x26, 0xa3, 0x1a, 0x1e, 0x22, 0xf7, 0x17, 0x8a, 0xb5,
+ 0x59, 0xd8, 0x2b, 0x13, 0xdd, 0x12, 0x4e},
+ /* User Plane w/ZUC enc. UL for 18-bit SN*/
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x32, 0xF9, 0x21, 0x1D, 0xBB, 0xF8, 0xE5, 0x7C,
+ 0x74, 0xC2, 0xD7, 0xFF, 0x74, 0x59, 0x3A, 0x69, 0xD1, 0x8B, 0x65, 0x98,
+ 0xB9, 0x3C, 0xFB, 0x63, 0xB1, 0x9E, 0xB7, 0xCA, 0x04, 0x68, 0xB9, 0xAB,
+ 0xA2, 0x5A, 0xAF, 0x15, 0x8E, 0x71, 0xED, 0xE4, 0xFA, 0x99, 0x79, 0xF9,
+ 0x51, 0x54, 0x82, 0x69, 0x4C, 0x45, 0x0B, 0xFA, 0x87, 0x4D, 0x97, 0x6E,
+ 0xB0, 0xC9, 0x06, 0x08, 0x6B, 0xFC, 0x4A, 0x85, 0x43, 0x62, 0x73, 0xD8},
+ /* User Plane w/ZUC enc. DL for 18-bit SN*/
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x30, 0x62, 0x48, 0xC0, 0xB1, 0xED, 0x1F, 0x13,
+ 0x8A, 0x7A, 0x62, 0x40, 0x12, 0x35, 0x54, 0x03, 0x93, 0xBD, 0xE5, 0x88,
+ 0x51, 0x38, 0xB5, 0x89, 0xC6, 0xD3, 0xB5, 0x44, 0xC2, 0xB9, 0xB9, 0x59,
+ 0x7C, 0xEC, 0x71, 0xD8, 0x42, 0x01, 0x03, 0x3C, 0x0E, 0xBB, 0x7B, 0xDD,
+ 0x7D, 0x2D, 0xE0, 0x3C, 0xE3, 0x81, 0xAA, 0xEA, 0xCC, 0xD7, 0xFC, 0x46,
+ 0x07, 0x7C, 0x8E, 0x8E, 0x0E, 0x99, 0xB8, 0x31, 0x65, 0x17, 0xF6, 0xE3},
+
+ /************************* 12-bit u-plane with int ************/
+ /* User Plane w/NULL enc. + NULL int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + NULL int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD},
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x74, 0xB8, 0x27, 0x96},
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x97, 0x50, 0x3F, 0xF7},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x3F, 0x71, 0x26, 0x2E},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xE8, 0xBB, 0xE9, 0x36},
+ /* User Plane w/NULL enc. + ZUC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x54, 0xEF, 0x25, 0xC3},
+ /* User Plane w/NULL enc. + ZUC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x86, 0xB8, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82,
+ 0x53, 0xFD, 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71,
+ 0xFB, 0xEB, 0x35, 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57,
+ 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70,
+ 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F, 0xEE, 0x2C,
+ 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0x76, 0xD0, 0x5B, 0x2C},
+
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x12, 0x07, 0xAC, 0x93},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0xDC, 0x32, 0x96, 0x65},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x66, 0xBF, 0x8B, 0x05},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0x4B, 0x62, 0xA9, 0x92},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x2D, 0x76, 0x8A, 0xBD},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0x34, 0x89, 0x7F, 0x53},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0xD6, 0xCC, 0xB5, 0xCE, 0x7C, 0xF8, 0xBE, 0x68,
+ 0x2B, 0xAB, 0xC7, 0x32, 0xDA, 0x49, 0xD0, 0xC7, 0x54, 0xCA,
+ 0x18, 0xBB, 0x05, 0x6D, 0xC5, 0x5F, 0xD3, 0xA7, 0xE6, 0xD8,
+ 0xE1, 0xDF, 0x7C, 0x4F, 0x3C, 0x8B, 0x86, 0xC6, 0x8E, 0x24,
+ 0xF7, 0xBC, 0x45, 0x2A, 0x2E, 0xB4, 0xF5, 0xD0, 0x39, 0x5B,
+ 0x70, 0xB4, 0x53, 0x90, 0x98, 0x8A, 0x7C, 0x87, 0x21, 0xED,
+ 0x76, 0x83, 0x63, 0x39, 0x2C, 0xDB, 0x46, 0xE8, 0x89, 0x50},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0xC1, 0x3A, 0x28, 0xBC, 0xEB, 0xAC, 0x49, 0xB9,
+ 0xA1, 0xFC, 0xD6, 0x83, 0xEC, 0xA2, 0x89, 0xE6, 0x8F, 0xCA,
+ 0x77, 0x62, 0xF8, 0x55, 0xC6, 0x8B, 0x25, 0x7B, 0xA3, 0xAF,
+ 0x67, 0x6A, 0xEB, 0x45, 0x18, 0x0B, 0xD6, 0x03, 0xDD, 0xFC,
+ 0xDE, 0x74, 0x3C, 0x4C, 0x7F, 0x5E, 0x67, 0x25, 0x9F, 0xC9,
+ 0x0F, 0xD8, 0x38, 0xE6, 0x3F, 0xD4, 0x59, 0x7A, 0x9A, 0xB7,
+ 0xF4, 0x52, 0xC6, 0x66, 0xC2, 0x73, 0xAA, 0xE2, 0xCD, 0x49},
+ /* User Plane w/AES CTR enc. + NULL int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0x86, 0x33, 0x3F, 0x3C},
+
+ /* User Plane w/AES CTR enc. + NULL int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x87, 0x7A, 0x32, 0x1B},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xF2, 0x8B, 0x18, 0xAA},
+
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x10, 0x2A, 0x0D, 0xEC},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xB9, 0x42, 0x19, 0x12},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0x6F, 0xC1, 0xDB, 0x2D},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x57, 0xB2, 0x7E, 0x21, 0xE7, 0xDD, 0x56, 0xCF,
+ 0xE9, 0x97, 0x27, 0xE8, 0xA3, 0xDE, 0x4C, 0xF6, 0xD1, 0x10,
+ 0x4A, 0x7D, 0xC0, 0xD0, 0xF7, 0x1B, 0x3E, 0x16, 0xF0, 0xA8,
+ 0x4F, 0xBC, 0x17, 0x73, 0x9A, 0x69, 0x73, 0x6C, 0x83, 0xE5,
+ 0x9D, 0x56, 0xBA, 0xF7, 0x08, 0x6D, 0xC5, 0x89, 0xFB, 0xAB,
+ 0x99, 0xD1, 0x37, 0x42, 0x89, 0x8F, 0xE1, 0xAE, 0xA3, 0x22,
+ 0x60, 0x98, 0xFD, 0x79, 0x32, 0xDB, 0xD2, 0xDC, 0x1A, 0xFF},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x84, 0x3D, 0x5A, 0x2C, 0xBA, 0x02, 0xC1, 0x6C,
+ 0x8D, 0x78, 0xB5, 0x1F, 0x51, 0x70, 0x18, 0x61, 0x92, 0x10,
+ 0x18, 0xD1, 0x25, 0xB4, 0x4B, 0x24, 0x94, 0xAE, 0x6D, 0x45,
+ 0xA7, 0x00, 0x01, 0xF8, 0x97, 0x9F, 0xF9, 0x58, 0xD6, 0x62,
+ 0x30, 0x7D, 0xE9, 0x41, 0x69, 0x65, 0x1C, 0xBA, 0x79, 0x54,
+ 0x7E, 0xF5, 0xBD, 0x60, 0xEB, 0x9E, 0xC2, 0xC9, 0x54, 0x65,
+ 0x7D, 0xAC, 0xB6, 0x47, 0xFF, 0x1C, 0xF1, 0xAA, 0x69, 0x37},
+
+ /* User Plane w/ZUC enc. + NULL int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x1D, 0xCD, 0x3A, 0xE0},
+ /* User Plane w/ZUC enc. + NULL int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x90, 0xF5, 0xBD, 0x56},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x69, 0x75, 0x1D, 0x76},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x07, 0xA5, 0x82, 0xA1},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x22, 0xBC, 0x1C, 0xCE},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0x78, 0x4E, 0x54, 0x60},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 12-bit SN */
+ (uint8_t[]){0x50, 0x01, 0x47, 0x9B, 0x21, 0xD1, 0xB2, 0x99, 0x23, 0x56,
+ 0xC5, 0xFF, 0xC2, 0xB7, 0x7D, 0x30, 0xBA, 0xFB, 0x43, 0xED,
+ 0x79, 0xC9, 0x9D, 0x9D, 0x38, 0x35, 0xC6, 0x7B, 0xD0, 0xAA,
+ 0x33, 0x08, 0x88, 0x72, 0x16, 0x1D, 0xF7, 0xA0, 0xD9, 0xEC,
+ 0x73, 0x45, 0x51, 0x87, 0xFF, 0x64, 0xFB, 0x3C, 0xA6, 0xB5,
+ 0xD0, 0x1C, 0xD6, 0x90, 0x3D, 0x40, 0x54, 0x22, 0x2F, 0x6C,
+ 0xE4, 0xB1, 0x71, 0x15, 0x78, 0x54, 0x49, 0x22, 0x1F, 0x23},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 12-bit SN */
+ (uint8_t[]){0xA0, 0x00, 0x3F, 0x01, 0xCE, 0xBD, 0x8A, 0x98, 0x7B, 0x26,
+ 0xF1, 0x28, 0x74, 0xDC, 0x26, 0x2B, 0x02, 0xE8, 0x9C, 0xBC,
+ 0x98, 0x41, 0xC5, 0x03, 0x57, 0x48, 0x83, 0xBB, 0x8E, 0xCA,
+ 0x87, 0xCD, 0x8B, 0xE9, 0x96, 0x2A, 0x35, 0x5C, 0xD3, 0x32,
+ 0x53, 0xA7, 0x12, 0xC2, 0xBC, 0x0C, 0x75, 0x98, 0x8E, 0x29,
+ 0x85, 0xAF, 0x0A, 0xFF, 0xAC, 0x6A, 0x00, 0x19, 0xC1, 0x51,
+ 0x53, 0xDE, 0x78, 0x07, 0x6D, 0x10, 0xE6, 0x25, 0xE6, 0x7A},
+
+ /************************* 18-bit u-plane with int ************/
+ /* User Plane w/NULL enc. + NULL int. UL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/NULL enc. + NULL int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35,
+ 0xF3, 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91,
+ 0xA3, 0x9C, 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36,
+ 0x47, 0x0E, 0x8F, 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B,
+ 0x01, 0x7F, 0x96, 0x46, 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC,
+ 0x69, 0x00, 0x00, 0x00, 0x00},
+ /* User Plane w/NULL enc. + SNOW f9 int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9,
+ 0x68, 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13,
+ 0x52, 0x08, 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62,
+ 0x31, 0xA2, 0x76, 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A,
+ 0xD2, 0xEE, 0xD6, 0x93, 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA,
+ 0x91, 0x7F, 0x71, 0x17, 0x69},
+ /* User Plane w/NULL enc. + SNOW f9 int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35, 0xF3,
+ 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C,
+ 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F,
+ 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC, 0x69, 0x84, 0x45, 0xA8, 0x88},
+ /* User Plane w/NULL enc. + AES CMAC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9, 0x68,
+ 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13, 0x52, 0x08,
+ 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62, 0x31, 0xA2, 0x76,
+ 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A, 0xD2, 0xEE, 0xD6, 0x93,
+ 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA, 0x91, 0x33, 0x9B, 0x38, 0xF7},
+ /* User Plane w/NULL enc. + AES CMAC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35, 0xF3,
+ 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C,
+ 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F,
+ 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC, 0x69, 0xD9, 0x0B, 0x89, 0x7F},
+ /* User Plane w/NULL enc. + ZUC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xB8, 0x33, 0x4F, 0x85, 0x8C, 0x2C, 0x65, 0x7D,
+ 0x8F, 0x5D, 0x40, 0x57, 0x60, 0x52, 0x4F, 0xB9, 0xF1, 0x69, 0xE9, 0x68,
+ 0x04, 0xFC, 0x7A, 0xBE, 0xD2, 0x5B, 0x4A, 0x21, 0x7F, 0x13, 0x52, 0x08,
+ 0xBA, 0xBD, 0x69, 0x51, 0xC9, 0x63, 0xCF, 0x06, 0x62, 0x31, 0xA2, 0x76,
+ 0xBA, 0xFC, 0x5A, 0xDB, 0xAA, 0xA3, 0x0B, 0x6A, 0xD2, 0xEE, 0xD6, 0x93,
+ 0xE4, 0x1B, 0x11, 0x4F, 0xC4, 0xD7, 0xDA, 0x91, 0xB5, 0xD9, 0x5D, 0xE0},
+ /* User Plane w/NULL enc. + ZUC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0xF8, 0xDB, 0x2D, 0x3F, 0x23, 0x82, 0x53, 0xFD,
+ 0x37, 0xDE, 0x88, 0x63, 0x08, 0x4F, 0xD3, 0x71, 0xFB, 0xEB, 0x35, 0xF3,
+ 0x64, 0xD3, 0x5E, 0xAF, 0x3F, 0x57, 0xC2, 0xE2, 0x91, 0x91, 0xA3, 0x9C,
+ 0xE6, 0x30, 0x69, 0x70, 0x33, 0x8A, 0x15, 0xD0, 0x36, 0x47, 0x0E, 0x8F,
+ 0xEE, 0x2C, 0x96, 0x0C, 0xD7, 0x7D, 0x70, 0x1B, 0x01, 0x7F, 0x96, 0x46,
+ 0x53, 0xB0, 0xA4, 0x7A, 0xF9, 0xDD, 0xCC, 0x69, 0xDA, 0xE9, 0x17, 0x96},
+ /* User Plane w/SNOW f8 enc. + NULL int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x9A, 0xAF, 0x1D, 0x21, 0x2F, 0x48, 0xB2, 0x30,
+ 0xCF, 0xBB, 0x8A, 0x2C, 0xB7, 0x57, 0xB6, 0x27, 0x89, 0x0D, 0x91,
+ 0x03, 0x2C, 0x2B, 0x8D, 0x29, 0x4A, 0xBD, 0x8D, 0x48, 0xD2, 0x69,
+ 0x37, 0xB1, 0xA1, 0x97, 0x12, 0xBD, 0x0A, 0x91, 0x4D, 0xEB, 0x76,
+ 0xC8, 0x96, 0x7A, 0x0A, 0x25, 0x08, 0xEB, 0x41, 0x30, 0x00, 0x33,
+ 0xC7, 0xFF, 0x33, 0x4E, 0xC1, 0xFE, 0x5C, 0x0F, 0x15, 0xE7, 0x9F,
+ 0x31, 0x55, 0xDA, 0x18, 0x4D},
+ /* User Plane w/SNOW f8 enc. + NULL int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x22, 0x2D, 0x15, 0xBA, 0x95, 0xAC, 0x47, 0x5A,
+ 0xE3, 0x90, 0x82, 0xEA, 0xC2, 0x93, 0x80, 0x23, 0xE9, 0xAC, 0xEA, 0x5D,
+ 0xAA, 0x70, 0x42, 0x04, 0x7C, 0xE6, 0xA6, 0x1D, 0x91, 0xAE, 0x2E, 0x43,
+ 0x60, 0x39, 0x23, 0x06, 0xD2, 0x31, 0x73, 0x98, 0xF0, 0x61, 0x47, 0xB5,
+ 0xC4, 0xB0, 0xB8, 0x31, 0x50, 0x9E, 0x37, 0x15, 0x0E, 0x0D, 0x29, 0x9D,
+ 0xB3, 0x78, 0xFB, 0x9D, 0x5C, 0x90, 0xF8, 0x80, 0x53, 0x93, 0xEF, 0x7C},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x9A, 0xAF, 0x1D, 0x21, 0x2F, 0x48, 0xB2, 0x30,
+ 0xCF, 0xBB, 0x8A, 0x2C, 0xB7, 0x57, 0xB6, 0x27, 0x89, 0x0D, 0x91, 0x03,
+ 0x2C, 0x2B, 0x8D, 0x29, 0x4A, 0xBD, 0x8D, 0x48, 0xD2, 0x69, 0x37, 0xB1,
+ 0xA1, 0x97, 0x12, 0xBD, 0x0A, 0x91, 0x4D, 0xEB, 0x76, 0xC8, 0x96, 0x7A,
+ 0x0A, 0x25, 0x08, 0xEB, 0x41, 0x30, 0x00, 0x33, 0xC7, 0xFF, 0x33, 0x4E,
+ 0xC1, 0xFE, 0x5C, 0x0F, 0x15, 0xE7, 0x9F, 0x31, 0x2A, 0xAB, 0x0F, 0x24},
+ /* User Plane w/SNOW f8 enc. + SNOW f9 int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x22, 0x2D, 0x15, 0xBA, 0x95, 0xAC, 0x47, 0x5A,
+ 0xE3, 0x90, 0x82, 0xEA, 0xC2, 0x93, 0x80, 0x23, 0xE9, 0xAC, 0xEA, 0x5D,
+ 0xAA, 0x70, 0x42, 0x04, 0x7C, 0xE6, 0xA6, 0x1D, 0x91, 0xAE, 0x2E, 0x43,
+ 0x60, 0x39, 0x23, 0x06, 0xD2, 0x31, 0x73, 0x98, 0xF0, 0x61, 0x47, 0xB5,
+ 0xC4, 0xB0, 0xB8, 0x31, 0x50, 0x9E, 0x37, 0x15, 0x0E, 0x0D, 0x29, 0x9D,
+ 0xB3, 0x78, 0xFB, 0x9D, 0x5C, 0x90, 0xF8, 0x80, 0xD7, 0xD6, 0x47, 0xF4},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x9A, 0xAF, 0x1D, 0x21, 0x2F, 0x48, 0xB2, 0x30,
+ 0xCF, 0xBB, 0x8A, 0x2C, 0xB7, 0x57, 0xB6, 0x27, 0x89, 0x0D, 0x91, 0x03,
+ 0x2C, 0x2B, 0x8D, 0x29, 0x4A, 0xBD, 0x8D, 0x48, 0xD2, 0x69, 0x37, 0xB1,
+ 0xA1, 0x97, 0x12, 0xBD, 0x0A, 0x91, 0x4D, 0xEB, 0x76, 0xC8, 0x96, 0x7A,
+ 0x0A, 0x25, 0x08, 0xEB, 0x41, 0x30, 0x00, 0x33, 0xC7, 0xFF, 0x33, 0x4E,
+ 0xC1, 0xFE, 0x5C, 0x0F, 0x15, 0xE7, 0x9F, 0x31, 0x66, 0x41, 0x20, 0xBA},
+ /* User Plane w/SNOW f8 enc. + AES CMAC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x22, 0x2D, 0x15, 0xBA, 0x95, 0xAC, 0x47, 0x5A,
+ 0xE3, 0x90, 0x82, 0xEA, 0xC2, 0x93, 0x80, 0x23, 0xE9, 0xAC, 0xEA, 0x5D,
+ 0xAA, 0x70, 0x42, 0x04, 0x7C, 0xE6, 0xA6, 0x1D, 0x91, 0xAE, 0x2E, 0x43,
+ 0x60, 0x39, 0x23, 0x06, 0xD2, 0x31, 0x73, 0x98, 0xF0, 0x61, 0x47, 0xB5,
+ 0xC4, 0xB0, 0xB8, 0x31, 0x50, 0x9E, 0x37, 0x15, 0x0E, 0x0D, 0x29, 0x9D,
+ 0xB3, 0x78, 0xFB, 0x9D, 0x5C, 0x90, 0xF8, 0x80, 0x8A, 0x98, 0x66, 0x03},
+ /* User Plane w/SNOW f8 enc. + ZUC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x9A, 0xAF, 0x1D, 0x21, 0x2F, 0x48, 0xB2, 0x30,
+ 0xCF, 0xBB, 0x8A, 0x2C, 0xB7, 0x57, 0xB6, 0x27, 0x89, 0x0D, 0x91, 0x03,
+ 0x2C, 0x2B, 0x8D, 0x29, 0x4A, 0xBD, 0x8D, 0x48, 0xD2, 0x69, 0x37, 0xB1,
+ 0xA1, 0x97, 0x12, 0xBD, 0x0A, 0x91, 0x4D, 0xEB, 0x76, 0xC8, 0x96, 0x7A,
+ 0x0A, 0x25, 0x08, 0xEB, 0x41, 0x30, 0x00, 0x33, 0xC7, 0xFF, 0x33, 0x4E,
+ 0xC1, 0xFE, 0x5C, 0x0F, 0x15, 0xE7, 0x9F, 0x31, 0xE0, 0x03, 0x45, 0xAD},
+ /* User Plane w/SNOW f8 enc. + ZUC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x22, 0x2D, 0x15, 0xBA, 0x95, 0xAC, 0x47, 0x5A,
+ 0xE3, 0x90, 0x82, 0xEA, 0xC2, 0x93, 0x80, 0x23, 0xE9, 0xAC, 0xEA, 0x5D,
+ 0xAA, 0x70, 0x42, 0x04, 0x7C, 0xE6, 0xA6, 0x1D, 0x91, 0xAE, 0x2E, 0x43,
+ 0x60, 0x39, 0x23, 0x06, 0xD2, 0x31, 0x73, 0x98, 0xF0, 0x61, 0x47, 0xB5,
+ 0xC4, 0xB0, 0xB8, 0x31, 0x50, 0x9E, 0x37, 0x15, 0x0E, 0x0D, 0x29, 0x9D,
+ 0xB3, 0x78, 0xFB, 0x9D, 0x5C, 0x90, 0xF8, 0x80, 0x89, 0x7A, 0xF8, 0xEA},
+ /* User Plane w/AES CTR enc. + NULL int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xBF, 0x31, 0x94, 0xCF, 0x6E, 0x99, 0x84, 0x08,
+ 0xF1, 0x90, 0xC2, 0x22, 0xD0, 0xD2, 0x3D, 0x44, 0x75, 0x7F, 0xC5, 0x0F,
+ 0xAC, 0x7C, 0x18, 0x46, 0xA5, 0x3E, 0x2F, 0x0F, 0x26, 0x9E, 0x5A, 0x49,
+ 0xF7, 0xCB, 0x70, 0x17, 0xBC, 0x01, 0x1D, 0xA3, 0x65, 0x0E, 0x4B, 0x53,
+ 0x14, 0x73, 0x76, 0xDE, 0x54, 0xA0, 0xF9, 0x4C, 0xC2, 0x8F, 0x02, 0x88,
+ 0x36, 0xC7, 0xC4, 0x5A, 0x57, 0x7D, 0xA1, 0x0D, 0xC1, 0x66, 0x96, 0xC8},
+ /* User Plane w/AES CTR enc. + NULL int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x01, 0x0D, 0x4B, 0x5E, 0xD3, 0xCE, 0x96, 0xE1,
+ 0x9A, 0x9D, 0xB3, 0x01, 0xD6, 0x40, 0x50, 0x00, 0x6C, 0x63, 0xFD, 0x37,
+ 0xD9, 0xBB, 0x3B, 0x76, 0xE5, 0x7D, 0x3C, 0xFC, 0xE3, 0x9D, 0x45, 0x4A,
+ 0x07, 0x14, 0xD3, 0x14, 0xBC, 0x7E, 0x57, 0xAB, 0xB0, 0x8D, 0x8F, 0x42,
+ 0x39, 0x22, 0xB2, 0xF6, 0x5F, 0xBD, 0x58, 0xE3, 0xE0, 0xDB, 0xD5, 0x7F,
+ 0xFB, 0x78, 0x95, 0xE1, 0x5E, 0x36, 0xF8, 0x52, 0x98, 0x15, 0x68, 0x35},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xBF, 0x31, 0x94, 0xCF, 0x6E, 0x99, 0x84, 0x08,
+ 0xF1, 0x90, 0xC2, 0x22, 0xD0, 0xD2, 0x3D, 0x44, 0x75, 0x7F, 0xC5, 0x0F,
+ 0xAC, 0x7C, 0x18, 0x46, 0xA5, 0x3E, 0x2F, 0x0F, 0x26, 0x9E, 0x5A, 0x49,
+ 0xF7, 0xCB, 0x70, 0x17, 0xBC, 0x01, 0x1D, 0xA3, 0x65, 0x0E, 0x4B, 0x53,
+ 0x14, 0x73, 0x76, 0xDE, 0x54, 0xA0, 0xF9, 0x4C, 0xC2, 0x8F, 0x02, 0x88,
+ 0x36, 0xC7, 0xC4, 0x5A, 0x57, 0x7D, 0xA1, 0x0D, 0xBE, 0x17, 0x81, 0xA1},
+ /* User Plane w/AES CTR enc. + SNOW f9 int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x01, 0x0D, 0x4B, 0x5E, 0xD3, 0xCE, 0x96, 0xE1,
+ 0x9A, 0x9D, 0xB3, 0x01, 0xD6, 0x40, 0x50, 0x00, 0x6C, 0x63, 0xFD, 0x37,
+ 0xD9, 0xBB, 0x3B, 0x76, 0xE5, 0x7D, 0x3C, 0xFC, 0xE3, 0x9D, 0x45, 0x4A,
+ 0x07, 0x14, 0xD3, 0x14, 0xBC, 0x7E, 0x57, 0xAB, 0xB0, 0x8D, 0x8F, 0x42,
+ 0x39, 0x22, 0xB2, 0xF6, 0x5F, 0xBD, 0x58, 0xE3, 0xE0, 0xDB, 0xD5, 0x7F,
+ 0xFB, 0x78, 0x95, 0xE1, 0x5E, 0x36, 0xF8, 0x52, 0x1C, 0x50, 0xC0, 0xBD},
+ /* User Plane w/AES CTR enc. + AES CMAC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xBF, 0x31, 0x94, 0xCF, 0x6E, 0x99, 0x84, 0x08,
+ 0xF1, 0x90, 0xC2, 0x22, 0xD0, 0xD2, 0x3D, 0x44, 0x75, 0x7F, 0xC5, 0x0F,
+ 0xAC, 0x7C, 0x18, 0x46, 0xA5, 0x3E, 0x2F, 0x0F, 0x26, 0x9E, 0x5A, 0x49,
+ 0xF7, 0xCB, 0x70, 0x17, 0xBC, 0x01, 0x1D, 0xA3, 0x65, 0x0E, 0x4B, 0x53,
+ 0x14, 0x73, 0x76, 0xDE, 0x54, 0xA0, 0xF9, 0x4C, 0xC2, 0x8F, 0x02, 0x88,
+ 0x36, 0xC7, 0xC4, 0x5A, 0x57, 0x7D, 0xA1, 0x0D, 0xF2, 0xFD, 0xAE, 0x3F},
+ /* User Plane w/AES CTR enc. + AES CMAC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x01, 0x0D, 0x4B, 0x5E, 0xD3, 0xCE, 0x96, 0xE1,
+ 0x9A, 0x9D, 0xB3, 0x01, 0xD6, 0x40, 0x50, 0x00, 0x6C, 0x63, 0xFD, 0x37,
+ 0xD9, 0xBB, 0x3B, 0x76, 0xE5, 0x7D, 0x3C, 0xFC, 0xE3, 0x9D, 0x45, 0x4A,
+ 0x07, 0x14, 0xD3, 0x14, 0xBC, 0x7E, 0x57, 0xAB, 0xB0, 0x8D, 0x8F, 0x42,
+ 0x39, 0x22, 0xB2, 0xF6, 0x5F, 0xBD, 0x58, 0xE3, 0xE0, 0xDB, 0xD5, 0x7F,
+ 0xFB, 0x78, 0x95, 0xE1, 0x5E, 0x36, 0xF8, 0x52, 0x41, 0x1E, 0xE1, 0x4A},
+ /* User Plane w/AES CTR enc. + ZUC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0xBF, 0x31, 0x94, 0xCF, 0x6E, 0x99, 0x84, 0x08,
+ 0xF1, 0x90, 0xC2, 0x22, 0xD0, 0xD2, 0x3D, 0x44, 0x75, 0x7F, 0xC5, 0x0F,
+ 0xAC, 0x7C, 0x18, 0x46, 0xA5, 0x3E, 0x2F, 0x0F, 0x26, 0x9E, 0x5A, 0x49,
+ 0xF7, 0xCB, 0x70, 0x17, 0xBC, 0x01, 0x1D, 0xA3, 0x65, 0x0E, 0x4B, 0x53,
+ 0x14, 0x73, 0x76, 0xDE, 0x54, 0xA0, 0xF9, 0x4C, 0xC2, 0x8F, 0x02, 0x88,
+ 0x36, 0xC7, 0xC4, 0x5A, 0x57, 0x7D, 0xA1, 0x0D, 0x74, 0xBF, 0xCB, 0x28},
+ /* User Plane w/AES CTR enc. + ZUC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x01, 0x0D, 0x4B, 0x5E, 0xD3, 0xCE, 0x96, 0xE1,
+ 0x9A, 0x9D, 0xB3, 0x01, 0xD6, 0x40, 0x50, 0x00, 0x6C, 0x63, 0xFD, 0x37,
+ 0xD9, 0xBB, 0x3B, 0x76, 0xE5, 0x7D, 0x3C, 0xFC, 0xE3, 0x9D, 0x45, 0x4A,
+ 0x07, 0x14, 0xD3, 0x14, 0xBC, 0x7E, 0x57, 0xAB, 0xB0, 0x8D, 0x8F, 0x42,
+ 0x39, 0x22, 0xB2, 0xF6, 0x5F, 0xBD, 0x58, 0xE3, 0xE0, 0xDB, 0xD5, 0x7F,
+ 0xFB, 0x78, 0x95, 0xE1, 0x5E, 0x36, 0xF8, 0x52, 0x42, 0xFC, 0x7F, 0xA3},
+ /* User Plane w/ZUC enc. + NULL int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x32, 0xF9, 0x21, 0x1D, 0xBB, 0xF8, 0xE5, 0x7C,
+ 0x74, 0xC2, 0xD7, 0xFF, 0x74, 0x59, 0x3A, 0x69, 0xD1, 0x8B, 0x65, 0x98,
+ 0xB9, 0x3C, 0xFB, 0x63, 0xB1, 0x9E, 0xB7, 0xCA, 0x04, 0x68, 0xB9, 0xAB,
+ 0xA2, 0x5A, 0xAF, 0x15, 0x8E, 0x71, 0xED, 0xE4, 0xFA, 0x99, 0x79, 0xF9,
+ 0x51, 0x54, 0x82, 0x69, 0x4C, 0x45, 0x0B, 0xFA, 0x87, 0x4D, 0x97, 0x6E,
+ 0xB0, 0xC9, 0x06, 0x08, 0x6B, 0xFC, 0x4A, 0x85, 0x43, 0x62, 0x73, 0xD8},
+ /* User Plane w/ZUC enc. + NULL int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x30, 0x62, 0x48, 0xC0, 0xB1, 0xED, 0x1F, 0x13,
+ 0x8A, 0x7A, 0x62, 0x40, 0x12, 0x35, 0x54, 0x03, 0x93, 0xBD, 0xE5, 0x88,
+ 0x51, 0x38, 0xB5, 0x89, 0xC6, 0xD3, 0xB5, 0x44, 0xC2, 0xB9, 0xB9, 0x59,
+ 0x7C, 0xEC, 0x71, 0xD8, 0x42, 0x01, 0x03, 0x3C, 0x0E, 0xBB, 0x7B, 0xDD,
+ 0x7D, 0x2D, 0xE0, 0x3C, 0xE3, 0x81, 0xAA, 0xEA, 0xCC, 0xD7, 0xFC, 0x46,
+ 0x07, 0x7C, 0x8E, 0x8E, 0x0E, 0x99, 0xB8, 0x31, 0x65, 0x17, 0xF6, 0xE3},
+ /* User Plane w/ZUC enc. + SNOW f9 int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x32, 0xF9, 0x21, 0x1D, 0xBB, 0xF8, 0xE5, 0x7C,
+ 0x74, 0xC2, 0xD7, 0xFF, 0x74, 0x59, 0x3A, 0x69, 0xD1, 0x8B, 0x65, 0x98,
+ 0xB9, 0x3C, 0xFB, 0x63, 0xB1, 0x9E, 0xB7, 0xCA, 0x04, 0x68, 0xB9, 0xAB,
+ 0xA2, 0x5A, 0xAF, 0x15, 0x8E, 0x71, 0xED, 0xE4, 0xFA, 0x99, 0x79, 0xF9,
+ 0x51, 0x54, 0x82, 0x69, 0x4C, 0x45, 0x0B, 0xFA, 0x87, 0x4D, 0x97, 0x6E,
+ 0xB0, 0xC9, 0x06, 0x08, 0x6B, 0xFC, 0x4A, 0x85, 0x3C, 0x13, 0x64, 0xB1},
+ /* User Plane w/ZUC enc. + SNOW f9 int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x30, 0x62, 0x48, 0xC0, 0xB1, 0xED, 0x1F, 0x13,
+ 0x8A, 0x7A, 0x62, 0x40, 0x12, 0x35, 0x54, 0x03, 0x93, 0xBD, 0xE5, 0x88,
+ 0x51, 0x38, 0xB5, 0x89, 0xC6, 0xD3, 0xB5, 0x44, 0xC2, 0xB9, 0xB9, 0x59,
+ 0x7C, 0xEC, 0x71, 0xD8, 0x42, 0x01, 0x03, 0x3C, 0x0E, 0xBB, 0x7B, 0xDD,
+ 0x7D, 0x2D, 0xE0, 0x3C, 0xE3, 0x81, 0xAA, 0xEA, 0xCC, 0xD7, 0xFC, 0x46,
+ 0x07, 0x7C, 0x8E, 0x8E, 0x0E, 0x99, 0xB8, 0x31, 0xE1, 0x52, 0x5E, 0x6B},
+ /* User Plane w/ZUC enc. + AES CMAC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x32, 0xF9, 0x21, 0x1D, 0xBB, 0xF8, 0xE5, 0x7C,
+ 0x74, 0xC2, 0xD7, 0xFF, 0x74, 0x59, 0x3A, 0x69, 0xD1, 0x8B, 0x65, 0x98,
+ 0xB9, 0x3C, 0xFB, 0x63, 0xB1, 0x9E, 0xB7, 0xCA, 0x04, 0x68, 0xB9, 0xAB,
+ 0xA2, 0x5A, 0xAF, 0x15, 0x8E, 0x71, 0xED, 0xE4, 0xFA, 0x99, 0x79, 0xF9,
+ 0x51, 0x54, 0x82, 0x69, 0x4C, 0x45, 0x0B, 0xFA, 0x87, 0x4D, 0x97, 0x6E,
+ 0xB0, 0xC9, 0x06, 0x08, 0x6B, 0xFC, 0x4A, 0x85, 0x70, 0xF9, 0x4B, 0x2F},
+ /* User Plane w/ZUC enc. + AES CMAC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x30, 0x62, 0x48, 0xC0, 0xB1, 0xED, 0x1F, 0x13,
+ 0x8A, 0x7A, 0x62, 0x40, 0x12, 0x35, 0x54, 0x03, 0x93, 0xBD, 0xE5, 0x88,
+ 0x51, 0x38, 0xB5, 0x89, 0xC6, 0xD3, 0xB5, 0x44, 0xC2, 0xB9, 0xB9, 0x59,
+ 0x7C, 0xEC, 0x71, 0xD8, 0x42, 0x01, 0x03, 0x3C, 0x0E, 0xBB, 0x7B, 0xDD,
+ 0x7D, 0x2D, 0xE0, 0x3C, 0xE3, 0x81, 0xAA, 0xEA, 0xCC, 0xD7, 0xFC, 0x46,
+ 0x07, 0x7C, 0x8E, 0x8E, 0x0E, 0x99, 0xB8, 0x31, 0xBC, 0x1C, 0x7F, 0x9C},
+ /* User Plane w/ZUC enc. + ZUC int. UL for 18-bit SN */
+ (uint8_t[]){0x0C, 0x00, 0x01, 0x32, 0xF9, 0x21, 0x1D, 0xBB, 0xF8, 0xE5, 0x7C,
+ 0x74, 0xC2, 0xD7, 0xFF, 0x74, 0x59, 0x3A, 0x69, 0xD1, 0x8B, 0x65, 0x98,
+ 0xB9, 0x3C, 0xFB, 0x63, 0xB1, 0x9E, 0xB7, 0xCA, 0x04, 0x68, 0xB9, 0xAB,
+ 0xA2, 0x5A, 0xAF, 0x15, 0x8E, 0x71, 0xED, 0xE4, 0xFA, 0x99, 0x79, 0xF9,
+ 0x51, 0x54, 0x82, 0x69, 0x4C, 0x45, 0x0B, 0xFA, 0x87, 0x4D, 0x97, 0x6E,
+ 0xB0, 0xC9, 0x06, 0x08, 0x6B, 0xFC, 0x4A, 0x85, 0xF6, 0xBB, 0x2E, 0x38},
+ /* User Plane w/ZUC enc. + ZUC int. DL for 18-bit SN */
+ (uint8_t[]){0xF8, 0x00, 0x00, 0x30, 0x62, 0x48, 0xC0, 0xB1, 0xED, 0x1F, 0x13,
+ 0x8A, 0x7A, 0x62, 0x40, 0x12, 0x35, 0x54, 0x03, 0x93, 0xBD, 0xE5, 0x88,
+ 0x51, 0x38, 0xB5, 0x89, 0xC6, 0xD3, 0xB5, 0x44, 0xC2, 0xB9, 0xB9, 0x59,
+ 0x7C, 0xEC, 0x71, 0xD8, 0x42, 0x01, 0x03, 0x3C, 0x0E, 0xBB, 0x7B, 0xDD,
+ 0x7D, 0x2D, 0xE0, 0x3C, 0xE3, 0x81, 0xAA, 0xEA, 0xCC, 0xD7, 0xFC, 0x46,
+ 0x07, 0x7C, 0x8E, 0x8E, 0x0E, 0x99, 0xB8, 0x31, 0xBF, 0xFE, 0xE1, 0x75},
+};
+
+#endif /* SECURITY_PDCP_TEST_VECTOR_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_snow3g_hash_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_snow3g_hash_test_vectors.h
new file mode 100644
index 000000000..e9fb2147b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_snow3g_hash_test_vectors.h
@@ -0,0 +1,498 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_SNOW3G_HASH_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SNOW3G_HASH_TEST_VECTORS_H_
+
+struct snow3g_hash_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } auth_iv;
+
+ struct {
+ uint8_t data[2056];
+ unsigned len; /* length must be in Bits */
+ } plaintext;
+
+ struct {
+ unsigned len;
+ } validAuthLenInBits;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } digest;
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_1 = {
+ .key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len = 384
+ },
+ .validAuthLenInBits = {
+ .len = 384
+ },
+ .digest = {
+ .data = {0x38, 0xB5, 0x54, 0xC0 },
+ .len = 4
+ }
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_2 = {
+ .key = {
+ .data = {
+ 0xF4, 0xEB, 0xEC, 0x69, 0xE7, 0x3E, 0xAF, 0x2E,
+ 0xB2, 0xCF, 0x6A, 0xF4, 0xB3, 0x12, 0x0F, 0xFD
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x29, 0x6F, 0x39, 0x3C, 0x6B, 0x22, 0x77, 0x37,
+ 0xA9, 0x6F, 0x39, 0x3C, 0x6B, 0x22, 0xF7, 0x37
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x10, 0xBF, 0xFF, 0x83, 0x9E, 0x0C, 0x71, 0x65,
+ 0x8D, 0xBB, 0x2D, 0x17, 0x07, 0xE1, 0x45, 0x72,
+ 0x4F, 0x41, 0xC1, 0x6F, 0x48, 0xBF, 0x40, 0x3C,
+ 0x3B, 0x18, 0xE3, 0x8F, 0xD5, 0xD1, 0x66, 0x3B,
+ 0x6F, 0x6D, 0x90, 0x01, 0x93, 0xE3, 0xCE, 0xA8,
+ 0xBB, 0x4F, 0x1B, 0x4F, 0x5B, 0xE8, 0x22, 0x03,
+ 0x22, 0x32, 0xA7, 0x8D, 0x7D, 0x75, 0x23, 0x8D,
+ 0x5E, 0x6D, 0xAE, 0xCD, 0x3B, 0x43, 0x22, 0xCF,
+ 0x59, 0xBC, 0x7E, 0xA8, 0x4A, 0xB1, 0x88, 0x11,
+ 0xB5, 0xBF, 0xB7, 0xBC, 0x55, 0x3F, 0x4F, 0xE4,
+ 0x44, 0x78, 0xCE, 0x28, 0x7A, 0x14, 0x87, 0x99,
+ 0x90, 0xD1, 0x8D, 0x12, 0xCA, 0x79, 0xD2, 0xC8,
+ 0x55, 0x14, 0x90, 0x21, 0xCD, 0x5C, 0xE8, 0xCA,
+ 0x03, 0x71, 0xCA, 0x04, 0xFC, 0xCE, 0x14, 0x3E,
+ 0x3D, 0x7C, 0xFE, 0xE9, 0x45, 0x85, 0xB5, 0x88,
+ 0x5C, 0xAC, 0x46, 0x06, 0x8B
+ },
+ .len = 1000
+ },
+ .validAuthLenInBits = {
+ .len = 1000
+ },
+ .digest = {
+ .data = {0x06, 0x17, 0x45, 0xAE},
+ .len = 4
+ }
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_3 = {
+ .key = {
+ .data = {
+ 0xB3, 0x12, 0x0F, 0xFD, 0xB2, 0xCF, 0x6A, 0xF4,
+ 0xE7, 0x3E, 0xAF, 0x2E, 0xF4, 0xEB, 0xEC, 0x69
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x29, 0x6F, 0x39, 0x3C, 0x6B, 0x22, 0x77, 0x37,
+ 0xA9, 0x6F, 0x39, 0x3C, 0x6B, 0x22, 0xF7, 0x37
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0xE0, 0x95, 0x80, 0x45, 0xF3, 0xA0, 0xBB, 0xA4,
+ 0xE3, 0x96, 0x83, 0x46, 0xF0, 0xA3, 0xB8, 0xA7,
+ 0xC0, 0x2A, 0x01, 0x8A, 0xE6, 0x40, 0x76, 0x52,
+ 0x26, 0xB9, 0x87, 0xC9, 0x13, 0xE6, 0xCB, 0xF0,
+ 0x83, 0x57, 0x00, 0x16, 0xCF, 0x83, 0xEF, 0xBC,
+ 0x61, 0xC0, 0x82, 0x51, 0x3E, 0x21, 0x56, 0x1A,
+ 0x42, 0x7C, 0x00, 0x9D, 0x28, 0xC2, 0x98, 0xEF,
+ 0xAC, 0xE7, 0x8E, 0xD6, 0xD5, 0x6C, 0x2D, 0x45,
+ 0x05, 0xAD, 0x03, 0x2E, 0x9C, 0x04, 0xDC, 0x60,
+ 0xE7, 0x3A, 0x81, 0x69, 0x6D, 0xA6, 0x65, 0xC6,
+ 0xC4, 0x86, 0x03, 0xA5, 0x7B, 0x45, 0xAB, 0x33,
+ 0x22, 0x15, 0x85, 0xE6, 0x8E, 0xE3, 0x16, 0x91,
+ 0x87, 0xFB, 0x02, 0x39, 0x52, 0x86, 0x32, 0xDD,
+ 0x65, 0x6C, 0x80, 0x7E, 0xA3, 0x24, 0x8B, 0x7B,
+ 0x46, 0xD0, 0x02, 0xB2, 0xB5, 0xC7, 0x45, 0x8E,
+ 0xB8, 0x5B, 0x9C, 0xE9, 0x58, 0x79, 0xE0, 0x34,
+ 0x08, 0x59, 0x05, 0x5E, 0x3B, 0x0A, 0xBB, 0xC3,
+ 0xEA, 0xCE, 0x87, 0x19, 0xCA, 0xA8, 0x02, 0x65,
+ 0xC9, 0x72, 0x05, 0xD5, 0xDC, 0x4B, 0xCC, 0x90,
+ 0x2F, 0xE1, 0x83, 0x96, 0x29, 0xED, 0x71, 0x32,
+ 0x8A, 0x0F, 0x04, 0x49, 0xF5, 0x88, 0x55, 0x7E,
+ 0x68, 0x98, 0x86, 0x0E, 0x04, 0x2A, 0xEC, 0xD8,
+ 0x4B, 0x24, 0x04, 0xC2, 0x12, 0xC9, 0x22, 0x2D,
+ 0xA5, 0xBF, 0x8A, 0x89, 0xEF, 0x67, 0x97, 0x87,
+ 0x0C, 0xF5, 0x07, 0x71, 0xA6, 0x0F, 0x66, 0xA2,
+ 0xEE, 0x62, 0x85, 0x36, 0x57, 0xAD, 0xDF, 0x04,
+ 0xCD, 0xDE, 0x07, 0xFA, 0x41, 0x4E, 0x11, 0xF1,
+ 0x2B, 0x4D, 0x81, 0xB9, 0xB4, 0xE8, 0xAC, 0x53,
+ 0x8E, 0xA3, 0x06, 0x66, 0x68, 0x8D, 0x88, 0x1F,
+ 0x6C, 0x34, 0x84, 0x21, 0x99, 0x2F, 0x31, 0xB9,
+ 0x4F, 0x88, 0x06, 0xED, 0x8F, 0xCC, 0xFF, 0x4C,
+ 0x91, 0x23, 0xB8, 0x96, 0x42, 0x52, 0x7A, 0xD6,
+ 0x13, 0xB1, 0x09, 0xBF, 0x75, 0x16, 0x74, 0x85,
+ 0xF1, 0x26, 0x8B, 0xF8, 0x84, 0xB4, 0xCD, 0x23,
+ 0xD2, 0x9A, 0x09, 0x34, 0x92, 0x57, 0x03, 0xD6,
+ 0x34, 0x09, 0x8F, 0x77, 0x67, 0xF1, 0xBE, 0x74,
+ 0x91, 0xE7, 0x08, 0xA8, 0xBB, 0x94, 0x9A, 0x38,
+ 0x73, 0x70, 0x8A, 0xEF, 0x4A, 0x36, 0x23, 0x9E,
+ 0x50, 0xCC, 0x08, 0x23, 0x5C, 0xD5, 0xED, 0x6B,
+ 0xBE, 0x57, 0x86, 0x68, 0xA1, 0x7B, 0x58, 0xC1,
+ 0x17, 0x1D, 0x0B, 0x90, 0xE8, 0x13, 0xA9, 0xE4,
+ 0xF5, 0x8A, 0x89, 0xD7, 0x19, 0xB1, 0x10, 0x42,
+ 0xD6, 0x36, 0x0B, 0x1B, 0x0F, 0x52, 0xDE, 0xB7,
+ 0x30, 0xA5, 0x8D, 0x58, 0xFA, 0xF4, 0x63, 0x15,
+ 0x95, 0x4B, 0x0A, 0x87, 0x26, 0x91, 0x47, 0x59,
+ 0x77, 0xDC, 0x88, 0xC0, 0xD7, 0x33, 0xFE, 0xFF,
+ 0x54, 0x60, 0x0A, 0x0C, 0xC1, 0xD0, 0x30, 0x0A,
+ 0xAA, 0xEB, 0x94, 0x57, 0x2C, 0x6E, 0x95, 0xB0,
+ 0x1A, 0xE9, 0x0D, 0xE0, 0x4F, 0x1D, 0xCE, 0x47,
+ 0xF8, 0x7E, 0x8F, 0xA7, 0xBE, 0xBF, 0x77, 0xE1,
+ 0xDB, 0xC2, 0x0D, 0x6B, 0xA8, 0x5C, 0xB9, 0x14,
+ 0x3D, 0x51, 0x8B, 0x28, 0x5D, 0xFA, 0x04, 0xB6,
+ 0x98, 0xBF, 0x0C, 0xF7, 0x81, 0x9F, 0x20, 0xFA,
+ 0x7A, 0x28, 0x8E, 0xB0, 0x70, 0x3D, 0x99, 0x5C,
+ 0x59, 0x94, 0x0C, 0x7C, 0x66, 0xDE, 0x57, 0xA9,
+ 0xB7, 0x0F, 0x82, 0x37, 0x9B, 0x70, 0xE2, 0x03,
+ 0x1E, 0x45, 0x0F, 0xCF, 0xD2, 0x18, 0x13, 0x26,
+ 0xFC, 0xD2, 0x8D, 0x88, 0x23, 0xBA, 0xAA, 0x80,
+ 0xDF, 0x6E, 0x0F, 0x44, 0x35, 0x59, 0x64, 0x75,
+ 0x39, 0xFD, 0x89, 0x07, 0xC0, 0xFF, 0xD9, 0xD7,
+ 0x9C, 0x13, 0x0E, 0xD8, 0x1C, 0x9A, 0xFD, 0x9B,
+ 0x7E, 0x84, 0x8C, 0x9F, 0xED, 0x38, 0x44, 0x3D,
+ 0x5D, 0x38, 0x0E, 0x53, 0xFB, 0xDB, 0x8A, 0xC8,
+ 0xC3, 0xD3, 0xF0, 0x68, 0x76, 0x05, 0x4F, 0x12,
+ 0x24, 0x61, 0x10, 0x7D, 0xE9, 0x2F, 0xEA, 0x09,
+ 0xC6, 0xF6, 0x92, 0x3A, 0x18, 0x8D, 0x53, 0xAF,
+ 0xE5, 0x4A, 0x10, 0xF6, 0x0E, 0x6E, 0x9D, 0x5A,
+ 0x03, 0xD9, 0x96, 0xB5, 0xFB, 0xC8, 0x20, 0xF8,
+ 0xA6, 0x37, 0x11, 0x6A, 0x27, 0xAD, 0x04, 0xB4,
+ 0x44, 0xA0, 0x93, 0x2D, 0xD6, 0x0F, 0xBD, 0x12,
+ 0x67, 0x1C, 0x11, 0xE1, 0xC0, 0xEC, 0x73, 0xE7,
+ 0x89, 0x87, 0x9F, 0xAA, 0x3D, 0x42, 0xC6, 0x4D,
+ 0x20, 0xCD, 0x12, 0x52, 0x74, 0x2A, 0x37, 0x68,
+ 0xC2, 0x5A, 0x90, 0x15, 0x85, 0x88, 0x8E, 0xCE,
+ 0xE1, 0xE6, 0x12, 0xD9, 0x93, 0x6B, 0x40, 0x3B,
+ 0x07, 0x75, 0x94, 0x9A, 0x66, 0xCD, 0xFD, 0x99,
+ 0xA2, 0x9B, 0x13, 0x45, 0xBA, 0xA8, 0xD9, 0xD5,
+ 0x40, 0x0C, 0x91, 0x02, 0x4B, 0x0A, 0x60, 0x73,
+ 0x63, 0xB0, 0x13, 0xCE, 0x5D, 0xE9, 0xAE, 0x86,
+ 0x9D, 0x3B, 0x8D, 0x95, 0xB0, 0x57, 0x0B, 0x3C,
+ 0x2D, 0x39, 0x14, 0x22, 0xD3, 0x24, 0x50, 0xCB,
+ 0xCF, 0xAE, 0x96, 0x65, 0x22, 0x86, 0xE9, 0x6D,
+ 0xEC, 0x12, 0x14, 0xA9, 0x34, 0x65, 0x27, 0x98,
+ 0x0A, 0x81, 0x92, 0xEA, 0xC1, 0xC3, 0x9A, 0x3A,
+ 0xAF, 0x6F, 0x15, 0x35, 0x1D, 0xA6, 0xBE, 0x76,
+ 0x4D, 0xF8, 0x97, 0x72, 0xEC, 0x04, 0x07, 0xD0,
+ 0x6E, 0x44, 0x15, 0xBE, 0xFA, 0xE7, 0xC9, 0x25,
+ 0x80, 0xDF, 0x9B, 0xF5, 0x07, 0x49, 0x7C, 0x8F,
+ 0x29, 0x95, 0x16, 0x0D, 0x4E, 0x21, 0x8D, 0xAA,
+ 0xCB, 0x02, 0x94, 0x4A, 0xBF, 0x83, 0x34, 0x0C,
+ 0xE8, 0xBE, 0x16, 0x86, 0xA9, 0x60, 0xFA, 0xF9,
+ 0x0E, 0x2D, 0x90, 0xC5, 0x5C, 0xC6, 0x47, 0x5B,
+ 0xAB, 0xC3, 0x17, 0x1A, 0x80, 0xA3, 0x63, 0x17,
+ 0x49, 0x54, 0x95, 0x5D, 0x71, 0x01, 0xDA, 0xB1,
+ 0x6A, 0xE8, 0x17, 0x91, 0x67, 0xE2, 0x14, 0x44,
+ 0xB4, 0x43, 0xA9, 0xEA, 0xAA, 0x7C, 0x91, 0xDE,
+ 0x36, 0xD1, 0x18, 0xC3, 0x9D, 0x38, 0x9F, 0x8D,
+ 0xD4, 0x46, 0x9A, 0x84, 0x6C, 0x9A, 0x26, 0x2B,
+ 0xF7, 0xFA, 0x18, 0x48, 0x7A, 0x79, 0xE8, 0xDE,
+ 0x11, 0x69, 0x9E, 0x0B, 0x8F, 0xDF, 0x55, 0x7C,
+ 0xB4, 0x87, 0x19, 0xD4, 0x53, 0xBA, 0x71, 0x30,
+ 0x56, 0x10, 0x9B, 0x93, 0xA2, 0x18, 0xC8, 0x96,
+ 0x75, 0xAC, 0x19, 0x5F, 0xB4, 0xFB, 0x06, 0x63,
+ 0x9B, 0x37, 0x97, 0x14, 0x49, 0x55, 0xB3, 0xC9,
+ 0x32, 0x7D, 0x1A, 0xEC, 0x00, 0x3D, 0x42, 0xEC,
+ 0xD0, 0xEA, 0x98, 0xAB, 0xF1, 0x9F, 0xFB, 0x4A,
+ 0xF3, 0x56, 0x1A, 0x67, 0xE7, 0x7C, 0x35, 0xBF,
+ 0x15, 0xC5, 0x9C, 0x24, 0x12, 0xDA, 0x88, 0x1D,
+ 0xB0, 0x2B, 0x1B, 0xFB, 0xCE, 0xBF, 0xAC, 0x51,
+ 0x52, 0xBC, 0x99, 0xBC, 0x3F, 0x1D, 0x15, 0xF7,
+ 0x71, 0x00, 0x1B, 0x70, 0x29, 0xFE, 0xDB, 0x02,
+ 0x8F, 0x8B, 0x85, 0x2B, 0xC4, 0x40, 0x7E, 0xB8,
+ 0x3F, 0x89, 0x1C, 0x9C, 0xA7, 0x33, 0x25, 0x4F,
+ 0xDD, 0x1E, 0x9E, 0xDB, 0x56, 0x91, 0x9C, 0xE9,
+ 0xFE, 0xA2, 0x1C, 0x17, 0x40, 0x72, 0x52, 0x1C,
+ 0x18, 0x31, 0x9A, 0x54, 0xB5, 0xD4, 0xEF, 0xBE,
+ 0xBD, 0xDF, 0x1D, 0x8B, 0x69, 0xB1, 0xCB, 0xF2,
+ 0x5F, 0x48, 0x9F, 0xCC, 0x98, 0x13, 0x72, 0x54,
+ 0x7C, 0xF4, 0x1D, 0x00, 0x8E, 0xF0, 0xBC, 0xA1,
+ 0x92, 0x6F, 0x93, 0x4B, 0x73, 0x5E, 0x09, 0x0B,
+ 0x3B, 0x25, 0x1E, 0xB3, 0x3A, 0x36, 0xF8, 0x2E,
+ 0xD9, 0xB2, 0x9C, 0xF4, 0xCB, 0x94, 0x41, 0x88,
+ 0xFA, 0x0E, 0x1E, 0x38, 0xDD, 0x77, 0x8F, 0x7D,
+ 0x1C, 0x9D, 0x98, 0x7B, 0x28, 0xD1, 0x32, 0xDF,
+ 0xB9, 0x73, 0x1F, 0xA4, 0xF4, 0xB4, 0x16, 0x93,
+ 0x5B, 0xE4, 0x9D, 0xE3, 0x05, 0x16, 0xAF, 0x35,
+ 0x78, 0x58, 0x1F, 0x2F, 0x13, 0xF5, 0x61, 0xC0,
+ 0x66, 0x33, 0x61, 0x94, 0x1E, 0xAB, 0x24, 0x9A,
+ 0x4B, 0xC1, 0x23, 0xF8, 0xD1, 0x5C, 0xD7, 0x11,
+ 0xA9, 0x56, 0xA1, 0xBF, 0x20, 0xFE, 0x6E, 0xB7,
+ 0x8A, 0xEA, 0x23, 0x73, 0x36, 0x1D, 0xA0, 0x42,
+ 0x6C, 0x79, 0xA5, 0x30, 0xC3, 0xBB, 0x1D, 0xE0,
+ 0xC9, 0x97, 0x22, 0xEF, 0x1F, 0xDE, 0x39, 0xAC,
+ 0x2B, 0x00, 0xA0, 0xA8, 0xEE, 0x7C, 0x80, 0x0A,
+ 0x08, 0xBC, 0x22, 0x64, 0xF8, 0x9F, 0x4E, 0xFF,
+ 0xE6, 0x27, 0xAC, 0x2F, 0x05, 0x31, 0xFB, 0x55,
+ 0x4F, 0x6D, 0x21, 0xD7, 0x4C, 0x59, 0x0A, 0x70,
+ 0xAD, 0xFA, 0xA3, 0x90, 0xBD, 0xFB, 0xB3, 0xD6,
+ 0x8E, 0x46, 0x21, 0x5C, 0xAB, 0x18, 0x7D, 0x23,
+ 0x68, 0xD5, 0xA7, 0x1F, 0x5E, 0xBE, 0xC0, 0x81,
+ 0xCD, 0x3B, 0x20, 0xC0, 0x82, 0xDB, 0xE4, 0xCD,
+ 0x2F, 0xAC, 0xA2, 0x87, 0x73, 0x79, 0x5D, 0x6B,
+ 0x0C, 0x10, 0x20, 0x4B, 0x65, 0x9A, 0x93, 0x9E,
+ 0xF2, 0x9B, 0xBE, 0x10, 0x88, 0x24, 0x36, 0x24,
+ 0x42, 0x99, 0x27, 0xA7, 0xEB, 0x57, 0x6D, 0xD3,
+ 0xA0, 0x0E, 0xA5, 0xE0, 0x1A, 0xF5, 0xD4, 0x75,
+ 0x83, 0xB2, 0x27, 0x2C, 0x0C, 0x16, 0x1A, 0x80,
+ 0x65, 0x21, 0xA1, 0x6F, 0xF9, 0xB0, 0xA7, 0x22,
+ 0xC0, 0xCF, 0x26, 0xB0, 0x25, 0xD5, 0x83, 0x6E,
+ 0x22, 0x58, 0xA4, 0xF7, 0xD4, 0x77, 0x3A, 0xC8,
+ 0x01, 0xE4, 0x26, 0x3B, 0xC2, 0x94, 0xF4, 0x3D,
+ 0xEF, 0x7F, 0xA8, 0x70, 0x3F, 0x3A, 0x41, 0x97,
+ 0x46, 0x35, 0x25, 0x88, 0x76, 0x52, 0xB0, 0xB2,
+ 0xA4, 0xA2, 0xA7, 0xCF, 0x87, 0xF0, 0x09, 0x14,
+ 0x87, 0x1E, 0x25, 0x03, 0x91, 0x13, 0xC7, 0xE1,
+ 0x61, 0x8D, 0xA3, 0x40, 0x64, 0xB5, 0x7A, 0x43,
+ 0xC4, 0x63, 0x24, 0x9F, 0xB8, 0xD0, 0x5E, 0x0F,
+ 0x26, 0xF4, 0xA6, 0xD8, 0x49, 0x72, 0xE7, 0xA9,
+ 0x05, 0x48, 0x24, 0x14, 0x5F, 0x91, 0x29, 0x5C,
+ 0xDB, 0xE3, 0x9A, 0x6F, 0x92, 0x0F, 0xAC, 0xC6,
+ 0x59, 0x71, 0x2B, 0x46, 0xA5, 0x4B, 0xA2, 0x95,
+ 0xBB, 0xE6, 0xA9, 0x01, 0x54, 0xE9, 0x1B, 0x33,
+ 0x98, 0x5A, 0x2B, 0xCD, 0x42, 0x0A, 0xD5, 0xC6,
+ 0x7E, 0xC9, 0xAD, 0x8E, 0xB7, 0xAC, 0x68, 0x64,
+ 0xDB, 0x27, 0x2A, 0x51, 0x6B, 0xC9, 0x4C, 0x28,
+ 0x39, 0xB0, 0xA8, 0x16, 0x9A, 0x6B, 0xF5, 0x8E,
+ 0x1A, 0x0C, 0x2A, 0xDA, 0x8C, 0x88, 0x3B, 0x7B,
+ 0xF4, 0x97, 0xA4, 0x91, 0x71, 0x26, 0x8E, 0xD1,
+ 0x5D, 0xDD, 0x29, 0x69, 0x38, 0x4E, 0x7F, 0xF4,
+ 0xBF, 0x4A, 0xAB, 0x2E, 0xC9, 0xEC, 0xC6, 0x52,
+ 0x9C, 0xF6, 0x29, 0xE2, 0xDF, 0x0F, 0x08, 0xA7,
+ 0x7A, 0x65, 0xAF, 0xA1, 0x2A, 0xA9, 0xB5, 0x05,
+ 0xDF, 0x8B, 0x28, 0x7E, 0xF6, 0xCC, 0x91, 0x49,
+ 0x3D, 0x1C, 0xAA, 0x39, 0x07, 0x6E, 0x28, 0xEF,
+ 0x1E, 0xA0, 0x28, 0xF5, 0x11, 0x8D, 0xE6, 0x1A,
+ 0xE0, 0x2B, 0xB6, 0xAE, 0xFC, 0x33, 0x43, 0xA0,
+ 0x50, 0x29, 0x2F, 0x19, 0x9F, 0x40, 0x18, 0x57,
+ 0xB2, 0xBE, 0xAD, 0x5E, 0x6E, 0xE2, 0xA1, 0xF1,
+ 0x91, 0x02, 0x2F, 0x92, 0x78, 0x01, 0x6F, 0x04,
+ 0x77, 0x91, 0xA9, 0xD1, 0x8D, 0xA7, 0xD2, 0xA6,
+ 0xD2, 0x7F, 0x2E, 0x0E, 0x51, 0xC2, 0xF6, 0xEA,
+ 0x30, 0xE8, 0xAC, 0x49, 0xA0, 0x60, 0x4F, 0x4C,
+ 0x13, 0x54, 0x2E, 0x85, 0xB6, 0x83, 0x81, 0xB9,
+ 0xFD, 0xCF, 0xA0, 0xCE, 0x4B, 0x2D, 0x34, 0x13,
+ 0x54, 0x85, 0x2D, 0x36, 0x02, 0x45, 0xC5, 0x36,
+ 0xB6, 0x12, 0xAF, 0x71, 0xF3, 0xE7, 0x7C, 0x90,
+ 0x95, 0xAE, 0x2D, 0xBD, 0xE5, 0x04, 0xB2, 0x65,
+ 0x73, 0x3D, 0xAB, 0xFE, 0x10, 0xA2, 0x0F, 0xC7,
+ 0xD6, 0xD3, 0x2C, 0x21, 0xCC, 0xC7, 0x2B, 0x8B,
+ 0x34, 0x44, 0xAE, 0x66, 0x3D, 0x65, 0x92, 0x2D,
+ 0x17, 0xF8, 0x2C, 0xAA, 0x2B, 0x86, 0x5C, 0xD8,
+ 0x89, 0x13, 0xD2, 0x91, 0xA6, 0x58, 0x99, 0x02,
+ 0x6E, 0xA1, 0x32, 0x84, 0x39, 0x72, 0x3C, 0x19,
+ 0x8C, 0x36, 0xB0, 0xC3, 0xC8, 0xD0, 0x85, 0xBF,
+ 0xAF, 0x8A, 0x32, 0x0F, 0xDE, 0x33, 0x4B, 0x4A,
+ 0x49, 0x19, 0xB4, 0x4C, 0x2B, 0x95, 0xF6, 0xE8,
+ 0xEC, 0xF7, 0x33, 0x93, 0xF7, 0xF0, 0xD2, 0xA4,
+ 0x0E, 0x60, 0xB1, 0xD4, 0x06, 0x52, 0x6B, 0x02,
+ 0x2D, 0xDC, 0x33, 0x18, 0x10, 0xB1, 0xA5, 0xF7,
+ 0xC3, 0x47, 0xBD, 0x53, 0xED, 0x1F, 0x10, 0x5D,
+ 0x6A, 0x0D, 0x30, 0xAB, 0xA4, 0x77, 0xE1, 0x78,
+ 0x88, 0x9A, 0xB2, 0xEC, 0x55, 0xD5, 0x58, 0xDE,
+ 0xAB, 0x26, 0x30, 0x20, 0x43, 0x36, 0x96, 0x2B,
+ 0x4D, 0xB5, 0xB6, 0x63, 0xB6, 0x90, 0x2B, 0x89,
+ 0xE8, 0x5B, 0x31, 0xBC, 0x6A, 0xF5, 0x0F, 0xC5,
+ 0x0A, 0xCC, 0xB3, 0xFB, 0x9B, 0x57, 0xB6, 0x63,
+ 0x29, 0x70, 0x31, 0x37, 0x8D, 0xB4, 0x78, 0x96,
+ 0xD7, 0xFB, 0xAF, 0x6C, 0x60, 0x0A, 0xDD, 0x2C,
+ 0x67, 0xF9, 0x36, 0xDB, 0x03, 0x79, 0x86, 0xDB,
+ 0x85, 0x6E, 0xB4, 0x9C, 0xF2, 0xDB, 0x3F, 0x7D,
+ 0xA6, 0xD2, 0x36, 0x50, 0xE4, 0x38, 0xF1, 0x88,
+ 0x40, 0x41, 0xB0, 0x13, 0x11, 0x9E, 0x4C, 0x2A,
+ 0xE5, 0xAF, 0x37, 0xCC, 0xCD, 0xFB, 0x68, 0x66,
+ 0x07, 0x38, 0xB5, 0x8B, 0x3C, 0x59, 0xD1, 0xC0,
+ 0x24, 0x84, 0x37, 0x47, 0x2A, 0xBA, 0x1F, 0x35,
+ 0xCA, 0x1F, 0xB9, 0x0C, 0xD7, 0x14, 0xAA, 0x9F,
+ 0x63, 0x55, 0x34, 0xF4, 0x9E, 0x7C, 0x5B, 0xBA,
+ 0x81, 0xC2, 0xB6, 0xB3, 0x6F, 0xDE, 0xE2, 0x1C,
+ 0xA2, 0x7E, 0x34, 0x7F, 0x79, 0x3D, 0x2C, 0xE9,
+ 0x44, 0xED, 0xB2, 0x3C, 0x8C, 0x9B, 0x91, 0x4B,
+ 0xE1, 0x03, 0x35, 0xE3, 0x50, 0xFE, 0xB5, 0x07,
+ 0x03, 0x94, 0xB7, 0xA4, 0xA1, 0x5C, 0x0C, 0xA1,
+ 0x20, 0x28, 0x35, 0x68, 0xB7, 0xBF, 0xC2, 0x54,
+ 0xFE, 0x83, 0x8B, 0x13, 0x7A, 0x21, 0x47, 0xCE,
+ 0x7C, 0x11, 0x3A, 0x3A, 0x4D, 0x65, 0x49, 0x9D,
+ 0x9E, 0x86, 0xB8, 0x7D, 0xBC, 0xC7, 0xF0, 0x3B,
+ 0xBD, 0x3A, 0x3A, 0xB1, 0xAA, 0x24, 0x3E, 0xCE,
+ 0x5B, 0xA9, 0xBC, 0xF2, 0x5F, 0x82, 0x83, 0x6C,
+ 0xFE, 0x47, 0x3B, 0x2D, 0x83, 0xE7, 0xA7, 0x20,
+ 0x1C, 0xD0, 0xB9, 0x6A, 0x72, 0x45, 0x1E, 0x86,
+ 0x3F, 0x6C, 0x3B, 0xA6, 0x64, 0xA6, 0xD0, 0x73,
+ 0xD1, 0xF7, 0xB5, 0xED, 0x99, 0x08, 0x65, 0xD9,
+ 0x78, 0xBD, 0x38, 0x15, 0xD0, 0x60, 0x94, 0xFC,
+ 0x9A, 0x2A, 0xBA, 0x52, 0x21, 0xC2, 0x2D, 0x5A,
+ 0xB9, 0x96, 0x38, 0x9E, 0x37, 0x21, 0xE3, 0xAF,
+ 0x5F, 0x05, 0xBE, 0xDD, 0xC2, 0x87, 0x5E, 0x0D,
+ 0xFA, 0xEB, 0x39, 0x02, 0x1E, 0xE2, 0x7A, 0x41,
+ 0x18, 0x7C, 0xBB, 0x45, 0xEF, 0x40, 0xC3, 0xE7,
+ 0x3B, 0xC0, 0x39, 0x89, 0xF9, 0xA3, 0x0D, 0x12,
+ 0xC5, 0x4B, 0xA7, 0xD2, 0x14, 0x1D, 0xA8, 0xA8,
+ 0x75, 0x49, 0x3E, 0x65, 0x77, 0x6E, 0xF3, 0x5F,
+ 0x97, 0xDE, 0xBC, 0x22, 0x86, 0xCC, 0x4A, 0xF9,
+ 0xB4, 0x62, 0x3E, 0xEE, 0x90, 0x2F, 0x84, 0x0C,
+ 0x52, 0xF1, 0xB8, 0xAD, 0x65, 0x89, 0x39, 0xAE,
+ 0xF7, 0x1F, 0x3F, 0x72, 0xB9, 0xEC, 0x1D, 0xE2,
+ 0x15, 0x88, 0xBD, 0x35, 0x48, 0x4E, 0xA4, 0x44,
+ 0x36, 0x34, 0x3F, 0xF9, 0x5E, 0xAD, 0x6A, 0xB1,
+ 0xD8, 0xAF, 0xB1, 0xB2, 0xA3, 0x03, 0xDF, 0x1B,
+ 0x71, 0xE5, 0x3C, 0x4A, 0xEA, 0x6B, 0x2E, 0x3E,
+ 0x93, 0x72, 0xBE, 0x0D, 0x1B, 0xC9, 0x97, 0x98,
+ 0xB0, 0xCE, 0x3C, 0xC1, 0x0D, 0x2A, 0x59, 0x6D,
+ 0x56, 0x5D, 0xBA, 0x82, 0xF8, 0x8C, 0xE4, 0xCF,
+ 0xF3, 0xB3, 0x3D, 0x5D, 0x24, 0xE9, 0xC0, 0x83,
+ 0x11, 0x24, 0xBF, 0x1A, 0xD5, 0x4B, 0x79, 0x25,
+ 0x32, 0x98, 0x3D, 0xD6, 0xC3, 0xA8, 0xB7, 0xD0
+ },
+ .len = 16448
+ },
+ .validAuthLenInBits = {
+ .len = 16448
+ },
+ .digest = {
+ .data = {0x17, 0x9F, 0x2F, 0xA6},
+ .len = 4
+ }
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_4 = {
+ .key = {
+ .data = {
+ 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00,
+ 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ 0x38, 0xA6, 0xF0, 0x56, 0x05, 0xD2, 0xEC, 0x49,
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x6B, 0x22, 0x77, 0x37, 0x29, 0x6F, 0x39, 0x3C,
+ 0x80, 0x79, 0x35, 0x3E, 0xDC, 0x87, 0xE2, 0xE8,
+ 0x05, 0xD2, 0xEC, 0x49, 0xA4, 0xF2, 0xD8, 0xE0
+ },
+ .len = 189
+ },
+ .validAuthLenInBits = {
+ .len = 189
+ },
+ .digest = {
+ .data = {0x2B, 0xCE, 0x18, 0x20},
+ .len = 4
+ }
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_5 = {
+ .key = {
+ .data = {
+ 0xD4, 0x2F, 0x68, 0x24, 0x28, 0x20, 0x1C, 0xAF,
+ 0xCD, 0x9F, 0x97, 0x94, 0x5E, 0x6D, 0xE7, 0xB7
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x3E, 0xDC, 0x87, 0xE2, 0xA4, 0xF2, 0xD8, 0xE2,
+ 0xBE, 0xDC, 0x87, 0xE2, 0xA4, 0xF2, 0x58, 0xE2
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xB5, 0x92, 0x43, 0x84, 0x32, 0x8A, 0x4A, 0xE0,
+ 0x0B, 0x73, 0x71, 0x09, 0xF8, 0xB6, 0xC8, 0xDD,
+ 0x2B, 0x4D, 0xB6, 0x3D, 0xD5, 0x33, 0x98, 0x1C,
+ 0xEB, 0x19, 0xAA, 0xD5, 0x2A, 0x5B, 0x2B, 0xC0
+ },
+ .len = 254
+ },
+ .validAuthLenInBits = {
+ .len = 254
+ },
+ .digest = {
+ .data = {0xFC, 0x7B, 0x18, 0xBD},
+ .len = 4
+ }
+};
+
+struct snow3g_hash_test_data snow3g_hash_test_case_6 = {
+ .key = {
+ .data = {
+ 0xFD, 0xB9, 0xCF, 0xDF, 0x28, 0x93, 0x6C, 0xC4,
+ 0x83, 0xA3, 0x18, 0x69, 0xD8, 0x1B, 0x8F, 0xAB
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x36, 0xAF, 0x61, 0x44, 0x98, 0x38, 0xF0, 0x3A,
+ 0xB6, 0xAF, 0x61, 0x44, 0x98, 0x38, 0x70, 0x3A
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x59, 0x32, 0xBC, 0x0A, 0xCE, 0x2B, 0x0A, 0xBA,
+ 0x33, 0xD8, 0xAC, 0x18, 0x8A, 0xC5, 0x4F, 0x34,
+ 0x6F, 0xAD, 0x10, 0xBF, 0x9D, 0xEE, 0x29, 0x20,
+ 0xB4, 0x3B, 0xD0, 0xC5, 0x3A, 0x91, 0x5C, 0xB7,
+ 0xDF, 0x6C, 0xAA, 0x72, 0x05, 0x3A, 0xBF, 0xF2
+ },
+ .len = 319
+ },
+ .validAuthLenInBits = {
+ .len = 319
+ },
+ .digest = {
+ .data = {0x02, 0xF1, 0xFA, 0xAF},
+ .len = 4
+ }
+};
+#endif /* TEST_CRYPTODEV_SNOW3G_HASH_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_snow3g_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_snow3g_test_vectors.h
new file mode 100644
index 000000000..bbe05662b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_snow3g_test_vectors.h
@@ -0,0 +1,739 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2019 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_SNOW3G_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SNOW3G_TEST_VECTORS_H_
+
+struct snow3g_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned len;
+ } cipher_iv;
+
+ struct {
+ uint8_t data[1024];
+ unsigned len; /* length must be in Bits */
+ } plaintext;
+
+ struct {
+ uint8_t data[1024];
+ unsigned len; /* length must be in Bits */
+ } ciphertext;
+
+ struct {
+ unsigned len;
+ } validDataLenInBits;
+
+ struct {
+ unsigned len;
+ } validCipherLenInBits;
+
+ struct {
+ unsigned len;
+ } validAuthLenInBits;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } auth_iv;
+
+ struct {
+ uint8_t data[64];
+ unsigned int len; /* length must be in Bytes */
+ unsigned int offset_bytes; /* offset must be in Bytes */
+ } digest;
+
+ struct {
+ unsigned int len_bits; /* length must be in Bits */
+ unsigned int offset_bits;
+ } cipher;
+
+ struct {
+ unsigned int len_bits; /* length must be in Bits */
+ unsigned int offset_bits;
+ } auth;
+};
+
+struct snow3g_test_data snow3g_test_case_1 = {
+ .key = {
+ .data = {
+ 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00,
+ 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x72, 0xA4, 0xF2, 0x0F, 0x64, 0x00, 0x00, 0x00,
+ 0x72, 0xA4, 0xF2, 0x0F, 0x64, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x7E, 0xC6, 0x12, 0x72, 0x74, 0x3B, 0xF1, 0x61,
+ 0x47, 0x26, 0x44, 0x6A, 0x6C, 0x38, 0xCE, 0xD1,
+ 0x66, 0xF6, 0xCA, 0x76, 0xEB, 0x54, 0x30, 0x04,
+ 0x42, 0x86, 0x34, 0x6C, 0xEF, 0x13, 0x0F, 0x92,
+ 0x92, 0x2B, 0x03, 0x45, 0x0D, 0x3A, 0x99, 0x75,
+ 0xE5, 0xBD, 0x2E, 0xA0, 0xEB, 0x55, 0xAD, 0x8E,
+ 0x1B, 0x19, 0x9E, 0x3E, 0xC4, 0x31, 0x60, 0x20,
+ 0xE9, 0xA1, 0xB2, 0x85, 0xE7, 0x62, 0x79, 0x53,
+ 0x59, 0xB7, 0xBD, 0xFD, 0x39, 0xBE, 0xF4, 0xB2,
+ 0x48, 0x45, 0x83, 0xD5, 0xAF, 0xE0, 0x82, 0xAE,
+ 0xE6, 0x38, 0xBF, 0x5F, 0xD5, 0xA6, 0x06, 0x19,
+ 0x39, 0x01, 0xA0, 0x8F, 0x4A, 0xB4, 0x1A, 0xAB,
+ 0x9B, 0x13, 0x48, 0x80
+ },
+ .len = 800
+ },
+ .ciphertext = {
+ .data = {
+ 0x8C, 0xEB, 0xA6, 0x29, 0x43, 0xDC, 0xED, 0x3A,
+ 0x09, 0x90, 0xB0, 0x6E, 0xA1, 0xB0, 0xA2, 0xC4,
+ 0xFB, 0x3C, 0xED, 0xC7, 0x1B, 0x36, 0x9F, 0x42,
+ 0xBA, 0x64, 0xC1, 0xEB, 0x66, 0x65, 0xE7, 0x2A,
+ 0xA1, 0xC9, 0xBB, 0x0D, 0xEA, 0xA2, 0x0F, 0xE8,
+ 0x60, 0x58, 0xB8, 0xBA, 0xEE, 0x2C, 0x2E, 0x7F,
+ 0x0B, 0xEC, 0xCE, 0x48, 0xB5, 0x29, 0x32, 0xA5,
+ 0x3C, 0x9D, 0x5F, 0x93, 0x1A, 0x3A, 0x7C, 0x53,
+ 0x22, 0x59, 0xAF, 0x43, 0x25, 0xE2, 0xA6, 0x5E,
+ 0x30, 0x84, 0xAD, 0x5F, 0x6A, 0x51, 0x3B, 0x7B,
+ 0xDD, 0xC1, 0xB6, 0x5F, 0x0A, 0xA0, 0xD9, 0x7A,
+ 0x05, 0x3D, 0xB5, 0x5A, 0x88, 0xC4, 0xC4, 0xF9,
+ 0x60, 0x5E, 0x41, 0x40
+ },
+ .len = 800
+ },
+ .cipher = {
+ .offset_bits = 0
+ },
+ .validDataLenInBits = {
+ .len = 798
+ },
+ .validCipherLenInBits = {
+ .len = 800
+ },
+ .auth_iv = {
+ .data = {
+ 0x72, 0xA4, 0xF2, 0x0F, 0x64, 0x00, 0x00, 0x00,
+ 0x72, 0xA4, 0xF2, 0x0F, 0x64, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ }
+};
+
+struct snow3g_test_data snow3g_test_case_2 = {
+ .key = {
+ .data = {
+ 0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A,
+ 0x7C, 0x36, 0xEA, 0x55, 0xE9, 0x60, 0x56, 0x95
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xE2, 0x8B, 0xCF, 0x7B, 0xC0, 0x00, 0x00, 0x00,
+ 0xE2, 0x8B, 0xCF, 0x7B, 0xC0, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x10, 0x11, 0x12, 0x31, 0xE0, 0x60, 0x25, 0x3A,
+ 0x43, 0xFD, 0x3F, 0x57, 0xE3, 0x76, 0x07, 0xAB,
+ 0x28, 0x27, 0xB5, 0x99, 0xB6, 0xB1, 0xBB, 0xDA,
+ 0x37, 0xA8, 0xAB, 0xCC, 0x5A, 0x8C, 0x55, 0x0D,
+ 0x1B, 0xFB, 0x2F, 0x49, 0x46, 0x24, 0xFB, 0x50,
+ 0x36, 0x7F, 0xA3, 0x6C, 0xE3, 0xBC, 0x68, 0xF1,
+ 0x1C, 0xF9, 0x3B, 0x15, 0x10, 0x37, 0x6B, 0x02,
+ 0x13, 0x0F, 0x81, 0x2A, 0x9F, 0xA1, 0x69, 0xD8
+ },
+ .len = 512
+ },
+ .ciphertext = {
+ .data = {
+ 0xE0, 0xDA, 0x15, 0xCA, 0x8E, 0x25, 0x54, 0xF5,
+ 0xE5, 0x6C, 0x94, 0x68, 0xDC, 0x6C, 0x7C, 0x12,
+ 0x9C, 0x56, 0x8A, 0xA5, 0x03, 0x23, 0x17, 0xE0,
+ 0x4E, 0x07, 0x29, 0x64, 0x6C, 0xAB, 0xEF, 0xA6,
+ 0x89, 0x86, 0x4C, 0x41, 0x0F, 0x24, 0xF9, 0x19,
+ 0xE6, 0x1E, 0x3D, 0xFD, 0xFA, 0xD7, 0x7E, 0x56,
+ 0x0D, 0xB0, 0xA9, 0xCD, 0x36, 0xC3, 0x4A, 0xE4,
+ 0x18, 0x14, 0x90, 0xB2, 0x9F, 0x5F, 0xA2, 0xFC
+ },
+ .len = 512
+ },
+ .cipher = {
+ .offset_bits = 0
+ },
+ .validDataLenInBits = {
+ .len = 510
+ },
+ .validCipherLenInBits = {
+ .len = 512
+ },
+ .auth_iv = {
+ .data = {
+ 0xE2, 0x8B, 0xCF, 0x7B, 0xC0, 0x00, 0x00, 0x00,
+ 0xE2, 0x8B, 0xCF, 0x7B, 0xC0, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ }
+};
+
+struct snow3g_test_data snow3g_test_case_3 = {
+ .key = {
+ .data = {
+ 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20,
+ 0x4E, 0xA5, 0xF1, 0x45, 0x10, 0x10, 0xD8, 0x52
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00,
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xAD, 0x9C, 0x44, 0x1F, 0x89, 0x0B, 0x38, 0xC4,
+ 0x57, 0xA4, 0x9D, 0x42, 0x14, 0x07, 0xE8
+ },
+ .len = 120
+ },
+ .ciphertext = {
+ .data = {
+ 0xBA, 0x0F, 0x31, 0x30, 0x03, 0x34, 0xC5, 0x6B,
+ 0x52, 0xA7, 0x49, 0x7C, 0xBA, 0xC0, 0x46
+ },
+ .len = 120
+ },
+ .cipher = {
+ .offset_bits = 0
+ },
+ .validDataLenInBits = {
+ .len = 120
+ },
+ .validCipherLenInBits = {
+ .len = 120
+ },
+ .auth_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00,
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {0xE8, 0x60, 0x5A, 0x3E},
+ .len = 4
+ },
+ .validAuthLenInBits = {
+ .len = 120
+ }
+};
+
+struct snow3g_test_data snow3g_test_case_4 = {
+ .key = {
+ .data = {
+ 0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C,
+ 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x39, 0x8A, 0x59, 0xB4, 0x2C, 0x00, 0x00, 0x00,
+ 0x39, 0x8A, 0x59, 0xB4, 0x2C, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x1B, 0xA6, 0x82, 0x4C, 0x1B, 0xFB, 0x1A,
+ 0xB4, 0x85, 0x47, 0x20, 0x29, 0xB7, 0x1D, 0x80,
+ 0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC,
+ 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66, 0xB1, 0xF0
+ },
+ .len = 256
+ },
+ .ciphertext = {
+ .data = {
+ 0x98, 0x9B, 0x71, 0x9C, 0xDC, 0x33, 0xCE, 0xB7,
+ 0xCF, 0x27, 0x6A, 0x52, 0x82, 0x7C, 0xEF, 0x94,
+ 0xA5, 0x6C, 0x40, 0xC0, 0xAB, 0x9D, 0x81, 0xF7,
+ 0xA2, 0xA9, 0xBA, 0xC6, 0x0E, 0x11, 0xC4, 0xB0
+ },
+ .len = 256
+ },
+ .cipher = {
+ .offset_bits = 0
+ },
+ .validDataLenInBits = {
+ .len = 253
+ },
+ .validCipherLenInBits = {
+ .len = 256
+ }
+};
+
+struct snow3g_test_data snow3g_test_case_5 = {
+ .key = {
+ .data = {
+ 0x60, 0x90, 0xEA, 0xE0, 0x4C, 0x83, 0x70, 0x6E,
+ 0xEC, 0xBF, 0x65, 0x2B, 0xE8, 0xE3, 0x65, 0x66
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x72, 0xA4, 0xF2, 0x0F, 0x48, 0x00, 0x00, 0x00,
+ 0x72, 0xA4, 0xF2, 0x0F, 0x48, 0x00, 0x00, 0x00
+ },
+ .len = 16},
+ .plaintext = {
+ .data = {
+ 0x40, 0x98, 0x1B, 0xA6, 0x82, 0x4C, 0x1B, 0xFB,
+ 0x42, 0x86, 0xB2, 0x99, 0x78, 0x3D, 0xAF, 0x44,
+ 0x2C, 0x09, 0x9F, 0x7A, 0xB0, 0xF5, 0x8D, 0x5C,
+ 0x8E, 0x46, 0xB1, 0x04, 0xF0, 0x8F, 0x01, 0xB4,
+ 0x1A, 0xB4, 0x85, 0x47, 0x20, 0x29, 0xB7, 0x1D,
+ 0x36, 0xBD, 0x1A, 0x3D, 0x90, 0xDC, 0x3A, 0x41,
+ 0xB4, 0x6D, 0x51, 0x67, 0x2A, 0xC4, 0xC9, 0x66,
+ 0x3A, 0x2B, 0xE0, 0x63, 0xDA, 0x4B, 0xC8, 0xD2,
+ 0x80, 0x8C, 0xE3, 0x3E, 0x2C, 0xCC, 0xBF, 0xC6,
+ 0x34, 0xE1, 0xB2, 0x59, 0x06, 0x08, 0x76, 0xA0,
+ 0xFB, 0xB5, 0xA4, 0x37, 0xEB, 0xCC, 0x8D, 0x31,
+ 0xC1, 0x9E, 0x44, 0x54, 0x31, 0x87, 0x45, 0xE3,
+ 0x98, 0x76, 0x45, 0x98, 0x7A, 0x98, 0x6F, 0x2C,
+ 0xB0
+ },
+ .len = 840
+ },
+ .ciphertext = {
+ .data = {
+ 0x58, 0x92, 0xBB, 0xA8, 0x8B, 0xBB, 0xCA, 0xAE,
+ 0xAE, 0x76, 0x9A, 0xA0, 0x6B, 0x68, 0x3D, 0x3A,
+ 0x17, 0xCC, 0x04, 0xA3, 0x69, 0x88, 0x16, 0x97,
+ 0x43, 0x5E, 0x44, 0xFE, 0xD5, 0xFF, 0x9A, 0xF5,
+ 0x7B, 0x9E, 0x89, 0x0D, 0x4D, 0x5C, 0x64, 0x70,
+ 0x98, 0x85, 0xD4, 0x8A, 0xE4, 0x06, 0x90, 0xEC,
+ 0x04, 0x3B, 0xAA, 0xE9, 0x70, 0x57, 0x96, 0xE4,
+ 0xA9, 0xFF, 0x5A, 0x4B, 0x8D, 0x8B, 0x36, 0xD7,
+ 0xF3, 0xFE, 0x57, 0xCC, 0x6C, 0xFD, 0x6C, 0xD0,
+ 0x05, 0xCD, 0x38, 0x52, 0xA8, 0x5E, 0x94, 0xCE,
+ 0x6B, 0xCD, 0x90, 0xD0, 0xD0, 0x78, 0x39, 0xCE,
+ 0x09, 0x73, 0x35, 0x44, 0xCA, 0x8E, 0x35, 0x08,
+ 0x43, 0x24, 0x85, 0x50, 0x92, 0x2A, 0xC1, 0x28,
+ 0x18
+ },
+ .len = 840
+ },
+ .cipher = {
+ .offset_bits = 0
+ },
+ .validDataLenInBits = {
+ .len = 837
+ },
+ .validCipherLenInBits = {
+ .len = 840
+ },
+};
+
+struct snow3g_test_data snow3g_auth_cipher_test_case_1 = {
+ .key = {
+ .data = {
+ 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+ 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+ 0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+ 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+ 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+ 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+ 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+ 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+ },
+ .len = 384
+ },
+ .ciphertext = {
+ .data = {
+ 0x95, 0x2E, 0x5A, 0xE1, 0x50, 0xB8, 0x59, 0x2A,
+ 0x9B, 0xA0, 0x38, 0xA9, 0x8E, 0x2F, 0xED, 0xAB,
+ 0xFD, 0xC8, 0x3B, 0x47, 0x46, 0x0B, 0x50, 0x16,
+ 0xEC, 0x88, 0x45, 0xB6, 0x05, 0xC7, 0x54, 0xF8,
+ 0xBD, 0x91, 0xAA, 0xB6, 0xA4, 0xDC, 0x64, 0xB4,
+ 0xCB, 0xEB, 0x97, 0x06, 0x4C, 0xF7, 0x02, 0x3D
+ },
+ .len = 384
+ },
+ .cipher = {
+ .len_bits = 384,
+ .offset_bits = 0
+ },
+ .auth = {
+ .len_bits = 384,
+ .offset_bits = 0
+ },
+ .digest = {
+ .data = {0x38, 0xB5, 0x54, 0xC0 },
+ .len = 4,
+ .offset_bytes = 0
+ },
+ .validDataLenInBits = {
+ .len = 384
+ },
+ .validCipherLenInBits = {
+ .len = 384
+ },
+ .validAuthLenInBits = {
+ .len = 384
+ },
+};
+
+struct snow3g_test_data snow3g_test_case_7 = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0xF1, 0x9E, 0x2B, 0x6F,
+ },
+ .len = 128 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xE4, 0xAD, 0x29, 0xA2, 0x6A, 0xA6,
+ 0x20, 0x1D, 0xCD, 0x08, 0x50, 0xD6, 0xE6, 0x47,
+ 0xBC, 0x88, 0x08, 0x01, 0x17, 0xFA, 0x47, 0x5B,
+ 0x90, 0x40, 0xBA, 0x0C, 0xB5, 0x58, 0xF3, 0x0C,
+ 0xA0, 0xD4, 0x98, 0x83, 0x1B, 0xCE, 0x54, 0xE3,
+ 0x29, 0x00, 0x3C, 0xA4, 0xAD, 0x74, 0xEE, 0x05,
+ 0xA3, 0x6C, 0xD4, 0xAC, 0xC6, 0x30, 0x33, 0xC9,
+ 0x37, 0x57, 0x41, 0x9B, 0xD4, 0x73, 0xB9, 0x77,
+ 0x70, 0x8B, 0x63, 0xDD, 0x22, 0xB8, 0xE1, 0x85,
+ 0xB2, 0x92, 0x7C, 0x37, 0xD3, 0x2E, 0xD9, 0xF4,
+ 0x4A, 0x69, 0x25, 0x30, 0xE3, 0x5B, 0x8B, 0xF6,
+ 0x0F, 0xDE, 0x0B, 0x92, 0xD5, 0x25, 0x52, 0x6D,
+ 0x26, 0xEB, 0x2F, 0x8A, 0x3B, 0x8B, 0x38, 0xE2,
+ 0x48, 0xD3, 0x4A, 0x98, 0xF7, 0x3A, 0xC2, 0x46,
+ 0x69, 0x8D, 0x73, 0x3E, 0x57, 0x88, 0x2C, 0x80,
+ 0xF0, 0xF2, 0x75, 0xB8, 0x7D, 0x27, 0xC6, 0xDA,
+
+ },
+ .len = 128 << 3
+ },
+ .cipher = {
+ .len_bits = 126 << 3,
+ .offset_bits = 2 << 3
+ },
+ .auth = {
+ .len_bits = 124 << 3,
+ .offset_bits = 0
+ },
+ .digest = {
+ .data = {
+ 0x7D, 0x27, 0xC6, 0xDA
+ },
+ .len = 4,
+ .offset_bytes = 124
+ },
+ .validDataLenInBits = {
+ .len = 128 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 126 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 124 << 3
+ },
+};
+
+struct snow3g_test_data snow3g_auth_cipher_test_case_2 = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x01, 0x02, 0x03, 0x04,
+
+ },
+ .len = 128 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xE4, 0xAD, 0x29, 0xA2, 0x6A, 0xA6,
+ 0x20, 0x1D, 0xCD, 0x08, 0x50, 0xD6, 0xE6, 0x47,
+ 0xBC, 0x88, 0x08, 0x01, 0x17, 0xFA, 0x47, 0x5B,
+ 0x90, 0x40, 0xBA, 0x0C, 0xB5, 0x58, 0xF3, 0x0C,
+ 0xA0, 0xD4, 0x98, 0x83, 0x1B, 0xCE, 0x54, 0xE3,
+ 0x29, 0x00, 0x3C, 0xA4, 0xAD, 0x74, 0xEE, 0x05,
+ 0xA3, 0x6C, 0xD4, 0xAC, 0xC6, 0x30, 0x33, 0xC9,
+ 0x37, 0x57, 0x41, 0x9B, 0xD4, 0x73, 0xB9, 0x77,
+ 0x70, 0x8B, 0x63, 0xDD, 0x22, 0xB8, 0xE1, 0x85,
+ 0xB2, 0x92, 0x7C, 0x37, 0xD3, 0x2E, 0xD9, 0xF4,
+ 0x4A, 0x69, 0x25, 0x30, 0xE3, 0x5B, 0x8B, 0xF6,
+ 0x0F, 0xDE, 0x0B, 0x92, 0xD5, 0x25, 0x52, 0x6D,
+ 0x26, 0xEB, 0x2F, 0x8A, 0x3B, 0x8B, 0x38, 0xE2,
+ 0x48, 0xD3, 0x4A, 0x98, 0xF7, 0x3A, 0xC2, 0x46,
+ 0x69, 0x8D, 0x73, 0x3E, 0x57, 0x88, 0x2C, 0x80,
+ 0xF0, 0xF2, 0x75, 0xB8, 0x7D, 0x27, 0xC6, 0xDA,
+
+ },
+ .len = 128 << 3
+ },
+ .cipher = {
+ .len_bits = 126 << 3,
+ .offset_bits = 2 << 3
+ },
+ .auth = {
+ .len_bits = 124 << 3,
+ .offset_bits = 0
+ },
+ .digest = {
+ .data = {
+ 0x7D, 0x27, 0xC6, 0xDA
+ },
+ .len = 4,
+ .offset_bytes = 124
+ },
+ .validDataLenInBits = {
+ .len = 128 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 126 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 124 << 3
+ },
+};
+
+struct snow3g_test_data snow3g_auth_cipher_test_case_3 = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ },
+ .len = 32 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xE4, 0xAD, 0x29, 0xA2, 0x6A, 0xA6,
+ 0x20, 0x1D, 0xCD, 0x08, 0x50, 0xD6, 0xE6, 0x47,
+ 0xBC, 0x88, 0x08, 0x01, 0x17, 0xFA, 0x47, 0x5B,
+ 0x90, 0x40, 0xBA, 0x0C, 0xBA, 0x6D, 0x6A, 0x5E,
+ },
+ .len = 32 << 3
+ },
+ .cipher = {
+ .len_bits = 30 << 3,
+ .offset_bits = 2 << 3
+ },
+ .auth = {
+ .len_bits = 28 << 3,
+ .offset_bits = 0
+ },
+ .digest = {
+ .data = {
+ 0xBA, 0x6D, 0x6A, 0x5E
+ },
+ .len = 4,
+ .offset_bytes = 28
+ },
+ .validDataLenInBits = {
+ .len = 32 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 30 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 28 << 3
+ },
+};
+
+struct snow3g_test_data snow3g_auth_cipher_partial_digest_encryption = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A
+ },
+ .len = 32 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0xE4, 0xAD,
+ 0x29, 0xA2, 0x6A, 0xA6, 0x20, 0x1D, 0xCD, 0x08,
+ 0x50, 0xD6, 0xE6, 0x47, 0xB3, 0xBD, 0xC3, 0x08
+ },
+ .len = 32 << 3
+ },
+ .cipher = {
+ .len_bits = 16 << 3,
+ .offset_bits = 14 << 3
+ },
+ .auth = {
+ .len_bits = 28 << 3,
+ .offset_bits = 0
+ },
+ .digest = {
+ .data = {
+ 0xB3, 0xBD, 0xC3, 0x08
+ },
+ .len = 4,
+ .offset_bytes = 28
+ },
+ .validDataLenInBits = {
+ .len = 32 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 16 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 28 << 3
+ },
+};
+
+#endif /* TEST_CRYPTODEV_SNOW3G_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cryptodev_zuc_test_vectors.h b/src/spdk/dpdk/app/test/test_cryptodev_zuc_test_vectors.h
new file mode 100644
index 000000000..cc2338e10
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cryptodev_zuc_test_vectors.h
@@ -0,0 +1,1132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_ZUC_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_ZUC_TEST_VECTORS_H_
+
+struct wireless_test_data {
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } key;
+
+ struct {
+ uint8_t data[64] __rte_aligned(16);
+ unsigned len;
+ } cipher_iv;
+
+ struct {
+ uint8_t data[2048];
+ unsigned len; /* length must be in Bits */
+ } plaintext;
+
+ struct {
+ uint8_t data[2048];
+ unsigned len; /* length must be in Bits */
+ } ciphertext;
+
+ struct {
+ unsigned len;
+ } validDataLenInBits;
+
+ struct {
+ unsigned len;
+ } validCipherLenInBits;
+
+ struct {
+ unsigned int len;
+ } validCipherOffsetInBits;
+
+
+ struct {
+ unsigned len;
+ } validAuthLenInBits;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ } auth_iv;
+
+ struct {
+ uint8_t data[64];
+ unsigned len;
+ unsigned int offset_bytes; /* offset must be in Bytes */
+ } digest;
+};
+static struct wireless_test_data zuc_test_case_cipher_193b = {
+ .key = {
+ .data = {
+ 0x17, 0x3D, 0x14, 0xBA, 0x50, 0x03, 0x73, 0x1D,
+ 0x7A, 0x60, 0x04, 0x94, 0x70, 0xF0, 0x0A, 0x29
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x66, 0x03, 0x54, 0x92, 0x78, 0x00, 0x00, 0x00,
+ 0x66, 0x03, 0x54, 0x92, 0x78, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x6C, 0xF6, 0x53, 0x40, 0x73, 0x55, 0x52, 0xAB,
+ 0x0C, 0x97, 0x52, 0xFA, 0x6F, 0x90, 0x25, 0xFE,
+ 0x0B, 0xD6, 0x75, 0xD9, 0x00, 0x58, 0x75, 0xB2,
+ 0x00
+ },
+ .len = 200
+ },
+ .ciphertext = {
+ .data = {
+ 0xA6, 0xC8, 0x5F, 0xC6, 0x6A, 0xFB, 0x85, 0x33,
+ 0xAA, 0xFC, 0x25, 0x18, 0xDF, 0xE7, 0x84, 0x94,
+ 0x0E, 0xE1, 0xE4, 0xB0, 0x30, 0x23, 0x8C, 0xC8,
+ 0x00
+ },
+ .len = 200
+ },
+ .validDataLenInBits = {
+ .len = 193
+ },
+ .validCipherLenInBits = {
+ .len = 193
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_800b = {
+ .key = {
+ .data = {
+ 0xE5, 0xBD, 0x3E, 0xA0, 0xEB, 0x55, 0xAD, 0xE8,
+ 0x66, 0xC6, 0xAC, 0x58, 0xBD, 0x54, 0x30, 0x2A
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x00, 0x05, 0x68, 0x23, 0xC4, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x68, 0x23, 0xC4, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x14, 0xA8, 0xEF, 0x69, 0x3D, 0x67, 0x85, 0x07,
+ 0xBB, 0xE7, 0x27, 0x0A, 0x7F, 0x67, 0xFF, 0x50,
+ 0x06, 0xC3, 0x52, 0x5B, 0x98, 0x07, 0xE4, 0x67,
+ 0xC4, 0xE5, 0x60, 0x00, 0xBA, 0x33, 0x8F, 0x5D,
+ 0x42, 0x95, 0x59, 0x03, 0x67, 0x51, 0x82, 0x22,
+ 0x46, 0xC8, 0x0D, 0x3B, 0x38, 0xF0, 0x7F, 0x4B,
+ 0xE2, 0xD8, 0xFF, 0x58, 0x05, 0xF5, 0x13, 0x22,
+ 0x29, 0xBD, 0xE9, 0x3B, 0xBB, 0xDC, 0xAF, 0x38,
+ 0x2B, 0xF1, 0xEE, 0x97, 0x2F, 0xBF, 0x99, 0x77,
+ 0xBA, 0xDA, 0x89, 0x45, 0x84, 0x7A, 0x2A, 0x6C,
+ 0x9A, 0xD3, 0x4A, 0x66, 0x75, 0x54, 0xE0, 0x4D,
+ 0x1F, 0x7F, 0xA2, 0xC3, 0x32, 0x41, 0xBD, 0x8F,
+ 0x01, 0xBA, 0x22, 0x0D
+ },
+ .len = 800
+ },
+ .ciphertext = {
+ .data = {
+ 0x13, 0x1D, 0x43, 0xE0, 0xDE, 0xA1, 0xBE, 0x5C,
+ 0x5A, 0x1B, 0xFD, 0x97, 0x1D, 0x85, 0x2C, 0xBF,
+ 0x71, 0x2D, 0x7B, 0x4F, 0x57, 0x96, 0x1F, 0xEA,
+ 0x32, 0x08, 0xAF, 0xA8, 0xBC, 0xA4, 0x33, 0xF4,
+ 0x56, 0xAD, 0x09, 0xC7, 0x41, 0x7E, 0x58, 0xBC,
+ 0x69, 0xCF, 0x88, 0x66, 0xD1, 0x35, 0x3F, 0x74,
+ 0x86, 0x5E, 0x80, 0x78, 0x1D, 0x20, 0x2D, 0xFB,
+ 0x3E, 0xCF, 0xF7, 0xFC, 0xBC, 0x3B, 0x19, 0x0F,
+ 0xE8, 0x2A, 0x20, 0x4E, 0xD0, 0xE3, 0x50, 0xFC,
+ 0x0F, 0x6F, 0x26, 0x13, 0xB2, 0xF2, 0xBC, 0xA6,
+ 0xDF, 0x5A, 0x47, 0x3A, 0x57, 0xA4, 0xA0, 0x0D,
+ 0x98, 0x5E, 0xBA, 0xD8, 0x80, 0xD6, 0xF2, 0x38,
+ 0x64, 0xA0, 0x7B, 0x01
+ },
+ .len = 800
+ },
+ .validDataLenInBits = {
+ .len = 800
+ },
+ .validCipherLenInBits = {
+ .len = 800
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_1570b = {
+ .key = {
+ .data = {
+ 0xD4, 0x55, 0x2A, 0x8F, 0xD6, 0xE6, 0x1C, 0xC8,
+ 0x1A, 0x20, 0x09, 0x14, 0x1A, 0x29, 0xC1, 0x0B
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x76, 0x45, 0x2E, 0xC1, 0x14, 0x00, 0x00, 0x00,
+ 0x76, 0x45, 0x2E, 0xC1, 0x14, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x38, 0xF0, 0x7F, 0x4B, 0xE2, 0xD8, 0xFF, 0x58,
+ 0x05, 0xF5, 0x13, 0x22, 0x29, 0xBD, 0xE9, 0x3B,
+ 0xBB, 0xDC, 0xAF, 0x38, 0x2B, 0xF1, 0xEE, 0x97,
+ 0x2F, 0xBF, 0x99, 0x77, 0xBA, 0xDA, 0x89, 0x45,
+ 0x84, 0x7A, 0x2A, 0x6C, 0x9A, 0xD3, 0x4A, 0x66,
+ 0x75, 0x54, 0xE0, 0x4D, 0x1F, 0x7F, 0xA2, 0xC3,
+ 0x32, 0x41, 0xBD, 0x8F, 0x01, 0xBA, 0x22, 0x0D,
+ 0x3C, 0xA4, 0xEC, 0x41, 0xE0, 0x74, 0x59, 0x5F,
+ 0x54, 0xAE, 0x2B, 0x45, 0x4F, 0xD9, 0x71, 0x43,
+ 0x20, 0x43, 0x60, 0x19, 0x65, 0xCC, 0xA8, 0x5C,
+ 0x24, 0x17, 0xED, 0x6C, 0xBE, 0xC3, 0xBA, 0xDA,
+ 0x84, 0xFC, 0x8A, 0x57, 0x9A, 0xEA, 0x78, 0x37,
+ 0xB0, 0x27, 0x11, 0x77, 0x24, 0x2A, 0x64, 0xDC,
+ 0x0A, 0x9D, 0xE7, 0x1A, 0x8E, 0xDE, 0xE8, 0x6C,
+ 0xA3, 0xD4, 0x7D, 0x03, 0x3D, 0x6B, 0xF5, 0x39,
+ 0x80, 0x4E, 0xCA, 0x86, 0xC5, 0x84, 0xA9, 0x05,
+ 0x2D, 0xE4, 0x6A, 0xD3, 0xFC, 0xED, 0x65, 0x54,
+ 0x3B, 0xD9, 0x02, 0x07, 0x37, 0x2B, 0x27, 0xAF,
+ 0xB7, 0x92, 0x34, 0xF5, 0xFF, 0x43, 0xEA, 0x87,
+ 0x08, 0x20, 0xE2, 0xC2, 0xB7, 0x8A, 0x8A, 0xAE,
+ 0x61, 0xCC, 0xE5, 0x2A, 0x05, 0x15, 0xE3, 0x48,
+ 0xD1, 0x96, 0x66, 0x4A, 0x34, 0x56, 0xB1, 0x82,
+ 0xA0, 0x7C, 0x40, 0x6E, 0x4A, 0x20, 0x79, 0x12,
+ 0x71, 0xCF, 0xED, 0xA1, 0x65, 0xD5, 0x35, 0xEC,
+ 0x5E, 0xA2, 0xD4, 0xDF, 0x40
+ },
+ .len = 1576
+ },
+ .ciphertext = {
+ .data = {
+ 0x83, 0x83, 0xB0, 0x22, 0x9F, 0xCC, 0x0B, 0x9D,
+ 0x22, 0x95, 0xEC, 0x41, 0xC9, 0x77, 0xE9, 0xC2,
+ 0xBB, 0x72, 0xE2, 0x20, 0x37, 0x81, 0x41, 0xF9,
+ 0xC8, 0x31, 0x8F, 0x3A, 0x27, 0x0D, 0xFB, 0xCD,
+ 0xEE, 0x64, 0x11, 0xC2, 0xB3, 0x04, 0x4F, 0x17,
+ 0x6D, 0xC6, 0xE0, 0x0F, 0x89, 0x60, 0xF9, 0x7A,
+ 0xFA, 0xCD, 0x13, 0x1A, 0xD6, 0xA3, 0xB4, 0x9B,
+ 0x16, 0xB7, 0xBA, 0xBC, 0xF2, 0xA5, 0x09, 0xEB,
+ 0xB1, 0x6A, 0x75, 0xDC, 0xAB, 0x14, 0xFF, 0x27,
+ 0x5D, 0xBE, 0xEE, 0xA1, 0xA2, 0xB1, 0x55, 0xF9,
+ 0xD5, 0x2C, 0x26, 0x45, 0x2D, 0x01, 0x87, 0xC3,
+ 0x10, 0xA4, 0xEE, 0x55, 0xBE, 0xAA, 0x78, 0xAB,
+ 0x40, 0x24, 0x61, 0x5B, 0xA9, 0xF5, 0xD5, 0xAD,
+ 0xC7, 0x72, 0x8F, 0x73, 0x56, 0x06, 0x71, 0xF0,
+ 0x13, 0xE5, 0xE5, 0x50, 0x08, 0x5D, 0x32, 0x91,
+ 0xDF, 0x7D, 0x5F, 0xEC, 0xED, 0xDE, 0xD5, 0x59,
+ 0x64, 0x1B, 0x6C, 0x2F, 0x58, 0x52, 0x33, 0xBC,
+ 0x71, 0xE9, 0x60, 0x2B, 0xD2, 0x30, 0x58, 0x55,
+ 0xBB, 0xD2, 0x5F, 0xFA, 0x7F, 0x17, 0xEC, 0xBC,
+ 0x04, 0x2D, 0xAA, 0xE3, 0x8C, 0x1F, 0x57, 0xAD,
+ 0x8E, 0x8E, 0xBD, 0x37, 0x34, 0x6F, 0x71, 0xBE,
+ 0xFD, 0xBB, 0x74, 0x32, 0xE0, 0xE0, 0xBB, 0x2C,
+ 0xFC, 0x09, 0xBC, 0xD9, 0x65, 0x70, 0xCB, 0x0C,
+ 0x0C, 0x39, 0xDF, 0x5E, 0x29, 0x29, 0x4E, 0x82,
+ 0x70, 0x3A, 0x63, 0x7F, 0x80
+ },
+ .len = 1576
+ },
+ .validDataLenInBits = {
+ .len = 1570
+ },
+ .validCipherLenInBits = {
+ .len = 1570
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_2798b = {
+ .key = {
+ .data = {
+ 0xDB, 0x84, 0xB4, 0xFB, 0xCC, 0xDA, 0x56, 0x3B,
+ 0x66, 0x22, 0x7B, 0xFE, 0x45, 0x6F, 0x0F, 0x77
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0xE4, 0x85, 0x0F, 0xE1, 0x84, 0x00, 0x00, 0x00,
+ 0xE4, 0x85, 0x0F, 0xE1, 0x84, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xE5, 0x39, 0xF3, 0xB8, 0x97, 0x32, 0x40, 0xDA,
+ 0x03, 0xF2, 0xB8, 0xAA, 0x05, 0xEE, 0x0A, 0x00,
+ 0xDB, 0xAF, 0xC0, 0xE1, 0x82, 0x05, 0x5D, 0xFE,
+ 0x3D, 0x73, 0x83, 0xD9, 0x2C, 0xEF, 0x40, 0xE9,
+ 0x29, 0x28, 0x60, 0x5D, 0x52, 0xD0, 0x5F, 0x4F,
+ 0x90, 0x18, 0xA1, 0xF1, 0x89, 0xAE, 0x39, 0x97,
+ 0xCE, 0x19, 0x15, 0x5F, 0xB1, 0x22, 0x1D, 0xB8,
+ 0xBB, 0x09, 0x51, 0xA8, 0x53, 0xAD, 0x85, 0x2C,
+ 0xE1, 0x6C, 0xFF, 0x07, 0x38, 0x2C, 0x93, 0xA1,
+ 0x57, 0xDE, 0x00, 0xDD, 0xB1, 0x25, 0xC7, 0x53,
+ 0x9F, 0xD8, 0x50, 0x45, 0xE4, 0xEE, 0x07, 0xE0,
+ 0xC4, 0x3F, 0x9E, 0x9D, 0x6F, 0x41, 0x4F, 0xC4,
+ 0xD1, 0xC6, 0x29, 0x17, 0x81, 0x3F, 0x74, 0xC0,
+ 0x0F, 0xC8, 0x3F, 0x3E, 0x2E, 0xD7, 0xC4, 0x5B,
+ 0xA5, 0x83, 0x52, 0x64, 0xB4, 0x3E, 0x0B, 0x20,
+ 0xAF, 0xDA, 0x6B, 0x30, 0x53, 0xBF, 0xB6, 0x42,
+ 0x3B, 0x7F, 0xCE, 0x25, 0x47, 0x9F, 0xF5, 0xF1,
+ 0x39, 0xDD, 0x9B, 0x5B, 0x99, 0x55, 0x58, 0xE2,
+ 0xA5, 0x6B, 0xE1, 0x8D, 0xD5, 0x81, 0xCD, 0x01,
+ 0x7C, 0x73, 0x5E, 0x6F, 0x0D, 0x0D, 0x97, 0xC4,
+ 0xDD, 0xC1, 0xD1, 0xDA, 0x70, 0xC6, 0xDB, 0x4A,
+ 0x12, 0xCC, 0x92, 0x77, 0x8E, 0x2F, 0xBB, 0xD6,
+ 0xF3, 0xBA, 0x52, 0xAF, 0x91, 0xC9, 0xC6, 0xB6,
+ 0x4E, 0x8D, 0xA4, 0xF7, 0xA2, 0xC2, 0x66, 0xD0,
+ 0x2D, 0x00, 0x17, 0x53, 0xDF, 0x08, 0x96, 0x03,
+ 0x93, 0xC5, 0xD5, 0x68, 0x88, 0xBF, 0x49, 0xEB,
+ 0x5C, 0x16, 0xD9, 0xA8, 0x04, 0x27, 0xA4, 0x16,
+ 0xBC, 0xB5, 0x97, 0xDF, 0x5B, 0xFE, 0x6F, 0x13,
+ 0x89, 0x0A, 0x07, 0xEE, 0x13, 0x40, 0xE6, 0x47,
+ 0x6B, 0x0D, 0x9A, 0xA8, 0xF8, 0x22, 0xAB, 0x0F,
+ 0xD1, 0xAB, 0x0D, 0x20, 0x4F, 0x40, 0xB7, 0xCE,
+ 0x6F, 0x2E, 0x13, 0x6E, 0xB6, 0x74, 0x85, 0xE5,
+ 0x07, 0x80, 0x4D, 0x50, 0x45, 0x88, 0xAD, 0x37,
+ 0xFF, 0xD8, 0x16, 0x56, 0x8B, 0x2D, 0xC4, 0x03,
+ 0x11, 0xDF, 0xB6, 0x54, 0xCD, 0xEA, 0xD4, 0x7E,
+ 0x23, 0x85, 0xC3, 0x43, 0x62, 0x03, 0xDD, 0x83,
+ 0x6F, 0x9C, 0x64, 0xD9, 0x74, 0x62, 0xAD, 0x5D,
+ 0xFA, 0x63, 0xB5, 0xCF, 0xE0, 0x8A, 0xCB, 0x95,
+ 0x32, 0x86, 0x6F, 0x5C, 0xA7, 0x87, 0x56, 0x6F,
+ 0xCA, 0x93, 0xE6, 0xB1, 0x69, 0x3E, 0xE1, 0x5C,
+ 0xF6, 0xF7, 0xA2, 0xD6, 0x89, 0xD9, 0x74, 0x17,
+ 0x98, 0xDC, 0x1C, 0x23, 0x8E, 0x1B, 0xE6, 0x50,
+ 0x73, 0x3B, 0x18, 0xFB, 0x34, 0xFF, 0x88, 0x0E,
+ 0x16, 0xBB, 0xD2, 0x1B, 0x47, 0xAC
+ },
+ .len = 2800
+ },
+ .ciphertext = {
+ .data = {
+ 0x4B, 0xBF, 0xA9, 0x1B, 0xA2, 0x5D, 0x47, 0xDB,
+ 0x9A, 0x9F, 0x19, 0x0D, 0x96, 0x2A, 0x19, 0xAB,
+ 0x32, 0x39, 0x26, 0xB3, 0x51, 0xFB, 0xD3, 0x9E,
+ 0x35, 0x1E, 0x05, 0xDA, 0x8B, 0x89, 0x25, 0xE3,
+ 0x0B, 0x1C, 0xCE, 0x0D, 0x12, 0x21, 0x10, 0x10,
+ 0x95, 0x81, 0x5C, 0xC7, 0xCB, 0x63, 0x19, 0x50,
+ 0x9E, 0xC0, 0xD6, 0x79, 0x40, 0x49, 0x19, 0x87,
+ 0xE1, 0x3F, 0x0A, 0xFF, 0xAC, 0x33, 0x2A, 0xA6,
+ 0xAA, 0x64, 0x62, 0x6D, 0x3E, 0x9A, 0x19, 0x17,
+ 0x51, 0x9E, 0x0B, 0x97, 0xB6, 0x55, 0xC6, 0xA1,
+ 0x65, 0xE4, 0x4C, 0xA9, 0xFE, 0xAC, 0x07, 0x90,
+ 0xD2, 0xA3, 0x21, 0xAD, 0x3D, 0x86, 0xB7, 0x9C,
+ 0x51, 0x38, 0x73, 0x9F, 0xA3, 0x8D, 0x88, 0x7E,
+ 0xC7, 0xDE, 0xF4, 0x49, 0xCE, 0x8A, 0xBD, 0xD3,
+ 0xE7, 0xF8, 0xDC, 0x4C, 0xA9, 0xE7, 0xB7, 0x33,
+ 0x14, 0xAD, 0x31, 0x0F, 0x90, 0x25, 0xE6, 0x19,
+ 0x46, 0xB3, 0xA5, 0x6D, 0xC6, 0x49, 0xEC, 0x0D,
+ 0xA0, 0xD6, 0x39, 0x43, 0xDF, 0xF5, 0x92, 0xCF,
+ 0x96, 0x2A, 0x7E, 0xFB, 0x2C, 0x85, 0x24, 0xE3,
+ 0x5A, 0x2A, 0x6E, 0x78, 0x79, 0xD6, 0x26, 0x04,
+ 0xEF, 0x26, 0x86, 0x95, 0xFA, 0x40, 0x03, 0x02,
+ 0x7E, 0x22, 0xE6, 0x08, 0x30, 0x77, 0x52, 0x20,
+ 0x64, 0xBD, 0x4A, 0x5B, 0x90, 0x6B, 0x5F, 0x53,
+ 0x12, 0x74, 0xF2, 0x35, 0xED, 0x50, 0x6C, 0xFF,
+ 0x01, 0x54, 0xC7, 0x54, 0x92, 0x8A, 0x0C, 0xE5,
+ 0x47, 0x6F, 0x2C, 0xB1, 0x02, 0x0A, 0x12, 0x22,
+ 0xD3, 0x2C, 0x14, 0x55, 0xEC, 0xAE, 0xF1, 0xE3,
+ 0x68, 0xFB, 0x34, 0x4D, 0x17, 0x35, 0xBF, 0xBE,
+ 0xDE, 0xB7, 0x1D, 0x0A, 0x33, 0xA2, 0xA5, 0x4B,
+ 0x1D, 0xA5, 0xA2, 0x94, 0xE6, 0x79, 0x14, 0x4D,
+ 0xDF, 0x11, 0xEB, 0x1A, 0x3D, 0xE8, 0xCF, 0x0C,
+ 0xC0, 0x61, 0x91, 0x79, 0x74, 0xF3, 0x5C, 0x1D,
+ 0x9C, 0xA0, 0xAC, 0x81, 0x80, 0x7F, 0x8F, 0xCC,
+ 0xE6, 0x19, 0x9A, 0x6C, 0x77, 0x12, 0xDA, 0x86,
+ 0x50, 0x21, 0xB0, 0x4C, 0xE0, 0x43, 0x95, 0x16,
+ 0xF1, 0xA5, 0x26, 0xCC, 0xDA, 0x9F, 0xD9, 0xAB,
+ 0xBD, 0x53, 0xC3, 0xA6, 0x84, 0xF9, 0xAE, 0x1E,
+ 0x7E, 0xE6, 0xB1, 0x1D, 0xA1, 0x38, 0xEA, 0x82,
+ 0x6C, 0x55, 0x16, 0xB5, 0xAA, 0xDF, 0x1A, 0xBB,
+ 0xE3, 0x6F, 0xA7, 0xFF, 0xF9, 0x2E, 0x3A, 0x11,
+ 0x76, 0x06, 0x4E, 0x8D, 0x95, 0xF2, 0xE4, 0x88,
+ 0x2B, 0x55, 0x00, 0xB9, 0x32, 0x28, 0xB2, 0x19,
+ 0x4A, 0x47, 0x5C, 0x1A, 0x27, 0xF6, 0x3F, 0x9F,
+ 0xFD, 0x26, 0x49, 0x89, 0xA1, 0xBC
+ },
+ .len = 2800
+ },
+ .validDataLenInBits = {
+ .len = 2798
+ },
+ .validCipherLenInBits = {
+ .len = 2798
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_4019b = {
+ .key = {
+ .data = {
+ 0xE1, 0x3F, 0xED, 0x21, 0xB4, 0x6E, 0x4E, 0x7E,
+ 0xC3, 0x12, 0x53, 0xB2, 0xBB, 0x17, 0xB3, 0xE0
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x27, 0x38, 0xCD, 0xAA, 0xD0, 0x00, 0x00, 0x00,
+ 0x27, 0x38, 0xCD, 0xAA, 0xD0, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x8D, 0x74, 0xE2, 0x0D, 0x54, 0x89, 0x4E, 0x06,
+ 0xD3, 0xCB, 0x13, 0xCB, 0x39, 0x33, 0x06, 0x5E,
+ 0x86, 0x74, 0xBE, 0x62, 0xAD, 0xB1, 0xC7, 0x2B,
+ 0x3A, 0x64, 0x69, 0x65, 0xAB, 0x63, 0xCB, 0x7B,
+ 0x78, 0x54, 0xDF, 0xDC, 0x27, 0xE8, 0x49, 0x29,
+ 0xF4, 0x9C, 0x64, 0xB8, 0x72, 0xA4, 0x90, 0xB1,
+ 0x3F, 0x95, 0x7B, 0x64, 0x82, 0x7E, 0x71, 0xF4,
+ 0x1F, 0xBD, 0x42, 0x69, 0xA4, 0x2C, 0x97, 0xF8,
+ 0x24, 0x53, 0x70, 0x27, 0xF8, 0x6E, 0x9F, 0x4A,
+ 0xD8, 0x2D, 0x1D, 0xF4, 0x51, 0x69, 0x0F, 0xDD,
+ 0x98, 0xB6, 0xD0, 0x3F, 0x3A, 0x0E, 0xBE, 0x3A,
+ 0x31, 0x2D, 0x6B, 0x84, 0x0B, 0xA5, 0xA1, 0x82,
+ 0x0B, 0x2A, 0x2C, 0x97, 0x09, 0xC0, 0x90, 0xD2,
+ 0x45, 0xED, 0x26, 0x7C, 0xF8, 0x45, 0xAE, 0x41,
+ 0xFA, 0x97, 0x5D, 0x33, 0x33, 0xAC, 0x30, 0x09,
+ 0xFD, 0x40, 0xEB, 0xA9, 0xEB, 0x5B, 0x88, 0x57,
+ 0x14, 0xB7, 0x68, 0xB6, 0x97, 0x13, 0x8B, 0xAF,
+ 0x21, 0x38, 0x0E, 0xCA, 0x49, 0xF6, 0x44, 0xD4,
+ 0x86, 0x89, 0xE4, 0x21, 0x57, 0x60, 0xB9, 0x06,
+ 0x73, 0x9F, 0x0D, 0x2B, 0x3F, 0x09, 0x11, 0x33,
+ 0xCA, 0x15, 0xD9, 0x81, 0xCB, 0xE4, 0x01, 0xBA,
+ 0xF7, 0x2D, 0x05, 0xAC, 0xE0, 0x5C, 0xCC, 0xB2,
+ 0xD2, 0x97, 0xF4, 0xEF, 0x6A, 0x5F, 0x58, 0xD9,
+ 0x12, 0x46, 0xCF, 0xA7, 0x72, 0x15, 0xB8, 0x92,
+ 0xAB, 0x44, 0x1D, 0x52, 0x78, 0x45, 0x27, 0x95,
+ 0xCC, 0xB7, 0xF5, 0xD7, 0x90, 0x57, 0xA1, 0xC4,
+ 0xF7, 0x7F, 0x80, 0xD4, 0x6D, 0xB2, 0x03, 0x3C,
+ 0xB7, 0x9B, 0xED, 0xF8, 0xE6, 0x05, 0x51, 0xCE,
+ 0x10, 0xC6, 0x67, 0xF6, 0x2A, 0x97, 0xAB, 0xAF,
+ 0xAB, 0xBC, 0xD6, 0x77, 0x20, 0x18, 0xDF, 0x96,
+ 0xA2, 0x82, 0xEA, 0x73, 0x7C, 0xE2, 0xCB, 0x33,
+ 0x12, 0x11, 0xF6, 0x0D, 0x53, 0x54, 0xCE, 0x78,
+ 0xF9, 0x91, 0x8D, 0x9C, 0x20, 0x6C, 0xA0, 0x42,
+ 0xC9, 0xB6, 0x23, 0x87, 0xDD, 0x70, 0x96, 0x04,
+ 0xA5, 0x0A, 0xF1, 0x6D, 0x8D, 0x35, 0xA8, 0x90,
+ 0x6B, 0xE4, 0x84, 0xCF, 0x2E, 0x74, 0xA9, 0x28,
+ 0x99, 0x40, 0x36, 0x43, 0x53, 0x24, 0x9B, 0x27,
+ 0xB4, 0xC9, 0xAE, 0x29, 0xED, 0xDF, 0xC7, 0xDA,
+ 0x64, 0x18, 0x79, 0x1A, 0x4E, 0x7B, 0xAA, 0x06,
+ 0x60, 0xFA, 0x64, 0x51, 0x1F, 0x2D, 0x68, 0x5C,
+ 0xC3, 0xA5, 0xFF, 0x70, 0xE0, 0xD2, 0xB7, 0x42,
+ 0x92, 0xE3, 0xB8, 0xA0, 0xCD, 0x6B, 0x04, 0xB1,
+ 0xC7, 0x90, 0xB8, 0xEA, 0xD2, 0x70, 0x37, 0x08,
+ 0x54, 0x0D, 0xEA, 0x2F, 0xC0, 0x9C, 0x3D, 0xA7,
+ 0x70, 0xF6, 0x54, 0x49, 0xE8, 0x4D, 0x81, 0x7A,
+ 0x4F, 0x55, 0x10, 0x55, 0xE1, 0x9A, 0xB8, 0x50,
+ 0x18, 0xA0, 0x02, 0x8B, 0x71, 0xA1, 0x44, 0xD9,
+ 0x67, 0x91, 0xE9, 0xA3, 0x57, 0x79, 0x33, 0x50,
+ 0x4E, 0xEE, 0x00, 0x60, 0x34, 0x0C, 0x69, 0xD2,
+ 0x74, 0xE1, 0xBF, 0x9D, 0x80, 0x5D, 0xCB, 0xCC,
+ 0x1A, 0x6F, 0xAA, 0x97, 0x68, 0x00, 0xB6, 0xFF,
+ 0x2B, 0x67, 0x1D, 0xC4, 0x63, 0x65, 0x2F, 0xA8,
+ 0xA3, 0x3E, 0xE5, 0x09, 0x74, 0xC1, 0xC2, 0x1B,
+ 0xE0, 0x1E, 0xAB, 0xB2, 0x16, 0x74, 0x30, 0x26,
+ 0x9D, 0x72, 0xEE, 0x51, 0x1C, 0x9D, 0xDE, 0x30,
+ 0x79, 0x7C, 0x9A, 0x25, 0xD8, 0x6C, 0xE7, 0x4F,
+ 0x5B, 0x96, 0x1B, 0xE5, 0xFD, 0xFB, 0x68, 0x07,
+ 0x81, 0x40, 0x39, 0xE7, 0x13, 0x76, 0x36, 0xBD,
+ 0x1D, 0x7F, 0xA9, 0xE0, 0x9E, 0xFD, 0x20, 0x07,
+ 0x50, 0x59, 0x06, 0xA5, 0xAC, 0x45, 0xDF, 0xDE,
+ 0xED, 0x77, 0x57, 0xBB, 0xEE, 0x74, 0x57, 0x49,
+ 0xC2, 0x96, 0x33, 0x35, 0x0B, 0xEE, 0x0E, 0xA6,
+ 0xF4, 0x09, 0xDF, 0x45, 0x80, 0x16, 0x00
+ },
+ .len = 4024
+ },
+ .ciphertext = {
+ .data = {
+ 0x94, 0xEA, 0xA4, 0xAA, 0x30, 0xA5, 0x71, 0x37,
+ 0xDD, 0xF0, 0x9B, 0x97, 0xB2, 0x56, 0x18, 0xA2,
+ 0x0A, 0x13, 0xE2, 0xF1, 0x0F, 0xA5, 0xBF, 0x81,
+ 0x61, 0xA8, 0x79, 0xCC, 0x2A, 0xE7, 0x97, 0xA6,
+ 0xB4, 0xCF, 0x2D, 0x9D, 0xF3, 0x1D, 0xEB, 0xB9,
+ 0x90, 0x5C, 0xCF, 0xEC, 0x97, 0xDE, 0x60, 0x5D,
+ 0x21, 0xC6, 0x1A, 0xB8, 0x53, 0x1B, 0x7F, 0x3C,
+ 0x9D, 0xA5, 0xF0, 0x39, 0x31, 0xF8, 0xA0, 0x64,
+ 0x2D, 0xE4, 0x82, 0x11, 0xF5, 0xF5, 0x2F, 0xFE,
+ 0xA1, 0x0F, 0x39, 0x2A, 0x04, 0x76, 0x69, 0x98,
+ 0x5D, 0xA4, 0x54, 0xA2, 0x8F, 0x08, 0x09, 0x61,
+ 0xA6, 0xC2, 0xB6, 0x2D, 0xAA, 0x17, 0xF3, 0x3C,
+ 0xD6, 0x0A, 0x49, 0x71, 0xF4, 0x8D, 0x2D, 0x90,
+ 0x93, 0x94, 0xA5, 0x5F, 0x48, 0x11, 0x7A, 0xCE,
+ 0x43, 0xD7, 0x08, 0xE6, 0xB7, 0x7D, 0x3D, 0xC4,
+ 0x6D, 0x8B, 0xC0, 0x17, 0xD4, 0xD1, 0xAB, 0xB7,
+ 0x7B, 0x74, 0x28, 0xC0, 0x42, 0xB0, 0x6F, 0x2F,
+ 0x99, 0xD8, 0xD0, 0x7C, 0x98, 0x79, 0xD9, 0x96,
+ 0x00, 0x12, 0x7A, 0x31, 0x98, 0x5F, 0x10, 0x99,
+ 0xBB, 0xD7, 0xD6, 0xC1, 0x51, 0x9E, 0xDE, 0x8F,
+ 0x5E, 0xEB, 0x4A, 0x61, 0x0B, 0x34, 0x9A, 0xC0,
+ 0x1E, 0xA2, 0x35, 0x06, 0x91, 0x75, 0x6B, 0xD1,
+ 0x05, 0xC9, 0x74, 0xA5, 0x3E, 0xDD, 0xB3, 0x5D,
+ 0x1D, 0x41, 0x00, 0xB0, 0x12, 0xE5, 0x22, 0xAB,
+ 0x41, 0xF4, 0xC5, 0xF2, 0xFD, 0xE7, 0x6B, 0x59,
+ 0xCB, 0x8B, 0x96, 0xD8, 0x85, 0xCF, 0xE4, 0x08,
+ 0x0D, 0x13, 0x28, 0xA0, 0xD6, 0x36, 0xCC, 0x0E,
+ 0xDC, 0x05, 0x80, 0x0B, 0x76, 0xAC, 0xCA, 0x8F,
+ 0xEF, 0x67, 0x20, 0x84, 0xD1, 0xF5, 0x2A, 0x8B,
+ 0xBD, 0x8E, 0x09, 0x93, 0x32, 0x09, 0x92, 0xC7,
+ 0xFF, 0xBA, 0xE1, 0x7C, 0x40, 0x84, 0x41, 0xE0,
+ 0xEE, 0x88, 0x3F, 0xC8, 0xA8, 0xB0, 0x5E, 0x22,
+ 0xF5, 0xFF, 0x7F, 0x8D, 0x1B, 0x48, 0xC7, 0x4C,
+ 0x46, 0x8C, 0x46, 0x7A, 0x02, 0x8F, 0x09, 0xFD,
+ 0x7C, 0xE9, 0x11, 0x09, 0xA5, 0x70, 0xA2, 0xD5,
+ 0xC4, 0xD5, 0xF4, 0xFA, 0x18, 0xC5, 0xDD, 0x3E,
+ 0x45, 0x62, 0xAF, 0xE2, 0x4E, 0xF7, 0x71, 0x90,
+ 0x1F, 0x59, 0xAF, 0x64, 0x58, 0x98, 0xAC, 0xEF,
+ 0x08, 0x8A, 0xBA, 0xE0, 0x7E, 0x92, 0xD5, 0x2E,
+ 0xB2, 0xDE, 0x55, 0x04, 0x5B, 0xB1, 0xB7, 0xC4,
+ 0x16, 0x4E, 0xF2, 0xD7, 0xA6, 0xCA, 0xC1, 0x5E,
+ 0xEB, 0x92, 0x6D, 0x7E, 0xA2, 0xF0, 0x8B, 0x66,
+ 0xE1, 0xF7, 0x59, 0xF3, 0xAE, 0xE4, 0x46, 0x14,
+ 0x72, 0x5A, 0xA3, 0xC7, 0x48, 0x2B, 0x30, 0x84,
+ 0x4C, 0x14, 0x3F, 0xF8, 0x5B, 0x53, 0xF1, 0xE5,
+ 0x83, 0xC5, 0x01, 0x25, 0x7D, 0xDD, 0xD0, 0x96,
+ 0xB8, 0x12, 0x68, 0xDA, 0xA3, 0x03, 0xF1, 0x72,
+ 0x34, 0xC2, 0x33, 0x35, 0x41, 0xF0, 0xBB, 0x8E,
+ 0x19, 0x06, 0x48, 0xC5, 0x80, 0x7C, 0x86, 0x6D,
+ 0x71, 0x93, 0x22, 0x86, 0x09, 0xAD, 0xB9, 0x48,
+ 0x68, 0x6F, 0x7D, 0xE2, 0x94, 0xA8, 0x02, 0xCC,
+ 0x38, 0xF7, 0xFE, 0x52, 0x08, 0xF5, 0xEA, 0x31,
+ 0x96, 0xD0, 0x16, 0x7B, 0x9B, 0xDD, 0x02, 0xF0,
+ 0xD2, 0xA5, 0x22, 0x1C, 0xA5, 0x08, 0xF8, 0x93,
+ 0xAF, 0x5C, 0x4B, 0x4B, 0xB9, 0xF4, 0xF5, 0x20,
+ 0xFD, 0x84, 0x28, 0x9B, 0x3D, 0xBE, 0x7E, 0x61,
+ 0x49, 0x7A, 0x7E, 0x2A, 0x58, 0x40, 0x37, 0xEA,
+ 0x63, 0x7B, 0x69, 0x81, 0x12, 0x71, 0x74, 0xAF,
+ 0x57, 0xB4, 0x71, 0xDF, 0x4B, 0x27, 0x68, 0xFD,
+ 0x79, 0xC1, 0x54, 0x0F, 0xB3, 0xED, 0xF2, 0xEA,
+ 0x22, 0xCB, 0x69, 0xBE, 0xC0, 0xCF, 0x8D, 0x93,
+ 0x3D, 0x9C, 0x6F, 0xDD, 0x64, 0x5E, 0x85, 0x05,
+ 0x91, 0xCC, 0xA3, 0xD6, 0x2C, 0x0C, 0xC0
+ },
+ .len = 4024
+ },
+ .validDataLenInBits = {
+ .len = 4019
+ },
+ .validCipherLenInBits = {
+ .len = 4019
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_200b_auth_200b = {
+ .key = {
+ .data = {
+ 0x17, 0x3D, 0x14, 0xBA, 0x50, 0x03, 0x73, 0x1D,
+ 0x7A, 0x60, 0x04, 0x94, 0x70, 0xF0, 0x0A, 0x29
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x66, 0x03, 0x54, 0x92, 0x78, 0x00, 0x00, 0x00,
+ 0x66, 0x03, 0x54, 0x92, 0x78, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x6C, 0xF6, 0x53, 0x40, 0x73, 0x55, 0x52, 0xAB,
+ 0x0C, 0x97, 0x52, 0xFA, 0x6F, 0x90, 0x25, 0xFE,
+ 0x0B, 0xD6, 0x75, 0xD9, 0x00, 0x58, 0x75, 0xB2,
+ 0x00
+ },
+ .len = 200
+ },
+ .ciphertext = {
+ .data = {
+ 0xA6, 0xC8, 0x5F, 0xC6, 0x6A, 0xFB, 0x85, 0x33,
+ 0xAA, 0xFC, 0x25, 0x18, 0xDF, 0xE7, 0x84, 0x94,
+ 0x0E, 0xE1, 0xE4, 0xB0, 0x30, 0x23, 0x8C, 0xC8,
+ 0x10
+ },
+ .len = 200
+ },
+ .validDataLenInBits = {
+ .len = 200
+ },
+ .validCipherLenInBits = {
+ .len = 200
+ },
+ .auth_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00,
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {0x01, 0xFE, 0x5E, 0x38},
+ .len = 4
+ },
+ .validAuthLenInBits = {
+ .len = 200
+ }
+};
+
+static struct wireless_test_data zuc_test_case_cipher_800b_auth_120b = {
+ .key = {
+ .data = {
+ 0xE5, 0xBD, 0x3E, 0xA0, 0xEB, 0x55, 0xAD, 0xE8,
+ 0x66, 0xC6, 0xAC, 0x58, 0xBD, 0x54, 0x30, 0x2A
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x00, 0x05, 0x68, 0x23, 0xC4, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x68, 0x23, 0xC4, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x14, 0xA8, 0xEF, 0x69, 0x3D, 0x67, 0x85, 0x07,
+ 0xBB, 0xE7, 0x27, 0x0A, 0x7F, 0x67, 0xFF, 0x50,
+ 0x06, 0xC3, 0x52, 0x5B, 0x98, 0x07, 0xE4, 0x67,
+ 0xC4, 0xE5, 0x60, 0x00, 0xBA, 0x33, 0x8F, 0x5D,
+ 0x42, 0x95, 0x59, 0x03, 0x67, 0x51, 0x82, 0x22,
+ 0x46, 0xC8, 0x0D, 0x3B, 0x38, 0xF0, 0x7F, 0x4B,
+ 0xE2, 0xD8, 0xFF, 0x58, 0x05, 0xF5, 0x13, 0x22,
+ 0x29, 0xBD, 0xE9, 0x3B, 0xBB, 0xDC, 0xAF, 0x38,
+ 0x2B, 0xF1, 0xEE, 0x97, 0x2F, 0xBF, 0x99, 0x77,
+ 0xBA, 0xDA, 0x89, 0x45, 0x84, 0x7A, 0x2A, 0x6C,
+ 0x9A, 0xD3, 0x4A, 0x66, 0x75, 0x54, 0xE0, 0x4D,
+ 0x1F, 0x7F, 0xA2, 0xC3, 0x32, 0x41, 0xBD, 0x8F,
+ 0x01, 0xBA, 0x22, 0x0D
+ },
+ .len = 800
+ },
+ .ciphertext = {
+ .data = {
+ 0x13, 0x1D, 0x43, 0xE0, 0xDE, 0xA1, 0xBE, 0x5C,
+ 0x5A, 0x1B, 0xFD, 0x97, 0x1D, 0x85, 0x2C, 0xBF,
+ 0x71, 0x2D, 0x7B, 0x4F, 0x57, 0x96, 0x1F, 0xEA,
+ 0x32, 0x08, 0xAF, 0xA8, 0xBC, 0xA4, 0x33, 0xF4,
+ 0x56, 0xAD, 0x09, 0xC7, 0x41, 0x7E, 0x58, 0xBC,
+ 0x69, 0xCF, 0x88, 0x66, 0xD1, 0x35, 0x3F, 0x74,
+ 0x86, 0x5E, 0x80, 0x78, 0x1D, 0x20, 0x2D, 0xFB,
+ 0x3E, 0xCF, 0xF7, 0xFC, 0xBC, 0x3B, 0x19, 0x0F,
+ 0xE8, 0x2A, 0x20, 0x4E, 0xD0, 0xE3, 0x50, 0xFC,
+ 0x0F, 0x6F, 0x26, 0x13, 0xB2, 0xF2, 0xBC, 0xA6,
+ 0xDF, 0x5A, 0x47, 0x3A, 0x57, 0xA4, 0xA0, 0x0D,
+ 0x98, 0x5E, 0xBA, 0xD8, 0x80, 0xD6, 0xF2, 0x38,
+ 0x64, 0xA0, 0x7B, 0x01
+ },
+ .len = 800
+ },
+ .validDataLenInBits = {
+ .len = 800
+ },
+ .validCipherLenInBits = {
+ .len = 800
+ },
+ .auth_iv = {
+ .data = {
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00,
+ 0xFA, 0x55, 0x6B, 0x26, 0x1C, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .digest = {
+ .data = {0x9D, 0x42, 0x1C, 0xEA},
+ .len = 4
+ },
+ .validAuthLenInBits = {
+ .len = 120
+ }
+};
+
+struct wireless_test_data zuc_test_case_auth_1b = {
+ .key = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {0x00},
+ .len = 8
+ },
+ .validAuthLenInBits = {
+ .len = 1
+ },
+ .digest = {
+ .data = {0xC8, 0xA9, 0x59, 0x5E},
+ .len = 4
+ }
+};
+
+struct wireless_test_data zuc_test_case_auth_90b = {
+ .key = {
+ .data = {
+ 0x47, 0x05, 0x41, 0x25, 0x56, 0x1E, 0xB2, 0xDD,
+ 0xA9, 0x40, 0x59, 0xDA, 0x05, 0x09, 0x78, 0x50
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x56, 0x1E, 0xB2, 0xDD, 0xA0, 0x00, 0x00, 0x00,
+ 0x56, 0x1E, 0xB2, 0xDD, 0xA0, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 96
+ },
+ .validAuthLenInBits = {
+ .len = 90
+ },
+ .digest = {
+ .data = {0x67, 0x19, 0xA0, 0x88},
+ .len = 4
+ }
+};
+
+struct wireless_test_data zuc_test_case_auth_577b = {
+ .key = {
+ .data = {
+ 0xC9, 0xE6, 0xCE, 0xC4, 0x60, 0x7C, 0x72, 0xDB,
+ 0x00, 0x0A, 0xEF, 0xA8, 0x83, 0x85, 0xAB, 0x0A
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0xA9, 0x40, 0x59, 0xDA, 0x50, 0x00, 0x00, 0x00,
+ 0x29, 0x40, 0x59, 0xDA, 0x50, 0x00, 0x80, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x3B, 0x41, 0xD4, 0x7D, 0x78, 0x0C, 0x9E,
+ 0x1A, 0xD1, 0x1D, 0x7E, 0xB7, 0x03, 0x91, 0xB1,
+ 0xDE, 0x0B, 0x35, 0xDA, 0x2D, 0xC6, 0x2F, 0x83,
+ 0xE7, 0xB7, 0x8D, 0x63, 0x06, 0xCA, 0x0E, 0xA0,
+ 0x7E, 0x94, 0x1B, 0x7B, 0xE9, 0x13, 0x48, 0xF9,
+ 0xFC, 0xB1, 0x70, 0xE2, 0x21, 0x7F, 0xEC, 0xD9,
+ 0x7F, 0x9F, 0x68, 0xAD, 0xB1, 0x6E, 0x5D, 0x7D,
+ 0x21, 0xE5, 0x69, 0xD2, 0x80, 0xED, 0x77, 0x5C,
+ 0xEB, 0xDE, 0x3F, 0x40, 0x93, 0xC5, 0x38, 0x81,
+ 0x00
+ },
+ .len = 584
+ },
+ .validAuthLenInBits = {
+ .len = 577
+ },
+ .digest = {
+ .data = {0xFA, 0xE8, 0xFF, 0x0B},
+ .len = 4
+ }
+};
+
+struct wireless_test_data zuc_test_case_auth_2079b = {
+ .key = {
+ .data = {
+ 0xC8, 0xA4, 0x82, 0x62, 0xD0, 0xC2, 0xE2, 0xBA,
+ 0xC4, 0xB9, 0x6E, 0xF7, 0x7E, 0x80, 0xCA, 0x59
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x05, 0x09, 0x78, 0x50, 0x80, 0x00, 0x00, 0x00,
+ 0x85, 0x09, 0x78, 0x50, 0x80, 0x00, 0x80, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xB5, 0x46, 0x43, 0x0B, 0xF8, 0x7B, 0x4F, 0x1E,
+ 0xE8, 0x34, 0x70, 0x4C, 0xD6, 0x95, 0x1C, 0x36,
+ 0xE2, 0x6F, 0x10, 0x8C, 0xF7, 0x31, 0x78, 0x8F,
+ 0x48, 0xDC, 0x34, 0xF1, 0x67, 0x8C, 0x05, 0x22,
+ 0x1C, 0x8F, 0xA7, 0xFF, 0x2F, 0x39, 0xF4, 0x77,
+ 0xE7, 0xE4, 0x9E, 0xF6, 0x0A, 0x4E, 0xC2, 0xC3,
+ 0xDE, 0x24, 0x31, 0x2A, 0x96, 0xAA, 0x26, 0xE1,
+ 0xCF, 0xBA, 0x57, 0x56, 0x38, 0x38, 0xB2, 0x97,
+ 0xF4, 0x7E, 0x85, 0x10, 0xC7, 0x79, 0xFD, 0x66,
+ 0x54, 0xB1, 0x43, 0x38, 0x6F, 0xA6, 0x39, 0xD3,
+ 0x1E, 0xDB, 0xD6, 0xC0, 0x6E, 0x47, 0xD1, 0x59,
+ 0xD9, 0x43, 0x62, 0xF2, 0x6A, 0xEE, 0xED, 0xEE,
+ 0x0E, 0x4F, 0x49, 0xD9, 0xBF, 0x84, 0x12, 0x99,
+ 0x54, 0x15, 0xBF, 0xAD, 0x56, 0xEE, 0x82, 0xD1,
+ 0xCA, 0x74, 0x63, 0xAB, 0xF0, 0x85, 0xB0, 0x82,
+ 0xB0, 0x99, 0x04, 0xD6, 0xD9, 0x90, 0xD4, 0x3C,
+ 0xF2, 0xE0, 0x62, 0xF4, 0x08, 0x39, 0xD9, 0x32,
+ 0x48, 0xB1, 0xEB, 0x92, 0xCD, 0xFE, 0xD5, 0x30,
+ 0x0B, 0xC1, 0x48, 0x28, 0x04, 0x30, 0xB6, 0xD0,
+ 0xCA, 0xA0, 0x94, 0xB6, 0xEC, 0x89, 0x11, 0xAB,
+ 0x7D, 0xC3, 0x68, 0x24, 0xB8, 0x24, 0xDC, 0x0A,
+ 0xF6, 0x68, 0x2B, 0x09, 0x35, 0xFD, 0xE7, 0xB4,
+ 0x92, 0xA1, 0x4D, 0xC2, 0xF4, 0x36, 0x48, 0x03,
+ 0x8D, 0xA2, 0xCF, 0x79, 0x17, 0x0D, 0x2D, 0x50,
+ 0x13, 0x3F, 0xD4, 0x94, 0x16, 0xCB, 0x6E, 0x33,
+ 0xBE, 0xA9, 0x0B, 0x8B, 0xF4, 0x55, 0x9B, 0x03,
+ 0x73, 0x2A, 0x01, 0xEA, 0x29, 0x0E, 0x6D, 0x07,
+ 0x4F, 0x79, 0xBB, 0x83, 0xC1, 0x0E, 0x58, 0x00,
+ 0x15, 0xCC, 0x1A, 0x85, 0xB3, 0x6B, 0x55, 0x01,
+ 0x04, 0x6E, 0x9C, 0x4B, 0xDC, 0xAE, 0x51, 0x35,
+ 0x69, 0x0B, 0x86, 0x66, 0xBD, 0x54, 0xB7, 0xA7,
+ 0x03, 0xEA, 0x7B, 0x6F, 0x22, 0x0A, 0x54, 0x69,
+ 0xA5, 0x68, 0x02, 0x7E
+ },
+ .len = 2080
+ },
+ .validAuthLenInBits = {
+ .len = 2079
+ },
+ .digest = {
+ .data = {0x00, 0x4A, 0xC4, 0xD6},
+ .len = 4
+ }
+};
+
+struct wireless_test_data zuc_test_auth_5670b = {
+ .key = {
+ .data = {
+ 0x6B, 0x8B, 0x08, 0xEE, 0x79, 0xE0, 0xB5, 0x98,
+ 0x2D, 0x6D, 0x12, 0x8E, 0xA9, 0xF2, 0x20, 0xCB
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x56, 0x1E, 0xB2, 0xDD, 0xE0, 0x00, 0x00, 0x00,
+ 0x56, 0x1E, 0xB2, 0xDD, 0xE0, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5B, 0xAD, 0x72, 0x47, 0x10, 0xBA, 0x1C, 0x56,
+ 0xD5, 0xA3, 0x15, 0xF8, 0xD4, 0x0F, 0x6E, 0x09,
+ 0x37, 0x80, 0xBE, 0x8E, 0x8D, 0xE0, 0x7B, 0x69,
+ 0x92, 0x43, 0x20, 0x18, 0xE0, 0x8E, 0xD9, 0x6A,
+ 0x57, 0x34, 0xAF, 0x8B, 0xAD, 0x8A, 0x57, 0x5D,
+ 0x3A, 0x1F, 0x16, 0x2F, 0x85, 0x04, 0x5C, 0xC7,
+ 0x70, 0x92, 0x55, 0x71, 0xD9, 0xF5, 0xB9, 0x4E,
+ 0x45, 0x4A, 0x77, 0xC1, 0x6E, 0x72, 0x93, 0x6B,
+ 0xF0, 0x16, 0xAE, 0x15, 0x74, 0x99, 0xF0, 0x54,
+ 0x3B, 0x5D, 0x52, 0xCA, 0xA6, 0xDB, 0xEA, 0xB6,
+ 0x97, 0xD2, 0xBB, 0x73, 0xE4, 0x1B, 0x80, 0x75,
+ 0xDC, 0xE7, 0x9B, 0x4B, 0x86, 0x04, 0x4F, 0x66,
+ 0x1D, 0x44, 0x85, 0xA5, 0x43, 0xDD, 0x78, 0x60,
+ 0x6E, 0x04, 0x19, 0xE8, 0x05, 0x98, 0x59, 0xD3,
+ 0xCB, 0x2B, 0x67, 0xCE, 0x09, 0x77, 0x60, 0x3F,
+ 0x81, 0xFF, 0x83, 0x9E, 0x33, 0x18, 0x59, 0x54,
+ 0x4C, 0xFB, 0xC8, 0xD0, 0x0F, 0xEF, 0x1A, 0x4C,
+ 0x85, 0x10, 0xFB, 0x54, 0x7D, 0x6B, 0x06, 0xC6,
+ 0x11, 0xEF, 0x44, 0xF1, 0xBC, 0xE1, 0x07, 0xCF,
+ 0xA4, 0x5A, 0x06, 0xAA, 0xB3, 0x60, 0x15, 0x2B,
+ 0x28, 0xDC, 0x1E, 0xBE, 0x6F, 0x7F, 0xE0, 0x9B,
+ 0x05, 0x16, 0xF9, 0xA5, 0xB0, 0x2A, 0x1B, 0xD8,
+ 0x4B, 0xB0, 0x18, 0x1E, 0x2E, 0x89, 0xE1, 0x9B,
+ 0xD8, 0x12, 0x59, 0x30, 0xD1, 0x78, 0x68, 0x2F,
+ 0x38, 0x62, 0xDC, 0x51, 0xB6, 0x36, 0xF0, 0x4E,
+ 0x72, 0x0C, 0x47, 0xC3, 0xCE, 0x51, 0xAD, 0x70,
+ 0xD9, 0x4B, 0x9B, 0x22, 0x55, 0xFB, 0xAE, 0x90,
+ 0x65, 0x49, 0xF4, 0x99, 0xF8, 0xC6, 0xD3, 0x99,
+ 0x47, 0xED, 0x5E, 0x5D, 0xF8, 0xE2, 0xDE, 0xF1,
+ 0x13, 0x25, 0x3E, 0x7B, 0x08, 0xD0, 0xA7, 0x6B,
+ 0x6B, 0xFC, 0x68, 0xC8, 0x12, 0xF3, 0x75, 0xC7,
+ 0x9B, 0x8F, 0xE5, 0xFD, 0x85, 0x97, 0x6A, 0xA6,
+ 0xD4, 0x6B, 0x4A, 0x23, 0x39, 0xD8, 0xAE, 0x51,
+ 0x47, 0xF6, 0x80, 0xFB, 0xE7, 0x0F, 0x97, 0x8B,
+ 0x38, 0xEF, 0xFD, 0x7B, 0x2F, 0x78, 0x66, 0xA2,
+ 0x25, 0x54, 0xE1, 0x93, 0xA9, 0x4E, 0x98, 0xA6,
+ 0x8B, 0x74, 0xBD, 0x25, 0xBB, 0x2B, 0x3F, 0x5F,
+ 0xB0, 0xA5, 0xFD, 0x59, 0x88, 0x7F, 0x9A, 0xB6,
+ 0x81, 0x59, 0xB7, 0x17, 0x8D, 0x5B, 0x7B, 0x67,
+ 0x7C, 0xB5, 0x46, 0xBF, 0x41, 0xEA, 0xDC, 0xA2,
+ 0x16, 0xFC, 0x10, 0x85, 0x01, 0x28, 0xF8, 0xBD,
+ 0xEF, 0x5C, 0x8D, 0x89, 0xF9, 0x6A, 0xFA, 0x4F,
+ 0xA8, 0xB5, 0x48, 0x85, 0x56, 0x5E, 0xD8, 0x38,
+ 0xA9, 0x50, 0xFE, 0xE5, 0xF1, 0xC3, 0xB0, 0xA4,
+ 0xF6, 0xFB, 0x71, 0xE5, 0x4D, 0xFD, 0x16, 0x9E,
+ 0x82, 0xCE, 0xCC, 0x72, 0x66, 0xC8, 0x50, 0xE6,
+ 0x7C, 0x5E, 0xF0, 0xBA, 0x96, 0x0F, 0x52, 0x14,
+ 0x06, 0x0E, 0x71, 0xEB, 0x17, 0x2A, 0x75, 0xFC,
+ 0x14, 0x86, 0x83, 0x5C, 0xBE, 0xA6, 0x53, 0x44,
+ 0x65, 0xB0, 0x55, 0xC9, 0x6A, 0x72, 0xE4, 0x10,
+ 0x52, 0x24, 0x18, 0x23, 0x25, 0xD8, 0x30, 0x41,
+ 0x4B, 0x40, 0x21, 0x4D, 0xAA, 0x80, 0x91, 0xD2,
+ 0xE0, 0xFB, 0x01, 0x0A, 0xE1, 0x5C, 0x6D, 0xE9,
+ 0x08, 0x50, 0x97, 0x3B, 0xDF, 0x1E, 0x42, 0x3B,
+ 0xE1, 0x48, 0xA2, 0x37, 0xB8, 0x7A, 0x0C, 0x9F,
+ 0x34, 0xD4, 0xB4, 0x76, 0x05, 0xB8, 0x03, 0xD7,
+ 0x43, 0xA8, 0x6A, 0x90, 0x39, 0x9A, 0x4A, 0xF3,
+ 0x96, 0xD3, 0xA1, 0x20, 0x0A, 0x62, 0xF3, 0xD9,
+ 0x50, 0x79, 0x62, 0xE8, 0xE5, 0xBE, 0xE6, 0xD3,
+ 0xDA, 0x2B, 0xB3, 0xF7, 0x23, 0x76, 0x64, 0xAC,
+ 0x7A, 0x29, 0x28, 0x23, 0x90, 0x0B, 0xC6, 0x35,
+ 0x03, 0xB2, 0x9E, 0x80, 0xD6, 0x3F, 0x60, 0x67,
+ 0xBF, 0x8E, 0x17, 0x16, 0xAC, 0x25, 0xBE, 0xBA,
+ 0x35, 0x0D, 0xEB, 0x62, 0xA9, 0x9F, 0xE0, 0x31,
+ 0x85, 0xEB, 0x4F, 0x69, 0x93, 0x7E, 0xCD, 0x38,
+ 0x79, 0x41, 0xFD, 0xA5, 0x44, 0xBA, 0x67, 0xDB,
+ 0x09, 0x11, 0x77, 0x49, 0x38, 0xB0, 0x18, 0x27,
+ 0xBC, 0xC6, 0x9C, 0x92, 0xB3, 0xF7, 0x72, 0xA9,
+ 0xD2, 0x85, 0x9E, 0xF0, 0x03, 0x39, 0x8B, 0x1F,
+ 0x6B, 0xBA, 0xD7, 0xB5, 0x74, 0xF7, 0x98, 0x9A,
+ 0x1D, 0x10, 0xB2, 0xDF, 0x79, 0x8E, 0x0D, 0xBF,
+ 0x30, 0xD6, 0x58, 0x74, 0x64, 0xD2, 0x48, 0x78,
+ 0xCD, 0x00, 0xC0, 0xEA, 0xEE, 0x8A, 0x1A, 0x0C,
+ 0xC7, 0x53, 0xA2, 0x79, 0x79, 0xE1, 0x1B, 0x41,
+ 0xDB, 0x1D, 0xE3, 0xD5, 0x03, 0x8A, 0xFA, 0xF4,
+ 0x9F, 0x5C, 0x68, 0x2C, 0x37, 0x48, 0xD8, 0xA3,
+ 0xA9, 0xEC, 0x54, 0xE6, 0xA3, 0x71, 0x27, 0x5F,
+ 0x16, 0x83, 0x51, 0x0F, 0x8E, 0x4F, 0x90, 0x93,
+ 0x8F, 0x9A, 0xB6, 0xE1, 0x34, 0xC2, 0xCF, 0xDF,
+ 0x48, 0x41, 0xCB, 0xA8, 0x8E, 0x0C, 0xFF, 0x2B,
+ 0x0B, 0xCC, 0x8E, 0x6A, 0xDC, 0xB7, 0x11, 0x09,
+ 0xB5, 0x19, 0x8F, 0xEC, 0xF1, 0xBB, 0x7E, 0x5C,
+ 0x53, 0x1A, 0xCA, 0x50, 0xA5, 0x6A, 0x8A, 0x3B,
+ 0x6D, 0xE5, 0x98, 0x62, 0xD4, 0x1F, 0xA1, 0x13,
+ 0xD9, 0xCD, 0x95, 0x78, 0x08, 0xF0, 0x85, 0x71,
+ 0xD9, 0xA4, 0xBB, 0x79, 0x2A, 0xF2, 0x71, 0xF6,
+ 0xCC, 0x6D, 0xBB, 0x8D, 0xC7, 0xEC, 0x36, 0xE3,
+ 0x6B, 0xE1, 0xED, 0x30, 0x81, 0x64, 0xC3, 0x1C,
+ 0x7C, 0x0A, 0xFC, 0x54, 0x1C
+ },
+ .len = 5672
+ },
+ .validAuthLenInBits = {
+ .len = 5670
+ },
+ .digest = {
+ .data = {0x0C, 0xA1, 0x27, 0x92},
+ .len = 4
+ }
+};
+
+static struct wireless_test_data zuc_test_case_auth_128b = {
+ .key = {
+ .data = { 0x0 },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = { 0x0 },
+ .len = 16
+ },
+ .plaintext = {
+ .data = { 0x0 },
+ .len = 8
+ },
+ .validAuthLenInBits = {
+ .len = 8
+ },
+ .digest = {
+ .data = { 0x39, 0x0a, 0x91, 0xb7 },
+ .len = 4
+ }
+};
+
+static struct wireless_test_data zuc_test_case_auth_2080b = {
+ .key = {
+ .data = {
+ 0xC8, 0xA4, 0x82, 0x62, 0xD0, 0xC2, 0xE2, 0xBA,
+ 0xC4, 0xB9, 0x6E, 0xF7, 0x7E, 0x80, 0xCA, 0x59
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x05, 0x09, 0x78, 0x50, 0x80, 0x00, 0x00, 0x00,
+ 0x85, 0x09, 0x78, 0x50, 0x80, 0x00, 0x80, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0xB5, 0x46, 0x43, 0x0B, 0xF8, 0x7B, 0x4F, 0x1E,
+ 0xE8, 0x34, 0x70, 0x4C, 0xD6, 0x95, 0x1C, 0x36,
+ 0xE2, 0x6F, 0x10, 0x8C, 0xF7, 0x31, 0x78, 0x8F,
+ 0x48, 0xDC, 0x34, 0xF1, 0x67, 0x8C, 0x05, 0x22,
+ 0x1C, 0x8F, 0xA7, 0xFF, 0x2F, 0x39, 0xF4, 0x77,
+ 0xE7, 0xE4, 0x9E, 0xF6, 0x0A, 0x4E, 0xC2, 0xC3,
+ 0xDE, 0x24, 0x31, 0x2A, 0x96, 0xAA, 0x26, 0xE1,
+ 0xCF, 0xBA, 0x57, 0x56, 0x38, 0x38, 0xB2, 0x97,
+ 0xF4, 0x7E, 0x85, 0x10, 0xC7, 0x79, 0xFD, 0x66,
+ 0x54, 0xB1, 0x43, 0x38, 0x6F, 0xA6, 0x39, 0xD3,
+ 0x1E, 0xDB, 0xD6, 0xC0, 0x6E, 0x47, 0xD1, 0x59,
+ 0xD9, 0x43, 0x62, 0xF2, 0x6A, 0xEE, 0xED, 0xEE,
+ 0x0E, 0x4F, 0x49, 0xD9, 0xBF, 0x84, 0x12, 0x99,
+ 0x54, 0x15, 0xBF, 0xAD, 0x56, 0xEE, 0x82, 0xD1,
+ 0xCA, 0x74, 0x63, 0xAB, 0xF0, 0x85, 0xB0, 0x82,
+ 0xB0, 0x99, 0x04, 0xD6, 0xD9, 0x90, 0xD4, 0x3C,
+ 0xF2, 0xE0, 0x62, 0xF4, 0x08, 0x39, 0xD9, 0x32,
+ 0x48, 0xB1, 0xEB, 0x92, 0xCD, 0xFE, 0xD5, 0x30,
+ 0x0B, 0xC1, 0x48, 0x28, 0x04, 0x30, 0xB6, 0xD0,
+ 0xCA, 0xA0, 0x94, 0xB6, 0xEC, 0x89, 0x11, 0xAB,
+ 0x7D, 0xC3, 0x68, 0x24, 0xB8, 0x24, 0xDC, 0x0A,
+ 0xF6, 0x68, 0x2B, 0x09, 0x35, 0xFD, 0xE7, 0xB4,
+ 0x92, 0xA1, 0x4D, 0xC2, 0xF4, 0x36, 0x48, 0x03,
+ 0x8D, 0xA2, 0xCF, 0x79, 0x17, 0x0D, 0x2D, 0x50,
+ 0x13, 0x3F, 0xD4, 0x94, 0x16, 0xCB, 0x6E, 0x33,
+ 0xBE, 0xA9, 0x0B, 0x8B, 0xF4, 0x55, 0x9B, 0x03,
+ 0x73, 0x2A, 0x01, 0xEA, 0x29, 0x0E, 0x6D, 0x07,
+ 0x4F, 0x79, 0xBB, 0x83, 0xC1, 0x0E, 0x58, 0x00,
+ 0x15, 0xCC, 0x1A, 0x85, 0xB3, 0x6B, 0x55, 0x01,
+ 0x04, 0x6E, 0x9C, 0x4B, 0xDC, 0xAE, 0x51, 0x35,
+ 0x69, 0x0B, 0x86, 0x66, 0xBD, 0x54, 0xB7, 0xA7,
+ 0x03, 0xEA, 0x7B, 0x6F, 0x22, 0x0A, 0x54, 0x69,
+ 0xA5, 0x68, 0x02, 0x7E
+ },
+ .len = 2080
+ },
+ .validAuthLenInBits = {
+ .len = 2080
+ },
+ .digest = {
+ .data = {0x03, 0x95, 0x32, 0xe1},
+ .len = 4
+ }
+};
+
+static struct wireless_test_data zuc_test_case_auth_584b = {
+ .key = {
+ .data = {
+ 0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+ 0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0xa9, 0x40, 0x59, 0xda, 0x50, 0x0, 0x0, 0x0,
+ 0x29, 0x40, 0x59, 0xda, 0x50, 0x0, 0x80, 0x0
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+ 0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+ 0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+ 0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+ 0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+ 0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+ 0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+ 0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+ 0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+ 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 584
+ },
+ .validAuthLenInBits = {
+ .len = 584
+ },
+ .digest = {
+ .data = {0x24, 0xa8, 0x42, 0xb3},
+ .len = 4
+ }
+};
+
+struct wireless_test_data zuc_auth_cipher_test_case_1 = {
+ .key = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10
+ },
+ .len = 16
+ },
+ .cipher_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .auth_iv = {
+ .data = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ },
+ .len = 16
+ },
+ .plaintext = {
+ .data = {
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+ 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A
+ },
+ .len = 128 << 3
+ },
+ .ciphertext = {
+ .data = {
+ 0x5A, 0x5A, 0xDB, 0x3D, 0xD5, 0xB7, 0xB9, 0x58,
+ 0xA5, 0xD3, 0xE3, 0xF9, 0x18, 0x73, 0xB4, 0x74,
+ 0x05, 0xF0, 0xE9, 0xB6, 0x5D, 0x9A, 0xE3, 0xFA,
+ 0x5D, 0xFD, 0x24, 0x51, 0xAD, 0x73, 0xCA, 0x64,
+ 0x91, 0xD5, 0xB3, 0x94, 0x10, 0x91, 0x89, 0xEA,
+ 0x73, 0x6F, 0xB0, 0x2A, 0x0A, 0x63, 0x0F, 0x8D,
+ 0x64, 0x87, 0xA3, 0x14, 0x6B, 0x93, 0x31, 0x0F,
+ 0x14, 0xAD, 0xEA, 0x62, 0x80, 0x3F, 0x44, 0xDD,
+ 0x4E, 0x30, 0xFA, 0xC8, 0x0E, 0x5F, 0x46, 0xE7,
+ 0x60, 0xEC, 0xDF, 0x8B, 0x94, 0x7D, 0x2E, 0x63,
+ 0x48, 0xD9, 0x69, 0x06, 0x13, 0xF2, 0x20, 0x49,
+ 0x54, 0xA6, 0xD4, 0x98, 0xF4, 0xF6, 0x1D, 0x4A,
+ 0xC9, 0xA5, 0xDA, 0x46, 0x3D, 0xD9, 0x02, 0x47,
+ 0x1C, 0x20, 0x73, 0x35, 0x17, 0x1D, 0x81, 0x8D,
+ 0x2E, 0xCD, 0x70, 0x37, 0x22, 0x55, 0x3C, 0xF3,
+ 0xDA, 0x70, 0x42, 0x12, 0x0E, 0xAA, 0xC4, 0xAB
+ },
+ .len = 128 << 3
+ },
+ .validDataLenInBits = {
+ .len = 128 << 3
+ },
+ .validCipherLenInBits = {
+ .len = 126 << 3
+ },
+ .validAuthLenInBits = {
+ .len = 124 << 3
+ },
+ .validCipherOffsetInBits = {
+ .len = 2 << 3
+ },
+ .digest = {
+ .data = {0x0E, 0xAA, 0xC4, 0xAB},
+ .len = 4,
+ .offset_bytes = 124
+ }
+};
+
+#endif /* TEST_CRYPTODEV_ZUC_TEST_VECTORS_H_ */
diff --git a/src/spdk/dpdk/app/test/test_cycles.c b/src/spdk/dpdk/app/test/test_cycles.c
new file mode 100644
index 000000000..c78e6a5b1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_cycles.c
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+
+#include "test.h"
+
+#define N 10000
+
+/*
+ * Cycles test
+ * ===========
+ *
+ * - Loop N times and check that the timer always increments and
+ * never decrements during this loop.
+ *
+ * - Wait one second using rte_usleep() and check that the increment
+ * of cycles is correct with regard to the frequency of the timer.
+ */
+
+static int
+check_wait_one_second(void)
+{
+ uint64_t cycles, prev_cycles;
+ uint64_t hz = rte_get_timer_hz();
+ uint64_t max_inc = (hz / 100); /* 10 ms max between 2 reads */
+
+ /* check that waiting 1 second is precise */
+ prev_cycles = rte_get_timer_cycles();
+ rte_delay_us(1000000);
+ cycles = rte_get_timer_cycles();
+
+ if ((uint64_t)(cycles - prev_cycles) > (hz + max_inc)) {
+ printf("delay_us is not accurate: too long\n");
+ return -1;
+ }
+ if ((uint64_t)(cycles - prev_cycles) < (hz - max_inc)) {
+ printf("delay_us is not accurate: too short\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_cycles(void)
+{
+ unsigned i;
+ uint64_t start_cycles, cycles, prev_cycles;
+ uint64_t hz = rte_get_timer_hz();
+ uint64_t max_inc = (hz / 100); /* 10 ms max between 2 reads */
+
+ /* check that the timer is always incrementing */
+ start_cycles = rte_get_timer_cycles();
+ prev_cycles = start_cycles;
+ for (i=0; i<N; i++) {
+ cycles = rte_get_timer_cycles();
+ if ((uint64_t)(cycles - prev_cycles) > max_inc) {
+ printf("increment too high or going backwards\n");
+ return -1;
+ }
+ prev_cycles = cycles;
+ }
+
+ return check_wait_one_second();
+}
+
+REGISTER_TEST_COMMAND(cycles_autotest, test_cycles);
+
+/*
+ * One second precision test with rte_delay_us_sleep.
+ */
+
+static int
+test_delay_us_sleep(void)
+{
+ rte_delay_us_callback_register(rte_delay_us_sleep);
+ return check_wait_one_second();
+}
+
+REGISTER_TEST_COMMAND(delay_us_sleep_autotest, test_delay_us_sleep);
+
+/*
+ * rte_delay_us_callback test
+ *
+ * - check if callback is correctly registered/unregistered
+ *
+ */
+
+static unsigned int pattern;
+static void my_rte_delay_us(unsigned int us)
+{
+ pattern += us;
+}
+
+static int
+test_user_delay_us(void)
+{
+ pattern = 0;
+
+ rte_delay_us(2);
+ if (pattern != 0)
+ return -1;
+
+ /* register custom delay function */
+ rte_delay_us_callback_register(my_rte_delay_us);
+
+ rte_delay_us(2);
+ if (pattern != 2)
+ return -1;
+
+ rte_delay_us(3);
+ if (pattern != 5)
+ return -1;
+
+ /* restore original delay function */
+ rte_delay_us_callback_register(rte_delay_us_block);
+
+ rte_delay_us(3);
+ if (pattern != 5)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(user_delay_us, test_user_delay_us);
diff --git a/src/spdk/dpdk/app/test/test_debug.c b/src/spdk/dpdk/app/test/test_debug.c
new file mode 100644
index 000000000..25eab97e2
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_debug.c
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <rte_debug.h>
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_service_component.h>
+
+#include "test.h"
+
+/*
+ * Debug test
+ * ==========
+ */
+
+/* use fork() to test rte_panic() */
+static int
+test_panic(void)
+{
+ int pid;
+ int status;
+
+ pid = fork();
+
+ if (pid == 0)
+ rte_panic("Test Debug\n");
+ else if (pid < 0){
+ printf("Fork Failed\n");
+ return -1;
+ }
+ wait(&status);
+ if(status == 0){
+ printf("Child process terminated normally!\n");
+ return -1;
+ } else
+ printf("Child process terminated as expected - Test passed!\n");
+
+ return 0;
+}
+
+/* use fork() to test rte_exit() */
+static int
+test_exit_val(int exit_val)
+{
+ int pid;
+ int status;
+
+ /* manually cleanup EAL memory, as the fork() below would otherwise
+ * cause the same hugepages to be free()-ed multiple times.
+ */
+ rte_service_finalize();
+
+ pid = fork();
+
+ if (pid == 0)
+ rte_exit(exit_val, __func__);
+ else if (pid < 0){
+ printf("Fork Failed\n");
+ return -1;
+ }
+ wait(&status);
+ printf("Child process status: %d\n", status);
+#ifndef RTE_EAL_ALWAYS_PANIC_ON_ERROR
+ if(!WIFEXITED(status) || WEXITSTATUS(status) != (uint8_t)exit_val){
+ printf("Child process terminated with incorrect status (expected = %d)!\n",
+ exit_val);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static int
+test_exit(void)
+{
+ int test_vals[] = { 0, 1, 2, 255, -1 };
+ unsigned i;
+ for (i = 0; i < RTE_DIM(test_vals); i++) {
+ if (test_exit_val(test_vals[i]) < 0)
+ return -1;
+ }
+ printf("%s Passed\n", __func__);
+ return 0;
+}
+
+static void
+dummy_app_usage(const char *progname)
+{
+ RTE_SET_USED(progname);
+}
+
+static int
+test_usage(void)
+{
+ if (rte_set_application_usage_hook(dummy_app_usage) != NULL) {
+ printf("Non-NULL value returned for initial usage hook\n");
+ return -1;
+ }
+ if (rte_set_application_usage_hook(NULL) != dummy_app_usage) {
+ printf("Incorrect value returned for application usage hook\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_debug(void)
+{
+ rte_dump_stack();
+ rte_dump_registers();
+ if (test_panic() < 0)
+ return -1;
+ if (test_exit() < 0)
+ return -1;
+ if (test_usage() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(debug_autotest, test_debug);
diff --git a/src/spdk/dpdk/app/test/test_distributor.c b/src/spdk/dpdk/app/test/test_distributor.c
new file mode 100644
index 000000000..ba1f81cf8
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_distributor.c
@@ -0,0 +1,704 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include "test.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_distributor.h>
+#include <rte_string_fns.h>
+
+#define ITER_POWER 20 /* log 2 of how many iterations we do when timing. */
+#define BURST 32
+#define BIG_BATCH 1024
+
+struct worker_params {
+ char name[64];
+ struct rte_distributor *dist;
+};
+
+struct worker_params worker_params;
+
+/* statics - all zero-initialized by default */
+static volatile int quit; /**< general quit variable for all threads */
+static volatile int zero_quit; /**< var for when we just want thr0 to quit*/
+static volatile unsigned worker_idx;
+
+struct worker_stats {
+ volatile unsigned handled_packets;
+} __rte_cache_aligned;
+struct worker_stats worker_stats[RTE_MAX_LCORE];
+
+/* returns the total count of the number of packets handled by the worker
+ * functions given below.
+ */
+static inline unsigned
+total_packet_count(void)
+{
+ unsigned i, count = 0;
+ for (i = 0; i < worker_idx; i++)
+ count += worker_stats[i].handled_packets;
+ return count;
+}
+
+/* resets the packet counts for a new test */
+static inline void
+clear_packet_count(void)
+{
+ memset(&worker_stats, 0, sizeof(worker_stats));
+}
+
+/* this is the basic worker function for sanity test
+ * it does nothing but return packets and count them.
+ */
+static int
+handle_work(void *arg)
+{
+ struct rte_mbuf *buf[8] __rte_cache_aligned;
+ struct worker_params *wp = arg;
+ struct rte_distributor *db = wp->dist;
+ unsigned int count = 0, num = 0;
+ unsigned int id = __atomic_fetch_add(&worker_idx, 1, __ATOMIC_RELAXED);
+ int i;
+
+ for (i = 0; i < 8; i++)
+ buf[i] = NULL;
+ num = rte_distributor_get_pkt(db, id, buf, buf, num);
+ while (!quit) {
+ __atomic_fetch_add(&worker_stats[id].handled_packets, num,
+ __ATOMIC_RELAXED);
+ count += num;
+ num = rte_distributor_get_pkt(db, id,
+ buf, buf, num);
+ }
+ __atomic_fetch_add(&worker_stats[id].handled_packets, num,
+ __ATOMIC_RELAXED);
+ count += num;
+ rte_distributor_return_pkt(db, id, buf, num);
+ return 0;
+}
+
+/* do basic sanity testing of the distributor. This test tests the following:
+ * - send 32 packets through distributor with the same tag and ensure they
+ * all go to the one worker
+ * - send 32 packets through the distributor with two different tags and
+ * verify that they go equally to two different workers.
+ * - send 32 packets with different tags through the distributors and
+ * just verify we get all packets back.
+ * - send 1024 packets through the distributor, gathering the returned packets
+ * as we go. Then verify that we correctly got all 1024 pointers back again,
+ * not necessarily in the same order (as different flows).
+ */
+static int
+sanity_test(struct worker_params *wp, struct rte_mempool *p)
+{
+ struct rte_distributor *db = wp->dist;
+ struct rte_mbuf *bufs[BURST];
+ struct rte_mbuf *returns[BURST*2];
+ unsigned int i, count;
+ unsigned int retries;
+
+ printf("=== Basic distributor sanity tests ===\n");
+ clear_packet_count();
+ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
+
+ /* now set all hash values in all buffers to zero, so all pkts go to the
+ * one worker thread */
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = 0;
+
+ rte_distributor_process(db, bufs, BURST);
+ count = 0;
+ do {
+
+ rte_distributor_flush(db);
+ count += rte_distributor_returned_pkts(db,
+ returns, BURST*2);
+ } while (count < BURST);
+
+ if (total_packet_count() != BURST) {
+ printf("Line %d: Error, not all packets flushed. "
+ "Expected %u, got %u\n",
+ __LINE__, BURST, total_packet_count());
+ return -1;
+ }
+
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+ printf("Sanity test with all zero hashes done.\n");
+
+ /* pick two flows and check they go correctly */
+ if (rte_lcore_count() >= 3) {
+ clear_packet_count();
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = (i & 1) << 8;
+
+ rte_distributor_process(db, bufs, BURST);
+ count = 0;
+ do {
+ rte_distributor_flush(db);
+ count += rte_distributor_returned_pkts(db,
+ returns, BURST*2);
+ } while (count < BURST);
+ if (total_packet_count() != BURST) {
+ printf("Line %d: Error, not all packets flushed. "
+ "Expected %u, got %u\n",
+ __LINE__, BURST, total_packet_count());
+ return -1;
+ }
+
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+ printf("Sanity test with two hash values done\n");
+ }
+
+ /* give a different hash value to each packet,
+ * so load gets distributed */
+ clear_packet_count();
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = i+1;
+
+ rte_distributor_process(db, bufs, BURST);
+ count = 0;
+ do {
+ rte_distributor_flush(db);
+ count += rte_distributor_returned_pkts(db,
+ returns, BURST*2);
+ } while (count < BURST);
+ if (total_packet_count() != BURST) {
+ printf("Line %d: Error, not all packets flushed. "
+ "Expected %u, got %u\n",
+ __LINE__, BURST, total_packet_count());
+ return -1;
+ }
+
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+ printf("Sanity test with non-zero hashes done\n");
+
+ rte_mempool_put_bulk(p, (void *)bufs, BURST);
+
+ /* sanity test with BIG_BATCH packets to ensure they all arrived back
+ * from the returned packets function */
+ clear_packet_count();
+ struct rte_mbuf *many_bufs[BIG_BATCH], *return_bufs[BIG_BATCH];
+ unsigned num_returned = 0;
+
+ /* flush out any remaining packets */
+ rte_distributor_flush(db);
+ rte_distributor_clear_returns(db);
+
+ if (rte_mempool_get_bulk(p, (void *)many_bufs, BIG_BATCH) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
+ for (i = 0; i < BIG_BATCH; i++)
+ many_bufs[i]->hash.usr = i << 2;
+
+ printf("=== testing big burst (%s) ===\n", wp->name);
+ for (i = 0; i < BIG_BATCH/BURST; i++) {
+ rte_distributor_process(db,
+ &many_bufs[i*BURST], BURST);
+ count = rte_distributor_returned_pkts(db,
+ &return_bufs[num_returned],
+ BIG_BATCH - num_returned);
+ num_returned += count;
+ }
+ rte_distributor_flush(db);
+ count = rte_distributor_returned_pkts(db,
+ &return_bufs[num_returned],
+ BIG_BATCH - num_returned);
+ num_returned += count;
+ retries = 0;
+ do {
+ rte_distributor_flush(db);
+ count = rte_distributor_returned_pkts(db,
+ &return_bufs[num_returned],
+ BIG_BATCH - num_returned);
+ num_returned += count;
+ retries++;
+ } while ((num_returned < BIG_BATCH) && (retries < 100));
+
+ if (num_returned != BIG_BATCH) {
+ printf("line %d: Missing packets, expected %d\n",
+ __LINE__, num_returned);
+ return -1;
+ }
+
+ /* big check - make sure all packets made it back!! */
+ for (i = 0; i < BIG_BATCH; i++) {
+ unsigned j;
+ struct rte_mbuf *src = many_bufs[i];
+ for (j = 0; j < BIG_BATCH; j++) {
+ if (return_bufs[j] == src)
+ break;
+ }
+
+ if (j == BIG_BATCH) {
+ printf("Error: could not find source packet #%u\n", i);
+ return -1;
+ }
+ }
+ printf("Sanity test of returned packets done\n");
+
+ rte_mempool_put_bulk(p, (void *)many_bufs, BIG_BATCH);
+
+ printf("\n");
+ return 0;
+}
+
+
+/* to test that the distributor does not lose packets, we use this worker
+ * function which frees mbufs when it gets them. The distributor thread does
+ * the mbuf allocation. If distributor drops packets we'll eventually run out
+ * of mbufs.
+ */
+static int
+handle_work_with_free_mbufs(void *arg)
+{
+ struct rte_mbuf *buf[8] __rte_cache_aligned;
+ struct worker_params *wp = arg;
+ struct rte_distributor *d = wp->dist;
+ unsigned int count = 0;
+ unsigned int i;
+ unsigned int num = 0;
+ unsigned int id = __atomic_fetch_add(&worker_idx, 1, __ATOMIC_RELAXED);
+
+ for (i = 0; i < 8; i++)
+ buf[i] = NULL;
+ num = rte_distributor_get_pkt(d, id, buf, buf, num);
+ while (!quit) {
+ worker_stats[id].handled_packets += num;
+ count += num;
+ for (i = 0; i < num; i++)
+ rte_pktmbuf_free(buf[i]);
+ num = rte_distributor_get_pkt(d,
+ id, buf, buf, num);
+ }
+ worker_stats[id].handled_packets += num;
+ count += num;
+ rte_distributor_return_pkt(d, id, buf, num);
+ return 0;
+}
+
+/* Perform a sanity test of the distributor with a large number of packets,
+ * where we allocate a new set of mbufs for each burst. The workers then
+ * free the mbufs. This ensures that we don't have any packet leaks in the
+ * library.
+ */
+static int
+sanity_test_with_mbuf_alloc(struct worker_params *wp, struct rte_mempool *p)
+{
+ struct rte_distributor *d = wp->dist;
+ unsigned i;
+ struct rte_mbuf *bufs[BURST];
+
+ printf("=== Sanity test with mbuf alloc/free (%s) ===\n", wp->name);
+
+ clear_packet_count();
+ for (i = 0; i < ((1<<ITER_POWER)); i += BURST) {
+ unsigned j;
+ while (rte_mempool_get_bulk(p, (void *)bufs, BURST) < 0)
+ rte_distributor_process(d, NULL, 0);
+ for (j = 0; j < BURST; j++) {
+ bufs[j]->hash.usr = (i+j) << 1;
+ rte_mbuf_refcnt_set(bufs[j], 1);
+ }
+
+ rte_distributor_process(d, bufs, BURST);
+ }
+
+ rte_distributor_flush(d);
+
+ rte_delay_us(10000);
+
+ if (total_packet_count() < (1<<ITER_POWER)) {
+ printf("Line %u: Packet count is incorrect, %u, expected %u\n",
+ __LINE__, total_packet_count(),
+ (1<<ITER_POWER));
+ return -1;
+ }
+
+ printf("Sanity test with mbuf alloc/free passed\n\n");
+ return 0;
+}
+
+static int
+handle_work_for_shutdown_test(void *arg)
+{
+ struct rte_mbuf *pkt = NULL;
+ struct rte_mbuf *buf[8] __rte_cache_aligned;
+ struct worker_params *wp = arg;
+ struct rte_distributor *d = wp->dist;
+ unsigned int count = 0;
+ unsigned int num = 0;
+ unsigned int total = 0;
+ unsigned int i;
+ unsigned int returned = 0;
+ const unsigned int id = __atomic_fetch_add(&worker_idx, 1,
+ __ATOMIC_RELAXED);
+
+ num = rte_distributor_get_pkt(d, id, buf, buf, num);
+
+ /* wait for quit single globally, or for worker zero, wait
+ * for zero_quit */
+ while (!quit && !(id == 0 && zero_quit)) {
+ worker_stats[id].handled_packets += num;
+ count += num;
+ for (i = 0; i < num; i++)
+ rte_pktmbuf_free(buf[i]);
+ num = rte_distributor_get_pkt(d,
+ id, buf, buf, num);
+ total += num;
+ }
+ worker_stats[id].handled_packets += num;
+ count += num;
+ returned = rte_distributor_return_pkt(d, id, buf, num);
+
+ if (id == 0) {
+ /* for worker zero, allow it to restart to pick up last packet
+ * when all workers are shutting down.
+ */
+ while (zero_quit)
+ usleep(100);
+
+ num = rte_distributor_get_pkt(d,
+ id, buf, buf, num);
+
+ while (!quit) {
+ worker_stats[id].handled_packets += num;
+ count += num;
+ rte_pktmbuf_free(pkt);
+ num = rte_distributor_get_pkt(d, id, buf, buf, num);
+ }
+ returned = rte_distributor_return_pkt(d,
+ id, buf, num);
+ printf("Num returned = %d\n", returned);
+ }
+ return 0;
+}
+
+
+/* Perform a sanity test of the distributor with a large number of packets,
+ * where we allocate a new set of mbufs for each burst. The workers then
+ * free the mbufs. This ensures that we don't have any packet leaks in the
+ * library.
+ */
+static int
+sanity_test_with_worker_shutdown(struct worker_params *wp,
+ struct rte_mempool *p)
+{
+ struct rte_distributor *d = wp->dist;
+ struct rte_mbuf *bufs[BURST];
+ unsigned i;
+
+ printf("=== Sanity test of worker shutdown ===\n");
+
+ clear_packet_count();
+
+ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
+
+ /*
+ * Now set all hash values in all buffers to same value so all
+ * pkts go to the one worker thread
+ */
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = 1;
+
+ rte_distributor_process(d, bufs, BURST);
+ rte_distributor_flush(d);
+
+ /* at this point, we will have processed some packets and have a full
+ * backlog for the other ones at worker 0.
+ */
+
+ /* get more buffers to queue up, again setting them to the same flow */
+ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = 1;
+
+ /* get worker zero to quit */
+ zero_quit = 1;
+ rte_distributor_process(d, bufs, BURST);
+
+ /* flush the distributor */
+ rte_distributor_flush(d);
+ rte_delay_us(10000);
+
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+
+ if (total_packet_count() != BURST * 2) {
+ printf("Line %d: Error, not all packets flushed. "
+ "Expected %u, got %u\n",
+ __LINE__, BURST * 2, total_packet_count());
+ return -1;
+ }
+
+ printf("Sanity test with worker shutdown passed\n\n");
+ return 0;
+}
+
+/* Test that the flush function is able to move packets between workers when
+ * one worker shuts down..
+ */
+static int
+test_flush_with_worker_shutdown(struct worker_params *wp,
+ struct rte_mempool *p)
+{
+ struct rte_distributor *d = wp->dist;
+ struct rte_mbuf *bufs[BURST];
+ unsigned i;
+
+ printf("=== Test flush fn with worker shutdown (%s) ===\n", wp->name);
+
+ clear_packet_count();
+ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+ printf("line %d: Error getting mbufs from pool\n", __LINE__);
+ return -1;
+ }
+
+ /* now set all hash values in all buffers to zero, so all pkts go to the
+ * one worker thread */
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = 0;
+
+ rte_distributor_process(d, bufs, BURST);
+ /* at this point, we will have processed some packets and have a full
+ * backlog for the other ones at worker 0.
+ */
+
+ /* get worker zero to quit */
+ zero_quit = 1;
+
+ /* flush the distributor */
+ rte_distributor_flush(d);
+
+ rte_delay_us(10000);
+
+ zero_quit = 0;
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+
+ if (total_packet_count() != BURST) {
+ printf("Line %d: Error, not all packets flushed. "
+ "Expected %u, got %u\n",
+ __LINE__, BURST, total_packet_count());
+ return -1;
+ }
+
+ printf("Flush test with worker shutdown passed\n\n");
+ return 0;
+}
+
+static
+int test_error_distributor_create_name(void)
+{
+ struct rte_distributor *d = NULL;
+ struct rte_distributor *db = NULL;
+ char *name = NULL;
+
+ d = rte_distributor_create(name, rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_SINGLE);
+ if (d != NULL || rte_errno != EINVAL) {
+ printf("ERROR: No error on create() with NULL name param\n");
+ return -1;
+ }
+
+ db = rte_distributor_create(name, rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_BURST);
+ if (db != NULL || rte_errno != EINVAL) {
+ printf("ERROR: No error on create() with NULL param\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static
+int test_error_distributor_create_numworkers(void)
+{
+ struct rte_distributor *ds = NULL;
+ struct rte_distributor *db = NULL;
+
+ ds = rte_distributor_create("test_numworkers", rte_socket_id(),
+ RTE_MAX_LCORE + 10,
+ RTE_DIST_ALG_SINGLE);
+ if (ds != NULL || rte_errno != EINVAL) {
+ printf("ERROR: No error on create() with num_workers > MAX\n");
+ return -1;
+ }
+
+ db = rte_distributor_create("test_numworkers", rte_socket_id(),
+ RTE_MAX_LCORE + 10,
+ RTE_DIST_ALG_BURST);
+ if (db != NULL || rte_errno != EINVAL) {
+ printf("ERROR: No error on create() num_workers > MAX\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Useful function which ensures that all worker functions terminate */
+static void
+quit_workers(struct worker_params *wp, struct rte_mempool *p)
+{
+ struct rte_distributor *d = wp->dist;
+ const unsigned num_workers = rte_lcore_count() - 1;
+ unsigned i;
+ struct rte_mbuf *bufs[RTE_MAX_LCORE];
+ rte_mempool_get_bulk(p, (void *)bufs, num_workers);
+
+ zero_quit = 0;
+ quit = 1;
+ for (i = 0; i < num_workers; i++)
+ bufs[i]->hash.usr = i << 1;
+ rte_distributor_process(d, bufs, num_workers);
+
+ rte_mempool_put_bulk(p, (void *)bufs, num_workers);
+
+ rte_distributor_process(d, NULL, 0);
+ rte_distributor_flush(d);
+ rte_eal_mp_wait_lcore();
+ quit = 0;
+ worker_idx = 0;
+}
+
+static int
+test_distributor(void)
+{
+ static struct rte_distributor *ds;
+ static struct rte_distributor *db;
+ static struct rte_distributor *dist[2];
+ static struct rte_mempool *p;
+ int i;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for distributor_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ if (db == NULL) {
+ db = rte_distributor_create("Test_dist_burst", rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_BURST);
+ if (db == NULL) {
+ printf("Error creating burst distributor\n");
+ return -1;
+ }
+ } else {
+ rte_distributor_flush(db);
+ rte_distributor_clear_returns(db);
+ }
+
+ if (ds == NULL) {
+ ds = rte_distributor_create("Test_dist_single",
+ rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_SINGLE);
+ if (ds == NULL) {
+ printf("Error creating single distributor\n");
+ return -1;
+ }
+ } else {
+ rte_distributor_flush(ds);
+ rte_distributor_clear_returns(ds);
+ }
+
+ const unsigned nb_bufs = (511 * rte_lcore_count()) < BIG_BATCH ?
+ (BIG_BATCH * 2) - 1 : (511 * rte_lcore_count());
+ if (p == NULL) {
+ p = rte_pktmbuf_pool_create("DT_MBUF_POOL", nb_bufs, BURST,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ if (p == NULL) {
+ printf("Error creating mempool\n");
+ return -1;
+ }
+ }
+
+ dist[0] = ds;
+ dist[1] = db;
+
+ for (i = 0; i < 2; i++) {
+
+ worker_params.dist = dist[i];
+ if (i)
+ strlcpy(worker_params.name, "burst",
+ sizeof(worker_params.name));
+ else
+ strlcpy(worker_params.name, "single",
+ sizeof(worker_params.name));
+
+ rte_eal_mp_remote_launch(handle_work,
+ &worker_params, SKIP_MASTER);
+ if (sanity_test(&worker_params, p) < 0)
+ goto err;
+ quit_workers(&worker_params, p);
+
+ rte_eal_mp_remote_launch(handle_work_with_free_mbufs,
+ &worker_params, SKIP_MASTER);
+ if (sanity_test_with_mbuf_alloc(&worker_params, p) < 0)
+ goto err;
+ quit_workers(&worker_params, p);
+
+ if (rte_lcore_count() > 2) {
+ rte_eal_mp_remote_launch(handle_work_for_shutdown_test,
+ &worker_params,
+ SKIP_MASTER);
+ if (sanity_test_with_worker_shutdown(&worker_params,
+ p) < 0)
+ goto err;
+ quit_workers(&worker_params, p);
+
+ rte_eal_mp_remote_launch(handle_work_for_shutdown_test,
+ &worker_params,
+ SKIP_MASTER);
+ if (test_flush_with_worker_shutdown(&worker_params,
+ p) < 0)
+ goto err;
+ quit_workers(&worker_params, p);
+
+ } else {
+ printf("Too few cores to run worker shutdown test\n");
+ }
+
+ }
+
+ if (test_error_distributor_create_numworkers() == -1 ||
+ test_error_distributor_create_name() == -1) {
+ printf("rte_distributor_create parameter check tests failed");
+ return -1;
+ }
+
+ return 0;
+
+err:
+ quit_workers(&worker_params, p);
+ return -1;
+}
+
+REGISTER_TEST_COMMAND(distributor_autotest, test_distributor);
diff --git a/src/spdk/dpdk/app/test/test_distributor_perf.c b/src/spdk/dpdk/app/test/test_distributor_perf.c
new file mode 100644
index 000000000..f153bcf9b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_distributor_perf.c
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include "test.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <rte_mempool.h>
+#include <rte_cycles.h>
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_distributor.h>
+#include <rte_pause.h>
+
+#define ITER_POWER_CL 25 /* log 2 of how many iterations for Cache Line test */
+#define ITER_POWER 21 /* log 2 of how many iterations we do when timing. */
+#define BURST 64
+#define BIG_BATCH 1024
+
+/* static vars - zero initialized by default */
+static volatile int quit;
+static volatile unsigned worker_idx;
+
+struct worker_stats {
+ volatile unsigned handled_packets;
+} __rte_cache_aligned;
+static struct worker_stats worker_stats[RTE_MAX_LCORE];
+
+/*
+ * worker thread used for testing the time to do a round-trip of a cache
+ * line between two cores and back again
+ */
+static int
+flip_bit(volatile uint64_t *arg)
+{
+ uint64_t old_val = 0;
+ while (old_val != 2) {
+ while (!*arg)
+ rte_pause();
+ old_val = *arg;
+ *arg = 0;
+ }
+ return 0;
+}
+
+/*
+ * test case to time the number of cycles to round-trip a cache line between
+ * two cores and back again.
+ */
+static void
+time_cache_line_switch(void)
+{
+ /* allocate a full cache line for data, we use only first byte of it */
+ uint64_t data[RTE_CACHE_LINE_SIZE*3 / sizeof(uint64_t)];
+
+ unsigned i, slaveid = rte_get_next_lcore(rte_lcore_id(), 0, 0);
+ volatile uint64_t *pdata = &data[0];
+ *pdata = 1;
+ rte_eal_remote_launch((lcore_function_t *)flip_bit, &data[0], slaveid);
+ while (*pdata)
+ rte_pause();
+
+ const uint64_t start_time = rte_rdtsc();
+ for (i = 0; i < (1 << ITER_POWER_CL); i++) {
+ while (*pdata)
+ rte_pause();
+ *pdata = 1;
+ }
+ const uint64_t end_time = rte_rdtsc();
+
+ while (*pdata)
+ rte_pause();
+ *pdata = 2;
+ rte_eal_wait_lcore(slaveid);
+ printf("==== Cache line switch test ===\n");
+ printf("Time for %u iterations = %"PRIu64" ticks\n", (1<<ITER_POWER_CL),
+ end_time-start_time);
+ printf("Ticks per iteration = %"PRIu64"\n\n",
+ (end_time-start_time) >> ITER_POWER_CL);
+}
+
+/*
+ * returns the total count of the number of packets handled by the worker
+ * functions given below.
+ */
+static unsigned
+total_packet_count(void)
+{
+ unsigned i, count = 0;
+ for (i = 0; i < worker_idx; i++)
+ count += worker_stats[i].handled_packets;
+ return count;
+}
+
+/* resets the packet counts for a new test */
+static void
+clear_packet_count(void)
+{
+ memset(&worker_stats, 0, sizeof(worker_stats));
+}
+
+/*
+ * This is the basic worker function for performance tests.
+ * it does nothing but return packets and count them.
+ */
+static int
+handle_work(void *arg)
+{
+ struct rte_distributor *d = arg;
+ unsigned int count = 0;
+ unsigned int num = 0;
+ int i;
+ unsigned int id = __atomic_fetch_add(&worker_idx, 1, __ATOMIC_RELAXED);
+ struct rte_mbuf *buf[8] __rte_cache_aligned;
+
+ for (i = 0; i < 8; i++)
+ buf[i] = NULL;
+
+ num = rte_distributor_get_pkt(d, id, buf, buf, num);
+ while (!quit) {
+ worker_stats[id].handled_packets += num;
+ count += num;
+ num = rte_distributor_get_pkt(d, id, buf, buf, num);
+ }
+ worker_stats[id].handled_packets += num;
+ count += num;
+ rte_distributor_return_pkt(d, id, buf, num);
+ return 0;
+}
+
+/*
+ * This basic performance test just repeatedly sends in 32 packets at a time
+ * to the distributor and verifies at the end that we got them all in the worker
+ * threads and finally how long per packet the processing took.
+ */
+static inline int
+perf_test(struct rte_distributor *d, struct rte_mempool *p)
+{
+ unsigned int i;
+ uint64_t start, end;
+ struct rte_mbuf *bufs[BURST];
+
+ clear_packet_count();
+ if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+ printf("Error getting mbufs from pool\n");
+ return -1;
+ }
+ /* ensure we have different hash value for each pkt */
+ for (i = 0; i < BURST; i++)
+ bufs[i]->hash.usr = i;
+
+ start = rte_rdtsc();
+ for (i = 0; i < (1<<ITER_POWER); i++)
+ rte_distributor_process(d, bufs, BURST);
+ end = rte_rdtsc();
+
+ do {
+ usleep(100);
+ rte_distributor_process(d, NULL, 0);
+ } while (total_packet_count() < (BURST << ITER_POWER));
+
+ rte_distributor_clear_returns(d);
+
+ printf("Time per burst: %"PRIu64"\n", (end - start) >> ITER_POWER);
+ printf("Time per packet: %"PRIu64"\n\n",
+ ((end - start) >> ITER_POWER)/BURST);
+ rte_mempool_put_bulk(p, (void *)bufs, BURST);
+
+ for (i = 0; i < rte_lcore_count() - 1; i++)
+ printf("Worker %u handled %u packets\n", i,
+ worker_stats[i].handled_packets);
+ printf("Total packets: %u (%x)\n", total_packet_count(),
+ total_packet_count());
+ printf("=== Perf test done ===\n\n");
+
+ return 0;
+}
+
+/* Useful function which ensures that all worker functions terminate */
+static void
+quit_workers(struct rte_distributor *d, struct rte_mempool *p)
+{
+ const unsigned int num_workers = rte_lcore_count() - 1;
+ unsigned int i;
+ struct rte_mbuf *bufs[RTE_MAX_LCORE];
+
+ rte_mempool_get_bulk(p, (void *)bufs, num_workers);
+
+ quit = 1;
+ for (i = 0; i < num_workers; i++)
+ bufs[i]->hash.usr = i << 1;
+ rte_distributor_process(d, bufs, num_workers);
+
+ rte_mempool_put_bulk(p, (void *)bufs, num_workers);
+
+ rte_distributor_process(d, NULL, 0);
+ rte_eal_mp_wait_lcore();
+ quit = 0;
+ worker_idx = 0;
+}
+
+static int
+test_distributor_perf(void)
+{
+ static struct rte_distributor *ds;
+ static struct rte_distributor *db;
+ static struct rte_mempool *p;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for distributor_perf_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ /* first time how long it takes to round-trip a cache line */
+ time_cache_line_switch();
+
+ if (ds == NULL) {
+ ds = rte_distributor_create("Test_perf", rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_SINGLE);
+ if (ds == NULL) {
+ printf("Error creating distributor\n");
+ return -1;
+ }
+ } else {
+ rte_distributor_clear_returns(ds);
+ }
+
+ if (db == NULL) {
+ db = rte_distributor_create("Test_burst", rte_socket_id(),
+ rte_lcore_count() - 1,
+ RTE_DIST_ALG_BURST);
+ if (db == NULL) {
+ printf("Error creating burst distributor\n");
+ return -1;
+ }
+ } else {
+ rte_distributor_clear_returns(db);
+ }
+
+ const unsigned nb_bufs = (511 * rte_lcore_count()) < BIG_BATCH ?
+ (BIG_BATCH * 2) - 1 : (511 * rte_lcore_count());
+ if (p == NULL) {
+ p = rte_pktmbuf_pool_create("DPT_MBUF_POOL", nb_bufs, BURST,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ if (p == NULL) {
+ printf("Error creating mempool\n");
+ return -1;
+ }
+ }
+
+ printf("=== Performance test of distributor (single mode) ===\n");
+ rte_eal_mp_remote_launch(handle_work, ds, SKIP_MASTER);
+ if (perf_test(ds, p) < 0)
+ return -1;
+ quit_workers(ds, p);
+
+ printf("=== Performance test of distributor (burst mode) ===\n");
+ rte_eal_mp_remote_launch(handle_work, db, SKIP_MASTER);
+ if (perf_test(db, p) < 0)
+ return -1;
+ quit_workers(db, p);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(distributor_perf_autotest, test_distributor_perf);
diff --git a/src/spdk/dpdk/app/test/test_eal_flags.c b/src/spdk/dpdk/app/test/test_eal_flags.c
new file mode 100644
index 000000000..4ee809e3d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_eal_flags.c
@@ -0,0 +1,1552 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ */
+
+#include <stdio.h>
+
+#include "test.h"
+
+#include <string.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <limits.h>
+#include <fcntl.h>
+
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_string_fns.h>
+
+#include "process.h"
+
+#define DEFAULT_MEM_SIZE "18"
+#define mp_flag "--proc-type=secondary"
+#define no_hpet "--no-hpet"
+#define no_huge "--no-huge"
+#define no_shconf "--no-shconf"
+#define pci_whitelist "--pci-whitelist"
+#define vdev "--vdev"
+#define memtest "memtest"
+#define memtest1 "memtest1"
+#define memtest2 "memtest2"
+#define SOCKET_MEM_STRLEN (RTE_MAX_NUMA_NODES * 20)
+#define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
+
+enum hugepage_action {
+ HUGEPAGE_CHECK_EXISTS = 0,
+ HUGEPAGE_CHECK_LOCKED,
+ HUGEPAGE_DELETE,
+ HUGEPAGE_INVALID
+};
+
+/* if string contains a hugepage path */
+static int
+get_hugepage_path(char * src, int src_len, char * dst, int dst_len)
+{
+#define NUM_TOKENS 4
+ char *tokens[NUM_TOKENS];
+
+ /* if we couldn't properly split the string */
+ if (rte_strsplit(src, src_len, tokens, NUM_TOKENS, ' ') < NUM_TOKENS)
+ return 0;
+
+ if (strncmp(tokens[2], "hugetlbfs", sizeof("hugetlbfs")) == 0) {
+ strlcpy(dst, tokens[1], dst_len);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Cycles through hugepage directories and looks for hugepage
+ * files associated with a given prefix. Depending on value of
+ * action, the hugepages are checked if they exist, checked if
+ * they can be locked, or are simply deleted.
+ *
+ * Returns 1 if it finds at least one hugepage matching the action
+ * Returns 0 if no matching hugepages were found
+ * Returns -1 if it encounters an error
+ */
+static int
+process_hugefiles(const char * prefix, enum hugepage_action action)
+{
+ FILE * hugedir_handle = NULL;
+ DIR * hugepage_dir = NULL;
+ struct dirent *dirent = NULL;
+
+ char hugefile_prefix[PATH_MAX] = {0};
+ char hugedir[PATH_MAX] = {0};
+ char line[PATH_MAX] = {0};
+
+ int fd, lck_result, result = 0;
+
+ const int prefix_len = snprintf(hugefile_prefix,
+ sizeof(hugefile_prefix), "%smap_", prefix);
+ if (prefix_len <= 0 || prefix_len >= (int)sizeof(hugefile_prefix)
+ || prefix_len >= (int)sizeof(dirent->d_name)) {
+ printf("Error creating hugefile filename prefix\n");
+ return -1;
+ }
+
+ /* get hugetlbfs mountpoints from /proc/mounts */
+ hugedir_handle = fopen("/proc/mounts", "r");
+
+ if (hugedir_handle == NULL) {
+ printf("Error parsing /proc/mounts!\n");
+ return -1;
+ }
+
+ /* read and parse script output */
+ while (fgets(line, sizeof(line), hugedir_handle) != NULL) {
+
+ /* check if we have a hugepage filesystem path */
+ if (!get_hugepage_path(line, sizeof(line), hugedir, sizeof(hugedir)))
+ continue;
+
+ /* check if directory exists */
+ if ((hugepage_dir = opendir(hugedir)) == NULL) {
+ fclose(hugedir_handle);
+ printf("Error reading %s: %s\n", hugedir, strerror(errno));
+ return -1;
+ }
+
+ while ((dirent = readdir(hugepage_dir)) != NULL) {
+ if (memcmp(dirent->d_name, hugefile_prefix, prefix_len) != 0)
+ continue;
+
+ switch (action) {
+ case HUGEPAGE_CHECK_EXISTS:
+ {
+ /* file exists, return */
+ result = 1;
+ goto end;
+ }
+ break;
+ case HUGEPAGE_DELETE:
+ {
+ char file_path[PATH_MAX] = {0};
+
+ snprintf(file_path, sizeof(file_path),
+ "%s/%s", hugedir, dirent->d_name);
+
+ /* remove file */
+ if (remove(file_path) < 0) {
+ printf("Error deleting %s - %s!\n",
+ dirent->d_name, strerror(errno));
+ closedir(hugepage_dir);
+ result = -1;
+ goto end;
+ }
+ result = 1;
+ }
+ break;
+ case HUGEPAGE_CHECK_LOCKED:
+ {
+ /* try and lock the file */
+ fd = openat(dirfd(hugepage_dir), dirent->d_name, O_RDONLY);
+
+ /* this shouldn't happen */
+ if (fd == -1) {
+ printf("Error opening %s - %s!\n",
+ dirent->d_name, strerror(errno));
+ closedir(hugepage_dir);
+ result = -1;
+ goto end;
+ }
+
+ /* non-blocking lock */
+ lck_result = flock(fd, LOCK_EX | LOCK_NB);
+
+ /* if lock succeeds, there's something wrong */
+ if (lck_result != -1) {
+ result = 0;
+
+ /* unlock the resulting lock */
+ flock(fd, LOCK_UN);
+ close(fd);
+ closedir(hugepage_dir);
+ goto end;
+ }
+ result = 1;
+ close(fd);
+ }
+ break;
+ /* shouldn't happen */
+ default:
+ goto end;
+ } /* switch */
+
+ } /* read hugepage directory */
+ closedir(hugepage_dir);
+ } /* read /proc/mounts */
+end:
+ fclose(hugedir_handle);
+ return result;
+}
+
+#ifdef RTE_EXEC_ENV_LINUX
+/*
+ * count the number of "node*" files in /sys/devices/system/node/
+ */
+static int
+get_number_of_sockets(void)
+{
+ struct dirent *dirent = NULL;
+ const char * nodedir = "/sys/devices/system/node/";
+ DIR * dir = NULL;
+ int result = 0;
+
+ /* check if directory exists */
+ if ((dir = opendir(nodedir)) == NULL) {
+ /* if errno==ENOENT this means we don't have NUMA support */
+ if (errno == ENOENT) {
+ printf("No NUMA nodes detected: assuming 1 available socket\n");
+ return 1;
+ }
+ printf("Error opening %s: %s\n", nodedir, strerror(errno));
+ return -1;
+ }
+
+ while ((dirent = readdir(dir)) != NULL)
+ if (strncmp(dirent->d_name, "node", sizeof("node") - 1) == 0)
+ result++;
+
+ closedir(dir);
+ return result;
+}
+#endif
+
+/*
+ * Test that the app doesn't run with invalid whitelist option.
+ * Final tests ensures it does run with valid options as sanity check (one
+ * test for with Domain+BDF, second for just with BDF)
+ */
+static int
+test_whitelist_flag(void)
+{
+ unsigned i;
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ const char *wlinval[][7] = {
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "error", "", ""},
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "0:0:0", "", ""},
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "0:error:0.1", "", ""},
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "0:0:0.1error", "", ""},
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "error0:0:0.1", "", ""},
+ {prgname, prefix, mp_flag,
+ pci_whitelist, "0:0:0.1.2", "", ""},
+ };
+ /* Test with valid whitelist option */
+ const char *wlval1[] = {prgname, prefix, mp_flag,
+ pci_whitelist, "00FF:09:0B.3"};
+ const char *wlval2[] = {prgname, prefix, mp_flag,
+ pci_whitelist, "09:0B.3", pci_whitelist, "0a:0b.1"};
+ const char *wlval3[] = {prgname, prefix, mp_flag,
+ pci_whitelist, "09:0B.3,type=test",
+ pci_whitelist, "08:00.1,type=normal",
+ };
+
+ for (i = 0; i < RTE_DIM(wlinval); i++) {
+ if (launch_proc(wlinval[i]) == 0) {
+ printf("Error - process did run ok with invalid "
+ "whitelist parameter\n");
+ return -1;
+ }
+ }
+ if (launch_proc(wlval1) != 0 ) {
+ printf("Error - process did not run ok with valid whitelist\n");
+ return -1;
+ }
+ if (launch_proc(wlval2) != 0 ) {
+ printf("Error - process did not run ok with valid whitelist value set\n");
+ return -1;
+ }
+ if (launch_proc(wlval3) != 0 ) {
+ printf("Error - process did not run ok with valid whitelist + args\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Test that the app doesn't run with invalid blacklist option.
+ * Final test ensures it does run with valid options as sanity check
+ */
+static int
+test_invalid_b_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ const char *blinval[][5] = {
+ {prgname, prefix, mp_flag, "-b", "error"},
+ {prgname, prefix, mp_flag, "-b", "0:0:0"},
+ {prgname, prefix, mp_flag, "-b", "0:error:0.1"},
+ {prgname, prefix, mp_flag, "-b", "0:0:0.1error"},
+ {prgname, prefix, mp_flag, "-b", "error0:0:0.1"},
+ {prgname, prefix, mp_flag, "-b", "0:0:0.1.2"},
+ };
+ /* Test with valid blacklist option */
+ const char *blval[] = {prgname, prefix, mp_flag,
+ "-b", "FF:09:0B.3"};
+
+ int i;
+
+ for (i = 0; i != RTE_DIM(blinval); i++) {
+ if (launch_proc(blinval[i]) == 0) {
+ printf("Error - process did run ok with invalid "
+ "blacklist parameter\n");
+ return -1;
+ }
+ }
+ if (launch_proc(blval) != 0) {
+ printf("Error - process did not run ok with valid blacklist value\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Test that the app doesn't run with invalid vdev option.
+ * Final test ensures it does run with valid options as sanity check
+ */
+static int
+test_invalid_vdev_flag(void)
+{
+#ifdef RTE_LIBRTE_PMD_RING
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point, and we also need to
+ * run another primary process here */
+ const char * prefix = no_shconf;
+#else
+ const char * prefix = "--file-prefix=vdev";
+#endif
+
+ /* Test with invalid vdev option */
+ const char *vdevinval[] = {prgname, prefix, no_huge,
+ vdev, "eth_dummy"};
+
+ /* Test with valid vdev option */
+ const char *vdevval1[] = {prgname, prefix, no_huge,
+ vdev, "net_ring0"};
+
+ const char *vdevval2[] = {prgname, prefix, no_huge,
+ vdev, "net_ring0,args=test"};
+
+ const char *vdevval3[] = {prgname, prefix, no_huge,
+ vdev, "net_ring0,nodeaction=r1:0:CREATE"};
+
+ if (launch_proc(vdevinval) == 0) {
+ printf("Error - process did run ok with invalid "
+ "vdev parameter\n");
+ return -1;
+ }
+
+ if (launch_proc(vdevval1) != 0) {
+ printf("Error - process did not run ok with valid vdev value\n");
+ return -1;
+ }
+
+ if (launch_proc(vdevval2) != 0) {
+ printf("Error - process did not run ok with valid vdev value,"
+ "with dummy args\n");
+ return -1;
+ }
+
+ if (launch_proc(vdevval3) != 0) {
+ printf("Error - process did not run ok with valid vdev value,"
+ "with valid args\n");
+ return -1;
+ }
+ return 0;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/*
+ * Test that the app doesn't run with invalid -r option.
+ */
+static int
+test_invalid_r_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ const char *rinval[][5] = {
+ {prgname, prefix, mp_flag, "-r", "error"},
+ {prgname, prefix, mp_flag, "-r", "0"},
+ {prgname, prefix, mp_flag, "-r", "-1"},
+ {prgname, prefix, mp_flag, "-r", "17"},
+ };
+ /* Test with valid blacklist option */
+ const char *rval[] = {prgname, prefix, mp_flag, "-r", "16"};
+
+ int i;
+
+ for (i = 0; i != RTE_DIM(rinval); i++) {
+ if (launch_proc(rinval[i]) == 0) {
+ printf("Error - process did run ok with invalid "
+ "-r (rank) parameter\n");
+ return -1;
+ }
+ }
+ if (launch_proc(rval) != 0) {
+ printf("Error - process did not run ok with valid -r (rank) value\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Test that the app doesn't run without the coremask/corelist flags. In all cases
+ * should give an error and fail to run
+ */
+static int
+test_missing_c_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ /* -c flag but no coremask value */
+ const char *argv1[] = { prgname, prefix, mp_flag, "-c"};
+ /* No -c, -l or --lcores flag at all */
+ const char *argv2[] = { prgname, prefix, mp_flag};
+ /* bad coremask value */
+ const char *argv3[] = { prgname, prefix, mp_flag,
+ "-c", "error" };
+ /* sanity check of tests - valid coremask value */
+ const char *argv4[] = { prgname, prefix, mp_flag,
+ "-c", "1" };
+ /* -l flag but no corelist value */
+ const char *argv5[] = { prgname, prefix, mp_flag,
+ "-l"};
+ const char *argv6[] = { prgname, prefix, mp_flag,
+ "-l", " " };
+ /* bad corelist values */
+ const char *argv7[] = { prgname, prefix, mp_flag,
+ "-l", "error" };
+ const char *argv8[] = { prgname, prefix, mp_flag,
+ "-l", "1-" };
+ const char *argv9[] = { prgname, prefix, mp_flag,
+ "-l", "1," };
+ const char *argv10[] = { prgname, prefix, mp_flag,
+ "-l", "1#2" };
+ /* core number is negative value */
+ const char * const argv11[] = { prgname, prefix, mp_flag,
+ "-l", "-5" };
+ const char * const argv12[] = { prgname, prefix, mp_flag,
+ "-l", "-5-7" };
+ /* core number is maximum value */
+ const char * const argv13[] = { prgname, prefix, mp_flag,
+ "-l", RTE_STR(RTE_MAX_LCORE) };
+ const char * const argv14[] = { prgname, prefix, mp_flag,
+ "-l", "1-"RTE_STR(RTE_MAX_LCORE) };
+ /* sanity check test - valid corelist value */
+ const char * const argv15[] = { prgname, prefix, mp_flag,
+ "-l", "1-2,3" };
+
+ /* --lcores flag but no lcores value */
+ const char * const argv16[] = { prgname, prefix, mp_flag,
+ "--lcores" };
+ const char * const argv17[] = { prgname, prefix, mp_flag,
+ "--lcores", " " };
+ /* bad lcores value */
+ const char * const argv18[] = { prgname, prefix, mp_flag,
+ "--lcores", "1-3-5" };
+ const char * const argv19[] = { prgname, prefix, mp_flag,
+ "--lcores", "0-1,,2" };
+ const char * const argv20[] = { prgname, prefix, mp_flag,
+ "--lcores", "0-,1" };
+ const char * const argv21[] = { prgname, prefix, mp_flag,
+ "--lcores", "(0-,2-4)" };
+ const char * const argv22[] = { prgname, prefix, mp_flag,
+ "--lcores", "(-1,2)" };
+ const char * const argv23[] = { prgname, prefix, mp_flag,
+ "--lcores", "(2-4)@(2-4-6)" };
+ const char * const argv24[] = { prgname, prefix, mp_flag,
+ "--lcores", "(a,2)" };
+ const char * const argv25[] = { prgname, prefix, mp_flag,
+ "--lcores", "1-3@(1,3)" };
+ const char * const argv26[] = { prgname, prefix, mp_flag,
+ "--lcores", "3@((1,3)" };
+ const char * const argv27[] = { prgname, prefix, mp_flag,
+ "--lcores", "(4-7)=(1,3)" };
+ const char * const argv28[] = { prgname, prefix, mp_flag,
+ "--lcores", "[4-7]@(1,3)" };
+ /* sanity check of tests - valid lcores value */
+ const char * const argv29[] = { prgname, prefix, mp_flag,
+ "--lcores",
+ "0-1,2@(5-7),(3-5)@(0,2),(0,6),7"};
+
+ if (launch_proc(argv2) != 0) {
+ printf("Error - "
+ "process did not run ok when missing -c flag\n");
+ return -1;
+ }
+
+ if (launch_proc(argv1) == 0
+ || launch_proc(argv3) == 0) {
+ printf("Error - "
+ "process ran without error with invalid -c flag\n");
+ return -1;
+ }
+ if (launch_proc(argv4) != 0) {
+ printf("Error - "
+ "process did not run ok with valid coremask value\n");
+ return -1;
+ }
+
+ /* start -l test */
+ if (launch_proc(argv5) == 0
+ || launch_proc(argv6) == 0
+ || launch_proc(argv7) == 0
+ || launch_proc(argv8) == 0
+ || launch_proc(argv9) == 0
+ || launch_proc(argv10) == 0
+ || launch_proc(argv11) == 0
+ || launch_proc(argv12) == 0
+ || launch_proc(argv13) == 0
+ || launch_proc(argv14) == 0) {
+ printf("Error - "
+ "process ran without error with invalid -l flag\n");
+ return -1;
+ }
+ if (rte_lcore_is_enabled(0) && rte_lcore_is_enabled(1) &&
+ rte_lcore_is_enabled(2) && rte_lcore_is_enabled(3) &&
+ launch_proc(argv15) != 0) {
+ printf("Error - "
+ "process did not run ok with valid corelist value\n");
+ return -1;
+ }
+
+ /* start --lcores tests */
+ if (launch_proc(argv16) == 0 || launch_proc(argv17) == 0 ||
+ launch_proc(argv18) == 0 || launch_proc(argv19) == 0 ||
+ launch_proc(argv20) == 0 || launch_proc(argv21) == 0 ||
+ launch_proc(argv22) == 0 || launch_proc(argv23) == 0 ||
+ launch_proc(argv24) == 0 || launch_proc(argv25) == 0 ||
+ launch_proc(argv26) == 0 || launch_proc(argv27) == 0 ||
+ launch_proc(argv28) == 0) {
+ printf("Error - "
+ "process ran without error with invalid --lcore flag\n");
+ return -1;
+ }
+
+ if (rte_lcore_is_enabled(0) && rte_lcore_is_enabled(1) &&
+ rte_lcore_is_enabled(2) && rte_lcore_is_enabled(3) &&
+ rte_lcore_is_enabled(3) && rte_lcore_is_enabled(5) &&
+ rte_lcore_is_enabled(4) && rte_lcore_is_enabled(7) &&
+ launch_proc(argv29) != 0) {
+ printf("Error - "
+ "process did not run ok with valid corelist value\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Test --master-lcore option with matching coremask
+ */
+static int
+test_master_lcore_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char *prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1))
+ return TEST_SKIPPED;
+
+ /* --master-lcore flag but no value */
+ const char *argv1[] = { prgname, prefix, mp_flag,
+ "-c", "3", "--master-lcore"};
+ /* --master-lcore flag with invalid value */
+ const char *argv2[] = { prgname, prefix, mp_flag,
+ "-c", "3", "--master-lcore", "-1"};
+ const char *argv3[] = { prgname, prefix, mp_flag,
+ "-c", "3", "--master-lcore", "X"};
+ /* master lcore not in coremask */
+ const char *argv4[] = { prgname, prefix, mp_flag,
+ "-c", "3", "--master-lcore", "2"};
+ /* valid value */
+ const char *argv5[] = { prgname, prefix, mp_flag,
+ "-c", "3", "--master-lcore", "1"};
+ /* valid value set before coremask */
+ const char *argv6[] = { prgname, prefix, mp_flag,
+ "--master-lcore", "1", "-c", "3"};
+
+ if (launch_proc(argv1) == 0
+ || launch_proc(argv2) == 0
+ || launch_proc(argv3) == 0
+ || launch_proc(argv4) == 0) {
+ printf("Error - process ran without error with wrong --master-lcore\n");
+ return -1;
+ }
+ if (launch_proc(argv5) != 0
+ || launch_proc(argv6) != 0) {
+ printf("Error - process did not run ok with valid --master-lcore\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Test that the app doesn't run with invalid -n flag option.
+ * Final test ensures it does run with valid options as sanity check
+ * Since -n is not compulsory for MP, we instead use --no-huge and --no-shconf
+ * flags.
+ */
+static int
+test_invalid_n_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ /* -n flag but no value */
+ const char *argv1[] = { prgname, prefix, no_huge, no_shconf,
+ "-n"};
+ /* bad numeric value */
+ const char *argv2[] = { prgname, prefix, no_huge, no_shconf,
+ "-n", "e" };
+ /* zero is invalid */
+ const char *argv3[] = { prgname, prefix, no_huge, no_shconf,
+ "-n", "0" };
+ /* sanity test - check with good value */
+ const char *argv4[] = { prgname, prefix, no_huge, no_shconf,
+ "-n", "2" };
+ /* sanity test - check with no -n flag */
+ const char *argv5[] = { prgname, prefix, no_huge, no_shconf};
+
+ if (launch_proc(argv1) == 0
+ || launch_proc(argv2) == 0
+ || launch_proc(argv3) == 0) {
+ printf("Error - process ran without error when"
+ "invalid -n flag\n");
+ return -1;
+ }
+ if (launch_proc(argv4) != 0) {
+ printf("Error - process did not run ok with valid num-channel value\n");
+ return -1;
+ }
+ if (launch_proc(argv5) != 0) {
+ printf("Error - process did not run ok without -n flag\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Test that the app runs with HPET, and without HPET
+ */
+static int
+test_no_hpet_flag(void)
+{
+ char prefix[PATH_MAX] = "";
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ return 0;
+#else
+ char tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ /* With --no-hpet */
+ const char *argv1[] = {prgname, prefix, mp_flag, no_hpet};
+ /* Without --no-hpet */
+ const char *argv2[] = {prgname, prefix, mp_flag};
+
+ if (launch_proc(argv1) != 0) {
+ printf("Error - process did not run ok with --no-hpet flag\n");
+ return -1;
+ }
+ if (launch_proc(argv2) != 0) {
+ printf("Error - process did not run ok without --no-hpet flag\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Test that the app runs with --no-huge and doesn't run when --socket-mem are
+ * specified with --no-huge.
+ */
+static int
+test_no_huge_flag(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point, and we also need to
+ * run another primary process here */
+ const char * prefix = no_shconf;
+#else
+ const char * prefix = "--file-prefix=nohuge";
+#endif
+
+ /* With --no-huge */
+ const char *argv1[] = {prgname, prefix, no_huge};
+ /* With --no-huge and -m */
+ const char *argv2[] = {prgname, prefix, no_huge,
+ "-m", DEFAULT_MEM_SIZE};
+
+ /* With --no-huge and --socket-mem */
+ const char *argv3[] = {prgname, prefix, no_huge,
+ "--socket-mem=" DEFAULT_MEM_SIZE};
+ /* With --no-huge, -m and --socket-mem */
+ const char *argv4[] = {prgname, prefix, no_huge,
+ "-m", DEFAULT_MEM_SIZE, "--socket-mem=" DEFAULT_MEM_SIZE};
+ if (launch_proc(argv1) != 0) {
+ printf("Error - process did not run ok with --no-huge flag\n");
+ return -1;
+ }
+ if (launch_proc(argv2) != 0) {
+ printf("Error - process did not run ok with --no-huge and -m flags\n");
+ return -1;
+ }
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target does not support NUMA, hence no --socket-mem tests */
+ return 0;
+#endif
+
+ if (launch_proc(argv3) == 0) {
+ printf("Error - process run ok with --no-huge and --socket-mem "
+ "flags\n");
+ return -1;
+ }
+ if (launch_proc(argv4) == 0) {
+ printf("Error - process run ok with --no-huge, -m and "
+ "--socket-mem flags\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_misc_flags(void)
+{
+ char hugepath[PATH_MAX] = {0};
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+ const char * nosh_prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ const char * nosh_prefix = "--file-prefix=noshconf";
+ FILE * hugedir_handle = NULL;
+ char line[PATH_MAX] = {0};
+ unsigned i, isempty = 1;
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+
+ /*
+ * get first valid hugepage path
+ */
+
+ /* get hugetlbfs mountpoints from /proc/mounts */
+ hugedir_handle = fopen("/proc/mounts", "r");
+
+ if (hugedir_handle == NULL) {
+ printf("Error opening /proc/mounts!\n");
+ return -1;
+ }
+
+ /* read /proc/mounts */
+ while (fgets(line, sizeof(line), hugedir_handle) != NULL) {
+
+ /* find first valid hugepath */
+ if (get_hugepage_path(line, sizeof(line), hugepath, sizeof(hugepath)))
+ break;
+ }
+
+ fclose(hugedir_handle);
+
+ /* check if path is not empty */
+ for (i = 0; i < sizeof(hugepath); i++)
+ if (hugepath[i] != '\0')
+ isempty = 0;
+
+ if (isempty) {
+ printf("No mounted hugepage dir found!\n");
+ return -1;
+ }
+#endif
+
+
+ /* check that some general flags don't prevent things from working.
+ * All cases, apart from the first, app should run.
+ * No further testing of output done.
+ */
+ /* sanity check - failure with invalid option */
+ const char *argv0[] = {prgname, prefix, mp_flag, "--invalid-opt"};
+
+ /* With --no-pci */
+ const char *argv1[] = {prgname, prefix, mp_flag, "--no-pci"};
+ /* With -v */
+ const char *argv2[] = {prgname, prefix, mp_flag, "-v"};
+ /* With valid --syslog */
+ const char *argv3[] = {prgname, prefix, mp_flag,
+ "--syslog", "syslog"};
+ /* With empty --syslog (should fail) */
+ const char *argv4[] = {prgname, prefix, mp_flag, "--syslog"};
+ /* With invalid --syslog */
+ const char *argv5[] = {prgname, prefix, mp_flag, "--syslog", "error"};
+ /* With no-sh-conf, also use no-huge to ensure this test runs on BSD */
+ const char *argv6[] = {prgname, "-m", DEFAULT_MEM_SIZE,
+ no_shconf, nosh_prefix, no_huge};
+
+ /* With --huge-dir */
+ const char *argv7[] = {prgname, "-m", DEFAULT_MEM_SIZE,
+ "--file-prefix=hugedir", "--huge-dir", hugepath};
+ /* With empty --huge-dir (should fail) */
+ const char *argv8[] = {prgname, "-m", DEFAULT_MEM_SIZE,
+ "--file-prefix=hugedir", "--huge-dir"};
+ /* With invalid --huge-dir */
+ const char *argv9[] = {prgname, "-m", DEFAULT_MEM_SIZE,
+ "--file-prefix=hugedir", "--huge-dir", "invalid"};
+ /* Secondary process with invalid --huge-dir (should run as flag has no
+ * effect on secondary processes) */
+ const char *argv10[] = {prgname, prefix, mp_flag,
+ "--huge-dir", "invalid"};
+
+ /* try running with base-virtaddr param */
+ const char *argv11[] = {prgname, "--file-prefix=virtaddr",
+ "--base-virtaddr=0x12345678"};
+
+ /* try running with --vfio-intr INTx flag */
+ const char *argv12[] = {prgname, "--file-prefix=intr",
+ "--vfio-intr=legacy"};
+
+ /* try running with --vfio-intr MSI flag */
+ const char *argv13[] = {prgname, "--file-prefix=intr",
+ "--vfio-intr=msi"};
+
+ /* try running with --vfio-intr MSI-X flag */
+ const char *argv14[] = {prgname, "--file-prefix=intr",
+ "--vfio-intr=msix"};
+
+ /* try running with --vfio-intr invalid flag */
+ const char *argv15[] = {prgname, "--file-prefix=intr",
+ "--vfio-intr=invalid"};
+
+ /* With process type as auto-detect */
+ const char * const argv16[] = {prgname, "--file-prefix=auto",
+ "--proc-type=auto"};
+
+ /* With process type as auto-detect with no-shconf */
+ const char * const argv17[] = {prgname, "--proc-type=auto",
+ no_shconf, nosh_prefix, no_huge};
+
+ /* With process type as --create-uio-dev flag */
+ const char * const argv18[] = {prgname, "--file-prefix=uiodev",
+ "--create-uio-dev"};
+
+ /* run all tests also applicable to FreeBSD first */
+
+ if (launch_proc(argv0) == 0) {
+ printf("Error - process ran ok with invalid flag\n");
+ return -1;
+ }
+ if (launch_proc(argv1) != 0) {
+ printf("Error - process did not run ok with --no-pci flag\n");
+ return -1;
+ }
+ if (launch_proc(argv2) != 0) {
+ printf("Error - process did not run ok with -v flag\n");
+ return -1;
+ }
+ if (launch_proc(argv6) != 0) {
+ printf("Error - process did not run ok with --no-shconf flag\n");
+ return -1;
+ }
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* no more tests to be done on FreeBSD */
+ return 0;
+#endif
+
+ if (launch_proc(argv3) != 0) {
+ printf("Error - process did not run ok with --syslog flag\n");
+ return -1;
+ }
+ if (launch_proc(argv4) == 0) {
+ printf("Error - process run ok with empty --syslog flag\n");
+ return -1;
+ }
+ if (launch_proc(argv5) == 0) {
+ printf("Error - process run ok with invalid --syslog flag\n");
+ return -1;
+ }
+ if (launch_proc(argv7) != 0) {
+ printf("Error - process did not run ok with --huge-dir flag\n");
+ return -1;
+ }
+ if (launch_proc(argv8) == 0) {
+ printf("Error - process run ok with empty --huge-dir flag\n");
+ return -1;
+ }
+ if (launch_proc(argv9) == 0) {
+ printf("Error - process run ok with invalid --huge-dir flag\n");
+ return -1;
+ }
+ if (launch_proc(argv10) != 0) {
+ printf("Error - secondary process did not run ok with invalid --huge-dir flag\n");
+ return -1;
+ }
+ if (launch_proc(argv11) != 0) {
+ printf("Error - process did not run ok with --base-virtaddr parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv12) != 0) {
+ printf("Error - process did not run ok with "
+ "--vfio-intr INTx parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv13) != 0) {
+ printf("Error - process did not run ok with "
+ "--vfio-intr MSI parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv14) != 0) {
+ printf("Error - process did not run ok with "
+ "--vfio-intr MSI-X parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv15) == 0) {
+ printf("Error - process run ok with "
+ "--vfio-intr invalid parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv16) != 0) {
+ printf("Error - process did not run ok with "
+ "--proc-type as auto parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv17) != 0) {
+ printf("Error - process did not run ok with "
+ "--proc-type and --no-shconf parameter\n");
+ return -1;
+ }
+ if (launch_proc(argv18) != 0) {
+ printf("Error - process did not run ok with "
+ "--create-uio-dev parameter\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_file_prefix(void)
+{
+ /*
+ * 1. check if current process hugefiles are locked
+ * 2. try to run secondary process without a corresponding primary process
+ * (while failing to run, it will also remove any unused hugepage files)
+ * 3. check if current process hugefiles are still in place and are locked
+ * 4. run a primary process with memtest1 prefix in default and legacy
+ * mem mode
+ * 5. check if memtest1 hugefiles are created in case of legacy mem
+ * mode, and deleted in case of default mem mode
+ * 6. run a primary process with memtest2 prefix in default and legacy
+ * mem modes
+ * 7. check that memtest2 hugefiles are present in the hugedir after a
+ * run in legacy mode, and not present at all after run in default
+ * mem mode
+ */
+ char prefix[PATH_MAX] = "";
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ return 0;
+#else
+ if (get_current_prefix(prefix, sizeof(prefix)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+#endif
+
+ /* this should fail unless the test itself is run with "memtest" prefix */
+ const char *argv0[] = {prgname, mp_flag, "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest };
+
+ /* primary process with memtest1 and default mem mode */
+ const char *argv1[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest1 };
+
+ /* primary process with memtest1 and legacy mem mode */
+ const char *argv2[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest1,
+ "--legacy-mem" };
+
+ /* primary process with memtest2 and legacy mem mode */
+ const char *argv3[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest2,
+ "--legacy-mem" };
+
+ /* primary process with memtest2 and default mem mode */
+ const char *argv4[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--file-prefix=" memtest2 };
+
+ /* primary process with --in-memory mode */
+ const char * const argv5[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--in-memory" };
+
+ /* primary process with memtest1 and --in-memory mode */
+ const char * const argv6[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--in-memory",
+ "--file-prefix=" memtest1 };
+
+ /* primary process with parent file-prefix and --in-memory mode */
+ const char * const argv7[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--in-memory", "--file-prefix", prefix };
+
+ /* primary process with memtest1 and --single-file-segments mode */
+ const char * const argv8[] = {prgname, "-m",
+ DEFAULT_MEM_SIZE, "--single-file-segments",
+ "--file-prefix=" memtest1 };
+
+ /* check if files for current prefix are present */
+ if (process_hugefiles(prefix, HUGEPAGE_CHECK_EXISTS) != 1) {
+ printf("Error - hugepage files for %s were not created!\n", prefix);
+ return -1;
+ }
+
+ /* checks if files for current prefix are locked */
+ if (process_hugefiles(prefix, HUGEPAGE_CHECK_LOCKED) != 1) {
+ printf("Error - hugepages for current process aren't locked!\n");
+ return -1;
+ }
+
+ /* check if files for secondary process are present */
+ if (process_hugefiles(memtest, HUGEPAGE_CHECK_EXISTS) == 1) {
+ /* check if they are not locked */
+ if (process_hugefiles(memtest, HUGEPAGE_CHECK_LOCKED) == 1) {
+ printf("Error - hugepages for current process are locked!\n");
+ return -1;
+ }
+ /* they aren't locked, delete them */
+ else {
+ if (process_hugefiles(memtest, HUGEPAGE_DELETE) != 1) {
+ printf("Error - deleting hugepages failed!\n");
+ return -1;
+ }
+ }
+ }
+
+ if (launch_proc(argv0) == 0) {
+ printf("Error - secondary process ran ok without primary process\n");
+ return -1;
+ }
+
+ /* check if files for current prefix are present */
+ if (process_hugefiles(prefix, HUGEPAGE_CHECK_EXISTS) != 1) {
+ printf("Error - hugepage files for %s were not created!\n", prefix);
+ return -1;
+ }
+
+ /* checks if files for current prefix are locked */
+ if (process_hugefiles(prefix, HUGEPAGE_CHECK_LOCKED) != 1) {
+ printf("Error - hugepages for current process aren't locked!\n");
+ return -1;
+ }
+
+ /* we're running this process in default memory mode, which means it
+ * should clean up after itself on exit and leave no hugepages behind.
+ */
+ if (launch_proc(argv1) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest1);
+ return -1;
+ }
+
+ /* check if memtest1_map0 is present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ /* now, we're running a process under the same prefix, but with legacy
+ * mem mode - this should leave behind hugepage files.
+ */
+ if (launch_proc(argv2) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest1);
+ return -1;
+ }
+
+ /* check if memtest1_map0 is present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 1) {
+ printf("Error - hugepage files for %s were not created!\n",
+ memtest1);
+ return -1;
+ }
+
+ if (launch_proc(argv3) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest2 are present */
+ if (process_hugefiles(memtest2, HUGEPAGE_CHECK_EXISTS) != 1) {
+ printf("Error - hugepage files for %s were not created!\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest1 are present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ /* this process will run in default mem mode, so it should not leave any
+ * hugepage files behind.
+ */
+ if (launch_proc(argv4) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest2 are present */
+ if (process_hugefiles(memtest2, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest2);
+ return -1;
+ }
+
+ /* check if hugefiles for memtest1 are present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ /* this process will run in --in-memory mode, so it should not leave any
+ * hugepage files behind.
+ */
+
+ /* test case to check eal-options with --in-memory mode */
+ if (launch_proc(argv5) != 0) {
+ printf("Error - failed to run with --in-memory mode\n");
+ return -1;
+ }
+
+ /*test case to check eal-options with --in-memory mode with
+ * custom file-prefix.
+ */
+ if (launch_proc(argv6) != 0) {
+ printf("Error - failed to run with --in-memory mode\n");
+ return -1;
+ }
+
+ /* check if hugefiles for memtest1 are present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were created and not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ /* test case to check eal-options with --in-memory mode with
+ * parent file-prefix.
+ */
+ if (launch_proc(argv7) != 0) {
+ printf("Error - failed to run with --file-prefix=%s\n", prefix);
+ return -1;
+ }
+
+ /* this process will run in --single-file-segments mode,
+ * so it should not leave any hugepage files behind.
+ */
+ if (launch_proc(argv8) != 0) {
+ printf("Error - failed to run with --single-file-segments mode\n");
+ return -1;
+ }
+
+ /* check if hugefiles for memtest1 are present */
+ if (process_hugefiles(memtest1, HUGEPAGE_CHECK_EXISTS) != 0) {
+ printf("Error - hugepage files for %s were not deleted!\n",
+ memtest1);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* This function writes in passed buf pointer a valid --socket-mem= option
+ * for num_sockets then concatenates the provided suffix string.
+ *
+ * Example for num_sockets 4, mem "2", suffix "plop"
+ * --socket-mem=2,2,2,2plop
+ */
+static void
+populate_socket_mem_param(int num_sockets, const char *mem,
+ const char *suffix, char *buf, size_t buf_size)
+{
+ unsigned int offset = 0;
+ int written;
+ int i;
+
+ written = snprintf(&buf[offset], buf_size - offset, "--socket-mem=");
+ if (written < 0 || written + offset >= buf_size)
+ return;
+ offset += written;
+
+ for (i = 0; i < num_sockets - 1; i++) {
+ written = snprintf(&buf[offset], buf_size - offset,
+ "%s,", mem);
+ if (written < 0 || written + offset >= buf_size)
+ return;
+ offset += written;
+ }
+
+ written = snprintf(&buf[offset], buf_size - offset, "%s%s", mem,
+ suffix);
+ if (written < 0 || written + offset >= buf_size)
+ return;
+ offset += written;
+}
+
+/*
+ * Tests for correct handling of -m and --socket-mem flags
+ */
+static int
+test_memory_flags(void)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD target doesn't support prefixes at this point */
+ const char * prefix = "";
+#else
+ char prefix[PATH_MAX], tmp[PATH_MAX];
+ if (get_current_prefix(tmp, sizeof(tmp)) == NULL) {
+ printf("Error - unable to get current prefix!\n");
+ return -1;
+ }
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#endif
+
+ /* valid -m flag and mp flag */
+ const char *argv0[] = {prgname, prefix, mp_flag,
+ "-m", DEFAULT_MEM_SIZE};
+
+ /* valid -m flag */
+ const char *argv1[] = {prgname,
+ "--file-prefix=" memtest, "-m", DEFAULT_MEM_SIZE};
+
+ /* valid (zero) --socket-mem flag */
+ char arg2_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv2[] = {prgname,
+ "--file-prefix=" memtest, arg2_socket_mem};
+
+ /* invalid (incomplete) --socket-mem flag */
+ char arg3_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv3[] = {prgname,
+ "--file-prefix=" memtest, arg3_socket_mem};
+
+ /* invalid (mixed with invalid data) --socket-mem flag */
+ char arg4_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv4[] = {prgname,
+ "--file-prefix=" memtest, arg4_socket_mem};
+
+ /* invalid (with numeric value as last character) --socket-mem flag */
+ char arg5_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv5[] = {prgname,
+ "--file-prefix=" memtest, arg5_socket_mem};
+
+ /* invalid (with empty socket) --socket-mem flag */
+ char arg6_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv6[] = {prgname,
+ "--file-prefix=" memtest, arg6_socket_mem};
+
+ /* invalid (null) --socket-mem flag */
+ const char *argv7[] = {prgname,
+ "--file-prefix=" memtest, "--socket-mem="};
+
+ /* valid --socket-mem specified together with -m flag */
+ char arg8_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv8[] = {prgname,
+ "--file-prefix=" memtest, "-m", DEFAULT_MEM_SIZE,
+ arg8_socket_mem};
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ int num_sockets = 1;
+#else
+ int num_sockets = RTE_MIN(get_number_of_sockets(),
+ RTE_MAX_NUMA_NODES);
+#endif
+
+ if (num_sockets <= 0) {
+ printf("Error - cannot get number of sockets!\n");
+ return -1;
+ }
+
+ /* invalid --socket-mem flag (with extra socket) */
+ char invalid_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv9[] = {prgname,
+ "--file-prefix=" memtest, invalid_socket_mem};
+
+ /* valid --socket-mem flag */
+ char valid_socket_mem[SOCKET_MEM_STRLEN];
+ const char *argv10[] = {prgname,
+ "--file-prefix=" memtest, valid_socket_mem};
+
+ if (launch_proc(argv0) != 0) {
+ printf("Error - secondary process failed with valid -m flag !\n");
+ return -1;
+ }
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* no other tests are applicable to BSD */
+ return 0;
+#endif
+
+ if (launch_proc(argv1) != 0) {
+ printf("Error - process failed with valid -m flag!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets, "0", "",
+ arg2_socket_mem, sizeof(arg2_socket_mem));
+ if (launch_proc(argv2) != 0) {
+ printf("Error - process failed with valid (zero) --socket-mem!\n");
+ return -1;
+ }
+
+ if (num_sockets > 1) {
+ populate_socket_mem_param(num_sockets - 1, "2", ",",
+ arg3_socket_mem, sizeof(arg3_socket_mem));
+ if (launch_proc(argv3) == 0) {
+ printf("Error - process run ok with invalid "
+ "(incomplete) --socket-mem!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets - 1, "2", ",Fred",
+ arg4_socket_mem, sizeof(arg4_socket_mem));
+ if (launch_proc(argv4) == 0) {
+ printf("Error - process run ok with invalid "
+ "(mixed with invalid input) --socket-mem!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets - 1, "2", ",Fred0",
+ arg5_socket_mem, sizeof(arg5_socket_mem));
+ if (launch_proc(argv5) == 0) {
+ printf("Error - process run ok with invalid "
+ "(mixed with invalid input with a numeric value as "
+ "last character) --socket-mem!\n");
+ return -1;
+ }
+ }
+
+ if (num_sockets > 2) {
+ populate_socket_mem_param(num_sockets - 2, "2", ",,2",
+ arg6_socket_mem, sizeof(arg6_socket_mem));
+ if (launch_proc(argv6) == 0) {
+ printf("Error - process run ok with invalid "
+ "(with empty socket) --socket-mem!\n");
+ return -1;
+ }
+ }
+
+ if (launch_proc(argv7) == 0) {
+ printf("Error - process run ok with invalid (null) --socket-mem!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets, "2", "",
+ arg8_socket_mem, sizeof(arg8_socket_mem));
+ if (launch_proc(argv8) == 0) {
+ printf("Error - process run ok with --socket-mem and -m specified!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets + 1, "2", "",
+ invalid_socket_mem, sizeof(invalid_socket_mem));
+ if (launch_proc(argv9) == 0) {
+ printf("Error - process run ok with extra socket in --socket-mem!\n");
+ return -1;
+ }
+
+ populate_socket_mem_param(num_sockets, "2", "",
+ valid_socket_mem, sizeof(valid_socket_mem));
+ if (launch_proc(argv10) != 0) {
+ printf("Error - process failed with valid --socket-mem!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_eal_flags(void)
+{
+ int ret = 0;
+
+ ret = test_missing_c_flag();
+ if (ret < 0) {
+ printf("Error in test_missing_c_flag()\n");
+ return ret;
+ }
+
+ ret = test_master_lcore_flag();
+ if (ret < 0) {
+ printf("Error in test_master_lcore_flag()\n");
+ return ret;
+ }
+
+ ret = test_invalid_n_flag();
+ if (ret < 0) {
+ printf("Error in test_invalid_n_flag()\n");
+ return ret;
+ }
+
+ ret = test_no_hpet_flag();
+ if (ret < 0) {
+ printf("Error in test_no_hpet_flag()\n");
+ return ret;
+ }
+
+ ret = test_no_huge_flag();
+ if (ret < 0) {
+ printf("Error in test_no_huge_flag()\n");
+ return ret;
+ }
+
+ ret = test_whitelist_flag();
+ if (ret < 0) {
+ printf("Error in test_invalid_whitelist_flag()\n");
+ return ret;
+ }
+
+ ret = test_invalid_b_flag();
+ if (ret < 0) {
+ printf("Error in test_invalid_b_flag()\n");
+ return ret;
+ }
+
+#ifdef RTE_LIBRTE_PMD_RING
+ ret = test_invalid_vdev_flag();
+ if (ret < 0) {
+ printf("Error in test_invalid_vdev_flag()\n");
+ return ret;
+ }
+#endif
+ ret = test_invalid_r_flag();
+ if (ret < 0) {
+ printf("Error in test_invalid_r_flag()\n");
+ return ret;
+ }
+
+ ret = test_memory_flags();
+ if (ret < 0) {
+ printf("Error in test_memory_flags()\n");
+ return ret;
+ }
+
+ ret = test_file_prefix();
+ if (ret < 0) {
+ printf("Error in test_file_prefix()\n");
+ return ret;
+ }
+
+ ret = test_misc_flags();
+ if (ret < 0) {
+ printf("Error in test_misc_flags()");
+ return ret;
+ }
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(eal_flags_autotest, test_eal_flags);
+
+/* subtests used in meson for CI */
+REGISTER_TEST_COMMAND(eal_flags_c_opt_autotest, test_missing_c_flag);
+REGISTER_TEST_COMMAND(eal_flags_master_opt_autotest, test_master_lcore_flag);
+REGISTER_TEST_COMMAND(eal_flags_n_opt_autotest, test_invalid_n_flag);
+REGISTER_TEST_COMMAND(eal_flags_hpet_autotest, test_no_hpet_flag);
+REGISTER_TEST_COMMAND(eal_flags_no_huge_autotest, test_no_huge_flag);
+REGISTER_TEST_COMMAND(eal_flags_w_opt_autotest, test_whitelist_flag);
+REGISTER_TEST_COMMAND(eal_flags_b_opt_autotest, test_invalid_b_flag);
+REGISTER_TEST_COMMAND(eal_flags_vdev_opt_autotest, test_invalid_vdev_flag);
+REGISTER_TEST_COMMAND(eal_flags_r_opt_autotest, test_invalid_r_flag);
+REGISTER_TEST_COMMAND(eal_flags_mem_autotest, test_memory_flags);
+REGISTER_TEST_COMMAND(eal_flags_file_prefix_autotest, test_file_prefix);
+REGISTER_TEST_COMMAND(eal_flags_misc_autotest, test_misc_flags);
diff --git a/src/spdk/dpdk/app/test/test_eal_fs.c b/src/spdk/dpdk/app/test/test_eal_fs.c
new file mode 100644
index 000000000..cae624f82
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_eal_fs.c
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include "test.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/* eal_filesystem.h is not a public header file, so use relative path */
+#include "../../lib/librte_eal/common/eal_filesystem.h"
+
+static int
+test_parse_sysfs_value(void)
+{
+ char filename[PATH_MAX] = "";
+ char proc_path[PATH_MAX];
+ char file_template[] = "/tmp/eal_test_XXXXXX";
+ int tmp_file_handle = -1;
+ FILE *fd = NULL;
+ unsigned valid_number;
+ unsigned long retval = 0;
+
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD doesn't have /proc/pid/fd */
+ return 0;
+#endif
+
+ printf("Testing function eal_parse_sysfs_value()\n");
+
+ /* get a temporary filename to use for all tests - create temp file handle and then
+ * use /proc to get the actual file that we can open */
+ tmp_file_handle = mkstemp(file_template);
+ if (tmp_file_handle == -1) {
+ perror("mkstemp() failure");
+ goto error;
+ }
+ snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", tmp_file_handle);
+ if (readlink(proc_path, filename, sizeof(filename)) < 0) {
+ perror("readlink() failure");
+ goto error;
+ }
+ printf("Temporary file is: %s\n", filename);
+
+ /* test we get an error value if we use file before it's created */
+ printf("Test reading a missing file ...\n");
+ if (eal_parse_sysfs_value("/dev/not-quite-null", &retval) == 0) {
+ printf("Error with eal_parse_sysfs_value() - returned success on reading empty file\n");
+ goto error;
+ }
+ printf("Confirmed return error when reading empty file\n");
+
+ /* test reading a valid number value with "\n" on the end */
+ printf("Test reading valid values ...\n");
+ valid_number = 15;
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd,"%u\n", valid_number);
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) < 0) {
+ printf("eal_parse_sysfs_value() returned error - test failed\n");
+ goto error;
+ }
+ if (retval != valid_number) {
+ printf("Invalid value read by eal_parse_sysfs_value() - test failed\n");
+ goto error;
+ }
+ printf("Read '%u\\n' ok\n", valid_number);
+
+ /* test reading a valid hex number value with "\n" on the end */
+ valid_number = 25;
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd,"0x%x\n", valid_number);
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) < 0) {
+ printf("eal_parse_sysfs_value() returned error - test failed\n");
+ goto error;
+ }
+ if (retval != valid_number) {
+ printf("Invalid value read by eal_parse_sysfs_value() - test failed\n");
+ goto error;
+ }
+ printf("Read '0x%x\\n' ok\n", valid_number);
+
+ printf("Test reading invalid values ...\n");
+
+ /* test reading an empty file - expect failure!*/
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) == 0) {
+ printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ goto error;
+ }
+
+ /* test reading a valid number value *without* "\n" on the end - expect failure!*/
+ valid_number = 3;
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd,"%u", valid_number);
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) == 0) {
+ printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ goto error;
+ }
+
+ /* test reading a valid number value followed by string - expect failure!*/
+ valid_number = 3;
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd,"%uJ\n", valid_number);
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) == 0) {
+ printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ goto error;
+ }
+
+ /* test reading a non-numeric value - expect failure!*/
+ fd = fopen(filename,"w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd,"error\n");
+ fclose(fd);
+ fd = NULL;
+ if (eal_parse_sysfs_value(filename, &retval) == 0) {
+ printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ goto error;
+ }
+
+ close(tmp_file_handle);
+ unlink(filename);
+ printf("eal_parse_sysfs_value() - OK\n");
+ return 0;
+
+error:
+ if (fd)
+ fclose(fd);
+ if (tmp_file_handle > 0)
+ close(tmp_file_handle);
+ if (filename[0] != '\0')
+ unlink(filename);
+ return -1;
+}
+
+static int
+test_eal_fs(void)
+{
+ if (test_parse_sysfs_value() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(eal_fs_autotest, test_eal_fs);
diff --git a/src/spdk/dpdk/app/test/test_efd.c b/src/spdk/dpdk/app/test/test_efd.c
new file mode 100644
index 000000000..e3e5e30ea
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_efd.c
@@ -0,0 +1,469 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <rte_memcpy.h>
+#include <rte_malloc.h>
+#include <rte_efd.h>
+#include <rte_byteorder.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+#define EFD_TEST_KEY_LEN 8
+#define TABLE_SIZE (1 << 21)
+#define ITERATIONS 3
+
+#if RTE_EFD_VALUE_NUM_BITS == 32
+#define VALUE_BITMASK 0xffffffff
+#else
+#define VALUE_BITMASK ((1 << RTE_EFD_VALUE_NUM_BITS) - 1)
+#endif
+static unsigned int test_socket_id;
+
+/* 5-tuple key type */
+struct flow_key {
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint8_t proto;
+} __rte_packed;
+
+int efd_logtype_test;
+
+RTE_INIT(test_efd_init_log)
+{
+ efd_logtype_test = rte_log_register("test.efd");
+}
+
+/*
+ * Print out result of unit test efd operation.
+ */
+static void print_key_info(const char *msg, const struct flow_key *key,
+ efd_value_t val)
+{
+ const uint8_t *p = (const uint8_t *) key;
+ unsigned int i;
+
+ rte_log(RTE_LOG_DEBUG, efd_logtype_test, "%s key:0x", msg);
+ for (i = 0; i < sizeof(struct flow_key); i++)
+ rte_log(RTE_LOG_DEBUG, efd_logtype_test, "%02X", p[i]);
+
+ rte_log(RTE_LOG_DEBUG, efd_logtype_test, " @ val %d\n", val);
+}
+
+/* Keys used by unit test functions */
+static struct flow_key keys[5] = {
+ {
+ .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
+ .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
+ .port_src = 0x0908,
+ .port_dst = 0x0b0a,
+ .proto = 0x0c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10),
+ .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14),
+ .port_src = 0x1918,
+ .port_dst = 0x1b1a,
+ .proto = 0x1c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20),
+ .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24),
+ .port_src = 0x2928,
+ .port_dst = 0x2b2a,
+ .proto = 0x2c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30),
+ .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34),
+ .port_src = 0x3938,
+ .port_dst = 0x3b3a,
+ .proto = 0x3c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40),
+ .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44),
+ .port_src = 0x4948,
+ .port_dst = 0x4b4a,
+ .proto = 0x4c,
+ }
+};
+/* Array to store the data */
+static efd_value_t data[5];
+
+static inline uint8_t efd_get_all_sockets_bitmask(void)
+{
+ uint8_t all_cpu_sockets_bitmask = 0;
+ unsigned int i;
+ unsigned int next_lcore = rte_get_master_lcore();
+ const int val_true = 1, val_false = 0;
+ for (i = 0; i < rte_lcore_count(); i++) {
+ all_cpu_sockets_bitmask |= 1 << rte_lcore_to_socket_id(next_lcore);
+ next_lcore = rte_get_next_lcore(next_lcore, val_false, val_true);
+ }
+
+ return all_cpu_sockets_bitmask;
+}
+
+/*
+ * Basic sequence of operations for a single key:
+ * - add
+ * - lookup (hit)
+ * - delete
+ * Note: lookup (miss) is not applicable since this is a filter
+ */
+static int test_add_delete(void)
+{
+ struct rte_efd_table *handle;
+ /* test with standard add/lookup/delete functions */
+ efd_value_t prev_value;
+ printf("Entering %s\n", __func__);
+
+ handle = rte_efd_create("test_add_delete",
+ TABLE_SIZE, sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ TEST_ASSERT_NOT_NULL(handle, "Error creating the EFD table\n");
+
+ data[0] = mrand48() & VALUE_BITMASK;
+ TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[0],
+ data[0]),
+ "Error inserting the key");
+ print_key_info("Add", &keys[0], data[0]);
+
+ TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[0]),
+ data[0],
+ "failed to find key");
+
+ TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id, &keys[0],
+ &prev_value),
+ "failed to delete key");
+ TEST_ASSERT_EQUAL(prev_value, data[0],
+ "failed to delete the expected value, got %d, "
+ "expected %d", prev_value, data[0]);
+ print_key_info("Del", &keys[0], data[0]);
+
+ rte_efd_free(handle);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for a single key:
+ * - add
+ * - lookup: hit
+ * - add: update
+ * - lookup: hit (updated data)
+ * - delete: hit
+ */
+static int test_add_update_delete(void)
+{
+ struct rte_efd_table *handle;
+ printf("Entering %s\n", __func__);
+ /* test with standard add/lookup/delete functions */
+ efd_value_t prev_value;
+ data[1] = mrand48() & VALUE_BITMASK;
+
+ handle = rte_efd_create("test_add_update_delete", TABLE_SIZE,
+ sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+ TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[1],
+ data[1]), "Error inserting the key");
+ print_key_info("Add", &keys[1], data[1]);
+
+ TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[1]),
+ data[1], "failed to find key");
+ print_key_info("Lkp", &keys[1], data[1]);
+
+ data[1] = data[1] + 1;
+ TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id, &keys[1],
+ data[1]), "Error re-inserting the key");
+ print_key_info("Add", &keys[1], data[1]);
+
+ TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id, &keys[1]),
+ data[1], "failed to find key");
+ print_key_info("Lkp", &keys[1], data[1]);
+
+ TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id, &keys[1],
+ &prev_value), "failed to delete key");
+ TEST_ASSERT_EQUAL(prev_value, data[1],
+ "failed to delete the expected value, got %d, "
+ "expected %d", prev_value, data[1]);
+ print_key_info("Del", &keys[1], data[1]);
+
+
+ rte_efd_free(handle);
+ return 0;
+}
+
+/*
+ * Sequence of operations for find existing EFD table
+ *
+ * - create table
+ * - find existing table: hit
+ * - find non-existing table: miss
+ *
+ */
+static int test_efd_find_existing(void)
+{
+ struct rte_efd_table *handle = NULL, *result = NULL;
+
+ printf("Entering %s\n", __func__);
+
+ /* Create EFD table. */
+ handle = rte_efd_create("efd_find_existing", TABLE_SIZE,
+ sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+ /* Try to find existing EFD table */
+ result = rte_efd_find_existing("efd_find_existing");
+ TEST_ASSERT_EQUAL(result, handle, "could not find existing efd table");
+
+ /* Try to find non-existing EFD table */
+ result = rte_efd_find_existing("efd_find_non_existing");
+ TEST_ASSERT_NULL(result, "found table that shouldn't exist");
+
+ /* Cleanup. */
+ rte_efd_free(handle);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for 5 keys
+ * - add keys
+ * - lookup keys: hit (bulk)
+ * - add keys (update)
+ * - lookup keys: hit (updated data)
+ * - delete keys : hit
+ */
+static int test_five_keys(void)
+{
+ struct rte_efd_table *handle;
+ const void *key_array[5] = {0};
+ efd_value_t result[5] = {0};
+ efd_value_t prev_value;
+ unsigned int i;
+ printf("Entering %s\n", __func__);
+
+ handle = rte_efd_create("test_five_keys", TABLE_SIZE,
+ sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ TEST_ASSERT_NOT_NULL(handle, "Error creating the efd table\n");
+
+ /* Setup data */
+ for (i = 0; i < 5; i++)
+ data[i] = mrand48() & VALUE_BITMASK;
+
+ /* Add */
+ for (i = 0; i < 5; i++) {
+ TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id,
+ &keys[i], data[i]),
+ "Error inserting the key");
+ print_key_info("Add", &keys[i], data[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++)
+ key_array[i] = &keys[i];
+
+ rte_efd_lookup_bulk(handle, test_socket_id, 5,
+ (void *) &key_array, result);
+
+ for (i = 0; i < 5; i++) {
+ TEST_ASSERT_EQUAL(result[i], data[i],
+ "bulk: failed to find key. Expected %d, got %d",
+ data[i], result[i]);
+ print_key_info("Lkp", &keys[i], data[i]);
+ }
+
+ /* Modify data (bulk) */
+ for (i = 0; i < 5; i++)
+ data[i] = data[i] + 1;
+
+ /* Add - update */
+ for (i = 0; i < 5; i++) {
+ TEST_ASSERT_SUCCESS(rte_efd_update(handle, test_socket_id,
+ &keys[i], data[i]),
+ "Error inserting the key");
+ print_key_info("Add", &keys[i], data[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ TEST_ASSERT_EQUAL(rte_efd_lookup(handle, test_socket_id,
+ &keys[i]), data[i],
+ "failed to find key");
+ print_key_info("Lkp", &keys[i], data[i]);
+ }
+
+ /* Delete */
+ for (i = 0; i < 5; i++) {
+ TEST_ASSERT_SUCCESS(rte_efd_delete(handle, test_socket_id,
+ &keys[i], &prev_value),
+ "failed to delete key");
+ TEST_ASSERT_EQUAL(prev_value, data[i],
+ "failed to delete the expected value, got %d, "
+ "expected %d", prev_value, data[i]);
+ print_key_info("Del", &keys[i], data[i]);
+ }
+
+
+ rte_efd_free(handle);
+
+ return 0;
+}
+
+/*
+ * Test to see the average table utilization (entries added/max entries)
+ * before hitting a random entry that cannot be added
+ */
+static int test_average_table_utilization(void)
+{
+ struct rte_efd_table *handle = NULL;
+ uint32_t num_rules_in = TABLE_SIZE;
+ uint8_t simple_key[EFD_TEST_KEY_LEN];
+ unsigned int i, j;
+ unsigned int added_keys, average_keys_added = 0;
+
+ printf("Evaluating table utilization and correctness, please wait\n");
+ fflush(stdout);
+
+ for (j = 0; j < ITERATIONS; j++) {
+ handle = rte_efd_create("test_efd", num_rules_in,
+ EFD_TEST_KEY_LEN, efd_get_all_sockets_bitmask(),
+ test_socket_id);
+ if (handle == NULL) {
+ printf("efd table creation failed\n");
+ return -1;
+ }
+
+ unsigned int succeeded = 0;
+ unsigned int lost_keys = 0;
+
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; added_keys < num_rules_in; added_keys++) {
+
+ for (i = 0; i < EFD_TEST_KEY_LEN; i++)
+ simple_key[i] = rte_rand() & 0xFF;
+
+ efd_value_t val = simple_key[0];
+
+ if (rte_efd_update(handle, test_socket_id, simple_key,
+ val))
+ break; /* continue;*/
+ if (rte_efd_lookup(handle, test_socket_id, simple_key)
+ != val)
+ lost_keys++;
+ else
+ succeeded++;
+ }
+
+ average_keys_added += succeeded;
+
+ /* Reset the table */
+ rte_efd_free(handle);
+
+ /* Print progress on operations */
+ printf("Added %10u Succeeded %10u Lost %10u\n",
+ added_keys, succeeded, lost_keys);
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nAverage table utilization = %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / num_rules_in * 100),
+ average_keys_added, num_rules_in);
+
+ return 0;
+}
+
+/*
+ * Do tests for EFD creation with bad parameters.
+ */
+static int test_efd_creation_with_bad_parameters(void)
+{
+ struct rte_efd_table *handle, *tmp;
+ printf("Entering %s, **Errors are expected **\n", __func__);
+
+ handle = rte_efd_create("creation_with_bad_parameters_0", TABLE_SIZE, 0,
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ if (handle != NULL) {
+ rte_efd_free(handle);
+ printf("Impossible creating EFD table successfully "
+ "if key_len in parameter is zero\n");
+ return -1;
+ }
+
+ handle = rte_efd_create("creation_with_bad_parameters_1", TABLE_SIZE,
+ sizeof(struct flow_key), 0, test_socket_id);
+ if (handle != NULL) {
+ rte_efd_free(handle);
+ printf("Impossible creating EFD table successfully "
+ "with invalid socket bitmask\n");
+ return -1;
+ }
+
+ handle = rte_efd_create("creation_with_bad_parameters_2", TABLE_SIZE,
+ sizeof(struct flow_key), efd_get_all_sockets_bitmask(),
+ 255);
+ if (handle != NULL) {
+ rte_efd_free(handle);
+ printf("Impossible creating EFD table successfully "
+ "with invalid socket\n");
+ return -1;
+ }
+
+ /* test with same name should fail */
+ handle = rte_efd_create("same_name", TABLE_SIZE,
+ sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), 0);
+ if (handle == NULL) {
+ printf("Cannot create first EFD table with 'same_name'\n");
+ return -1;
+ }
+ tmp = rte_efd_create("same_name", TABLE_SIZE, sizeof(struct flow_key),
+ efd_get_all_sockets_bitmask(), 0);
+ if (tmp != NULL) {
+ printf("Creation of EFD table with same name should fail\n");
+ rte_efd_free(handle);
+ rte_efd_free(tmp);
+ return -1;
+ }
+ rte_efd_free(handle);
+
+ printf("# Test successful. No more errors expected\n");
+
+ return 0;
+}
+
+static int
+test_efd(void)
+{
+
+ /* Unit tests */
+ if (test_add_delete() < 0)
+ return -1;
+ if (test_efd_find_existing() < 0)
+ return -1;
+ if (test_add_update_delete() < 0)
+ return -1;
+ if (test_five_keys() < 0)
+ return -1;
+ if (test_efd_creation_with_bad_parameters() < 0)
+ return -1;
+ if (test_average_table_utilization() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(efd_autotest, test_efd);
diff --git a/src/spdk/dpdk/app/test/test_efd_perf.c b/src/spdk/dpdk/app/test/test_efd_perf.c
new file mode 100644
index 000000000..d47622d5c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_efd_perf.c
@@ -0,0 +1,385 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016-2017 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_efd.h>
+#include <rte_memcpy.h>
+#include <rte_thash.h>
+
+#include "test.h"
+
+#define NUM_KEYSIZES 10
+#define NUM_SHUFFLES 10
+#define MAX_KEYSIZE 64
+#define MAX_ENTRIES (1 << 19)
+#define KEYS_TO_ADD (MAX_ENTRIES * 3 / 4) /* 75% table utilization */
+#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
+
+#if RTE_EFD_VALUE_NUM_BITS == 32
+#define VALUE_BITMASK 0xffffffff
+#else
+#define VALUE_BITMASK ((1 << RTE_EFD_VALUE_NUM_BITS) - 1)
+#endif
+static unsigned int test_socket_id;
+
+static inline uint8_t efd_get_all_sockets_bitmask(void)
+{
+ uint8_t all_cpu_sockets_bitmask = 0;
+ unsigned int i;
+ unsigned int next_lcore = rte_get_master_lcore();
+ const int val_true = 1, val_false = 0;
+ for (i = 0; i < rte_lcore_count(); i++) {
+ all_cpu_sockets_bitmask |= 1 << rte_lcore_to_socket_id(next_lcore);
+ next_lcore = rte_get_next_lcore(next_lcore, val_false, val_true);
+ }
+
+ return all_cpu_sockets_bitmask;
+}
+
+enum operations {
+ ADD = 0,
+ LOOKUP,
+ LOOKUP_MULTI,
+ DELETE,
+ NUM_OPERATIONS
+};
+
+struct efd_perf_params {
+ struct rte_efd_table *efd_table;
+ uint32_t key_size;
+ unsigned int cycle;
+};
+
+static uint32_t hashtest_key_lens[] = {
+ /* standard key sizes */
+ 4, 8, 16, 32, 48, 64,
+ /* IPv4 SRC + DST + protocol, unpadded */
+ 9,
+ /* IPv4 5-tuple, unpadded */
+ 13,
+ /* IPv6 5-tuple, unpadded */
+ 37,
+ /* IPv6 5-tuple, padded to 8-byte boundary */
+ 40
+};
+
+/* Array to store number of cycles per operation */
+static uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS];
+
+/* Array to store the data */
+static efd_value_t data[KEYS_TO_ADD];
+
+/* Array to store all input keys */
+static uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
+
+/* Shuffle the keys that have been added, so lookups will be totally random */
+static void
+shuffle_input_keys(struct efd_perf_params *params)
+{
+ efd_value_t temp_data;
+ unsigned int i;
+ uint32_t swap_idx;
+ uint8_t temp_key[MAX_KEYSIZE];
+
+ for (i = KEYS_TO_ADD - 1; i > 0; i--) {
+ swap_idx = rte_rand() % i;
+
+ memcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]);
+ temp_data = data[i];
+
+ memcpy(keys[i], keys[swap_idx], hashtest_key_lens[params->cycle]);
+ data[i] = data[swap_idx];
+
+ memcpy(keys[swap_idx], temp_key, hashtest_key_lens[params->cycle]);
+ data[swap_idx] = temp_data;
+ }
+}
+
+static int key_compare(const void *key1, const void *key2)
+{
+ return memcmp(key1, key2, MAX_KEYSIZE);
+}
+
+/*
+ * TODO: we could "error proof" these as done in test_hash_perf.c ln 165:
+ *
+ * The current setup may give errors if too full in some cases which we check
+ * for. However, since EFD allows for ~99% capacity, these errors are rare for
+ * #"KEYS_TO_ADD" which is 75% capacity.
+ */
+static int
+setup_keys_and_data(struct efd_perf_params *params, unsigned int cycle)
+{
+ unsigned int i, j;
+ int num_duplicates;
+
+ params->key_size = hashtest_key_lens[cycle];
+ params->cycle = cycle;
+
+ /* Reset all arrays */
+ for (i = 0; i < params->key_size; i++)
+ keys[0][i] = 0;
+
+ /* Generate a list of keys, some of which may be duplicates */
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ for (j = 0; j < params->key_size; j++)
+ keys[i][j] = rte_rand() & 0xFF;
+
+ data[i] = rte_rand() & VALUE_BITMASK;
+ }
+
+ /* Remove duplicates from the keys array */
+ do {
+ num_duplicates = 0;
+
+ /* Sort the list of keys to make it easier to find duplicates */
+ qsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare);
+
+ /* Sift through the list of keys and look for duplicates */
+ int num_duplicates = 0;
+ for (i = 0; i < KEYS_TO_ADD - 1; i++) {
+ if (memcmp(keys[i], keys[i + 1], params->key_size) == 0) {
+ /* This key already exists, try again */
+ num_duplicates++;
+ for (j = 0; j < params->key_size; j++)
+ keys[i][j] = rte_rand() & 0xFF;
+ }
+ }
+ } while (num_duplicates != 0);
+
+ /* Shuffle the random values again */
+ shuffle_input_keys(params);
+
+ params->efd_table = rte_efd_create("test_efd_perf",
+ MAX_ENTRIES, params->key_size,
+ efd_get_all_sockets_bitmask(), test_socket_id);
+ TEST_ASSERT_NOT_NULL(params->efd_table, "Error creating the efd table\n");
+
+ return 0;
+}
+
+static int
+timed_adds(struct efd_perf_params *params)
+{
+ const uint64_t start_tsc = rte_rdtsc();
+ unsigned int i, a;
+ int32_t ret;
+
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ ret = rte_efd_update(params->efd_table, test_socket_id, keys[i],
+ data[i]);
+ if (ret != 0) {
+ printf("Error %d in rte_efd_update - key=0x", ret);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x", keys[i][a]);
+ printf(" value=%d\n", data[i]);
+
+ return -1;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[params->cycle][ADD] = time_taken / KEYS_TO_ADD;
+ return 0;
+}
+
+static int
+timed_lookups(struct efd_perf_params *params)
+{
+ unsigned int i, j, a;
+ const uint64_t start_tsc = rte_rdtsc();
+ efd_value_t ret_data;
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD; j++) {
+ ret_data = rte_efd_lookup(params->efd_table,
+ test_socket_id, keys[j]);
+ if (ret_data != data[j]) {
+ printf("Value mismatch using rte_efd_lookup: "
+ "key #%d (0x", i);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x", keys[i][a]);
+ printf(")\n");
+ printf(" Expected %d, got %d\n", data[i],
+ ret_data);
+
+ return -1;
+ }
+
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_lookups_multi(struct efd_perf_params *params)
+{
+ unsigned int i, j, k, a;
+ efd_value_t result[RTE_EFD_BURST_MAX] = {0};
+ const void *keys_burst[RTE_EFD_BURST_MAX];
+ const uint64_t start_tsc = rte_rdtsc();
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD / RTE_EFD_BURST_MAX; j++) {
+ for (k = 0; k < RTE_EFD_BURST_MAX; k++)
+ keys_burst[k] = keys[j * RTE_EFD_BURST_MAX + k];
+
+ rte_efd_lookup_bulk(params->efd_table, test_socket_id,
+ RTE_EFD_BURST_MAX,
+ keys_burst, result);
+
+ for (k = 0; k < RTE_EFD_BURST_MAX; k++) {
+ uint32_t data_idx = j * RTE_EFD_BURST_MAX + k;
+ if (result[k] != data[data_idx]) {
+ printf("Value mismatch using "
+ "rte_efd_lookup_bulk: key #%d "
+ "(0x", i);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x",
+ keys[data_idx][a]);
+ printf(")\n");
+ printf(" Expected %d, got %d\n",
+ data[data_idx], result[k]);
+
+ return -1;
+ }
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_deletes(struct efd_perf_params *params)
+{
+ unsigned int i, a;
+ const uint64_t start_tsc = rte_rdtsc();
+ int32_t ret;
+
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ ret = rte_efd_delete(params->efd_table, test_socket_id, keys[i],
+ NULL);
+
+ if (ret != 0) {
+ printf("Error %d in rte_efd_delete - key=0x", ret);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x", keys[i][a]);
+ printf("\n");
+
+ return -1;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[params->cycle][DELETE] = time_taken / KEYS_TO_ADD;
+
+ return 0;
+}
+
+static void
+perform_frees(struct efd_perf_params *params)
+{
+ if (params->efd_table != NULL) {
+ rte_efd_free(params->efd_table);
+ params->efd_table = NULL;
+ }
+}
+
+static int
+exit_with_fail(const char *testname, struct efd_perf_params *params,
+ unsigned int i)
+{
+
+ printf("<<<<<Test %s failed at keysize %d iteration %d >>>>>\n",
+ testname, hashtest_key_lens[params->cycle], i);
+ perform_frees(params);
+ return -1;
+}
+
+static int
+run_all_tbl_perf_tests(void)
+{
+ unsigned int i, j;
+ struct efd_perf_params params;
+
+ printf("Measuring performance, please wait\n");
+ fflush(stdout);
+
+ test_socket_id = rte_socket_id();
+
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+
+ if (setup_keys_and_data(&params, i) < 0) {
+ printf("Could not create keys/data/table\n");
+ return -1;
+ }
+
+ if (timed_adds(&params) < 0)
+ return exit_with_fail("timed_adds", &params, i);
+
+ for (j = 0; j < NUM_SHUFFLES; j++)
+ shuffle_input_keys(&params);
+
+ if (timed_lookups(&params) < 0)
+ return exit_with_fail("timed_lookups", &params, i);
+
+ if (timed_lookups_multi(&params) < 0)
+ return exit_with_fail("timed_lookups_multi", &params, i);
+
+ if (timed_deletes(&params) < 0)
+ return exit_with_fail("timed_deletes", &params, i);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+
+ perform_frees(&params);
+ }
+
+ printf("\nResults (in CPU cycles/operation)\n");
+ printf("-----------------------------------\n");
+ printf("\n%-18s%-18s%-18s%-18s%-18s\n",
+ "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete");
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ printf("%-18d", hashtest_key_lens[i]);
+ for (j = 0; j < NUM_OPERATIONS; j++)
+ printf("%-18"PRIu64, cycles[i][j]);
+ printf("\n");
+ }
+ return 0;
+}
+
+static int
+test_efd_perf(void)
+{
+
+ if (run_all_tbl_perf_tests() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(efd_perf_autotest, test_efd_perf);
diff --git a/src/spdk/dpdk/app/test/test_errno.c b/src/spdk/dpdk/app/test/test_errno.c
new file mode 100644
index 000000000..3ff0456a5
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_errno.c
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <rte_per_lcore.h>
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+static int
+test_errno(void)
+{
+ const char *rte_retval;
+ const char *libc_retval;
+#ifdef RTE_EXEC_ENV_FREEBSD
+ /* BSD has a colon in the string, unlike linux */
+ const char unknown_code_result[] = "Unknown error: %d";
+#else
+ const char unknown_code_result[] = "Unknown error %d";
+#endif
+ char expected_libc_retval[sizeof(unknown_code_result)+3];
+
+ /* use a small selection of standard errors for testing */
+ int std_errs[] = {EAGAIN, EBADF, EACCES, EINTR, EINVAL};
+ /* test ALL registered RTE error codes for overlap */
+ int rte_errs[] = {E_RTE_SECONDARY, E_RTE_NO_CONFIG};
+ unsigned i;
+
+ rte_errno = 0;
+ if (rte_errno != 0)
+ return -1;
+ /* check for standard errors we return the same as libc */
+ for (i = 0; i < RTE_DIM(std_errs); i++) {
+ rte_retval = rte_strerror(std_errs[i]);
+ libc_retval = strerror(std_errs[i]);
+ printf("rte_strerror: '%s', strerror: '%s'\n",
+ rte_retval, libc_retval);
+ if (strcmp(rte_retval, libc_retval) != 0)
+ return -1;
+ }
+ /* for rte-specific errors ensure we return a different string
+ * and that the string for libc is for an unknown error
+ */
+ for (i = 0; i < RTE_DIM(rte_errs); i++) {
+ rte_retval = rte_strerror(rte_errs[i]);
+ libc_retval = strerror(rte_errs[i]);
+ printf("rte_strerror: '%s', strerror: '%s'\n",
+ rte_retval, libc_retval);
+ if (strcmp(rte_retval, libc_retval) == 0)
+ return -1;
+ /* generate appropriate error string for unknown error number
+ * and then check that this is what we got back. If not, we have
+ * a duplicate error number that conflicts with errno.h */
+ snprintf(expected_libc_retval, sizeof(expected_libc_retval),
+ unknown_code_result, rte_errs[i]);
+ if ((strcmp(expected_libc_retval, libc_retval) != 0) &&
+ (strcmp("", libc_retval) != 0)){
+ printf("Error, duplicate error code %d\n", rte_errs[i]);
+ return -1;
+ }
+ }
+
+ /* ensure that beyond RTE_MAX_ERRNO, we always get an unknown code */
+ rte_retval = rte_strerror(RTE_MAX_ERRNO + 1);
+ libc_retval = strerror(RTE_MAX_ERRNO + 1);
+ snprintf(expected_libc_retval, sizeof(expected_libc_retval),
+ unknown_code_result, RTE_MAX_ERRNO + 1);
+ printf("rte_strerror: '%s', strerror: '%s'\n",
+ rte_retval, libc_retval);
+ if ((strcmp(rte_retval, libc_retval) != 0) ||
+ (strcmp(expected_libc_retval, libc_retval) != 0)){
+ if (strcmp("", libc_retval) != 0){
+ printf("Failed test for RTE_MAX_ERRNO + 1 value\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(errno_autotest, test_errno);
diff --git a/src/spdk/dpdk/app/test/test_event_crypto_adapter.c b/src/spdk/dpdk/app/test/test_event_crypto_adapter.c
new file mode 100644
index 000000000..8d42462d8
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_event_crypto_adapter.c
@@ -0,0 +1,979 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation.
+ * All rights reserved.
+ */
+
+#include <string.h>
+#include <rte_common.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_cryptodev.h>
+#include <rte_eventdev.h>
+#include <rte_bus_vdev.h>
+#include <rte_service.h>
+#include <rte_event_crypto_adapter.h>
+#include "test.h"
+
+#define PKT_TRACE 0
+#define NUM 1
+#define DEFAULT_NUM_XFORMS (2)
+#define NUM_MBUFS (8191)
+#define MBUF_CACHE_SIZE (256)
+#define MAXIMUM_IV_LENGTH (16)
+#define DEFAULT_NUM_OPS_INFLIGHT (128)
+#define MAX_NB_SESSIONS 4
+#define TEST_APP_PORT_ID 0
+#define TEST_APP_EV_QUEUE_ID 0
+#define TEST_APP_EV_PRIORITY 0
+#define TEST_APP_EV_FLOWID 0xAABB
+#define TEST_CRYPTO_EV_QUEUE_ID 1
+#define TEST_ADAPTER_ID 0
+#define TEST_CDEV_ID 0
+#define TEST_CDEV_QP_ID 0
+#define PACKET_LENGTH 64
+#define NB_TEST_PORTS 1
+#define NB_TEST_QUEUES 2
+#define NUM_CORES 1
+#define CRYPTODEV_NAME_NULL_PMD crypto_null
+
+#define MBUF_SIZE (sizeof(struct rte_mbuf) + \
+ RTE_PKTMBUF_HEADROOM + PACKET_LENGTH)
+#define IV_OFFSET (sizeof(struct rte_crypto_op) + \
+ sizeof(struct rte_crypto_sym_op) + \
+ DEFAULT_NUM_XFORMS * \
+ sizeof(struct rte_crypto_sym_xform))
+
+/* Handle log statements in same manner as test macros */
+#define LOG_DBG(...) RTE_LOG(DEBUG, EAL, __VA_ARGS__)
+
+static const uint8_t text_64B[] = {
+ 0x05, 0x15, 0x77, 0x32, 0xc9, 0x66, 0x91, 0x50,
+ 0x93, 0x9f, 0xbb, 0x4e, 0x2e, 0x5a, 0x02, 0xd0,
+ 0x2d, 0x9d, 0x31, 0x5d, 0xc8, 0x9e, 0x86, 0x36,
+ 0x54, 0x5c, 0x50, 0xe8, 0x75, 0x54, 0x74, 0x5e,
+ 0xd5, 0xa2, 0x84, 0x21, 0x2d, 0xc5, 0xf8, 0x1c,
+ 0x55, 0x1a, 0xba, 0x91, 0xce, 0xb5, 0xa3, 0x1e,
+ 0x31, 0xbf, 0xe9, 0xa1, 0x97, 0x5c, 0x2b, 0xd6,
+ 0x57, 0xa5, 0x9f, 0xab, 0xbd, 0xb0, 0x9b, 0x9c
+};
+
+struct event_crypto_adapter_test_params {
+ struct rte_mempool *mbuf_pool;
+ struct rte_mempool *op_mpool;
+ struct rte_mempool *session_mpool;
+ struct rte_mempool *session_priv_mpool;
+ struct rte_cryptodev_config *config;
+ uint8_t crypto_event_port_id;
+};
+
+struct rte_event response_info = {
+ .queue_id = TEST_APP_EV_QUEUE_ID,
+ .sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .flow_id = TEST_APP_EV_FLOWID,
+ .priority = TEST_APP_EV_PRIORITY
+};
+
+struct rte_event_crypto_request request_info = {
+ .cdev_id = TEST_CDEV_ID,
+ .queue_pair_id = TEST_CDEV_QP_ID
+};
+
+static struct event_crypto_adapter_test_params params;
+static uint8_t crypto_adapter_setup_done;
+static uint32_t slcore_id;
+static int evdev;
+
+static struct rte_mbuf *
+alloc_fill_mbuf(struct rte_mempool *mpool, const uint8_t *data,
+ size_t len, uint8_t blocksize)
+{
+ struct rte_mbuf *m = rte_pktmbuf_alloc(mpool);
+ size_t t_len = len - (blocksize ? (len % blocksize) : 0);
+
+ if (m) {
+ char *dst = rte_pktmbuf_append(m, t_len);
+
+ if (!dst) {
+ rte_pktmbuf_free(m);
+ return NULL;
+ }
+
+ rte_memcpy(dst, (const void *)data, t_len);
+ }
+ return m;
+}
+
+static int
+send_recv_ev(struct rte_event *ev)
+{
+ struct rte_crypto_op *op;
+ struct rte_event recv_ev;
+ int ret;
+
+ ret = rte_event_enqueue_burst(evdev, TEST_APP_PORT_ID, ev, NUM);
+ TEST_ASSERT_EQUAL(ret, NUM,
+ "Failed to send event to crypto adapter\n");
+
+ while (rte_event_dequeue_burst(evdev,
+ TEST_APP_PORT_ID, &recv_ev, NUM, 0) == 0)
+ rte_pause();
+
+ op = recv_ev.event_ptr;
+#if PKT_TRACE
+ struct rte_mbuf *m = op->sym->m_src;
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+#endif
+ rte_pktmbuf_free(op->sym->m_src);
+ rte_crypto_op_free(op);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_crypto_adapter_stats(void)
+{
+ struct rte_event_crypto_adapter_stats stats;
+
+ rte_event_crypto_adapter_stats_get(TEST_ADAPTER_ID, &stats);
+ printf(" +------------------------------------------------------+\n");
+ printf(" + Crypto adapter stats for instance %u:\n", TEST_ADAPTER_ID);
+ printf(" + Event port poll count %" PRIx64 "\n",
+ stats.event_poll_count);
+ printf(" + Event dequeue count %" PRIx64 "\n",
+ stats.event_deq_count);
+ printf(" + Cryptodev enqueue count %" PRIx64 "\n",
+ stats.crypto_enq_count);
+ printf(" + Cryptodev enqueue failed count %" PRIx64 "\n",
+ stats.crypto_enq_fail);
+ printf(" + Cryptodev dequeue count %" PRIx64 "\n",
+ stats.crypto_deq_count);
+ printf(" + Event enqueue count %" PRIx64 "\n",
+ stats.event_enq_count);
+ printf(" + Event enqueue retry count %" PRIx64 "\n",
+ stats.event_enq_retry_count);
+ printf(" + Event enqueue fail count %" PRIx64 "\n",
+ stats.event_enq_fail_count);
+ printf(" +------------------------------------------------------+\n");
+
+ rte_event_crypto_adapter_stats_reset(TEST_ADAPTER_ID);
+ return TEST_SUCCESS;
+}
+
+static int
+test_op_forward_mode(uint8_t session_less)
+{
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_cryptodev_sym_session *sess;
+ union rte_event_crypto_metadata m_data;
+ struct rte_crypto_sym_op *sym_op;
+ struct rte_crypto_op *op;
+ struct rte_mbuf *m;
+ struct rte_event ev;
+ uint32_t cap;
+ int ret;
+ uint8_t cipher_key[17];
+
+ memset(&m_data, 0, sizeof(m_data));
+
+ m = alloc_fill_mbuf(params.mbuf_pool, text_64B, PACKET_LENGTH, 0);
+ TEST_ASSERT_NOT_NULL(m, "Failed to allocate mbuf!\n");
+#if PKT_TRACE
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+#endif
+ /* Setup Cipher Parameters */
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+
+ cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ cipher_xform.cipher.key.data = cipher_key;
+ cipher_xform.cipher.key.length = 16;
+ cipher_xform.cipher.iv.offset = IV_OFFSET;
+ cipher_xform.cipher.iv.length = 16;
+
+ op = rte_crypto_op_alloc(params.op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(op,
+ "Failed to allocate symmetric crypto operation struct\n");
+
+ sym_op = op->sym;
+
+ if (!session_less) {
+ sess = rte_cryptodev_sym_session_create(
+ params.session_mpool);
+ TEST_ASSERT_NOT_NULL(sess, "Session creation failed\n");
+
+ /* Create Crypto session*/
+ ret = rte_cryptodev_sym_session_init(TEST_CDEV_ID, sess,
+ &cipher_xform, params.session_priv_mpool);
+ TEST_ASSERT_SUCCESS(ret, "Failed to init session\n");
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID,
+ evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_SESSION_PRIVATE_DATA) {
+ /* Fill in private user data information */
+ rte_memcpy(&m_data.response_info, &response_info,
+ sizeof(response_info));
+ rte_memcpy(&m_data.request_info, &request_info,
+ sizeof(request_info));
+ rte_cryptodev_sym_session_set_user_data(sess,
+ &m_data, sizeof(m_data));
+ }
+
+ rte_crypto_op_attach_sym_session(op, sess);
+ } else {
+ struct rte_crypto_sym_xform *first_xform;
+
+ rte_crypto_op_sym_xforms_alloc(op, NUM);
+ op->sess_type = RTE_CRYPTO_OP_SESSIONLESS;
+ first_xform = &cipher_xform;
+ sym_op->xform = first_xform;
+ uint32_t len = IV_OFFSET + MAXIMUM_IV_LENGTH +
+ (sizeof(struct rte_crypto_sym_xform) * 2);
+ op->private_data_offset = len;
+ /* Fill in private data information */
+ rte_memcpy(&m_data.response_info, &response_info,
+ sizeof(response_info));
+ rte_memcpy(&m_data.request_info, &request_info,
+ sizeof(request_info));
+ rte_memcpy((uint8_t *)op + len, &m_data, sizeof(m_data));
+ }
+
+ sym_op->m_src = m;
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = PACKET_LENGTH;
+
+ /* Fill in event info and update event_ptr with rte_crypto_op */
+ memset(&ev, 0, sizeof(ev));
+ ev.queue_id = TEST_CRYPTO_EV_QUEUE_ID;
+ ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev.flow_id = 0xAABB;
+ ev.event_ptr = op;
+
+ ret = send_recv_ev(&ev);
+ TEST_ASSERT_SUCCESS(ret, "Failed to send/receive event to "
+ "crypto adapter\n");
+
+ test_crypto_adapter_stats();
+
+ return TEST_SUCCESS;
+}
+
+static int
+map_adapter_service_core(void)
+{
+ uint32_t adapter_service_id;
+ int ret;
+
+ if (rte_event_crypto_adapter_service_id_get(TEST_ADAPTER_ID,
+ &adapter_service_id) == 0) {
+ uint32_t core_list[NUM_CORES];
+
+ ret = rte_service_lcore_list(core_list, NUM_CORES);
+ TEST_ASSERT(ret >= 0, "Failed to get service core list!");
+
+ if (core_list[0] != slcore_id) {
+ TEST_ASSERT_SUCCESS(rte_service_lcore_add(slcore_id),
+ "Failed to add service core");
+ TEST_ASSERT_SUCCESS(rte_service_lcore_start(slcore_id),
+ "Failed to start service core");
+ }
+
+ TEST_ASSERT_SUCCESS(rte_service_map_lcore_set(
+ adapter_service_id, slcore_id, 1),
+ "Failed to map adapter service");
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_sessionless_with_op_forward_mode(void)
+{
+ uint32_t cap;
+ int ret;
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
+ !(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ map_adapter_service_core();
+ else {
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD))
+ return TEST_SKIPPED;
+ }
+
+ TEST_ASSERT_SUCCESS(rte_event_crypto_adapter_start(TEST_ADAPTER_ID),
+ "Failed to start event crypto adapter");
+
+ ret = test_op_forward_mode(1);
+ TEST_ASSERT_SUCCESS(ret, "Sessionless - FORWARD mode test failed\n");
+ return TEST_SUCCESS;
+}
+
+static int
+test_session_with_op_forward_mode(void)
+{
+ uint32_t cap;
+ int ret;
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
+ !(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ map_adapter_service_core();
+ else {
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD))
+ return TEST_SKIPPED;
+ }
+
+ TEST_ASSERT_SUCCESS(rte_event_crypto_adapter_start(TEST_ADAPTER_ID
+ ), "Failed to start event crypto adapter");
+
+ ret = test_op_forward_mode(0);
+ TEST_ASSERT_SUCCESS(ret, "Session based - FORWARD mode test failed\n");
+ return TEST_SUCCESS;
+}
+
+static int
+send_op_recv_ev(struct rte_crypto_op *op)
+{
+ struct rte_crypto_op *recv_op;
+ struct rte_event ev;
+ int ret;
+
+ ret = rte_cryptodev_enqueue_burst(TEST_CDEV_ID, TEST_CDEV_QP_ID,
+ &op, NUM);
+ TEST_ASSERT_EQUAL(ret, NUM, "Failed to enqueue to cryptodev\n");
+ memset(&ev, 0, sizeof(ev));
+
+ while (rte_event_dequeue_burst(evdev,
+ TEST_APP_PORT_ID, &ev, NUM, 0) == 0)
+ rte_pause();
+
+ recv_op = ev.event_ptr;
+#if PKT_TRACE
+ struct rte_mbuf *m = recv_op->sym->m_src;
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+#endif
+ rte_pktmbuf_free(recv_op->sym->m_src);
+ rte_crypto_op_free(recv_op);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_op_new_mode(uint8_t session_less)
+{
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_cryptodev_sym_session *sess;
+ union rte_event_crypto_metadata m_data;
+ struct rte_crypto_sym_op *sym_op;
+ struct rte_crypto_op *op;
+ struct rte_mbuf *m;
+ uint32_t cap;
+ int ret;
+ uint8_t cipher_key[17];
+
+ memset(&m_data, 0, sizeof(m_data));
+
+ m = alloc_fill_mbuf(params.mbuf_pool, text_64B, PACKET_LENGTH, 0);
+ TEST_ASSERT_NOT_NULL(m, "Failed to allocate mbuf!\n");
+#if PKT_TRACE
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+#endif
+ /* Setup Cipher Parameters */
+ cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cipher_xform.next = NULL;
+
+ cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+ cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+
+ cipher_xform.cipher.key.data = cipher_key;
+ cipher_xform.cipher.key.length = 16;
+ cipher_xform.cipher.iv.offset = IV_OFFSET;
+ cipher_xform.cipher.iv.length = 16;
+
+ op = rte_crypto_op_alloc(params.op_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ TEST_ASSERT_NOT_NULL(op, "Failed to allocate crypto_op!\n");
+
+ sym_op = op->sym;
+
+ if (!session_less) {
+ sess = rte_cryptodev_sym_session_create(
+ params.session_mpool);
+ TEST_ASSERT_NOT_NULL(sess, "Session creation failed\n");
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID,
+ evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_SESSION_PRIVATE_DATA) {
+ /* Fill in private user data information */
+ rte_memcpy(&m_data.response_info, &response_info,
+ sizeof(m_data));
+ rte_cryptodev_sym_session_set_user_data(sess,
+ &m_data, sizeof(m_data));
+ }
+ ret = rte_cryptodev_sym_session_init(TEST_CDEV_ID, sess,
+ &cipher_xform, params.session_priv_mpool);
+ TEST_ASSERT_SUCCESS(ret, "Failed to init session\n");
+
+ rte_crypto_op_attach_sym_session(op, sess);
+ } else {
+ struct rte_crypto_sym_xform *first_xform;
+
+ rte_crypto_op_sym_xforms_alloc(op, NUM);
+ op->sess_type = RTE_CRYPTO_OP_SESSIONLESS;
+ first_xform = &cipher_xform;
+ sym_op->xform = first_xform;
+ uint32_t len = IV_OFFSET + MAXIMUM_IV_LENGTH +
+ (sizeof(struct rte_crypto_sym_xform) * 2);
+ op->private_data_offset = len;
+ /* Fill in private data information */
+ rte_memcpy(&m_data.response_info, &response_info,
+ sizeof(m_data));
+ rte_memcpy((uint8_t *)op + len, &m_data, sizeof(m_data));
+ }
+
+ sym_op->m_src = m;
+ sym_op->cipher.data.offset = 0;
+ sym_op->cipher.data.length = PACKET_LENGTH;
+
+ ret = send_op_recv_ev(op);
+ TEST_ASSERT_SUCCESS(ret, "Failed to enqueue op to cryptodev\n");
+
+ test_crypto_adapter_stats();
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_sessionless_with_op_new_mode(void)
+{
+ uint32_t cap;
+ int ret;
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
+ !(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ map_adapter_service_core();
+ else {
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ return TEST_SKIPPED;
+ }
+
+ /* start the event crypto adapter */
+ TEST_ASSERT_SUCCESS(rte_event_crypto_adapter_start(TEST_ADAPTER_ID),
+ "Failed to start event crypto adapter");
+
+ ret = test_op_new_mode(1);
+ TEST_ASSERT_SUCCESS(ret, "Sessionless - NEW mode test failed\n");
+ return TEST_SUCCESS;
+}
+
+static int
+test_session_with_op_new_mode(void)
+{
+ uint32_t cap;
+ int ret;
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
+ !(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ map_adapter_service_core();
+ else {
+ if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_NEW))
+ return TEST_SKIPPED;
+ }
+
+ TEST_ASSERT_SUCCESS(rte_event_crypto_adapter_start(TEST_ADAPTER_ID),
+ "Failed to start event crypto adapter");
+
+ ret = test_op_new_mode(0);
+ TEST_ASSERT_SUCCESS(ret, "Session based - NEW mode test failed\n");
+ return TEST_SUCCESS;
+}
+
+static int
+configure_cryptodev(void)
+{
+ struct rte_cryptodev_qp_conf qp_conf;
+ struct rte_cryptodev_config conf;
+ struct rte_cryptodev_info info;
+ unsigned int session_size;
+ uint8_t nb_devs;
+ int ret;
+
+ params.mbuf_pool = rte_pktmbuf_pool_create(
+ "CRYPTO_ADAPTER_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (params.mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+
+ params.op_mpool = rte_crypto_op_pool_create(
+ "EVENT_CRYPTO_SYM_OP_POOL",
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ NUM_MBUFS, MBUF_CACHE_SIZE,
+ DEFAULT_NUM_XFORMS *
+ sizeof(struct rte_crypto_sym_xform) +
+ MAXIMUM_IV_LENGTH,
+ rte_socket_id());
+ if (params.op_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ /* Create a NULL crypto device */
+ nb_devs = rte_cryptodev_device_count_by_driver(
+ rte_cryptodev_driver_id_get(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD)));
+ if (!nb_devs) {
+ ret = rte_vdev_init(
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD), NULL);
+
+ TEST_ASSERT(ret == 0, "Failed to create pmd:%s instance\n",
+ RTE_STR(CRYPTODEV_NAME_NULL_PMD));
+ }
+
+ nb_devs = rte_cryptodev_count();
+ if (!nb_devs) {
+ RTE_LOG(ERR, USER1, "No crypto devices found!\n");
+ return TEST_FAILED;
+ }
+
+ /*
+ * Create mempool with maximum number of sessions * 2,
+ * to include the session headers & private data
+ */
+ session_size = rte_cryptodev_sym_get_private_session_size(TEST_CDEV_ID);
+ session_size += sizeof(union rte_event_crypto_metadata);
+
+ params.session_mpool = rte_cryptodev_sym_session_pool_create(
+ "CRYPTO_ADAPTER_SESSION_MP",
+ MAX_NB_SESSIONS, 0, 0, 0, SOCKET_ID_ANY);
+ TEST_ASSERT_NOT_NULL(params.session_mpool,
+ "session mempool allocation failed\n");
+
+ params.session_priv_mpool = rte_mempool_create(
+ "CRYPTO_AD_SESS_MP_PRIV",
+ MAX_NB_SESSIONS,
+ session_size,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+ TEST_ASSERT_NOT_NULL(params.session_priv_mpool,
+ "session mempool allocation failed\n");
+
+ rte_cryptodev_info_get(TEST_CDEV_ID, &info);
+ conf.nb_queue_pairs = info.max_nb_queue_pairs;
+ conf.socket_id = SOCKET_ID_ANY;
+ conf.ff_disable = RTE_CRYPTODEV_FF_SECURITY;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(TEST_CDEV_ID, &conf),
+ "Failed to configure cryptodev %u with %u qps\n",
+ TEST_CDEV_ID, conf.nb_queue_pairs);
+
+ qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT;
+ qp_conf.mp_session = params.session_mpool;
+ qp_conf.mp_session_private = params.session_priv_mpool;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ TEST_CDEV_ID, TEST_CDEV_QP_ID, &qp_conf,
+ rte_cryptodev_socket_id(TEST_CDEV_ID)),
+ "Failed to setup queue pair %u on cryptodev %u\n",
+ TEST_CDEV_QP_ID, TEST_CDEV_ID);
+
+ return TEST_SUCCESS;
+}
+
+static inline void
+evdev_set_conf_values(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
+ dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
+ dev_conf->nb_event_ports = NB_TEST_PORTS;
+ dev_conf->nb_event_queues = NB_TEST_QUEUES;
+ dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
+ dev_conf->nb_event_port_dequeue_depth =
+ info->max_event_port_dequeue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_events_limit =
+ info->max_num_events;
+}
+
+static int
+configure_eventdev(void)
+{
+ struct rte_event_queue_conf queue_conf;
+ struct rte_event_dev_config devconf;
+ struct rte_event_dev_info info;
+ uint32_t queue_count;
+ uint32_t port_count;
+ int ret;
+ uint8_t qid;
+
+ if (!rte_event_dev_count()) {
+ /* If there is no hardware eventdev, or no software vdev was
+ * specified on the command line, create an instance of
+ * event_sw.
+ */
+ LOG_DBG("Failed to find a valid event device... "
+ "testing with event_sw device\n");
+ TEST_ASSERT_SUCCESS(rte_vdev_init("event_sw0", NULL),
+ "Error creating eventdev");
+ evdev = rte_event_dev_get_dev_id("event_sw0");
+ }
+
+ ret = rte_event_dev_info_get(evdev, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info\n");
+
+ evdev_set_conf_values(&devconf, &info);
+
+ ret = rte_event_dev_configure(evdev, &devconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev\n");
+
+ /* Set up event queue */
+ ret = rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_QUEUE_COUNT,
+ &queue_count);
+ TEST_ASSERT_SUCCESS(ret, "Queue count get failed\n");
+ TEST_ASSERT_EQUAL(queue_count, 2, "Unexpected queue count\n");
+
+ qid = TEST_APP_EV_QUEUE_ID;
+ ret = rte_event_queue_setup(evdev, qid, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d\n", qid);
+
+ queue_conf.nb_atomic_flows = info.max_event_queue_flows;
+ queue_conf.nb_atomic_order_sequences = 32;
+ queue_conf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
+ queue_conf.priority = RTE_EVENT_DEV_PRIORITY_HIGHEST;
+ queue_conf.event_queue_cfg = RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
+
+ qid = TEST_CRYPTO_EV_QUEUE_ID;
+ ret = rte_event_queue_setup(evdev, qid, &queue_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%u\n", qid);
+
+ /* Set up event port */
+ ret = rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count);
+ TEST_ASSERT_SUCCESS(ret, "Port count get failed\n");
+ TEST_ASSERT_EQUAL(port_count, 1, "Unexpected port count\n");
+
+ ret = rte_event_port_setup(evdev, TEST_APP_PORT_ID, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port=%d\n",
+ TEST_APP_PORT_ID);
+
+ qid = TEST_APP_EV_QUEUE_ID;
+ ret = rte_event_port_link(evdev, TEST_APP_PORT_ID, &qid, NULL, 1);
+ TEST_ASSERT(ret >= 0, "Failed to link queue port=%d\n",
+ TEST_APP_PORT_ID);
+
+ return TEST_SUCCESS;
+}
+
+static void
+test_crypto_adapter_free(void)
+{
+ rte_event_crypto_adapter_free(TEST_ADAPTER_ID);
+}
+
+static int
+test_crypto_adapter_create(void)
+{
+ struct rte_event_port_conf conf = {
+ .dequeue_depth = 8,
+ .enqueue_depth = 8,
+ .new_event_threshold = 1200,
+ };
+ int ret;
+
+ /* Create adapter with default port creation callback */
+ ret = rte_event_crypto_adapter_create(TEST_ADAPTER_ID,
+ TEST_CDEV_ID,
+ &conf, 0);
+ TEST_ASSERT_SUCCESS(ret, "Failed to create event crypto adapter\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_crypto_adapter_qp_add_del(void)
+{
+ uint32_t cap;
+ int ret;
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_QP_EV_BIND) {
+ ret = rte_event_crypto_adapter_queue_pair_add(TEST_ADAPTER_ID,
+ TEST_CDEV_ID, TEST_CDEV_QP_ID, &response_info);
+ } else
+ ret = rte_event_crypto_adapter_queue_pair_add(TEST_ADAPTER_ID,
+ TEST_CDEV_ID, TEST_CDEV_QP_ID, NULL);
+
+ TEST_ASSERT_SUCCESS(ret, "Failed to create add queue pair\n");
+
+ ret = rte_event_crypto_adapter_queue_pair_del(TEST_ADAPTER_ID,
+ TEST_CDEV_ID, TEST_CDEV_QP_ID);
+ TEST_ASSERT_SUCCESS(ret, "Failed to delete add queue pair\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+configure_event_crypto_adapter(enum rte_event_crypto_adapter_mode mode)
+{
+ struct rte_event_port_conf conf = {
+ .dequeue_depth = 8,
+ .enqueue_depth = 8,
+ .new_event_threshold = 1200,
+ };
+
+ uint32_t cap;
+ int ret;
+
+ /* Create adapter with default port creation callback */
+ ret = rte_event_crypto_adapter_create(TEST_ADAPTER_ID,
+ TEST_CDEV_ID,
+ &conf, mode);
+ TEST_ASSERT_SUCCESS(ret, "Failed to create event crypto adapter\n");
+
+ ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
+
+ if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_QP_EV_BIND) {
+ ret = rte_event_crypto_adapter_queue_pair_add(TEST_ADAPTER_ID,
+ TEST_CDEV_ID, TEST_CDEV_QP_ID, &response_info);
+ } else
+ ret = rte_event_crypto_adapter_queue_pair_add(TEST_ADAPTER_ID,
+ TEST_CDEV_ID, TEST_CDEV_QP_ID, NULL);
+
+ TEST_ASSERT_SUCCESS(ret, "Failed to add queue pair\n");
+
+ ret = rte_event_crypto_adapter_event_port_get(TEST_ADAPTER_ID,
+ &params.crypto_event_port_id);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event port\n");
+
+ return TEST_SUCCESS;
+}
+
+static void
+test_crypto_adapter_stop(void)
+{
+ uint32_t evdev_service_id, adapter_service_id;
+
+ /* retrieve service ids & stop services */
+ if (rte_event_crypto_adapter_service_id_get(TEST_ADAPTER_ID,
+ &adapter_service_id) == 0) {
+ rte_service_runstate_set(adapter_service_id, 0);
+ rte_service_lcore_stop(slcore_id);
+ rte_service_lcore_del(slcore_id);
+ rte_event_crypto_adapter_stop(TEST_ADAPTER_ID);
+ }
+
+ if (rte_event_dev_service_id_get(evdev, &evdev_service_id) == 0) {
+ rte_service_runstate_set(evdev_service_id, 0);
+ rte_service_lcore_stop(slcore_id);
+ rte_service_lcore_del(slcore_id);
+ rte_event_dev_stop(evdev);
+ }
+}
+
+static int
+test_crypto_adapter_conf(enum rte_event_crypto_adapter_mode mode)
+{
+ uint32_t evdev_service_id;
+ uint8_t qid;
+ int ret;
+
+ if (!crypto_adapter_setup_done) {
+ ret = configure_event_crypto_adapter(mode);
+ if (!ret) {
+ qid = TEST_CRYPTO_EV_QUEUE_ID;
+ ret = rte_event_port_link(evdev,
+ params.crypto_event_port_id, &qid, NULL, 1);
+ TEST_ASSERT(ret >= 0, "Failed to link queue %d "
+ "port=%u\n", qid,
+ params.crypto_event_port_id);
+ }
+ crypto_adapter_setup_done = 1;
+ }
+
+ /* retrieve service ids */
+ if (rte_event_dev_service_id_get(evdev, &evdev_service_id) == 0) {
+ /* add a service core and start it */
+ TEST_ASSERT_SUCCESS(rte_service_lcore_add(slcore_id),
+ "Failed to add service core");
+ TEST_ASSERT_SUCCESS(rte_service_lcore_start(slcore_id),
+ "Failed to start service core");
+
+ /* map services to it */
+ TEST_ASSERT_SUCCESS(rte_service_map_lcore_set(evdev_service_id,
+ slcore_id, 1), "Failed to map evdev service");
+
+ /* set services to running */
+ TEST_ASSERT_SUCCESS(rte_service_runstate_set(evdev_service_id,
+ 1), "Failed to start evdev service");
+ }
+
+ /* start the eventdev */
+ TEST_ASSERT_SUCCESS(rte_event_dev_start(evdev),
+ "Failed to start event device");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_crypto_adapter_conf_op_forward_mode(void)
+{
+ enum rte_event_crypto_adapter_mode mode;
+
+ mode = RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD;
+ TEST_ASSERT_SUCCESS(test_crypto_adapter_conf(mode),
+ "Failed to config crypto adapter");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_crypto_adapter_conf_op_new_mode(void)
+{
+ enum rte_event_crypto_adapter_mode mode;
+
+ mode = RTE_EVENT_CRYPTO_ADAPTER_OP_NEW;
+ TEST_ASSERT_SUCCESS(test_crypto_adapter_conf(mode),
+ "Failed to config crypto adapter");
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+testsuite_setup(void)
+{
+ int ret;
+
+ slcore_id = rte_get_next_lcore(-1, 1, 0);
+ TEST_ASSERT_NOT_EQUAL(slcore_id, RTE_MAX_LCORE, "At least 2 lcores "
+ "are required to run this autotest\n");
+
+ /* Setup and start event device. */
+ ret = configure_eventdev();
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup eventdev\n");
+
+ /* Setup and start crypto device. */
+ ret = configure_cryptodev();
+ TEST_ASSERT_SUCCESS(ret, "cryptodev initialization failed\n");
+
+ return TEST_SUCCESS;
+}
+
+static void
+crypto_teardown(void)
+{
+ /* Free mbuf mempool */
+ if (params.mbuf_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_ADAPTER_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(params.mbuf_pool));
+ rte_mempool_free(params.mbuf_pool);
+ params.mbuf_pool = NULL;
+ }
+
+ /* Free session mempool */
+ if (params.session_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_ADAPTER_SESSION_MP count %u\n",
+ rte_mempool_avail_count(params.session_mpool));
+ rte_mempool_free(params.session_mpool);
+ params.session_mpool = NULL;
+ }
+ if (params.session_priv_mpool != NULL) {
+ rte_mempool_avail_count(params.session_priv_mpool);
+ rte_mempool_free(params.session_priv_mpool);
+ params.session_priv_mpool = NULL;
+ }
+
+ /* Free ops mempool */
+ if (params.op_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "EVENT_CRYPTO_SYM_OP_POOL count %u\n",
+ rte_mempool_avail_count(params.op_mpool));
+ rte_mempool_free(params.op_mpool);
+ params.op_mpool = NULL;
+ }
+}
+
+static void
+eventdev_teardown(void)
+{
+ rte_event_dev_stop(evdev);
+}
+
+static void
+testsuite_teardown(void)
+{
+ crypto_teardown();
+ eventdev_teardown();
+}
+
+static struct unit_test_suite functional_testsuite = {
+ .suite_name = "Event crypto adapter test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+
+ TEST_CASE_ST(NULL, test_crypto_adapter_free,
+ test_crypto_adapter_create),
+
+ TEST_CASE_ST(test_crypto_adapter_create,
+ test_crypto_adapter_free,
+ test_crypto_adapter_qp_add_del),
+
+ TEST_CASE_ST(test_crypto_adapter_create,
+ test_crypto_adapter_free,
+ test_crypto_adapter_stats),
+
+ TEST_CASE_ST(test_crypto_adapter_conf_op_forward_mode,
+ test_crypto_adapter_stop,
+ test_session_with_op_forward_mode),
+
+ TEST_CASE_ST(test_crypto_adapter_conf_op_forward_mode,
+ test_crypto_adapter_stop,
+ test_sessionless_with_op_forward_mode),
+
+ TEST_CASE_ST(test_crypto_adapter_conf_op_new_mode,
+ test_crypto_adapter_stop,
+ test_session_with_op_new_mode),
+
+ TEST_CASE_ST(test_crypto_adapter_conf_op_new_mode,
+ test_crypto_adapter_stop,
+ test_sessionless_with_op_new_mode),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_event_crypto_adapter(void)
+{
+ return unit_test_suite_runner(&functional_testsuite);
+}
+
+REGISTER_TEST_COMMAND(event_crypto_adapter_autotest,
+ test_event_crypto_adapter);
diff --git a/src/spdk/dpdk/app/test/test_event_eth_rx_adapter.c b/src/spdk/dpdk/app/test/test_event_eth_rx_adapter.c
new file mode 100644
index 000000000..dd3bce71b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_event_eth_rx_adapter.c
@@ -0,0 +1,721 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+#include <string.h>
+#include <rte_common.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_bus_vdev.h>
+
+#include <rte_event_eth_rx_adapter.h>
+
+#include "test.h"
+
+#define MAX_NUM_RX_QUEUE 64
+#define NB_MBUFS (8192 * num_ports * MAX_NUM_RX_QUEUE)
+#define MBUF_CACHE_SIZE 512
+#define MBUF_PRIV_SIZE 0
+#define TEST_INST_ID 0
+#define TEST_DEV_ID 0
+#define TEST_ETHDEV_ID 0
+
+struct event_eth_rx_adapter_test_params {
+ struct rte_mempool *mp;
+ uint16_t rx_rings, tx_rings;
+ uint32_t caps;
+ int rx_intr_port_inited;
+ uint16_t rx_intr_port;
+};
+
+static struct event_eth_rx_adapter_test_params default_params;
+
+static inline int
+port_init_common(uint16_t port, const struct rte_eth_conf *port_conf,
+ struct rte_mempool *mp)
+{
+ const uint16_t rx_ring_size = 512, tx_ring_size = 512;
+ int retval;
+ uint16_t q;
+ struct rte_eth_dev_info dev_info;
+
+ if (!rte_eth_dev_is_valid_port(port))
+ return -1;
+
+ retval = rte_eth_dev_configure(port, 0, 0, port_conf);
+
+ retval = rte_eth_dev_info_get(port, &dev_info);
+ if (retval != 0)
+ return retval;
+
+ default_params.rx_rings = RTE_MIN(dev_info.max_rx_queues,
+ MAX_NUM_RX_QUEUE);
+ default_params.tx_rings = 1;
+
+ /* Configure the Ethernet device. */
+ retval = rte_eth_dev_configure(port, default_params.rx_rings,
+ default_params.tx_rings, port_conf);
+ if (retval != 0)
+ return retval;
+
+ for (q = 0; q < default_params.rx_rings; q++) {
+ retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
+ rte_eth_dev_socket_id(port), NULL, mp);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Allocate and set up 1 TX queue per Ethernet port. */
+ for (q = 0; q < default_params.tx_rings; q++) {
+ retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
+ rte_eth_dev_socket_id(port), NULL);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Start the Ethernet port. */
+ retval = rte_eth_dev_start(port);
+ if (retval < 0)
+ return retval;
+
+ /* Display the port MAC address. */
+ struct rte_ether_addr addr;
+ retval = rte_eth_macaddr_get(port, &addr);
+ if (retval < 0)
+ return retval;
+ printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+ " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
+ (unsigned int)port,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ /* Enable RX in promiscuous mode for the Ethernet device. */
+ retval = rte_eth_promiscuous_enable(port);
+ if (retval != 0)
+ return retval;
+
+ return 0;
+}
+
+static inline int
+port_init_rx_intr(uint16_t port, struct rte_mempool *mp)
+{
+ static const struct rte_eth_conf port_conf_default = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ },
+ .intr_conf = {
+ .rxq = 1,
+ },
+ };
+
+ return port_init_common(port, &port_conf_default, mp);
+}
+
+static inline int
+port_init(uint16_t port, struct rte_mempool *mp)
+{
+ static const struct rte_eth_conf port_conf_default = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ },
+ };
+
+ return port_init_common(port, &port_conf_default, mp);
+}
+
+static int
+init_port_rx_intr(int num_ports)
+{
+ int retval;
+ uint16_t portid;
+ int err;
+
+ default_params.mp = rte_pktmbuf_pool_create("packet_pool",
+ NB_MBUFS,
+ MBUF_CACHE_SIZE,
+ MBUF_PRIV_SIZE,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+ if (!default_params.mp)
+ return -ENOMEM;
+
+ RTE_ETH_FOREACH_DEV(portid) {
+ retval = port_init_rx_intr(portid, default_params.mp);
+ if (retval)
+ continue;
+ err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID, portid,
+ &default_params.caps);
+ if (err)
+ continue;
+ if (!(default_params.caps &
+ RTE_EVENT_ETH_RX_ADAPTER_CAP_INTERNAL_PORT)) {
+ default_params.rx_intr_port_inited = 1;
+ default_params.rx_intr_port = portid;
+ return 0;
+ }
+ rte_eth_dev_stop(portid);
+ }
+ return 0;
+}
+
+static int
+init_ports(int num_ports)
+{
+ uint16_t portid;
+ int retval;
+
+ struct rte_mempool *ptr = rte_mempool_lookup("packet_pool");
+
+ if (ptr == NULL)
+ default_params.mp = rte_pktmbuf_pool_create("packet_pool",
+ NB_MBUFS,
+ MBUF_CACHE_SIZE,
+ MBUF_PRIV_SIZE,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+ else
+ default_params.mp = ptr;
+
+ if (!default_params.mp)
+ return -ENOMEM;
+
+ RTE_ETH_FOREACH_DEV(portid) {
+ retval = port_init(portid, default_params.mp);
+ if (retval)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int
+testsuite_setup(void)
+{
+ int err;
+ uint8_t count;
+ struct rte_event_dev_info dev_info;
+
+ count = rte_event_dev_count();
+ if (!count) {
+ printf("Failed to find a valid event device,"
+ " testing with event_skeleton device\n");
+ rte_vdev_init("event_skeleton", NULL);
+ }
+
+ struct rte_event_dev_config config = {
+ .nb_event_queues = 1,
+ .nb_event_ports = 1,
+ };
+
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ config.nb_event_queue_flows = dev_info.max_event_queue_flows;
+ config.nb_event_port_dequeue_depth =
+ dev_info.max_event_port_dequeue_depth;
+ config.nb_event_port_enqueue_depth =
+ dev_info.max_event_port_enqueue_depth;
+ config.nb_events_limit =
+ dev_info.max_num_events;
+ err = rte_event_dev_configure(TEST_DEV_ID, &config);
+ TEST_ASSERT(err == 0, "Event device initialization failed err %d\n",
+ err);
+
+ /*
+ * eth devices like octeontx use event device to receive packets
+ * so rte_eth_dev_start invokes rte_event_dev_start internally, so
+ * call init_ports after rte_event_dev_configure
+ */
+ err = init_ports(rte_eth_dev_count_total());
+ TEST_ASSERT(err == 0, "Port initialization failed err %d\n", err);
+
+ err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID, TEST_ETHDEV_ID,
+ &default_params.caps);
+ TEST_ASSERT(err == 0, "Failed to get adapter cap err %d\n",
+ err);
+
+ return err;
+}
+
+static int
+testsuite_setup_rx_intr(void)
+{
+ int err;
+ uint8_t count;
+ struct rte_event_dev_info dev_info;
+
+ count = rte_event_dev_count();
+ if (!count) {
+ printf("Failed to find a valid event device,"
+ " testing with event_skeleton device\n");
+ rte_vdev_init("event_skeleton", NULL);
+ }
+
+ struct rte_event_dev_config config = {
+ .nb_event_queues = 1,
+ .nb_event_ports = 1,
+ };
+
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ config.nb_event_queue_flows = dev_info.max_event_queue_flows;
+ config.nb_event_port_dequeue_depth =
+ dev_info.max_event_port_dequeue_depth;
+ config.nb_event_port_enqueue_depth =
+ dev_info.max_event_port_enqueue_depth;
+ config.nb_events_limit =
+ dev_info.max_num_events;
+
+ err = rte_event_dev_configure(TEST_DEV_ID, &config);
+ TEST_ASSERT(err == 0, "Event device initialization failed err %d\n",
+ err);
+
+ /*
+ * eth devices like octeontx use event device to receive packets
+ * so rte_eth_dev_start invokes rte_event_dev_start internally, so
+ * call init_ports after rte_event_dev_configure
+ */
+ err = init_port_rx_intr(rte_eth_dev_count_total());
+ TEST_ASSERT(err == 0, "Port initialization failed err %d\n", err);
+
+ if (!default_params.rx_intr_port_inited)
+ return 0;
+
+ err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID,
+ default_params.rx_intr_port,
+ &default_params.caps);
+ TEST_ASSERT(err == 0, "Failed to get adapter cap err %d\n", err);
+
+ return err;
+}
+
+static void
+testsuite_teardown(void)
+{
+ uint32_t i;
+ RTE_ETH_FOREACH_DEV(i)
+ rte_eth_dev_stop(i);
+
+ rte_mempool_free(default_params.mp);
+}
+
+static void
+testsuite_teardown_rx_intr(void)
+{
+ if (!default_params.rx_intr_port_inited)
+ return;
+
+ rte_eth_dev_stop(default_params.rx_intr_port);
+ rte_mempool_free(default_params.mp);
+}
+
+static int
+adapter_create(void)
+{
+ int err;
+ struct rte_event_dev_info dev_info;
+ struct rte_event_port_conf rx_p_conf;
+
+ memset(&rx_p_conf, 0, sizeof(rx_p_conf));
+
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ rx_p_conf.new_event_threshold = dev_info.max_num_events;
+ rx_p_conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
+ rx_p_conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
+ err = rte_event_eth_rx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ &rx_p_conf);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ return err;
+}
+
+static void
+adapter_free(void)
+{
+ rte_event_eth_rx_adapter_free(TEST_INST_ID);
+}
+
+static int
+adapter_create_free(void)
+{
+ int err;
+
+ struct rte_event_port_conf rx_p_conf = {
+ .dequeue_depth = 8,
+ .enqueue_depth = 8,
+ .new_event_threshold = 1200,
+ };
+
+ err = rte_event_eth_rx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ NULL);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_rx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ &rx_p_conf);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_create(TEST_INST_ID,
+ TEST_DEV_ID, &rx_p_conf);
+ TEST_ASSERT(err == -EEXIST, "Expected -EEXIST %d got %d", -EEXIST, err);
+
+ err = rte_event_eth_rx_adapter_free(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_free(TEST_INST_ID);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL %d got %d", -EINVAL, err);
+
+ err = rte_event_eth_rx_adapter_free(1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL %d got %d", -EINVAL, err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_queue_add_del(void)
+{
+ int err;
+ struct rte_event ev;
+ uint32_t cap;
+
+ struct rte_event_eth_rx_adapter_queue_conf queue_config;
+
+ err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID, TEST_ETHDEV_ID,
+ &cap);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ ev.queue_id = 0;
+ ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev.priority = 0;
+
+ queue_config.rx_queue_flags = 0;
+ if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_OVERRIDE_FLOW_ID) {
+ ev.flow_id = 1;
+ queue_config.rx_queue_flags =
+ RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID;
+ }
+ queue_config.ev = ev;
+ queue_config.servicing_weight = 1;
+
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ rte_eth_dev_count_total(),
+ -1, &queue_config);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_MULTI_EVENTQ) {
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID, 0,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID, 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ } else {
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ 0,
+ &queue_config);
+ TEST_ASSERT(err == -EINVAL, "Expected EINVAL got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID, -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID, 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID, -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID, -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ err = rte_event_eth_rx_adapter_queue_add(1, TEST_ETHDEV_ID, -1,
+ &queue_config);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(1, TEST_ETHDEV_ID, -1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_multi_eth_add_del(void)
+{
+ int err;
+ struct rte_event ev;
+
+ uint16_t port_index, drv_id = 0;
+ char driver_name[50];
+
+ struct rte_event_eth_rx_adapter_queue_conf queue_config;
+
+ ev.queue_id = 0;
+ ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev.priority = 0;
+
+ queue_config.rx_queue_flags = 0;
+ queue_config.ev = ev;
+ queue_config.servicing_weight = 1;
+
+ /* stop eth devices for existing */
+ port_index = 0;
+ for (; port_index < rte_eth_dev_count_total(); port_index += 1)
+ rte_eth_dev_stop(port_index);
+
+ /* add the max port for rx_adapter */
+ port_index = rte_eth_dev_count_total();
+ for (; port_index < RTE_MAX_ETHPORTS; port_index += 1) {
+ snprintf(driver_name, sizeof(driver_name), "%s%u", "net_null",
+ drv_id);
+ err = rte_vdev_init(driver_name, NULL);
+ TEST_ASSERT(err == 0, "Failed driver %s got %d",
+ driver_name, err);
+ drv_id += 1;
+ }
+
+ err = init_ports(rte_eth_dev_count_total());
+ TEST_ASSERT(err == 0, "Port initialization failed err %d\n", err);
+
+ /* eth_rx_adapter_queue_add for n ports */
+ port_index = 0;
+ for (; port_index < rte_eth_dev_count_total(); port_index += 1) {
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ port_index, -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ /* eth_rx_adapter_queue_del n ports */
+ port_index = 0;
+ for (; port_index < rte_eth_dev_count_total(); port_index += 1) {
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ port_index, -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_intr_queue_add_del(void)
+{
+ int err;
+ struct rte_event ev;
+ uint32_t cap;
+ uint16_t eth_port;
+ struct rte_event_eth_rx_adapter_queue_conf queue_config;
+
+ if (!default_params.rx_intr_port_inited)
+ return 0;
+
+ eth_port = default_params.rx_intr_port;
+ err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID, eth_port, &cap);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ ev.queue_id = 0;
+ ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev.priority = 0;
+
+ queue_config.rx_queue_flags = 0;
+ queue_config.ev = ev;
+
+ /* weight = 0 => interrupt mode */
+ queue_config.servicing_weight = 0;
+
+ if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_MULTI_EVENTQ) {
+ /* add queue 0 */
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID, 0,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ /* add all queues */
+ queue_config.servicing_weight = 0;
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_MULTI_EVENTQ) {
+ /* del queue 0 */
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ /* del remaining queues */
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ /* add all queues */
+ queue_config.servicing_weight = 0;
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ /* intr -> poll mode queue */
+ queue_config.servicing_weight = 1;
+
+ if (cap & RTE_EVENT_ETH_RX_ADAPTER_CAP_MULTI_EVENTQ) {
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ 0,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1,
+ &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ /* del queues */
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_start_stop(void)
+{
+ int err;
+ struct rte_event ev;
+
+ ev.queue_id = 0;
+ ev.sched_type = RTE_SCHED_TYPE_ATOMIC;
+ ev.priority = 0;
+
+ struct rte_event_eth_rx_adapter_queue_conf queue_config;
+
+ queue_config.rx_queue_flags = 0;
+ if (default_params.caps &
+ RTE_EVENT_ETH_RX_ADAPTER_CAP_OVERRIDE_FLOW_ID) {
+ ev.flow_id = 1;
+ queue_config.rx_queue_flags =
+ RTE_EVENT_ETH_RX_ADAPTER_QUEUE_FLOW_ID_VALID;
+ }
+
+ queue_config.ev = ev;
+ queue_config.servicing_weight = 1;
+
+ err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1, &queue_config);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_start(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_stop(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_queue_del(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_start(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_stop(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_start(1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_rx_adapter_stop(1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_stats(void)
+{
+ int err;
+ struct rte_event_eth_rx_adapter_stats stats;
+
+ err = rte_event_eth_rx_adapter_stats_get(TEST_INST_ID, NULL);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_rx_adapter_stats_get(TEST_INST_ID, &stats);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_rx_adapter_stats_get(1, &stats);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite event_eth_rx_tests = {
+ .suite_name = "rx event eth adapter test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(NULL, NULL, adapter_create_free),
+ TEST_CASE_ST(adapter_create, adapter_free,
+ adapter_queue_add_del),
+ TEST_CASE_ST(adapter_create, adapter_free,
+ adapter_multi_eth_add_del),
+ TEST_CASE_ST(adapter_create, adapter_free, adapter_start_stop),
+ TEST_CASE_ST(adapter_create, adapter_free, adapter_stats),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static struct unit_test_suite event_eth_rx_intr_tests = {
+ .suite_name = "rx event eth adapter test suite",
+ .setup = testsuite_setup_rx_intr,
+ .teardown = testsuite_teardown_rx_intr,
+ .unit_test_cases = {
+ TEST_CASE_ST(adapter_create, adapter_free,
+ adapter_intr_queue_add_del),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_event_eth_rx_adapter_common(void)
+{
+ return unit_test_suite_runner(&event_eth_rx_tests);
+}
+
+static int
+test_event_eth_rx_intr_adapter_common(void)
+{
+ return unit_test_suite_runner(&event_eth_rx_intr_tests);
+}
+
+REGISTER_TEST_COMMAND(event_eth_rx_adapter_autotest,
+ test_event_eth_rx_adapter_common);
+REGISTER_TEST_COMMAND(event_eth_rx_intr_adapter_autotest,
+ test_event_eth_rx_intr_adapter_common);
diff --git a/src/spdk/dpdk/app/test/test_event_eth_tx_adapter.c b/src/spdk/dpdk/app/test/test_event_eth_tx_adapter.c
new file mode 100644
index 000000000..3af749280
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_event_eth_tx_adapter.c
@@ -0,0 +1,703 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <string.h>
+
+#include <rte_bus_vdev.h>
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_eth_ring.h>
+#include <rte_eventdev.h>
+#include <rte_event_eth_tx_adapter.h>
+#include <rte_mbuf.h>
+#include <rte_mempool.h>
+#include <rte_service.h>
+
+#include "test.h"
+
+#define MAX_NUM_QUEUE RTE_PMD_RING_MAX_RX_RINGS
+#define TEST_INST_ID 0
+#define TEST_DEV_ID 0
+#define SOCKET0 0
+#define RING_SIZE 256
+#define ETH_NAME_LEN 32
+#define NUM_ETH_PAIR 1
+#define NUM_ETH_DEV (2 * NUM_ETH_PAIR)
+#define NB_MBUF 512
+#define PAIR_PORT_INDEX(p) ((p) + NUM_ETH_PAIR)
+#define PORT(p) default_params.port[(p)]
+#define TEST_ETHDEV_ID PORT(0)
+#define TEST_ETHDEV_PAIR_ID PORT(PAIR_PORT_INDEX(0))
+
+#define EDEV_RETRY 0xffff
+
+struct event_eth_tx_adapter_test_params {
+ struct rte_mempool *mp;
+ uint16_t rx_rings, tx_rings;
+ struct rte_ring *r[NUM_ETH_DEV][MAX_NUM_QUEUE];
+ int port[NUM_ETH_DEV];
+};
+
+static int event_dev_delete;
+static struct event_eth_tx_adapter_test_params default_params;
+static uint64_t eid = ~0ULL;
+static uint32_t tid;
+
+static inline int
+port_init_common(uint8_t port, const struct rte_eth_conf *port_conf,
+ struct rte_mempool *mp)
+{
+ const uint16_t rx_ring_size = RING_SIZE, tx_ring_size = RING_SIZE;
+ int retval;
+ uint16_t q;
+
+ if (!rte_eth_dev_is_valid_port(port))
+ return -1;
+
+ default_params.rx_rings = MAX_NUM_QUEUE;
+ default_params.tx_rings = MAX_NUM_QUEUE;
+
+ /* Configure the Ethernet device. */
+ retval = rte_eth_dev_configure(port, default_params.rx_rings,
+ default_params.tx_rings, port_conf);
+ if (retval != 0)
+ return retval;
+
+ for (q = 0; q < default_params.rx_rings; q++) {
+ retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
+ rte_eth_dev_socket_id(port), NULL, mp);
+ if (retval < 0)
+ return retval;
+ }
+
+ for (q = 0; q < default_params.tx_rings; q++) {
+ retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
+ rte_eth_dev_socket_id(port), NULL);
+ if (retval < 0)
+ return retval;
+ }
+
+ /* Start the Ethernet port. */
+ retval = rte_eth_dev_start(port);
+ if (retval < 0)
+ return retval;
+
+ /* Display the port MAC address. */
+ struct rte_ether_addr addr;
+ retval = rte_eth_macaddr_get(port, &addr);
+ if (retval < 0)
+ return retval;
+ printf("Port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8
+ " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n",
+ (unsigned int)port,
+ addr.addr_bytes[0], addr.addr_bytes[1],
+ addr.addr_bytes[2], addr.addr_bytes[3],
+ addr.addr_bytes[4], addr.addr_bytes[5]);
+
+ /* Enable RX in promiscuous mode for the Ethernet device. */
+ retval = rte_eth_promiscuous_enable(port);
+ if (retval != 0)
+ return retval;
+
+ return 0;
+}
+
+static inline int
+port_init(uint8_t port, struct rte_mempool *mp)
+{
+ struct rte_eth_conf conf = { 0 };
+ return port_init_common(port, &conf, mp);
+}
+
+#define RING_NAME_LEN 20
+#define DEV_NAME_LEN 20
+
+static int
+init_ports(void)
+{
+ char ring_name[ETH_NAME_LEN];
+ unsigned int i, j;
+ struct rte_ring * const *c1;
+ struct rte_ring * const *c2;
+ int err;
+
+ if (!default_params.mp)
+ default_params.mp = rte_pktmbuf_pool_create("mbuf_pool",
+ NB_MBUF, 32,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+
+ if (!default_params.mp)
+ return -ENOMEM;
+
+ for (i = 0; i < NUM_ETH_DEV; i++) {
+ for (j = 0; j < MAX_NUM_QUEUE; j++) {
+ snprintf(ring_name, sizeof(ring_name), "R%u%u", i, j);
+ default_params.r[i][j] = rte_ring_create(ring_name,
+ RING_SIZE,
+ SOCKET0,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ TEST_ASSERT((default_params.r[i][j] != NULL),
+ "Failed to allocate ring");
+ }
+ }
+
+ /*
+ * To create two pseudo-Ethernet ports where the traffic is
+ * switched between them, that is, traffic sent to port 1 is
+ * read back from port 2 and vice-versa
+ */
+ for (i = 0; i < NUM_ETH_PAIR; i++) {
+ char dev_name[DEV_NAME_LEN];
+ int p;
+
+ c1 = default_params.r[i];
+ c2 = default_params.r[PAIR_PORT_INDEX(i)];
+
+ snprintf(dev_name, DEV_NAME_LEN, "%u-%u", i, i + NUM_ETH_PAIR);
+ p = rte_eth_from_rings(dev_name, c1, MAX_NUM_QUEUE,
+ c2, MAX_NUM_QUEUE, SOCKET0);
+ TEST_ASSERT(p >= 0, "Port creation failed %s", dev_name);
+ err = port_init(p, default_params.mp);
+ TEST_ASSERT(err == 0, "Port init failed %s", dev_name);
+ default_params.port[i] = p;
+
+ snprintf(dev_name, DEV_NAME_LEN, "%u-%u", i + NUM_ETH_PAIR, i);
+ p = rte_eth_from_rings(dev_name, c2, MAX_NUM_QUEUE,
+ c1, MAX_NUM_QUEUE, SOCKET0);
+ TEST_ASSERT(p > 0, "Port creation failed %s", dev_name);
+ err = port_init(p, default_params.mp);
+ TEST_ASSERT(err == 0, "Port init failed %s", dev_name);
+ default_params.port[PAIR_PORT_INDEX(i)] = p;
+ }
+
+ return 0;
+}
+
+static void
+deinit_ports(void)
+{
+ uint16_t i, j;
+ char name[ETH_NAME_LEN];
+
+ for (i = 0; i < RTE_DIM(default_params.port); i++) {
+ rte_eth_dev_stop(default_params.port[i]);
+ rte_eth_dev_get_name_by_port(default_params.port[i], name);
+ rte_vdev_uninit(name);
+ for (j = 0; j < RTE_DIM(default_params.r[i]); j++)
+ rte_ring_free(default_params.r[i][j]);
+ }
+}
+
+static int
+testsuite_setup(void)
+{
+ const char *vdev_name = "event_sw0";
+
+ int err = init_ports();
+ TEST_ASSERT(err == 0, "Port initialization failed err %d\n", err);
+
+ if (rte_event_dev_count() == 0) {
+ printf("Failed to find a valid event device,"
+ " testing with event_sw0 device\n");
+ err = rte_vdev_init(vdev_name, NULL);
+ TEST_ASSERT(err == 0, "vdev %s creation failed %d\n",
+ vdev_name, err);
+ event_dev_delete = 1;
+ }
+ return err;
+}
+
+#define DEVICE_ID_SIZE 64
+
+static void
+testsuite_teardown(void)
+{
+ deinit_ports();
+ rte_mempool_free(default_params.mp);
+ default_params.mp = NULL;
+ if (event_dev_delete)
+ rte_vdev_uninit("event_sw0");
+}
+
+static int
+tx_adapter_create(void)
+{
+ int err;
+ struct rte_event_dev_info dev_info;
+ struct rte_event_port_conf tx_p_conf;
+ uint8_t priority;
+ uint8_t queue_id;
+
+ struct rte_event_dev_config config = {
+ .nb_event_queues = 1,
+ .nb_event_ports = 1,
+ };
+
+ struct rte_event_queue_conf wkr_q_conf = {
+ .schedule_type = RTE_SCHED_TYPE_ORDERED,
+ .priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .nb_atomic_flows = 1024,
+ .nb_atomic_order_sequences = 1024,
+ };
+
+ memset(&tx_p_conf, 0, sizeof(tx_p_conf));
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ config.nb_event_queue_flows = dev_info.max_event_queue_flows;
+ config.nb_event_port_dequeue_depth =
+ dev_info.max_event_port_dequeue_depth;
+ config.nb_event_port_enqueue_depth =
+ dev_info.max_event_port_enqueue_depth;
+ config.nb_events_limit =
+ dev_info.max_num_events;
+
+ err = rte_event_dev_configure(TEST_DEV_ID, &config);
+ TEST_ASSERT(err == 0, "Event device initialization failed err %d\n",
+ err);
+
+ queue_id = 0;
+ err = rte_event_queue_setup(TEST_DEV_ID, 0, &wkr_q_conf);
+ TEST_ASSERT(err == 0, "Event queue setup failed %d\n", err);
+
+ err = rte_event_port_setup(TEST_DEV_ID, 0, NULL);
+ TEST_ASSERT(err == 0, "Event port setup failed %d\n", err);
+
+ priority = RTE_EVENT_DEV_PRIORITY_LOWEST;
+ err = rte_event_port_link(TEST_DEV_ID, 0, &queue_id, &priority, 1);
+ TEST_ASSERT(err == 1, "Error linking port %s\n",
+ rte_strerror(rte_errno));
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ tx_p_conf.new_event_threshold = dev_info.max_num_events;
+ tx_p_conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
+ tx_p_conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
+ err = rte_event_eth_tx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ &tx_p_conf);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ return err;
+}
+
+static void
+tx_adapter_free(void)
+{
+ rte_event_eth_tx_adapter_free(TEST_INST_ID);
+}
+
+static int
+tx_adapter_create_free(void)
+{
+ int err;
+ struct rte_event_dev_info dev_info;
+ struct rte_event_port_conf tx_p_conf;
+
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ tx_p_conf.new_event_threshold = dev_info.max_num_events;
+ tx_p_conf.dequeue_depth = dev_info.max_event_port_dequeue_depth;
+ tx_p_conf.enqueue_depth = dev_info.max_event_port_enqueue_depth;
+
+ err = rte_event_eth_tx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ NULL);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_tx_adapter_create(TEST_INST_ID, TEST_DEV_ID,
+ &tx_p_conf);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_create(TEST_INST_ID,
+ TEST_DEV_ID, &tx_p_conf);
+ TEST_ASSERT(err == -EEXIST, "Expected -EEXIST %d got %d", -EEXIST, err);
+
+ err = rte_event_eth_tx_adapter_free(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_free(TEST_INST_ID);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL %d got %d", -EINVAL, err);
+
+ err = rte_event_eth_tx_adapter_free(1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL %d got %d", -EINVAL, err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+tx_adapter_queue_add_del(void)
+{
+ int err;
+ uint32_t cap;
+
+ err = rte_event_eth_tx_adapter_caps_get(TEST_DEV_ID, TEST_ETHDEV_ID,
+ &cap);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+
+ err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+ rte_eth_dev_count_total(),
+ -1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+ TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_add(1, TEST_ETHDEV_ID, -1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(1, TEST_ETHDEV_ID, -1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+static int
+tx_adapter_start_stop(void)
+{
+ int err;
+
+ err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_start(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_stop(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_start(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_stop(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_start(1);
+
+ err = rte_event_eth_tx_adapter_stop(1);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+tx_adapter_single(uint16_t port, uint16_t tx_queue_id,
+ struct rte_mbuf *m, uint8_t qid,
+ uint8_t sched_type)
+{
+ struct rte_event event;
+ struct rte_mbuf *r;
+ int ret;
+ unsigned int l;
+
+ event.queue_id = qid;
+ event.op = RTE_EVENT_OP_NEW;
+ event.event_type = RTE_EVENT_TYPE_CPU;
+ event.sched_type = sched_type;
+ event.mbuf = m;
+
+ m->port = port;
+ rte_event_eth_tx_adapter_txq_set(m, tx_queue_id);
+
+ l = 0;
+ while (rte_event_enqueue_burst(TEST_DEV_ID, 0, &event, 1) != 1) {
+ l++;
+ if (l > EDEV_RETRY)
+ break;
+ }
+
+ TEST_ASSERT(l < EDEV_RETRY, "Unable to enqueue to eventdev");
+ l = 0;
+ while (l++ < EDEV_RETRY) {
+
+ if (eid != ~0ULL) {
+ ret = rte_service_run_iter_on_app_lcore(eid, 0);
+ TEST_ASSERT(ret == 0, "failed to run service %d", ret);
+ }
+
+ ret = rte_service_run_iter_on_app_lcore(tid, 0);
+ TEST_ASSERT(ret == 0, "failed to run service %d", ret);
+
+ if (rte_eth_rx_burst(TEST_ETHDEV_PAIR_ID, tx_queue_id,
+ &r, 1)) {
+ TEST_ASSERT_EQUAL(r, m, "mbuf comparison failed"
+ " expected %p received %p", m, r);
+ return 0;
+ }
+ }
+
+ TEST_ASSERT(0, "Failed to receive packet");
+ return -1;
+}
+
+static int
+tx_adapter_service(void)
+{
+ struct rte_event_eth_tx_adapter_stats stats;
+ uint32_t i;
+ int err;
+ uint8_t ev_port, ev_qid;
+ struct rte_mbuf bufs[RING_SIZE];
+ struct rte_mbuf *pbufs[RING_SIZE];
+ struct rte_event_dev_info dev_info;
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_queue_conf qconf;
+ uint32_t qcnt, pcnt;
+ uint16_t q;
+ int internal_port;
+ uint32_t cap;
+
+ memset(&dev_conf, 0, sizeof(dev_conf));
+ err = rte_event_eth_tx_adapter_caps_get(TEST_DEV_ID, TEST_ETHDEV_ID,
+ &cap);
+ TEST_ASSERT(err == 0, "Failed to get adapter cap err %d\n", err);
+
+ internal_port = !!(cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT);
+ if (internal_port)
+ return TEST_SUCCESS;
+
+ err = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_event_port_get(TEST_INST_ID,
+ &ev_port);
+ TEST_ASSERT_SUCCESS(err, "Failed to get event port %d", err);
+
+ err = rte_event_dev_attr_get(TEST_DEV_ID, RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &pcnt);
+ TEST_ASSERT_SUCCESS(err, "Port count get failed");
+
+ err = rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &qcnt);
+ TEST_ASSERT_SUCCESS(err, "Queue count get failed");
+
+ err = rte_event_dev_info_get(TEST_DEV_ID, &dev_info);
+ TEST_ASSERT_SUCCESS(err, "Dev info failed");
+
+ dev_conf.nb_event_queue_flows = dev_info.max_event_queue_flows;
+ dev_conf.nb_event_port_dequeue_depth =
+ dev_info.max_event_port_dequeue_depth;
+ dev_conf.nb_event_port_enqueue_depth =
+ dev_info.max_event_port_enqueue_depth;
+ dev_conf.nb_events_limit =
+ dev_info.max_num_events;
+ dev_conf.nb_event_queues = qcnt + 1;
+ dev_conf.nb_event_ports = pcnt;
+ err = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT(err == 0, "Event device initialization failed err %d\n",
+ err);
+
+ ev_qid = qcnt;
+ qconf.nb_atomic_flows = dev_info.max_event_queue_flows;
+ qconf.nb_atomic_order_sequences = 32;
+ qconf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
+ qconf.priority = RTE_EVENT_DEV_PRIORITY_HIGHEST;
+ qconf.event_queue_cfg = RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
+ err = rte_event_queue_setup(TEST_DEV_ID, ev_qid, &qconf);
+ TEST_ASSERT_SUCCESS(err, "Failed to setup queue %u", ev_qid);
+
+ /*
+ * Setup ports again so that the newly added queue is visible
+ * to them
+ */
+ for (i = 0; i < pcnt; i++) {
+
+ int n_links;
+ uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t priorities[RTE_EVENT_MAX_QUEUES_PER_DEV];
+
+ if (i == ev_port)
+ continue;
+
+ n_links = rte_event_port_links_get(TEST_DEV_ID, i, queues,
+ priorities);
+ TEST_ASSERT(n_links > 0, "Failed to get port links %d\n",
+ n_links);
+ err = rte_event_port_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT(err == 0, "Failed to setup port err %d\n", err);
+ err = rte_event_port_link(TEST_DEV_ID, i, queues, priorities,
+ n_links);
+ TEST_ASSERT(n_links == err, "Failed to link all queues"
+ " err %s\n", rte_strerror(rte_errno));
+ }
+
+ err = rte_event_port_link(TEST_DEV_ID, ev_port, &ev_qid, NULL, 1);
+ TEST_ASSERT(err == 1, "Failed to link queue port %u",
+ ev_port);
+
+ err = rte_event_eth_tx_adapter_start(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ if (!(dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED)) {
+ err = rte_event_dev_service_id_get(0, (uint32_t *)&eid);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_service_runstate_set(eid, 1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_service_set_runstate_mapped_check(eid, 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+
+ err = rte_event_eth_tx_adapter_service_id_get(TEST_INST_ID, &tid);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_service_runstate_set(tid, 1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_service_set_runstate_mapped_check(tid, 0);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_dev_start(TEST_DEV_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ for (q = 0; q < MAX_NUM_QUEUE; q++) {
+ for (i = 0; i < RING_SIZE; i++)
+ pbufs[i] = &bufs[i];
+ for (i = 0; i < RING_SIZE; i++) {
+ pbufs[i] = &bufs[i];
+ err = tx_adapter_single(TEST_ETHDEV_ID, q, pbufs[i],
+ ev_qid,
+ RTE_SCHED_TYPE_ORDERED);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ }
+ for (i = 0; i < RING_SIZE; i++) {
+ TEST_ASSERT_EQUAL(pbufs[i], &bufs[i],
+ "Error: received data does not match"
+ " that transmitted");
+ }
+ }
+
+ err = rte_event_eth_tx_adapter_stats_get(TEST_INST_ID, NULL);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_tx_adapter_stats_get(TEST_INST_ID, &stats);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ TEST_ASSERT_EQUAL(stats.tx_packets, MAX_NUM_QUEUE * RING_SIZE,
+ "stats.tx_packets expected %u got %"PRIu64,
+ MAX_NUM_QUEUE * RING_SIZE,
+ stats.tx_packets);
+
+ err = rte_event_eth_tx_adapter_stats_reset(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_stats_get(TEST_INST_ID, &stats);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+ TEST_ASSERT_EQUAL(stats.tx_packets, 0,
+ "stats.tx_packets expected %u got %"PRIu64,
+ 0,
+ stats.tx_packets);
+
+ err = rte_event_eth_tx_adapter_stats_get(1, &stats);
+ TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
+
+ err = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID, TEST_ETHDEV_ID,
+ -1);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ err = rte_event_eth_tx_adapter_free(TEST_INST_ID);
+ TEST_ASSERT(err == 0, "Expected 0 got %d", err);
+
+ rte_event_dev_stop(TEST_DEV_ID);
+
+ return TEST_SUCCESS;
+}
+
+static int
+tx_adapter_dynamic_device(void)
+{
+ uint16_t port_id = rte_eth_dev_count_avail();
+ const char *null_dev[2] = { "eth_null0", "eth_null1" };
+ struct rte_eth_conf dev_conf;
+ int ret;
+ size_t i;
+
+ memset(&dev_conf, 0, sizeof(dev_conf));
+ for (i = 0; i < RTE_DIM(null_dev); i++) {
+ ret = rte_vdev_init(null_dev[i], NULL);
+ TEST_ASSERT_SUCCESS(ret, "%s Port creation failed %d",
+ null_dev[i], ret);
+
+ if (i == 0) {
+ ret = tx_adapter_create();
+ TEST_ASSERT_SUCCESS(ret, "Adapter create failed %d",
+ ret);
+ }
+
+ ret = rte_eth_dev_configure(port_id + i, MAX_NUM_QUEUE,
+ MAX_NUM_QUEUE, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure device %d", ret);
+
+ ret = rte_event_eth_tx_adapter_queue_add(TEST_INST_ID,
+ port_id + i, 0);
+ TEST_ASSERT_SUCCESS(ret, "Failed to add queues %d", ret);
+
+ }
+
+ for (i = 0; i < RTE_DIM(null_dev); i++) {
+ ret = rte_event_eth_tx_adapter_queue_del(TEST_INST_ID,
+ port_id + i, -1);
+ TEST_ASSERT_SUCCESS(ret, "Failed to delete queues %d", ret);
+ }
+
+ tx_adapter_free();
+
+ for (i = 0; i < RTE_DIM(null_dev); i++)
+ rte_vdev_uninit(null_dev[i]);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite event_eth_tx_tests = {
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .suite_name = "tx event eth adapter test suite",
+ .unit_test_cases = {
+ TEST_CASE_ST(NULL, NULL, tx_adapter_create_free),
+ TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+ tx_adapter_queue_add_del),
+ TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+ tx_adapter_start_stop),
+ TEST_CASE_ST(tx_adapter_create, tx_adapter_free,
+ tx_adapter_service),
+ TEST_CASE_ST(NULL, NULL, tx_adapter_dynamic_device),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_event_eth_tx_adapter_common(void)
+{
+ return unit_test_suite_runner(&event_eth_tx_tests);
+}
+
+REGISTER_TEST_COMMAND(event_eth_tx_adapter_autotest,
+ test_event_eth_tx_adapter_common);
diff --git a/src/spdk/dpdk/app/test/test_event_ring.c b/src/spdk/dpdk/app/test/test_event_ring.c
new file mode 100644
index 000000000..70eb9845e
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_event_ring.c
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include <string.h>
+
+#include <rte_event_ring.h>
+
+#include "test.h"
+
+/*
+ * Event Ring
+ * ===========
+ *
+ * Test some basic ops for the event rings.
+ * Does not fully test everything, since most code is reused from rte_ring
+ * library and tested as part of the normal ring autotests.
+ */
+
+#define RING_SIZE 4096
+#define MAX_BULK 32
+
+static struct rte_event_ring *r;
+
+/*
+ * ensure failure to create ring with a bad ring size
+ */
+static int
+test_event_ring_creation_with_wrong_size(void)
+{
+ struct rte_event_ring *rp = NULL;
+
+ /* Test if ring size is not power of 2 */
+ rp = rte_event_ring_create("test_bad_ring_size", RING_SIZE + 1,
+ SOCKET_ID_ANY, 0);
+ if (rp != NULL)
+ return -1;
+
+ /* Test if ring size is exceeding the limit */
+ rp = rte_event_ring_create("test_bad_ring_size", (RTE_RING_SZ_MASK + 1),
+ SOCKET_ID_ANY, 0);
+ if (rp != NULL)
+ return -1;
+ return 0;
+}
+
+/*
+ * Test to check if a non-power-of-2 count causes the create
+ * function to fail correctly
+ */
+static int
+test_create_count_odd(void)
+{
+ struct rte_event_ring *r = rte_event_ring_create("test_event_ring_count",
+ 4097, SOCKET_ID_ANY, 0);
+ if (r != NULL)
+ return -1;
+ return 0;
+}
+
+static int
+test_lookup_null(void)
+{
+ struct rte_event_ring *rlp = rte_event_ring_lookup("ring_not_found");
+ if (rlp == NULL && rte_errno != ENOENT) {
+ printf("test failed to return error on null pointer\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_basic_event_enqueue_dequeue(void)
+{
+ struct rte_event_ring *sr = NULL;
+ struct rte_event evs[16];
+ uint16_t ret, free_count, used_count;
+
+ memset(evs, 0, sizeof(evs));
+ sr = rte_event_ring_create("spsc_ring", 32, rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (sr == NULL) {
+ printf("Failed to create sp/sc ring\n");
+ return -1;
+ }
+ if (rte_event_ring_get_capacity(sr) != 31) {
+ printf("Error, invalid capacity\n");
+ goto error;
+ }
+
+ /* test sp/sc ring */
+ if (rte_event_ring_count(sr) != 0) {
+ printf("Error, ring not empty as expected\n");
+ goto error;
+ }
+ if (rte_event_ring_free_count(sr) != rte_event_ring_get_capacity(sr)) {
+ printf("Error, ring free count not as expected\n");
+ goto error;
+ }
+
+ ret = rte_event_ring_enqueue_burst(sr, evs, RTE_DIM(evs), &free_count);
+ if (ret != RTE_DIM(evs) ||
+ free_count != rte_event_ring_get_capacity(sr) - ret) {
+ printf("Error, status after enqueue is unexpected\n");
+ goto error;
+ }
+
+ ret = rte_event_ring_enqueue_burst(sr, evs, RTE_DIM(evs), &free_count);
+ if (ret != RTE_DIM(evs) - 1 ||
+ free_count != 0) {
+ printf("Error, status after enqueue is unexpected\n");
+ goto error;
+ }
+
+ ret = rte_event_ring_dequeue_burst(sr, evs, RTE_DIM(evs), &used_count);
+ if (ret != RTE_DIM(evs) ||
+ used_count != rte_event_ring_get_capacity(sr) - ret) {
+ printf("Error, status after enqueue is unexpected\n");
+ goto error;
+ }
+ ret = rte_event_ring_dequeue_burst(sr, evs, RTE_DIM(evs), &used_count);
+ if (ret != RTE_DIM(evs) - 1 ||
+ used_count != 0) {
+ printf("Error, status after enqueue is unexpected\n");
+ goto error;
+ }
+
+ rte_event_ring_free(sr);
+ return 0;
+error:
+ rte_event_ring_free(sr);
+ return -1;
+}
+
+static int
+test_event_ring_with_exact_size(void)
+{
+ struct rte_event_ring *std_ring, *exact_sz_ring;
+ struct rte_event ev = { .mbuf = NULL };
+ struct rte_event ev_array[16];
+ static const unsigned int ring_sz = RTE_DIM(ev_array);
+ unsigned int i;
+
+ std_ring = rte_event_ring_create("std", ring_sz, rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (std_ring == NULL) {
+ printf("%s: error, can't create std ring\n", __func__);
+ return -1;
+ }
+ exact_sz_ring = rte_event_ring_create("exact sz",
+ ring_sz, rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ | RING_F_EXACT_SZ);
+ if (exact_sz_ring == NULL) {
+ printf("%s: error, can't create exact size ring\n", __func__);
+ return -1;
+ }
+
+ /*
+ * Check that the exact size ring is bigger than the standard ring
+ */
+ if (rte_event_ring_get_size(std_ring) >=
+ rte_event_ring_get_size(exact_sz_ring)) {
+ printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
+ __func__,
+ rte_event_ring_get_size(std_ring),
+ rte_event_ring_get_size(exact_sz_ring));
+ return -1;
+ }
+ /*
+ * check that the exact_sz_ring can hold one more element than the
+ * standard ring. (16 vs 15 elements)
+ */
+ for (i = 0; i < ring_sz - 1; i++) {
+ rte_event_ring_enqueue_burst(std_ring, &ev, 1, NULL);
+ rte_event_ring_enqueue_burst(exact_sz_ring, &ev, 1, NULL);
+ }
+ if (rte_event_ring_enqueue_burst(std_ring, &ev, 1, NULL) != 0) {
+ printf("%s: error, unexpected successful enqueue\n", __func__);
+ return -1;
+ }
+ if (rte_event_ring_enqueue_burst(exact_sz_ring, &ev, 1, NULL) != 1) {
+ printf("%s: error, enqueue failed\n", __func__);
+ return -1;
+ }
+
+ /* check that dequeue returns the expected number of elements */
+ if (rte_event_ring_dequeue_burst(exact_sz_ring, ev_array,
+ RTE_DIM(ev_array), NULL) != ring_sz) {
+ printf("%s: error, failed to dequeue expected nb of elements\n",
+ __func__);
+ return -1;
+ }
+
+ /* check that the capacity function returns expected value */
+ if (rte_event_ring_get_capacity(exact_sz_ring) != ring_sz) {
+ printf("%s: error, incorrect ring capacity reported\n",
+ __func__);
+ return -1;
+ }
+
+ rte_event_ring_free(std_ring);
+ rte_event_ring_free(exact_sz_ring);
+ return 0;
+}
+
+static int
+test_event_ring(void)
+{
+ if (r == NULL)
+ r = rte_event_ring_create("ev_test", RING_SIZE,
+ SOCKET_ID_ANY, 0);
+ if (r == NULL)
+ return -1;
+
+ /* retrieve the ring from its name */
+ if (rte_event_ring_lookup("ev_test") != r) {
+ printf("Cannot lookup ring from its name\n");
+ return -1;
+ }
+
+ /* basic operations */
+ if (test_create_count_odd() < 0) {
+ printf("Test failed to detect odd count\n");
+ return -1;
+ }
+ printf("Test detected odd count\n");
+
+ if (test_lookup_null() < 0) {
+ printf("Test failed to detect NULL ring lookup\n");
+ return -1;
+ }
+ printf("Test detected NULL ring lookup\n");
+
+ /* test of creating ring with wrong size */
+ if (test_event_ring_creation_with_wrong_size() < 0)
+ return -1;
+
+ if (test_basic_event_enqueue_dequeue() < 0)
+ return -1;
+
+ if (test_event_ring_with_exact_size() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(event_ring_autotest, test_event_ring);
diff --git a/src/spdk/dpdk/app/test/test_event_timer_adapter.c b/src/spdk/dpdk/app/test/test_event_timer_adapter.c
new file mode 100644
index 000000000..ad3f4dcc2
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_event_timer_adapter.c
@@ -0,0 +1,1844 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ * Copyright(c) 2017-2018 Intel Corporation.
+ */
+
+#include <rte_atomic.h>
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_event_timer_adapter.h>
+#include <rte_mempool.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_random.h>
+#include <rte_bus_vdev.h>
+#include <rte_service.h>
+#include <stdbool.h>
+
+#include "test.h"
+
+/* 4K timers corresponds to sw evdev max inflight events */
+#define MAX_TIMERS (4 * 1024)
+#define BKT_TCK_NSEC
+
+#define NSECPERSEC 1E9
+#define BATCH_SIZE 16
+/* Both the app lcore and adapter ports are linked to this queue */
+#define TEST_QUEUE_ID 0
+/* Port the application dequeues from */
+#define TEST_PORT_ID 0
+#define TEST_ADAPTER_ID 0
+
+/* Handle log statements in same manner as test macros */
+#define LOG_DBG(...) RTE_LOG(DEBUG, EAL, __VA_ARGS__)
+
+static int evdev;
+static struct rte_event_timer_adapter *timdev;
+static struct rte_mempool *eventdev_test_mempool;
+static struct rte_ring *timer_producer_ring;
+static uint64_t global_bkt_tck_ns;
+static uint64_t global_info_bkt_tck_ns;
+static volatile uint8_t arm_done;
+
+#define CALC_TICKS(tks) \
+ ((tks * global_bkt_tck_ns) / global_info_bkt_tck_ns)
+
+
+static bool using_services;
+static uint32_t test_lcore1;
+static uint32_t test_lcore2;
+static uint32_t test_lcore3;
+static uint32_t sw_evdev_slcore;
+static uint32_t sw_adptr_slcore;
+
+static inline void
+devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
+ dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
+ dev_conf->nb_event_ports = 1;
+ dev_conf->nb_event_queues = 1;
+ dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
+ dev_conf->nb_event_port_dequeue_depth =
+ info->max_event_port_dequeue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_events_limit =
+ info->max_num_events;
+}
+
+static inline int
+eventdev_setup(void)
+{
+ int ret;
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_dev_info info;
+ uint32_t service_id;
+
+ ret = rte_event_dev_info_get(evdev, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+ TEST_ASSERT(info.max_num_events < 0 ||
+ info.max_num_events >= (int32_t)MAX_TIMERS,
+ "ERROR max_num_events=%d < max_events=%d",
+ info.max_num_events, MAX_TIMERS);
+
+ devconf_set_default_sane_values(&dev_conf, &info);
+ ret = rte_event_dev_configure(evdev, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
+
+ ret = rte_event_queue_setup(evdev, 0, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue=%d", 0);
+
+ /* Configure event port */
+ ret = rte_event_port_setup(evdev, 0, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port=%d", 0);
+ ret = rte_event_port_link(evdev, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret >= 0, "Failed to link all queues port=%d", 0);
+
+ /* If this is a software event device, map and start its service */
+ if (rte_event_dev_service_id_get(evdev, &service_id) == 0) {
+ TEST_ASSERT_SUCCESS(rte_service_lcore_add(sw_evdev_slcore),
+ "Failed to add service core");
+ TEST_ASSERT_SUCCESS(rte_service_lcore_start(
+ sw_evdev_slcore),
+ "Failed to start service core");
+ TEST_ASSERT_SUCCESS(rte_service_map_lcore_set(
+ service_id, sw_evdev_slcore, 1),
+ "Failed to map evdev service");
+ TEST_ASSERT_SUCCESS(rte_service_runstate_set(
+ service_id, 1),
+ "Failed to start evdev service");
+ }
+
+ ret = rte_event_dev_start(evdev);
+ TEST_ASSERT_SUCCESS(ret, "Failed to start device");
+
+ return TEST_SUCCESS;
+}
+
+static int
+testsuite_setup(void)
+{
+ /* Some of the multithreaded tests require 3 other lcores to run */
+ unsigned int required_lcore_count = 4;
+ uint32_t service_id;
+
+ /* To make it easier to map services later if needed, just reset
+ * service core state.
+ */
+ (void) rte_service_lcore_reset_all();
+
+ if (!rte_event_dev_count()) {
+ /* If there is no hardware eventdev, or no software vdev was
+ * specified on the command line, create an instance of
+ * event_sw.
+ */
+ LOG_DBG("Failed to find a valid event device... testing with"
+ " event_sw device\n");
+ TEST_ASSERT_SUCCESS(rte_vdev_init("event_sw0", NULL),
+ "Error creating eventdev");
+ evdev = rte_event_dev_get_dev_id("event_sw0");
+ }
+
+ if (rte_event_dev_service_id_get(evdev, &service_id) == 0) {
+ /* A software event device will use a software event timer
+ * adapter as well. 2 more cores required to convert to
+ * service cores.
+ */
+ required_lcore_count += 2;
+ using_services = true;
+ }
+
+ if (rte_lcore_count() < required_lcore_count) {
+ printf("Not enough cores for event_timer_adapter_test, expecting at least %u\n",
+ required_lcore_count);
+ return TEST_SKIPPED;
+ }
+
+ /* Assign lcores for various tasks */
+ test_lcore1 = rte_get_next_lcore(-1, 1, 0);
+ test_lcore2 = rte_get_next_lcore(test_lcore1, 1, 0);
+ test_lcore3 = rte_get_next_lcore(test_lcore2, 1, 0);
+ if (using_services) {
+ sw_evdev_slcore = rte_get_next_lcore(test_lcore3, 1, 0);
+ sw_adptr_slcore = rte_get_next_lcore(sw_evdev_slcore, 1, 0);
+ }
+
+ return eventdev_setup();
+}
+
+static void
+testsuite_teardown(void)
+{
+ rte_event_dev_stop(evdev);
+ rte_event_dev_close(evdev);
+}
+
+static int
+setup_adapter_service(struct rte_event_timer_adapter *adptr)
+{
+ uint32_t adapter_service_id;
+ int ret;
+
+ /* retrieve service ids */
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_service_id_get(adptr,
+ &adapter_service_id), "Failed to get event timer "
+ "adapter service id");
+ /* add a service core and start it */
+ ret = rte_service_lcore_add(sw_adptr_slcore);
+ TEST_ASSERT(ret == 0 || ret == -EALREADY,
+ "Failed to add service core");
+ ret = rte_service_lcore_start(sw_adptr_slcore);
+ TEST_ASSERT(ret == 0 || ret == -EALREADY,
+ "Failed to start service core");
+
+ /* map services to it */
+ TEST_ASSERT_SUCCESS(rte_service_map_lcore_set(adapter_service_id,
+ sw_adptr_slcore, 1),
+ "Failed to map adapter service");
+
+ /* set services to running */
+ TEST_ASSERT_SUCCESS(rte_service_runstate_set(adapter_service_id, 1),
+ "Failed to start event timer adapter service");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_port_conf_cb(uint16_t id, uint8_t event_dev_id, uint8_t *event_port_id,
+ void *conf_arg)
+{
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_dev_info info;
+ struct rte_event_port_conf *port_conf, def_port_conf = {0};
+ uint32_t started;
+ static int port_allocated;
+ static uint8_t port_id;
+ int ret;
+
+ if (port_allocated) {
+ *event_port_id = port_id;
+ return 0;
+ }
+
+ RTE_SET_USED(id);
+
+ ret = rte_event_dev_attr_get(event_dev_id, RTE_EVENT_DEV_ATTR_STARTED,
+ &started);
+ if (ret < 0)
+ return ret;
+
+ if (started)
+ rte_event_dev_stop(event_dev_id);
+
+ ret = rte_event_dev_info_get(evdev, &info);
+ if (ret < 0)
+ return ret;
+
+ devconf_set_default_sane_values(&dev_conf, &info);
+
+ port_id = dev_conf.nb_event_ports;
+ dev_conf.nb_event_ports++;
+
+ ret = rte_event_dev_configure(event_dev_id, &dev_conf);
+ if (ret < 0) {
+ if (started)
+ rte_event_dev_start(event_dev_id);
+ return ret;
+ }
+
+ if (conf_arg != NULL)
+ port_conf = conf_arg;
+ else {
+ port_conf = &def_port_conf;
+ ret = rte_event_port_default_conf_get(event_dev_id, port_id,
+ port_conf);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = rte_event_port_setup(event_dev_id, port_id, port_conf);
+ if (ret < 0)
+ return ret;
+
+ *event_port_id = port_id;
+
+ if (started)
+ rte_event_dev_start(event_dev_id);
+
+ /* Reuse this port number next time this is called */
+ port_allocated = 1;
+
+ return 0;
+}
+
+static int
+_timdev_setup(uint64_t max_tmo_ns, uint64_t bkt_tck_ns)
+{
+ struct rte_event_timer_adapter_info info;
+ struct rte_event_timer_adapter_conf config = {
+ .event_dev_id = evdev,
+ .timer_adapter_id = TEST_ADAPTER_ID,
+ .timer_tick_ns = bkt_tck_ns,
+ .max_tmo_ns = max_tmo_ns,
+ .nb_timers = MAX_TIMERS * 10,
+ .flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES,
+ };
+ uint32_t caps = 0;
+ const char *pool_name = "timdev_test_pool";
+
+ global_bkt_tck_ns = bkt_tck_ns;
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
+ "failed to get adapter capabilities");
+ if (!(caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT)) {
+ timdev = rte_event_timer_adapter_create_ext(&config,
+ test_port_conf_cb,
+ NULL);
+ setup_adapter_service(timdev);
+ using_services = true;
+ } else
+ timdev = rte_event_timer_adapter_create(&config);
+
+ TEST_ASSERT_NOT_NULL(timdev,
+ "failed to create event timer ring");
+
+ TEST_ASSERT_EQUAL(rte_event_timer_adapter_start(timdev), 0,
+ "failed to Start event timer adapter");
+
+ /* Create event timer mempool */
+ eventdev_test_mempool = rte_mempool_create(pool_name,
+ MAX_TIMERS * 2,
+ sizeof(struct rte_event_timer), /* element size*/
+ 0, /* cache size*/
+ 0, NULL, NULL, NULL, NULL,
+ rte_socket_id(), 0);
+ if (!eventdev_test_mempool) {
+ printf("ERROR creating mempool\n");
+ return TEST_FAILED;
+ }
+
+ rte_event_timer_adapter_get_info(timdev, &info);
+
+ global_info_bkt_tck_ns = info.min_resolution_ns;
+
+ return TEST_SUCCESS;
+}
+
+static int
+timdev_setup_usec(void)
+{
+ return using_services ?
+ /* Max timeout is 10,000us and bucket interval is 100us */
+ _timdev_setup(1E7, 1E5) :
+ /* Max timeout is 100us and bucket interval is 1us */
+ _timdev_setup(1E5, 1E3);
+}
+
+static int
+timdev_setup_usec_multicore(void)
+{
+ return using_services ?
+ /* Max timeout is 10,000us and bucket interval is 100us */
+ _timdev_setup(1E7, 1E5) :
+ /* Max timeout is 100us and bucket interval is 1us */
+ _timdev_setup(1E5, 1E3);
+}
+
+static int
+timdev_setup_msec(void)
+{
+ /* Max timeout is 2 mins, and bucket interval is 100 ms */
+ return _timdev_setup(180 * NSECPERSEC, NSECPERSEC / 10);
+}
+
+static int
+timdev_setup_sec(void)
+{
+ /* Max timeout is 100sec and bucket interval is 1sec */
+ return _timdev_setup(1E11, 1E9);
+}
+
+static int
+timdev_setup_sec_multicore(void)
+{
+ /* Max timeout is 100sec and bucket interval is 1sec */
+ return _timdev_setup(1E11, 1E9);
+}
+
+static void
+timdev_teardown(void)
+{
+ rte_event_timer_adapter_stop(timdev);
+ rte_event_timer_adapter_free(timdev);
+
+ rte_mempool_free(eventdev_test_mempool);
+}
+
+static inline int
+test_timer_state(void)
+{
+ struct rte_event_timer *ev_tim;
+ struct rte_event ev;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ };
+
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&ev_tim);
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+ ev_tim->timeout_ticks = CALC_TICKS(120);
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 0,
+ "Armed timer exceeding max_timeout.");
+ TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_ERROR_TOOLATE,
+ "Improper timer state set expected %d returned %d",
+ RTE_EVENT_TIMER_ERROR_TOOLATE, ev_tim->state);
+
+ ev_tim->state = RTE_EVENT_TIMER_NOT_ARMED;
+ ev_tim->timeout_ticks = CALC_TICKS(10);
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 1,
+ "Failed to arm timer with proper timeout.");
+ TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_ARMED,
+ "Improper timer state set expected %d returned %d",
+ RTE_EVENT_TIMER_ARMED, ev_tim->state);
+
+ if (!using_services)
+ rte_delay_us(20);
+ else
+ rte_delay_us(1000 + 200);
+ TEST_ASSERT_EQUAL(rte_event_dequeue_burst(evdev, 0, &ev, 1, 0), 1,
+ "Armed timer failed to trigger.");
+
+ ev_tim->state = RTE_EVENT_TIMER_NOT_ARMED;
+ ev_tim->timeout_ticks = CALC_TICKS(90);
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 1,
+ "Failed to arm timer with proper timeout.");
+ TEST_ASSERT_EQUAL(rte_event_timer_cancel_burst(timdev, &ev_tim, 1),
+ 1, "Failed to cancel armed timer");
+ TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_CANCELED,
+ "Improper timer state set expected %d returned %d",
+ RTE_EVENT_TIMER_CANCELED, ev_tim->state);
+
+ rte_mempool_put(eventdev_test_mempool, (void *)ev_tim);
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+_arm_timers(uint64_t timeout_tcks, uint64_t timers)
+{
+ uint64_t i;
+ struct rte_event_timer *ev_tim;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
+ };
+
+ for (i = 0; i < timers; i++) {
+
+ TEST_ASSERT_SUCCESS(rte_mempool_get(eventdev_test_mempool,
+ (void **)&ev_tim),
+ "mempool alloc failed");
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim,
+ 1), 1, "Failed to arm timer %d",
+ rte_errno);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+_wait_timer_triggers(uint64_t wait_sec, uint64_t arm_count,
+ uint64_t cancel_count)
+{
+ uint8_t valid_event;
+ uint64_t events = 0;
+ uint64_t wait_start, max_wait;
+ struct rte_event ev;
+
+ max_wait = rte_get_timer_hz() * wait_sec;
+ wait_start = rte_get_timer_cycles();
+ while (1) {
+ if (rte_get_timer_cycles() - wait_start > max_wait) {
+ if (events + cancel_count != arm_count)
+ TEST_ASSERT_SUCCESS(max_wait,
+ "Max time limit for timers exceeded.");
+ break;
+ }
+
+ valid_event = rte_event_dequeue_burst(evdev, 0, &ev, 1, 0);
+ if (!valid_event)
+ continue;
+
+ rte_mempool_put(eventdev_test_mempool, ev.event_ptr);
+ events++;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_arm(void)
+{
+ TEST_ASSERT_SUCCESS(_arm_timers(20, MAX_TIMERS),
+ "Failed to arm timers");
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(10, MAX_TIMERS, 0),
+ "Timer triggered count doesn't match arm count");
+ return TEST_SUCCESS;
+}
+
+static int
+_arm_wrapper(void *arg)
+{
+ RTE_SET_USED(arg);
+
+ TEST_ASSERT_SUCCESS(_arm_timers(20, MAX_TIMERS),
+ "Failed to arm timers");
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_arm_multicore(void)
+{
+
+ uint32_t lcore_1 = rte_get_next_lcore(-1, 1, 0);
+ uint32_t lcore_2 = rte_get_next_lcore(lcore_1, 1, 0);
+
+ rte_eal_remote_launch(_arm_wrapper, NULL, lcore_1);
+ rte_eal_remote_launch(_arm_wrapper, NULL, lcore_2);
+
+ rte_eal_mp_wait_lcore();
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(10, MAX_TIMERS * 2, 0),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
+#define MAX_BURST 16
+static inline int
+_arm_timers_burst(uint64_t timeout_tcks, uint64_t timers)
+{
+ uint64_t i;
+ int j;
+ struct rte_event_timer *ev_tim[MAX_BURST];
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
+ };
+
+ for (i = 0; i < timers / MAX_BURST; i++) {
+ TEST_ASSERT_SUCCESS(rte_mempool_get_bulk(
+ eventdev_test_mempool,
+ (void **)ev_tim, MAX_BURST),
+ "mempool alloc failed");
+
+ for (j = 0; j < MAX_BURST; j++) {
+ *ev_tim[j] = tim;
+ ev_tim[j]->ev.event_ptr = ev_tim[j];
+ }
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_tmo_tick_burst(timdev,
+ ev_tim, tim.timeout_ticks, MAX_BURST),
+ MAX_BURST, "Failed to arm timer %d", rte_errno);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_arm_burst(void)
+{
+ TEST_ASSERT_SUCCESS(_arm_timers_burst(20, MAX_TIMERS),
+ "Failed to arm timers");
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(10, MAX_TIMERS, 0),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
+static int
+_arm_wrapper_burst(void *arg)
+{
+ RTE_SET_USED(arg);
+
+ TEST_ASSERT_SUCCESS(_arm_timers_burst(20, MAX_TIMERS),
+ "Failed to arm timers");
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_arm_burst_multicore(void)
+{
+ rte_eal_remote_launch(_arm_wrapper_burst, NULL, test_lcore1);
+ rte_eal_remote_launch(_arm_wrapper_burst, NULL, test_lcore2);
+
+ rte_eal_mp_wait_lcore();
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(10, MAX_TIMERS * 2, 0),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_cancel(void)
+{
+ uint64_t i;
+ struct rte_event_timer *ev_tim;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(20),
+ };
+
+ for (i = 0; i < MAX_TIMERS; i++) {
+ TEST_ASSERT_SUCCESS(rte_mempool_get(eventdev_test_mempool,
+ (void **)&ev_tim),
+ "mempool alloc failed");
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim,
+ 1), 1, "Failed to arm timer %d",
+ rte_errno);
+
+ rte_delay_us(100 + (i % 5000));
+
+ TEST_ASSERT_EQUAL(rte_event_timer_cancel_burst(timdev,
+ &ev_tim, 1), 1,
+ "Failed to cancel event timer %d", rte_errno);
+ rte_mempool_put(eventdev_test_mempool, ev_tim);
+ }
+
+
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(30, MAX_TIMERS,
+ MAX_TIMERS),
+ "Timer triggered count doesn't match arm, cancel count");
+
+ return TEST_SUCCESS;
+}
+
+static int
+_cancel_producer(uint64_t timeout_tcks, uint64_t timers)
+{
+ uint64_t i;
+ struct rte_event_timer *ev_tim;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
+ };
+
+ for (i = 0; i < timers; i++) {
+ TEST_ASSERT_SUCCESS(rte_mempool_get(eventdev_test_mempool,
+ (void **)&ev_tim),
+ "mempool alloc failed");
+
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim,
+ 1), 1, "Failed to arm timer %d",
+ rte_errno);
+
+ TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_ARMED,
+ "Failed to arm event timer");
+
+ while (rte_ring_enqueue(timer_producer_ring, ev_tim) != 0)
+ ;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+_cancel_producer_burst(uint64_t timeout_tcks, uint64_t timers)
+{
+
+ uint64_t i;
+ int j, ret;
+ struct rte_event_timer *ev_tim[MAX_BURST];
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(timeout_tcks),
+ };
+ int arm_count = 0;
+
+ for (i = 0; i < timers / MAX_BURST; i++) {
+ TEST_ASSERT_SUCCESS(rte_mempool_get_bulk(
+ eventdev_test_mempool,
+ (void **)ev_tim, MAX_BURST),
+ "mempool alloc failed");
+
+ for (j = 0; j < MAX_BURST; j++) {
+ *ev_tim[j] = tim;
+ ev_tim[j]->ev.event_ptr = ev_tim[j];
+ }
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_tmo_tick_burst(timdev,
+ ev_tim, tim.timeout_ticks, MAX_BURST),
+ MAX_BURST, "Failed to arm timer %d", rte_errno);
+
+ for (j = 0; j < MAX_BURST; j++)
+ TEST_ASSERT_EQUAL(ev_tim[j]->state,
+ RTE_EVENT_TIMER_ARMED,
+ "Event timer not armed, state = %d",
+ ev_tim[j]->state);
+
+ ret = rte_ring_enqueue_bulk(timer_producer_ring,
+ (void **)ev_tim, MAX_BURST, NULL);
+ TEST_ASSERT_EQUAL(ret, MAX_BURST,
+ "Failed to enqueue event timers to ring");
+ arm_count += ret;
+ }
+
+ TEST_ASSERT_EQUAL(arm_count, MAX_TIMERS,
+ "Failed to arm expected number of event timers");
+
+ return TEST_SUCCESS;
+}
+
+static int
+_cancel_producer_wrapper(void *args)
+{
+ RTE_SET_USED(args);
+
+ return _cancel_producer(20, MAX_TIMERS);
+}
+
+static int
+_cancel_producer_burst_wrapper(void *args)
+{
+ RTE_SET_USED(args);
+
+ return _cancel_producer_burst(100, MAX_TIMERS);
+}
+
+static int
+_cancel_thread(void *args)
+{
+ RTE_SET_USED(args);
+ struct rte_event_timer *ev_tim = NULL;
+ uint64_t cancel_count = 0;
+ uint16_t ret;
+
+ while (!arm_done || rte_ring_count(timer_producer_ring) > 0) {
+ if (rte_ring_dequeue(timer_producer_ring, (void **)&ev_tim))
+ continue;
+
+ ret = rte_event_timer_cancel_burst(timdev, &ev_tim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to cancel timer");
+ rte_mempool_put(eventdev_test_mempool, (void *)ev_tim);
+ cancel_count++;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+_cancel_burst_thread(void *args)
+{
+ RTE_SET_USED(args);
+
+ int ret, i, n;
+ struct rte_event_timer *ev_tim[MAX_BURST];
+ uint64_t cancel_count = 0;
+ uint64_t dequeue_count = 0;
+
+ while (!arm_done || rte_ring_count(timer_producer_ring) > 0) {
+ n = rte_ring_dequeue_burst(timer_producer_ring,
+ (void **)ev_tim, MAX_BURST, NULL);
+ if (!n)
+ continue;
+
+ dequeue_count += n;
+
+ for (i = 0; i < n; i++)
+ TEST_ASSERT_EQUAL(ev_tim[i]->state,
+ RTE_EVENT_TIMER_ARMED,
+ "Event timer not armed, state = %d",
+ ev_tim[i]->state);
+
+ ret = rte_event_timer_cancel_burst(timdev, ev_tim, n);
+ TEST_ASSERT_EQUAL(n, ret, "Failed to cancel complete burst of "
+ "event timers");
+ rte_mempool_put_bulk(eventdev_test_mempool, (void **)ev_tim,
+ RTE_MIN(ret, MAX_BURST));
+
+ cancel_count += ret;
+ }
+
+ TEST_ASSERT_EQUAL(cancel_count, MAX_TIMERS,
+ "Failed to cancel expected number of timers: "
+ "expected = %d, cancel_count = %"PRIu64", "
+ "dequeue_count = %"PRIu64"\n", MAX_TIMERS,
+ cancel_count, dequeue_count);
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_cancel_multicore(void)
+{
+ arm_done = 0;
+ timer_producer_ring = rte_ring_create("timer_cancel_queue",
+ MAX_TIMERS * 2, rte_socket_id(), 0);
+ TEST_ASSERT_NOT_NULL(timer_producer_ring,
+ "Unable to reserve memory for ring");
+
+ rte_eal_remote_launch(_cancel_thread, NULL, test_lcore3);
+ rte_eal_remote_launch(_cancel_producer_wrapper, NULL, test_lcore1);
+ rte_eal_remote_launch(_cancel_producer_wrapper, NULL, test_lcore2);
+
+ rte_eal_wait_lcore(test_lcore1);
+ rte_eal_wait_lcore(test_lcore2);
+ arm_done = 1;
+ rte_eal_wait_lcore(test_lcore3);
+ rte_ring_free(timer_producer_ring);
+
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(30, MAX_TIMERS * 2,
+ MAX_TIMERS * 2),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_cancel_burst_multicore(void)
+{
+ arm_done = 0;
+ timer_producer_ring = rte_ring_create("timer_cancel_queue",
+ MAX_TIMERS * 2, rte_socket_id(), 0);
+ TEST_ASSERT_NOT_NULL(timer_producer_ring,
+ "Unable to reserve memory for ring");
+
+ rte_eal_remote_launch(_cancel_burst_thread, NULL, test_lcore2);
+ rte_eal_remote_launch(_cancel_producer_burst_wrapper, NULL,
+ test_lcore1);
+
+ rte_eal_wait_lcore(test_lcore1);
+ arm_done = 1;
+ rte_eal_wait_lcore(test_lcore2);
+ rte_ring_free(timer_producer_ring);
+
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(30, MAX_TIMERS,
+ MAX_TIMERS),
+ "Timer triggered count doesn't match arm count");
+
+ return TEST_SUCCESS;
+}
+
+static inline int
+test_timer_cancel_random(void)
+{
+ uint64_t i;
+ uint64_t events_canceled = 0;
+ struct rte_event_timer *ev_tim;
+ const struct rte_event_timer tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = 0,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(20),
+ };
+
+ for (i = 0; i < MAX_TIMERS; i++) {
+
+ TEST_ASSERT_SUCCESS(rte_mempool_get(eventdev_test_mempool,
+ (void **)&ev_tim),
+ "mempool alloc failed");
+ *ev_tim = tim;
+ ev_tim->ev.event_ptr = ev_tim;
+
+ TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim,
+ 1), 1, "Failed to arm timer %d",
+ rte_errno);
+
+ if (rte_rand() & 1) {
+ rte_delay_us(100 + (i % 5000));
+ TEST_ASSERT_EQUAL(rte_event_timer_cancel_burst(
+ timdev,
+ &ev_tim, 1), 1,
+ "Failed to cancel event timer %d", rte_errno);
+ rte_mempool_put(eventdev_test_mempool, ev_tim);
+ events_canceled++;
+ }
+ }
+
+ TEST_ASSERT_SUCCESS(_wait_timer_triggers(30, MAX_TIMERS,
+ events_canceled),
+ "Timer triggered count doesn't match arm, cancel count");
+
+ return TEST_SUCCESS;
+}
+
+/* Check that the adapter can be created correctly */
+static int
+adapter_create(void)
+{
+ int adapter_id = 0;
+ struct rte_event_timer_adapter *adapter, *adapter2;
+
+ struct rte_event_timer_adapter_conf conf = {
+ .event_dev_id = evdev + 1, // invalid event dev id
+ .timer_adapter_id = adapter_id,
+ .clk_src = RTE_EVENT_TIMER_ADAPTER_CPU_CLK,
+ .timer_tick_ns = NSECPERSEC / 10,
+ .max_tmo_ns = 180 * NSECPERSEC,
+ .nb_timers = MAX_TIMERS,
+ .flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES,
+ };
+ uint32_t caps = 0;
+
+ /* Test invalid conf */
+ adapter = rte_event_timer_adapter_create(&conf);
+ TEST_ASSERT_NULL(adapter, "Created adapter with invalid "
+ "event device id");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Incorrect errno value for "
+ "invalid event device id");
+
+ /* Test valid conf */
+ conf.event_dev_id = evdev;
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_caps_get(evdev, &caps),
+ "failed to get adapter capabilities");
+ if (!(caps & RTE_EVENT_TIMER_ADAPTER_CAP_INTERNAL_PORT))
+ adapter = rte_event_timer_adapter_create_ext(&conf,
+ test_port_conf_cb,
+ NULL);
+ else
+ adapter = rte_event_timer_adapter_create(&conf);
+ TEST_ASSERT_NOT_NULL(adapter, "Failed to create adapter with valid "
+ "configuration");
+
+ /* Test existing id */
+ adapter2 = rte_event_timer_adapter_create(&conf);
+ TEST_ASSERT_NULL(adapter2, "Created adapter with in-use id");
+ TEST_ASSERT(rte_errno == EEXIST, "Incorrect errno value for existing "
+ "id");
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_free(adapter),
+ "Failed to free adapter");
+
+ rte_mempool_free(eventdev_test_mempool);
+
+ return TEST_SUCCESS;
+}
+
+
+/* Test that adapter can be freed correctly. */
+static int
+adapter_free(void)
+{
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_stop(timdev),
+ "Failed to stop adapter");
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_free(timdev),
+ "Failed to free valid adapter");
+
+ /* Test free of already freed adapter */
+ TEST_ASSERT_FAIL(rte_event_timer_adapter_free(timdev),
+ "Freed adapter that was already freed");
+
+ /* Test free of null adapter */
+ timdev = NULL;
+ TEST_ASSERT_FAIL(rte_event_timer_adapter_free(timdev),
+ "Freed null adapter");
+
+ rte_mempool_free(eventdev_test_mempool);
+
+ return TEST_SUCCESS;
+}
+
+/* Test that adapter info can be retrieved and is correct. */
+static int
+adapter_get_info(void)
+{
+ struct rte_event_timer_adapter_info info;
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_get_info(timdev, &info),
+ "Failed to get adapter info");
+
+ if (using_services)
+ TEST_ASSERT_EQUAL(info.event_dev_port_id, 1,
+ "Expected port id = 1, got port id = %d",
+ info.event_dev_port_id);
+
+ return TEST_SUCCESS;
+}
+
+/* Test adapter lookup via adapter ID. */
+static int
+adapter_lookup(void)
+{
+ struct rte_event_timer_adapter *adapter;
+
+ adapter = rte_event_timer_adapter_lookup(TEST_ADAPTER_ID);
+ TEST_ASSERT_NOT_NULL(adapter, "Failed to lookup adapter");
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_start(void)
+{
+ TEST_ASSERT_SUCCESS(_timdev_setup(180 * NSECPERSEC,
+ NSECPERSEC / 10),
+ "Failed to start adapter");
+ TEST_ASSERT_EQUAL(rte_event_timer_adapter_start(timdev), -EALREADY,
+ "Timer adapter started without call to stop.");
+
+ return TEST_SUCCESS;
+}
+
+/* Test that adapter stops correctly. */
+static int
+adapter_stop(void)
+{
+ struct rte_event_timer_adapter *l_adapter = NULL;
+
+ /* Test adapter stop */
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_stop(timdev),
+ "Failed to stop event adapter");
+
+ TEST_ASSERT_FAIL(rte_event_timer_adapter_stop(l_adapter),
+ "Erroneously stopped null event adapter");
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_free(timdev),
+ "Failed to free adapter");
+
+ rte_mempool_free(eventdev_test_mempool);
+
+ return TEST_SUCCESS;
+}
+
+/* Test increment and reset of ev_enq_count stat */
+static int
+stat_inc_reset_ev_enq(void)
+{
+ int ret, i, n;
+ int num_evtims = MAX_TIMERS;
+ struct rte_event_timer *evtims[num_evtims];
+ struct rte_event evs[BATCH_SIZE];
+ struct rte_event_timer_adapter_stats stats;
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ ret = rte_mempool_get_bulk(eventdev_test_mempool, (void **)evtims,
+ num_evtims);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to get array of timer objs: ret = %d",
+ ret);
+
+ for (i = 0; i < num_evtims; i++) {
+ *evtims[i] = init_tim;
+ evtims[i]->ev.event_ptr = evtims[i];
+ }
+
+ ret = rte_event_timer_adapter_stats_get(timdev, &stats);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to get stats");
+ TEST_ASSERT_EQUAL((int)stats.ev_enq_count, 0, "Stats not clear at "
+ "startup");
+
+ /* Test with the max value for the adapter */
+ ret = rte_event_timer_arm_burst(timdev, evtims, num_evtims);
+ TEST_ASSERT_EQUAL(ret, num_evtims,
+ "Failed to arm all event timers: attempted = %d, "
+ "succeeded = %d, rte_errno = %s",
+ num_evtims, ret, rte_strerror(rte_errno));
+
+ rte_delay_ms(1000);
+
+#define MAX_TRIES num_evtims
+ int sum = 0;
+ int tries = 0;
+ bool done = false;
+ while (!done) {
+ sum += rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs,
+ RTE_DIM(evs), 10);
+ if (sum >= num_evtims || ++tries >= MAX_TRIES)
+ done = true;
+
+ rte_delay_ms(10);
+ }
+
+ TEST_ASSERT_EQUAL(sum, num_evtims, "Expected %d timer expiry events, "
+ "got %d", num_evtims, sum);
+
+ TEST_ASSERT(tries < MAX_TRIES, "Exceeded max tries");
+
+ rte_delay_ms(100);
+
+ /* Make sure the eventdev is still empty */
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs),
+ 10);
+
+ TEST_ASSERT_EQUAL(n, 0, "Dequeued unexpected number of timer expiry "
+ "events from event device");
+
+ /* Check stats again */
+ ret = rte_event_timer_adapter_stats_get(timdev, &stats);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to get stats");
+ TEST_ASSERT_EQUAL((int)stats.ev_enq_count, num_evtims,
+ "Expected enqueue stat = %d; got %d", num_evtims,
+ (int)stats.ev_enq_count);
+
+ /* Reset and check again */
+ ret = rte_event_timer_adapter_stats_reset(timdev);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to reset stats");
+
+ ret = rte_event_timer_adapter_stats_get(timdev, &stats);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to get stats");
+ TEST_ASSERT_EQUAL((int)stats.ev_enq_count, 0,
+ "Expected enqueue stat = %d; got %d", 0,
+ (int)stats.ev_enq_count);
+
+ rte_mempool_put_bulk(eventdev_test_mempool, (void **)evtims,
+ num_evtims);
+
+ return TEST_SUCCESS;
+}
+
+/* Test various cases in arming timers */
+static int
+event_timer_arm(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer_adapter *adapter = timdev;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Set up a timer */
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+
+ /* Test single timer arm succeeds */
+ ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
+ rte_strerror(rte_errno));
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ARMED, "Event timer "
+ "in incorrect state");
+
+ /* Test arm of armed timer fails */
+ ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "expected return value from "
+ "rte_event_timer_arm_burst: 0, got: %d", ret);
+ TEST_ASSERT_EQUAL(rte_errno, EALREADY, "Unexpected rte_errno value "
+ "after arming already armed timer");
+
+ /* Let timer expire */
+ rte_delay_ms(1000);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 1, "Failed to dequeue expected number of expiry "
+ "events from event device");
+
+ rte_mempool_put(eventdev_test_mempool, evtim);
+
+ return TEST_SUCCESS;
+}
+
+/* This test checks that repeated references to the same event timer in the
+ * arm request work as expected; only the first one through should succeed.
+ */
+static int
+event_timer_arm_double(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer_adapter *adapter = timdev;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Set up a timer */
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+
+ struct rte_event_timer *evtim_arr[] = {evtim, evtim};
+ ret = rte_event_timer_arm_burst(adapter, evtim_arr, RTE_DIM(evtim_arr));
+ TEST_ASSERT_EQUAL(ret, 1, "Unexpected return value from "
+ "rte_event_timer_arm_burst");
+ TEST_ASSERT_EQUAL(rte_errno, EALREADY, "Unexpected rte_errno value "
+ "after double-arm");
+
+ /* Let timer expire */
+ rte_delay_ms(600);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 1, "Dequeued incorrect number of expiry events - "
+ "expected: 1, actual: %d", n);
+
+ rte_mempool_put(eventdev_test_mempool, evtim);
+
+ return TEST_SUCCESS;
+}
+
+/* Test the timer expiry event is generated at the expected time. */
+static int
+event_timer_arm_expiry(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer_adapter *adapter = timdev;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event_timer *evtim2 = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Set up an event timer */
+ *evtim = init_tim;
+ evtim->timeout_ticks = CALC_TICKS(30), // expire in 3 secs
+ evtim->ev.event_ptr = evtim;
+
+ ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s",
+ rte_strerror(rte_errno));
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ARMED, "Event "
+ "timer in incorrect state");
+
+ rte_delay_ms(2999);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 0, "Dequeued unexpected timer expiry event");
+
+ /* Delay 100 ms to account for the adapter tick window - should let us
+ * dequeue one event
+ */
+ rte_delay_ms(100);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 1, "Dequeued incorrect number (%d) of timer "
+ "expiry events", n);
+ TEST_ASSERT_EQUAL(evs[0].event_type, RTE_EVENT_TYPE_TIMER,
+ "Dequeued unexpected type of event");
+
+ /* Check that we recover the original event timer and then free it */
+ evtim2 = evs[0].event_ptr;
+ TEST_ASSERT_EQUAL(evtim, evtim2,
+ "Failed to recover pointer to original event timer");
+ rte_mempool_put(eventdev_test_mempool, evtim2);
+
+ return TEST_SUCCESS;
+}
+
+/* Check that rearming a timer works as expected. */
+static int
+event_timer_arm_rearm(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event_timer *evtim2 = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Set up a timer */
+ *evtim = init_tim;
+ evtim->timeout_ticks = CALC_TICKS(1); // expire in 0.1 sec
+ evtim->ev.event_ptr = evtim;
+
+ /* Arm it */
+ ret = rte_event_timer_arm_burst(timdev, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
+ rte_strerror(rte_errno));
+
+ /* Add 100ms to account for the adapter tick window */
+ rte_delay_ms(100 + 100);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 1, "Failed to dequeue expected number of expiry "
+ "events from event device");
+
+ /* Recover the timer through the event that was dequeued. */
+ evtim2 = evs[0].event_ptr;
+ TEST_ASSERT_EQUAL(evtim, evtim2,
+ "Failed to recover pointer to original event timer");
+
+ /* Need to reset state in case implementation can't do it */
+ evtim2->state = RTE_EVENT_TIMER_NOT_ARMED;
+
+ /* Rearm it */
+ ret = rte_event_timer_arm_burst(timdev, &evtim2, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
+ rte_strerror(rte_errno));
+
+ /* Add 100ms to account for the adapter tick window */
+ rte_delay_ms(100 + 100);
+
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 1, "Failed to dequeue expected number of expiry "
+ "events from event device");
+
+ /* Free it */
+ evtim2 = evs[0].event_ptr;
+ TEST_ASSERT_EQUAL(evtim, evtim2,
+ "Failed to recover pointer to original event timer");
+ rte_mempool_put(eventdev_test_mempool, evtim2);
+
+ return TEST_SUCCESS;
+}
+
+/* Check that the adapter handles the max specified number of timers as
+ * expected.
+ */
+static int
+event_timer_arm_max(void)
+{
+ int ret, i, n;
+ int num_evtims = MAX_TIMERS;
+ struct rte_event_timer *evtims[num_evtims];
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ ret = rte_mempool_get_bulk(eventdev_test_mempool, (void **)evtims,
+ num_evtims);
+ TEST_ASSERT_EQUAL(ret, 0, "Failed to get array of timer objs: ret = %d",
+ ret);
+
+ for (i = 0; i < num_evtims; i++) {
+ *evtims[i] = init_tim;
+ evtims[i]->ev.event_ptr = evtims[i];
+ }
+
+ /* Test with the max value for the adapter */
+ ret = rte_event_timer_arm_burst(timdev, evtims, num_evtims);
+ TEST_ASSERT_EQUAL(ret, num_evtims,
+ "Failed to arm all event timers: attempted = %d, "
+ "succeeded = %d, rte_errno = %s",
+ num_evtims, ret, rte_strerror(rte_errno));
+
+ rte_delay_ms(1000);
+
+#define MAX_TRIES num_evtims
+ int sum = 0;
+ int tries = 0;
+ bool done = false;
+ while (!done) {
+ sum += rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs,
+ RTE_DIM(evs), 10);
+ if (sum >= num_evtims || ++tries >= MAX_TRIES)
+ done = true;
+
+ rte_delay_ms(10);
+ }
+
+ TEST_ASSERT_EQUAL(sum, num_evtims, "Expected %d timer expiry events, "
+ "got %d", num_evtims, sum);
+
+ TEST_ASSERT(tries < MAX_TRIES, "Exceeded max tries");
+
+ rte_delay_ms(100);
+
+ /* Make sure the eventdev is still empty */
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs),
+ 10);
+
+ TEST_ASSERT_EQUAL(n, 0, "Dequeued unexpected number of timer expiry "
+ "events from event device");
+
+ rte_mempool_put_bulk(eventdev_test_mempool, (void **)evtims,
+ num_evtims);
+
+ return TEST_SUCCESS;
+}
+
+/* Check that creating an event timer with incorrect event sched type fails. */
+static int
+event_timer_arm_invalid_sched_type(void)
+{
+ int ret;
+ struct rte_event_timer *evtim = NULL;
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ if (!using_services)
+ return -ENOTSUP;
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+ evtim->ev.sched_type = RTE_SCHED_TYPE_PARALLEL; // bad sched type
+
+ ret = rte_event_timer_arm_burst(timdev, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "Expected to fail timer arm with invalid "
+ "sched type, but didn't");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Unexpected rte_errno value after"
+ " arm fail with invalid queue");
+
+ rte_mempool_put(eventdev_test_mempool, &evtim);
+
+ return TEST_SUCCESS;
+}
+
+/* Check that creating an event timer with a timeout value that is too small or
+ * too big fails.
+ */
+static int
+event_timer_arm_invalid_timeout(void)
+{
+ int ret;
+ struct rte_event_timer *evtim = NULL;
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+ evtim->timeout_ticks = 0; // timeout too small
+
+ ret = rte_event_timer_arm_burst(timdev, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "Expected to fail timer arm with invalid "
+ "timeout, but didn't");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Unexpected rte_errno value after"
+ " arm fail with invalid timeout");
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ERROR_TOOEARLY,
+ "Unexpected event timer state");
+
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+ evtim->timeout_ticks = CALC_TICKS(1801); // timeout too big
+
+ ret = rte_event_timer_arm_burst(timdev, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "Expected to fail timer arm with invalid "
+ "timeout, but didn't");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Unexpected rte_errno value after"
+ " arm fail with invalid timeout");
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ERROR_TOOLATE,
+ "Unexpected event timer state");
+
+ rte_mempool_put(eventdev_test_mempool, evtim);
+
+ return TEST_SUCCESS;
+}
+
+static int
+event_timer_cancel(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer_adapter *adapter = timdev;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Check that cancelling an uninited timer fails */
+ ret = rte_event_timer_cancel_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "Succeeded unexpectedly in canceling "
+ "uninited timer");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Unexpected rte_errno value after "
+ "cancelling uninited timer");
+
+ /* Set up a timer */
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+ evtim->timeout_ticks = CALC_TICKS(30); // expire in 3 sec
+
+ /* Check that cancelling an inited but unarmed timer fails */
+ ret = rte_event_timer_cancel_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 0, "Succeeded unexpectedly in canceling "
+ "unarmed timer");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Unexpected rte_errno value after "
+ "cancelling unarmed timer");
+
+ ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
+ rte_strerror(rte_errno));
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ARMED,
+ "evtim in incorrect state");
+
+ /* Delay 1 sec */
+ rte_delay_ms(1000);
+
+ ret = rte_event_timer_cancel_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to cancel event_timer: %s\n",
+ rte_strerror(rte_errno));
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_CANCELED,
+ "evtim in incorrect state");
+
+ rte_delay_ms(3000);
+
+ /* Make sure that no expiry event was generated */
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 0, "Dequeued unexpected timer expiry event\n");
+
+ rte_mempool_put(eventdev_test_mempool, evtim);
+
+ return TEST_SUCCESS;
+}
+
+static int
+event_timer_cancel_double(void)
+{
+ uint16_t n;
+ int ret;
+ struct rte_event_timer_adapter *adapter = timdev;
+ struct rte_event_timer *evtim = NULL;
+ struct rte_event evs[BATCH_SIZE];
+ const struct rte_event_timer init_tim = {
+ .ev.op = RTE_EVENT_OP_NEW,
+ .ev.queue_id = TEST_QUEUE_ID,
+ .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+ .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+ .ev.event_type = RTE_EVENT_TYPE_TIMER,
+ .state = RTE_EVENT_TIMER_NOT_ARMED,
+ .timeout_ticks = CALC_TICKS(5), // expire in .5 sec
+ };
+
+ rte_mempool_get(eventdev_test_mempool, (void **)&evtim);
+ if (evtim == NULL) {
+ /* Failed to get an event timer object */
+ return TEST_FAILED;
+ }
+
+ /* Set up a timer */
+ *evtim = init_tim;
+ evtim->ev.event_ptr = evtim;
+ evtim->timeout_ticks = CALC_TICKS(30); // expire in 3 sec
+
+ ret = rte_event_timer_arm_burst(adapter, &evtim, 1);
+ TEST_ASSERT_EQUAL(ret, 1, "Failed to arm event timer: %s\n",
+ rte_strerror(rte_errno));
+ TEST_ASSERT_EQUAL(evtim->state, RTE_EVENT_TIMER_ARMED,
+ "timer in unexpected state");
+
+ /* Now, test that referencing the same timer twice in the same call
+ * fails
+ */
+ struct rte_event_timer *evtim_arr[] = {evtim, evtim};
+ ret = rte_event_timer_cancel_burst(adapter, evtim_arr,
+ RTE_DIM(evtim_arr));
+
+ /* Two requests to cancel same timer, only one should succeed */
+ TEST_ASSERT_EQUAL(ret, 1, "Succeeded unexpectedly in canceling timer "
+ "twice");
+
+ TEST_ASSERT_EQUAL(rte_errno, EALREADY, "Unexpected rte_errno value "
+ "after double-cancel: rte_errno = %d", rte_errno);
+
+ rte_delay_ms(3000);
+
+ /* Still make sure that no expiry event was generated */
+ n = rte_event_dequeue_burst(evdev, TEST_PORT_ID, evs, RTE_DIM(evs), 0);
+ TEST_ASSERT_EQUAL(n, 0, "Dequeued unexpected timer expiry event\n");
+
+ rte_mempool_put(eventdev_test_mempool, evtim);
+
+ return TEST_SUCCESS;
+}
+
+/* Check that event timer adapter tick resolution works as expected by testing
+ * the number of adapter ticks that occur within a particular time interval.
+ */
+static int
+adapter_tick_resolution(void)
+{
+ struct rte_event_timer_adapter_stats stats;
+ uint64_t adapter_tick_count;
+
+ /* Only run this test in the software driver case */
+ if (!using_services)
+ return -ENOTSUP;
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_stats_reset(timdev),
+ "Failed to reset stats");
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_stats_get(timdev,
+ &stats), "Failed to get adapter stats");
+ TEST_ASSERT_EQUAL(stats.adapter_tick_count, 0, "Adapter tick count "
+ "not zeroed out");
+
+ /* Delay 1 second; should let at least 10 ticks occur with the default
+ * adapter configuration used by this test.
+ */
+ rte_delay_ms(1000);
+
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_stats_get(timdev,
+ &stats), "Failed to get adapter stats");
+
+ adapter_tick_count = stats.adapter_tick_count;
+ TEST_ASSERT(adapter_tick_count >= 10 && adapter_tick_count <= 12,
+ "Expected 10-12 adapter ticks, got %"PRIu64"\n",
+ adapter_tick_count);
+
+ return TEST_SUCCESS;
+}
+
+static int
+adapter_create_max(void)
+{
+ int i;
+ uint32_t svc_start_count, svc_end_count;
+ struct rte_event_timer_adapter *adapters[
+ RTE_EVENT_TIMER_ADAPTER_NUM_MAX + 1];
+
+ struct rte_event_timer_adapter_conf conf = {
+ .event_dev_id = evdev,
+ // timer_adapter_id set in loop
+ .clk_src = RTE_EVENT_TIMER_ADAPTER_CPU_CLK,
+ .timer_tick_ns = NSECPERSEC / 10,
+ .max_tmo_ns = 180 * NSECPERSEC,
+ .nb_timers = MAX_TIMERS,
+ .flags = RTE_EVENT_TIMER_ADAPTER_F_ADJUST_RES,
+ };
+
+ if (!using_services)
+ return -ENOTSUP;
+
+ svc_start_count = rte_service_get_count();
+
+ /* This test expects that there are sufficient service IDs available
+ * to be allocated. I.e., RTE_EVENT_TIMER_ADAPTER_NUM_MAX may need to
+ * be less than RTE_SERVICE_NUM_MAX if anything else uses a service
+ * (the SW event device, for example).
+ */
+ for (i = 0; i < RTE_EVENT_TIMER_ADAPTER_NUM_MAX; i++) {
+ conf.timer_adapter_id = i;
+ adapters[i] = rte_event_timer_adapter_create_ext(&conf,
+ test_port_conf_cb, NULL);
+ TEST_ASSERT_NOT_NULL(adapters[i], "Failed to create adapter "
+ "%d", i);
+ }
+
+ conf.timer_adapter_id = i;
+ adapters[i] = rte_event_timer_adapter_create(&conf);
+ TEST_ASSERT_NULL(adapters[i], "Created too many adapters");
+
+ /* Check that at least RTE_EVENT_TIMER_ADAPTER_NUM_MAX services
+ * have been created
+ */
+ svc_end_count = rte_service_get_count();
+ TEST_ASSERT_EQUAL(svc_end_count - svc_start_count,
+ RTE_EVENT_TIMER_ADAPTER_NUM_MAX,
+ "Failed to create expected number of services");
+
+ for (i = 0; i < RTE_EVENT_TIMER_ADAPTER_NUM_MAX; i++)
+ TEST_ASSERT_SUCCESS(rte_event_timer_adapter_free(adapters[i]),
+ "Failed to free adapter %d", i);
+
+ /* Check that service count is back to where it was at start */
+ svc_end_count = rte_service_get_count();
+ TEST_ASSERT_EQUAL(svc_start_count, svc_end_count, "Failed to release "
+ "correct number of services");
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite event_timer_adptr_functional_testsuite = {
+ .suite_name = "event timer functional test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(timdev_setup_usec, timdev_teardown,
+ test_timer_state),
+ TEST_CASE_ST(timdev_setup_usec, timdev_teardown,
+ test_timer_arm),
+ TEST_CASE_ST(timdev_setup_usec, timdev_teardown,
+ test_timer_arm_burst),
+ TEST_CASE_ST(timdev_setup_sec, timdev_teardown,
+ test_timer_cancel),
+ TEST_CASE_ST(timdev_setup_sec, timdev_teardown,
+ test_timer_cancel_random),
+ TEST_CASE_ST(timdev_setup_usec_multicore, timdev_teardown,
+ test_timer_arm_multicore),
+ TEST_CASE_ST(timdev_setup_usec_multicore, timdev_teardown,
+ test_timer_arm_burst_multicore),
+ TEST_CASE_ST(timdev_setup_sec_multicore, timdev_teardown,
+ test_timer_cancel_multicore),
+ TEST_CASE_ST(timdev_setup_sec_multicore, timdev_teardown,
+ test_timer_cancel_burst_multicore),
+ TEST_CASE(adapter_create),
+ TEST_CASE_ST(timdev_setup_msec, NULL, adapter_free),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ adapter_get_info),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ adapter_lookup),
+ TEST_CASE_ST(NULL, timdev_teardown,
+ adapter_start),
+ TEST_CASE_ST(timdev_setup_msec, NULL,
+ adapter_stop),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ stat_inc_reset_ev_enq),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_double),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_expiry),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_rearm),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_max),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_invalid_sched_type),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_arm_invalid_timeout),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_cancel),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ event_timer_cancel_double),
+ TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+ adapter_tick_resolution),
+ TEST_CASE(adapter_create_max),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_event_timer_adapter_func(void)
+{
+ return unit_test_suite_runner(&event_timer_adptr_functional_testsuite);
+}
+
+REGISTER_TEST_COMMAND(event_timer_adapter_test, test_event_timer_adapter_func);
diff --git a/src/spdk/dpdk/app/test/test_eventdev.c b/src/spdk/dpdk/app/test/test_eventdev.c
new file mode 100644
index 000000000..43ccb1ce9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_eventdev.c
@@ -0,0 +1,1039 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Cavium, Inc
+ */
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_eventdev.h>
+#include <rte_dev.h>
+#include <rte_bus_vdev.h>
+
+#include "test.h"
+
+#define TEST_DEV_ID 0
+
+static int
+testsuite_setup(void)
+{
+ RTE_BUILD_BUG_ON(sizeof(struct rte_event) != 16);
+ uint8_t count;
+ count = rte_event_dev_count();
+ if (!count) {
+ printf("Failed to find a valid event device,"
+ " testing with event_skeleton device\n");
+ return rte_vdev_init("event_skeleton", NULL);
+ }
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+}
+
+static int
+test_eventdev_count(void)
+{
+ uint8_t count;
+ count = rte_event_dev_count();
+ TEST_ASSERT(count > 0, "Invalid eventdev count %" PRIu8, count);
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_get_dev_id(void)
+{
+ int ret;
+ ret = rte_event_dev_get_dev_id("not_a_valid_eventdev_driver");
+ TEST_ASSERT_FAIL(ret, "Expected <0 for invalid dev name ret=%d", ret);
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_socket_id(void)
+{
+ int socket_id;
+ socket_id = rte_event_dev_socket_id(TEST_DEV_ID);
+ TEST_ASSERT(socket_id != -EINVAL, "Failed to get socket_id %d",
+ socket_id);
+ socket_id = rte_event_dev_socket_id(RTE_EVENT_MAX_DEVS);
+ TEST_ASSERT(socket_id == -EINVAL, "Expected -EINVAL %d", socket_id);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_info_get(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+ ret = rte_event_dev_info_get(TEST_DEV_ID, NULL);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+ TEST_ASSERT(info.max_event_ports > 0,
+ "Not enough event ports %d", info.max_event_ports);
+ TEST_ASSERT(info.max_event_queues > 0,
+ "Not enough event queues %d", info.max_event_queues);
+ return TEST_SUCCESS;
+}
+
+static inline void
+devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
+ dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
+ dev_conf->nb_event_ports = info->max_event_ports;
+ dev_conf->nb_event_queues = info->max_event_queues;
+ dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
+ dev_conf->nb_event_port_dequeue_depth =
+ info->max_event_port_dequeue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth;
+ dev_conf->nb_events_limit =
+ info->max_num_events;
+}
+
+static int
+test_ethdev_config_run(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info,
+ void (*fn)(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info))
+{
+ devconf_set_default_sane_values(dev_conf, info);
+ fn(dev_conf, info);
+ return rte_event_dev_configure(TEST_DEV_ID, dev_conf);
+}
+
+static void
+max_dequeue_limit(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->dequeue_timeout_ns = info->max_dequeue_timeout_ns + 1;
+}
+
+static void
+max_events_limit(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_events_limit = info->max_num_events + 1;
+}
+
+static void
+max_event_ports(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_event_ports = info->max_event_ports + 1;
+}
+
+static void
+max_event_queues(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_event_queues = info->max_event_queues + 1;
+}
+
+static void
+max_event_queue_flows(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_event_queue_flows = info->max_event_queue_flows + 1;
+}
+
+static void
+max_event_port_dequeue_depth(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_event_port_dequeue_depth =
+ info->max_event_port_dequeue_depth + 1;
+}
+
+static void
+max_event_port_enqueue_depth(struct rte_event_dev_config *dev_conf,
+ struct rte_event_dev_info *info)
+{
+ dev_conf->nb_event_port_enqueue_depth =
+ info->max_event_port_enqueue_depth + 1;
+}
+
+
+static int
+test_eventdev_configure(void)
+{
+ int ret;
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_dev_info info;
+ ret = rte_event_dev_configure(TEST_DEV_ID, NULL);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ /* Check limits */
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info, max_dequeue_limit),
+ "Config negative test failed");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info, max_events_limit),
+ "Config negative test failed");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info, max_event_ports),
+ "Config negative test failed");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info, max_event_queues),
+ "Config negative test failed");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info, max_event_queue_flows),
+ "Config negative test failed");
+
+ if (info.event_dev_cap & RTE_EVENT_DEV_CAP_BURST_MODE) {
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info,
+ max_event_port_dequeue_depth),
+ "Config negative test failed");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ test_ethdev_config_run(&dev_conf, &info,
+ max_event_port_enqueue_depth),
+ "Config negative test failed");
+ }
+
+ /* Positive case */
+ devconf_set_default_sane_values(&dev_conf, &info);
+ ret = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
+
+ /* re-configure */
+ devconf_set_default_sane_values(&dev_conf, &info);
+ dev_conf.nb_event_ports = RTE_MAX(info.max_event_ports/2, 1);
+ dev_conf.nb_event_queues = RTE_MAX(info.max_event_queues/2, 1);
+ ret = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to re configure eventdev");
+
+ /* re-configure back to max_event_queues and max_event_ports */
+ devconf_set_default_sane_values(&dev_conf, &info);
+ ret = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to re-configure eventdev");
+
+ return TEST_SUCCESS;
+
+}
+
+static int
+eventdev_configure_setup(void)
+{
+ int ret;
+ struct rte_event_dev_config dev_conf;
+ struct rte_event_dev_info info;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+ devconf_set_default_sane_values(&dev_conf, &info);
+ ret = rte_event_dev_configure(TEST_DEV_ID, &dev_conf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_default_conf_get(void)
+{
+ int i, ret;
+ struct rte_event_queue_conf qconf;
+
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, NULL);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, i,
+ &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue%d info", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_setup(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_queue_conf qconf;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ /* Negative cases */
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue0 info");
+ qconf.event_queue_cfg = RTE_EVENT_QUEUE_CFG_ALL_TYPES;
+ qconf.nb_atomic_flows = info.max_event_queue_flows + 1;
+ ret = rte_event_queue_setup(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ qconf.nb_atomic_flows = info.max_event_queue_flows;
+ qconf.schedule_type = RTE_SCHED_TYPE_ORDERED;
+ qconf.nb_atomic_order_sequences = info.max_event_queue_flows + 1;
+ ret = rte_event_queue_setup(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ ret = rte_event_queue_setup(TEST_DEV_ID, info.max_event_queues,
+ &qconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ /* Positive case */
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue0 info");
+ ret = rte_event_queue_setup(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue0");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_count(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ TEST_ASSERT_EQUAL(queue_count, info.max_event_queues,
+ "Wrong queue count");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_attr_priority(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_queue_conf qconf;
+ uint8_t priority;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, i,
+ &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue%d def conf", i);
+ qconf.priority = i % RTE_EVENT_DEV_PRIORITY_LOWEST;
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ for (i = 0; i < (int)queue_count; i++) {
+ uint32_t tmp;
+ TEST_ASSERT_SUCCESS(rte_event_queue_attr_get(TEST_DEV_ID, i,
+ RTE_EVENT_QUEUE_ATTR_PRIORITY, &tmp),
+ "Queue priority get failed");
+ priority = tmp;
+
+ if (info.event_dev_cap & RTE_EVENT_DEV_CAP_QUEUE_QOS)
+ TEST_ASSERT_EQUAL(priority,
+ i % RTE_EVENT_DEV_PRIORITY_LOWEST,
+ "Wrong priority value for queue%d", i);
+ else
+ TEST_ASSERT_EQUAL(priority,
+ RTE_EVENT_DEV_PRIORITY_NORMAL,
+ "Wrong priority value for queue%d", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_attr_nb_atomic_flows(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_queue_conf qconf;
+ uint32_t nb_atomic_flows;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue 0's def conf");
+
+ if (qconf.nb_atomic_flows == 0)
+ /* Assume PMD doesn't support atomic flows, return early */
+ return -ENOTSUP;
+
+ qconf.schedule_type = RTE_SCHED_TYPE_ATOMIC;
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ for (i = 0; i < (int)queue_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_event_queue_attr_get(TEST_DEV_ID, i,
+ RTE_EVENT_QUEUE_ATTR_NB_ATOMIC_FLOWS,
+ &nb_atomic_flows),
+ "Queue nb_atomic_flows get failed");
+
+ TEST_ASSERT_EQUAL(nb_atomic_flows, qconf.nb_atomic_flows,
+ "Wrong atomic flows value for queue%d", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_attr_nb_atomic_order_sequences(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_queue_conf qconf;
+ uint32_t nb_atomic_order_sequences;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue 0's def conf");
+
+ if (qconf.nb_atomic_order_sequences == 0)
+ /* Assume PMD doesn't support reordering */
+ return -ENOTSUP;
+
+ qconf.schedule_type = RTE_SCHED_TYPE_ORDERED;
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ for (i = 0; i < (int)queue_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_event_queue_attr_get(TEST_DEV_ID, i,
+ RTE_EVENT_QUEUE_ATTR_NB_ATOMIC_ORDER_SEQUENCES,
+ &nb_atomic_order_sequences),
+ "Queue nb_atomic_order_sequencess get failed");
+
+ TEST_ASSERT_EQUAL(nb_atomic_order_sequences,
+ qconf.nb_atomic_order_sequences,
+ "Wrong atomic order sequences value for queue%d",
+ i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_queue_attr_event_queue_cfg(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_queue_conf qconf;
+ uint32_t event_queue_cfg;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+
+ ret = rte_event_queue_default_conf_get(TEST_DEV_ID, 0, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get queue0 def conf");
+
+ qconf.event_queue_cfg = RTE_EVENT_QUEUE_CFG_SINGLE_LINK;
+
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, &qconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ for (i = 0; i < (int)queue_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_event_queue_attr_get(TEST_DEV_ID, i,
+ RTE_EVENT_QUEUE_ATTR_EVENT_QUEUE_CFG,
+ &event_queue_cfg),
+ "Queue event_queue_cfg get failed");
+
+ TEST_ASSERT_EQUAL(event_queue_cfg, qconf.event_queue_cfg,
+ "Wrong event_queue_cfg value for queue%d",
+ i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_default_conf_get(void)
+{
+ int i, ret;
+ struct rte_event_port_conf pconf;
+
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, NULL);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ uint32_t port_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count), "Port count get failed");
+
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID,
+ port_count + 1, NULL);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ for (i = 0; i < (int)port_count; i++) {
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, i,
+ &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port%d info", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_setup(void)
+{
+ int i, ret;
+ struct rte_event_dev_info info;
+ struct rte_event_port_conf pconf;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ /* Negative cases */
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port0 info");
+ pconf.new_event_threshold = info.max_num_events + 1;
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ pconf.new_event_threshold = info.max_num_events;
+ pconf.dequeue_depth = info.max_event_port_dequeue_depth + 1;
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ pconf.dequeue_depth = info.max_event_port_dequeue_depth;
+ pconf.enqueue_depth = info.max_event_port_enqueue_depth + 1;
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ if (!(info.event_dev_cap &
+ RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE)) {
+ pconf.enqueue_depth = info.max_event_port_enqueue_depth;
+ pconf.disable_implicit_release = 1;
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+ pconf.disable_implicit_release = 0;
+ }
+
+ ret = rte_event_port_setup(TEST_DEV_ID, info.max_event_ports,
+ &pconf);
+ TEST_ASSERT(ret == -EINVAL, "Expected -EINVAL, %d", ret);
+
+ /* Positive case */
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port0 info");
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port0");
+
+ uint32_t port_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count), "Port count get failed");
+
+ for (i = 0; i < (int)port_count; i++) {
+ ret = rte_event_port_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port%d", i);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_attr_dequeue_depth(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+ struct rte_event_port_conf pconf;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port0 info");
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port0");
+
+ uint32_t value;
+ TEST_ASSERT_EQUAL(rte_event_port_attr_get(TEST_DEV_ID, 0,
+ RTE_EVENT_PORT_ATTR_DEQ_DEPTH, &value),
+ 0, "Call to get port dequeue depth failed");
+ TEST_ASSERT_EQUAL(value, pconf.dequeue_depth,
+ "Wrong port dequeue depth");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_attr_enqueue_depth(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+ struct rte_event_port_conf pconf;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port0 info");
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port0");
+
+ uint32_t value;
+ TEST_ASSERT_EQUAL(rte_event_port_attr_get(TEST_DEV_ID, 0,
+ RTE_EVENT_PORT_ATTR_ENQ_DEPTH, &value),
+ 0, "Call to get port enqueue depth failed");
+ TEST_ASSERT_EQUAL(value, pconf.enqueue_depth,
+ "Wrong port enqueue depth");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_attr_new_event_threshold(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+ struct rte_event_port_conf pconf;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ ret = rte_event_port_default_conf_get(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get port0 info");
+ ret = rte_event_port_setup(TEST_DEV_ID, 0, &pconf);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port0");
+
+ uint32_t value;
+ TEST_ASSERT_EQUAL(rte_event_port_attr_get(TEST_DEV_ID, 0,
+ RTE_EVENT_PORT_ATTR_NEW_EVENT_THRESHOLD, &value),
+ 0, "Call to get port new event threshold failed");
+ TEST_ASSERT_EQUAL((int32_t) value, pconf.new_event_threshold,
+ "Wrong port new event threshold");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_port_count(void)
+{
+ int ret;
+ struct rte_event_dev_info info;
+
+ ret = rte_event_dev_info_get(TEST_DEV_ID, &info);
+ TEST_ASSERT_SUCCESS(ret, "Failed to get event dev info");
+
+ uint32_t port_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count), "Port count get failed");
+ TEST_ASSERT_EQUAL(port_count, info.max_event_ports, "Wrong port count");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_timeout_ticks(void)
+{
+ int ret;
+ uint64_t timeout_ticks;
+
+ ret = rte_event_dequeue_timeout_ticks(TEST_DEV_ID, 100, &timeout_ticks);
+ if (ret != -ENOTSUP)
+ TEST_ASSERT_SUCCESS(ret, "Fail to get timeout_ticks");
+
+ return ret;
+}
+
+
+static int
+test_eventdev_start_stop(void)
+{
+ int i, ret;
+
+ ret = eventdev_configure_setup();
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ uint32_t port_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count), "Port count get failed");
+
+ for (i = 0; i < (int)port_count; i++) {
+ ret = rte_event_port_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port%d", i);
+ }
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret == (int)queue_count, "Failed to link port, device %d",
+ TEST_DEV_ID);
+
+ ret = rte_event_dev_start(TEST_DEV_ID);
+ TEST_ASSERT_SUCCESS(ret, "Failed to start device%d", TEST_DEV_ID);
+
+ rte_event_dev_stop(TEST_DEV_ID);
+ return TEST_SUCCESS;
+}
+
+
+static int
+eventdev_setup_device(void)
+{
+ int i, ret;
+
+ ret = eventdev_configure_setup();
+ TEST_ASSERT_SUCCESS(ret, "Failed to configure eventdev");
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ for (i = 0; i < (int)queue_count; i++) {
+ ret = rte_event_queue_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup queue%d", i);
+ }
+
+ uint32_t port_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_PORT_COUNT,
+ &port_count), "Port count get failed");
+
+ for (i = 0; i < (int)port_count; i++) {
+ ret = rte_event_port_setup(TEST_DEV_ID, i, NULL);
+ TEST_ASSERT_SUCCESS(ret, "Failed to setup port%d", i);
+ }
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret == (int)queue_count, "Failed to link port, device %d",
+ TEST_DEV_ID);
+
+ ret = rte_event_dev_start(TEST_DEV_ID);
+ TEST_ASSERT_SUCCESS(ret, "Failed to start device%d", TEST_DEV_ID);
+
+ return TEST_SUCCESS;
+}
+
+static void
+eventdev_stop_device(void)
+{
+ rte_event_dev_stop(TEST_DEV_ID);
+}
+
+static int
+test_eventdev_link(void)
+{
+ int ret, nb_queues, i;
+ uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t priorities[RTE_EVENT_MAX_QUEUES_PER_DEV];
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret >= 0, "Failed to link with NULL device%d",
+ TEST_DEV_ID);
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ nb_queues = queue_count;
+ for (i = 0; i < nb_queues; i++) {
+ queues[i] = i;
+ priorities[i] = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ }
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, queues,
+ priorities, nb_queues);
+ TEST_ASSERT(ret == nb_queues, "Failed to link(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_unlink(void)
+{
+ int ret, nb_queues, i;
+ uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV];
+
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, NULL, 0);
+ TEST_ASSERT(ret >= 0, "Failed to unlink with NULL device%d",
+ TEST_DEV_ID);
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ nb_queues = queue_count;
+ for (i = 0; i < nb_queues; i++)
+ queues[i] = i;
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret >= 0, "Failed to link with NULL device%d",
+ TEST_DEV_ID);
+
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, queues, nb_queues);
+ TEST_ASSERT(ret == nb_queues, "Failed to unlink(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_link_get(void)
+{
+ int ret, i;
+ uint8_t queues[RTE_EVENT_MAX_QUEUES_PER_DEV];
+ uint8_t priorities[RTE_EVENT_MAX_QUEUES_PER_DEV];
+
+ /* link all queues */
+ ret = rte_event_port_link(TEST_DEV_ID, 0, NULL, NULL, 0);
+ TEST_ASSERT(ret >= 0, "Failed to link with NULL device%d",
+ TEST_DEV_ID);
+
+ uint32_t queue_count;
+ TEST_ASSERT_SUCCESS(rte_event_dev_attr_get(TEST_DEV_ID,
+ RTE_EVENT_DEV_ATTR_QUEUE_COUNT, &queue_count),
+ "Queue count get failed");
+ const int nb_queues = queue_count;
+ for (i = 0; i < nb_queues; i++)
+ queues[i] = i;
+
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, queues, nb_queues);
+ TEST_ASSERT(ret == nb_queues, "Failed to unlink(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+
+ ret = rte_event_port_links_get(TEST_DEV_ID, 0, queues, priorities);
+ TEST_ASSERT(ret == 0, "(%d)Wrong link get=%d", TEST_DEV_ID, ret);
+
+ /* link all queues and get the links */
+ for (i = 0; i < nb_queues; i++) {
+ queues[i] = i;
+ priorities[i] = RTE_EVENT_DEV_PRIORITY_NORMAL;
+ }
+ ret = rte_event_port_link(TEST_DEV_ID, 0, queues, priorities,
+ nb_queues);
+ TEST_ASSERT(ret == nb_queues, "Failed to link(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ ret = rte_event_port_links_get(TEST_DEV_ID, 0, queues, priorities);
+ TEST_ASSERT(ret == nb_queues, "(%d)Wrong link get ret=%d expected=%d",
+ TEST_DEV_ID, ret, nb_queues);
+ /* unlink all*/
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, NULL, 0);
+ TEST_ASSERT(ret == nb_queues, "Failed to unlink(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ /* link just one queue */
+ queues[0] = 0;
+ priorities[0] = RTE_EVENT_DEV_PRIORITY_NORMAL;
+
+ ret = rte_event_port_link(TEST_DEV_ID, 0, queues, priorities, 1);
+ TEST_ASSERT(ret == 1, "Failed to link(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ ret = rte_event_port_links_get(TEST_DEV_ID, 0, queues, priorities);
+ TEST_ASSERT(ret == 1, "(%d)Wrong link get ret=%d expected=%d",
+ TEST_DEV_ID, ret, 1);
+ /* unlink the queue */
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, NULL, 0);
+ TEST_ASSERT(ret == 1, "Failed to unlink(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+
+ /* 4links and 2 unlinks */
+ if (nb_queues >= 4) {
+ for (i = 0; i < 4; i++) {
+ queues[i] = i;
+ priorities[i] = 0x40;
+ }
+ ret = rte_event_port_link(TEST_DEV_ID, 0, queues, priorities,
+ 4);
+ TEST_ASSERT(ret == 4, "Failed to link(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+
+ for (i = 0; i < 2; i++)
+ queues[i] = i;
+
+ ret = rte_event_port_unlink(TEST_DEV_ID, 0, queues, 2);
+ TEST_ASSERT(ret == 2, "Failed to unlink(device%d) ret=%d",
+ TEST_DEV_ID, ret);
+ ret = rte_event_port_links_get(TEST_DEV_ID, 0,
+ queues, priorities);
+ TEST_ASSERT(ret == 2, "(%d)Wrong link get ret=%d expected=%d",
+ TEST_DEV_ID, ret, 2);
+ TEST_ASSERT(queues[0] == 2, "ret=%d expected=%d", ret, 2);
+ TEST_ASSERT(priorities[0] == 0x40, "ret=%d expected=%d",
+ ret, 0x40);
+ TEST_ASSERT(queues[1] == 3, "ret=%d expected=%d", ret, 3);
+ TEST_ASSERT(priorities[1] == 0x40, "ret=%d expected=%d",
+ ret, 0x40);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_eventdev_close(void)
+{
+ rte_event_dev_stop(TEST_DEV_ID);
+ return rte_event_dev_close(TEST_DEV_ID);
+}
+
+static struct unit_test_suite eventdev_common_testsuite = {
+ .suite_name = "eventdev common code unit test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_count),
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_get_dev_id),
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_socket_id),
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_info_get),
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_configure),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_default_conf_get),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_setup),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_count),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_attr_priority),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_attr_nb_atomic_flows),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_attr_nb_atomic_order_sequences),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_queue_attr_event_queue_cfg),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_default_conf_get),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_setup),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_attr_dequeue_depth),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_attr_enqueue_depth),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_attr_new_event_threshold),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_port_count),
+ TEST_CASE_ST(eventdev_configure_setup, NULL,
+ test_eventdev_timeout_ticks),
+ TEST_CASE_ST(NULL, NULL,
+ test_eventdev_start_stop),
+ TEST_CASE_ST(eventdev_setup_device, eventdev_stop_device,
+ test_eventdev_link),
+ TEST_CASE_ST(eventdev_setup_device, eventdev_stop_device,
+ test_eventdev_unlink),
+ TEST_CASE_ST(eventdev_setup_device, eventdev_stop_device,
+ test_eventdev_link_get),
+ TEST_CASE_ST(eventdev_setup_device, NULL,
+ test_eventdev_close),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_eventdev_common(void)
+{
+ return unit_test_suite_runner(&eventdev_common_testsuite);
+}
+
+static int
+test_eventdev_selftest_impl(const char *pmd, const char *opts)
+{
+ int ret = 0;
+
+ if (rte_event_dev_get_dev_id(pmd) == -ENODEV)
+ ret = rte_vdev_init(pmd, opts);
+ if (ret)
+ return TEST_SKIPPED;
+
+ return rte_event_dev_selftest(rte_event_dev_get_dev_id(pmd));
+}
+
+static int
+test_eventdev_selftest_sw(void)
+{
+ return test_eventdev_selftest_impl("event_sw", "");
+}
+
+static int
+test_eventdev_selftest_octeontx(void)
+{
+ return test_eventdev_selftest_impl("event_octeontx", "");
+}
+
+static int
+test_eventdev_selftest_octeontx2(void)
+{
+ return test_eventdev_selftest_impl("event_octeontx2", "");
+}
+
+static int
+test_eventdev_selftest_dpaa2(void)
+{
+ return test_eventdev_selftest_impl("event_dpaa2", "");
+}
+
+REGISTER_TEST_COMMAND(eventdev_common_autotest, test_eventdev_common);
+REGISTER_TEST_COMMAND(eventdev_selftest_sw, test_eventdev_selftest_sw);
+REGISTER_TEST_COMMAND(eventdev_selftest_octeontx,
+ test_eventdev_selftest_octeontx);
+REGISTER_TEST_COMMAND(eventdev_selftest_octeontx2,
+ test_eventdev_selftest_octeontx2);
+REGISTER_TEST_COMMAND(eventdev_selftest_dpaa2, test_eventdev_selftest_dpaa2);
diff --git a/src/spdk/dpdk/app/test/test_external_mem.c b/src/spdk/dpdk/app/test/test_external_mem.c
new file mode 100644
index 000000000..7eb81f644
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_external_mem.c
@@ -0,0 +1,576 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_ring.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+#define EXTERNAL_MEM_SZ (RTE_PGSIZE_4K << 10) /* 4M of data */
+
+static int
+check_mem(void *addr, rte_iova_t *iova, size_t pgsz, int n_pages)
+{
+ int i;
+
+ /* check that we can get this memory from EAL now */
+ for (i = 0; i < n_pages; i++) {
+ const struct rte_memseg_list *msl;
+ const struct rte_memseg *ms;
+ void *cur = RTE_PTR_ADD(addr, pgsz * i);
+ rte_iova_t expected_iova;
+
+ msl = rte_mem_virt2memseg_list(cur);
+ if (!msl->external) {
+ printf("%s():%i: Memseg list is not marked as external\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ ms = rte_mem_virt2memseg(cur, msl);
+ if (ms == NULL) {
+ printf("%s():%i: Failed to retrieve memseg for external mem\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (ms->addr != cur) {
+ printf("%s():%i: VA mismatch\n", __func__, __LINE__);
+ return -1;
+ }
+ expected_iova = (iova == NULL) ? RTE_BAD_IOVA : iova[i];
+ if (ms->iova != expected_iova) {
+ printf("%s():%i: IOVA mismatch\n", __func__, __LINE__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+test_malloc_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
+ int n_pages)
+{
+ static const char * const names[] = {
+ NULL, /* NULL name */
+ "", /* empty name */
+ "this heap name is definitely way too long to be valid"
+ };
+ const char *valid_name = "valid heap name";
+ unsigned int i;
+
+ /* check invalid name handling */
+ for (i = 0; i < RTE_DIM(names); i++) {
+ const char *name = names[i];
+
+ /* these calls may fail for other reasons, so check errno */
+ if (rte_malloc_heap_create(name) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Created heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_destroy(name) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Destroyed heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_get_socket(name) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Found socket for heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_add(name, addr, len,
+ NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Added memory to heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_remove(name, addr, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Removed memory from heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_attach(name, addr, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Attached memory to heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_detach(name, addr, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Detached memory from heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ }
+
+ /* do same as above, but with a valid heap name */
+
+ /* skip create call */
+ if (rte_malloc_heap_destroy(valid_name) >= 0 || rte_errno != ENOENT) {
+ printf("%s():%i: Destroyed heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_get_socket(valid_name) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Found socket for heap with invalid name\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* these calls may fail for other reasons, so check errno */
+ if (rte_malloc_heap_memory_add(valid_name, addr, len,
+ NULL, 0, pgsz) >= 0 || rte_errno != ENOENT) {
+ printf("%s():%i: Added memory to non-existent heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_remove(valid_name, addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Removed memory from non-existent heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_attach(valid_name, addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Attached memory to non-existent heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_detach(valid_name, addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Detached memory from non-existent heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* create a valid heap but test other invalid parameters */
+ if (rte_malloc_heap_create(valid_name) != 0) {
+ printf("%s():%i: Failed to create valid heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* zero length */
+ if (rte_malloc_heap_memory_add(valid_name, addr, 0,
+ NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Added memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_remove(valid_name, addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Removed memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_attach(valid_name, addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Attached memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_detach(valid_name, addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Detached memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* zero address */
+ if (rte_malloc_heap_memory_add(valid_name, NULL, len,
+ NULL, 0, pgsz) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Added memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_remove(valid_name, NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Removed memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ if (rte_malloc_heap_memory_attach(valid_name, NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Attached memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_detach(valid_name, NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Detached memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* the following tests are only valid if IOVA table is not NULL */
+ if (iova != NULL) {
+ /* wrong page count */
+ if (rte_malloc_heap_memory_add(valid_name, addr, len,
+ iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Added memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_add(valid_name, addr, len,
+ iova, n_pages - 1, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Added memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_memory_add(valid_name, addr, len,
+ iova, n_pages + 1, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Added memory with invalid parameters\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ }
+
+ /* tests passed, destroy heap */
+ if (rte_malloc_heap_destroy(valid_name) != 0) {
+ printf("%s():%i: Failed to destroy valid heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ return 0;
+fail:
+ rte_malloc_heap_destroy(valid_name);
+ return -1;
+}
+
+static int
+test_malloc_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
+ int n_pages)
+{
+ const char *heap_name = "heap";
+ void *ptr = NULL;
+ int socket_id;
+ const struct rte_memzone *mz = NULL, *contig_mz = NULL;
+
+ /* create heap */
+ if (rte_malloc_heap_create(heap_name) != 0) {
+ printf("%s():%i: Failed to create malloc heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* get socket ID corresponding to this heap */
+ socket_id = rte_malloc_heap_get_socket(heap_name);
+ if (socket_id < 0) {
+ printf("%s():%i: cannot find socket for external heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* heap is empty, so any allocation should fail */
+ ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
+ if (ptr != NULL) {
+ printf("%s():%i: Allocated from empty heap\n", __func__,
+ __LINE__);
+ goto fail;
+ }
+
+ /* add memory to heap */
+ if (rte_malloc_heap_memory_add(heap_name, addr, len,
+ iova, n_pages, pgsz) != 0) {
+ printf("%s():%i: Failed to add memory to heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* check if memory is accessible from EAL */
+ if (check_mem(addr, iova, pgsz, n_pages) < 0)
+ goto fail;
+
+ /* allocate - this now should succeed */
+ ptr = rte_malloc_socket("EXTMEM", 64, 0, socket_id);
+ if (ptr == NULL) {
+ printf("%s():%i: Failed to allocate from external heap\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* check if address is in expected range */
+ if (ptr < addr || ptr >= RTE_PTR_ADD(addr, len)) {
+ printf("%s():%i: Allocated from unexpected address space\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* we've allocated something - removing memory should fail */
+ if (rte_malloc_heap_memory_remove(heap_name, addr, len) >= 0 ||
+ rte_errno != EBUSY) {
+ printf("%s():%i: Removing memory succeeded when memory is not free\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_destroy(heap_name) >= 0 || rte_errno != EBUSY) {
+ printf("%s():%i: Destroying heap succeeded when memory is not free\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* try allocating a memzone */
+ mz = rte_memzone_reserve("heap_test", pgsz * 2, socket_id, 0);
+ if (mz == NULL) {
+ printf("%s():%i: Failed to reserve memzone\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ /* try allocating an IOVA-contiguous memzone - this should succeed
+ * if we've set up a contiguous IOVA table, and fail if we haven't.
+ */
+ contig_mz = rte_memzone_reserve("heap_test_contig", pgsz * 2, socket_id,
+ RTE_MEMZONE_IOVA_CONTIG);
+ if ((iova == NULL) != (contig_mz == NULL)) {
+ printf("%s():%i: Failed to reserve memzone\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ rte_malloc_dump_stats(stdout, NULL);
+ rte_malloc_dump_heaps(stdout);
+
+ /* free memory - removing it should now succeed */
+ rte_free(ptr);
+ ptr = NULL;
+
+ rte_memzone_free(mz);
+ mz = NULL;
+ rte_memzone_free(contig_mz);
+ contig_mz = NULL;
+
+ if (rte_malloc_heap_memory_remove(heap_name, addr, len) != 0) {
+ printf("%s():%i: Removing memory from heap failed\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+ if (rte_malloc_heap_destroy(heap_name) != 0) {
+ printf("%s():%i: Destroying heap failed\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ rte_memzone_free(contig_mz);
+ rte_memzone_free(mz);
+ rte_free(ptr);
+ /* even if something failed, attempt to clean up */
+ rte_malloc_heap_memory_remove(heap_name, addr, len);
+ rte_malloc_heap_destroy(heap_name);
+
+ return -1;
+}
+
+static int
+test_extmem_invalid_param(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
+ int n_pages)
+{
+ /* these calls may fail for other reasons, so check errno */
+ if (rte_extmem_unregister(addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Unregistered non-existent memory\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_extmem_attach(addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Attached to non-existent memory\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (rte_extmem_attach(addr, len) >= 0 ||
+ rte_errno != ENOENT) {
+ printf("%s():%i: Detached from non-existent memory\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* zero length */
+ if (rte_extmem_register(addr, 0, NULL, 0, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Registered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_extmem_unregister(addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Unregistered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_extmem_attach(addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Attached memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (rte_extmem_attach(addr, 0) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Detached memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* zero address */
+ if (rte_extmem_register(NULL, len, NULL, 0, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Registered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_extmem_unregister(NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Unregistered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_extmem_attach(NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Attached memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (rte_extmem_attach(NULL, len) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Detached memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ /* the following tests are only valid if IOVA table is not NULL */
+ if (iova != NULL) {
+ /* wrong page count */
+ if (rte_extmem_register(addr, len,
+ iova, 0, pgsz) >= 0 || rte_errno != EINVAL) {
+ printf("%s():%i: Registered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (rte_extmem_register(addr, len,
+ iova, n_pages - 1, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Registered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ if (rte_extmem_register(addr, len,
+ iova, n_pages + 1, pgsz) >= 0 ||
+ rte_errno != EINVAL) {
+ printf("%s():%i: Registered memory with invalid parameters\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_extmem_basic(void *addr, size_t len, size_t pgsz, rte_iova_t *iova,
+ int n_pages)
+{
+ /* register memory */
+ if (rte_extmem_register(addr, len, iova, n_pages, pgsz) != 0) {
+ printf("%s():%i: Failed to register memory\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ /* check if memory is accessible from EAL */
+ if (check_mem(addr, iova, pgsz, n_pages) < 0)
+ goto fail;
+
+ if (rte_extmem_unregister(addr, len) != 0) {
+ printf("%s():%i: Removing memory from heap failed\n",
+ __func__, __LINE__);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ /* even if something failed, attempt to clean up */
+ rte_extmem_unregister(addr, len);
+
+ return -1;
+}
+
+/* we need to test attach/detach in secondary processes. */
+static int
+test_external_mem(void)
+{
+ size_t len = EXTERNAL_MEM_SZ;
+ size_t pgsz = RTE_PGSIZE_4K;
+ rte_iova_t iova[len / pgsz];
+ void *addr;
+ int ret, n_pages;
+ int i;
+
+ /* create external memory area */
+ n_pages = RTE_DIM(iova);
+ addr = mmap(NULL, len, PROT_WRITE | PROT_READ,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (addr == MAP_FAILED) {
+ printf("%s():%i: Failed to create dummy memory area\n",
+ __func__, __LINE__);
+ return -1;
+ }
+ for (i = 0; i < n_pages; i++) {
+ /* arbitrary IOVA */
+ rte_iova_t tmp = 0x100000000 + i * pgsz;
+ iova[i] = tmp;
+ }
+
+ /* test external heap memory */
+ ret = test_malloc_invalid_param(addr, len, pgsz, iova, n_pages);
+ ret |= test_malloc_basic(addr, len, pgsz, iova, n_pages);
+ /* when iova table is NULL, everything should still work */
+ ret |= test_malloc_invalid_param(addr, len, pgsz, NULL, n_pages);
+ ret |= test_malloc_basic(addr, len, pgsz, NULL, n_pages);
+
+ /* test non-heap memory */
+ ret |= test_extmem_invalid_param(addr, len, pgsz, iova, n_pages);
+ ret |= test_extmem_basic(addr, len, pgsz, iova, n_pages);
+ /* when iova table is NULL, everything should still work */
+ ret |= test_extmem_invalid_param(addr, len, pgsz, NULL, n_pages);
+ ret |= test_extmem_basic(addr, len, pgsz, NULL, n_pages);
+
+ munmap(addr, len);
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(external_mem_autotest, test_external_mem);
diff --git a/src/spdk/dpdk/app/test/test_fbarray.c b/src/spdk/dpdk/app/test/test_fbarray.c
new file mode 100644
index 000000000..a691bf445
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_fbarray.c
@@ -0,0 +1,736 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_errno.h>
+#include <rte_fbarray.h>
+
+#include "test.h"
+
+struct fbarray_testsuite_params {
+ struct rte_fbarray arr;
+ int start;
+ int end;
+};
+
+static struct fbarray_testsuite_params param;
+
+#define FBARRAY_TEST_ARR_NAME "fbarray_autotest"
+#define FBARRAY_TEST_LEN 256
+#define FBARRAY_TEST_ELT_SZ (sizeof(int))
+
+static int autotest_setup(void)
+{
+ return rte_fbarray_init(&param.arr, FBARRAY_TEST_ARR_NAME,
+ FBARRAY_TEST_LEN, FBARRAY_TEST_ELT_SZ);
+}
+
+static void autotest_teardown(void)
+{
+ rte_fbarray_destroy(&param.arr);
+}
+
+static int init_array(void)
+{
+ int i;
+ for (i = param.start; i <= param.end; i++) {
+ if (rte_fbarray_set_used(&param.arr, i))
+ return -1;
+ }
+ return 0;
+}
+
+static void reset_array(void)
+{
+ int i;
+ for (i = 0; i < FBARRAY_TEST_LEN; i++)
+ rte_fbarray_set_free(&param.arr, i);
+}
+
+static int first_msk_test_setup(void)
+{
+ /* put all within first mask */
+ param.start = 3;
+ param.end = 10;
+ return init_array();
+}
+
+static int cross_msk_test_setup(void)
+{
+ /* put all within second and third mask */
+ param.start = 70;
+ param.end = 160;
+ return init_array();
+}
+
+static int multi_msk_test_setup(void)
+{
+ /* put all within first and last mask */
+ param.start = 3;
+ param.end = FBARRAY_TEST_LEN - 20;
+ return init_array();
+}
+
+static int last_msk_test_setup(void)
+{
+ /* put all within last mask */
+ param.start = FBARRAY_TEST_LEN - 20;
+ param.end = FBARRAY_TEST_LEN - 1;
+ return init_array();
+}
+
+static int full_msk_test_setup(void)
+{
+ /* fill entire mask */
+ param.start = 0;
+ param.end = FBARRAY_TEST_LEN - 1;
+ return init_array();
+}
+
+static int empty_msk_test_setup(void)
+{
+ /* do not fill anything in */
+ reset_array();
+ param.start = -1;
+ param.end = -1;
+ return 0;
+}
+
+static int test_invalid(void)
+{
+ struct rte_fbarray dummy;
+
+ /* invalid parameters */
+ TEST_ASSERT_FAIL(rte_fbarray_attach(NULL),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT_FAIL(rte_fbarray_detach(NULL),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT_FAIL(rte_fbarray_destroy(NULL),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno valuey\n");
+ TEST_ASSERT_FAIL(rte_fbarray_init(NULL, "fail", 16, 16),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, NULL, 16, 16),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", 0, 16),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", 16, 0),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ /* len must not be greater than INT_MAX */
+ TEST_ASSERT_FAIL(rte_fbarray_init(&dummy, "fail", INT_MAX + 1U, 16),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT_NULL(rte_fbarray_get(NULL, 0),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_idx(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_set_free(NULL, 0),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_set_used(NULL, 0),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_contig_free(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_contig_used(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_rev_contig_free(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_rev_contig_used(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_free(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_used(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_free(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_used(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_free(NULL, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_used(NULL, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_free(NULL, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_used(NULL, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_is_used(NULL, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT_SUCCESS(rte_fbarray_init(&dummy, "success",
+ FBARRAY_TEST_LEN, 8),
+ "Failed to initialize valid fbarray\n");
+
+ /* test API for handling invalid parameters with a valid fbarray */
+ TEST_ASSERT_NULL(rte_fbarray_get(&dummy, FBARRAY_TEST_LEN),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_idx(&dummy, NULL) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_set_free(&dummy, FBARRAY_TEST_LEN),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_set_used(&dummy, FBARRAY_TEST_LEN),
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_contig_free(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_contig_used(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_rev_contig_free(&dummy,
+ FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_rev_contig_used(&dummy,
+ FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_next_free(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_next_used(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_prev_free(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_prev_used(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy,
+ FBARRAY_TEST_LEN, 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy, 0,
+ FBARRAY_TEST_LEN + 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_free(&dummy, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy,
+ FBARRAY_TEST_LEN, 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy, 0,
+ FBARRAY_TEST_LEN + 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_used(&dummy, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy,
+ FBARRAY_TEST_LEN, 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy, 0,
+ FBARRAY_TEST_LEN + 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_free(&dummy, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy,
+ FBARRAY_TEST_LEN, 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy, 0,
+ FBARRAY_TEST_LEN + 1) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_used(&dummy, 0, 0) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT(rte_fbarray_is_used(&dummy, FBARRAY_TEST_LEN) < 0,
+ "Call succeeded with invalid parameters\n");
+ TEST_ASSERT_EQUAL(rte_errno, EINVAL, "Wrong errno value\n");
+
+ TEST_ASSERT_SUCCESS(rte_fbarray_destroy(&dummy),
+ "Failed to destroy valid fbarray\n");
+
+ return TEST_SUCCESS;
+}
+
+static int check_free(void)
+{
+ const int idx = 0;
+ const int last_idx = FBARRAY_TEST_LEN - 1;
+
+ /* ensure we can find a free spot */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_free(&param.arr, idx), idx,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(&param.arr, idx, 1), idx,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(&param.arr, idx),
+ FBARRAY_TEST_LEN,
+ "Free space not found where expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(&param.arr, idx), idx,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, idx, 1), idx,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr, idx), 1,
+ "Free space not found where expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(&param.arr, last_idx),
+ last_idx, "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(&param.arr, last_idx, 1),
+ last_idx, "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr,
+ last_idx), FBARRAY_TEST_LEN,
+ "Free space not found where expected\n");
+
+ /* ensure we can't find any used spots */
+ TEST_ASSERT(rte_fbarray_find_next_used(&param.arr, idx) < 0,
+ "Used space found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_used(&param.arr, idx, 1) < 0,
+ "Used space found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx), 0,
+ "Used space found where none was expected\n");
+
+ TEST_ASSERT(rte_fbarray_find_prev_used(&param.arr, last_idx) < 0,
+ "Used space found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1) < 0,
+ "Used space found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
+ last_idx), 0,
+ "Used space found where none was expected\n");
+
+ return 0;
+}
+
+static int check_used_one(void)
+{
+ const int idx = 0;
+ const int last_idx = FBARRAY_TEST_LEN - 1;
+
+ /* check that we can find used spots now */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_used(&param.arr, idx), idx,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(&param.arr, idx, 1), idx,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx), 1,
+ "Used space not found where expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(&param.arr, last_idx), idx,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1),
+ idx, "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr, idx), 1,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
+ last_idx), idx,
+ "Used space not found where expected\n");
+
+ /* check if further indices are still free */
+ TEST_ASSERT(rte_fbarray_find_next_used(&param.arr, idx + 1) < 0,
+ "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT(rte_fbarray_find_next_n_used(&param.arr, idx + 1, 1) < 0,
+ "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_errno, ENOENT, "Wrong errno value\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(&param.arr, idx + 1), 0,
+ "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(&param.arr, idx + 1),
+ FBARRAY_TEST_LEN - 1,
+ "Used space not found where none was expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(&param.arr, last_idx), 0,
+ "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(&param.arr, last_idx, 1),
+ 0, "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(&param.arr,
+ last_idx), 0,
+ "Used space not found where none was expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(&param.arr,
+ last_idx), FBARRAY_TEST_LEN - 1,
+ "Used space not found where none was expected\n");
+
+ return 0;
+}
+
+static int test_basic(void)
+{
+ const int idx = 0;
+ int i;
+
+ /* check array count */
+ TEST_ASSERT_EQUAL(param.arr.count, 0, "Wrong element count\n");
+
+ /* ensure we can find a free spot */
+ if (check_free())
+ return TEST_FAILED;
+
+ /* check if used */
+ TEST_ASSERT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
+ "Used space found where not expected\n");
+
+ /* mark as used */
+ TEST_ASSERT_SUCCESS(rte_fbarray_set_used(&param.arr, idx),
+ "Failed to set as used\n");
+
+ /* check if used again */
+ TEST_ASSERT_NOT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
+ "Used space not found where expected\n");
+
+ if (check_used_one())
+ return TEST_FAILED;
+
+ /* check array count */
+ TEST_ASSERT_EQUAL(param.arr.count, 1, "Wrong element count\n");
+
+ /* check if getting pointers works for every element */
+ for (i = 0; i < FBARRAY_TEST_LEN; i++) {
+ void *td = rte_fbarray_get(&param.arr, i);
+ TEST_ASSERT_NOT_NULL(td, "Invalid pointer returned\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_idx(&param.arr, td), i,
+ "Wrong index returned\n");
+ }
+
+ /* mark as free */
+ TEST_ASSERT_SUCCESS(rte_fbarray_set_free(&param.arr, idx),
+ "Failed to set as free\n");
+
+ /* check array count */
+ TEST_ASSERT_EQUAL(param.arr.count, 0, "Wrong element count\n");
+
+ /* check if used */
+ TEST_ASSERT_EQUAL(rte_fbarray_is_used(&param.arr, idx), 0,
+ "Used space found where not expected\n");
+
+ if (check_free())
+ return TEST_FAILED;
+
+ reset_array();
+
+ return TEST_SUCCESS;
+}
+
+static int test_biggest(struct rte_fbarray *arr, int first, int last)
+{
+ int lo_free_space_first, lo_free_space_last, lo_free_space_len;
+ int hi_free_space_first, hi_free_space_last, hi_free_space_len;
+ int max_free_space_first, max_free_space_last, max_free_space_len;
+ int len = last - first + 1;
+
+ /* first and last must either be both -1, or both not -1 */
+ TEST_ASSERT((first == -1) == (last == -1),
+ "Invalid arguments provided\n");
+
+ /* figure out what we expect from the low chunk of free space */
+ if (first == -1) {
+ /* special case: if there are no occupied elements at all,
+ * consider both free spaces to consume the entire array.
+ */
+ lo_free_space_first = 0;
+ lo_free_space_last = arr->len - 1;
+ lo_free_space_len = arr->len;
+ /* if there's no used space, length should be invalid */
+ len = -1;
+ } else if (first == 0) {
+ /* if occupied items start at 0, there's no free space */
+ lo_free_space_first = -1;
+ lo_free_space_last = -1;
+ lo_free_space_len = 0;
+ } else {
+ lo_free_space_first = 0;
+ lo_free_space_last = first - 1;
+ lo_free_space_len = lo_free_space_last -
+ lo_free_space_first + 1;
+ }
+
+ /* figure out what we expect from the high chunk of free space */
+ if (last == -1) {
+ /* special case: if there are no occupied elements at all,
+ * consider both free spaces to consume the entire array.
+ */
+ hi_free_space_first = 0;
+ hi_free_space_last = arr->len - 1;
+ hi_free_space_len = arr->len;
+ /* if there's no used space, length should be invalid */
+ len = -1;
+ } else if (last == ((int)arr->len - 1)) {
+ /* if occupied items end at array len, there's no free space */
+ hi_free_space_first = -1;
+ hi_free_space_last = -1;
+ hi_free_space_len = 0;
+ } else {
+ hi_free_space_first = last + 1;
+ hi_free_space_last = arr->len - 1;
+ hi_free_space_len = hi_free_space_last -
+ hi_free_space_first + 1;
+ }
+
+ /* find which one will be biggest */
+ if (lo_free_space_len > hi_free_space_len) {
+ max_free_space_first = lo_free_space_first;
+ max_free_space_last = lo_free_space_last;
+ max_free_space_len = lo_free_space_len;
+ } else {
+ /* if they are equal, we'll just use the high chunk */
+ max_free_space_first = hi_free_space_first;
+ max_free_space_last = hi_free_space_last;
+ max_free_space_len = hi_free_space_len;
+ }
+
+ /* check used regions - these should produce identical results */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_used(arr, 0), first,
+ "Used space index is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_used(arr, arr->len - 1),
+ first,
+ "Used space index is wrong\n");
+ /* len may be -1, but function will return error anyway */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(arr, first), len,
+ "Used space length is wrong\n");
+
+ /* check if biggest free region is the one we expect to find. It can be
+ * -1 if there's no free space - we've made sure we use one or the
+ * other, even if both are invalid.
+ */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_free(arr, 0),
+ max_free_space_first,
+ "Biggest free space index is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_free(arr, arr->len - 1),
+ max_free_space_first,
+ "Biggest free space index is wrong\n");
+
+ /* if biggest region exists, check its length */
+ if (max_free_space_first != -1) {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
+ max_free_space_first),
+ max_free_space_len,
+ "Biggest free space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
+ max_free_space_last),
+ max_free_space_len,
+ "Biggest free space length is wrong\n");
+ }
+
+ /* find if we see what we expect to see in the low region. if there is
+ * no free space, the function should still match expected value, as
+ * we've set it to -1. we're scanning backwards to avoid accidentally
+ * hitting the high free space region. if there is no occupied space,
+ * there's nothing to do.
+ */
+ if (last != -1) {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_biggest_free(arr, last),
+ lo_free_space_first,
+ "Low free space index is wrong\n");
+ }
+
+ if (lo_free_space_first != -1) {
+ /* if low free region exists, check its length */
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
+ lo_free_space_first),
+ lo_free_space_len,
+ "Low free space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
+ lo_free_space_last),
+ lo_free_space_len,
+ "Low free space length is wrong\n");
+ }
+
+ /* find if we see what we expect to see in the high region. if there is
+ * no free space, the function should still match expected value, as
+ * we've set it to -1. we're scanning forwards to avoid accidentally
+ * hitting the low free space region. if there is no occupied space,
+ * there's nothing to do.
+ */
+ if (first != -1) {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_biggest_free(arr, first),
+ hi_free_space_first,
+ "High free space index is wrong\n");
+ }
+
+ /* if high free region exists, check its length */
+ if (hi_free_space_first != -1) {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
+ hi_free_space_first),
+ hi_free_space_len,
+ "High free space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
+ hi_free_space_last),
+ hi_free_space_len,
+ "High free space length is wrong\n");
+ }
+
+ return 0;
+}
+
+static int ensure_correct(struct rte_fbarray *arr, int first, int last,
+ bool used)
+{
+ int i, len = last - first + 1;
+ for (i = 0; i < len; i++) {
+ int cur = first + i;
+ int cur_len = len - i;
+
+ if (used) {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_used(arr,
+ cur), cur_len,
+ "Used space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(arr,
+ last), len,
+ "Used space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_used(arr,
+ cur), i + 1,
+ "Used space length is wrong\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_used(arr, cur),
+ cur,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(arr,
+ cur, 1), cur,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_used(arr, cur,
+ cur_len), cur,
+ "Used space not found where expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_used(arr, cur),
+ cur,
+ "Used space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_used(arr,
+ last, cur_len), cur,
+ "Used space not found where expected\n");
+ } else {
+ TEST_ASSERT_EQUAL(rte_fbarray_find_contig_free(arr,
+ cur), cur_len,
+ "Free space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
+ last), len,
+ "Free space length is wrong\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_rev_contig_free(arr,
+ cur), i + 1,
+ "Free space length is wrong\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_free(arr, cur),
+ cur,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(arr, cur,
+ 1), cur,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_next_n_free(arr, cur,
+ cur_len), cur,
+ "Free space not found where expected\n");
+
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_free(arr, cur),
+ cur,
+ "Free space not found where expected\n");
+ TEST_ASSERT_EQUAL(rte_fbarray_find_prev_n_free(arr,
+ last, cur_len), cur,
+ "Free space not found where expected\n");
+ }
+ }
+ return 0;
+}
+
+static int test_find(void)
+{
+ TEST_ASSERT_EQUAL((int)param.arr.count, param.end - param.start + 1,
+ "Wrong element count\n");
+ /* ensure space is free before start */
+ if (ensure_correct(&param.arr, 0, param.start - 1, false))
+ return TEST_FAILED;
+ /* ensure space is occupied where it's supposed to be */
+ if (ensure_correct(&param.arr, param.start, param.end, true))
+ return TEST_FAILED;
+ /* ensure space after end is free as well */
+ if (ensure_correct(&param.arr, param.end + 1, FBARRAY_TEST_LEN - 1,
+ false))
+ return TEST_FAILED;
+ /* test if find_biggest API's work correctly */
+ if (test_biggest(&param.arr, param.start, param.end))
+ return TEST_FAILED;
+ return TEST_SUCCESS;
+}
+
+static int test_empty(void)
+{
+ TEST_ASSERT_EQUAL((int)param.arr.count, 0, "Wrong element count\n");
+ /* ensure space is free */
+ if (ensure_correct(&param.arr, 0, FBARRAY_TEST_LEN - 1, false))
+ return TEST_FAILED;
+ /* test if find_biggest API's work correctly */
+ if (test_biggest(&param.arr, param.start, param.end))
+ return TEST_FAILED;
+ return TEST_SUCCESS;
+}
+
+
+static struct unit_test_suite fbarray_test_suite = {
+ .suite_name = "fbarray autotest",
+ .setup = autotest_setup,
+ .teardown = autotest_teardown,
+ .unit_test_cases = {
+ TEST_CASE(test_invalid),
+ TEST_CASE(test_basic),
+ TEST_CASE_ST(first_msk_test_setup, reset_array, test_find),
+ TEST_CASE_ST(cross_msk_test_setup, reset_array, test_find),
+ TEST_CASE_ST(multi_msk_test_setup, reset_array, test_find),
+ TEST_CASE_ST(last_msk_test_setup, reset_array, test_find),
+ TEST_CASE_ST(full_msk_test_setup, reset_array, test_find),
+ TEST_CASE_ST(empty_msk_test_setup, reset_array, test_empty),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_fbarray(void)
+{
+ return unit_test_suite_runner(&fbarray_test_suite);
+}
+
+REGISTER_TEST_COMMAND(fbarray_autotest, test_fbarray);
diff --git a/src/spdk/dpdk/app/test/test_fib.c b/src/spdk/dpdk/app/test/test_fib.c
new file mode 100644
index 000000000..ca80a5dd2
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_fib.c
@@ -0,0 +1,414 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_log.h>
+#include <rte_fib.h>
+
+#include "test.h"
+
+typedef int32_t (*rte_fib_test)(void);
+
+static int32_t test_create_invalid(void);
+static int32_t test_multiple_create(void);
+static int32_t test_free_null(void);
+static int32_t test_add_del_invalid(void);
+static int32_t test_get_invalid(void);
+static int32_t test_lookup(void);
+
+#define MAX_ROUTES (1 << 16)
+#define MAX_TBL8 (1 << 15)
+
+/*
+ * Check that rte_fib_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_create_invalid(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB_DUMMY;
+
+ /* rte_fib_create: fib name == NULL */
+ fib = rte_fib_create(NULL, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib_create: config == NULL */
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, NULL);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* socket_id < -1 is invalid */
+ fib = rte_fib_create(__func__, -2, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib_create: max_routes = 0 */
+ config.max_routes = 0;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.max_routes = MAX_ROUTES;
+
+ config.type = RTE_FIB_TYPE_MAX;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ config.type = RTE_FIB_DIR24_8;
+ config.dir24_8.num_tbl8 = MAX_TBL8;
+
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B + 1;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
+
+ config.dir24_8.num_tbl8 = 0;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Create fib table then delete fib table 10 times
+ * Use a slightly different rules size each time
+ */
+int32_t
+test_multiple_create(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+ int32_t i;
+
+ config.default_nh = 0;
+ config.type = RTE_FIB_DUMMY;
+
+ for (i = 0; i < 100; i++) {
+ config.max_routes = MAX_ROUTES - i;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ rte_fib_free(fib);
+ }
+ /* Can not test free so return success */
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_fib_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test_free_null(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB_DUMMY;
+
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+
+ rte_fib_free(fib);
+ rte_fib_free(NULL);
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_fib_add and rte_fib_delete fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_add_del_invalid(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+ uint64_t nh = 100;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0);
+ int ret;
+ uint8_t depth = 24;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB_DUMMY;
+
+ /* rte_fib_add: fib == NULL */
+ ret = rte_fib_add(NULL, ip, depth, nh);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib_delete: fib == NULL */
+ ret = rte_fib_delete(NULL, ip, depth);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /*Create valid fib to use in rest of test. */
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+
+ /* rte_fib_add: depth > RTE_FIB_MAXDEPTH */
+ ret = rte_fib_add(fib, ip, RTE_FIB_MAXDEPTH + 1, nh);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib_delete: depth > RTE_FIB_MAXDEPTH */
+ ret = rte_fib_delete(fib, ip, RTE_FIB_MAXDEPTH + 1);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ rte_fib_free(fib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_fib_get_dp and rte_fib_get_rib fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_get_invalid(void)
+{
+ void *p;
+
+ p = rte_fib_get_dp(NULL);
+ RTE_TEST_ASSERT(p == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ p = rte_fib_get_rib(NULL);
+ RTE_TEST_ASSERT(p == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Add routes for one supernet with all possible depths and do lookup
+ * on each step
+ * After delete routes with doing lookup on each step
+ */
+static int
+lookup_and_check_asc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
+ uint32_t ip_missing, uint64_t def_nh, uint32_t n)
+{
+ uint64_t nh_arr[RTE_FIB_MAXDEPTH];
+ int ret;
+ uint32_t i = 0;
+
+ ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
+ RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
+
+ for (; i <= RTE_FIB_MAXDEPTH - n; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == n,
+ "Failed to get proper nexthop\n");
+
+ for (; i < RTE_FIB_MAXDEPTH; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == --n,
+ "Failed to get proper nexthop\n");
+
+ ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
+ RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
+ "Failed to get proper nexthop\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+lookup_and_check_desc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
+ uint32_t ip_missing, uint64_t def_nh, uint32_t n)
+{
+ uint64_t nh_arr[RTE_FIB_MAXDEPTH];
+ int ret;
+ uint32_t i = 0;
+
+ ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
+ RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
+
+ for (; i < n; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB_MAXDEPTH - i,
+ "Failed to get proper nexthop\n");
+
+ for (; i < RTE_FIB_MAXDEPTH; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == def_nh,
+ "Failed to get proper nexthop\n");
+
+ ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
+ RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
+ "Failed to get proper nexthop\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+check_fib(struct rte_fib *fib)
+{
+ uint64_t def_nh = 100;
+ uint32_t ip_arr[RTE_FIB_MAXDEPTH];
+ uint32_t ip_add = RTE_IPV4(128, 0, 0, 0);
+ uint32_t i, ip_missing = RTE_IPV4(127, 255, 255, 255);
+ int ret;
+
+ for (i = 0; i < RTE_FIB_MAXDEPTH; i++)
+ ip_arr[i] = ip_add + (1ULL << i) - 1;
+
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+
+ for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
+ ret = rte_fib_add(fib, ip_add, i, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
+ ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
+ def_nh, i);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+ }
+
+ for (i = RTE_FIB_MAXDEPTH; i > 1; i--) {
+ ret = rte_fib_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
+ def_nh, i - 1);
+
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+ }
+ ret = rte_fib_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+
+ for (i = 0; i < RTE_FIB_MAXDEPTH; i++) {
+ ret = rte_fib_add(fib, ip_add, RTE_FIB_MAXDEPTH - i,
+ RTE_FIB_MAXDEPTH - i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
+ def_nh, i + 1);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+ }
+
+ for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
+ ret = rte_fib_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
+ RTE_FIB_MAXDEPTH - i);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+ }
+
+ return TEST_SUCCESS;
+}
+
+int32_t
+test_lookup(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+ uint64_t def_nh = 100;
+ int ret;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = def_nh;
+ config.type = RTE_FIB_DUMMY;
+
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DUMMY type\n");
+ rte_fib_free(fib);
+
+ config.type = RTE_FIB_DIR24_8;
+
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_1B;
+ config.dir24_8.num_tbl8 = 127;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DIR24_8_1B type\n");
+ rte_fib_free(fib);
+
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_2B;
+ config.dir24_8.num_tbl8 = MAX_TBL8 - 1;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DIR24_8_2B type\n");
+ rte_fib_free(fib);
+
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+ config.dir24_8.num_tbl8 = MAX_TBL8;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DIR24_8_4B type\n");
+ rte_fib_free(fib);
+
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
+ config.dir24_8.num_tbl8 = MAX_TBL8;
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DIR24_8_8B type\n");
+ rte_fib_free(fib);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite fib_fast_tests = {
+ .suite_name = "fib autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_create_invalid),
+ TEST_CASE(test_free_null),
+ TEST_CASE(test_add_del_invalid),
+ TEST_CASE(test_get_invalid),
+ TEST_CASE(test_lookup),
+ TEST_CASES_END()
+ }
+};
+
+static struct unit_test_suite fib_slow_tests = {
+ .suite_name = "fib slow autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_multiple_create),
+ TEST_CASES_END()
+ }
+};
+
+/*
+ * Do all unit tests.
+ */
+static int
+test_fib(void)
+{
+ return unit_test_suite_runner(&fib_fast_tests);
+}
+
+static int
+test_slow_fib(void)
+{
+ return unit_test_suite_runner(&fib_slow_tests);
+}
+
+REGISTER_TEST_COMMAND(fib_autotest, test_fib);
+REGISTER_TEST_COMMAND(fib_slow_autotest, test_slow_fib);
diff --git a/src/spdk/dpdk/app/test/test_fib6.c b/src/spdk/dpdk/app/test/test_fib6.c
new file mode 100644
index 000000000..af589fe8c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_fib6.c
@@ -0,0 +1,423 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_memory.h>
+#include <rte_log.h>
+#include <rte_rib6.h>
+#include <rte_fib6.h>
+
+#include "test.h"
+
+typedef int32_t (*rte_fib6_test)(void);
+
+static int32_t test_create_invalid(void);
+static int32_t test_multiple_create(void);
+static int32_t test_free_null(void);
+static int32_t test_add_del_invalid(void);
+static int32_t test_get_invalid(void);
+static int32_t test_lookup(void);
+
+#define MAX_ROUTES (1 << 16)
+/** Maximum number of tbl8 for 2-byte entries */
+#define MAX_TBL8 (1 << 15)
+
+/*
+ * Check that rte_fib6_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_create_invalid(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf config;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB6_DUMMY;
+
+ /* rte_fib6_create: fib name == NULL */
+ fib = rte_fib6_create(NULL, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib6_create: config == NULL */
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, NULL);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* socket_id < -1 is invalid */
+ fib = rte_fib6_create(__func__, -2, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib6_create: max_routes = 0 */
+ config.max_routes = 0;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.max_routes = MAX_ROUTES;
+
+ config.type = RTE_FIB6_TYPE_MAX;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ config.type = RTE_FIB6_TRIE;
+ config.trie.num_tbl8 = MAX_TBL8;
+
+ config.trie.nh_sz = RTE_FIB6_TRIE_8B + 1;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.trie.nh_sz = RTE_FIB6_TRIE_8B;
+
+ config.trie.num_tbl8 = 0;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Create fib table then delete fib table 10 times
+ * Use a slightly different rules size each time
+ */
+int32_t
+test_multiple_create(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf config;
+ int32_t i;
+
+ config.default_nh = 0;
+ config.type = RTE_FIB6_DUMMY;
+
+ for (i = 0; i < 100; i++) {
+ config.max_routes = MAX_ROUTES - i;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ rte_fib6_free(fib);
+ }
+ /* Can not test free so return success */
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_fib6_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test_free_null(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf config;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB6_DUMMY;
+
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+
+ rte_fib6_free(fib);
+ rte_fib6_free(NULL);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_fib6_add and rte_fib6_delete fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_add_del_invalid(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf config;
+ uint64_t nh = 100;
+ uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
+ int ret;
+ uint8_t depth = 24;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = 0;
+ config.type = RTE_FIB6_DUMMY;
+
+ /* rte_fib6_add: fib == NULL */
+ ret = rte_fib6_add(NULL, ip, depth, nh);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib6_delete: fib == NULL */
+ ret = rte_fib6_delete(NULL, ip, depth);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /*Create valid fib to use in rest of test. */
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+
+ /* rte_fib6_add: depth > RTE_FIB6_MAXDEPTH */
+ ret = rte_fib6_add(fib, ip, RTE_FIB6_MAXDEPTH + 1, nh);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_fib6_delete: depth > RTE_FIB6_MAXDEPTH */
+ ret = rte_fib6_delete(fib, ip, RTE_FIB6_MAXDEPTH + 1);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ rte_fib6_free(fib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_fib6_get_dp and rte_fib6_get_rib fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_get_invalid(void)
+{
+ void *p;
+
+ p = rte_fib6_get_dp(NULL);
+ RTE_TEST_ASSERT(p == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ p = rte_fib6_get_rib(NULL);
+ RTE_TEST_ASSERT(p == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Add routes for one supernet with all possible depths and do lookup
+ * on each step
+ * After delete routes with doing lookup on each step
+ */
+static int
+lookup_and_check_asc(struct rte_fib6 *fib,
+ uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
+ uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
+ uint32_t n)
+{
+ uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
+ int ret;
+ uint32_t i = 0;
+
+ ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
+ RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
+
+ for (; i <= RTE_FIB6_MAXDEPTH - n; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == n,
+ "Failed to get proper nexthop\n");
+
+ for (; i < RTE_FIB6_MAXDEPTH; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == --n,
+ "Failed to get proper nexthop\n");
+
+ ret = rte_fib6_lookup_bulk(fib, ip_missing, nh_arr, 1);
+ RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
+ "Failed to get proper nexthop\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+lookup_and_check_desc(struct rte_fib6 *fib,
+ uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
+ uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
+ uint32_t n)
+{
+ uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
+ int ret;
+ uint32_t i = 0;
+
+ ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
+ RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
+
+ for (; i < n; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB6_MAXDEPTH - i,
+ "Failed to get proper nexthop\n");
+
+ for (; i < RTE_FIB6_MAXDEPTH; i++)
+ RTE_TEST_ASSERT(nh_arr[i] == def_nh,
+ "Failed to get proper nexthop\n");
+
+ ret = rte_fib6_lookup_bulk(fib, ip_missing, nh_arr, 1);
+ RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
+ "Failed to get proper nexthop\n");
+
+ return TEST_SUCCESS;
+}
+
+static int
+check_fib(struct rte_fib6 *fib)
+{
+ uint64_t def_nh = 100;
+ uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE];
+ uint8_t ip_add[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
+ uint8_t ip_missing[1][RTE_FIB6_IPV6_ADDR_SIZE] = { {255} };
+ uint32_t i, j;
+ int ret;
+
+ ip_add[0] = 128;
+ ip_missing[0][0] = 127;
+ for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
+ for (j = 0; j < RTE_FIB6_IPV6_ADDR_SIZE; j++) {
+ ip_arr[i][j] = ip_add[j] |
+ ~get_msk_part(RTE_FIB6_MAXDEPTH - i, j);
+ }
+ }
+
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
+
+ for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
+ ret = rte_fib6_add(fib, ip_add, i, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
+ ret = lookup_and_check_asc(fib, ip_arr, ip_missing, def_nh, i);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Lookup and check fails\n");
+ }
+
+ for (i = RTE_FIB6_MAXDEPTH; i > 1; i--) {
+ ret = rte_fib6_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
+ def_nh, i - 1);
+
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Lookup and check fails\n");
+ }
+ ret = rte_fib6_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Lookup and check fails\n");
+
+ for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
+ ret = rte_fib6_add(fib, ip_add, RTE_FIB6_MAXDEPTH - i,
+ RTE_FIB6_MAXDEPTH - i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
+ def_nh, i + 1);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Lookup and check fails\n");
+ }
+
+ for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
+ ret = rte_fib6_delete(fib, ip_add, i);
+ RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
+ ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
+ RTE_FIB6_MAXDEPTH - i);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Lookup and check fails\n");
+ }
+
+ return TEST_SUCCESS;
+}
+
+int32_t
+test_lookup(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf config;
+ uint64_t def_nh = 100;
+ int ret;
+
+ config.max_routes = MAX_ROUTES;
+ config.default_nh = def_nh;
+ config.type = RTE_FIB6_DUMMY;
+
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for DUMMY type\n");
+ rte_fib6_free(fib);
+
+ config.type = RTE_FIB6_TRIE;
+
+ config.trie.nh_sz = RTE_FIB6_TRIE_2B;
+ config.trie.num_tbl8 = MAX_TBL8 - 1;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for TRIE_2B type\n");
+ rte_fib6_free(fib);
+
+ config.trie.nh_sz = RTE_FIB6_TRIE_4B;
+ config.trie.num_tbl8 = MAX_TBL8;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for TRIE_4B type\n");
+ rte_fib6_free(fib);
+
+ config.trie.nh_sz = RTE_FIB6_TRIE_8B;
+ config.trie.num_tbl8 = MAX_TBL8;
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
+ ret = check_fib(fib);
+ RTE_TEST_ASSERT(ret == TEST_SUCCESS,
+ "Check_fib fails for TRIE_8B type\n");
+ rte_fib6_free(fib);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite fib6_fast_tests = {
+ .suite_name = "fib6 autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_create_invalid),
+ TEST_CASE(test_free_null),
+ TEST_CASE(test_add_del_invalid),
+ TEST_CASE(test_get_invalid),
+ TEST_CASE(test_lookup),
+ TEST_CASES_END()
+ }
+};
+
+static struct unit_test_suite fib6_slow_tests = {
+ .suite_name = "fib6 slow autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_multiple_create),
+ TEST_CASES_END()
+ }
+};
+
+/*
+ * Do all unit tests.
+ */
+static int
+test_fib6(void)
+{
+ return unit_test_suite_runner(&fib6_fast_tests);
+}
+
+static int
+test_slow_fib6(void)
+{
+ return unit_test_suite_runner(&fib6_slow_tests);
+}
+
+REGISTER_TEST_COMMAND(fib6_autotest, test_fib6);
+REGISTER_TEST_COMMAND(fib6_slow_autotest, test_slow_fib6);
diff --git a/src/spdk/dpdk/app/test/test_fib6_perf.c b/src/spdk/dpdk/app/test/test_fib6_perf.c
new file mode 100644
index 000000000..56c799b2e
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_fib6_perf.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_memory.h>
+#include <rte_fib6.h>
+
+#include "test.h"
+#include "test_lpm6_data.h"
+
+#define TEST_FIB_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d:\n", __LINE__); \
+ return -1; \
+ } \
+} while (0)
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE 100000
+#define NUMBER_TBL8S (1 << 16)
+
+static void
+print_route_distribution(const struct rules_tbl_entry *table, uint32_t n)
+{
+ unsigned int i, j;
+
+ printf("Route distribution per prefix width:\n");
+ printf("DEPTH QUANTITY (PERCENT)\n");
+ printf("---------------------------\n");
+
+ /* Count depths. */
+ for (i = 1; i <= 128; i++) {
+ unsigned int depth_counter = 0;
+ double percent_hits;
+
+ for (j = 0; j < n; j++)
+ if (table[j].depth == (uint8_t) i)
+ depth_counter++;
+
+ percent_hits = ((double)depth_counter)/((double)n) * 100;
+ printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
+ }
+ printf("\n");
+}
+
+static inline uint8_t
+bits_in_nh(uint8_t nh_sz)
+{
+ return 8 * (1 << nh_sz);
+}
+
+static inline uint64_t
+get_max_nh(uint8_t nh_sz)
+{
+ return ((1ULL << (bits_in_nh(nh_sz) - 1)) - 1);
+}
+
+static int
+test_fib6_perf(void)
+{
+ struct rte_fib6 *fib = NULL;
+ struct rte_fib6_conf conf;
+ uint64_t begin, total_time;
+ unsigned int i, j;
+ uint64_t next_hop_add;
+ int status = 0;
+ int64_t count = 0;
+ uint8_t ip_batch[NUM_IPS_ENTRIES][16];
+ uint64_t next_hops[NUM_IPS_ENTRIES];
+
+ conf.type = RTE_FIB6_TRIE;
+ conf.default_nh = 0;
+ conf.max_routes = 1000000;
+ conf.trie.nh_sz = RTE_FIB6_TRIE_4B;
+ conf.trie.num_tbl8 = RTE_MIN(get_max_nh(conf.trie.nh_sz), 1000000U);
+
+ rte_srand(rte_rdtsc());
+
+ printf("No. routes = %u\n", (unsigned int) NUM_ROUTE_ENTRIES);
+
+ print_route_distribution(large_route_table,
+ (uint32_t)NUM_ROUTE_ENTRIES);
+
+ /* Only generate IPv6 address of each item in large IPS table,
+ * here next_hop is not needed.
+ */
+ generate_large_ips_table(0);
+
+ fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &conf);
+ TEST_FIB_ASSERT(fib != NULL);
+
+ /* Measure add. */
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ next_hop_add = (i & ((1 << 14) - 1)) + 1;
+ if (rte_fib6_add(fib, large_route_table[i].ip,
+ large_route_table[i].depth, next_hop_add) == 0)
+ status++;
+ }
+ /* End Timer. */
+ total_time = rte_rdtsc() - begin;
+
+ printf("Unique added entries = %d\n", status);
+ printf("Average FIB Add: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ /* Measure bulk Lookup */
+ total_time = 0;
+ count = 0;
+
+ for (i = 0; i < NUM_IPS_ENTRIES; i++)
+ memcpy(ip_batch[i], large_ips_table[i].ip, 16);
+
+ for (i = 0; i < ITERATIONS; i++) {
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+ rte_fib6_lookup_bulk(fib, ip_batch, next_hops, NUM_IPS_ENTRIES);
+ total_time += rte_rdtsc() - begin;
+
+ for (j = 0; j < NUM_IPS_ENTRIES; j++)
+ if (next_hops[j] == 0)
+ count++;
+ }
+ printf("BULK FIB Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Delete */
+ status = 0;
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ /* rte_fib_delete(fib, ip, depth) */
+ status += rte_fib6_delete(fib, large_route_table[i].ip,
+ large_route_table[i].depth);
+ }
+
+ total_time = rte_rdtsc() - begin;
+
+ printf("Average FIB Delete: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ rte_fib6_free(fib);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(fib6_perf_autotest, test_fib6_perf);
diff --git a/src/spdk/dpdk/app/test/test_fib_perf.c b/src/spdk/dpdk/app/test/test_fib_perf.c
new file mode 100644
index 000000000..dd2e54db8
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_fib_perf.c
@@ -0,0 +1,411 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_branch_prediction.h>
+#include <rte_ip.h>
+#include <rte_fib.h>
+
+#include "test.h"
+#include "test_xmmt_ops.h"
+
+#define TEST_FIB_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d:\n", __LINE__); \
+ return -1; \
+ } \
+} while (0)
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE (1 << 12)
+#define BULK_SIZE 32
+
+#define MAX_RULE_NUM (1200000)
+
+struct route_rule {
+ uint32_t ip;
+ uint8_t depth;
+};
+
+static struct route_rule large_route_table[MAX_RULE_NUM];
+
+static uint32_t num_route_entries;
+#define NUM_ROUTE_ENTRIES num_route_entries
+
+enum {
+ IP_CLASS_A,
+ IP_CLASS_B,
+ IP_CLASS_C
+};
+#define RTE_FIB_MAX_DEPTH 32
+/* struct route_rule_count defines the total number of rules in following a/b/c
+ * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
+ * including the ones for private local network.
+ */
+struct route_rule_count {
+ uint32_t a[RTE_FIB_MAX_DEPTH];
+ uint32_t b[RTE_FIB_MAX_DEPTH];
+ uint32_t c[RTE_FIB_MAX_DEPTH];
+};
+
+/* All following numbers of each depth of each common IP class are just
+ * got from previous large constant table in app/test/test_lpm_routes.h .
+ * In order to match similar performance, they keep same depth and IP
+ * address coverage as previous constant table. These numbers don't
+ * include any private local IP address. As previous large const rule
+ * table was just dumped from a real router, there are no any IP address
+ * in class C or D.
+ */
+static struct route_rule_count rule_count = {
+ .a = { /* IP class A in which the most significant bit is 0 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 1, /* depth = 3 */
+ 0, /* depth = 4 */
+ 2, /* depth = 5 */
+ 1, /* depth = 6 */
+ 3, /* depth = 7 */
+ 185, /* depth = 8 */
+ 26, /* depth = 9 */
+ 16, /* depth = 10 */
+ 39, /* depth = 11 */
+ 144, /* depth = 12 */
+ 233, /* depth = 13 */
+ 528, /* depth = 14 */
+ 866, /* depth = 15 */
+ 3856, /* depth = 16 */
+ 3268, /* depth = 17 */
+ 5662, /* depth = 18 */
+ 17301, /* depth = 19 */
+ 22226, /* depth = 20 */
+ 11147, /* depth = 21 */
+ 16746, /* depth = 22 */
+ 17120, /* depth = 23 */
+ 77578, /* depth = 24 */
+ 401, /* depth = 25 */
+ 656, /* depth = 26 */
+ 1107, /* depth = 27 */
+ 1121, /* depth = 28 */
+ 2316, /* depth = 29 */
+ 717, /* depth = 30 */
+ 10, /* depth = 31 */
+ 66 /* depth = 32 */
+ },
+ .b = { /* IP class A in which the most 2 significant bits are 10 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 0, /* depth = 3 */
+ 0, /* depth = 4 */
+ 1, /* depth = 5 */
+ 1, /* depth = 6 */
+ 1, /* depth = 7 */
+ 3, /* depth = 8 */
+ 3, /* depth = 9 */
+ 30, /* depth = 10 */
+ 25, /* depth = 11 */
+ 168, /* depth = 12 */
+ 305, /* depth = 13 */
+ 569, /* depth = 14 */
+ 1129, /* depth = 15 */
+ 50800, /* depth = 16 */
+ 1645, /* depth = 17 */
+ 1820, /* depth = 18 */
+ 3506, /* depth = 19 */
+ 3258, /* depth = 20 */
+ 3424, /* depth = 21 */
+ 4971, /* depth = 22 */
+ 6885, /* depth = 23 */
+ 39771, /* depth = 24 */
+ 424, /* depth = 25 */
+ 170, /* depth = 26 */
+ 433, /* depth = 27 */
+ 92, /* depth = 28 */
+ 366, /* depth = 29 */
+ 377, /* depth = 30 */
+ 2, /* depth = 31 */
+ 200 /* depth = 32 */
+ },
+ .c = { /* IP class A in which the most 3 significant bits are 110 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 0, /* depth = 3 */
+ 0, /* depth = 4 */
+ 0, /* depth = 5 */
+ 0, /* depth = 6 */
+ 0, /* depth = 7 */
+ 12, /* depth = 8 */
+ 8, /* depth = 9 */
+ 9, /* depth = 10 */
+ 33, /* depth = 11 */
+ 69, /* depth = 12 */
+ 237, /* depth = 13 */
+ 1007, /* depth = 14 */
+ 1717, /* depth = 15 */
+ 14663, /* depth = 16 */
+ 8070, /* depth = 17 */
+ 16185, /* depth = 18 */
+ 48261, /* depth = 19 */
+ 36870, /* depth = 20 */
+ 33960, /* depth = 21 */
+ 50638, /* depth = 22 */
+ 61422, /* depth = 23 */
+ 466549, /* depth = 24 */
+ 1829, /* depth = 25 */
+ 4824, /* depth = 26 */
+ 4927, /* depth = 27 */
+ 5914, /* depth = 28 */
+ 10254, /* depth = 29 */
+ 4905, /* depth = 30 */
+ 1, /* depth = 31 */
+ 716 /* depth = 32 */
+ }
+};
+
+static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
+{
+/* IP address class A, the most significant bit is 0 */
+#define IP_HEAD_MASK_A 0x00000000
+#define IP_HEAD_BIT_NUM_A 1
+
+/* IP address class B, the most significant 2 bits are 10 */
+#define IP_HEAD_MASK_B 0x80000000
+#define IP_HEAD_BIT_NUM_B 2
+
+/* IP address class C, the most significant 3 bits are 110 */
+#define IP_HEAD_MASK_C 0xC0000000
+#define IP_HEAD_BIT_NUM_C 3
+
+ uint32_t class_depth;
+ uint32_t range;
+ uint32_t mask;
+ uint32_t step;
+ uint32_t start;
+ uint32_t fixed_bit_num;
+ uint32_t ip_head_mask;
+ uint32_t rule_num;
+ uint32_t k;
+ struct route_rule *ptr_rule;
+
+ if (ip_class == IP_CLASS_A) { /* IP Address class A */
+ fixed_bit_num = IP_HEAD_BIT_NUM_A;
+ ip_head_mask = IP_HEAD_MASK_A;
+ rule_num = rule_count.a[depth - 1];
+ } else if (ip_class == IP_CLASS_B) { /* IP Address class B */
+ fixed_bit_num = IP_HEAD_BIT_NUM_B;
+ ip_head_mask = IP_HEAD_MASK_B;
+ rule_num = rule_count.b[depth - 1];
+ } else { /* IP Address class C */
+ fixed_bit_num = IP_HEAD_BIT_NUM_C;
+ ip_head_mask = IP_HEAD_MASK_C;
+ rule_num = rule_count.c[depth - 1];
+ }
+
+ if (rule_num == 0)
+ return;
+
+ /* the number of rest bits which don't include the most significant
+ * fixed bits for this IP address class
+ */
+ class_depth = depth - fixed_bit_num;
+
+ /* range is the maximum number of rules for this depth and
+ * this IP address class
+ */
+ range = 1 << class_depth;
+
+ /* only mask the most depth significant generated bits
+ * except fixed bits for IP address class
+ */
+ mask = range - 1;
+
+ /* Widen coverage of IP address in generated rules */
+ if (range <= rule_num)
+ step = 1;
+ else
+ step = round((double)range / rule_num);
+
+ /* Only generate rest bits except the most significant
+ * fixed bits for IP address class
+ */
+ start = lrand48() & mask;
+ ptr_rule = &large_route_table[num_route_entries];
+ for (k = 0; k < rule_num; k++) {
+ ptr_rule->ip = (start << (RTE_FIB_MAX_DEPTH - depth))
+ | ip_head_mask;
+ ptr_rule->depth = depth;
+ ptr_rule++;
+ start = (start + step) & mask;
+ }
+ num_route_entries += rule_num;
+}
+
+static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
+{
+ uint32_t pos;
+ int try_count = 0;
+ struct route_rule tmp;
+
+ do {
+ pos = lrand48();
+ try_count++;
+ } while ((try_count < 10) && (pos > num_route_entries));
+
+ if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
+ pos = num_route_entries >> 1;
+
+ tmp = large_route_table[pos];
+ large_route_table[pos].ip = ip;
+ large_route_table[pos].depth = depth;
+ if (num_route_entries < MAX_RULE_NUM)
+ large_route_table[num_route_entries++] = tmp;
+}
+
+static void generate_large_route_rule_table(void)
+{
+ uint32_t ip_class;
+ uint8_t depth;
+
+ num_route_entries = 0;
+ memset(large_route_table, 0, sizeof(large_route_table));
+
+ for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
+ for (depth = 1; depth <= RTE_FIB_MAX_DEPTH; depth++)
+ generate_random_rule_prefix(ip_class, depth);
+ }
+
+ /* Add following rules to keep same as previous large constant table,
+ * they are 4 rules with private local IP address and 1 all-zeros prefix
+ * with depth = 8.
+ */
+ insert_rule_in_random_pos(RTE_IPV4(0, 0, 0, 0), 8);
+ insert_rule_in_random_pos(RTE_IPV4(10, 2, 23, 147), 32);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 100, 10), 24);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 25, 100), 24);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 129, 124), 32);
+}
+
+static void
+print_route_distribution(const struct route_rule *table, uint32_t n)
+{
+ unsigned int i, j;
+
+ printf("Route distribution per prefix width:\n");
+ printf("DEPTH QUANTITY (PERCENT)\n");
+ printf("---------------------------\n");
+
+ /* Count depths. */
+ for (i = 1; i <= 32; i++) {
+ unsigned int depth_counter = 0;
+ double percent_hits;
+
+ for (j = 0; j < n; j++)
+ if (table[j].depth == (uint8_t) i)
+ depth_counter++;
+
+ percent_hits = ((double)depth_counter)/((double)n) * 100;
+ printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
+ }
+ printf("\n");
+}
+
+static int
+test_fib_perf(void)
+{
+ struct rte_fib *fib = NULL;
+ struct rte_fib_conf config;
+
+ config.max_routes = 2000000;
+ config.type = RTE_FIB_DIR24_8;
+ config.default_nh = 0;
+ config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
+ config.dir24_8.num_tbl8 = 65535;
+ uint64_t begin, total_time;
+ unsigned int i, j;
+ uint32_t next_hop_add = 0xAA;
+ int status = 0;
+ int64_t count = 0;
+
+ rte_srand(rte_rdtsc());
+
+ generate_large_route_rule_table();
+
+ printf("No. routes = %u\n", (unsigned int) NUM_ROUTE_ENTRIES);
+
+ print_route_distribution(large_route_table,
+ (uint32_t) NUM_ROUTE_ENTRIES);
+
+ fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_FIB_ASSERT(fib != NULL);
+
+ /* Measue add. */
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ if (rte_fib_add(fib, large_route_table[i].ip,
+ large_route_table[i].depth, next_hop_add) == 0)
+ status++;
+ }
+ /* End Timer. */
+ total_time = rte_rdtsc() - begin;
+
+ printf("Unique added entries = %d\n", status);
+
+ printf("Average FIB Add: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ /* Measure bulk Lookup */
+ total_time = 0;
+ count = 0;
+ for (i = 0; i < ITERATIONS; i++) {
+ static uint32_t ip_batch[BATCH_SIZE];
+ uint64_t next_hops[BULK_SIZE];
+
+ /* Create array of random IP addresses */
+ for (j = 0; j < BATCH_SIZE; j++)
+ ip_batch[j] = rte_rand();
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+ for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
+ uint32_t k;
+ rte_fib_lookup_bulk(fib, &ip_batch[j], next_hops,
+ BULK_SIZE);
+ for (k = 0; k < BULK_SIZE; k++)
+ if (unlikely(!(next_hops[k] != 0)))
+ count++;
+ }
+
+ total_time += rte_rdtsc() - begin;
+ }
+ printf("BULK FIB Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Delete */
+ status = 0;
+ begin = rte_rdtsc();
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ /* rte_lpm_delete(lpm, ip, depth) */
+ status += rte_fib_delete(fib, large_route_table[i].ip,
+ large_route_table[i].depth);
+ }
+
+ total_time += rte_rdtsc() - begin;
+
+ printf("Average FIB Delete: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ rte_fib_free(fib);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(fib_perf_autotest, test_fib_perf);
diff --git a/src/spdk/dpdk/app/test/test_flow_classify.c b/src/spdk/dpdk/app/test/test_flow_classify.c
new file mode 100644
index 000000000..ef0b6fdd5
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_flow_classify.c
@@ -0,0 +1,876 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include "test.h"
+
+#include <rte_string_fns.h>
+#include <rte_mbuf.h>
+#include <rte_byteorder.h>
+#include <rte_ip.h>
+#include <rte_acl.h>
+#include <rte_common.h>
+#include <rte_table_acl.h>
+#include <rte_flow.h>
+#include <rte_flow_classify.h>
+
+#include "packet_burst_generator.h"
+#include "test_flow_classify.h"
+
+
+#define FLOW_CLASSIFY_MAX_RULE_NUM 100
+#define MAX_PKT_BURST 32
+#define NB_SOCKETS 4
+#define MEMPOOL_CACHE_SIZE 256
+#define MBUF_SIZE 512
+#define NB_MBUF 512
+
+/* test UDP, TCP and SCTP packets */
+static struct rte_mempool *mbufpool[NB_SOCKETS];
+static struct rte_mbuf *bufs[MAX_PKT_BURST];
+
+static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+ /* first input field - always one byte long. */
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_INPUT_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, next_proto_id),
+ },
+ /* next input field (IPv4 source address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_INPUT_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, src_addr),
+ },
+ /* next input field (IPv4 destination address) - 4 consecutive bytes. */
+ {
+ /* rte_flow uses a bit mask for IPv4 addresses */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_INPUT_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ offsetof(struct rte_ipv4_hdr, dst_addr),
+ },
+ /*
+ * Next 2 fields (src & dst ports) form 4 consecutive bytes.
+ * They share the same input index.
+ */
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr) +
+ offsetof(struct rte_tcp_hdr, src_port),
+ },
+ {
+ /* rte_flow uses a bit mask for protocol ports */
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_DESTP_INPUT_IPV4,
+ .offset = sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_ipv4_hdr) +
+ offsetof(struct rte_tcp_hdr, dst_port),
+ },
+};
+
+/* parameters for rte_flow_classify_validate and rte_flow_classify_create */
+
+/* test UDP pattern:
+ * "eth / ipv4 src spec 2.2.2.3 src mask 255.255.255.00 dst spec 2.2.2.7
+ * dst mask 255.255.255.00 / udp src is 32 dst is 33 / end"
+ */
+static struct rte_flow_item_ipv4 ipv4_udp_spec_1 = {
+ { 0, 0, 0, 0, 0, 0, IPPROTO_UDP, 0,
+ RTE_IPV4(2, 2, 2, 3), RTE_IPV4(2, 2, 2, 7)}
+};
+static const struct rte_flow_item_ipv4 ipv4_mask_24 = {
+ .hdr = {
+ .next_proto_id = 0xff,
+ .src_addr = 0xffffff00,
+ .dst_addr = 0xffffff00,
+ },
+};
+static struct rte_flow_item_udp udp_spec_1 = {
+ { 32, 33, 0, 0 }
+};
+
+static struct rte_flow_item eth_item = { RTE_FLOW_ITEM_TYPE_ETH,
+ 0, 0, 0 };
+static struct rte_flow_item eth_item_bad = { -1, 0, 0, 0 };
+
+static struct rte_flow_item ipv4_udp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
+ &ipv4_udp_spec_1, 0, &ipv4_mask_24};
+static struct rte_flow_item ipv4_udp_item_bad = { RTE_FLOW_ITEM_TYPE_IPV4,
+ NULL, 0, NULL};
+
+static struct rte_flow_item udp_item_1 = { RTE_FLOW_ITEM_TYPE_UDP,
+ &udp_spec_1, 0, &rte_flow_item_udp_mask};
+static struct rte_flow_item udp_item_bad = { RTE_FLOW_ITEM_TYPE_UDP,
+ NULL, 0, NULL};
+
+static struct rte_flow_item end_item = { RTE_FLOW_ITEM_TYPE_END,
+ 0, 0, 0 };
+
+/* test TCP pattern:
+ * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
+ * dst mask 255.255.255.00 / tcp src is 16 dst is 17 / end"
+ */
+static struct rte_flow_item_ipv4 ipv4_tcp_spec_1 = {
+ { 0, 0, 0, 0, 0, 0, IPPROTO_TCP, 0,
+ RTE_IPV4(1, 2, 3, 4), RTE_IPV4(5, 6, 7, 8)}
+};
+
+static struct rte_flow_item_tcp tcp_spec_1 = {
+ { 16, 17, 0, 0, 0, 0, 0, 0, 0}
+};
+
+static struct rte_flow_item ipv4_tcp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
+ &ipv4_tcp_spec_1, 0, &ipv4_mask_24};
+
+static struct rte_flow_item tcp_item_1 = { RTE_FLOW_ITEM_TYPE_TCP,
+ &tcp_spec_1, 0, &rte_flow_item_tcp_mask};
+
+/* test SCTP pattern:
+ * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
+ * dst mask 255.255.255.00 / sctp src is 16 dst is 17/ end"
+ */
+static struct rte_flow_item_ipv4 ipv4_sctp_spec_1 = {
+ { 0, 0, 0, 0, 0, 0, IPPROTO_SCTP, 0, RTE_IPV4(11, 12, 13, 14),
+ RTE_IPV4(15, 16, 17, 18)}
+};
+
+static struct rte_flow_item_sctp sctp_spec_1 = {
+ { 10, 11, 0, 0}
+};
+
+static struct rte_flow_item ipv4_sctp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
+ &ipv4_sctp_spec_1, 0, &ipv4_mask_24};
+
+static struct rte_flow_item sctp_item_1 = { RTE_FLOW_ITEM_TYPE_SCTP,
+ &sctp_spec_1, 0, &rte_flow_item_sctp_mask};
+
+
+/* test actions:
+ * "actions count / end"
+ */
+static struct rte_flow_query_count count = {
+ .reset = 1,
+ .hits_set = 1,
+ .bytes_set = 1,
+ .hits = 0,
+ .bytes = 0,
+};
+static struct rte_flow_action count_action = { RTE_FLOW_ACTION_TYPE_COUNT,
+ &count};
+static struct rte_flow_action count_action_bad = { -1, 0};
+
+static struct rte_flow_action end_action = { RTE_FLOW_ACTION_TYPE_END, 0};
+
+static struct rte_flow_action actions[2];
+
+/* test attributes */
+static struct rte_flow_attr attr;
+
+/* test error */
+static struct rte_flow_error error;
+
+/* test pattern */
+static struct rte_flow_item pattern[4];
+
+/* flow classify data for UDP burst */
+static struct rte_flow_classify_ipv4_5tuple_stats udp_ntuple_stats;
+static struct rte_flow_classify_stats udp_classify_stats = {
+ .stats = (void *)&udp_ntuple_stats
+};
+
+/* flow classify data for TCP burst */
+static struct rte_flow_classify_ipv4_5tuple_stats tcp_ntuple_stats;
+static struct rte_flow_classify_stats tcp_classify_stats = {
+ .stats = (void *)&tcp_ntuple_stats
+};
+
+/* flow classify data for SCTP burst */
+static struct rte_flow_classify_ipv4_5tuple_stats sctp_ntuple_stats;
+static struct rte_flow_classify_stats sctp_classify_stats = {
+ .stats = (void *)&sctp_ntuple_stats
+};
+
+struct flow_classifier_acl *cls;
+
+struct flow_classifier_acl {
+ struct rte_flow_classifier *cls;
+} __rte_cache_aligned;
+
+/*
+ * test functions by passing invalid or
+ * non-workable parameters.
+ */
+static int
+test_invalid_parameters(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+
+ ret = rte_flow_classify_validate(NULL, NULL, NULL, NULL, NULL);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_validate",
+ __LINE__);
+ printf(" with NULL param should have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
+ NULL, NULL);
+ if (rule) {
+ printf("Line %i: flow_classifier_table_entry_add", __LINE__);
+ printf(" with NULL param should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(NULL, NULL);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" with NULL param should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
+ if (!ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" with NULL param should have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
+ NULL, &error);
+ if (rule) {
+ printf("Line %i: flow_classify_table_entry_add ", __LINE__);
+ printf("with NULL param should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(NULL, NULL);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf("with NULL param should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
+ if (!ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" with NULL param should have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_valid_parameters(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int key_found;
+
+ /*
+ * set up parameters for rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_udp_item_1;
+ pattern[2] = udp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action;
+ actions[1] = end_action;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_validate",
+ __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+
+ if (!rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_invalid_patterns(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int key_found;
+
+ /*
+ * set up parameters for rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item_bad;
+ pattern[1] = ipv4_udp_item_1;
+ pattern[2] = udp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action;
+ actions[1] = end_action;
+
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_udp_item_bad;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_validate", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ pattern[1] = ipv4_udp_item_1;
+ pattern[2] = udp_item_bad;
+ pattern[3] = end_item;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_validate", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_invalid_actions(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int key_found;
+
+ /*
+ * set up parameters for rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_udp_item_1;
+ pattern[2] = udp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action_bad;
+ actions[1] = end_action;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_validate", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (!ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should have failed!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+init_ipv4_udp_traffic(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, uint32_t burst_size)
+{
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_ipv4_hdr pkt_ipv4_hdr;
+ struct rte_udp_hdr pkt_udp_hdr;
+ uint32_t src_addr = IPV4_ADDR(2, 2, 2, 3);
+ uint32_t dst_addr = IPV4_ADDR(2, 2, 2, 7);
+ uint16_t src_port = 32;
+ uint16_t dst_port = 33;
+ uint16_t pktlen;
+
+ static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+ static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+
+ printf("Set up IPv4 UDP traffic\n");
+ initialize_eth_header(&pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
+ pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
+ printf("ETH pktlen %u\n", pktlen);
+
+ pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, src_addr, dst_addr,
+ pktlen);
+ printf("ETH + IPv4 pktlen %u\n", pktlen);
+
+ pktlen = initialize_udp_header(&pkt_udp_hdr, src_port, dst_port,
+ pktlen);
+ printf("ETH + IPv4 + UDP pktlen %u\n\n", pktlen);
+
+ return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr,
+ 0, &pkt_ipv4_hdr, 1,
+ &pkt_udp_hdr, burst_size,
+ PACKET_BURST_GEN_PKT_LEN, 1);
+}
+
+static int
+init_ipv4_tcp_traffic(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, uint32_t burst_size)
+{
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_ipv4_hdr pkt_ipv4_hdr;
+ struct rte_tcp_hdr pkt_tcp_hdr;
+ uint32_t src_addr = IPV4_ADDR(1, 2, 3, 4);
+ uint32_t dst_addr = IPV4_ADDR(5, 6, 7, 8);
+ uint16_t src_port = 16;
+ uint16_t dst_port = 17;
+ uint16_t pktlen;
+
+ static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+ static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+
+ printf("Set up IPv4 TCP traffic\n");
+ initialize_eth_header(&pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
+ pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
+ printf("ETH pktlen %u\n", pktlen);
+
+ pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
+ dst_addr, pktlen, IPPROTO_TCP);
+ printf("ETH + IPv4 pktlen %u\n", pktlen);
+
+ pktlen = initialize_tcp_header(&pkt_tcp_hdr, src_port, dst_port,
+ pktlen);
+ printf("ETH + IPv4 + TCP pktlen %u\n\n", pktlen);
+
+ return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
+ 0, &pkt_ipv4_hdr, 1, IPPROTO_TCP,
+ &pkt_tcp_hdr, burst_size,
+ PACKET_BURST_GEN_PKT_LEN, 1);
+}
+
+static int
+init_ipv4_sctp_traffic(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, uint32_t burst_size)
+{
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_ipv4_hdr pkt_ipv4_hdr;
+ struct rte_sctp_hdr pkt_sctp_hdr;
+ uint32_t src_addr = IPV4_ADDR(11, 12, 13, 14);
+ uint32_t dst_addr = IPV4_ADDR(15, 16, 17, 18);
+ uint16_t src_port = 10;
+ uint16_t dst_port = 11;
+ uint16_t pktlen;
+
+ static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+ static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+
+ printf("Set up IPv4 SCTP traffic\n");
+ initialize_eth_header(&pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
+ pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
+ printf("ETH pktlen %u\n", pktlen);
+
+ pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
+ dst_addr, pktlen, IPPROTO_SCTP);
+ printf("ETH + IPv4 pktlen %u\n", pktlen);
+
+ pktlen = initialize_sctp_header(&pkt_sctp_hdr, src_port, dst_port,
+ pktlen);
+ printf("ETH + IPv4 + SCTP pktlen %u\n\n", pktlen);
+
+ return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
+ 0, &pkt_ipv4_hdr, 1, IPPROTO_SCTP,
+ &pkt_sctp_hdr, burst_size,
+ PACKET_BURST_GEN_PKT_LEN, 1);
+}
+
+static int
+init_mbufpool(void)
+{
+ int socketid;
+ int ret = 0;
+ unsigned int lcore_id;
+ char s[64];
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (rte_lcore_is_enabled(lcore_id) == 0)
+ continue;
+
+ socketid = rte_lcore_to_socket_id(lcore_id);
+ if (socketid >= NB_SOCKETS) {
+ printf(
+ "Socket %d of lcore %u is out of range %d\n",
+ socketid, lcore_id, NB_SOCKETS);
+ ret = -1;
+ break;
+ }
+ if (mbufpool[socketid] == NULL) {
+ snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
+ mbufpool[socketid] =
+ rte_pktmbuf_pool_create(s, NB_MBUF,
+ MEMPOOL_CACHE_SIZE, 0, MBUF_SIZE,
+ socketid);
+ if (mbufpool[socketid]) {
+ printf("Allocated mbuf pool on socket %d\n",
+ socketid);
+ } else {
+ printf("Cannot init mbuf pool on socket %d\n",
+ socketid);
+ ret = -ENOMEM;
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+static int
+test_query_udp(void)
+{
+ struct rte_flow_error error;
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int i;
+ int key_found;
+
+ ret = init_ipv4_udp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
+ if (ret != MAX_PKT_BURST) {
+ printf("Line %i: init_udp_ipv4_traffic has failed!\n",
+ __LINE__);
+ return -1;
+ }
+
+ for (i = 0; i < MAX_PKT_BURST; i++)
+ bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
+
+ /*
+ * set up parameters for rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_udp_item_1;
+ pattern[2] = udp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action;
+ actions[1] = end_action;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_validate", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (!rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
+ rule, &udp_classify_stats);
+ if (ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_query_tcp(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int i;
+ int key_found;
+
+ ret = init_ipv4_tcp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
+ if (ret != MAX_PKT_BURST) {
+ printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
+ __LINE__);
+ return -1;
+ }
+
+ for (i = 0; i < MAX_PKT_BURST; i++)
+ bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
+
+ /*
+ * set up parameters for rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_tcp_item_1;
+ pattern[2] = tcp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action;
+ actions[1] = end_action;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (!rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
+ rule, &tcp_classify_stats);
+ if (ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_query_sctp(void)
+{
+ struct rte_flow_classify_rule *rule;
+ int ret;
+ int i;
+ int key_found;
+
+ ret = init_ipv4_sctp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
+ if (ret != MAX_PKT_BURST) {
+ printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
+ __LINE__);
+ return -1;
+ }
+
+ for (i = 0; i < MAX_PKT_BURST; i++)
+ bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
+
+ /*
+ * set up parameters rte_flow_classify_validate,
+ * rte_flow_classify_table_entry_add and
+ * rte_flow_classify_table_entry_delete
+ */
+
+ attr.ingress = 1;
+ attr.priority = 1;
+ pattern[0] = eth_item;
+ pattern[1] = ipv4_sctp_item_1;
+ pattern[2] = sctp_item_1;
+ pattern[3] = end_item;
+ actions[0] = count_action;
+ actions[1] = end_action;
+
+ ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
+ actions, &error);
+ if (ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
+ actions, &key_found, &error);
+ if (!rule) {
+ printf("Line %i: flow_classify_table_entry_add", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
+ rule, &sctp_classify_stats);
+ if (ret) {
+ printf("Line %i: flow_classifier_query", __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+
+ ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
+ if (ret) {
+ printf("Line %i: rte_flow_classify_table_entry_delete",
+ __LINE__);
+ printf(" should not have failed!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_flow_classify(void)
+{
+ struct rte_table_acl_params table_acl_params;
+ struct rte_flow_classify_table_params cls_table_params;
+ struct rte_flow_classifier_params cls_params;
+ int ret;
+ uint32_t size;
+
+ /* Memory allocation */
+ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl));
+ cls = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
+
+ cls_params.name = "flow_classifier";
+ cls_params.socket_id = 0;
+ cls->cls = rte_flow_classifier_create(&cls_params);
+
+ /* initialise ACL table params */
+ table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
+ table_acl_params.name = "table_acl_ipv4_5tuple";
+ table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
+ memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+
+ /* initialise table create params */
+ cls_table_params.ops = &rte_table_acl_ops;
+ cls_table_params.arg_create = &table_acl_params;
+ cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
+
+ ret = rte_flow_classify_table_create(cls->cls, &cls_table_params);
+ if (ret) {
+ printf("Line %i: f_create has failed!\n", __LINE__);
+ rte_flow_classifier_free(cls->cls);
+ rte_free(cls);
+ return TEST_FAILED;
+ }
+ printf("Created table_acl for for IPv4 five tuple packets\n");
+
+ ret = init_mbufpool();
+ if (ret) {
+ printf("Line %i: init_mbufpool has failed!\n", __LINE__);
+ return TEST_FAILED;
+ }
+
+ if (test_invalid_parameters() < 0)
+ return TEST_FAILED;
+ if (test_valid_parameters() < 0)
+ return TEST_FAILED;
+ if (test_invalid_patterns() < 0)
+ return TEST_FAILED;
+ if (test_invalid_actions() < 0)
+ return TEST_FAILED;
+ if (test_query_udp() < 0)
+ return TEST_FAILED;
+ if (test_query_tcp() < 0)
+ return TEST_FAILED;
+ if (test_query_sctp() < 0)
+ return TEST_FAILED;
+
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(flow_classify_autotest, test_flow_classify);
diff --git a/src/spdk/dpdk/app/test/test_flow_classify.h b/src/spdk/dpdk/app/test/test_flow_classify.h
new file mode 100644
index 000000000..6bd10ec97
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_flow_classify.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef TEST_FLOW_CLASSIFY_H_
+#define TEST_FLOW_CLASSIFY_H_
+
+/* ACL field definitions for IPv4 5 tuple rule */
+
+enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+};
+
+enum {
+ PROTO_INPUT_IPV4,
+ SRC_INPUT_IPV4,
+ DST_INPUT_IPV4,
+ SRCP_DESTP_INPUT_IPV4
+};
+
+#endif /* TEST_FLOW_CLASSIFY_H_ */
diff --git a/src/spdk/dpdk/app/test/test_func_reentrancy.c b/src/spdk/dpdk/app/test/test_func_reentrancy.c
new file mode 100644
index 000000000..f5ddd03d7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_func_reentrancy.c
@@ -0,0 +1,498 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_spinlock.h>
+#include <rte_malloc.h>
+
+#ifdef RTE_LIBRTE_HASH
+#include <rte_hash.h>
+#include <rte_fbk_hash.h>
+#include <rte_jhash.h>
+#endif /* RTE_LIBRTE_HASH */
+
+#ifdef RTE_LIBRTE_LPM
+#include <rte_lpm.h>
+#endif /* RTE_LIBRTE_LPM */
+
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+typedef int (*case_func_t)(void* arg);
+typedef void (*case_clean_t)(unsigned lcore_id);
+
+#define MAX_STRING_SIZE (256)
+#define MAX_ITER_MULTI (16)
+#define MAX_ITER_ONCE (4)
+#define MAX_LPM_ITER_TIMES (6)
+
+#define MEMPOOL_ELT_SIZE (sizeof(uint32_t))
+#define MEMPOOL_SIZE (4)
+
+#define MAX_LCORES (RTE_MAX_MEMZONE / (MAX_ITER_MULTI * 4U))
+
+static rte_atomic32_t obj_count = RTE_ATOMIC32_INIT(0);
+static rte_atomic32_t synchro = RTE_ATOMIC32_INIT(0);
+
+#define WAIT_SYNCHRO_FOR_SLAVES() do{ \
+ if (lcore_self != rte_get_master_lcore()) \
+ while (rte_atomic32_read(&synchro) == 0); \
+} while(0)
+
+/*
+ * rte_eal_init only init once
+ */
+static int
+test_eal_init_once(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ rte_atomic32_set(&obj_count, 1); /* silent the check in the caller */
+ if (rte_eal_init(0, NULL) != -1)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * ring create/lookup reentrancy test
+ */
+static void
+ring_clean(unsigned int lcore_id)
+{
+ struct rte_ring *rp;
+ char ring_name[MAX_STRING_SIZE];
+ int i;
+
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(ring_name, sizeof(ring_name),
+ "fr_test_%d_%d", lcore_id, i);
+ rp = rte_ring_lookup(ring_name);
+ if (rp != NULL)
+ rte_ring_free(rp);
+ }
+}
+
+static int
+ring_create_lookup(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+ struct rte_ring * rp;
+ char ring_name[MAX_STRING_SIZE];
+ int i;
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ /* create the same ring simultaneously on all threads */
+ for (i = 0; i < MAX_ITER_ONCE; i++) {
+ rp = rte_ring_create("fr_test_once", 4096, SOCKET_ID_ANY, 0);
+ if (rp != NULL)
+ rte_atomic32_inc(&obj_count);
+ }
+
+ /* create/lookup new ring several times */
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(ring_name, sizeof(ring_name), "fr_test_%d_%d", lcore_self, i);
+ rp = rte_ring_create(ring_name, 4096, SOCKET_ID_ANY, 0);
+ if (NULL == rp)
+ return -1;
+ if (rte_ring_lookup(ring_name) != rp)
+ return -1;
+
+ /* verify all ring created successful */
+ if (rte_ring_lookup(ring_name) == NULL)
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+my_obj_init(struct rte_mempool *mp, __rte_unused void *arg,
+ void *obj, unsigned i)
+{
+ uint32_t *objnum = obj;
+ memset(obj, 0, mp->elt_size);
+ *objnum = i;
+}
+
+static void
+mempool_clean(unsigned int lcore_id)
+{
+ struct rte_mempool *mp;
+ char mempool_name[MAX_STRING_SIZE];
+ int i;
+
+ /* verify all ring created successful */
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(mempool_name, sizeof(mempool_name), "fr_test_%d_%d",
+ lcore_id, i);
+ mp = rte_mempool_lookup(mempool_name);
+ if (mp != NULL)
+ rte_mempool_free(mp);
+ }
+}
+
+static int
+mempool_create_lookup(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+ struct rte_mempool * mp;
+ char mempool_name[MAX_STRING_SIZE];
+ int i;
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ /* create the same mempool simultaneously on all threads */
+ for (i = 0; i < MAX_ITER_ONCE; i++) {
+ mp = rte_mempool_create("fr_test_once", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+ if (mp != NULL)
+ rte_atomic32_inc(&obj_count);
+ }
+
+ /* create/lookup new ring several times */
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(mempool_name, sizeof(mempool_name), "fr_test_%d_%d", lcore_self, i);
+ mp = rte_mempool_create(mempool_name, MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+ if (NULL == mp)
+ return -1;
+ if (rte_mempool_lookup(mempool_name) != mp)
+ return -1;
+
+ /* verify all ring created successful */
+ if (rte_mempool_lookup(mempool_name) == NULL)
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef RTE_LIBRTE_HASH
+static void
+hash_clean(unsigned lcore_id)
+{
+ char hash_name[MAX_STRING_SIZE];
+ struct rte_hash *handle;
+ int i;
+
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(hash_name, sizeof(hash_name), "fr_test_%d_%d", lcore_id, i);
+
+ if ((handle = rte_hash_find_existing(hash_name)) != NULL)
+ rte_hash_free(handle);
+ }
+}
+
+static int
+hash_create_free(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+ struct rte_hash *handle;
+ char hash_name[MAX_STRING_SIZE];
+ int i;
+ struct rte_hash_parameters hash_params = {
+ .name = NULL,
+ .entries = 16,
+ .key_len = 4,
+ .hash_func = (rte_hash_function)rte_jhash_32b,
+ .hash_func_init_val = 0,
+ .socket_id = 0,
+ };
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ /* create the same hash simultaneously on all threads */
+ hash_params.name = "fr_test_once";
+ for (i = 0; i < MAX_ITER_ONCE; i++) {
+ handle = rte_hash_create(&hash_params);
+ if (handle != NULL)
+ rte_atomic32_inc(&obj_count);
+ }
+
+ /* create mutiple times simultaneously */
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(hash_name, sizeof(hash_name), "fr_test_%d_%d", lcore_self, i);
+ hash_params.name = hash_name;
+
+ handle = rte_hash_create(&hash_params);
+ if (NULL == handle)
+ return -1;
+
+ /* verify correct existing and then free all */
+ if (handle != rte_hash_find_existing(hash_name))
+ return -1;
+
+ rte_hash_free(handle);
+
+ /* verify free correct */
+ if (NULL != rte_hash_find_existing(hash_name))
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+fbk_clean(unsigned lcore_id)
+{
+ char fbk_name[MAX_STRING_SIZE];
+ struct rte_fbk_hash_table *handle;
+ int i;
+
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(fbk_name, sizeof(fbk_name), "fr_test_%d_%d", lcore_id, i);
+
+ if ((handle = rte_fbk_hash_find_existing(fbk_name)) != NULL)
+ rte_fbk_hash_free(handle);
+ }
+}
+
+static int
+fbk_create_free(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+ struct rte_fbk_hash_table *handle;
+ char fbk_name[MAX_STRING_SIZE];
+ int i;
+ struct rte_fbk_hash_params fbk_params = {
+ .name = NULL,
+ .entries = 4,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ .hash_func = rte_jhash_1word,
+ .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
+ };
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ /* create the same fbk hash table simultaneously on all threads */
+ fbk_params.name = "fr_test_once";
+ for (i = 0; i < MAX_ITER_ONCE; i++) {
+ handle = rte_fbk_hash_create(&fbk_params);
+ if (handle != NULL)
+ rte_atomic32_inc(&obj_count);
+ }
+
+ /* create mutiple fbk tables simultaneously */
+ for (i = 0; i < MAX_ITER_MULTI; i++) {
+ snprintf(fbk_name, sizeof(fbk_name), "fr_test_%d_%d", lcore_self, i);
+ fbk_params.name = fbk_name;
+
+ handle = rte_fbk_hash_create(&fbk_params);
+ if (NULL == handle)
+ return -1;
+
+ /* verify correct existing and then free all */
+ if (handle != rte_fbk_hash_find_existing(fbk_name))
+ return -1;
+
+ rte_fbk_hash_free(handle);
+
+ /* verify free correct */
+ if (NULL != rte_fbk_hash_find_existing(fbk_name))
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* RTE_LIBRTE_HASH */
+
+#ifdef RTE_LIBRTE_LPM
+static void
+lpm_clean(unsigned int lcore_id)
+{
+ char lpm_name[MAX_STRING_SIZE];
+ struct rte_lpm *lpm;
+ int i;
+
+ for (i = 0; i < MAX_LPM_ITER_TIMES; i++) {
+ snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", lcore_id, i);
+
+ if ((lpm = rte_lpm_find_existing(lpm_name)) != NULL)
+ rte_lpm_free(lpm);
+ }
+}
+
+static int
+lpm_create_free(__rte_unused void *arg)
+{
+ unsigned lcore_self = rte_lcore_id();
+ struct rte_lpm *lpm;
+ struct rte_lpm_config config;
+
+ config.max_rules = 4;
+ config.number_tbl8s = 256;
+ config.flags = 0;
+ char lpm_name[MAX_STRING_SIZE];
+ int i;
+
+ WAIT_SYNCHRO_FOR_SLAVES();
+
+ /* create the same lpm simultaneously on all threads */
+ for (i = 0; i < MAX_ITER_ONCE; i++) {
+ lpm = rte_lpm_create("fr_test_once", SOCKET_ID_ANY, &config);
+ if (lpm != NULL)
+ rte_atomic32_inc(&obj_count);
+ }
+
+ /* create mutiple fbk tables simultaneously */
+ for (i = 0; i < MAX_LPM_ITER_TIMES; i++) {
+ snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", lcore_self, i);
+ lpm = rte_lpm_create(lpm_name, SOCKET_ID_ANY, &config);
+ if (NULL == lpm)
+ return -1;
+
+ /* verify correct existing and then free all */
+ if (lpm != rte_lpm_find_existing(lpm_name))
+ return -1;
+
+ rte_lpm_free(lpm);
+
+ /* verify free correct */
+ if (NULL != rte_lpm_find_existing(lpm_name))
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* RTE_LIBRTE_LPM */
+
+struct test_case{
+ case_func_t func;
+ void* arg;
+ case_clean_t clean;
+ char name[MAX_STRING_SIZE];
+};
+
+/* All test cases in the test suite */
+struct test_case test_cases[] = {
+ { test_eal_init_once, NULL, NULL, "eal init once" },
+ { ring_create_lookup, NULL, ring_clean, "ring create/lookup" },
+ { mempool_create_lookup, NULL, mempool_clean,
+ "mempool create/lookup" },
+#ifdef RTE_LIBRTE_HASH
+ { hash_create_free, NULL, hash_clean, "hash create/free" },
+ { fbk_create_free, NULL, fbk_clean, "fbk create/free" },
+#endif /* RTE_LIBRTE_HASH */
+#ifdef RTE_LIBRTE_LPM
+ { lpm_create_free, NULL, lpm_clean, "lpm create/free" },
+#endif /* RTE_LIBRTE_LPM */
+};
+
+/**
+ * launch test case in two separate thread
+ */
+static int
+launch_test(struct test_case *pt_case)
+{
+ int ret = 0;
+ unsigned lcore_id;
+ unsigned cores_save = rte_lcore_count();
+ unsigned cores = RTE_MIN(cores_save, MAX_LCORES);
+ unsigned count;
+
+ if (pt_case->func == NULL)
+ return -1;
+
+ rte_atomic32_set(&obj_count, 0);
+ rte_atomic32_set(&synchro, 0);
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (cores == 1)
+ break;
+ cores--;
+ rte_eal_remote_launch(pt_case->func, pt_case->arg, lcore_id);
+ }
+
+ rte_atomic32_set(&synchro, 1);
+
+ if (pt_case->func(pt_case->arg) < 0)
+ ret = -1;
+
+ cores = cores_save;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (cores == 1)
+ break;
+ cores--;
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ ret = -1;
+
+ if (pt_case->clean != NULL)
+ pt_case->clean(lcore_id);
+ }
+
+ count = rte_atomic32_read(&obj_count);
+ if (count != 1) {
+ printf("%s: common object allocated %d times (should be 1)\n",
+ pt_case->name, count);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+/**
+ * Main entry of func_reentrancy test
+ */
+static int
+test_func_reentrancy(void)
+{
+ uint32_t case_id;
+ struct test_case *pt_case = NULL;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for func_reentrancy_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+ else if (rte_lcore_count() > MAX_LCORES)
+ printf("Too many lcores, some cores will be disabled\n");
+
+ for (case_id = 0; case_id < RTE_DIM(test_cases); case_id++) {
+ pt_case = &test_cases[case_id];
+ if (pt_case->func == NULL)
+ continue;
+
+ if (launch_test(pt_case) < 0) {
+ printf("Func-ReEnt CASE %"PRIu32": %s FAIL\n", case_id, pt_case->name);
+ return -1;
+ }
+ printf("Func-ReEnt CASE %"PRIu32": %s PASS\n", case_id, pt_case->name);
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(func_reentrancy_autotest, test_func_reentrancy);
diff --git a/src/spdk/dpdk/app/test/test_graph.c b/src/spdk/dpdk/app/test/test_graph.c
new file mode 100644
index 000000000..ed69eda99
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_graph.c
@@ -0,0 +1,821 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+#include <assert.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_errno.h>
+#include <rte_graph.h>
+#include <rte_graph_worker.h>
+#include <rte_mbuf.h>
+#include <rte_random.h>
+
+#include "test.h"
+
+static uint16_t test_node_worker_source(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs);
+
+static uint16_t test_node0_worker(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs);
+
+static uint16_t test_node1_worker(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs);
+
+static uint16_t test_node2_worker(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs);
+
+static uint16_t test_node3_worker(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs);
+
+#define MBUFF_SIZE 512
+#define MAX_NODES 4
+
+static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE];
+static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE];
+static rte_graph_t graph_id;
+static uint64_t obj_stats[MAX_NODES + 1];
+static uint64_t fn_calls[MAX_NODES + 1];
+
+const char *node_patterns[] = {
+ "test_node_source1", "test_node00",
+ "test_node00-test_node11", "test_node00-test_node22",
+ "test_node00-test_node33",
+};
+
+const char *node_names[] = {
+ "test_node00",
+ "test_node00-test_node11",
+ "test_node00-test_node22",
+ "test_node00-test_node33",
+};
+
+struct test_node_register {
+ char name[RTE_NODE_NAMESIZE];
+ rte_node_process_t process;
+ uint16_t nb_edges;
+ const char *next_nodes[MAX_NODES];
+};
+
+typedef struct {
+ uint32_t idx;
+ struct test_node_register node;
+} test_node_t;
+
+typedef struct {
+ test_node_t test_node[MAX_NODES];
+} test_main_t;
+
+static test_main_t test_main = {
+ .test_node = {
+ {
+ .node = {
+ .name = "test_node00",
+ .process = test_node0_worker,
+ .nb_edges = 2,
+ .next_nodes = {"test_node00-"
+ "test_node11",
+ "test_node00-"
+ "test_node22"},
+ },
+ },
+ {
+ .node = {
+ .name = "test_node11",
+ .process = test_node1_worker,
+ .nb_edges = 1,
+ .next_nodes = {"test_node00-"
+ "test_node22"},
+ },
+ },
+ {
+ .node = {
+ .name = "test_node22",
+ .process = test_node2_worker,
+ .nb_edges = 1,
+ .next_nodes = {"test_node00-"
+ "test_node33"},
+ },
+ },
+ {
+ .node = {
+ .name = "test_node33",
+ .process = test_node3_worker,
+ .nb_edges = 1,
+ .next_nodes = {"test_node00"},
+ },
+ },
+ },
+};
+
+static int
+node_init(const struct rte_graph *graph, struct rte_node *node)
+{
+ RTE_SET_USED(graph);
+ *(uint32_t *)node->ctx = node->id;
+
+ return 0;
+}
+
+static struct rte_node_register test_node_source = {
+ .name = "test_node_source1",
+ .process = test_node_worker_source,
+ .flags = RTE_NODE_SOURCE_F,
+ .nb_edges = 2,
+ .init = node_init,
+ .next_nodes = {"test_node00", "test_node00-test_node11"},
+};
+RTE_NODE_REGISTER(test_node_source);
+
+static struct rte_node_register test_node0 = {
+ .name = "test_node00",
+ .process = test_node0_worker,
+ .init = node_init,
+};
+RTE_NODE_REGISTER(test_node0);
+
+uint16_t
+test_node_worker_source(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ uint32_t obj_node0 = rte_rand() % 100, obj_node1;
+ test_main_t *tm = &test_main;
+ struct rte_mbuf *data;
+ void **next_stream;
+ rte_node_t next;
+ uint32_t i;
+
+ RTE_SET_USED(objs);
+ nb_objs = RTE_GRAPH_BURST_SIZE;
+
+ /* Prepare stream for next node 0 */
+ obj_node0 = nb_objs * obj_node0 * 0.01;
+ next = 0;
+ next_stream = rte_node_next_stream_get(graph, node, next, obj_node0);
+ for (i = 0; i < obj_node0; i++) {
+ data = &mbuf[0][i];
+ data->udata64 = ((uint64_t)tm->test_node[0].idx << 32) | i;
+ if ((i + 1) == obj_node0)
+ data->udata64 |= (1 << 16);
+ next_stream[i] = &mbuf[0][i];
+ }
+ rte_node_next_stream_put(graph, node, next, obj_node0);
+
+ /* Prepare stream for next node 1 */
+ obj_node1 = nb_objs - obj_node0;
+ next = 1;
+ next_stream = rte_node_next_stream_get(graph, node, next, obj_node1);
+ for (i = 0; i < obj_node1; i++) {
+ data = &mbuf[0][obj_node0 + i];
+ data->udata64 = ((uint64_t)tm->test_node[1].idx << 32) | i;
+ if ((i + 1) == obj_node1)
+ data->udata64 |= (1 << 16);
+ next_stream[i] = &mbuf[0][obj_node0 + i];
+ }
+
+ rte_node_next_stream_put(graph, node, next, obj_node1);
+ obj_stats[0] += nb_objs;
+ fn_calls[0] += 1;
+ return nb_objs;
+}
+
+uint16_t
+test_node0_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ test_main_t *tm = &test_main;
+
+ if (*(uint32_t *)node->ctx == test_node0.id) {
+ uint32_t obj_node0 = rte_rand() % 100, obj_node1;
+ struct rte_mbuf *data;
+ uint8_t second_pass = 0;
+ uint32_t count = 0;
+ uint32_t i;
+
+ obj_stats[1] += nb_objs;
+ fn_calls[1] += 1;
+
+ for (i = 0; i < nb_objs; i++) {
+ data = (struct rte_mbuf *)objs[i];
+ if ((data->udata64 >> 32) != tm->test_node[0].idx) {
+ printf("Data idx miss match at node 0, expected"
+ " = %u got = %u\n",
+ tm->test_node[0].idx,
+ (uint32_t)(data->udata64 >> 32));
+ goto end;
+ }
+
+ if ((data->udata64 & 0xffff) != (i - count)) {
+ printf("Expected buff count miss match at "
+ "node 0\n");
+ goto end;
+ }
+
+ if (data->udata64 & (0x1 << 16))
+ count = i + 1;
+ if (data->udata64 & (0x1 << 17))
+ second_pass = 1;
+ }
+
+ if (count != i) {
+ printf("Count mismatch at node 0\n");
+ goto end;
+ }
+
+ obj_node0 = nb_objs * obj_node0 * 0.01;
+ for (i = 0; i < obj_node0; i++) {
+ data = &mbuf[1][i];
+ data->udata64 =
+ ((uint64_t)tm->test_node[1].idx << 32) | i;
+ if ((i + 1) == obj_node0)
+ data->udata64 |= (1 << 16);
+ if (second_pass)
+ data->udata64 |= (1 << 17);
+ }
+ rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[1][0],
+ obj_node0);
+
+ obj_node1 = nb_objs - obj_node0;
+ for (i = 0; i < obj_node1; i++) {
+ data = &mbuf[1][obj_node0 + i];
+ data->udata64 =
+ ((uint64_t)tm->test_node[2].idx << 32) | i;
+ if ((i + 1) == obj_node1)
+ data->udata64 |= (1 << 16);
+ if (second_pass)
+ data->udata64 |= (1 << 17);
+ }
+ rte_node_enqueue(graph, node, 1, (void **)&mbuf_p[1][obj_node0],
+ obj_node1);
+
+ } else if (*(uint32_t *)node->ctx == tm->test_node[1].idx) {
+ test_node1_worker(graph, node, objs, nb_objs);
+ } else if (*(uint32_t *)node->ctx == tm->test_node[2].idx) {
+ test_node2_worker(graph, node, objs, nb_objs);
+ } else if (*(uint32_t *)node->ctx == tm->test_node[3].idx) {
+ test_node3_worker(graph, node, objs, nb_objs);
+ } else {
+ printf("Unexpected node context\n");
+ }
+
+end:
+ return nb_objs;
+}
+
+uint16_t
+test_node1_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ test_main_t *tm = &test_main;
+ uint8_t second_pass = 0;
+ uint32_t obj_node0 = 0;
+ struct rte_mbuf *data;
+ uint32_t count = 0;
+ uint32_t i;
+
+ obj_stats[2] += nb_objs;
+ fn_calls[2] += 1;
+ for (i = 0; i < nb_objs; i++) {
+ data = (struct rte_mbuf *)objs[i];
+ if ((data->udata64 >> 32) != tm->test_node[1].idx) {
+ printf("Data idx miss match at node 1, expected = %u"
+ " got = %u\n",
+ tm->test_node[1].idx,
+ (uint32_t)(data->udata64 >> 32));
+ goto end;
+ }
+
+ if ((data->udata64 & 0xffff) != (i - count)) {
+ printf("Expected buff count miss match at node 1\n");
+ goto end;
+ }
+
+ if (data->udata64 & (0x1 << 16))
+ count = i + 1;
+ if (data->udata64 & (0x1 << 17))
+ second_pass = 1;
+ }
+
+ if (count != i) {
+ printf("Count mismatch at node 1\n");
+ goto end;
+ }
+
+ obj_node0 = nb_objs;
+ for (i = 0; i < obj_node0; i++) {
+ data = &mbuf[2][i];
+ data->udata64 = ((uint64_t)tm->test_node[2].idx << 32) | i;
+ if ((i + 1) == obj_node0)
+ data->udata64 |= (1 << 16);
+ if (second_pass)
+ data->udata64 |= (1 << 17);
+ }
+ rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[2][0], obj_node0);
+
+end:
+ return nb_objs;
+}
+
+uint16_t
+test_node2_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ test_main_t *tm = &test_main;
+ uint8_t second_pass = 0;
+ struct rte_mbuf *data;
+ uint32_t count = 0;
+ uint32_t obj_node0;
+ uint32_t i;
+
+ obj_stats[3] += nb_objs;
+ fn_calls[3] += 1;
+ for (i = 0; i < nb_objs; i++) {
+ data = (struct rte_mbuf *)objs[i];
+ if ((data->udata64 >> 32) != tm->test_node[2].idx) {
+ printf("Data idx miss match at node 2, expected = %u"
+ " got = %u\n",
+ tm->test_node[2].idx,
+ (uint32_t)(data->udata64 >> 32));
+ goto end;
+ }
+
+ if ((data->udata64 & 0xffff) != (i - count)) {
+ printf("Expected buff count miss match at node 2\n");
+ goto end;
+ }
+
+ if (data->udata64 & (0x1 << 16))
+ count = i + 1;
+ if (data->udata64 & (0x1 << 17))
+ second_pass = 1;
+ }
+
+ if (count != i) {
+ printf("Count mismatch at node 2\n");
+ goto end;
+ }
+
+ if (!second_pass) {
+ obj_node0 = nb_objs;
+ for (i = 0; i < obj_node0; i++) {
+ data = &mbuf[3][i];
+ data->udata64 =
+ ((uint64_t)tm->test_node[3].idx << 32) | i;
+ if ((i + 1) == obj_node0)
+ data->udata64 |= (1 << 16);
+ }
+ rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[3][0],
+ obj_node0);
+ }
+
+end:
+ return nb_objs;
+}
+
+uint16_t
+test_node3_worker(struct rte_graph *graph, struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ test_main_t *tm = &test_main;
+ uint8_t second_pass = 0;
+ struct rte_mbuf *data;
+ uint32_t count = 0;
+ uint32_t obj_node0;
+ uint32_t i;
+
+ obj_stats[4] += nb_objs;
+ fn_calls[4] += 1;
+ for (i = 0; i < nb_objs; i++) {
+ data = (struct rte_mbuf *)objs[i];
+ if ((data->udata64 >> 32) != tm->test_node[3].idx) {
+ printf("Data idx miss match at node 3, expected = %u"
+ " got = %u\n",
+ tm->test_node[3].idx,
+ (uint32_t)(data->udata64 >> 32));
+ goto end;
+ }
+
+ if ((data->udata64 & 0xffff) != (i - count)) {
+ printf("Expected buff count miss match at node 3\n");
+ goto end;
+ }
+
+ if (data->udata64 & (0x1 << 16))
+ count = i + 1;
+ if (data->udata64 & (0x1 << 17))
+ second_pass = 1;
+ }
+
+ if (count != i) {
+ printf("Count mismatch at node 3\n");
+ goto end;
+ }
+
+ if (second_pass) {
+ printf("Unexpected buffers are at node 3\n");
+ goto end;
+ } else {
+ obj_node0 = nb_objs * 2;
+ for (i = 0; i < obj_node0; i++) {
+ data = &mbuf[4][i];
+ data->udata64 =
+ ((uint64_t)tm->test_node[0].idx << 32) | i;
+ data->udata64 |= (1 << 17);
+ if ((i + 1) == obj_node0)
+ data->udata64 |= (1 << 16);
+ }
+ rte_node_enqueue(graph, node, 0, (void **)&mbuf_p[4][0],
+ obj_node0);
+ }
+
+end:
+ return nb_objs;
+}
+
+static int
+test_lookup_functions(void)
+{
+ test_main_t *tm = &test_main;
+ int i;
+
+ /* Verify the name with ID */
+ for (i = 1; i < MAX_NODES; i++) {
+ char *name = rte_node_id_to_name(tm->test_node[i].idx);
+ if (strcmp(name, node_names[i]) != 0) {
+ printf("Test node name verify by ID = %d failed "
+ "Expected = %s, got %s\n",
+ i, node_names[i], name);
+ return -1;
+ }
+ }
+
+ /* Verify by name */
+ for (i = 1; i < MAX_NODES; i++) {
+ uint32_t idx = rte_node_from_name(node_names[i]);
+ if (idx != tm->test_node[i].idx) {
+ printf("Test node ID verify by name = %s failed "
+ "Expected = %d, got %d\n",
+ node_names[i], tm->test_node[i].idx, idx);
+ return -1;
+ }
+ }
+
+ /* Verify edge count */
+ for (i = 1; i < MAX_NODES; i++) {
+ uint32_t count = rte_node_edge_count(tm->test_node[i].idx);
+ if (count != tm->test_node[i].node.nb_edges) {
+ printf("Test number of edges for node = %s failed Expected = %d, got = %d\n",
+ tm->test_node[i].node.name,
+ tm->test_node[i].node.nb_edges, count);
+ return -1;
+ }
+ }
+
+ /* Verify edge names */
+ for (i = 1; i < MAX_NODES; i++) {
+ uint32_t j, count;
+ char **next_edges;
+
+ count = rte_node_edge_get(tm->test_node[i].idx, NULL);
+ if (count != tm->test_node[i].node.nb_edges * sizeof(char *)) {
+ printf("Test number of edge count for node = %s failed Expected = %d, got = %d\n",
+ tm->test_node[i].node.name,
+ tm->test_node[i].node.nb_edges, count);
+ return -1;
+ }
+ next_edges = malloc(count);
+ count = rte_node_edge_get(tm->test_node[i].idx, next_edges);
+ if (count != tm->test_node[i].node.nb_edges) {
+ printf("Test number of edges for node = %s failed Expected = %d, got %d\n",
+ tm->test_node[i].node.name,
+ tm->test_node[i].node.nb_edges, count);
+ free(next_edges);
+ return -1;
+ }
+
+ for (j = 0; j < count; j++) {
+ if (strcmp(next_edges[j],
+ tm->test_node[i].node.next_nodes[j]) != 0) {
+ printf("Edge name miss match, expected = %s got = %s\n",
+ tm->test_node[i].node.next_nodes[j],
+ next_edges[j]);
+ free(next_edges);
+ return -1;
+ }
+ }
+ free(next_edges);
+ }
+
+ return 0;
+}
+
+static int
+test_node_clone(void)
+{
+ test_main_t *tm = &test_main;
+ uint32_t node_id, dummy_id;
+ int i;
+
+ node_id = rte_node_from_name("test_node00");
+ tm->test_node[0].idx = node_id;
+
+ /* Clone with same name, should fail */
+ dummy_id = rte_node_clone(node_id, "test_node00");
+ if (!rte_node_is_invalid(dummy_id)) {
+ printf("Got valid id when clone with same name, Expecting fail\n");
+ return -1;
+ }
+
+ for (i = 1; i < MAX_NODES; i++) {
+ tm->test_node[i].idx =
+ rte_node_clone(node_id, tm->test_node[i].node.name);
+ if (rte_node_is_invalid(tm->test_node[i].idx)) {
+ printf("Got invalid node id\n");
+ return -1;
+ }
+ }
+
+ /* Clone from cloned node should fail */
+ dummy_id = rte_node_clone(tm->test_node[1].idx, "dummy_node");
+ if (!rte_node_is_invalid(dummy_id)) {
+ printf("Got valid node id when cloning from cloned node, expected fail\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_update_edges(void)
+{
+ test_main_t *tm = &test_main;
+ uint32_t node_id;
+ uint16_t count;
+ int i;
+
+ node_id = rte_node_from_name("test_node00");
+ count = rte_node_edge_update(node_id, 0,
+ tm->test_node[0].node.next_nodes,
+ tm->test_node[0].node.nb_edges);
+ if (count != tm->test_node[0].node.nb_edges) {
+ printf("Update edges failed expected: %d got = %d\n",
+ tm->test_node[0].node.nb_edges, count);
+ return -1;
+ }
+
+ for (i = 1; i < MAX_NODES; i++) {
+ count = rte_node_edge_update(tm->test_node[i].idx, 0,
+ tm->test_node[i].node.next_nodes,
+ tm->test_node[i].node.nb_edges);
+ if (count != tm->test_node[i].node.nb_edges) {
+ printf("Update edges failed expected: %d got = %d\n",
+ tm->test_node[i].node.nb_edges, count);
+ return -1;
+ }
+
+ count = rte_node_edge_shrink(tm->test_node[i].idx,
+ tm->test_node[i].node.nb_edges);
+ if (count != tm->test_node[i].node.nb_edges) {
+ printf("Shrink edges failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_create_graph(void)
+{
+ static const char *node_patterns_dummy[] = {
+ "test_node_source1", "test_node00",
+ "test_node00-test_node11", "test_node00-test_node22",
+ "test_node00-test_node33", "test_node00-dummy_node",
+ };
+ struct rte_graph_param gconf = {
+ .socket_id = SOCKET_ID_ANY,
+ .nb_node_patterns = 6,
+ .node_patterns = node_patterns_dummy,
+ };
+ uint32_t dummy_node_id;
+ uint32_t node_id;
+
+ node_id = rte_node_from_name("test_node00");
+ dummy_node_id = rte_node_clone(node_id, "dummy_node");
+ if (rte_node_is_invalid(dummy_node_id)) {
+ printf("Got invalid node id\n");
+ return -1;
+ }
+
+ graph_id = rte_graph_create("worker0", &gconf);
+ if (graph_id != RTE_GRAPH_ID_INVALID) {
+ printf("Graph creation success with isolated node, expected graph creation fail\n");
+ return -1;
+ }
+
+ gconf.nb_node_patterns = 5;
+ gconf.node_patterns = node_patterns;
+ graph_id = rte_graph_create("worker0", &gconf);
+ if (graph_id == RTE_GRAPH_ID_INVALID) {
+ printf("Graph creation failed with error = %d\n", rte_errno);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_graph_walk(void)
+{
+ struct rte_graph *graph = rte_graph_lookup("worker0");
+ int i;
+
+ if (!graph) {
+ printf("Graph lookup failed\n");
+ return -1;
+ }
+
+ for (i = 0; i < 5; i++)
+ rte_graph_walk(graph);
+ return 0;
+}
+
+static int
+test_graph_lookup_functions(void)
+{
+ test_main_t *tm = &test_main;
+ struct rte_node *node;
+ int i;
+
+ for (i = 0; i < MAX_NODES; i++) {
+ node = rte_graph_node_get(graph_id, tm->test_node[i].idx);
+ if (!node) {
+ printf("rte_graph_node_get, failed for node = %d\n",
+ tm->test_node[i].idx);
+ return -1;
+ }
+
+ if (tm->test_node[i].idx != node->id) {
+ printf("Node id didn't match, expected = %d got = %d\n",
+ tm->test_node[i].idx, node->id);
+ return 0;
+ }
+
+ if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
+ printf("Node name didn't match, expected = %s got %s\n",
+ node_names[i], node->name);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < MAX_NODES; i++) {
+ node = rte_graph_node_get_by_name("worker0", node_names[i]);
+ if (!node) {
+ printf("rte_graph_node_get, failed for node = %d\n",
+ tm->test_node[i].idx);
+ return -1;
+ }
+
+ if (tm->test_node[i].idx != node->id) {
+ printf("Node id didn't match, expected = %d got = %d\n",
+ tm->test_node[i].idx, node->id);
+ return 0;
+ }
+
+ if (strncmp(node->name, node_names[i], RTE_NODE_NAMESIZE)) {
+ printf("Node name didn't match, expected = %s got %s\n",
+ node_names[i], node->name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+graph_cluster_stats_cb_t(bool is_first, bool is_last, void *cookie,
+ const struct rte_graph_cluster_node_stats *st)
+{
+ int i;
+
+ RTE_SET_USED(is_first);
+ RTE_SET_USED(is_last);
+ RTE_SET_USED(cookie);
+
+ for (i = 0; i < MAX_NODES + 1; i++) {
+ rte_node_t id = rte_node_from_name(node_patterns[i]);
+ if (id == st->id) {
+ if (obj_stats[i] != st->objs) {
+ printf("Obj count miss match for node = %s expected = %"PRId64", got=%"PRId64"\n",
+ node_patterns[i], obj_stats[i],
+ st->objs);
+ return -1;
+ }
+
+ if (fn_calls[i] != st->calls) {
+ printf("Func call miss match for node = %s expected = %"PRId64", got = %"PRId64"\n",
+ node_patterns[i], fn_calls[i],
+ st->calls);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+test_print_stats(void)
+{
+ struct rte_graph_cluster_stats_param s_param;
+ struct rte_graph_cluster_stats *stats;
+ const char *pattern = "worker0";
+
+ if (!rte_graph_has_stats_feature())
+ return 0;
+
+ /* Prepare stats object */
+ memset(&s_param, 0, sizeof(s_param));
+ s_param.f = stdout;
+ s_param.socket_id = SOCKET_ID_ANY;
+ s_param.graph_patterns = &pattern;
+ s_param.nb_graph_patterns = 1;
+ s_param.fn = graph_cluster_stats_cb_t;
+
+ stats = rte_graph_cluster_stats_create(&s_param);
+ if (stats == NULL) {
+ printf("Unable to get stats\n");
+ return -1;
+ }
+ /* Clear screen and move to top left */
+ rte_graph_cluster_stats_get(stats, 0);
+ rte_graph_cluster_stats_destroy(stats);
+
+ return 0;
+}
+
+static int
+graph_setup(void)
+{
+ int i, j;
+
+ for (i = 0; i <= MAX_NODES; i++) {
+ for (j = 0; j < MBUFF_SIZE; j++)
+ mbuf_p[i][j] = &mbuf[i][j];
+ }
+ if (test_node_clone()) {
+ printf("test_node_clone: fail\n");
+ return -1;
+ }
+ printf("test_node_clone: pass\n");
+
+ return 0;
+}
+
+static void
+graph_teardown(void)
+{
+ int id;
+
+ id = rte_graph_destroy(rte_graph_from_name("worker0"));
+ if (id)
+ printf("Graph Destroy failed\n");
+}
+
+static struct unit_test_suite graph_testsuite = {
+ .suite_name = "Graph library test suite",
+ .setup = graph_setup,
+ .teardown = graph_teardown,
+ .unit_test_cases = {
+ TEST_CASE(test_update_edges),
+ TEST_CASE(test_lookup_functions),
+ TEST_CASE(test_create_graph),
+ TEST_CASE(test_graph_lookup_functions),
+ TEST_CASE(test_graph_walk),
+ TEST_CASE(test_print_stats),
+ TEST_CASES_END(), /**< NULL terminate unit test array */
+ },
+};
+
+static int
+graph_autotest_fn(void)
+{
+ return unit_test_suite_runner(&graph_testsuite);
+}
+
+REGISTER_TEST_COMMAND(graph_autotest, graph_autotest_fn);
+
+static int
+test_node_list_dump(void)
+{
+ rte_node_list_dump(stdout);
+
+ return TEST_SUCCESS;
+}
+REGISTER_TEST_COMMAND(node_list_dump, test_node_list_dump);
diff --git a/src/spdk/dpdk/app/test/test_graph_perf.c b/src/spdk/dpdk/app/test/test_graph_perf.c
new file mode 100644
index 000000000..296d99a9d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_graph_perf.c
@@ -0,0 +1,1063 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+#include <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_graph.h>
+#include <rte_graph_worker.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+
+#include "test.h"
+
+#define TEST_GRAPH_PERF_MZ "graph_perf_data"
+#define TEST_GRAPH_SRC_NAME "test_graph_perf_source"
+#define TEST_GRAPH_SRC_BRST_ONE_NAME "test_graph_perf_source_one"
+#define TEST_GRAPH_WRK_NAME "test_graph_perf_worker"
+#define TEST_GRAPH_SNK_NAME "test_graph_perf_sink"
+
+#define SOURCES(map) RTE_DIM(map)
+#define STAGES(map) RTE_DIM(map)
+#define NODES_PER_STAGE(map) RTE_DIM(map[0])
+#define SINKS(map) RTE_DIM(map[0])
+
+#define MAX_EDGES_PER_NODE 7
+
+struct test_node_data {
+ uint8_t node_id;
+ uint8_t is_sink;
+ uint8_t next_nodes[MAX_EDGES_PER_NODE];
+ uint8_t next_percentage[MAX_EDGES_PER_NODE];
+};
+
+struct test_graph_perf {
+ uint16_t nb_nodes;
+ rte_graph_t graph_id;
+ struct test_node_data *node_data;
+};
+
+struct graph_lcore_data {
+ uint8_t done;
+ rte_graph_t graph_id;
+};
+
+static struct test_node_data *
+graph_get_node_data(struct test_graph_perf *graph_data, rte_node_t id)
+{
+ struct test_node_data *node_data = NULL;
+ int i;
+
+ for (i = 0; i < graph_data->nb_nodes; i++)
+ if (graph_data->node_data[i].node_id == id) {
+ node_data = &graph_data->node_data[i];
+ break;
+ }
+
+ return node_data;
+}
+
+static int
+test_node_ctx_init(const struct rte_graph *graph, struct rte_node *node)
+{
+ struct test_graph_perf *graph_data;
+ struct test_node_data *node_data;
+ const struct rte_memzone *mz;
+ rte_node_t nid = node->id;
+ rte_edge_t edge = 0;
+ int i;
+
+ RTE_SET_USED(graph);
+
+ mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
+ if (mz == NULL)
+ return -ENOMEM;
+ graph_data = mz->addr;
+ node_data = graph_get_node_data(graph_data, nid);
+ node->ctx[0] = node->nb_edges;
+ for (i = 0; i < node->nb_edges && !node_data->is_sink; i++, edge++) {
+ node->ctx[i + 1] = edge;
+ node->ctx[i + 9] = node_data->next_percentage[i];
+ }
+
+ return 0;
+}
+
+/* Source node function */
+static uint16_t
+test_perf_node_worker_source(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ uint16_t count;
+ int i;
+
+ RTE_SET_USED(objs);
+ RTE_SET_USED(nb_objs);
+
+ /* Create a proportional stream for every next */
+ for (i = 0; i < node->ctx[0]; i++) {
+ count = (node->ctx[i + 9] * RTE_GRAPH_BURST_SIZE) / 100;
+ rte_node_next_stream_get(graph, node, node->ctx[i + 1], count);
+ rte_node_next_stream_put(graph, node, node->ctx[i + 1], count);
+ }
+
+ return RTE_GRAPH_BURST_SIZE;
+}
+
+static struct rte_node_register test_graph_perf_source = {
+ .name = TEST_GRAPH_SRC_NAME,
+ .process = test_perf_node_worker_source,
+ .flags = RTE_NODE_SOURCE_F,
+ .init = test_node_ctx_init,
+};
+
+RTE_NODE_REGISTER(test_graph_perf_source);
+
+static uint16_t
+test_perf_node_worker_source_burst_one(struct rte_graph *graph,
+ struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ uint16_t count;
+ int i;
+
+ RTE_SET_USED(objs);
+ RTE_SET_USED(nb_objs);
+
+ /* Create a proportional stream for every next */
+ for (i = 0; i < node->ctx[0]; i++) {
+ count = (node->ctx[i + 9]) / 100;
+ rte_node_next_stream_get(graph, node, node->ctx[i + 1], count);
+ rte_node_next_stream_put(graph, node, node->ctx[i + 1], count);
+ }
+
+ return 1;
+}
+
+static struct rte_node_register test_graph_perf_source_burst_one = {
+ .name = TEST_GRAPH_SRC_BRST_ONE_NAME,
+ .process = test_perf_node_worker_source_burst_one,
+ .flags = RTE_NODE_SOURCE_F,
+ .init = test_node_ctx_init,
+};
+
+RTE_NODE_REGISTER(test_graph_perf_source_burst_one);
+
+/* Worker node function */
+static uint16_t
+test_perf_node_worker(struct rte_graph *graph, struct rte_node *node,
+ void **objs, uint16_t nb_objs)
+{
+ uint16_t next = 0;
+ uint16_t enq = 0;
+ uint16_t count;
+ int i;
+
+ /* Move stream for single next node */
+ if (node->ctx[0] == 1) {
+ rte_node_next_stream_move(graph, node, node->ctx[1]);
+ return nb_objs;
+ }
+
+ /* Enqueue objects to next nodes proportionally */
+ for (i = 0; i < node->ctx[0]; i++) {
+ next = node->ctx[i + 1];
+ count = (node->ctx[i + 9] * nb_objs) / 100;
+ enq += count;
+ while (count) {
+ switch (count & (4 - 1)) {
+ case 0:
+ rte_node_enqueue_x4(graph, node, next, objs[0],
+ objs[1], objs[2], objs[3]);
+ objs += 4;
+ count -= 4;
+ break;
+ case 1:
+ rte_node_enqueue_x1(graph, node, next, objs[0]);
+ objs += 1;
+ count -= 1;
+ break;
+ case 2:
+ rte_node_enqueue_x2(graph, node, next, objs[0],
+ objs[1]);
+ objs += 2;
+ count -= 2;
+ break;
+ case 3:
+ rte_node_enqueue_x2(graph, node, next, objs[0],
+ objs[1]);
+ rte_node_enqueue_x1(graph, node, next, objs[0]);
+ objs += 3;
+ count -= 3;
+ break;
+ }
+ }
+ }
+
+ if (enq != nb_objs)
+ rte_node_enqueue(graph, node, next, objs, nb_objs - enq);
+
+ return nb_objs;
+}
+
+static struct rte_node_register test_graph_perf_worker = {
+ .name = TEST_GRAPH_WRK_NAME,
+ .process = test_perf_node_worker,
+ .init = test_node_ctx_init,
+};
+
+RTE_NODE_REGISTER(test_graph_perf_worker);
+
+/* Last node in graph a.k.a sink node */
+static uint16_t
+test_perf_node_sink(struct rte_graph *graph, struct rte_node *node, void **objs,
+ uint16_t nb_objs)
+{
+ RTE_SET_USED(graph);
+ RTE_SET_USED(node);
+ RTE_SET_USED(objs);
+ RTE_SET_USED(nb_objs);
+
+ return nb_objs;
+}
+
+static struct rte_node_register test_graph_perf_sink = {
+ .name = TEST_GRAPH_SNK_NAME,
+ .process = test_perf_node_sink,
+ .init = test_node_ctx_init,
+};
+
+RTE_NODE_REGISTER(test_graph_perf_sink);
+
+static int
+graph_perf_setup(void)
+{
+ if (rte_lcore_count() < 2) {
+ printf("Test requires at least 2 lcores\n");
+ return TEST_SKIPPED;
+ }
+
+ return 0;
+}
+
+static void
+graph_perf_teardown(void)
+{
+}
+
+static inline rte_node_t
+graph_node_get(const char *pname, char *nname)
+{
+ rte_node_t pnode_id = rte_node_from_name(pname);
+ char lookup_name[RTE_NODE_NAMESIZE];
+ rte_node_t node_id;
+
+ snprintf(lookup_name, RTE_NODE_NAMESIZE, "%s-%s", pname, nname);
+ node_id = rte_node_from_name(lookup_name);
+
+ if (node_id != RTE_NODE_ID_INVALID) {
+ if (rte_node_edge_count(node_id))
+ rte_node_edge_shrink(node_id, 0);
+ return node_id;
+ }
+
+ return rte_node_clone(pnode_id, nname);
+}
+
+static uint16_t
+graph_node_count_edges(uint32_t stage, uint16_t node, uint16_t nodes_per_stage,
+ uint8_t edge_map[][nodes_per_stage][nodes_per_stage],
+ char *ename[], struct test_node_data *node_data,
+ rte_node_t **node_map)
+{
+ uint8_t total_percent = 0;
+ uint16_t edges = 0;
+ int i;
+
+ for (i = 0; i < nodes_per_stage && edges < MAX_EDGES_PER_NODE; i++) {
+ if (edge_map[stage + 1][i][node]) {
+ ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
+ snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
+ rte_node_id_to_name(node_map[stage + 1][i]));
+ node_data->next_nodes[edges] = node_map[stage + 1][i];
+ node_data->next_percentage[edges] =
+ edge_map[stage + 1][i][node];
+ edges++;
+ total_percent += edge_map[stage + 1][i][node];
+ }
+ }
+
+ if (edges >= MAX_EDGES_PER_NODE || (edges && total_percent != 100)) {
+ for (i = 0; i < edges; i++)
+ free(ename[i]);
+ return RTE_EDGE_ID_INVALID;
+ }
+
+ return edges;
+}
+
+static int
+graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks,
+ uint32_t stages, uint16_t nodes_per_stage,
+ uint8_t src_map[][nodes_per_stage], uint8_t snk_map[][nb_sinks],
+ uint8_t edge_map[][nodes_per_stage][nodes_per_stage],
+ uint8_t burst_one)
+{
+ struct test_graph_perf *graph_data;
+ char nname[RTE_NODE_NAMESIZE / 2];
+ struct test_node_data *node_data;
+ char *ename[nodes_per_stage];
+ struct rte_graph_param gconf;
+ const struct rte_memzone *mz;
+ uint8_t total_percent = 0;
+ rte_node_t *src_nodes;
+ rte_node_t *snk_nodes;
+ rte_node_t **node_map;
+ char **node_patterns;
+ rte_graph_t graph_id;
+ rte_edge_t edges;
+ rte_edge_t count;
+ uint32_t i, j, k;
+
+ mz = rte_memzone_reserve(TEST_GRAPH_PERF_MZ,
+ sizeof(struct test_graph_perf), 0, 0);
+ if (mz == NULL) {
+ printf("Failed to allocate graph common memory\n");
+ return -ENOMEM;
+ }
+
+ graph_data = mz->addr;
+ graph_data->nb_nodes = 0;
+ graph_data->node_data =
+ malloc(sizeof(struct test_node_data) *
+ (nb_srcs + nb_sinks + stages * nodes_per_stage));
+ if (graph_data->node_data == NULL) {
+ printf("Failed to reserve memzone for graph data\n");
+ goto memzone_free;
+ }
+
+ node_patterns = malloc(sizeof(char *) *
+ (nb_srcs + nb_sinks + stages * nodes_per_stage));
+ if (node_patterns == NULL) {
+ printf("Failed to reserve memory for node patterns\n");
+ goto data_free;
+ }
+
+ src_nodes = malloc(sizeof(rte_node_t) * nb_srcs);
+ if (src_nodes == NULL) {
+ printf("Failed to reserve memory for src nodes\n");
+ goto pattern_free;
+ }
+
+ snk_nodes = malloc(sizeof(rte_node_t) * nb_sinks);
+ if (snk_nodes == NULL) {
+ printf("Failed to reserve memory for snk nodes\n");
+ goto src_free;
+ }
+
+ node_map = malloc(sizeof(rte_node_t *) * stages +
+ sizeof(rte_node_t) * nodes_per_stage * stages);
+ if (node_map == NULL) {
+ printf("Failed to reserve memory for node map\n");
+ goto snk_free;
+ }
+
+ /* Setup the Graph */
+ for (i = 0; i < stages; i++) {
+ node_map[i] =
+ (rte_node_t *)(node_map + stages) + nodes_per_stage * i;
+ for (j = 0; j < nodes_per_stage; j++) {
+ total_percent = 0;
+ for (k = 0; k < nodes_per_stage; k++)
+ total_percent += edge_map[i][j][k];
+ if (!total_percent)
+ continue;
+ node_patterns[graph_data->nb_nodes] =
+ malloc(RTE_NODE_NAMESIZE);
+ if (node_patterns[graph_data->nb_nodes] == NULL) {
+ printf("Failed to create memory for pattern\n");
+ goto pattern_name_free;
+ }
+
+ /* Clone a worker node */
+ snprintf(nname, sizeof(nname), "%d-%d", i, j);
+ node_map[i][j] =
+ graph_node_get(TEST_GRAPH_WRK_NAME, nname);
+ if (node_map[i][j] == RTE_NODE_ID_INVALID) {
+ printf("Failed to create node[%s]\n", nname);
+ graph_data->nb_nodes++;
+ goto pattern_name_free;
+ }
+ snprintf(node_patterns[graph_data->nb_nodes],
+ RTE_NODE_NAMESIZE, "%s",
+ rte_node_id_to_name(node_map[i][j]));
+ node_data =
+ &graph_data->node_data[graph_data->nb_nodes];
+ node_data->node_id = node_map[i][j];
+ node_data->is_sink = false;
+ graph_data->nb_nodes++;
+ }
+ }
+
+ for (i = 0; i < stages - 1; i++) {
+ for (j = 0; j < nodes_per_stage; j++) {
+ /* Count edges i.e connections of worker node to next */
+ node_data =
+ graph_get_node_data(graph_data, node_map[i][j]);
+ edges = graph_node_count_edges(i, j, nodes_per_stage,
+ edge_map, ename,
+ node_data, node_map);
+ if (edges == RTE_EDGE_ID_INVALID) {
+ printf("Invalid edge configuration\n");
+ goto pattern_name_free;
+ }
+ if (!edges)
+ continue;
+
+ /* Connect a node in stage 'i' to nodes
+ * in stage 'i + 1' with edges.
+ */
+ count = rte_node_edge_update(
+ node_map[i][j], 0,
+ (const char **)(uintptr_t)ename, edges);
+ for (k = 0; k < edges; k++)
+ free(ename[k]);
+ if (count != edges) {
+ printf("Couldn't add edges %d %d\n", edges,
+ count);
+ goto pattern_name_free;
+ }
+ }
+ }
+
+ /* Setup Source nodes */
+ for (i = 0; i < nb_srcs; i++) {
+ edges = 0;
+ total_percent = 0;
+ node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE);
+ if (node_patterns[graph_data->nb_nodes] == NULL) {
+ printf("Failed to create memory for pattern\n");
+ goto pattern_name_free;
+ }
+ /* Clone a source node */
+ snprintf(nname, sizeof(nname), "%d", i);
+ src_nodes[i] =
+ graph_node_get(burst_one ? TEST_GRAPH_SRC_BRST_ONE_NAME
+ : TEST_GRAPH_SRC_NAME,
+ nname);
+ if (src_nodes[i] == RTE_NODE_ID_INVALID) {
+ printf("Failed to create node[%s]\n", nname);
+ graph_data->nb_nodes++;
+ goto pattern_name_free;
+ }
+ snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE,
+ "%s", rte_node_id_to_name(src_nodes[i]));
+ node_data = &graph_data->node_data[graph_data->nb_nodes];
+ node_data->node_id = src_nodes[i];
+ node_data->is_sink = false;
+ graph_data->nb_nodes++;
+
+ /* Prepare next node list to connect to */
+ for (j = 0; j < nodes_per_stage; j++) {
+ if (!src_map[i][j])
+ continue;
+ ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
+ snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
+ rte_node_id_to_name(node_map[0][j]));
+ node_data->next_nodes[edges] = node_map[0][j];
+ node_data->next_percentage[edges] = src_map[i][j];
+ edges++;
+ total_percent += src_map[i][j];
+ }
+
+ if (!edges)
+ continue;
+ if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) {
+ printf("Invalid edge configuration\n");
+ for (j = 0; j < edges; j++)
+ free(ename[j]);
+ goto pattern_name_free;
+ }
+
+ /* Connect to list of next nodes using edges */
+ count = rte_node_edge_update(src_nodes[i], 0,
+ (const char **)(uintptr_t)ename,
+ edges);
+ for (k = 0; k < edges; k++)
+ free(ename[k]);
+ if (count != edges) {
+ printf("Couldn't add edges %d %d\n", edges, count);
+ goto pattern_name_free;
+ }
+ }
+
+ /* Setup Sink nodes */
+ for (i = 0; i < nb_sinks; i++) {
+ node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE);
+ if (node_patterns[graph_data->nb_nodes] == NULL) {
+ printf("Failed to create memory for pattern\n");
+ goto pattern_name_free;
+ }
+
+ /* Clone a sink node */
+ snprintf(nname, sizeof(nname), "%d", i);
+ snk_nodes[i] = graph_node_get(TEST_GRAPH_SNK_NAME, nname);
+ if (snk_nodes[i] == RTE_NODE_ID_INVALID) {
+ printf("Failed to create node[%s]\n", nname);
+ graph_data->nb_nodes++;
+ goto pattern_name_free;
+ }
+ snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE,
+ "%s", rte_node_id_to_name(snk_nodes[i]));
+ node_data = &graph_data->node_data[graph_data->nb_nodes];
+ node_data->node_id = snk_nodes[i];
+ node_data->is_sink = true;
+ graph_data->nb_nodes++;
+ }
+
+ /* Connect last stage worker nodes to sink nodes */
+ for (i = 0; i < nodes_per_stage; i++) {
+ edges = 0;
+ total_percent = 0;
+ node_data = graph_get_node_data(graph_data,
+ node_map[stages - 1][i]);
+ /* Prepare list of sink nodes to connect to */
+ for (j = 0; j < nb_sinks; j++) {
+ if (!snk_map[i][j])
+ continue;
+ ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE);
+ snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s",
+ rte_node_id_to_name(snk_nodes[j]));
+ node_data->next_nodes[edges] = snk_nodes[j];
+ node_data->next_percentage[edges] = snk_map[i][j];
+ edges++;
+ total_percent += snk_map[i][j];
+ }
+ if (!edges)
+ continue;
+ if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) {
+ printf("Invalid edge configuration\n");
+ for (j = 0; j < edges; j++)
+ free(ename[i]);
+ goto pattern_name_free;
+ }
+
+ /* Connect a worker node to a list of sink nodes */
+ count = rte_node_edge_update(node_map[stages - 1][i], 0,
+ (const char **)(uintptr_t)ename,
+ edges);
+ for (k = 0; k < edges; k++)
+ free(ename[k]);
+ if (count != edges) {
+ printf("Couldn't add edges %d %d\n", edges, count);
+ goto pattern_name_free;
+ }
+ }
+
+ /* Create a Graph */
+ gconf.socket_id = SOCKET_ID_ANY;
+ gconf.nb_node_patterns = graph_data->nb_nodes;
+ gconf.node_patterns = (const char **)(uintptr_t)node_patterns;
+
+ graph_id = rte_graph_create(gname, &gconf);
+ if (graph_id == RTE_GRAPH_ID_INVALID) {
+ printf("Graph creation failed with error = %d\n", rte_errno);
+ goto pattern_name_free;
+ }
+ graph_data->graph_id = graph_id;
+
+ free(node_map);
+ for (i = 0; i < graph_data->nb_nodes; i++)
+ free(node_patterns[i]);
+ free(snk_nodes);
+ free(src_nodes);
+ free(node_patterns);
+ return 0;
+
+pattern_name_free:
+ free(node_map);
+ for (i = 0; i < graph_data->nb_nodes; i++)
+ free(node_patterns[i]);
+snk_free:
+ free(snk_nodes);
+src_free:
+ free(src_nodes);
+pattern_free:
+ free(node_patterns);
+data_free:
+ free(graph_data->node_data);
+memzone_free:
+ rte_memzone_free(mz);
+ return -ENOMEM;
+}
+
+/* Worker thread function */
+static int
+_graph_perf_wrapper(void *args)
+{
+ struct graph_lcore_data *data = args;
+ struct rte_graph *graph;
+
+ /* Lookup graph */
+ graph = rte_graph_lookup(rte_graph_id_to_name(data->graph_id));
+
+ /* Graph walk until done */
+ while (!data->done)
+ rte_graph_walk(graph);
+
+ return 0;
+}
+
+static int
+measure_perf_get(rte_graph_t graph_id)
+{
+ const char *pattern = rte_graph_id_to_name(graph_id);
+ uint32_t lcore_id = rte_get_next_lcore(-1, 1, 0);
+ struct rte_graph_cluster_stats_param param;
+ struct rte_graph_cluster_stats *stats;
+ struct graph_lcore_data *data;
+
+ data = rte_zmalloc("Graph_perf", sizeof(struct graph_lcore_data),
+ RTE_CACHE_LINE_SIZE);
+ data->graph_id = graph_id;
+ data->done = 0;
+
+ /* Run graph worker thread function */
+ rte_eal_remote_launch(_graph_perf_wrapper, data, lcore_id);
+
+ /* Collect stats for few msecs */
+ if (rte_graph_has_stats_feature()) {
+ memset(&param, 0, sizeof(param));
+ param.f = stdout;
+ param.socket_id = SOCKET_ID_ANY;
+ param.graph_patterns = &pattern;
+ param.nb_graph_patterns = 1;
+
+ stats = rte_graph_cluster_stats_create(&param);
+ if (stats == NULL) {
+ printf("Failed to create stats\n");
+ return -ENOMEM;
+ }
+
+ rte_delay_ms(3E2);
+ rte_graph_cluster_stats_get(stats, true);
+ rte_delay_ms(1E3);
+ rte_graph_cluster_stats_get(stats, false);
+ rte_graph_cluster_stats_destroy(stats);
+ } else
+ rte_delay_ms(1E3);
+
+ data->done = 1;
+ rte_eal_wait_lcore(lcore_id);
+
+ return 0;
+}
+
+static inline void
+graph_fini(void)
+{
+ const struct rte_memzone *mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
+ struct test_graph_perf *graph_data;
+
+ if (mz == NULL)
+ return;
+ graph_data = mz->addr;
+
+ rte_graph_destroy(graph_data->graph_id);
+ free(graph_data->node_data);
+ rte_memzone_free(rte_memzone_lookup(TEST_GRAPH_PERF_MZ));
+}
+
+static int
+measure_perf(void)
+{
+ const struct rte_memzone *mz;
+ struct test_graph_perf *graph_data;
+
+ mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ);
+ if (mz == NULL)
+ return -ENOMEM;
+ graph_data = mz->addr;
+
+ return measure_perf_get(graph_data->graph_id);
+}
+
+static inline int
+graph_hr_4s_1n_1src_1snk(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_hr_4s_1n_1src_1snk_brst_one(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_hr_4s_1n_2src_1snk(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_hr_4s_1n_1src_2snk(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_tree_4s_4n_1src_4snk(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_reverse_tree_3s_4n_1src_1snk(void)
+{
+ return measure_perf();
+}
+
+static inline int
+graph_parallel_tree_5s_4n_4src_4snk(void)
+{
+ return measure_perf();
+}
+
+/* Graph Topology
+ * nodes per stage: 1
+ * stages: 4
+ * src: 1
+ * sink: 1
+ */
+static inline int
+graph_init_hr(void)
+{
+ uint8_t edge_map[][1][1] = {
+ { {100} },
+ { {100} },
+ { {100} },
+ { {100} },
+ };
+ uint8_t src_map[][1] = { {100} };
+ uint8_t snk_map[][1] = { {100} };
+
+ return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/* Graph Topology
+ * nodes per stage: 1
+ * stages: 4
+ * src: 1
+ * sink: 1
+ */
+static inline int
+graph_init_hr_brst_one(void)
+{
+ uint8_t edge_map[][1][1] = {
+ { {100} },
+ { {100} },
+ { {100} },
+ { {100} },
+ };
+ uint8_t src_map[][1] = { {100} };
+ uint8_t snk_map[][1] = { {100} };
+
+ return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 1);
+}
+
+/* Graph Topology
+ * nodes per stage: 1
+ * stages: 4
+ * src: 2
+ * sink: 1
+ */
+static inline int
+graph_init_hr_multi_src(void)
+{
+ uint8_t edge_map[][1][1] = {
+ { {100} },
+ { {100} },
+ { {100} },
+ { {100} },
+ };
+ uint8_t src_map[][1] = {
+ {100}, {100}
+ };
+ uint8_t snk_map[][1] = { {100} };
+
+ return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/* Graph Topology
+ * nodes per stage: 1
+ * stages: 4
+ * src: 1
+ * sink: 2
+ */
+static inline int
+graph_init_hr_multi_snk(void)
+{
+ uint8_t edge_map[][1][1] = {
+ { {100} },
+ { {100} },
+ { {100} },
+ { {100} },
+ };
+ uint8_t src_map[][1] = { {100} };
+ uint8_t snk_map[][2] = { {50, 50} };
+
+ return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/* Graph Topology
+ * nodes per stage: 4
+ * stages: 4
+ * src: 1
+ * sink: 4
+ */
+static inline int
+graph_init_tree(void)
+{
+ uint8_t edge_map[][4][4] = {
+ {
+ {100, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ },
+ {
+ {50, 0, 0, 0},
+ {50, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ },
+ {
+ {33, 33, 0, 0},
+ {34, 34, 0, 0},
+ {33, 33, 0, 0},
+ {0, 0, 0, 0}
+ },
+ {
+ {25, 25, 25, 0},
+ {25, 25, 25, 0},
+ {25, 25, 25, 0},
+ {25, 25, 25, 0}
+ }
+ };
+ uint8_t src_map[][4] = { {100, 0, 0, 0} };
+ uint8_t snk_map[][4] = {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ };
+
+ return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/* Graph Topology
+ * nodes per stage: 4
+ * stages: 3
+ * src: 1
+ * sink: 1
+ */
+static inline int
+graph_init_reverse_tree(void)
+{
+ uint8_t edge_map[][4][4] = {
+ {
+ {25, 25, 25, 25},
+ {25, 25, 25, 25},
+ {25, 25, 25, 25},
+ {25, 25, 25, 25}
+ },
+ {
+ {33, 33, 33, 33},
+ {33, 33, 33, 33},
+ {34, 34, 34, 34},
+ {0, 0, 0, 0}
+ },
+ {
+ {50, 50, 50, 0},
+ {50, 50, 50, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+ },
+ };
+ uint8_t src_map[][4] = { {25, 25, 25, 25} };
+ uint8_t snk_map[][1] = { {100}, {100}, {0}, {0} };
+
+ return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/* Graph Topology
+ * nodes per stage: 4
+ * stages: 5
+ * src: 4
+ * sink: 4
+ */
+static inline int
+graph_init_parallel_tree(void)
+{
+ uint8_t edge_map[][4][4] = {
+ {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ },
+ {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ },
+ {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ },
+ {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ },
+ {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ },
+ };
+ uint8_t src_map[][4] = {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ };
+ uint8_t snk_map[][4] = {
+ {100, 0, 0, 0},
+ {0, 100, 0, 0},
+ {0, 0, 100, 0},
+ {0, 0, 0, 100}
+ };
+
+ return graph_init("graph_parallel", SOURCES(src_map), SINKS(snk_map),
+ STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map,
+ snk_map, edge_map, 0);
+}
+
+/** Graph Creation cheat sheet
+ * edge_map -> dictates graph flow from worker stage 0 to worker stage n-1.
+ * src_map -> dictates source nodes enqueue percentage to worker stage 0.
+ * snk_map -> dictates stage n-1 enqueue percentage to sink.
+ *
+ * Layout:
+ * edge_map[<nb_stages>][<nodes_per_stg>][<nodes_in_nxt_stg = nodes_per_stg>]
+ * src_map[<nb_sources>][<nodes_in_stage0 = nodes_per_stage>]
+ * snk_map[<nodes_in_stage(n-1) = nodes_per_stage>][<nb_sinks>]
+ *
+ * The last array dictates the percentage of received objs to enqueue to next
+ * stage.
+ *
+ * Note: edge_map[][0][] will always be unused as it will receive from source
+ *
+ * Example:
+ * Graph:
+ * http://bit.ly/2PqbqOy
+ * Each stage(n) connects to all nodes in the next stage in decreasing
+ * order.
+ * Since we can't resize the edge_map dynamically we get away by creating
+ * dummy nodes and assigning 0 percentages.
+ * Max nodes across all stages = 4
+ * stages = 3
+ * nb_src = 1
+ * nb_snk = 1
+ * // Stages
+ * edge_map[][4][4] = {
+ * // Nodes per stage
+ * {
+ * {25, 25, 25, 25},
+ * {25, 25, 25, 25},
+ * {25, 25, 25, 25},
+ * {25, 25, 25, 25}
+ * }, // This will be unused.
+ * {
+ * // Nodes enabled in current stage + prev stage enq %
+ * {33, 33, 33, 33},
+ * {33, 33, 33, 33},
+ * {34, 34, 34, 34},
+ * {0, 0, 0, 0}
+ * },
+ * {
+ * {50, 50, 50, 0},
+ * {50, 50, 50, 0},
+ * {0, 0, 0, 0},
+ * {0, 0, 0, 0}
+ * },
+ * };
+ * Above, each stage tells how much it should receive from previous except
+ * from stage_0.
+ *
+ * src_map[][4] = { {25, 25, 25, 25} };
+ * Here, we tell each source the % it has to send to stage_0 nodes. In
+ * case we want 2 source node we can declare as
+ * src_map[][4] = { {25, 25, 25, 25}, {25, 25, 25, 25} };
+ *
+ * snk_map[][1] = { {100}, {100}, {0}, {0} }
+ * Here, we tell stage - 1 nodes how much to enqueue to sink_0.
+ * If we have 2 sinks we can do as follows
+ * snk_map[][2] = { {50, 50}, {50, 50}, {0, 0}, {0, 0} }
+ */
+
+static struct unit_test_suite graph_perf_testsuite = {
+ .suite_name = "Graph library performance test suite",
+ .setup = graph_perf_setup,
+ .teardown = graph_perf_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(graph_init_hr, graph_fini,
+ graph_hr_4s_1n_1src_1snk),
+ TEST_CASE_ST(graph_init_hr_brst_one, graph_fini,
+ graph_hr_4s_1n_1src_1snk_brst_one),
+ TEST_CASE_ST(graph_init_hr_multi_src, graph_fini,
+ graph_hr_4s_1n_2src_1snk),
+ TEST_CASE_ST(graph_init_hr_multi_snk, graph_fini,
+ graph_hr_4s_1n_1src_2snk),
+ TEST_CASE_ST(graph_init_tree, graph_fini,
+ graph_tree_4s_4n_1src_4snk),
+ TEST_CASE_ST(graph_init_reverse_tree, graph_fini,
+ graph_reverse_tree_3s_4n_1src_1snk),
+ TEST_CASE_ST(graph_init_parallel_tree, graph_fini,
+ graph_parallel_tree_5s_4n_4src_4snk),
+ TEST_CASES_END(), /**< NULL terminate unit test array */
+ },
+};
+
+static int
+test_graph_perf_func(void)
+{
+ return unit_test_suite_runner(&graph_perf_testsuite);
+}
+
+REGISTER_TEST_COMMAND(graph_perf_autotest, test_graph_perf_func);
diff --git a/src/spdk/dpdk/app/test/test_hash.c b/src/spdk/dpdk/app/test/test_hash.c
new file mode 100644
index 000000000..afa3a1a3c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash.c
@@ -0,0 +1,1873 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2015 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_memory.h>
+#include <rte_eal.h>
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+#include <rte_hash.h>
+#include <rte_fbk_hash.h>
+#include <rte_jhash.h>
+#include <rte_hash_crc.h>
+
+/*******************************************************************************
+ * Hash function performance test configuration section. Each performance test
+ * will be performed HASHTEST_ITERATIONS times.
+ *
+ * The five arrays below control what tests are performed. Every combination
+ * from the array entries is tested.
+ */
+static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};
+static uint32_t hashtest_initvals[] = {0};
+static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21, 31, 32, 33, 63, 64};
+#define MAX_KEYSIZE 64
+/******************************************************************************/
+#define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15)
+
+/*
+ * Check condition and return an error if true. Assumes that "handle" is the
+ * name of the hash structure pointer to be freed.
+ */
+#define RETURN_IF_ERROR(cond, str, ...) do { \
+ if (cond) { \
+ printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
+ if (handle) rte_hash_free(handle); \
+ return -1; \
+ } \
+} while(0)
+
+#define RETURN_IF_ERROR_FBK(cond, str, ...) do { \
+ if (cond) { \
+ printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
+ if (handle) rte_fbk_hash_free(handle); \
+ return -1; \
+ } \
+} while(0)
+
+/* 5-tuple key type */
+struct flow_key {
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint8_t proto;
+} __rte_packed;
+
+int hash_logtype_test;
+
+/*
+ * Hash function that always returns the same value, to easily test what
+ * happens when a bucket is full.
+ */
+static uint32_t pseudo_hash(__rte_unused const void *keys,
+ __rte_unused uint32_t key_len,
+ __rte_unused uint32_t init_val)
+{
+ return 3;
+}
+
+RTE_INIT(test_hash_init_log)
+{
+ hash_logtype_test = rte_log_register("test.hash");
+}
+
+/*
+ * Print out result of unit test hash operation.
+ */
+static void print_key_info(const char *msg, const struct flow_key *key,
+ int32_t pos)
+{
+ const uint8_t *p = (const uint8_t *)key;
+ unsigned int i;
+
+ rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%s key:0x", msg);
+ for (i = 0; i < sizeof(struct flow_key); i++)
+ rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%02X", p[i]);
+ rte_log(RTE_LOG_DEBUG, hash_logtype_test, " @ pos %d\n", pos);
+}
+
+/* Keys used by unit test functions */
+static struct flow_key keys[5] = { {
+ .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
+ .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
+ .port_src = 0x0908,
+ .port_dst = 0x0b0a,
+ .proto = 0x0c,
+}, {
+ .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10),
+ .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14),
+ .port_src = 0x1918,
+ .port_dst = 0x1b1a,
+ .proto = 0x1c,
+}, {
+ .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20),
+ .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24),
+ .port_src = 0x2928,
+ .port_dst = 0x2b2a,
+ .proto = 0x2c,
+}, {
+ .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30),
+ .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34),
+ .port_src = 0x3938,
+ .port_dst = 0x3b3a,
+ .proto = 0x3c,
+}, {
+ .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40),
+ .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44),
+ .port_src = 0x4948,
+ .port_dst = 0x4b4a,
+ .proto = 0x4c,
+} };
+
+/* Parameters used for hash table in unit test functions. Name set later. */
+static struct rte_hash_parameters ut_params = {
+ .entries = 64,
+ .key_len = sizeof(struct flow_key), /* 13 */
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+ .socket_id = 0,
+};
+
+#define CRC32_ITERATIONS (1U << 10)
+#define CRC32_DWORDS (1U << 6)
+/*
+ * Test if all CRC32 implementations yield the same hash value
+ */
+static int
+test_crc32_hash_alg_equiv(void)
+{
+ uint32_t hash_val;
+ uint32_t init_val;
+ uint64_t data64[CRC32_DWORDS];
+ unsigned i, j;
+ size_t data_len;
+
+ printf("\n# CRC32 implementations equivalence test\n");
+ for (i = 0; i < CRC32_ITERATIONS; i++) {
+ /* Randomizing data_len of data set */
+ data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1);
+ init_val = (uint32_t) rte_rand();
+
+ /* Fill the data set */
+ for (j = 0; j < CRC32_DWORDS; j++)
+ data64[j] = rte_rand();
+
+ /* Calculate software CRC32 */
+ rte_hash_crc_set_alg(CRC32_SW);
+ hash_val = rte_hash_crc(data64, data_len, init_val);
+
+ /* Check against 4-byte-operand sse4.2 CRC32 if available */
+ rte_hash_crc_set_alg(CRC32_SSE42);
+ if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
+ printf("Failed checking CRC32_SW against CRC32_SSE42\n");
+ break;
+ }
+
+ /* Check against 8-byte-operand sse4.2 CRC32 if available */
+ rte_hash_crc_set_alg(CRC32_SSE42_x64);
+ if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
+ printf("Failed checking CRC32_SW against CRC32_SSE42_x64\n");
+ break;
+ }
+
+ /* Check against 8-byte-operand ARM64 CRC32 if available */
+ rte_hash_crc_set_alg(CRC32_ARM64);
+ if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
+ printf("Failed checking CRC32_SW against CRC32_ARM64\n");
+ break;
+ }
+ }
+
+ /* Resetting to best available algorithm */
+ rte_hash_crc_set_alg(CRC32_SSE42_x64);
+
+ if (i == CRC32_ITERATIONS)
+ return 0;
+
+ printf("Failed test data (hex, %zu bytes total):\n", data_len);
+ for (j = 0; j < data_len; j++)
+ printf("%02X%c", ((uint8_t *)data64)[j],
+ ((j+1) % 16 == 0 || j == data_len - 1) ? '\n' : ' ');
+
+ return -1;
+}
+
+/*
+ * Test a hash function.
+ */
+static void run_hash_func_test(rte_hash_function f, uint32_t init_val,
+ uint32_t key_len)
+{
+ static uint8_t key[MAX_KEYSIZE];
+ unsigned i;
+
+
+ for (i = 0; i < key_len; i++)
+ key[i] = (uint8_t) rte_rand();
+
+ /* just to be on the safe side */
+ if (!f)
+ return;
+
+ f(key, key_len, init_val);
+}
+
+/*
+ * Test all hash functions.
+ */
+static void run_hash_func_tests(void)
+{
+ unsigned i, j, k;
+
+ for (i = 0; i < RTE_DIM(hashtest_funcs); i++) {
+ for (j = 0; j < RTE_DIM(hashtest_initvals); j++) {
+ for (k = 0; k < RTE_DIM(hashtest_key_lens); k++) {
+ run_hash_func_test(hashtest_funcs[i],
+ hashtest_initvals[j],
+ hashtest_key_lens[k]);
+ }
+ }
+ }
+}
+
+/*
+ * Basic sequence of operations for a single key:
+ * - add
+ * - lookup (hit)
+ * - delete
+ * - lookup (miss)
+ *
+ * Repeat the test case when 'free on delete' is disabled.
+ * - add
+ * - lookup (hit)
+ * - delete
+ * - lookup (miss)
+ * - free
+ */
+static int test_add_delete(void)
+{
+ struct rte_hash *handle;
+ /* test with standard add/lookup/delete functions */
+ int pos0, expectedPos0;
+
+ ut_params.name = "test1";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ pos0 = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
+ expectedPos0 = pos0;
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to find key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to delete key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found key after deleting! (pos0=%d)", pos0);
+
+ rte_hash_free(handle);
+
+ /* repeat test with precomputed hash functions */
+ hash_sig_t hash_value;
+ int pos1, expectedPos1, delPos1;
+
+ ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ ut_params.extra_flag = 0;
+
+ hash_value = rte_hash_hash(handle, &keys[0]);
+ pos1 = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Add", &keys[0], pos1);
+ RETURN_IF_ERROR(pos1 < 0, "failed to add key (pos1=%d)", pos1);
+ expectedPos1 = pos1;
+
+ pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Lkp", &keys[0], pos1);
+ RETURN_IF_ERROR(pos1 != expectedPos1,
+ "failed to find key (pos1=%d)", pos1);
+
+ pos1 = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Del", &keys[0], pos1);
+ RETURN_IF_ERROR(pos1 != expectedPos1,
+ "failed to delete key (pos1=%d)", pos1);
+ delPos1 = pos1;
+
+ pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Lkp", &keys[0], pos1);
+ RETURN_IF_ERROR(pos1 != -ENOENT,
+ "fail: found key after deleting! (pos1=%d)", pos1);
+
+ pos1 = rte_hash_free_key_with_position(handle, delPos1);
+ print_key_info("Free", &keys[0], delPos1);
+ RETURN_IF_ERROR(pos1 != 0,
+ "failed to free key (pos1=%d)", delPos1);
+
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for a single key:
+ * - delete: miss
+ * - add
+ * - lookup: hit
+ * - add: update
+ * - lookup: hit (updated data)
+ * - delete: hit
+ * - delete: miss
+ * - lookup: miss
+ */
+static int test_add_update_delete(void)
+{
+ struct rte_hash *handle;
+ int pos0, expectedPos0;
+
+ ut_params.name = "test2";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found non-existent key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
+ expectedPos0 = pos0;
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to find key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to re-add key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to find key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to delete key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: deleted already deleted key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found key after deleting! (pos0=%d)", pos0);
+
+ rte_hash_free(handle);
+ return 0;
+}
+
+/*
+ * Sequence of operations for a single key with 'disable free on del' set:
+ * - delete: miss
+ * - add
+ * - lookup: hit
+ * - add: update
+ * - lookup: hit (updated data)
+ * - delete: hit
+ * - delete: miss
+ * - lookup: miss
+ * - free: hit
+ * - lookup: miss
+ */
+static int test_add_update_delete_free(void)
+{
+ struct rte_hash *handle;
+ int pos0, expectedPos0, delPos0, result;
+
+ ut_params.name = "test2";
+ ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ ut_params.extra_flag = 0;
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found non-existent key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
+ expectedPos0 = pos0;
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to find key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to re-add key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != expectedPos0,
+ "failed to find key (pos0=%d)", pos0);
+
+ delPos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], delPos0);
+ RETURN_IF_ERROR(delPos0 != expectedPos0,
+ "failed to delete key (pos0=%d)", delPos0);
+
+ pos0 = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: deleted already deleted key (pos0=%d)", pos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found key after deleting! (pos0=%d)", pos0);
+
+ result = rte_hash_free_key_with_position(handle, delPos0);
+ print_key_info("Free", &keys[0], delPos0);
+ RETURN_IF_ERROR(result != 0,
+ "failed to free key (pos1=%d)", delPos0);
+
+ pos0 = rte_hash_lookup(handle, &keys[0]);
+ print_key_info("Lkp", &keys[0], pos0);
+ RETURN_IF_ERROR(pos0 != -ENOENT,
+ "fail: found key after deleting! (pos0=%d)", pos0);
+
+ rte_hash_free(handle);
+ return 0;
+}
+
+/*
+ * Sequence of operations for a single key with 'rw concurrency lock free' set:
+ * - add
+ * - delete: hit
+ * - free: hit
+ * Repeat the test case when 'multi writer add' is enabled.
+ * - add
+ * - delete: hit
+ * - free: hit
+ */
+static int test_add_delete_free_lf(void)
+{
+/* Should match the #define LCORE_CACHE_SIZE value in rte_cuckoo_hash.h */
+#define LCORE_CACHE_SIZE 64
+ struct rte_hash *handle;
+ hash_sig_t hash_value;
+ int pos, expectedPos, delPos;
+ uint8_t extra_flag;
+ uint32_t i, ip_src;
+
+ extra_flag = ut_params.extra_flag;
+ ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ ut_params.extra_flag = extra_flag;
+
+ /*
+ * The number of iterations is at least the same as the number of slots
+ * rte_hash allocates internally. This is to reveal potential issues of
+ * not freeing keys successfully.
+ */
+ for (i = 0; i < ut_params.entries + 1; i++) {
+ hash_value = rte_hash_hash(handle, &keys[0]);
+ pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Add", &keys[0], pos);
+ RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos);
+ expectedPos = pos;
+
+ pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Del", &keys[0], pos);
+ RETURN_IF_ERROR(pos != expectedPos,
+ "failed to delete key (pos=%d)", pos);
+ delPos = pos;
+
+ pos = rte_hash_free_key_with_position(handle, delPos);
+ print_key_info("Free", &keys[0], delPos);
+ RETURN_IF_ERROR(pos != 0,
+ "failed to free key (pos=%d)", delPos);
+ }
+
+ rte_hash_free(handle);
+
+ extra_flag = ut_params.extra_flag;
+ ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
+ RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ ut_params.extra_flag = extra_flag;
+
+ ip_src = keys[0].ip_src;
+ /*
+ * The number of iterations is at least the same as the number of slots
+ * rte_hash allocates internally. This is to reveal potential issues of
+ * not freeing keys successfully.
+ */
+ for (i = 0; i < ut_params.entries + (RTE_MAX_LCORE - 1) *
+ (LCORE_CACHE_SIZE - 1) + 1; i++) {
+ keys[0].ip_src++;
+ hash_value = rte_hash_hash(handle, &keys[0]);
+ pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Add", &keys[0], pos);
+ RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos);
+ expectedPos = pos;
+
+ pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
+ print_key_info("Del", &keys[0], pos);
+ RETURN_IF_ERROR(pos != expectedPos,
+ "failed to delete key (pos=%d)", pos);
+ delPos = pos;
+
+ pos = rte_hash_free_key_with_position(handle, delPos);
+ print_key_info("Free", &keys[0], delPos);
+ RETURN_IF_ERROR(pos != 0,
+ "failed to free key (pos=%d)", delPos);
+ }
+ keys[0].ip_src = ip_src;
+
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for retrieving a key with its position
+ *
+ * - create table
+ * - add key
+ * - get the key with its position: hit
+ * - delete key
+ * - try to get the deleted key: miss
+ *
+ * Repeat the test case when 'free on delete' is disabled.
+ * - create table
+ * - add key
+ * - get the key with its position: hit
+ * - delete key
+ * - try to get the deleted key: hit
+ * - free key
+ * - try to get the deleted key: miss
+ *
+ */
+static int test_hash_get_key_with_position(void)
+{
+ struct rte_hash *handle = NULL;
+ int pos, expectedPos, delPos, result;
+ void *key;
+
+ ut_params.name = "hash_get_key_w_pos";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ pos = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos);
+ RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos);
+ expectedPos = pos;
+
+ result = rte_hash_get_key_with_position(handle, pos, &key);
+ RETURN_IF_ERROR(result != 0, "error retrieving a key");
+
+ pos = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos);
+ RETURN_IF_ERROR(pos != expectedPos,
+ "failed to delete key (pos0=%d)", pos);
+
+ result = rte_hash_get_key_with_position(handle, pos, &key);
+ RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
+
+ rte_hash_free(handle);
+
+ ut_params.name = "hash_get_key_w_pos";
+ ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ ut_params.extra_flag = 0;
+
+ pos = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos);
+ RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos);
+ expectedPos = pos;
+
+ result = rte_hash_get_key_with_position(handle, pos, &key);
+ RETURN_IF_ERROR(result != 0, "error retrieving a key");
+
+ delPos = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], delPos);
+ RETURN_IF_ERROR(delPos != expectedPos,
+ "failed to delete key (pos0=%d)", delPos);
+
+ result = rte_hash_get_key_with_position(handle, delPos, &key);
+ RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
+
+ result = rte_hash_free_key_with_position(handle, delPos);
+ print_key_info("Free", &keys[0], delPos);
+ RETURN_IF_ERROR(result != 0,
+ "failed to free key (pos1=%d)", delPos);
+
+ result = rte_hash_get_key_with_position(handle, delPos, &key);
+ RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
+
+ rte_hash_free(handle);
+ return 0;
+}
+
+/*
+ * Sequence of operations for find existing hash table
+ *
+ * - create table
+ * - find existing table: hit
+ * - find non-existing table: miss
+ *
+ */
+static int test_hash_find_existing(void)
+{
+ struct rte_hash *handle = NULL, *result = NULL;
+
+ /* Create hash table. */
+ ut_params.name = "hash_find_existing";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Try to find existing hash table */
+ result = rte_hash_find_existing("hash_find_existing");
+ RETURN_IF_ERROR(result != handle, "could not find existing hash table");
+
+ /* Try to find non-existing hash table */
+ result = rte_hash_find_existing("hash_find_non_existing");
+ RETURN_IF_ERROR(!(result == NULL), "found table that shouldn't exist");
+
+ /* Cleanup. */
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for 5 keys
+ * - add keys
+ * - lookup keys: hit
+ * - add keys (update)
+ * - lookup keys: hit (updated data)
+ * - delete keys : hit
+ * - lookup keys: miss
+ */
+static int test_five_keys(void)
+{
+ struct rte_hash *handle;
+ const void *key_array[5] = {0};
+ int pos[5];
+ int expected_pos[5];
+ unsigned i;
+ int ret;
+
+ ut_params.name = "test3";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Add */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_add_key(handle, &keys[i]);
+ print_key_info("Add", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] < 0,
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ expected_pos[i] = pos[i];
+ }
+
+ /* Lookup */
+ for(i = 0; i < 5; i++)
+ key_array[i] = &keys[i];
+
+ ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
+ if(ret == 0)
+ for(i = 0; i < 5; i++) {
+ print_key_info("Lkp", key_array[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Add - update */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_add_key(handle, &keys[i]);
+ print_key_info("Add", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_lookup(handle, &keys[i]);
+ print_key_info("Lkp", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Delete */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_del_key(handle, &keys[i]);
+ print_key_info("Del", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to delete key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_lookup(handle, &keys[i]);
+ print_key_info("Lkp", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != -ENOENT,
+ "found non-existent key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup multi */
+ ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
+ if (ret == 0)
+ for (i = 0; i < 5; i++) {
+ print_key_info("Lkp", key_array[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != -ENOENT,
+ "found not-existent key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+/*
+ * Add keys to the same bucket until bucket full.
+ * - add 5 keys to the same bucket (hash created with 4 keys per bucket):
+ * first 4 successful, 5th successful, pushing existing item in bucket
+ * - lookup the 5 keys: 5 hits
+ * - add the 5 keys again: 5 OK
+ * - lookup the 5 keys: 5 hits (updated data)
+ * - delete the 5 keys: 5 OK
+ * - lookup the 5 keys: 5 misses
+ */
+static int test_full_bucket(void)
+{
+ struct rte_hash_parameters params_pseudo_hash = {
+ .name = "test4",
+ .entries = 64,
+ .key_len = sizeof(struct flow_key), /* 13 */
+ .hash_func = pseudo_hash,
+ .hash_func_init_val = 0,
+ .socket_id = 0,
+ };
+ struct rte_hash *handle;
+ int pos[5];
+ int expected_pos[5];
+ unsigned i;
+
+ handle = rte_hash_create(&params_pseudo_hash);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Fill bucket */
+ for (i = 0; i < 4; i++) {
+ pos[i] = rte_hash_add_key(handle, &keys[i]);
+ print_key_info("Add", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] < 0,
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ expected_pos[i] = pos[i];
+ }
+ /*
+ * This should work and will push one of the items
+ * in the bucket because it is full
+ */
+ pos[4] = rte_hash_add_key(handle, &keys[4]);
+ print_key_info("Add", &keys[4], pos[4]);
+ RETURN_IF_ERROR(pos[4] < 0,
+ "failed to add key (pos[4]=%d)", pos[4]);
+ expected_pos[4] = pos[4];
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_lookup(handle, &keys[i]);
+ print_key_info("Lkp", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Add - update */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_add_key(handle, &keys[i]);
+ print_key_info("Add", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_lookup(handle, &keys[i]);
+ print_key_info("Lkp", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Delete 1 key, check other keys are still found */
+ pos[1] = rte_hash_del_key(handle, &keys[1]);
+ print_key_info("Del", &keys[1], pos[1]);
+ RETURN_IF_ERROR(pos[1] != expected_pos[1],
+ "failed to delete key (pos[1]=%d)", pos[1]);
+ pos[3] = rte_hash_lookup(handle, &keys[3]);
+ print_key_info("Lkp", &keys[3], pos[3]);
+ RETURN_IF_ERROR(pos[3] != expected_pos[3],
+ "failed lookup after deleting key from same bucket "
+ "(pos[3]=%d)", pos[3]);
+
+ /* Go back to previous state */
+ pos[1] = rte_hash_add_key(handle, &keys[1]);
+ print_key_info("Add", &keys[1], pos[1]);
+ expected_pos[1] = pos[1];
+ RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]);
+
+ /* Delete */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_del_key(handle, &keys[i]);
+ print_key_info("Del", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to delete key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 5; i++) {
+ pos[i] = rte_hash_lookup(handle, &keys[i]);
+ print_key_info("Lkp", &keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != -ENOENT,
+ "fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ rte_hash_free(handle);
+
+ /* Cover the NULL case. */
+ rte_hash_free(0);
+ return 0;
+}
+
+/*
+ * Similar to the test above (full bucket test), but for extendable buckets.
+ */
+static int test_extendable_bucket(void)
+{
+ struct rte_hash_parameters params_pseudo_hash = {
+ .name = "test5",
+ .entries = 64,
+ .key_len = sizeof(struct flow_key), /* 13 */
+ .hash_func = pseudo_hash,
+ .hash_func_init_val = 0,
+ .socket_id = 0,
+ .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE
+ };
+ struct rte_hash *handle;
+ int pos[64];
+ int expected_pos[64];
+ unsigned int i;
+ struct flow_key rand_keys[64];
+
+ for (i = 0; i < 64; i++) {
+ rand_keys[i].port_dst = i;
+ rand_keys[i].port_src = i+1;
+ }
+
+ handle = rte_hash_create(&params_pseudo_hash);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Fill bucket */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
+ print_key_info("Add", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] < 0,
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ expected_pos[i] = pos[i];
+ }
+
+ /* Lookup */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
+ print_key_info("Lkp", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Add - update */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
+ print_key_info("Add", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
+ print_key_info("Lkp", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to find key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Delete 1 key, check other keys are still found */
+ pos[35] = rte_hash_del_key(handle, &rand_keys[35]);
+ print_key_info("Del", &rand_keys[35], pos[35]);
+ RETURN_IF_ERROR(pos[35] != expected_pos[35],
+ "failed to delete key (pos[1]=%d)", pos[35]);
+ pos[20] = rte_hash_lookup(handle, &rand_keys[20]);
+ print_key_info("Lkp", &rand_keys[20], pos[20]);
+ RETURN_IF_ERROR(pos[20] != expected_pos[20],
+ "failed lookup after deleting key from same bucket "
+ "(pos[20]=%d)", pos[20]);
+
+ /* Go back to previous state */
+ pos[35] = rte_hash_add_key(handle, &rand_keys[35]);
+ print_key_info("Add", &rand_keys[35], pos[35]);
+ expected_pos[35] = pos[35];
+ RETURN_IF_ERROR(pos[35] < 0, "failed to add key (pos[1]=%d)", pos[35]);
+
+ /* Delete */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_del_key(handle, &rand_keys[i]);
+ print_key_info("Del", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != expected_pos[i],
+ "failed to delete key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Lookup */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
+ print_key_info("Lkp", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] != -ENOENT,
+ "fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
+ }
+
+ /* Add again */
+ for (i = 0; i < 64; i++) {
+ pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
+ print_key_info("Add", &rand_keys[i], pos[i]);
+ RETURN_IF_ERROR(pos[i] < 0,
+ "failed to add key (pos[%u]=%d)", i, pos[i]);
+ expected_pos[i] = pos[i];
+ }
+
+ rte_hash_free(handle);
+
+ /* Cover the NULL case. */
+ rte_hash_free(0);
+ return 0;
+}
+
+/******************************************************************************/
+static int
+fbk_hash_unit_test(void)
+{
+ struct rte_fbk_hash_params params = {
+ .name = "fbk_hash_test",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_1 = {
+ .name = "invalid_1",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX + 1, /* Not power of 2 */
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_2 = {
+ .name = "invalid_2",
+ .entries = 4,
+ .entries_per_bucket = 3, /* Not power of 2 */
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_3 = {
+ .name = "invalid_3",
+ .entries = 0, /* Entries is 0 */
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_4 = {
+ .name = "invalid_4",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 0, /* Entries per bucket is 0 */
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_5 = {
+ .name = "invalid_5",
+ .entries = 4,
+ .entries_per_bucket = 8, /* Entries per bucket > entries */
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_6 = {
+ .name = "invalid_6",
+ .entries = RTE_FBK_HASH_ENTRIES_MAX * 2, /* Entries > max allowed */
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_7 = {
+ .name = "invalid_7",
+ .entries = RTE_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX * 2, /* Entries > max allowed */
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params invalid_params_8 = {
+ .name = "invalid_7",
+ .entries = RTE_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = RTE_MAX_NUMA_NODES + 1, /* invalid socket */
+ };
+
+ /* try to create two hashes with identical names
+ * in this case, trying to create a second one will not
+ * fail but will simply return pointer to the existing
+ * hash with that name. sort of like a "find hash by name" :-)
+ */
+ struct rte_fbk_hash_params invalid_params_same_name_1 = {
+ .name = "same_name", /* hash with identical name */
+ .entries = 4,
+ .entries_per_bucket = 2,
+ .socket_id = 0,
+ };
+
+ /* trying to create this hash should return a pointer to an existing hash */
+ struct rte_fbk_hash_params invalid_params_same_name_2 = {
+ .name = "same_name", /* hash with identical name */
+ .entries = RTE_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ /* this is a sanity check for "same name" test
+ * creating this hash will check if we are actually able to create
+ * multiple hashes with different names (instead of having just one).
+ */
+ struct rte_fbk_hash_params different_name = {
+ .name = "different_name", /* different name */
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+
+ struct rte_fbk_hash_params params_jhash = {
+ .name = "valid",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ .hash_func = rte_jhash_1word, /* Tests for different hash_func */
+ .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
+ };
+
+ struct rte_fbk_hash_params params_nohash = {
+ .name = "valid nohash",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ .hash_func = NULL, /* Tests for null hash_func */
+ .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
+ };
+
+ struct rte_fbk_hash_table *handle, *tmp;
+ uint32_t keys[5] =
+ {0xc6e18639, 0xe67c201c, 0xd4c8cffd, 0x44728691, 0xd5430fa9};
+ uint16_t vals[5] = {28108, 5699, 38490, 2166, 61571};
+ int status;
+ unsigned i;
+ double used_entries;
+
+ /* Try creating hashes with invalid parameters */
+ printf("# Testing hash creation with invalid parameters "
+ "- expect error msgs\n");
+ handle = rte_fbk_hash_create(&invalid_params_1);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_2);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_3);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_4);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_5);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_6);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ handle = rte_fbk_hash_create(&invalid_params_7);
+ RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+
+ if (rte_eal_has_hugepages()) {
+ handle = rte_fbk_hash_create(&invalid_params_8);
+ RETURN_IF_ERROR_FBK(handle != NULL,
+ "fbk hash creation should have failed");
+ }
+
+ handle = rte_fbk_hash_create(&invalid_params_same_name_1);
+ RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded");
+
+ tmp = rte_fbk_hash_create(&invalid_params_same_name_2);
+ if (tmp != NULL)
+ rte_fbk_hash_free(tmp);
+ RETURN_IF_ERROR_FBK(tmp != NULL, "fbk hash creation should have failed");
+
+ /* we are not freeing handle here because we need a hash list
+ * to be not empty for the next test */
+
+ /* create a hash in non-empty list - good for coverage */
+ tmp = rte_fbk_hash_create(&different_name);
+ RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded");
+
+ /* free both hashes */
+ rte_fbk_hash_free(handle);
+ rte_fbk_hash_free(tmp);
+
+ /* Create empty jhash hash. */
+ handle = rte_fbk_hash_create(&params_jhash);
+ RETURN_IF_ERROR_FBK(handle == NULL, "fbk jhash hash creation failed");
+
+ /* Cleanup. */
+ rte_fbk_hash_free(handle);
+
+ /* Create empty jhash hash. */
+ handle = rte_fbk_hash_create(&params_nohash);
+ RETURN_IF_ERROR_FBK(handle == NULL, "fbk nohash hash creation failed");
+
+ /* Cleanup. */
+ rte_fbk_hash_free(handle);
+
+ /* Create empty hash. */
+ handle = rte_fbk_hash_create(&params);
+ RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
+
+ used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
+ RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \
+ "load factor right after creation is not zero but it should be");
+ /* Add keys. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_add_key(handle, keys[i], vals[i]);
+ RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed");
+ }
+
+ used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
+ RETURN_IF_ERROR_FBK((unsigned)used_entries != (unsigned)((((double)5)/LOCAL_FBK_HASH_ENTRIES_MAX)*LOCAL_FBK_HASH_ENTRIES_MAX), \
+ "load factor now is not as expected");
+ /* Find value of added keys. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_lookup(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status != vals[i],
+ "fbk hash lookup failed");
+ }
+
+ /* Change value of added keys. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_add_key(handle, keys[i], vals[4 - i]);
+ RETURN_IF_ERROR_FBK(status != 0, "fbk hash update failed");
+ }
+
+ /* Find new values. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_lookup(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status != vals[4-i],
+ "fbk hash lookup failed");
+ }
+
+ /* Delete keys individually. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_delete_key(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status != 0, "fbk hash delete failed");
+ }
+
+ used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
+ RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \
+ "load factor right after deletion is not zero but it should be");
+ /* Lookup should now fail. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_lookup(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status == 0,
+ "fbk hash lookup should have failed");
+ }
+
+ /* Add keys again. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_add_key(handle, keys[i], vals[i]);
+ RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed");
+ }
+
+ /* Make sure they were added. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_lookup(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status != vals[i],
+ "fbk hash lookup failed");
+ }
+
+ /* Clear all entries. */
+ rte_fbk_hash_clear_all(handle);
+
+ /* Lookup should fail. */
+ for (i = 0; i < 5; i++) {
+ status = rte_fbk_hash_lookup(handle, keys[i]);
+ RETURN_IF_ERROR_FBK(status == 0,
+ "fbk hash lookup should have failed");
+ }
+
+ /* coverage */
+
+ /* fill up the hash_table */
+ for (i = 0; i < RTE_FBK_HASH_ENTRIES_MAX + 1; i++)
+ rte_fbk_hash_add_key(handle, i, (uint16_t) i);
+
+ /* Find non-existent key in a full hashtable */
+ status = rte_fbk_hash_lookup(handle, RTE_FBK_HASH_ENTRIES_MAX + 1);
+ RETURN_IF_ERROR_FBK(status != -ENOENT,
+ "fbk hash lookup succeeded");
+
+ /* Delete non-existent key in a full hashtable */
+ status = rte_fbk_hash_delete_key(handle, RTE_FBK_HASH_ENTRIES_MAX + 1);
+ RETURN_IF_ERROR_FBK(status != -ENOENT,
+ "fbk hash delete succeeded");
+
+ /* Delete one key from a full hashtable */
+ status = rte_fbk_hash_delete_key(handle, 1);
+ RETURN_IF_ERROR_FBK(status != 0,
+ "fbk hash delete failed");
+
+ /* Clear all entries. */
+ rte_fbk_hash_clear_all(handle);
+
+ /* Cleanup. */
+ rte_fbk_hash_free(handle);
+
+ /* Cover the NULL case. */
+ rte_fbk_hash_free(0);
+
+ return 0;
+}
+
+/*
+ * Sequence of operations for find existing fbk hash table
+ *
+ * - create table
+ * - find existing table: hit
+ * - find non-existing table: miss
+ *
+ */
+static int test_fbk_hash_find_existing(void)
+{
+ struct rte_fbk_hash_params params = {
+ .name = "fbk_hash_find_existing",
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
+ .entries_per_bucket = 4,
+ .socket_id = 0,
+ };
+ struct rte_fbk_hash_table *handle = NULL, *result = NULL;
+
+ /* Create hash table. */
+ handle = rte_fbk_hash_create(&params);
+ RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
+
+ /* Try to find existing fbk hash table */
+ result = rte_fbk_hash_find_existing("fbk_hash_find_existing");
+ RETURN_IF_ERROR_FBK(result != handle, "could not find existing fbk hash table");
+
+ /* Try to find non-existing fbk hash table */
+ result = rte_fbk_hash_find_existing("fbk_hash_find_non_existing");
+ RETURN_IF_ERROR_FBK(!(result == NULL), "found fbk table that shouldn't exist");
+
+ /* Cleanup. */
+ rte_fbk_hash_free(handle);
+
+ return 0;
+}
+
+#define BUCKET_ENTRIES 4
+/*
+ * Do tests for hash creation with bad parameters.
+ */
+static int test_hash_creation_with_bad_parameters(void)
+{
+ struct rte_hash *handle, *tmp;
+ struct rte_hash_parameters params;
+
+ handle = rte_hash_create(NULL);
+ if (handle != NULL) {
+ rte_hash_free(handle);
+ printf("Impossible creating hash successfully without any parameter\n");
+ return -1;
+ }
+
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "creation_with_bad_parameters_0";
+ params.entries = RTE_HASH_ENTRIES_MAX + 1;
+ handle = rte_hash_create(&params);
+ if (handle != NULL) {
+ rte_hash_free(handle);
+ printf("Impossible creating hash successfully with entries in parameter exceeded\n");
+ return -1;
+ }
+
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "creation_with_bad_parameters_2";
+ params.entries = BUCKET_ENTRIES - 1;
+ handle = rte_hash_create(&params);
+ if (handle != NULL) {
+ rte_hash_free(handle);
+ printf("Impossible creating hash successfully if entries less than bucket_entries in parameter\n");
+ return -1;
+ }
+
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "creation_with_bad_parameters_3";
+ params.key_len = 0;
+ handle = rte_hash_create(&params);
+ if (handle != NULL) {
+ rte_hash_free(handle);
+ printf("Impossible creating hash successfully if key_len in parameter is zero\n");
+ return -1;
+ }
+
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "creation_with_bad_parameters_4";
+ params.socket_id = RTE_MAX_NUMA_NODES + 1;
+ handle = rte_hash_create(&params);
+ if (handle != NULL) {
+ rte_hash_free(handle);
+ printf("Impossible creating hash successfully with invalid socket\n");
+ return -1;
+ }
+
+ /* test with same name should fail */
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "same_name";
+ handle = rte_hash_create(&params);
+ if (handle == NULL) {
+ printf("Cannot create first hash table with 'same_name'\n");
+ return -1;
+ }
+ tmp = rte_hash_create(&params);
+ if (tmp != NULL) {
+ printf("Creation of hash table with same name should fail\n");
+ rte_hash_free(handle);
+ rte_hash_free(tmp);
+ return -1;
+ }
+ rte_hash_free(handle);
+
+ printf("# Test successful. No more errors expected\n");
+
+ return 0;
+}
+
+/*
+ * Do tests for hash creation with parameters that look incorrect
+ * but are actually valid.
+ */
+static int
+test_hash_creation_with_good_parameters(void)
+{
+ struct rte_hash *handle;
+ struct rte_hash_parameters params;
+
+ /* create with null hash function - should choose DEFAULT_HASH_FUNC */
+ memcpy(&params, &ut_params, sizeof(params));
+ params.name = "name";
+ params.hash_func = NULL;
+ handle = rte_hash_create(&params);
+ if (handle == NULL) {
+ printf("Creating hash with null hash_func failed\n");
+ return -1;
+ }
+
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+#define ITERATIONS 3
+/*
+ * Test to see the average table utilization (entries added/max entries)
+ * before hitting a random entry that cannot be added
+ */
+static int test_average_table_utilization(uint32_t ext_table)
+{
+ struct rte_hash *handle;
+ uint8_t simple_key[MAX_KEYSIZE];
+ unsigned i, j;
+ unsigned added_keys, average_keys_added = 0;
+ int ret;
+ unsigned int cnt;
+
+ printf("\n# Running test to determine average utilization"
+ "\n before adding elements begins to fail\n");
+ if (ext_table)
+ printf("ext table is enabled\n");
+ else
+ printf("ext table is disabled\n");
+
+ printf("Measuring performance, please wait");
+ fflush(stdout);
+ ut_params.entries = 1 << 16;
+ ut_params.name = "test_average_utilization";
+ ut_params.hash_func = rte_jhash;
+ if (ext_table)
+ ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+ else
+ ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+
+ handle = rte_hash_create(&ut_params);
+
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ for (j = 0; j < ITERATIONS; j++) {
+ ret = 0;
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; ret >= 0; added_keys++) {
+ for (i = 0; i < ut_params.key_len; i++)
+ simple_key[i] = rte_rand() % 255;
+ ret = rte_hash_add_key(handle, simple_key);
+ if (ret < 0)
+ break;
+ }
+
+ if (ret != -ENOSPC) {
+ printf("Unexpected error when adding keys\n");
+ rte_hash_free(handle);
+ return -1;
+ }
+
+ cnt = rte_hash_count(handle);
+ if (cnt != added_keys) {
+ printf("rte_hash_count returned wrong value %u, %u,"
+ "%u\n", j, added_keys, cnt);
+ rte_hash_free(handle);
+ return -1;
+ }
+ if (ext_table) {
+ if (cnt != ut_params.entries) {
+ printf("rte_hash_count returned wrong value "
+ "%u, %u, %u\n", j, added_keys, cnt);
+ rte_hash_free(handle);
+ return -1;
+ }
+ }
+
+ average_keys_added += added_keys;
+
+ /* Reset the table */
+ rte_hash_reset(handle);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nAverage table utilization = %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / ut_params.entries * 100),
+ average_keys_added, ut_params.entries);
+ rte_hash_free(handle);
+
+ return 0;
+}
+
+#define NUM_ENTRIES 256
+static int test_hash_iteration(uint32_t ext_table)
+{
+ struct rte_hash *handle;
+ unsigned i;
+ uint8_t keys[NUM_ENTRIES][MAX_KEYSIZE];
+ const void *next_key;
+ void *next_data;
+ void *data[NUM_ENTRIES];
+ unsigned added_keys;
+ uint32_t iter = 0;
+ int ret = 0;
+
+ ut_params.entries = NUM_ENTRIES;
+ ut_params.name = "test_hash_iteration";
+ ut_params.hash_func = rte_jhash;
+ ut_params.key_len = 16;
+ if (ext_table)
+ ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+ else
+ ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) {
+ data[added_keys] = (void *) ((uintptr_t) rte_rand());
+ for (i = 0; i < ut_params.key_len; i++)
+ keys[added_keys][i] = rte_rand() % 255;
+ ret = rte_hash_add_key_data(handle, keys[added_keys], data[added_keys]);
+ if (ret < 0) {
+ if (ext_table) {
+ printf("Insertion failed for ext table\n");
+ goto err;
+ }
+ break;
+ }
+ }
+
+ /* Iterate through the hash table */
+ while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {
+ /* Search for the key in the list of keys added */
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ if (memcmp(next_key, keys[i], ut_params.key_len) == 0) {
+ if (next_data != data[i]) {
+ printf("Data found in the hash table is"
+ "not the data added with the key\n");
+ goto err;
+ }
+ added_keys--;
+ break;
+ }
+ }
+ if (i == NUM_ENTRIES) {
+ printf("Key found in the hash table was not added\n");
+ goto err;
+ }
+ }
+
+ /* Check if all keys have been iterated */
+ if (added_keys != 0) {
+ printf("There were still %u keys to iterate\n", added_keys);
+ goto err;
+ }
+
+ rte_hash_free(handle);
+ return 0;
+
+err:
+ rte_hash_free(handle);
+ return -1;
+}
+
+static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f};
+static struct rte_hash_parameters hash_params_ex = {
+ .name = NULL,
+ .entries = 64,
+ .key_len = 0,
+ .hash_func = NULL,
+ .hash_func_init_val = 0,
+ .socket_id = 0,
+};
+
+/*
+ * add/delete key with jhash2
+ */
+static int
+test_hash_add_delete_jhash2(void)
+{
+ int ret = -1;
+ struct rte_hash *handle;
+ int32_t pos1, pos2;
+
+ hash_params_ex.name = "hash_test_jhash2";
+ hash_params_ex.key_len = 4;
+ hash_params_ex.hash_func = (rte_hash_function)rte_jhash_32b;
+
+ handle = rte_hash_create(&hash_params_ex);
+ if (handle == NULL) {
+ printf("test_hash_add_delete_jhash2 fail to create hash\n");
+ goto fail_jhash2;
+ }
+ pos1 = rte_hash_add_key(handle, (void *)&key[0]);
+ if (pos1 < 0) {
+ printf("test_hash_add_delete_jhash2 fail to add hash key\n");
+ goto fail_jhash2;
+ }
+
+ pos2 = rte_hash_del_key(handle, (void *)&key[0]);
+ if (pos2 < 0 || pos1 != pos2) {
+ printf("test_hash_add_delete_jhash2 delete different key from being added\n");
+ goto fail_jhash2;
+ }
+ ret = 0;
+
+fail_jhash2:
+ if (handle != NULL)
+ rte_hash_free(handle);
+
+ return ret;
+}
+
+/*
+ * add/delete (2) key with jhash2
+ */
+static int
+test_hash_add_delete_2_jhash2(void)
+{
+ int ret = -1;
+ struct rte_hash *handle;
+ int32_t pos1, pos2;
+
+ hash_params_ex.name = "hash_test_2_jhash2";
+ hash_params_ex.key_len = 8;
+ hash_params_ex.hash_func = (rte_hash_function)rte_jhash_32b;
+
+ handle = rte_hash_create(&hash_params_ex);
+ if (handle == NULL)
+ goto fail_2_jhash2;
+
+ pos1 = rte_hash_add_key(handle, (void *)&key[0]);
+ if (pos1 < 0)
+ goto fail_2_jhash2;
+
+ pos2 = rte_hash_del_key(handle, (void *)&key[0]);
+ if (pos2 < 0 || pos1 != pos2)
+ goto fail_2_jhash2;
+
+ ret = 0;
+
+fail_2_jhash2:
+ if (handle != NULL)
+ rte_hash_free(handle);
+
+ return ret;
+}
+
+static uint32_t
+test_hash_jhash_1word(const void *key, uint32_t length, uint32_t initval)
+{
+ const uint32_t *k = key;
+
+ RTE_SET_USED(length);
+
+ return rte_jhash_1word(k[0], initval);
+}
+
+static uint32_t
+test_hash_jhash_2word(const void *key, uint32_t length, uint32_t initval)
+{
+ const uint32_t *k = key;
+
+ RTE_SET_USED(length);
+
+ return rte_jhash_2words(k[0], k[1], initval);
+}
+
+static uint32_t
+test_hash_jhash_3word(const void *key, uint32_t length, uint32_t initval)
+{
+ const uint32_t *k = key;
+
+ RTE_SET_USED(length);
+
+ return rte_jhash_3words(k[0], k[1], k[2], initval);
+}
+
+/*
+ * add/delete key with jhash 1word
+ */
+static int
+test_hash_add_delete_jhash_1word(void)
+{
+ int ret = -1;
+ struct rte_hash *handle;
+ int32_t pos1, pos2;
+
+ hash_params_ex.name = "hash_test_jhash_1word";
+ hash_params_ex.key_len = 4;
+ hash_params_ex.hash_func = test_hash_jhash_1word;
+
+ handle = rte_hash_create(&hash_params_ex);
+ if (handle == NULL)
+ goto fail_jhash_1word;
+
+ pos1 = rte_hash_add_key(handle, (void *)&key[0]);
+ if (pos1 < 0)
+ goto fail_jhash_1word;
+
+ pos2 = rte_hash_del_key(handle, (void *)&key[0]);
+ if (pos2 < 0 || pos1 != pos2)
+ goto fail_jhash_1word;
+
+ ret = 0;
+
+fail_jhash_1word:
+ if (handle != NULL)
+ rte_hash_free(handle);
+
+ return ret;
+}
+
+/*
+ * add/delete key with jhash 2word
+ */
+static int
+test_hash_add_delete_jhash_2word(void)
+{
+ int ret = -1;
+ struct rte_hash *handle;
+ int32_t pos1, pos2;
+
+ hash_params_ex.name = "hash_test_jhash_2word";
+ hash_params_ex.key_len = 8;
+ hash_params_ex.hash_func = test_hash_jhash_2word;
+
+ handle = rte_hash_create(&hash_params_ex);
+ if (handle == NULL)
+ goto fail_jhash_2word;
+
+ pos1 = rte_hash_add_key(handle, (void *)&key[0]);
+ if (pos1 < 0)
+ goto fail_jhash_2word;
+
+ pos2 = rte_hash_del_key(handle, (void *)&key[0]);
+ if (pos2 < 0 || pos1 != pos2)
+ goto fail_jhash_2word;
+
+ ret = 0;
+
+fail_jhash_2word:
+ if (handle != NULL)
+ rte_hash_free(handle);
+
+ return ret;
+}
+
+/*
+ * add/delete key with jhash 3word
+ */
+static int
+test_hash_add_delete_jhash_3word(void)
+{
+ int ret = -1;
+ struct rte_hash *handle;
+ int32_t pos1, pos2;
+
+ hash_params_ex.name = "hash_test_jhash_3word";
+ hash_params_ex.key_len = 12;
+ hash_params_ex.hash_func = test_hash_jhash_3word;
+
+ handle = rte_hash_create(&hash_params_ex);
+ if (handle == NULL)
+ goto fail_jhash_3word;
+
+ pos1 = rte_hash_add_key(handle, (void *)&key[0]);
+ if (pos1 < 0)
+ goto fail_jhash_3word;
+
+ pos2 = rte_hash_del_key(handle, (void *)&key[0]);
+ if (pos2 < 0 || pos1 != pos2)
+ goto fail_jhash_3word;
+
+ ret = 0;
+
+fail_jhash_3word:
+ if (handle != NULL)
+ rte_hash_free(handle);
+
+ return ret;
+}
+
+/*
+ * Do all unit and performance tests.
+ */
+static int
+test_hash(void)
+{
+ if (test_add_delete() < 0)
+ return -1;
+ if (test_hash_add_delete_jhash2() < 0)
+ return -1;
+ if (test_hash_add_delete_2_jhash2() < 0)
+ return -1;
+ if (test_hash_add_delete_jhash_1word() < 0)
+ return -1;
+ if (test_hash_add_delete_jhash_2word() < 0)
+ return -1;
+ if (test_hash_add_delete_jhash_3word() < 0)
+ return -1;
+ if (test_hash_get_key_with_position() < 0)
+ return -1;
+ if (test_hash_find_existing() < 0)
+ return -1;
+ if (test_add_update_delete() < 0)
+ return -1;
+ if (test_add_update_delete_free() < 0)
+ return -1;
+ if (test_add_delete_free_lf() < 0)
+ return -1;
+ if (test_five_keys() < 0)
+ return -1;
+ if (test_full_bucket() < 0)
+ return -1;
+ if (test_extendable_bucket() < 0)
+ return -1;
+
+ if (test_fbk_hash_find_existing() < 0)
+ return -1;
+ if (fbk_hash_unit_test() < 0)
+ return -1;
+ if (test_hash_creation_with_bad_parameters() < 0)
+ return -1;
+ if (test_hash_creation_with_good_parameters() < 0)
+ return -1;
+
+ /* ext table disabled */
+ if (test_average_table_utilization(0) < 0)
+ return -1;
+ if (test_hash_iteration(0) < 0)
+ return -1;
+
+ /* ext table enabled */
+ if (test_average_table_utilization(1) < 0)
+ return -1;
+ if (test_hash_iteration(1) < 0)
+ return -1;
+
+ run_hash_func_tests();
+
+ if (test_crc32_hash_alg_equiv() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_autotest, test_hash);
diff --git a/src/spdk/dpdk/app/test/test_hash_functions.c b/src/spdk/dpdk/app/test/test_hash_functions.c
new file mode 100644
index 000000000..76d51b6e7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash_functions.c
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2015 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_hash.h>
+#include <rte_jhash.h>
+#include <rte_hash_crc.h>
+
+#include "test.h"
+
+/*
+ * Hash values calculated for key sizes from array "hashtest_key_lens"
+ * and for initial values from array "hashtest_initvals.
+ * Each key will be formed by increasing each byte by 1:
+ * e.g.: key size = 4, key = 0x03020100
+ * key size = 8, key = 0x0706050403020100
+ */
+static uint32_t hash_values_jhash[2][12] = {{
+ 0x8ba9414b, 0xdf0d39c9,
+ 0xe4cf1d42, 0xd4ccb93c, 0x5e84eafc, 0x21362cfe,
+ 0x2f4775ab, 0x9ff036cc, 0xeca51474, 0xbc9d6816,
+ 0x12926a31, 0x1c9fa888
+},
+{
+ 0x5c62c303, 0x1b8cf784,
+ 0x8270ac65, 0x05fa6668, 0x762df861, 0xda088f2f,
+ 0x59614cd4, 0x7a94f690, 0xdc1e4993, 0x30825494,
+ 0x91d0e462, 0x768087fc
+}
+};
+static uint32_t hash_values_crc[2][12] = {{
+ 0x00000000, 0xf26b8303,
+ 0x91545164, 0x06040eb1, 0x9bb99201, 0xcc4c4fe4,
+ 0x14a90993, 0xf8a5dd8c, 0xcaa1ad0b, 0x7ac1e03e,
+ 0x43f44466, 0x4a11475e
+},
+{
+ 0xbdfd3980, 0x70204542,
+ 0x98cd4c70, 0xd52c702f, 0x41fc0e1c, 0x3905f65c,
+ 0x94bff47f, 0x1bab102d, 0xf4a2c645, 0xbf441539,
+ 0x789c104f, 0x53028d3e
+}
+};
+
+/*******************************************************************************
+ * Hash function performance test configuration section. Each performance test
+ * will be performed HASHTEST_ITERATIONS times.
+ *
+ * The three arrays below control what tests are performed. Every combination
+ * from the array entries is tested.
+ */
+#define HASHTEST_ITERATIONS 1000000
+#define MAX_KEYSIZE 64
+static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};
+static uint32_t hashtest_initvals[] = {0, 0xdeadbeef};
+static uint32_t hashtest_key_lens[] = {
+ 1, 2, /* Unusual key sizes */
+ 4, 8, 16, 32, 48, 64, /* standard key sizes */
+ 9, /* IPv4 SRC + DST + protocol, unpadded */
+ 13, /* IPv4 5-tuple, unpadded */
+ 37, /* IPv6 5-tuple, unpadded */
+ 40 /* IPv6 5-tuple, padded to 8-byte boundary */
+};
+/******************************************************************************/
+
+/*
+ * To help print out name of hash functions.
+ */
+static const char *
+get_hash_name(rte_hash_function f)
+{
+ if (f == rte_jhash)
+ return "jhash";
+
+ if (f == rte_hash_crc)
+ return "rte_hash_crc";
+
+ return "UnknownHash";
+}
+
+/*
+ * Test a hash function.
+ */
+static void
+run_hash_func_perf_test(uint32_t key_len, uint32_t init_val,
+ rte_hash_function f)
+{
+ static uint8_t key[HASHTEST_ITERATIONS][MAX_KEYSIZE];
+ uint64_t ticks, start, end;
+ unsigned i, j;
+
+ for (i = 0; i < HASHTEST_ITERATIONS; i++) {
+ for (j = 0; j < key_len; j++)
+ key[i][j] = (uint8_t) rte_rand();
+ }
+
+ start = rte_rdtsc();
+ for (i = 0; i < HASHTEST_ITERATIONS; i++)
+ f(key[i], key_len, init_val);
+ end = rte_rdtsc();
+ ticks = end - start;
+
+ printf("%-12s, %-18u, %-13u, %.02f\n", get_hash_name(f), (unsigned) key_len,
+ (unsigned) init_val, (double)ticks / HASHTEST_ITERATIONS);
+}
+
+/*
+ * Test all hash functions.
+ */
+static void
+run_hash_func_perf_tests(void)
+{
+ unsigned i, j, k;
+
+ printf(" *** Hash function performance test results ***\n");
+ printf(" Number of iterations for each test = %d\n",
+ HASHTEST_ITERATIONS);
+ printf("Hash Func. , Key Length (bytes), Initial value, Ticks/Op.\n");
+
+ for (i = 0; i < RTE_DIM(hashtest_initvals); i++) {
+ for (j = 0; j < RTE_DIM(hashtest_key_lens); j++) {
+ for (k = 0; k < RTE_DIM(hashtest_funcs); k++) {
+ run_hash_func_perf_test(hashtest_key_lens[j],
+ hashtest_initvals[i],
+ hashtest_funcs[k]);
+ }
+ }
+ }
+}
+
+/*
+ * Verify that hash functions return what they are expected to return
+ * (using precalculated values stored above)
+ */
+static int
+verify_precalculated_hash_func_tests(void)
+{
+ unsigned i, j;
+ uint8_t key[64];
+ uint32_t hash;
+
+ for (i = 0; i < 64; i++)
+ key[i] = (uint8_t) i;
+
+ for (i = 0; i < RTE_DIM(hashtest_key_lens); i++) {
+ for (j = 0; j < RTE_DIM(hashtest_initvals); j++) {
+ hash = rte_jhash(key, hashtest_key_lens[i],
+ hashtest_initvals[j]);
+ if (hash != hash_values_jhash[j][i]) {
+ printf("jhash for %u bytes with initial value 0x%x."
+ "Expected 0x%x, but got 0x%x\n",
+ hashtest_key_lens[i], hashtest_initvals[j],
+ hash_values_jhash[j][i], hash);
+ return -1;
+ }
+
+ hash = rte_hash_crc(key, hashtest_key_lens[i],
+ hashtest_initvals[j]);
+ if (hash != hash_values_crc[j][i]) {
+ printf("CRC for %u bytes with initial value 0x%x."
+ "Expected 0x%x, but got 0x%x\n",
+ hashtest_key_lens[i], hashtest_initvals[j],
+ hash_values_crc[j][i], hash);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Verify that rte_jhash and rte_jhash_32b return the same
+ */
+static int
+verify_jhash_32bits(void)
+{
+ unsigned i, j;
+ uint8_t key[64];
+ uint32_t hash, hash32;
+
+ for (i = 0; i < 64; i++)
+ key[i] = rand() & 0xff;
+
+ for (i = 0; i < RTE_DIM(hashtest_key_lens); i++) {
+ for (j = 0; j < RTE_DIM(hashtest_initvals); j++) {
+ /* Key size must be multiple of 4 (32 bits) */
+ if ((hashtest_key_lens[i] & 0x3) == 0) {
+ hash = rte_jhash(key, hashtest_key_lens[i],
+ hashtest_initvals[j]);
+ /* Divide key length by 4 in rte_jhash for 32 bits */
+ hash32 = rte_jhash_32b((const unaligned_uint32_t *)key,
+ hashtest_key_lens[i] >> 2,
+ hashtest_initvals[j]);
+ if (hash != hash32) {
+ printf("rte_jhash returns different value (0x%x)"
+ "than rte_jhash_32b (0x%x)\n",
+ hash, hash32);
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Verify that rte_jhash and rte_jhash_1word, rte_jhash_2words
+ * and rte_jhash_3words return the same
+ */
+static int
+verify_jhash_words(void)
+{
+ unsigned i;
+ uint32_t key[3];
+ uint32_t hash, hash_words;
+
+ for (i = 0; i < 3; i++)
+ key[i] = rand();
+
+ /* Test rte_jhash_1word */
+ hash = rte_jhash(key, 4, 0);
+ hash_words = rte_jhash_1word(key[0], 0);
+ if (hash != hash_words) {
+ printf("rte_jhash returns different value (0x%x)"
+ "than rte_jhash_1word (0x%x)\n",
+ hash, hash_words);
+ return -1;
+ }
+ /* Test rte_jhash_2words */
+ hash = rte_jhash(key, 8, 0);
+ hash_words = rte_jhash_2words(key[0], key[1], 0);
+ if (hash != hash_words) {
+ printf("rte_jhash returns different value (0x%x)"
+ "than rte_jhash_2words (0x%x)\n",
+ hash, hash_words);
+ return -1;
+ }
+ /* Test rte_jhash_3words */
+ hash = rte_jhash(key, 12, 0);
+ hash_words = rte_jhash_3words(key[0], key[1], key[2], 0);
+ if (hash != hash_words) {
+ printf("rte_jhash returns different value (0x%x)"
+ "than rte_jhash_3words (0x%x)\n",
+ hash, hash_words);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Run all functional tests for hash functions
+ */
+static int
+run_hash_func_tests(void)
+{
+ if (verify_precalculated_hash_func_tests() != 0)
+ return -1;
+
+ if (verify_jhash_32bits() != 0)
+ return -1;
+
+ if (verify_jhash_words() != 0)
+ return -1;
+
+ return 0;
+
+}
+
+static int
+test_hash_functions(void)
+{
+ if (run_hash_func_tests() != 0)
+ return -1;
+
+ run_hash_func_perf_tests();
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_functions_autotest, test_hash_functions);
diff --git a/src/spdk/dpdk/app/test/test_hash_multiwriter.c b/src/spdk/dpdk/app/test/test_hash_multiwriter.c
new file mode 100644
index 000000000..46ab45f82
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash_multiwriter.c
@@ -0,0 +1,293 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 Intel Corporation
+ */
+
+#include <inttypes.h>
+#include <locale.h>
+
+#include <rte_cycles.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_launch.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_spinlock.h>
+#include <rte_jhash.h>
+
+#include "test.h"
+
+/*
+ * Check condition and return an error if true. Assumes that "handle" is the
+ * name of the hash structure pointer to be freed.
+ */
+#define RETURN_IF_ERROR(cond, str, ...) do { \
+ if (cond) { \
+ printf("ERROR line %d: " str "\n", __LINE__, \
+ ##__VA_ARGS__); \
+ if (handle) \
+ rte_hash_free(handle); \
+ return -1; \
+ } \
+} while (0)
+
+#define RTE_APP_TEST_HASH_MULTIWRITER_FAILED 0
+
+struct {
+ uint32_t *keys;
+ uint32_t *found;
+ uint32_t nb_tsx_insertion;
+ struct rte_hash *h;
+} tbl_multiwriter_test_params;
+
+const uint32_t nb_entries = 5*1024*1024;
+const uint32_t nb_total_tsx_insertion = 4.5*1024*1024;
+uint32_t rounded_nb_total_tsx_insertion;
+
+static rte_atomic64_t gcycles;
+static rte_atomic64_t ginsertions;
+
+static int use_htm;
+
+static int
+test_hash_multiwriter_worker(void *arg)
+{
+ uint64_t i, offset;
+ uint16_t pos_core;
+ uint32_t lcore_id = rte_lcore_id();
+ uint64_t begin, cycles;
+ uint16_t *enabled_core_ids = (uint16_t *)arg;
+
+ for (pos_core = 0; pos_core < rte_lcore_count(); pos_core++) {
+ if (enabled_core_ids[pos_core] == lcore_id)
+ break;
+ }
+
+ /*
+ * Calculate offset for entries based on the position of the
+ * logical core, from the master core (not counting not enabled cores)
+ */
+ offset = pos_core * tbl_multiwriter_test_params.nb_tsx_insertion;
+
+ printf("Core #%d inserting %d: %'"PRId64" - %'"PRId64"\n",
+ lcore_id, tbl_multiwriter_test_params.nb_tsx_insertion,
+ offset,
+ offset + tbl_multiwriter_test_params.nb_tsx_insertion - 1);
+
+ begin = rte_rdtsc_precise();
+
+ for (i = offset;
+ i < offset + tbl_multiwriter_test_params.nb_tsx_insertion;
+ i++) {
+ if (rte_hash_add_key(tbl_multiwriter_test_params.h,
+ tbl_multiwriter_test_params.keys + i) < 0)
+ break;
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&gcycles, cycles);
+ rte_atomic64_add(&ginsertions, i - offset);
+
+ for (; i < offset + tbl_multiwriter_test_params.nb_tsx_insertion; i++)
+ tbl_multiwriter_test_params.keys[i]
+ = RTE_APP_TEST_HASH_MULTIWRITER_FAILED;
+
+ return 0;
+}
+
+
+static int
+test_hash_multiwriter(void)
+{
+ unsigned int i, rounded_nb_total_tsx_insertion;
+ static unsigned calledCount = 1;
+ uint16_t enabled_core_ids[RTE_MAX_LCORE];
+ uint16_t core_id;
+
+ uint32_t *keys;
+ uint32_t *found;
+
+ struct rte_hash_parameters hash_params = {
+ .entries = nb_entries,
+ .key_len = sizeof(uint32_t),
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+ if (use_htm)
+ hash_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT
+ | RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+ else
+ hash_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+
+ struct rte_hash *handle;
+ char name[RTE_HASH_NAMESIZE];
+
+ const void *next_key;
+ void *next_data;
+ uint32_t iter = 0;
+
+ uint32_t duplicated_keys = 0;
+ uint32_t lost_keys = 0;
+ uint32_t count;
+
+ snprintf(name, 32, "test%u", calledCount++);
+ hash_params.name = name;
+
+ handle = rte_hash_create(&hash_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ tbl_multiwriter_test_params.h = handle;
+ tbl_multiwriter_test_params.nb_tsx_insertion =
+ nb_total_tsx_insertion / rte_lcore_count();
+
+ rounded_nb_total_tsx_insertion = (nb_total_tsx_insertion /
+ tbl_multiwriter_test_params.nb_tsx_insertion)
+ * tbl_multiwriter_test_params.nb_tsx_insertion;
+
+ rte_srand(rte_rdtsc());
+
+ keys = rte_malloc(NULL, sizeof(uint32_t) * nb_entries, 0);
+
+ if (keys == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err1;
+ }
+
+ for (i = 0; i < nb_entries; i++)
+ keys[i] = i;
+
+ tbl_multiwriter_test_params.keys = keys;
+
+ found = rte_zmalloc(NULL, sizeof(uint32_t) * nb_entries, 0);
+ if (found == NULL) {
+ printf("RTE_ZMALLOC failed\n");
+ goto err2;
+ }
+
+ tbl_multiwriter_test_params.found = found;
+
+ rte_atomic64_init(&gcycles);
+ rte_atomic64_clear(&gcycles);
+
+ rte_atomic64_init(&ginsertions);
+ rte_atomic64_clear(&ginsertions);
+
+ /* Get list of enabled cores */
+ i = 0;
+ for (core_id = 0; core_id < RTE_MAX_LCORE; core_id++) {
+ if (i == rte_lcore_count())
+ break;
+
+ if (rte_lcore_is_enabled(core_id)) {
+ enabled_core_ids[i] = core_id;
+ i++;
+ }
+ }
+
+ if (i != rte_lcore_count()) {
+ printf("Number of enabled cores in list is different from "
+ "number given by rte_lcore_count()\n");
+ goto err3;
+ }
+
+ /* Fire all threads. */
+ rte_eal_mp_remote_launch(test_hash_multiwriter_worker,
+ enabled_core_ids, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ count = rte_hash_count(handle);
+ if (count != rounded_nb_total_tsx_insertion) {
+ printf("rte_hash_count returned wrong value %u, %d\n",
+ rounded_nb_total_tsx_insertion, count);
+ goto err3;
+ }
+
+ while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {
+ /* Search for the key in the list of keys added .*/
+ i = *(const uint32_t *)next_key;
+ tbl_multiwriter_test_params.found[i]++;
+ }
+
+ for (i = 0; i < rounded_nb_total_tsx_insertion; i++) {
+ if (tbl_multiwriter_test_params.keys[i]
+ != RTE_APP_TEST_HASH_MULTIWRITER_FAILED) {
+ if (tbl_multiwriter_test_params.found[i] > 1) {
+ duplicated_keys++;
+ break;
+ }
+ if (tbl_multiwriter_test_params.found[i] == 0) {
+ lost_keys++;
+ printf("key %d is lost\n", i);
+ break;
+ }
+ }
+ }
+
+ if (duplicated_keys > 0) {
+ printf("%d key duplicated\n", duplicated_keys);
+ goto err3;
+ }
+
+ if (lost_keys > 0) {
+ printf("%d key lost\n", lost_keys);
+ goto err3;
+ }
+
+ printf("No key corrupted during multiwriter insertion.\n");
+
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gcycles)/
+ rte_atomic64_read(&ginsertions);
+
+ printf(" cycles per insertion: %llu\n", cycles_per_insertion);
+
+ rte_free(tbl_multiwriter_test_params.found);
+ rte_free(tbl_multiwriter_test_params.keys);
+ rte_hash_free(handle);
+ return 0;
+
+err3:
+ rte_free(tbl_multiwriter_test_params.found);
+err2:
+ rte_free(tbl_multiwriter_test_params.keys);
+err1:
+ rte_hash_free(handle);
+ return -1;
+}
+
+static int
+test_hash_multiwriter_main(void)
+{
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for distributor_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ setlocale(LC_NUMERIC, "");
+
+
+ if (!rte_tm_supported()) {
+ printf("Hardware transactional memory (lock elision) "
+ "is NOT supported\n");
+ } else {
+ printf("Hardware transactional memory (lock elision) "
+ "is supported\n");
+
+ printf("Test multi-writer with Hardware transactional memory\n");
+
+ use_htm = 1;
+ if (test_hash_multiwriter() < 0)
+ return -1;
+ }
+
+ printf("Test multi-writer without Hardware transactional memory\n");
+ use_htm = 0;
+ if (test_hash_multiwriter() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_multiwriter_autotest, test_hash_multiwriter_main);
diff --git a/src/spdk/dpdk/app/test/test_hash_perf.c b/src/spdk/dpdk/app/test/test_hash_perf.c
new file mode 100644
index 000000000..76cdac5d5
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash_perf.c
@@ -0,0 +1,752 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2015 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_jhash.h>
+#include <rte_fbk_hash.h>
+#include <rte_random.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+#define MAX_ENTRIES (1 << 19)
+#define KEYS_TO_ADD (MAX_ENTRIES)
+#define ADD_PERCENT 0.75 /* 75% table utilization */
+#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
+/* BUCKET_SIZE should be same as RTE_HASH_BUCKET_ENTRIES in rte_hash library */
+#define BUCKET_SIZE 8
+#define NUM_BUCKETS (MAX_ENTRIES / BUCKET_SIZE)
+#define MAX_KEYSIZE 64
+#define NUM_KEYSIZES 10
+#define NUM_SHUFFLES 10
+#define BURST_SIZE 16
+
+enum operations {
+ ADD = 0,
+ LOOKUP,
+ LOOKUP_MULTI,
+ DELETE,
+ NUM_OPERATIONS
+};
+
+static uint32_t hashtest_key_lens[] = {
+ /* standard key sizes */
+ 4, 8, 16, 32, 48, 64,
+ /* IPv4 SRC + DST + protocol, unpadded */
+ 9,
+ /* IPv4 5-tuple, unpadded */
+ 13,
+ /* IPv6 5-tuple, unpadded */
+ 37,
+ /* IPv6 5-tuple, padded to 8-byte boundary */
+ 40
+};
+
+struct rte_hash *h[NUM_KEYSIZES];
+
+/* Array that stores if a slot is full */
+static uint8_t slot_taken[MAX_ENTRIES];
+
+/* Array to store number of cycles per operation */
+static uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS][2][2];
+
+/* Array to store all input keys */
+static uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
+
+/* Array to store the precomputed hash for 'keys' */
+static hash_sig_t signatures[KEYS_TO_ADD];
+
+/* Array to store how many busy entries have each bucket */
+static uint8_t buckets[NUM_BUCKETS];
+
+/* Array to store the positions where keys are added */
+static int32_t positions[KEYS_TO_ADD];
+
+/* Parameters used for hash table in unit test functions. */
+static struct rte_hash_parameters ut_params = {
+ .entries = MAX_ENTRIES,
+ .hash_func = rte_jhash,
+ .hash_func_init_val = 0,
+};
+
+static int
+create_table(unsigned int with_data, unsigned int table_index,
+ unsigned int with_locks, unsigned int ext)
+{
+ char name[RTE_HASH_NAMESIZE];
+
+ if (with_data)
+ /* Table will store 8-byte data */
+ snprintf(name, sizeof(name), "test_hash%u_data",
+ hashtest_key_lens[table_index]);
+ else
+ snprintf(name, sizeof(name), "test_hash%u",
+ hashtest_key_lens[table_index]);
+
+
+ if (with_locks)
+ ut_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT
+ | RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY;
+ else
+ ut_params.extra_flag = 0;
+
+ if (ext)
+ ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+
+ ut_params.name = name;
+ ut_params.key_len = hashtest_key_lens[table_index];
+ ut_params.socket_id = rte_socket_id();
+ h[table_index] = rte_hash_find_existing(name);
+ if (h[table_index] != NULL)
+ /*
+ * If table was already created, free it to create it again,
+ * so we force it is empty
+ */
+ rte_hash_free(h[table_index]);
+ h[table_index] = rte_hash_create(&ut_params);
+ if (h[table_index] == NULL) {
+ printf("Error creating table\n");
+ return -1;
+ }
+ return 0;
+
+}
+
+/* Shuffle the keys that have been added, so lookups will be totally random */
+static void
+shuffle_input_keys(unsigned int table_index, unsigned int ext)
+{
+ unsigned i;
+ uint32_t swap_idx;
+ uint8_t temp_key[MAX_KEYSIZE];
+ hash_sig_t temp_signature;
+ int32_t temp_position;
+ unsigned int keys_to_add;
+
+ if (!ext)
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ else
+ keys_to_add = KEYS_TO_ADD;
+
+ for (i = keys_to_add - 1; i > 0; i--) {
+ swap_idx = rte_rand() % i;
+
+ memcpy(temp_key, keys[i], hashtest_key_lens[table_index]);
+ temp_signature = signatures[i];
+ temp_position = positions[i];
+
+ memcpy(keys[i], keys[swap_idx], hashtest_key_lens[table_index]);
+ signatures[i] = signatures[swap_idx];
+ positions[i] = positions[swap_idx];
+
+ memcpy(keys[swap_idx], temp_key, hashtest_key_lens[table_index]);
+ signatures[swap_idx] = temp_signature;
+ positions[swap_idx] = temp_position;
+ }
+}
+
+/*
+ * Looks for random keys which
+ * ALL can fit in hash table (no errors)
+ */
+static int
+get_input_keys(unsigned int with_pushes, unsigned int table_index,
+ unsigned int ext)
+{
+ unsigned i, j;
+ unsigned bucket_idx, incr, success = 1;
+ uint8_t k = 0;
+ int32_t ret;
+ const uint32_t bucket_bitmask = NUM_BUCKETS - 1;
+ unsigned int keys_to_add;
+
+ if (!ext)
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ else
+ keys_to_add = KEYS_TO_ADD;
+ /* Reset all arrays */
+ for (i = 0; i < MAX_ENTRIES; i++)
+ slot_taken[i] = 0;
+
+ for (i = 0; i < NUM_BUCKETS; i++)
+ buckets[i] = 0;
+
+ for (j = 0; j < hashtest_key_lens[table_index]; j++)
+ keys[0][j] = 0;
+
+ /*
+ * Add only entries that are not duplicated and that fits in the table
+ * (cannot store more than BUCKET_SIZE entries in a bucket).
+ * Regardless a key has been added correctly or not (success),
+ * the next one to try will be increased by 1.
+ */
+ for (i = 0; i < keys_to_add;) {
+ incr = 0;
+ if (i != 0) {
+ keys[i][0] = ++k;
+ /* Overflow, need to increment the next byte */
+ if (keys[i][0] == 0)
+ incr = 1;
+ for (j = 1; j < hashtest_key_lens[table_index]; j++) {
+ /* Do not increase next byte */
+ if (incr == 0)
+ if (success == 1)
+ keys[i][j] = keys[i - 1][j];
+ else
+ keys[i][j] = keys[i][j];
+ /* Increase next byte by one */
+ else {
+ if (success == 1)
+ keys[i][j] = keys[i-1][j] + 1;
+ else
+ keys[i][j] = keys[i][j] + 1;
+ if (keys[i][j] == 0)
+ incr = 1;
+ else
+ incr = 0;
+ }
+ }
+ }
+ success = 0;
+ signatures[i] = rte_hash_hash(h[table_index], keys[i]);
+ bucket_idx = signatures[i] & bucket_bitmask;
+ /*
+ * If we are not inserting keys in secondary location,
+ * when bucket is full, do not try to insert the key
+ */
+ if (with_pushes == 0)
+ if (buckets[bucket_idx] == BUCKET_SIZE)
+ continue;
+
+ /* If key can be added, leave in successful key arrays "keys" */
+ ret = rte_hash_add_key_with_hash(h[table_index], keys[i],
+ signatures[i]);
+ if (ret >= 0) {
+ /* If key is already added, ignore the entry and do not store */
+ if (slot_taken[ret])
+ continue;
+ else {
+ /* Store the returned position and mark slot as taken */
+ slot_taken[ret] = 1;
+ positions[i] = ret;
+ buckets[bucket_idx]++;
+ success = 1;
+ i++;
+ }
+ }
+ }
+
+ /* Reset the table, so we can measure the time to add all the entries */
+ rte_hash_free(h[table_index]);
+ h[table_index] = rte_hash_create(&ut_params);
+
+ return 0;
+}
+
+static int
+timed_adds(unsigned int with_hash, unsigned int with_data,
+ unsigned int table_index, unsigned int ext)
+{
+ unsigned i;
+ const uint64_t start_tsc = rte_rdtsc();
+ void *data;
+ int32_t ret;
+ unsigned int keys_to_add;
+ if (!ext)
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ else
+ keys_to_add = KEYS_TO_ADD;
+
+ for (i = 0; i < keys_to_add; i++) {
+ data = (void *) ((uintptr_t) signatures[i]);
+ if (with_hash && with_data) {
+ ret = rte_hash_add_key_with_hash_data(h[table_index],
+ (const void *) keys[i],
+ signatures[i], data);
+ if (ret < 0) {
+ printf("H+D: Failed to add key number %u\n", i);
+ return -1;
+ }
+ } else if (with_hash && !with_data) {
+ ret = rte_hash_add_key_with_hash(h[table_index],
+ (const void *) keys[i],
+ signatures[i]);
+ if (ret >= 0)
+ positions[i] = ret;
+ else {
+ printf("H: Failed to add key number %u\n", i);
+ return -1;
+ }
+ } else if (!with_hash && with_data) {
+ ret = rte_hash_add_key_data(h[table_index],
+ (const void *) keys[i],
+ data);
+ if (ret < 0) {
+ printf("D: Failed to add key number %u\n", i);
+ return -1;
+ }
+ } else {
+ ret = rte_hash_add_key(h[table_index], keys[i]);
+ if (ret >= 0)
+ positions[i] = ret;
+ else {
+ printf("Failed to add key number %u\n", i);
+ return -1;
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[table_index][ADD][with_hash][with_data] = time_taken/keys_to_add;
+
+ return 0;
+}
+
+static int
+timed_lookups(unsigned int with_hash, unsigned int with_data,
+ unsigned int table_index, unsigned int ext)
+{
+ unsigned i, j;
+ const uint64_t start_tsc = rte_rdtsc();
+ void *ret_data;
+ void *expected_data;
+ int32_t ret;
+ unsigned int keys_to_add, num_lookups;
+
+ if (!ext) {
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ num_lookups = NUM_LOOKUPS * ADD_PERCENT;
+ } else {
+ keys_to_add = KEYS_TO_ADD;
+ num_lookups = NUM_LOOKUPS;
+ }
+ for (i = 0; i < num_lookups / keys_to_add; i++) {
+ for (j = 0; j < keys_to_add; j++) {
+ if (with_hash && with_data) {
+ ret = rte_hash_lookup_with_hash_data(h[table_index],
+ (const void *) keys[j],
+ signatures[j], &ret_data);
+ if (ret < 0) {
+ printf("Key number %u was not found\n", j);
+ return -1;
+ }
+ expected_data = (void *) ((uintptr_t) signatures[j]);
+ if (ret_data != expected_data) {
+ printf("Data returned for key number %u is %p,"
+ " but should be %p\n", j, ret_data,
+ expected_data);
+ return -1;
+ }
+ } else if (with_hash && !with_data) {
+ ret = rte_hash_lookup_with_hash(h[table_index],
+ (const void *) keys[j],
+ signatures[j]);
+ if (ret < 0 || ret != positions[j]) {
+ printf("Key looked up in %d, should be in %d\n",
+ ret, positions[j]);
+ return -1;
+ }
+ } else if (!with_hash && with_data) {
+ ret = rte_hash_lookup_data(h[table_index],
+ (const void *) keys[j], &ret_data);
+ if (ret < 0) {
+ printf("Key number %u was not found\n", j);
+ return -1;
+ }
+ expected_data = (void *) ((uintptr_t) signatures[j]);
+ if (ret_data != expected_data) {
+ printf("Data returned for key number %u is %p,"
+ " but should be %p\n", j, ret_data,
+ expected_data);
+ return -1;
+ }
+ } else {
+ ret = rte_hash_lookup(h[table_index], keys[j]);
+ if (ret < 0 || ret != positions[j]) {
+ printf("Key looked up in %d, should be in %d\n",
+ ret, positions[j]);
+ return -1;
+ }
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[table_index][LOOKUP][with_hash][with_data] = time_taken/num_lookups;
+
+ return 0;
+}
+
+static int
+timed_lookups_multi(unsigned int with_hash, unsigned int with_data,
+ unsigned int table_index, unsigned int ext)
+{
+ unsigned i, j, k;
+ int32_t positions_burst[BURST_SIZE];
+ const void *keys_burst[BURST_SIZE];
+ void *expected_data[BURST_SIZE];
+ void *ret_data[BURST_SIZE];
+ uint64_t hit_mask;
+ int ret;
+ unsigned int keys_to_add, num_lookups;
+
+ if (!ext) {
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ num_lookups = NUM_LOOKUPS * ADD_PERCENT;
+ } else {
+ keys_to_add = KEYS_TO_ADD;
+ num_lookups = NUM_LOOKUPS;
+ }
+
+ const uint64_t start_tsc = rte_rdtsc();
+
+ for (i = 0; i < num_lookups/keys_to_add; i++) {
+ for (j = 0; j < keys_to_add/BURST_SIZE; j++) {
+ for (k = 0; k < BURST_SIZE; k++)
+ keys_burst[k] = keys[j * BURST_SIZE + k];
+ if (!with_hash && with_data) {
+ ret = rte_hash_lookup_bulk_data(h[table_index],
+ (const void **) keys_burst,
+ BURST_SIZE,
+ &hit_mask,
+ ret_data);
+ if (ret != BURST_SIZE) {
+ printf("Expect to find %u keys,"
+ " but found %d\n", BURST_SIZE, ret);
+ return -1;
+ }
+ for (k = 0; k < BURST_SIZE; k++) {
+ if ((hit_mask & (1ULL << k)) == 0) {
+ printf("Key number %u not found\n",
+ j * BURST_SIZE + k);
+ return -1;
+ }
+ expected_data[k] = (void *) ((uintptr_t) signatures[j * BURST_SIZE + k]);
+ if (ret_data[k] != expected_data[k]) {
+ printf("Data returned for key number %u is %p,"
+ " but should be %p\n", j * BURST_SIZE + k,
+ ret_data[k], expected_data[k]);
+ return -1;
+ }
+ }
+ } else if (with_hash && with_data) {
+ ret = rte_hash_lookup_with_hash_bulk_data(
+ h[table_index],
+ (const void **)keys_burst,
+ &signatures[j * BURST_SIZE],
+ BURST_SIZE, &hit_mask, ret_data);
+ if (ret != BURST_SIZE) {
+ printf("Expect to find %u keys,"
+ " but found %d\n",
+ BURST_SIZE, ret);
+ return -1;
+ }
+ for (k = 0; k < BURST_SIZE; k++) {
+ if ((hit_mask & (1ULL << k)) == 0) {
+ printf("Key number %u"
+ " not found\n",
+ j * BURST_SIZE + k);
+ return -1;
+ }
+ expected_data[k] =
+ (void *)((uintptr_t)signatures[
+ j * BURST_SIZE + k]);
+ if (ret_data[k] != expected_data[k]) {
+ printf("Data returned for key"
+ " number %u is %p,"
+ " but should be %p\n",
+ j * BURST_SIZE + k,
+ ret_data[k],
+ expected_data[k]);
+ return -1;
+ }
+ }
+ } else if (with_hash && !with_data) {
+ ret = rte_hash_lookup_with_hash_bulk(
+ h[table_index],
+ (const void **)keys_burst,
+ &signatures[j * BURST_SIZE],
+ BURST_SIZE, positions_burst);
+ for (k = 0; k < BURST_SIZE; k++) {
+ if (positions_burst[k] !=
+ positions[j *
+ BURST_SIZE + k]) {
+ printf("Key looked up in %d, should be in %d\n",
+ positions_burst[k],
+ positions[j *
+ BURST_SIZE + k]);
+ return -1;
+ }
+ }
+ } else {
+ rte_hash_lookup_bulk(h[table_index],
+ (const void **) keys_burst,
+ BURST_SIZE,
+ positions_burst);
+ for (k = 0; k < BURST_SIZE; k++) {
+ if (positions_burst[k] != positions[j * BURST_SIZE + k]) {
+ printf("Key looked up in %d, should be in %d\n",
+ positions_burst[k],
+ positions[j * BURST_SIZE + k]);
+ return -1;
+ }
+ }
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[table_index][LOOKUP_MULTI][with_hash][with_data] =
+ time_taken/num_lookups;
+
+ return 0;
+}
+
+static int
+timed_deletes(unsigned int with_hash, unsigned int with_data,
+ unsigned int table_index, unsigned int ext)
+{
+ unsigned i;
+ const uint64_t start_tsc = rte_rdtsc();
+ int32_t ret;
+ unsigned int keys_to_add;
+ if (!ext)
+ keys_to_add = KEYS_TO_ADD * ADD_PERCENT;
+ else
+ keys_to_add = KEYS_TO_ADD;
+
+ for (i = 0; i < keys_to_add; i++) {
+ /* There are no delete functions with data, so just call two functions */
+ if (with_hash)
+ ret = rte_hash_del_key_with_hash(h[table_index],
+ (const void *) keys[i],
+ signatures[i]);
+ else
+ ret = rte_hash_del_key(h[table_index],
+ (const void *) keys[i]);
+ if (ret >= 0)
+ positions[i] = ret;
+ else {
+ printf("Failed to delete key number %u\n", i);
+ return -1;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[table_index][DELETE][with_hash][with_data] = time_taken/keys_to_add;
+
+ return 0;
+}
+
+static void
+free_table(unsigned table_index)
+{
+ rte_hash_free(h[table_index]);
+}
+
+static void
+reset_table(unsigned table_index)
+{
+ rte_hash_reset(h[table_index]);
+}
+
+static int
+run_all_tbl_perf_tests(unsigned int with_pushes, unsigned int with_locks,
+ unsigned int ext)
+{
+ unsigned i, j, with_data, with_hash;
+
+ printf("Measuring performance, please wait");
+ fflush(stdout);
+
+ for (with_data = 0; with_data <= 1; with_data++) {
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ if (create_table(with_data, i, with_locks, ext) < 0)
+ return -1;
+
+ if (get_input_keys(with_pushes, i, ext) < 0)
+ return -1;
+ for (with_hash = 0; with_hash <= 1; with_hash++) {
+ if (timed_adds(with_hash, with_data, i, ext) < 0)
+ return -1;
+
+ for (j = 0; j < NUM_SHUFFLES; j++)
+ shuffle_input_keys(i, ext);
+
+ if (timed_lookups(with_hash, with_data, i, ext) < 0)
+ return -1;
+
+ if (timed_lookups_multi(with_hash, with_data,
+ i, ext) < 0)
+ return -1;
+
+ if (timed_deletes(with_hash, with_data, i, ext) < 0)
+ return -1;
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+
+ reset_table(i);
+ }
+ free_table(i);
+ }
+ }
+
+ printf("\nResults (in CPU cycles/operation)\n");
+ printf("-----------------------------------\n");
+ for (with_data = 0; with_data <= 1; with_data++) {
+ if (with_data)
+ printf("\n Operations with 8-byte data\n");
+ else
+ printf("\n Operations without data\n");
+ for (with_hash = 0; with_hash <= 1; with_hash++) {
+ if (with_hash)
+ printf("\nWith pre-computed hash values\n");
+ else
+ printf("\nWithout pre-computed hash values\n");
+
+ printf("\n%-18s%-18s%-18s%-18s%-18s\n",
+ "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete");
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ printf("%-18d", hashtest_key_lens[i]);
+ for (j = 0; j < NUM_OPERATIONS; j++)
+ printf("%-18"PRIu64, cycles[i][j][with_hash][with_data]);
+ printf("\n");
+ }
+ }
+ }
+ return 0;
+}
+
+/* Control operation of performance testing of fbk hash. */
+#define LOAD_FACTOR 0.667 /* How full to make the hash table. */
+#define TEST_SIZE 1000000 /* How many operations to time. */
+#define TEST_ITERATIONS 30 /* How many measurements to take. */
+#define ENTRIES (1 << 15) /* How many entries. */
+
+static int
+fbk_hash_perf_test(void)
+{
+ struct rte_fbk_hash_params params = {
+ .name = "fbk_hash_test",
+ .entries = ENTRIES,
+ .entries_per_bucket = 4,
+ .socket_id = rte_socket_id(),
+ };
+ struct rte_fbk_hash_table *handle = NULL;
+ uint32_t *keys = NULL;
+ unsigned indexes[TEST_SIZE];
+ uint64_t lookup_time = 0;
+ unsigned added = 0;
+ unsigned value = 0;
+ uint32_t key;
+ uint16_t val;
+ unsigned i, j;
+
+ handle = rte_fbk_hash_create(&params);
+ if (handle == NULL) {
+ printf("Error creating table\n");
+ return -1;
+ }
+
+ keys = rte_zmalloc(NULL, ENTRIES * sizeof(*keys), 0);
+ if (keys == NULL) {
+ printf("fbk hash: memory allocation for key store failed\n");
+ return -1;
+ }
+
+ /* Generate random keys and values. */
+ for (i = 0; i < ENTRIES; i++) {
+ key = (uint32_t)rte_rand();
+ key = ((uint64_t)key << 32) | (uint64_t)rte_rand();
+ val = (uint16_t)rte_rand();
+
+ if (rte_fbk_hash_add_key(handle, key, val) == 0) {
+ keys[added] = key;
+ added++;
+ }
+ if (added > (LOAD_FACTOR * ENTRIES))
+ break;
+ }
+
+ for (i = 0; i < TEST_ITERATIONS; i++) {
+ uint64_t begin;
+ uint64_t end;
+
+ /* Generate random indexes into keys[] array. */
+ for (j = 0; j < TEST_SIZE; j++)
+ indexes[j] = rte_rand() % added;
+
+ begin = rte_rdtsc();
+ /* Do lookups */
+ for (j = 0; j < TEST_SIZE; j++)
+ value += rte_fbk_hash_lookup(handle, keys[indexes[j]]);
+
+ end = rte_rdtsc();
+ lookup_time += (double)(end - begin);
+ }
+
+ printf("\n\n *** FBK Hash function performance test results ***\n");
+ /*
+ * The use of the 'value' variable ensures that the hash lookup is not
+ * being optimised out by the compiler.
+ */
+ if (value != 0)
+ printf("Number of ticks per lookup = %g\n",
+ (double)lookup_time /
+ ((double)TEST_ITERATIONS * (double)TEST_SIZE));
+
+ rte_fbk_hash_free(handle);
+
+ return 0;
+}
+
+static int
+test_hash_perf(void)
+{
+ unsigned int with_pushes, with_locks;
+ for (with_locks = 0; with_locks <= 1; with_locks++) {
+ if (with_locks)
+ printf("\nWith locks in the code\n");
+ else
+ printf("\nWithout locks in the code\n");
+ for (with_pushes = 0; with_pushes <= 1; with_pushes++) {
+ if (with_pushes == 0)
+ printf("\nALL ELEMENTS IN PRIMARY LOCATION\n");
+ else
+ printf("\nELEMENTS IN PRIMARY OR SECONDARY LOCATION\n");
+ if (run_all_tbl_perf_tests(with_pushes, with_locks, 0) < 0)
+ return -1;
+ }
+ }
+
+ printf("\n EXTENDABLE BUCKETS PERFORMANCE\n");
+
+ if (run_all_tbl_perf_tests(1, 0, 1) < 0)
+ return -1;
+
+ if (fbk_hash_perf_test() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_perf_autotest, test_hash_perf);
diff --git a/src/spdk/dpdk/app/test/test_hash_readwrite.c b/src/spdk/dpdk/app/test/test_hash_readwrite.c
new file mode 100644
index 000000000..73333dff1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash_readwrite.c
@@ -0,0 +1,767 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <inttypes.h>
+#include <locale.h>
+
+#include <rte_cycles.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_jhash.h>
+#include <rte_launch.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_spinlock.h>
+
+#include "test.h"
+
+#define RTE_RWTEST_FAIL 0
+
+#define TOTAL_ENTRY (5*1024*1024)
+#define TOTAL_INSERT (4.5*1024*1024)
+#define TOTAL_INSERT_EXT (5*1024*1024)
+
+#define NUM_TEST 3
+unsigned int core_cnt[NUM_TEST] = {2, 4, 8};
+
+unsigned int slave_core_ids[RTE_MAX_LCORE];
+struct perf {
+ uint32_t single_read;
+ uint32_t single_write;
+ uint32_t read_only[NUM_TEST];
+ uint32_t write_only[NUM_TEST];
+ uint32_t read_write_r[NUM_TEST];
+ uint32_t read_write_w[NUM_TEST];
+};
+
+static struct perf htm_results, non_htm_results;
+
+struct {
+ uint32_t *keys;
+ uint8_t *found;
+ uint32_t num_insert;
+ uint32_t rounded_tot_insert;
+ struct rte_hash *h;
+} tbl_rw_test_param;
+
+static rte_atomic64_t gcycles;
+static rte_atomic64_t ginsertions;
+
+static rte_atomic64_t gread_cycles;
+static rte_atomic64_t gwrite_cycles;
+
+static rte_atomic64_t greads;
+static rte_atomic64_t gwrites;
+
+static int
+test_hash_readwrite_worker(__rte_unused void *arg)
+{
+ uint64_t i, offset;
+ uint32_t lcore_id = rte_lcore_id();
+ uint64_t begin, cycles;
+ int *ret;
+
+ ret = rte_malloc(NULL, sizeof(int) *
+ tbl_rw_test_param.num_insert, 0);
+ for (i = 0; i < rte_lcore_count(); i++) {
+ if (slave_core_ids[i] == lcore_id)
+ break;
+ }
+ offset = tbl_rw_test_param.num_insert * i;
+
+ printf("Core #%d inserting and reading %d: %'"PRId64" - %'"PRId64"\n",
+ lcore_id, tbl_rw_test_param.num_insert,
+ offset, offset + tbl_rw_test_param.num_insert - 1);
+
+ begin = rte_rdtsc_precise();
+
+ for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
+
+ if (rte_hash_lookup(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i) > 0)
+ break;
+
+ ret[i - offset] = rte_hash_add_key(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i);
+ if (ret[i - offset] < 0)
+ break;
+
+ /* lookup a random key */
+ uint32_t rand = rte_rand() % (i + 1 - offset);
+
+ if (rte_hash_lookup(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + rand) != ret[rand])
+ break;
+
+
+ if (rte_hash_del_key(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + rand) != ret[rand])
+ break;
+
+ ret[rand] = rte_hash_add_key(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + rand);
+ if (ret[rand] < 0)
+ break;
+
+ if (rte_hash_lookup(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + rand) != ret[rand])
+ break;
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&gcycles, cycles);
+ rte_atomic64_add(&ginsertions, i - offset);
+
+ for (; i < offset + tbl_rw_test_param.num_insert; i++)
+ tbl_rw_test_param.keys[i] = RTE_RWTEST_FAIL;
+
+ rte_free(ret);
+ return 0;
+}
+
+static int
+init_params(int use_ext, int use_htm, int rw_lf, int use_jhash)
+{
+ unsigned int i;
+
+ uint32_t *keys = NULL;
+ uint8_t *found = NULL;
+ struct rte_hash *handle;
+
+ struct rte_hash_parameters hash_params = {
+ .entries = TOTAL_ENTRY,
+ .key_len = sizeof(uint32_t),
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+ if (use_jhash)
+ hash_params.hash_func = rte_jhash;
+ else
+ hash_params.hash_func = rte_hash_crc;
+
+ hash_params.extra_flag = RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+ if (use_htm)
+ hash_params.extra_flag |=
+ RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT;
+ if (rw_lf)
+ hash_params.extra_flag |=
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
+ else
+ hash_params.extra_flag |=
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY;
+
+ if (use_ext)
+ hash_params.extra_flag |=
+ RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+ else
+ hash_params.extra_flag &=
+ ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+
+ hash_params.name = "tests";
+
+ handle = rte_hash_create(&hash_params);
+ if (handle == NULL) {
+ printf("hash creation failed");
+ return -1;
+ }
+
+ tbl_rw_test_param.h = handle;
+ keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
+
+ if (keys == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ found = rte_zmalloc(NULL, sizeof(uint8_t) * TOTAL_ENTRY, 0);
+ if (found == NULL) {
+ printf("RTE_ZMALLOC failed\n");
+ goto err;
+ }
+
+ tbl_rw_test_param.keys = keys;
+ tbl_rw_test_param.found = found;
+
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ keys[i] = i;
+
+ return 0;
+
+err:
+ rte_free(keys);
+ rte_hash_free(handle);
+
+ return -1;
+}
+
+static int
+test_hash_readwrite_functional(int use_htm, int use_rw_lf, int use_ext)
+{
+ unsigned int i;
+ const void *next_key;
+ void *next_data;
+ uint32_t iter = 0;
+
+ uint32_t duplicated_keys = 0;
+ uint32_t lost_keys = 0;
+ int use_jhash = 1;
+ int slave_cnt = rte_lcore_count() - 1;
+ uint32_t tot_insert = 0;
+
+ rte_atomic64_init(&gcycles);
+ rte_atomic64_clear(&gcycles);
+
+ rte_atomic64_init(&ginsertions);
+ rte_atomic64_clear(&ginsertions);
+
+ if (init_params(use_ext, use_htm, use_rw_lf, use_jhash) != 0)
+ goto err;
+
+ if (use_ext)
+ tot_insert = TOTAL_INSERT_EXT;
+ else
+ tot_insert = TOTAL_INSERT;
+
+ tbl_rw_test_param.num_insert =
+ tot_insert / slave_cnt;
+
+ tbl_rw_test_param.rounded_tot_insert =
+ tbl_rw_test_param.num_insert
+ * slave_cnt;
+
+ printf("\nHTM = %d, RW-LF = %d, EXT-Table = %d\n",
+ use_htm, use_rw_lf, use_ext);
+ printf("++++++++Start function tests:+++++++++\n");
+
+ /* Fire all threads. */
+ rte_eal_mp_remote_launch(test_hash_readwrite_worker,
+ NULL, SKIP_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ while (rte_hash_iterate(tbl_rw_test_param.h, &next_key,
+ &next_data, &iter) >= 0) {
+ /* Search for the key in the list of keys added .*/
+ i = *(const uint32_t *)next_key;
+ tbl_rw_test_param.found[i]++;
+ }
+
+ for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
+ if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
+ if (tbl_rw_test_param.found[i] > 1) {
+ duplicated_keys++;
+ break;
+ }
+ if (tbl_rw_test_param.found[i] == 0) {
+ lost_keys++;
+ printf("key %d is lost\n", i);
+ break;
+ }
+ }
+ }
+
+ if (duplicated_keys > 0) {
+ printf("%d key duplicated\n", duplicated_keys);
+ goto err_free;
+ }
+
+ if (lost_keys > 0) {
+ printf("%d key lost\n", lost_keys);
+ goto err_free;
+ }
+
+ printf("No key corrupted during read-write test.\n");
+
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gcycles) /
+ rte_atomic64_read(&ginsertions);
+
+ printf("cycles per insertion and lookup: %llu\n", cycles_per_insertion);
+
+ rte_free(tbl_rw_test_param.found);
+ rte_free(tbl_rw_test_param.keys);
+ rte_hash_free(tbl_rw_test_param.h);
+ printf("+++++++++Complete function tests+++++++++\n");
+ return 0;
+
+err_free:
+ rte_free(tbl_rw_test_param.found);
+ rte_free(tbl_rw_test_param.keys);
+ rte_hash_free(tbl_rw_test_param.h);
+err:
+ return -1;
+}
+
+static int
+test_rw_reader(void *arg)
+{
+ uint64_t i;
+ uint64_t begin, cycles;
+ uint64_t read_cnt = (uint64_t)((uintptr_t)arg);
+
+ begin = rte_rdtsc_precise();
+ for (i = 0; i < read_cnt; i++) {
+ void *data = arg;
+ rte_hash_lookup_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ &data);
+ if (i != (uint64_t)(uintptr_t)data) {
+ printf("lookup find wrong value %"PRIu64","
+ "%"PRIu64"\n", i,
+ (uint64_t)(uintptr_t)data);
+ break;
+ }
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&gread_cycles, cycles);
+ rte_atomic64_add(&greads, i);
+ return 0;
+}
+
+static int
+test_rw_writer(void *arg)
+{
+ uint64_t i;
+ uint32_t lcore_id = rte_lcore_id();
+ uint64_t begin, cycles;
+ int ret;
+ uint64_t start_coreid = (uint64_t)(uintptr_t)arg;
+ uint64_t offset;
+
+ for (i = 0; i < rte_lcore_count(); i++) {
+ if (slave_core_ids[i] == lcore_id)
+ break;
+ }
+
+ offset = TOTAL_INSERT / 2 + (i - (start_coreid)) *
+ tbl_rw_test_param.num_insert;
+ begin = rte_rdtsc_precise();
+ for (i = offset; i < offset + tbl_rw_test_param.num_insert; i++) {
+ ret = rte_hash_add_key_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ (void *)((uintptr_t)i));
+ if (ret < 0) {
+ printf("writer failed %"PRIu64"\n", i);
+ break;
+ }
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&gwrite_cycles, cycles);
+ rte_atomic64_add(&gwrites, tbl_rw_test_param.num_insert);
+ return 0;
+}
+
+static int
+test_hash_readwrite_perf(struct perf *perf_results, int use_htm,
+ int reader_faster)
+{
+ unsigned int n;
+ int ret;
+ int start_coreid;
+ uint64_t i, read_cnt;
+
+ const void *next_key;
+ void *next_data;
+ uint32_t iter;
+ int use_jhash = 0;
+
+ uint32_t duplicated_keys = 0;
+ uint32_t lost_keys = 0;
+
+ uint64_t start = 0, end = 0;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gwrites);
+ rte_atomic64_clear(&gwrites);
+ rte_atomic64_clear(&greads);
+
+ rte_atomic64_init(&gread_cycles);
+ rte_atomic64_clear(&gread_cycles);
+ rte_atomic64_init(&gwrite_cycles);
+ rte_atomic64_clear(&gwrite_cycles);
+
+ if (init_params(0, use_htm, 0, use_jhash) != 0)
+ goto err;
+
+ /*
+ * Do a readers finish faster or writers finish faster test.
+ * When readers finish faster, we timing the readers, and when writers
+ * finish faster, we timing the writers.
+ * Divided by 10 or 2 is just experimental values to vary the workload
+ * of readers.
+ */
+ if (reader_faster) {
+ printf("++++++Start perf test: reader++++++++\n");
+ read_cnt = TOTAL_INSERT / 10;
+ } else {
+ printf("++++++Start perf test: writer++++++++\n");
+ read_cnt = TOTAL_INSERT / 2;
+ }
+
+ /* We first test single thread performance */
+ start = rte_rdtsc_precise();
+ /* Insert half of the keys */
+ for (i = 0; i < TOTAL_INSERT / 2; i++) {
+ ret = rte_hash_add_key_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ (void *)((uintptr_t)i));
+ if (ret < 0) {
+ printf("Failed to insert half of keys\n");
+ goto err_free;
+ }
+ }
+ end = rte_rdtsc_precise() - start;
+ perf_results->single_write = end / i;
+
+ start = rte_rdtsc_precise();
+
+ for (i = 0; i < read_cnt; i++) {
+ void *data;
+ rte_hash_lookup_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ &data);
+ if (i != (uint64_t)(uintptr_t)data) {
+ printf("lookup find wrong value"
+ " %"PRIu64",%"PRIu64"\n", i,
+ (uint64_t)(uintptr_t)data);
+ break;
+ }
+ }
+ end = rte_rdtsc_precise() - start;
+ perf_results->single_read = end / i;
+
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_slave_lcore = rte_lcore_count() - 1;
+ if (tot_slave_lcore < core_cnt[n] * 2)
+ goto finish;
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+ rte_atomic64_clear(&gwrites);
+ rte_atomic64_clear(&gwrite_cycles);
+
+ rte_hash_reset(tbl_rw_test_param.h);
+
+ tbl_rw_test_param.num_insert = TOTAL_INSERT / 2 / core_cnt[n];
+ tbl_rw_test_param.rounded_tot_insert = TOTAL_INSERT / 2 +
+ tbl_rw_test_param.num_insert *
+ core_cnt[n];
+
+ for (i = 0; i < TOTAL_INSERT / 2; i++) {
+ ret = rte_hash_add_key_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ (void *)((uintptr_t)i));
+ if (ret < 0) {
+ printf("Failed to insert half of keys\n");
+ goto err_free;
+ }
+ }
+
+ /* Then test multiple thread case but only all reads or
+ * all writes
+ */
+
+ /* Test only reader cases */
+ for (i = 0; i < core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rw_reader,
+ (void *)(uintptr_t)read_cnt,
+ slave_core_ids[i]);
+
+ rte_eal_mp_wait_lcore();
+
+ start_coreid = i;
+ /* Test only writer cases */
+ for (; i < core_cnt[n] * 2; i++)
+ rte_eal_remote_launch(test_rw_writer,
+ (void *)((uintptr_t)start_coreid),
+ slave_core_ids[i]);
+
+ rte_eal_mp_wait_lcore();
+
+ if (reader_faster) {
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ perf_results->read_only[n] = cycles_per_insertion;
+ printf("Reader only: cycles per lookup: %llu\n",
+ cycles_per_insertion);
+ }
+
+ else {
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gwrite_cycles) /
+ rte_atomic64_read(&gwrites);
+ perf_results->write_only[n] = cycles_per_insertion;
+ printf("Writer only: cycles per writes: %llu\n",
+ cycles_per_insertion);
+ }
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+ rte_atomic64_clear(&gwrites);
+ rte_atomic64_clear(&gwrite_cycles);
+
+ rte_hash_reset(tbl_rw_test_param.h);
+
+ for (i = 0; i < TOTAL_INSERT / 2; i++) {
+ ret = rte_hash_add_key_data(tbl_rw_test_param.h,
+ tbl_rw_test_param.keys + i,
+ (void *)((uintptr_t)i));
+ if (ret < 0) {
+ printf("Failed to insert half of keys\n");
+ goto err_free;
+ }
+ }
+
+ start_coreid = core_cnt[n];
+
+ if (reader_faster) {
+ for (i = core_cnt[n]; i < core_cnt[n] * 2; i++)
+ rte_eal_remote_launch(test_rw_writer,
+ (void *)((uintptr_t)start_coreid),
+ slave_core_ids[i]);
+ for (i = 0; i < core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rw_reader,
+ (void *)(uintptr_t)read_cnt,
+ slave_core_ids[i]);
+ } else {
+ for (i = 0; i < core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rw_reader,
+ (void *)(uintptr_t)read_cnt,
+ slave_core_ids[i]);
+ for (; i < core_cnt[n] * 2; i++)
+ rte_eal_remote_launch(test_rw_writer,
+ (void *)((uintptr_t)start_coreid),
+ slave_core_ids[i]);
+ }
+
+ rte_eal_mp_wait_lcore();
+
+ iter = 0;
+ memset(tbl_rw_test_param.found, 0, TOTAL_ENTRY);
+ while (rte_hash_iterate(tbl_rw_test_param.h,
+ &next_key, &next_data, &iter) >= 0) {
+ /* Search for the key in the list of keys added .*/
+ i = *(const uint32_t *)next_key;
+ tbl_rw_test_param.found[i]++;
+ }
+
+ for (i = 0; i < tbl_rw_test_param.rounded_tot_insert; i++) {
+ if (tbl_rw_test_param.keys[i] != RTE_RWTEST_FAIL) {
+ if (tbl_rw_test_param.found[i] > 1) {
+ duplicated_keys++;
+ break;
+ }
+ if (tbl_rw_test_param.found[i] == 0) {
+ lost_keys++;
+ printf("key %"PRIu64" is lost\n", i);
+ break;
+ }
+ }
+ }
+
+ if (duplicated_keys > 0) {
+ printf("%d key duplicated\n", duplicated_keys);
+ goto err_free;
+ }
+
+ if (lost_keys > 0) {
+ printf("%d key lost\n", lost_keys);
+ goto err_free;
+ }
+
+ printf("No key corrupted during read-write test.\n");
+
+ if (reader_faster) {
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ perf_results->read_write_r[n] = cycles_per_insertion;
+ printf("Read-write cycles per lookup: %llu\n",
+ cycles_per_insertion);
+ }
+
+ else {
+ unsigned long long int cycles_per_insertion =
+ rte_atomic64_read(&gwrite_cycles) /
+ rte_atomic64_read(&gwrites);
+ perf_results->read_write_w[n] = cycles_per_insertion;
+ printf("Read-write cycles per writes: %llu\n",
+ cycles_per_insertion);
+ }
+ }
+
+finish:
+ rte_free(tbl_rw_test_param.found);
+ rte_free(tbl_rw_test_param.keys);
+ rte_hash_free(tbl_rw_test_param.h);
+ return 0;
+
+err_free:
+ rte_free(tbl_rw_test_param.found);
+ rte_free(tbl_rw_test_param.keys);
+ rte_hash_free(tbl_rw_test_param.h);
+
+err:
+ return -1;
+}
+
+static int
+test_hash_rw_perf_main(void)
+{
+ /*
+ * Variables used to choose different tests.
+ * use_htm indicates if hardware transactional memory should be used.
+ * reader_faster indicates if the reader threads should finish earlier
+ * than writer threads. This is to timing either reader threads or
+ * writer threads for performance numbers.
+ */
+ int use_htm, reader_faster;
+ unsigned int i = 0, core_id = 0;
+
+ if (rte_lcore_count() < 3) {
+ printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
+ return TEST_SKIPPED;
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(core_id) {
+ slave_core_ids[i] = core_id;
+ i++;
+ }
+
+ setlocale(LC_NUMERIC, "");
+
+ if (rte_tm_supported()) {
+ printf("Hardware transactional memory (lock elision) "
+ "is supported\n");
+
+ printf("Test read-write with Hardware transactional memory\n");
+
+ use_htm = 1;
+
+ reader_faster = 1;
+ if (test_hash_readwrite_perf(&htm_results, use_htm,
+ reader_faster) < 0)
+ return -1;
+
+ reader_faster = 0;
+ if (test_hash_readwrite_perf(&htm_results, use_htm,
+ reader_faster) < 0)
+ return -1;
+ } else {
+ printf("Hardware transactional memory (lock elision) "
+ "is NOT supported\n");
+ }
+
+ printf("Test read-write without Hardware transactional memory\n");
+ use_htm = 0;
+
+ reader_faster = 1;
+ if (test_hash_readwrite_perf(&non_htm_results, use_htm,
+ reader_faster) < 0)
+ return -1;
+ reader_faster = 0;
+ if (test_hash_readwrite_perf(&non_htm_results, use_htm,
+ reader_faster) < 0)
+ return -1;
+
+ printf("================\n");
+ printf("Results summary:\n");
+ printf("================\n");
+
+ printf("single read: %u\n", htm_results.single_read);
+ printf("single write: %u\n", htm_results.single_write);
+ for (i = 0; i < NUM_TEST; i++) {
+ printf("+++ core_cnt: %u +++\n", core_cnt[i]);
+ printf("HTM:\n");
+ printf(" read only: %u\n", htm_results.read_only[i]);
+ printf(" write only: %u\n", htm_results.write_only[i]);
+ printf(" read-write read: %u\n", htm_results.read_write_r[i]);
+ printf(" read-write write: %u\n", htm_results.read_write_w[i]);
+
+ printf("non HTM:\n");
+ printf(" read only: %u\n", non_htm_results.read_only[i]);
+ printf(" write only: %u\n", non_htm_results.write_only[i]);
+ printf(" read-write read: %u\n",
+ non_htm_results.read_write_r[i]);
+ printf(" read-write write: %u\n",
+ non_htm_results.read_write_w[i]);
+ }
+
+ return 0;
+}
+
+static int
+test_hash_rw_func_main(void)
+{
+ /*
+ * Variables used to choose different tests.
+ * use_htm indicates if hardware transactional memory should be used.
+ * reader_faster indicates if the reader threads should finish earlier
+ * than writer threads. This is to timing either reader threads or
+ * writer threads for performance numbers.
+ */
+ unsigned int i = 0, core_id = 0;
+
+ if (rte_lcore_count() < 3) {
+ printf("Not enough cores for hash_readwrite_autotest, expecting at least 3\n");
+ return TEST_SKIPPED;
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(core_id) {
+ slave_core_ids[i] = core_id;
+ i++;
+ }
+
+ setlocale(LC_NUMERIC, "");
+
+ if (rte_tm_supported()) {
+ printf("Hardware transactional memory (lock elision) "
+ "is supported\n");
+
+ printf("Test read-write with Hardware transactional memory\n");
+
+ /* htm = 1, rw_lf = 0, ext = 0 */
+ if (test_hash_readwrite_functional(1, 0, 0) < 0)
+ return -1;
+
+ /* htm = 1, rw_lf = 1, ext = 0 */
+ if (test_hash_readwrite_functional(1, 1, 0) < 0)
+ return -1;
+
+ /* htm = 1, rw_lf = 0, ext = 1 */
+ if (test_hash_readwrite_functional(1, 0, 1) < 0)
+ return -1;
+
+ /* htm = 1, rw_lf = 1, ext = 1 */
+ if (test_hash_readwrite_functional(1, 1, 1) < 0)
+ return -1;
+ } else {
+ printf("Hardware transactional memory (lock elision) "
+ "is NOT supported\n");
+ }
+
+ printf("Test read-write without Hardware transactional memory\n");
+ /* htm = 0, rw_lf = 0, ext = 0 */
+ if (test_hash_readwrite_functional(0, 0, 0) < 0)
+ return -1;
+
+ /* htm = 0, rw_lf = 1, ext = 0 */
+ if (test_hash_readwrite_functional(0, 1, 0) < 0)
+ return -1;
+
+ /* htm = 0, rw_lf = 0, ext = 1 */
+ if (test_hash_readwrite_functional(0, 0, 1) < 0)
+ return -1;
+
+ /* htm = 0, rw_lf = 1, ext = 1 */
+ if (test_hash_readwrite_functional(0, 1, 1) < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_readwrite_func_autotest, test_hash_rw_func_main);
+REGISTER_TEST_COMMAND(hash_readwrite_perf_autotest, test_hash_rw_perf_main);
diff --git a/src/spdk/dpdk/app/test/test_hash_readwrite_lf_perf.c b/src/spdk/dpdk/app/test/test_hash_readwrite_lf_perf.c
new file mode 100644
index 000000000..889799865
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_hash_readwrite_lf_perf.c
@@ -0,0 +1,1435 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Arm Limited
+ */
+
+#include <inttypes.h>
+#include <locale.h>
+
+#include <rte_cycles.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_jhash.h>
+#include <rte_launch.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_spinlock.h>
+
+#include "test.h"
+
+#ifndef RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF
+#define RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF 0
+#endif
+
+#define BULK_LOOKUP_SIZE 32
+
+#define RUN_WITH_HTM_DISABLED 0
+
+#if (RUN_WITH_HTM_DISABLED)
+
+#define TOTAL_ENTRY (5*1024)
+#define TOTAL_INSERT (5*1024)
+
+#else
+
+#define TOTAL_ENTRY (4*1024*1024)
+#define TOTAL_INSERT (4*1024*1024)
+
+#endif
+
+#define READ_FAIL 1
+#define READ_PASS_NO_KEY_SHIFTS 2
+#define READ_PASS_SHIFT_PATH 4
+#define READ_PASS_NON_SHIFT_PATH 8
+#define BULK_LOOKUP 16
+#define READ_PASS_KEY_SHIFTS_EXTBKT 32
+
+#define WRITE_NO_KEY_SHIFT 0
+#define WRITE_KEY_SHIFT 1
+#define WRITE_EXT_BKT 2
+
+#define NUM_TEST 3
+static unsigned int rwc_core_cnt[NUM_TEST] = {1, 2, 4};
+
+struct rwc_perf {
+ uint32_t w_no_ks_r_hit[2][NUM_TEST];
+ uint32_t w_no_ks_r_miss[2][NUM_TEST];
+ uint32_t w_ks_r_hit_nsp[2][NUM_TEST];
+ uint32_t w_ks_r_hit_sp[2][NUM_TEST];
+ uint32_t w_ks_r_miss[2][NUM_TEST];
+ uint32_t multi_rw[NUM_TEST - 1][2][NUM_TEST];
+ uint32_t w_ks_r_hit_extbkt[2][NUM_TEST];
+};
+
+static struct rwc_perf rwc_lf_results, rwc_non_lf_results;
+
+static struct {
+ uint32_t *keys;
+ uint32_t *keys_no_ks;
+ uint32_t *keys_ks;
+ uint32_t *keys_absent;
+ uint32_t *keys_shift_path;
+ uint32_t *keys_non_shift_path;
+ uint32_t *keys_ext_bkt;
+ uint32_t *keys_ks_extbkt;
+ uint32_t count_keys_no_ks;
+ uint32_t count_keys_ks;
+ uint32_t count_keys_absent;
+ uint32_t count_keys_shift_path;
+ uint32_t count_keys_non_shift_path;
+ uint32_t count_keys_extbkt;
+ uint32_t count_keys_ks_extbkt;
+ uint32_t single_insert;
+ struct rte_hash *h;
+} tbl_rwc_test_param;
+
+static rte_atomic64_t gread_cycles;
+static rte_atomic64_t greads;
+
+static volatile uint8_t writer_done;
+
+static uint16_t enabled_core_ids[RTE_MAX_LCORE];
+
+static uint8_t *scanned_bkts;
+
+static inline uint16_t
+get_short_sig(const hash_sig_t hash)
+{
+ return hash >> 16;
+}
+
+static inline uint32_t
+get_prim_bucket_index(__rte_unused const struct rte_hash *h,
+ const hash_sig_t hash)
+{
+ uint32_t num_buckets;
+ uint32_t bucket_bitmask;
+ num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
+ bucket_bitmask = num_buckets - 1;
+ return hash & bucket_bitmask;
+}
+
+static inline uint32_t
+get_alt_bucket_index(__rte_unused const struct rte_hash *h,
+ uint32_t cur_bkt_idx, uint16_t sig)
+{
+ uint32_t num_buckets;
+ uint32_t bucket_bitmask;
+ num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
+ bucket_bitmask = num_buckets - 1;
+ return (cur_bkt_idx ^ sig) & bucket_bitmask;
+}
+
+
+static inline int
+get_enabled_cores_list(void)
+{
+ uint32_t i = 0;
+ uint16_t core_id;
+ uint32_t max_cores = rte_lcore_count();
+ RTE_LCORE_FOREACH(core_id) {
+ enabled_core_ids[i] = core_id;
+ i++;
+ }
+
+ if (i != max_cores) {
+ printf("Number of enabled cores in list is different from "
+ "number given by rte_lcore_count()\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+init_params(int rwc_lf, int use_jhash, int htm, int ext_bkt)
+{
+ struct rte_hash *handle;
+
+ struct rte_hash_parameters hash_params = {
+ .entries = TOTAL_ENTRY,
+ .key_len = sizeof(uint32_t),
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ };
+
+ if (use_jhash)
+ hash_params.hash_func = rte_jhash;
+ else
+ hash_params.hash_func = rte_hash_crc;
+
+ if (rwc_lf)
+ hash_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
+ RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+ else if (htm)
+ hash_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT |
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
+ RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+ else
+ hash_params.extra_flag =
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY |
+ RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
+
+ if (ext_bkt)
+ hash_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
+
+ hash_params.name = "tests";
+
+ handle = rte_hash_create(&hash_params);
+ if (handle == NULL) {
+ printf("hash creation failed");
+ return -1;
+ }
+
+ tbl_rwc_test_param.h = handle;
+ return 0;
+}
+
+static inline int
+check_bucket(uint32_t bkt_idx, uint32_t key)
+{
+ uint32_t iter;
+ uint32_t prev_iter;
+ uint32_t diff;
+ uint32_t count = 0;
+ const void *next_key;
+ void *next_data;
+
+ /* Temporary bucket to hold the keys */
+ uint32_t keys_in_bkt[8];
+
+ iter = bkt_idx * 8;
+ prev_iter = iter;
+ while (rte_hash_iterate(tbl_rwc_test_param.h,
+ &next_key, &next_data, &iter) >= 0) {
+
+ /* Check for duplicate entries */
+ if (*(const uint32_t *)next_key == key)
+ return 1;
+
+ /* Identify if there is any free entry in the bucket */
+ diff = iter - prev_iter;
+ if (diff > 1)
+ break;
+
+ prev_iter = iter;
+ keys_in_bkt[count] = *(const uint32_t *)next_key;
+ count++;
+
+ /* All entries in the bucket are occupied */
+ if (count == 8) {
+
+ /*
+ * Check if bucket was not scanned before, to avoid
+ * duplicate keys.
+ */
+ if (scanned_bkts[bkt_idx] == 0) {
+ /*
+ * Since this bucket (pointed to by bkt_idx) is
+ * full, it is likely that key(s) in this
+ * bucket will be on the shift path, when
+ * collision occurs. Thus, add it to
+ * keys_shift_path.
+ */
+ memcpy(tbl_rwc_test_param.keys_shift_path +
+ tbl_rwc_test_param.count_keys_shift_path
+ , keys_in_bkt, 32);
+ tbl_rwc_test_param.count_keys_shift_path += 8;
+ scanned_bkts[bkt_idx] = 1;
+ }
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+generate_keys(void)
+{
+ uint32_t *keys = NULL;
+ uint32_t *keys_no_ks = NULL;
+ uint32_t *keys_ks = NULL;
+ uint32_t *keys_absent = NULL;
+ uint32_t *keys_non_shift_path = NULL;
+ uint32_t *keys_ext_bkt = NULL;
+ uint32_t *keys_ks_extbkt = NULL;
+ uint32_t *found = NULL;
+ uint32_t count_keys_no_ks = 0;
+ uint32_t count_keys_ks = 0;
+ uint32_t count_keys_extbkt = 0;
+ uint32_t i;
+
+ if (init_params(0, 0, 0, 0) != 0)
+ return -1;
+
+ /*
+ * keys will consist of a) keys whose addition to the hash table
+ * will result in shifting of the existing keys to their alternate
+ * locations b) keys whose addition to the hash table will not result
+ * in shifting of the existing keys.
+ */
+ keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * keys_no_ks (no key-shifts): Subset of 'keys' - consists of keys that
+ * will NOT result in shifting of the existing keys to their alternate
+ * locations. Roughly around 900K keys.
+ */
+ keys_no_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys_no_ks == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * keys_ks (key-shifts): Subset of 'keys' - consists of keys that will
+ * result in shifting of the existing keys to their alternate locations.
+ * Roughly around 146K keys. There might be repeating keys. More code is
+ * required to filter out these keys which will complicate the test case
+ */
+ keys_ks = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys_ks == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /* Used to identify keys not inserted in the hash table */
+ found = rte_zmalloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (found == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * This consist of keys not inserted to the hash table.
+ * Used to test perf of lookup on keys that do not exist in the table.
+ */
+ keys_absent = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys_absent == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * This consist of keys which are likely to be on the shift
+ * path (i.e. being moved to alternate location), when collision occurs
+ * on addition of a key to an already full primary bucket.
+ * Used to test perf of lookup on keys that are on the shift path.
+ */
+ tbl_rwc_test_param.keys_shift_path = rte_malloc(NULL, sizeof(uint32_t) *
+ TOTAL_INSERT, 0);
+ if (tbl_rwc_test_param.keys_shift_path == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * This consist of keys which are never on the shift
+ * path (i.e. being moved to alternate location), when collision occurs
+ * on addition of a key to an already full primary bucket.
+ * Used to test perf of lookup on keys that are not on the shift path.
+ */
+ keys_non_shift_path = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT,
+ 0);
+ if (keys_non_shift_path == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * This consist of keys which will be stored in extended buckets
+ */
+ keys_ext_bkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys_ext_bkt == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ /*
+ * This consist of keys which when deleted causes shifting of keys
+ * in extended buckets to respective secondary buckets
+ */
+ keys_ks_extbkt = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_INSERT, 0);
+ if (keys_ks_extbkt == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ hash_sig_t sig;
+ uint32_t prim_bucket_idx;
+ uint32_t sec_bucket_idx;
+ uint16_t short_sig;
+ uint32_t num_buckets;
+ num_buckets = rte_align32pow2(TOTAL_ENTRY) / 8;
+ int ret;
+
+ /*
+ * Used to mark bkts in which at least one key was shifted to its
+ * alternate location
+ */
+ scanned_bkts = rte_malloc(NULL, sizeof(uint8_t) * num_buckets, 0);
+ if (scanned_bkts == NULL) {
+ printf("RTE_MALLOC failed\n");
+ goto err;
+ }
+
+ tbl_rwc_test_param.keys = keys;
+ tbl_rwc_test_param.keys_no_ks = keys_no_ks;
+ tbl_rwc_test_param.keys_ks = keys_ks;
+ tbl_rwc_test_param.keys_absent = keys_absent;
+ tbl_rwc_test_param.keys_non_shift_path = keys_non_shift_path;
+ tbl_rwc_test_param.keys_ext_bkt = keys_ext_bkt;
+ tbl_rwc_test_param.keys_ks_extbkt = keys_ks_extbkt;
+ /* Generate keys by adding previous two keys, neglect overflow */
+ printf("Generating keys...\n");
+ keys[0] = 0;
+ keys[1] = 1;
+ for (i = 2; i < TOTAL_INSERT; i++)
+ keys[i] = keys[i-1] + keys[i-2];
+
+ /* Segregate keys into keys_no_ks and keys_ks */
+ for (i = 0; i < TOTAL_INSERT; i++) {
+ /* Check if primary bucket has space.*/
+ sig = rte_hash_hash(tbl_rwc_test_param.h,
+ tbl_rwc_test_param.keys+i);
+ prim_bucket_idx = get_prim_bucket_index(tbl_rwc_test_param.h,
+ sig);
+ ret = check_bucket(prim_bucket_idx, keys[i]);
+ if (ret < 0) {
+ /*
+ * Primary bucket is full, this key will result in
+ * shifting of the keys to their alternate locations.
+ */
+ keys_ks[count_keys_ks] = keys[i];
+ count_keys_ks++;
+ } else if (ret == 0) {
+ /*
+ * Primary bucket has space, this key will not result in
+ * shifting of the keys. Hence, add key to the table.
+ */
+ ret = rte_hash_add_key_data(tbl_rwc_test_param.h,
+ keys+i,
+ (void *)((uintptr_t)i));
+ if (ret < 0) {
+ printf("writer failed %"PRIu32"\n", i);
+ break;
+ }
+ keys_no_ks[count_keys_no_ks] = keys[i];
+ count_keys_no_ks++;
+ }
+ }
+
+ for (i = 0; i < count_keys_no_ks; i++) {
+ /*
+ * Identify keys in keys_no_ks with value less than
+ * 4M (HTM enabled) OR 5K (HTM disabled)
+ */
+ if (keys_no_ks[i] < TOTAL_INSERT)
+ found[keys_no_ks[i]]++;
+ }
+
+ for (i = 0; i < count_keys_ks; i++) {
+ /*
+ * Identify keys in keys_ks with value less than
+ * 4M (HTM enabled) OR 5K (HTM disabled)
+ */
+ if (keys_ks[i] < TOTAL_INSERT)
+ found[keys_ks[i]]++;
+ }
+
+ uint32_t count_keys_absent = 0;
+ for (i = 0; i < TOTAL_INSERT; i++) {
+ /*
+ * Identify missing keys between 0 and
+ * 4M (HTM enabled) OR 5K (HTM disabled)
+ */
+ if (found[i] == 0)
+ keys_absent[count_keys_absent++] = i;
+ }
+
+ /* Find keys that will not be on the shift path */
+ uint32_t iter;
+ const void *next_key;
+ void *next_data;
+ uint32_t count = 0;
+ for (i = 0; i < num_buckets; i++) {
+ /* Check bucket for no keys shifted to alternate locations */
+ if (scanned_bkts[i] == 0) {
+ iter = i * 8;
+ while (rte_hash_iterate(tbl_rwc_test_param.h,
+ &next_key, &next_data, &iter) >= 0) {
+
+ /* Check if key belongs to the current bucket */
+ if (i >= (iter-1)/8)
+ keys_non_shift_path[count++]
+ = *(const uint32_t *)next_key;
+ else
+ break;
+ }
+ }
+ }
+
+ tbl_rwc_test_param.count_keys_no_ks = count_keys_no_ks;
+ tbl_rwc_test_param.count_keys_ks = count_keys_ks;
+ tbl_rwc_test_param.count_keys_absent = count_keys_absent;
+ tbl_rwc_test_param.count_keys_non_shift_path = count;
+
+ memset(scanned_bkts, 0, num_buckets);
+ count = 0;
+ /* Find keys that will be in extended buckets */
+ for (i = 0; i < count_keys_ks; i++) {
+ ret = rte_hash_add_key(tbl_rwc_test_param.h, keys_ks + i);
+ if (ret < 0) {
+ /* Key will be added to ext bkt */
+ keys_ext_bkt[count_keys_extbkt++] = keys_ks[i];
+ /* Sec bkt to be added to keys_ks_extbkt */
+ sig = rte_hash_hash(tbl_rwc_test_param.h,
+ tbl_rwc_test_param.keys_ks + i);
+ prim_bucket_idx = get_prim_bucket_index(
+ tbl_rwc_test_param.h, sig);
+ short_sig = get_short_sig(sig);
+ sec_bucket_idx = get_alt_bucket_index(
+ tbl_rwc_test_param.h,
+ prim_bucket_idx, short_sig);
+ if (scanned_bkts[sec_bucket_idx] == 0)
+ scanned_bkts[sec_bucket_idx] = 1;
+ }
+ }
+
+ /* Find keys that will shift keys in ext bucket*/
+ for (i = 0; i < num_buckets; i++) {
+ if (scanned_bkts[i] == 1) {
+ iter = i * 8;
+ while (rte_hash_iterate(tbl_rwc_test_param.h,
+ &next_key, &next_data, &iter) >= 0) {
+ /* Check if key belongs to the current bucket */
+ if (i >= (iter-1)/8)
+ keys_ks_extbkt[count++]
+ = *(const uint32_t *)next_key;
+ else
+ break;
+ }
+ }
+ }
+
+ tbl_rwc_test_param.count_keys_ks_extbkt = count;
+ tbl_rwc_test_param.count_keys_extbkt = count_keys_extbkt;
+
+ printf("\nCount of keys NOT causing shifting of existing keys to "
+ "alternate location: %d\n", tbl_rwc_test_param.count_keys_no_ks);
+ printf("\nCount of keys causing shifting of existing keys to alternate "
+ "locations: %d\n\n", tbl_rwc_test_param.count_keys_ks);
+ printf("Count of absent keys that will never be added to the hash "
+ "table: %d\n\n", tbl_rwc_test_param.count_keys_absent);
+ printf("Count of keys likely to be on the shift path: %d\n\n",
+ tbl_rwc_test_param.count_keys_shift_path);
+ printf("Count of keys not likely to be on the shift path: %d\n\n",
+ tbl_rwc_test_param.count_keys_non_shift_path);
+ printf("Count of keys in extended buckets: %d\n\n",
+ tbl_rwc_test_param.count_keys_extbkt);
+ printf("Count of keys shifting keys in ext buckets: %d\n\n",
+ tbl_rwc_test_param.count_keys_ks_extbkt);
+
+ rte_free(found);
+ rte_free(scanned_bkts);
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_free(keys);
+ rte_free(keys_no_ks);
+ rte_free(keys_ks);
+ rte_free(keys_absent);
+ rte_free(found);
+ rte_free(tbl_rwc_test_param.keys_shift_path);
+ rte_free(keys_non_shift_path);
+ rte_free(keys_ext_bkt);
+ rte_free(keys_ks_extbkt);
+ rte_free(scanned_bkts);
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+static int
+test_rwc_reader(__rte_unused void *arg)
+{
+ uint32_t i, j;
+ int ret;
+ uint64_t begin, cycles;
+ uint32_t loop_cnt = 0;
+ uint8_t read_type = (uint8_t)((uintptr_t)arg);
+ uint32_t read_cnt;
+ uint32_t *keys;
+ uint32_t extra_keys;
+ int32_t pos[BULK_LOOKUP_SIZE];
+ void *temp_a[BULK_LOOKUP_SIZE];
+
+ if (read_type & READ_FAIL) {
+ keys = tbl_rwc_test_param.keys_absent;
+ read_cnt = tbl_rwc_test_param.count_keys_absent;
+ } else if (read_type & READ_PASS_NO_KEY_SHIFTS) {
+ keys = tbl_rwc_test_param.keys_no_ks;
+ read_cnt = tbl_rwc_test_param.count_keys_no_ks;
+ } else if (read_type & READ_PASS_SHIFT_PATH) {
+ keys = tbl_rwc_test_param.keys_shift_path;
+ read_cnt = tbl_rwc_test_param.count_keys_shift_path;
+ } else if (read_type & READ_PASS_KEY_SHIFTS_EXTBKT) {
+ keys = tbl_rwc_test_param.keys_ext_bkt;
+ read_cnt = tbl_rwc_test_param.count_keys_extbkt;
+ } else {
+ keys = tbl_rwc_test_param.keys_non_shift_path;
+ read_cnt = tbl_rwc_test_param.count_keys_non_shift_path;
+ }
+
+ extra_keys = read_cnt & (BULK_LOOKUP_SIZE - 1);
+
+ begin = rte_rdtsc_precise();
+ do {
+ if (read_type & BULK_LOOKUP) {
+ for (i = 0; i < (read_cnt - extra_keys);
+ i += BULK_LOOKUP_SIZE) {
+ /* Array of pointer to the list of keys */
+ for (j = 0; j < BULK_LOOKUP_SIZE; j++)
+ temp_a[j] = keys + i + j;
+ rte_hash_lookup_bulk(tbl_rwc_test_param.h,
+ (const void **)
+ ((uintptr_t)temp_a),
+ BULK_LOOKUP_SIZE, pos);
+ /* Validate lookup result */
+ for (j = 0; j < BULK_LOOKUP_SIZE; j++)
+ if ((read_type & READ_FAIL &&
+ pos[j] != -ENOENT) ||
+ (!(read_type & READ_FAIL) &&
+ pos[j] == -ENOENT)) {
+ printf("lookup failed!"
+ "%"PRIu32"\n",
+ keys[i + j]);
+ return -1;
+ }
+ }
+ for (j = 0; j < extra_keys; j++)
+ temp_a[j] = keys + i + j;
+
+ rte_hash_lookup_bulk(tbl_rwc_test_param.h,
+ (const void **)
+ ((uintptr_t)temp_a),
+ extra_keys, pos);
+ for (j = 0; j < extra_keys; j++)
+ if ((read_type & READ_FAIL &&
+ pos[j] != -ENOENT) ||
+ (!(read_type & READ_FAIL) &&
+ pos[j] == -ENOENT)) {
+ printf("lookup failed! %"PRIu32"\n",
+ keys[i + j]);
+ return -1;
+ }
+ } else {
+ for (i = 0; i < read_cnt; i++) {
+ ret = rte_hash_lookup
+ (tbl_rwc_test_param.h, keys + i);
+ if (((read_type & READ_FAIL) &&
+ (ret != -ENOENT)) ||
+ (!(read_type & READ_FAIL) &&
+ ret == -ENOENT)) {
+ printf("lookup failed! %"PRIu32"\n",
+ keys[i]);
+ return -1;
+ }
+ }
+ }
+ loop_cnt++;
+ } while (!writer_done);
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&gread_cycles, cycles);
+ rte_atomic64_add(&greads, read_cnt*loop_cnt);
+ return 0;
+}
+
+static int
+write_keys(uint8_t write_type)
+{
+ uint32_t i;
+ int ret;
+ uint32_t key_cnt = 0;
+ uint32_t *keys;
+ if (write_type == WRITE_KEY_SHIFT) {
+ key_cnt = tbl_rwc_test_param.count_keys_ks;
+ keys = tbl_rwc_test_param.keys_ks;
+ } else if (write_type == WRITE_NO_KEY_SHIFT) {
+ key_cnt = tbl_rwc_test_param.count_keys_no_ks;
+ keys = tbl_rwc_test_param.keys_no_ks;
+ } else if (write_type == WRITE_EXT_BKT) {
+ key_cnt = tbl_rwc_test_param.count_keys_extbkt;
+ keys = tbl_rwc_test_param.keys_ext_bkt;
+ }
+ for (i = 0; i < key_cnt; i++) {
+ ret = rte_hash_add_key(tbl_rwc_test_param.h, keys + i);
+ if ((write_type == WRITE_NO_KEY_SHIFT) && ret < 0) {
+ printf("writer failed %"PRIu32"\n", i);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+test_rwc_multi_writer(__rte_unused void *arg)
+{
+ uint32_t i, offset;
+ uint32_t pos_core = (uint32_t)((uintptr_t)arg);
+ offset = pos_core * tbl_rwc_test_param.single_insert;
+ for (i = offset; i < offset + tbl_rwc_test_param.single_insert; i++)
+ rte_hash_add_key(tbl_rwc_test_param.h,
+ tbl_rwc_test_param.keys_ks + i);
+ return 0;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys present in the table.
+ */
+static int
+test_hash_add_no_ks_lookup_hit(struct rwc_perf *rwc_perf_results, int rwc_lf,
+ int htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ uint8_t write_type = WRITE_NO_KEY_SHIFT;
+ uint8_t read_type = READ_PASS_NO_KEY_SHIFTS;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - no key-shifts, read - hit\n");
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+ if (write_keys(write_type) < 0)
+ goto err;
+ writer_done = 1;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_no_ks_r_hit[m][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys absent in the table while
+ * 'Main' thread adds with no key-shifts.
+ */
+static int
+test_hash_add_no_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf,
+ int htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ uint8_t write_type = WRITE_NO_KEY_SHIFT;
+ uint8_t read_type = READ_FAIL;
+ int ret;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - no key-shifts, Hash lookup - miss\n");
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ ret = write_keys(write_type);
+ writer_done = 1;
+
+ if (ret < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_no_ks_r_miss[m][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys present in the table and not likely to be on the
+ * shift path while 'Main' thread adds keys causing key-shifts.
+ */
+static int
+test_hash_add_ks_lookup_hit_non_sp(struct rwc_perf *rwc_perf_results,
+ int rwc_lf, int htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ int ret;
+ uint8_t write_type;
+ uint8_t read_type = READ_PASS_NON_SHIFT_PATH;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - key shift, Hash lookup - hit"
+ " (non-shift-path)\n");
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+ write_type = WRITE_NO_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ write_type = WRITE_KEY_SHIFT;
+ ret = write_keys(write_type);
+ writer_done = 1;
+
+ if (ret < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_ks_r_hit_nsp[m][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys present in the table and likely on the shift-path while
+ * 'Main' thread adds keys causing key-shifts.
+ */
+static int
+test_hash_add_ks_lookup_hit_sp(struct rwc_perf *rwc_perf_results, int rwc_lf,
+ int htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ int ret;
+ uint8_t write_type;
+ uint8_t read_type = READ_PASS_SHIFT_PATH;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - key shift, Hash lookup - hit (shift-path)"
+ "\n");
+
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+ write_type = WRITE_NO_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ write_type = WRITE_KEY_SHIFT;
+ ret = write_keys(write_type);
+ writer_done = 1;
+
+ if (ret < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_ks_r_hit_sp[m][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys absent in the table while
+ * 'Main' thread adds keys causing key-shifts.
+ */
+static int
+test_hash_add_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf, int
+ htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ int ret;
+ uint8_t write_type;
+ uint8_t read_type = READ_FAIL;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - key shift, Hash lookup - miss\n");
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+ write_type = WRITE_NO_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ write_type = WRITE_KEY_SHIFT;
+ ret = write_keys(write_type);
+ writer_done = 1;
+
+ if (ret < 0)
+ goto err;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_ks_r_miss[m][n] = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf for multi-writer:
+ * Reader(s) lookup keys present in the table and likely on the shift-path while
+ * Writers add keys causing key-shiftsi.
+ * Writers are running in parallel, on different data plane cores.
+ */
+static int
+test_hash_multi_add_lookup(struct rwc_perf *rwc_perf_results, int rwc_lf,
+ int htm, int ext_bkt)
+{
+ unsigned int n, m, k;
+ uint64_t i;
+ int use_jhash = 0;
+ uint8_t write_type;
+ uint8_t read_type = READ_PASS_SHIFT_PATH;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Multi-add-lookup\n");
+ uint8_t pos_core;
+ for (m = 1; m < NUM_TEST; m++) {
+ /* Calculate keys added by each writer */
+ tbl_rwc_test_param.single_insert =
+ tbl_rwc_test_param.count_keys_ks / rwc_core_cnt[m];
+ for (k = 0; k < 2; k++) {
+ if (k == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < (rwc_core_cnt[n] +
+ rwc_core_cnt[m] + 1))
+ goto finish;
+
+ printf("\nNumber of writers: %u",
+ rwc_core_cnt[m]);
+ printf("\nNumber of readers: %u\n",
+ rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ writer_done = 0;
+ write_type = WRITE_NO_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+
+ /* Launch reader(s) */
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ write_type = WRITE_KEY_SHIFT;
+ pos_core = 0;
+
+ /* Launch writers */
+ for (; i <= rwc_core_cnt[m]
+ + rwc_core_cnt[n]; i++) {
+ rte_eal_remote_launch
+ (test_rwc_multi_writer,
+ (void *)(uintptr_t)pos_core,
+ enabled_core_ids[i]);
+ pos_core++;
+ }
+
+ /* Wait for writers to complete */
+ for (i = rwc_core_cnt[n] + 1;
+ i <= rwc_core_cnt[m] + rwc_core_cnt[n];
+ i++)
+ rte_eal_wait_lcore(enabled_core_ids[i]);
+
+ writer_done = 1;
+
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles)
+ / rte_atomic64_read(&greads);
+ rwc_perf_results->multi_rw[m][k][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n",
+ cycles_per_lookup);
+ }
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+/*
+ * Test lookup perf:
+ * Reader(s) lookup keys present in the extendable bkt.
+ */
+static int
+test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf *rwc_perf_results,
+ int rwc_lf, int htm, int ext_bkt)
+{
+ unsigned int n, m;
+ uint64_t i;
+ int use_jhash = 0;
+ uint8_t write_type;
+ uint8_t read_type = READ_PASS_KEY_SHIFTS_EXTBKT;
+
+ rte_atomic64_init(&greads);
+ rte_atomic64_init(&gread_cycles);
+
+ if (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)
+ goto err;
+ printf("\nTest: Hash add - key-shifts, read - hit (ext_bkt)\n");
+ for (m = 0; m < 2; m++) {
+ if (m == 1) {
+ printf("\n** With bulk-lookup **\n");
+ read_type |= BULK_LOOKUP;
+ }
+ for (n = 0; n < NUM_TEST; n++) {
+ unsigned int tot_lcore = rte_lcore_count();
+ if (tot_lcore < rwc_core_cnt[n] + 1)
+ goto finish;
+
+ printf("\nNumber of readers: %u\n", rwc_core_cnt[n]);
+
+ rte_atomic64_clear(&greads);
+ rte_atomic64_clear(&gread_cycles);
+
+ rte_hash_reset(tbl_rwc_test_param.h);
+ write_type = WRITE_NO_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+ write_type = WRITE_KEY_SHIFT;
+ if (write_keys(write_type) < 0)
+ goto err;
+ writer_done = 0;
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ rte_eal_remote_launch(test_rwc_reader,
+ (void *)(uintptr_t)read_type,
+ enabled_core_ids[i]);
+ for (i = 0; i < tbl_rwc_test_param.count_keys_ks_extbkt;
+ i++) {
+ if (rte_hash_del_key(tbl_rwc_test_param.h,
+ tbl_rwc_test_param.keys_ks_extbkt + i)
+ < 0) {
+ printf("Delete Failed: %u\n",
+ tbl_rwc_test_param.keys_ks_extbkt[i]);
+ goto err;
+ }
+ }
+ writer_done = 1;
+
+ for (i = 1; i <= rwc_core_cnt[n]; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto err;
+
+ unsigned long long cycles_per_lookup =
+ rte_atomic64_read(&gread_cycles) /
+ rte_atomic64_read(&greads);
+ rwc_perf_results->w_ks_r_hit_extbkt[m][n]
+ = cycles_per_lookup;
+ printf("Cycles per lookup: %llu\n", cycles_per_lookup);
+ }
+ }
+
+finish:
+ rte_hash_free(tbl_rwc_test_param.h);
+ return 0;
+
+err:
+ rte_eal_mp_wait_lcore();
+ rte_hash_free(tbl_rwc_test_param.h);
+ return -1;
+}
+
+static int
+test_hash_readwrite_lf_perf_main(void)
+{
+ /*
+ * Variables used to choose different tests.
+ * rwc_lf indicates if read-write concurrency lock-free support is
+ * enabled.
+ * htm indicates if Hardware transactional memory support is enabled.
+ */
+ int rwc_lf = 0;
+ int htm;
+ int ext_bkt = 0;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for hash_readwrite_lf_perf_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ setlocale(LC_NUMERIC, "");
+
+ /* Reset tbl_rwc_test_param to discard values from previous run */
+ memset(&tbl_rwc_test_param, 0, sizeof(tbl_rwc_test_param));
+
+ if (rte_tm_supported())
+ htm = 1;
+ else
+ htm = 0;
+
+ if (generate_keys() != 0)
+ return -1;
+ if (get_enabled_cores_list() != 0)
+ return -1;
+
+ if (RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF) {
+ rwc_lf = 1;
+ ext_bkt = 1;
+ printf("Test lookup with read-write concurrency lock free support"
+ " enabled\n");
+ if (test_hash_add_no_ks_lookup_hit(&rwc_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_no_ks_lookup_miss(&rwc_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_non_sp(&rwc_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_sp(&rwc_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_miss(&rwc_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_multi_add_lookup(&rwc_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_extbkt(&rwc_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ }
+ printf("\nTest lookup with read-write concurrency lock free support"
+ " disabled\n");
+ rwc_lf = 0;
+ if (!htm) {
+ printf("With HTM Disabled\n");
+ if (!RUN_WITH_HTM_DISABLED) {
+ printf("Enable RUN_WITH_HTM_DISABLED to test with"
+ " lock-free disabled");
+ goto results;
+ }
+ } else
+ printf("With HTM Enabled\n");
+ if (test_hash_add_no_ks_lookup_hit(&rwc_non_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_no_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_non_sp(&rwc_non_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_sp(&rwc_non_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_miss(&rwc_non_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_multi_add_lookup(&rwc_non_lf_results, rwc_lf, htm,
+ ext_bkt) < 0)
+ return -1;
+ if (test_hash_add_ks_lookup_hit_extbkt(&rwc_non_lf_results, rwc_lf,
+ htm, ext_bkt) < 0)
+ return -1;
+results:
+ printf("\n\t\t\t\t\t\t********** Results summary **********\n\n");
+ int i, j, k;
+ for (j = 0; j < 2; j++) {
+ if (j == 1)
+ printf("\n\t\t\t\t\t#######********** Bulk Lookup "
+ "**********#######\n\n");
+ printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t"
+ "\t\t\t\t_________________\n");
+ printf("Writers\t\tReaders\t\tLock-free\tHTM\t\tTest-case\t\t\t"
+ "\t\t\tCycles per lookup\n");
+ printf("_______\t\t_______\t\t_________\t___\t\t_________\t\t\t"
+ "\t\t\t_________________\n");
+ for (i = 0; i < NUM_TEST; i++) {
+ printf("%u\t\t%u\t\t", 1, rwc_core_cnt[i]);
+ printf("Enabled\t\t");
+ printf("N/A\t\t");
+ printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_lf_results.w_no_ks_r_hit[j][i]);
+ printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_lf_results.w_no_ks_r_miss[j][i]);
+ printf("Hash add - key-shifts, lookup - hit"
+ "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
+ rwc_lf_results.w_ks_r_hit_nsp[j][i]);
+ printf("Hash add - key-shifts, lookup - hit "
+ "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
+ rwc_lf_results.w_ks_r_hit_sp[j][i]);
+ printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_lf_results.w_ks_r_miss[j][i]);
+ printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
+ "%u\n\n\t\t\t\t",
+ rwc_lf_results.w_ks_r_hit_extbkt[j][i]);
+
+ printf("Disabled\t");
+ if (htm)
+ printf("Enabled\t\t");
+ else
+ printf("Disabled\t");
+ printf("Hash add - no key-shifts, lookup - hit\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_non_lf_results.w_no_ks_r_hit[j][i]);
+ printf("Hash add - no key-shifts, lookup - miss\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_non_lf_results.w_no_ks_r_miss[j][i]);
+ printf("Hash add - key-shifts, lookup - hit "
+ "(non-shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
+ rwc_non_lf_results.w_ks_r_hit_nsp[j][i]);
+ printf("Hash add - key-shifts, lookup - hit "
+ "(shift-path)\t\t%u\n\t\t\t\t\t\t\t\t",
+ rwc_non_lf_results.w_ks_r_hit_sp[j][i]);
+ printf("Hash add - key-shifts, Hash lookup miss\t\t\t\t"
+ "%u\n\t\t\t\t\t\t\t\t",
+ rwc_non_lf_results.w_ks_r_miss[j][i]);
+ printf("Hash add - key-shifts, Hash lookup hit (ext_bkt)\t\t"
+ "%u\n",
+ rwc_non_lf_results.w_ks_r_hit_extbkt[j][i]);
+
+ printf("_______\t\t_______\t\t_________\t___\t\t"
+ "_________\t\t\t\t\t\t_________________\n");
+ }
+
+ for (i = 1; i < NUM_TEST; i++) {
+ for (k = 0; k < NUM_TEST; k++) {
+ printf("%u", rwc_core_cnt[i]);
+ printf("\t\t%u\t\t", rwc_core_cnt[k]);
+ printf("Enabled\t\t");
+ printf("N/A\t\t");
+ printf("Multi-add-lookup\t\t\t\t\t\t%u\n\n\t\t"
+ "\t\t",
+ rwc_lf_results.multi_rw[i][j][k]);
+ printf("Disabled\t");
+ if (htm)
+ printf("Enabled\t\t");
+ else
+ printf("Disabled\t");
+ printf("Multi-add-lookup\t\t\t\t\t\t%u\n",
+ rwc_non_lf_results.multi_rw[i][j][k]);
+
+ printf("_______\t\t_______\t\t_________\t___"
+ "\t\t_________\t\t\t\t\t\t"
+ "_________________\n");
+ }
+ }
+ }
+ rte_free(tbl_rwc_test_param.keys);
+ rte_free(tbl_rwc_test_param.keys_no_ks);
+ rte_free(tbl_rwc_test_param.keys_ks);
+ rte_free(tbl_rwc_test_param.keys_absent);
+ rte_free(tbl_rwc_test_param.keys_shift_path);
+ rte_free(tbl_rwc_test_param.keys_non_shift_path);
+ rte_free(tbl_rwc_test_param.keys_ext_bkt);
+ rte_free(tbl_rwc_test_param.keys_ks_extbkt);
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(hash_readwrite_lf_perf_autotest,
+ test_hash_readwrite_lf_perf_main);
diff --git a/src/spdk/dpdk/app/test/test_interrupts.c b/src/spdk/dpdk/app/test/test_interrupts.c
new file mode 100644
index 000000000..233b14a70
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_interrupts.c
@@ -0,0 +1,562 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_interrupts.h>
+
+#include "test.h"
+
+#define TEST_INTERRUPT_CHECK_INTERVAL 100 /* ms */
+
+/* predefined interrupt handle types */
+enum test_interrupt_handle_type {
+ TEST_INTERRUPT_HANDLE_INVALID,
+ TEST_INTERRUPT_HANDLE_VALID,
+ TEST_INTERRUPT_HANDLE_VALID_UIO,
+ TEST_INTERRUPT_HANDLE_VALID_ALARM,
+ TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT,
+ TEST_INTERRUPT_HANDLE_CASE1,
+ TEST_INTERRUPT_HANDLE_MAX
+};
+
+/* flag of if callback is called */
+static volatile int flag;
+static struct rte_intr_handle intr_handles[TEST_INTERRUPT_HANDLE_MAX];
+static enum test_interrupt_handle_type test_intr_type =
+ TEST_INTERRUPT_HANDLE_MAX;
+
+#ifdef RTE_EXEC_ENV_LINUX
+union intr_pipefds{
+ struct {
+ int pipefd[2];
+ };
+ struct {
+ int readfd;
+ int writefd;
+ };
+};
+
+static union intr_pipefds pfds;
+
+/**
+ * Check if the interrupt handle is valid.
+ */
+static inline int
+test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
+{
+ if (!intr_handle || intr_handle->fd < 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Initialization for interrupt test.
+ */
+static int
+test_interrupt_init(void)
+{
+ if (pipe(pfds.pipefd) < 0)
+ return -1;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_INVALID].fd = -1;
+ intr_handles[TEST_INTERRUPT_HANDLE_INVALID].type =
+ RTE_INTR_HANDLE_UNKNOWN;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID].fd = pfds.readfd;
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID].type =
+ RTE_INTR_HANDLE_UNKNOWN;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].fd = pfds.readfd;
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO].type =
+ RTE_INTR_HANDLE_UIO;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].fd = pfds.readfd;
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM].type =
+ RTE_INTR_HANDLE_ALARM;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT].fd = pfds.readfd;
+ intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT].type =
+ RTE_INTR_HANDLE_DEV_EVENT;
+
+ intr_handles[TEST_INTERRUPT_HANDLE_CASE1].fd = pfds.writefd;
+ intr_handles[TEST_INTERRUPT_HANDLE_CASE1].type = RTE_INTR_HANDLE_UIO;
+
+ return 0;
+}
+
+/**
+ * Deinitialization for interrupt test.
+ */
+static int
+test_interrupt_deinit(void)
+{
+ close(pfds.pipefd[0]);
+ close(pfds.pipefd[1]);
+
+ return 0;
+}
+
+/**
+ * Write the pipe to simulate an interrupt.
+ */
+static int
+test_interrupt_trigger_interrupt(void)
+{
+ if (write(pfds.writefd, "1", 1) < 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Check if two interrupt handles are the same.
+ */
+static int
+test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
+ struct rte_intr_handle *intr_handle_r)
+{
+ if (!intr_handle_l || !intr_handle_r)
+ return -1;
+
+ if (intr_handle_l->fd != intr_handle_r->fd ||
+ intr_handle_l->type != intr_handle_r->type)
+ return -1;
+
+ return 0;
+}
+
+#else
+/* to be implemented for bsd later */
+static inline int
+test_interrupt_handle_sanity_check(struct rte_intr_handle *intr_handle)
+{
+ RTE_SET_USED(intr_handle);
+
+ return 0;
+}
+
+static int
+test_interrupt_init(void)
+{
+ return 0;
+}
+
+static int
+test_interrupt_deinit(void)
+{
+ return 0;
+}
+
+static int
+test_interrupt_trigger_interrupt(void)
+{
+ return 0;
+}
+
+static int
+test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l,
+ struct rte_intr_handle *intr_handle_r)
+{
+ (void)intr_handle_l;
+ (void)intr_handle_r;
+
+ return 0;
+}
+#endif /* RTE_EXEC_ENV_LINUX */
+
+/**
+ * Callback for the test interrupt.
+ */
+static void
+test_interrupt_callback(void *arg)
+{
+ struct rte_intr_handle *intr_handle = arg;
+ if (test_intr_type >= TEST_INTERRUPT_HANDLE_MAX) {
+ printf("invalid interrupt type\n");
+ flag = -1;
+ return;
+ }
+
+ if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
+ printf("null or invalid intr_handle for %s\n", __func__);
+ flag = -1;
+ return;
+ }
+
+ if (rte_intr_callback_unregister(intr_handle,
+ test_interrupt_callback, arg) >= 0) {
+ printf("%s: unexpectedly able to unregister itself\n",
+ __func__);
+ flag = -1;
+ return;
+ }
+
+ if (test_interrupt_handle_compare(intr_handle,
+ &(intr_handles[test_intr_type])) == 0)
+ flag = 1;
+}
+
+/**
+ * Callback for the test interrupt.
+ */
+static void
+test_interrupt_callback_1(void *arg)
+{
+ struct rte_intr_handle *intr_handle = arg;
+ if (test_interrupt_handle_sanity_check(intr_handle) < 0) {
+ printf("null or invalid intr_handle for %s\n", __func__);
+ flag = -1;
+ return;
+ }
+}
+
+/**
+ * Tests for rte_intr_enable().
+ */
+static int
+test_interrupt_enable(void)
+{
+ struct rte_intr_handle test_intr_handle;
+
+ /* check with null intr_handle */
+ if (rte_intr_enable(NULL) == 0) {
+ printf("unexpectedly enable null intr_handle successfully\n");
+ return -1;
+ }
+
+ /* check with invalid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
+ if (rte_intr_enable(&test_intr_handle) == 0) {
+ printf("unexpectedly enable invalid intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
+ if (rte_intr_enable(&test_intr_handle) == 0) {
+ printf("unexpectedly enable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with specific valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
+ if (rte_intr_enable(&test_intr_handle) == 0) {
+ printf("unexpectedly enable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with specific valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
+ if (rte_intr_enable(&test_intr_handle) == 0) {
+ printf("unexpectedly enable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with valid handler and its type */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
+ if (rte_intr_enable(&test_intr_handle) < 0) {
+ printf("fail to enable interrupt on a simulated handler\n");
+ return -1;
+ }
+
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
+ if (rte_intr_enable(&test_intr_handle) == 0) {
+ printf("unexpectedly enable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Tests for rte_intr_disable().
+ */
+static int
+test_interrupt_disable(void)
+{
+ struct rte_intr_handle test_intr_handle;
+
+ /* check with null intr_handle */
+ if (rte_intr_disable(NULL) == 0) {
+ printf("unexpectedly disable null intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with invalid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
+ if (rte_intr_disable(&test_intr_handle) == 0) {
+ printf("unexpectedly disable invalid intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
+ if (rte_intr_disable(&test_intr_handle) == 0) {
+ printf("unexpectedly disable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with specific valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
+ if (rte_intr_disable(&test_intr_handle) == 0) {
+ printf("unexpectedly disable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with specific valid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
+ if (rte_intr_disable(&test_intr_handle) == 0) {
+ printf("unexpectedly disable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ /* check with valid handler and its type */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_CASE1];
+ if (rte_intr_disable(&test_intr_handle) < 0) {
+ printf("fail to disable interrupt on a simulated handler\n");
+ return -1;
+ }
+
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
+ if (rte_intr_disable(&test_intr_handle) == 0) {
+ printf("unexpectedly disable a specific intr_handle "
+ "successfully\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check the full path of a specified type of interrupt simulated.
+ */
+static int
+test_interrupt_full_path_check(enum test_interrupt_handle_type intr_type)
+{
+ int count;
+ struct rte_intr_handle test_intr_handle;
+
+ flag = 0;
+ test_intr_handle = intr_handles[intr_type];
+ test_intr_type = intr_type;
+ if (rte_intr_callback_register(&test_intr_handle,
+ test_interrupt_callback, &test_intr_handle) < 0) {
+ printf("fail to register callback\n");
+ return -1;
+ }
+
+ if (test_interrupt_trigger_interrupt() < 0)
+ return -1;
+
+ /* check flag */
+ for (count = 0; flag == 0 && count < 3; count++)
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+ while ((count =
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback,
+ &test_intr_handle)) < 0) {
+ if (count != -EAGAIN)
+ return -1;
+ }
+
+ if (flag == 0) {
+ printf("callback has not been called\n");
+ return -1;
+ } else if (flag < 0) {
+ printf("it has internal error in callback\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Main function of testing interrupt.
+ */
+static int
+test_interrupt(void)
+{
+ int ret = -1;
+ struct rte_intr_handle test_intr_handle;
+
+ if (test_interrupt_init() < 0) {
+ printf("fail to initialize for testing interrupt\n");
+ return -1;
+ }
+
+ printf("Check unknown valid interrupt full path\n");
+ if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID) < 0) {
+ printf("failure occurred during checking unknown valid "
+ "interrupt full path\n");
+ goto out;
+ }
+
+ printf("Check valid UIO interrupt full path\n");
+ if (test_interrupt_full_path_check(TEST_INTERRUPT_HANDLE_VALID_UIO)
+ < 0) {
+ printf("failure occurred during checking valid UIO interrupt "
+ "full path\n");
+ goto out;
+ }
+
+ printf("Check valid device event interrupt full path\n");
+ if (test_interrupt_full_path_check(
+ TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT) < 0) {
+ printf("failure occurred during checking valid device event "
+ "interrupt full path\n");
+ goto out;
+ }
+
+ printf("Check valid alarm interrupt full path\n");
+ if (test_interrupt_full_path_check(
+ TEST_INTERRUPT_HANDLE_VALID_ALARM) < 0) {
+ printf("failure occurred during checking valid alarm "
+ "interrupt full path\n");
+ goto out;
+ }
+
+ printf("start register/unregister test\n");
+ /* check if it will fail to register cb with intr_handle = NULL */
+ if (rte_intr_callback_register(NULL, test_interrupt_callback,
+ NULL) == 0) {
+ printf("unexpectedly register successfully with null "
+ "intr_handle\n");
+ goto out;
+ }
+
+ /* check if it will fail to register cb with invalid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
+ if (rte_intr_callback_register(&test_intr_handle,
+ test_interrupt_callback, &test_intr_handle) == 0) {
+ printf("unexpectedly register successfully with invalid "
+ "intr_handle\n");
+ goto out;
+ }
+
+ /* check if it will fail to register without callback */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
+ if (rte_intr_callback_register(&test_intr_handle, NULL, &test_intr_handle) == 0) {
+ printf("unexpectedly register successfully with "
+ "null callback\n");
+ goto out;
+ }
+
+ /* check if it will fail to unregister cb with intr_handle = NULL */
+ if (rte_intr_callback_unregister(NULL,
+ test_interrupt_callback, NULL) > 0) {
+ printf("unexpectedly unregister successfully with "
+ "null intr_handle\n");
+ goto out;
+ }
+
+ /* check if it will fail to unregister cb with invalid intr_handle */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_INVALID];
+ if (rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, &test_intr_handle) > 0) {
+ printf("unexpectedly unregister successfully with "
+ "invalid intr_handle\n");
+ goto out;
+ }
+
+ /* check if it is ok to register the same intr_handle twice */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
+ if (rte_intr_callback_register(&test_intr_handle,
+ test_interrupt_callback, &test_intr_handle) < 0) {
+ printf("it fails to register test_interrupt_callback\n");
+ goto out;
+ }
+ if (rte_intr_callback_register(&test_intr_handle,
+ test_interrupt_callback_1, &test_intr_handle) < 0) {
+ printf("it fails to register test_interrupt_callback_1\n");
+ goto out;
+ }
+ /* check if it will fail to unregister with invalid parameter */
+ if (rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, (void *)0xff) != 0) {
+ printf("unexpectedly unregisters successfully with "
+ "invalid arg\n");
+ goto out;
+ }
+ if (rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, &test_intr_handle) <= 0) {
+ printf("it fails to unregister test_interrupt_callback\n");
+ goto out;
+ }
+ if (rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback_1, (void *)-1) <= 0) {
+ printf("it fails to unregister test_interrupt_callback_1 "
+ "for all\n");
+ goto out;
+ }
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+
+ printf("start interrupt enable/disable test\n");
+ /* check interrupt enable/disable functions */
+ if (test_interrupt_enable() < 0) {
+ printf("fail to check interrupt enabling\n");
+ goto out;
+ }
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+
+ if (test_interrupt_disable() < 0) {
+ printf("fail to check interrupt disabling\n");
+ goto out;
+ }
+ rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL);
+
+ ret = 0;
+
+out:
+ printf("Clearing for interrupt tests\n");
+ /* clear registered callbacks */
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID];
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, (void *)-1);
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback_1, (void *)-1);
+
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_UIO];
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, (void *)-1);
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback_1, (void *)-1);
+
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_ALARM];
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, (void *)-1);
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback_1, (void *)-1);
+
+ test_intr_handle = intr_handles[TEST_INTERRUPT_HANDLE_VALID_DEV_EVENT];
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback, (void *)-1);
+ rte_intr_callback_unregister(&test_intr_handle,
+ test_interrupt_callback_1, (void *)-1);
+
+ rte_delay_ms(2 * TEST_INTERRUPT_CHECK_INTERVAL);
+ /* deinit */
+ test_interrupt_deinit();
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(interrupt_autotest, test_interrupt);
diff --git a/src/spdk/dpdk/app/test/test_ipfrag.c b/src/spdk/dpdk/app/test/test_ipfrag.c
new file mode 100644
index 000000000..da8c212f9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ipfrag.c
@@ -0,0 +1,262 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Red Hat, Inc.
+ */
+
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_hexdump.h>
+#include <rte_ip.h>
+#include <rte_ip_frag.h>
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_random.h>
+
+#include "test.h"
+
+#define NUM_MBUFS 128
+#define BURST 32
+
+static struct rte_mempool *pkt_pool,
+ *direct_pool,
+ *indirect_pool;
+
+static int
+setup_buf_pool(void)
+{
+ pkt_pool = rte_pktmbuf_pool_create("FRAG_MBUF_POOL",
+ NUM_MBUFS, BURST, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ SOCKET_ID_ANY);
+ if (pkt_pool == NULL) {
+ printf("%s: Error creating pkt mempool\n", __func__);
+ goto bad_setup;
+ }
+
+ direct_pool = rte_pktmbuf_pool_create("FRAG_D_MBUF_POOL",
+ NUM_MBUFS, BURST, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ SOCKET_ID_ANY);
+ if (direct_pool == NULL) {
+ printf("%s: Error creating direct mempool\n", __func__);
+ goto bad_setup;
+ }
+
+ indirect_pool = rte_pktmbuf_pool_create("FRAG_I_MBUF_POOL",
+ NUM_MBUFS, BURST, 0,
+ 0, SOCKET_ID_ANY);
+ if (indirect_pool == NULL) {
+ printf("%s: Error creating indirect mempool\n", __func__);
+ goto bad_setup;
+ }
+
+ return TEST_SUCCESS;
+
+bad_setup:
+ rte_mempool_free(pkt_pool);
+ pkt_pool = NULL;
+
+ rte_mempool_free(direct_pool);
+ direct_pool = NULL;
+
+ return TEST_FAILED;
+}
+
+static int testsuite_setup(void)
+{
+ return setup_buf_pool();
+}
+
+static void testsuite_teardown(void)
+{
+ rte_mempool_free(pkt_pool);
+ rte_mempool_free(direct_pool);
+ rte_mempool_free(indirect_pool);
+
+ pkt_pool = NULL;
+ direct_pool = NULL;
+ indirect_pool = NULL;
+}
+
+static int ut_setup(void)
+{
+ return TEST_SUCCESS;
+}
+
+static void ut_teardown(void)
+{
+}
+
+static void
+v4_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, int df,
+ uint8_t ttl, uint8_t proto, uint16_t pktid)
+{
+ /* Create a packet, 2k bytes long */
+ b->data_off = 0;
+ char *data = rte_pktmbuf_mtod(b, char *);
+
+ memset(data, fill, sizeof(struct rte_ipv4_hdr) + s);
+
+ struct rte_ipv4_hdr *hdr = (struct rte_ipv4_hdr *)data;
+
+ hdr->version_ihl = 0x45; /* standard IP header... */
+ hdr->type_of_service = 0;
+ b->pkt_len = s + sizeof(struct rte_ipv4_hdr);
+ b->data_len = b->pkt_len;
+ hdr->total_length = rte_cpu_to_be_16(b->pkt_len);
+ hdr->packet_id = rte_cpu_to_be_16(pktid);
+ hdr->fragment_offset = 0;
+ if (df)
+ hdr->fragment_offset = rte_cpu_to_be_16(0x4000);
+
+ if (!ttl)
+ ttl = 64; /* default to 64 */
+
+ if (!proto)
+ proto = 1; /* icmp */
+
+ hdr->time_to_live = ttl;
+ hdr->next_proto_id = proto;
+ hdr->hdr_checksum = 0;
+ hdr->src_addr = rte_cpu_to_be_32(0x8080808);
+ hdr->dst_addr = rte_cpu_to_be_32(0x8080404);
+}
+
+static void
+v6_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, uint8_t ttl,
+ uint8_t proto, uint16_t pktid)
+{
+ /* Create a packet, 2k bytes long */
+ b->data_off = 0;
+ char *data = rte_pktmbuf_mtod(b, char *);
+
+ memset(data, fill, sizeof(struct rte_ipv6_hdr) + s);
+
+ struct rte_ipv6_hdr *hdr = (struct rte_ipv6_hdr *)data;
+ b->pkt_len = s + sizeof(struct rte_ipv6_hdr);
+ b->data_len = b->pkt_len;
+
+ /* basic v6 header */
+ hdr->vtc_flow = rte_cpu_to_be_32(0x60 << 24 | pktid);
+ hdr->payload_len = rte_cpu_to_be_16(b->pkt_len);
+ hdr->proto = proto;
+ hdr->hop_limits = ttl;
+
+ memset(hdr->src_addr, 0x08, sizeof(hdr->src_addr));
+ memset(hdr->dst_addr, 0x04, sizeof(hdr->src_addr));
+}
+
+static inline void
+test_free_fragments(struct rte_mbuf *mb[], uint32_t num)
+{
+ uint32_t i;
+ for (i = 0; i < num; i++)
+ rte_pktmbuf_free(mb[i]);
+}
+
+static int
+test_ip_frag(void)
+{
+ static const uint16_t RND_ID = UINT16_MAX;
+ int result = TEST_SUCCESS;
+ size_t i;
+
+ struct test_ip_frags {
+ int ipv;
+ size_t mtu_size;
+ size_t pkt_size;
+ int set_df;
+ uint8_t ttl;
+ uint8_t proto;
+ uint16_t pkt_id;
+ int expected_frags;
+ } tests[] = {
+ {4, 1280, 1400, 0, 64, IPPROTO_ICMP, RND_ID, 2},
+ {4, 1280, 1400, 0, 64, IPPROTO_ICMP, 0, 2},
+ {4, 600, 1400, 0, 64, IPPROTO_ICMP, RND_ID, 3},
+ {4, 4, 1400, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL},
+ {4, 600, 1400, 1, 64, IPPROTO_ICMP, RND_ID, -ENOTSUP},
+ {4, 600, 1400, 0, 0, IPPROTO_ICMP, RND_ID, 3},
+
+ {6, 1280, 1400, 0, 64, IPPROTO_ICMP, RND_ID, 2},
+ {6, 1300, 1400, 0, 64, IPPROTO_ICMP, RND_ID, 2},
+ {6, 4, 1400, 0, 64, IPPROTO_ICMP, RND_ID, -EINVAL},
+ {6, 1300, 1400, 0, 0, IPPROTO_ICMP, RND_ID, 2},
+ };
+
+ for (i = 0; i < RTE_DIM(tests); i++) {
+ int32_t len = 0;
+ uint16_t pktid = tests[i].pkt_id;
+ struct rte_mbuf *pkts_out[BURST];
+ struct rte_mbuf *b = rte_pktmbuf_alloc(pkt_pool);
+
+ RTE_TEST_ASSERT_NOT_EQUAL(b, NULL,
+ "Failed to allocate pkt.");
+
+ if (tests[i].pkt_id == RND_ID)
+ pktid = rte_rand_max(UINT16_MAX);
+
+ if (tests[i].ipv == 4) {
+ v4_allocate_packet_of(b, 0x41414141,
+ tests[i].pkt_size,
+ tests[i].set_df,
+ tests[i].ttl,
+ tests[i].proto,
+ pktid);
+ } else if (tests[i].ipv == 6) {
+ v6_allocate_packet_of(b, 0x41414141,
+ tests[i].pkt_size,
+ tests[i].ttl,
+ tests[i].proto,
+ pktid);
+ }
+
+ if (tests[i].ipv == 4)
+ len = rte_ipv4_fragment_packet(b, pkts_out, BURST,
+ tests[i].mtu_size,
+ direct_pool,
+ indirect_pool);
+ else if (tests[i].ipv == 6)
+ len = rte_ipv6_fragment_packet(b, pkts_out, BURST,
+ tests[i].mtu_size,
+ direct_pool,
+ indirect_pool);
+
+ rte_pktmbuf_free(b);
+
+ if (len > 0)
+ test_free_fragments(pkts_out, len);
+
+ printf("%zd: checking %d with %d\n", i, len,
+ tests[i].expected_frags);
+ RTE_TEST_ASSERT_EQUAL(len, tests[i].expected_frags,
+ "Failed case %zd.\n", i);
+
+ }
+
+ return result;
+}
+
+static struct unit_test_suite ipfrag_testsuite = {
+ .suite_name = "IP Frag Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ip_frag),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_ipfrag(void)
+{
+ rte_log_set_global_level(RTE_LOG_DEBUG);
+ rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
+
+ return unit_test_suite_runner(&ipfrag_testsuite);
+}
+
+REGISTER_TEST_COMMAND(ipfrag_autotest, test_ipfrag);
diff --git a/src/spdk/dpdk/app/test/test_ipsec.c b/src/spdk/dpdk/app/test/test_ipsec.c
new file mode 100644
index 000000000..79d00d7e0
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ipsec.c
@@ -0,0 +1,2539 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <time.h>
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_cycles.h>
+#include <rte_bus_vdev.h>
+#include <rte_ip.h>
+
+#include <rte_crypto.h>
+#include <rte_cryptodev.h>
+#include <rte_cryptodev_pmd.h>
+#include <rte_lcore.h>
+#include <rte_ipsec.h>
+#include <rte_random.h>
+#include <rte_esp.h>
+#include <rte_security_driver.h>
+
+#include "test.h"
+#include "test_cryptodev.h"
+
+#define VDEV_ARGS_SIZE 100
+#define MAX_NB_SESSIONS 200
+#define MAX_NB_SAS 2
+#define REPLAY_WIN_0 0
+#define REPLAY_WIN_32 32
+#define REPLAY_WIN_64 64
+#define REPLAY_WIN_128 128
+#define REPLAY_WIN_256 256
+#define DATA_64_BYTES 64
+#define DATA_80_BYTES 80
+#define DATA_100_BYTES 100
+#define ESN_ENABLED 1
+#define ESN_DISABLED 0
+#define INBOUND_SPI 7
+#define OUTBOUND_SPI 17
+#define BURST_SIZE 32
+#define REORDER_PKTS 1
+#define DEQUEUE_COUNT 1000
+
+struct user_params {
+ enum rte_crypto_sym_xform_type auth;
+ enum rte_crypto_sym_xform_type cipher;
+ enum rte_crypto_sym_xform_type aead;
+
+ char auth_algo[128];
+ char cipher_algo[128];
+ char aead_algo[128];
+};
+
+struct ipsec_testsuite_params {
+ struct rte_mempool *mbuf_pool;
+ struct rte_mempool *cop_mpool;
+ struct rte_cryptodev_config conf;
+ struct rte_cryptodev_qp_conf qp_conf;
+
+ uint8_t valid_dev;
+ uint8_t valid_dev_found;
+};
+
+struct ipsec_unitest_params {
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_crypto_sym_xform aead_xform;
+ struct rte_crypto_sym_xform *crypto_xforms;
+
+ struct rte_security_ipsec_xform ipsec_xform;
+
+ struct rte_ipsec_sa_prm sa_prm;
+ struct rte_ipsec_session ss[MAX_NB_SAS];
+
+ struct rte_crypto_op *cop[BURST_SIZE];
+
+ struct rte_mbuf *obuf[BURST_SIZE], *ibuf[BURST_SIZE],
+ *testbuf[BURST_SIZE];
+
+ uint16_t pkt_index;
+};
+
+struct ipsec_test_cfg {
+ uint32_t replay_win_sz;
+ uint32_t esn;
+ uint64_t flags;
+ size_t pkt_sz;
+ uint16_t num_pkts;
+ uint32_t reorder_pkts;
+};
+
+static const struct ipsec_test_cfg test_cfg[] = {
+ {REPLAY_WIN_0, ESN_DISABLED, 0, DATA_64_BYTES, 1, 0},
+ {REPLAY_WIN_0, ESN_DISABLED, 0, DATA_64_BYTES, BURST_SIZE, 0},
+ {REPLAY_WIN_0, ESN_DISABLED, 0, DATA_80_BYTES, BURST_SIZE,
+ REORDER_PKTS},
+ {REPLAY_WIN_32, ESN_ENABLED, 0, DATA_100_BYTES, 1, 0},
+ {REPLAY_WIN_32, ESN_ENABLED, 0, DATA_100_BYTES, BURST_SIZE,
+ REORDER_PKTS},
+ {REPLAY_WIN_64, ESN_ENABLED, 0, DATA_64_BYTES, 1, 0},
+ {REPLAY_WIN_128, ESN_ENABLED, RTE_IPSEC_SAFLAG_SQN_ATOM,
+ DATA_80_BYTES, 1, 0},
+ {REPLAY_WIN_256, ESN_DISABLED, 0, DATA_100_BYTES, 1, 0},
+};
+
+static const int num_cfg = RTE_DIM(test_cfg);
+static struct ipsec_testsuite_params testsuite_params = { NULL };
+static struct ipsec_unitest_params unittest_params;
+static struct user_params uparams;
+
+struct supported_cipher_algo {
+ const char *keyword;
+ enum rte_crypto_cipher_algorithm algo;
+ uint16_t iv_len;
+ uint16_t block_size;
+ uint16_t key_len;
+};
+
+struct supported_auth_algo {
+ const char *keyword;
+ enum rte_crypto_auth_algorithm algo;
+ uint16_t digest_len;
+ uint16_t key_len;
+ uint8_t key_not_req;
+};
+
+const struct supported_cipher_algo cipher_algos[] = {
+ {
+ .keyword = "null",
+ .algo = RTE_CRYPTO_CIPHER_NULL,
+ .iv_len = 0,
+ .block_size = 4,
+ .key_len = 0
+ },
+};
+
+const struct supported_auth_algo auth_algos[] = {
+ {
+ .keyword = "null",
+ .algo = RTE_CRYPTO_AUTH_NULL,
+ .digest_len = 0,
+ .key_len = 0,
+ .key_not_req = 1
+ },
+};
+
+static int
+dummy_sec_create(void *device, struct rte_security_session_conf *conf,
+ struct rte_security_session *sess, struct rte_mempool *mp)
+{
+ RTE_SET_USED(device);
+ RTE_SET_USED(conf);
+ RTE_SET_USED(mp);
+
+ sess->sess_private_data = NULL;
+ return 0;
+}
+
+static int
+dummy_sec_destroy(void *device, struct rte_security_session *sess)
+{
+ RTE_SET_USED(device);
+ RTE_SET_USED(sess);
+ return 0;
+}
+
+static const struct rte_security_ops dummy_sec_ops = {
+ .session_create = dummy_sec_create,
+ .session_destroy = dummy_sec_destroy,
+};
+
+static struct rte_security_ctx dummy_sec_ctx = {
+ .ops = &dummy_sec_ops,
+};
+
+static const struct supported_cipher_algo *
+find_match_cipher_algo(const char *cipher_keyword)
+{
+ size_t i;
+
+ for (i = 0; i < RTE_DIM(cipher_algos); i++) {
+ const struct supported_cipher_algo *algo =
+ &cipher_algos[i];
+
+ if (strcmp(cipher_keyword, algo->keyword) == 0)
+ return algo;
+ }
+
+ return NULL;
+}
+
+static const struct supported_auth_algo *
+find_match_auth_algo(const char *auth_keyword)
+{
+ size_t i;
+
+ for (i = 0; i < RTE_DIM(auth_algos); i++) {
+ const struct supported_auth_algo *algo =
+ &auth_algos[i];
+
+ if (strcmp(auth_keyword, algo->keyword) == 0)
+ return algo;
+ }
+
+ return NULL;
+}
+
+static void
+fill_crypto_xform(struct ipsec_unitest_params *ut_params,
+ const struct supported_auth_algo *auth_algo,
+ const struct supported_cipher_algo *cipher_algo)
+{
+ ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ ut_params->cipher_xform.cipher.algo = cipher_algo->algo;
+ ut_params->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ ut_params->auth_xform.auth.algo = auth_algo->algo;
+
+ if (ut_params->ipsec_xform.direction ==
+ RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ ut_params->cipher_xform.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ ut_params->cipher_xform.next = NULL;
+ ut_params->auth_xform.next = &ut_params->cipher_xform;
+ ut_params->crypto_xforms = &ut_params->auth_xform;
+ } else {
+ ut_params->cipher_xform.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ ut_params->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ ut_params->auth_xform.next = NULL;
+ ut_params->cipher_xform.next = &ut_params->auth_xform;
+ ut_params->crypto_xforms = &ut_params->cipher_xform;
+ }
+}
+
+static int
+check_cryptodev_capability(const struct ipsec_unitest_params *ut,
+ uint8_t dev_id)
+{
+ struct rte_cryptodev_sym_capability_idx cap_idx;
+ const struct rte_cryptodev_symmetric_capability *cap;
+ int rc = -1;
+
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ cap_idx.algo.auth = ut->auth_xform.auth.algo;
+ cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
+
+ if (cap != NULL) {
+ rc = rte_cryptodev_sym_capability_check_auth(cap,
+ ut->auth_xform.auth.key.length,
+ ut->auth_xform.auth.digest_length, 0);
+ if (rc == 0) {
+ cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ cap_idx.algo.cipher = ut->cipher_xform.cipher.algo;
+ cap = rte_cryptodev_sym_capability_get(
+ dev_id, &cap_idx);
+ if (cap != NULL)
+ rc = rte_cryptodev_sym_capability_check_cipher(
+ cap,
+ ut->cipher_xform.cipher.key.length,
+ ut->cipher_xform.cipher.iv.length);
+ }
+ }
+
+ return rc;
+}
+
+static int
+testsuite_setup(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ const struct supported_auth_algo *auth_algo;
+ const struct supported_cipher_algo *cipher_algo;
+ struct rte_cryptodev_info info;
+ uint32_t i, nb_devs, dev_id;
+ size_t sess_sz;
+ int rc;
+
+ memset(ts_params, 0, sizeof(*ts_params));
+ memset(ut_params, 0, sizeof(*ut_params));
+ memset(&uparams, 0, sizeof(struct user_params));
+
+ uparams.auth = RTE_CRYPTO_SYM_XFORM_AUTH;
+ uparams.cipher = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ uparams.aead = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED;
+ strcpy(uparams.auth_algo, "null");
+ strcpy(uparams.cipher_algo, "null");
+
+ auth_algo = find_match_auth_algo(uparams.auth_algo);
+ cipher_algo = find_match_cipher_algo(uparams.cipher_algo);
+ fill_crypto_xform(ut_params, auth_algo, cipher_algo);
+
+ nb_devs = rte_cryptodev_count();
+ if (nb_devs < 1) {
+ RTE_LOG(WARNING, USER1, "No crypto devices found?\n");
+ return TEST_SKIPPED;
+ }
+
+ /* Find first valid crypto device */
+ for (i = 0; i < nb_devs; i++) {
+ rc = check_cryptodev_capability(ut_params, i);
+ if (rc == 0) {
+ ts_params->valid_dev = i;
+ ts_params->valid_dev_found = 1;
+ break;
+ }
+ }
+
+ if (ts_params->valid_dev_found == 0)
+ return TEST_FAILED;
+
+ ts_params->mbuf_pool = rte_pktmbuf_pool_create(
+ "CRYPTO_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (ts_params->mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+
+ ts_params->cop_mpool = rte_crypto_op_pool_create(
+ "MBUF_CRYPTO_SYM_OP_POOL",
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ NUM_MBUFS, MBUF_CACHE_SIZE,
+ DEFAULT_NUM_XFORMS *
+ sizeof(struct rte_crypto_sym_xform) +
+ MAXIMUM_IV_LENGTH,
+ rte_socket_id());
+ if (ts_params->cop_mpool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ /* Set up all the qps on the first of the valid devices found */
+ dev_id = ts_params->valid_dev;
+
+ rte_cryptodev_info_get(dev_id, &info);
+
+ ts_params->conf.nb_queue_pairs = info.max_nb_queue_pairs;
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+ ts_params->conf.ff_disable = RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO;
+
+ sess_sz = rte_cryptodev_sym_get_private_session_size(dev_id);
+ sess_sz = RTE_MAX(sess_sz, sizeof(struct rte_security_session));
+
+ /*
+ * Create mempools for sessions
+ */
+ if (info.sym.max_nb_sessions != 0 &&
+ info.sym.max_nb_sessions < MAX_NB_SESSIONS) {
+ RTE_LOG(ERR, USER1, "Device does not support "
+ "at least %u sessions\n",
+ MAX_NB_SESSIONS);
+ return TEST_FAILED;
+ }
+
+ ts_params->qp_conf.mp_session_private = rte_mempool_create(
+ "test_priv_sess_mp",
+ MAX_NB_SESSIONS,
+ sess_sz,
+ 0, 0, NULL, NULL, NULL,
+ NULL, SOCKET_ID_ANY,
+ 0);
+
+ TEST_ASSERT_NOT_NULL(ts_params->qp_conf.mp_session_private,
+ "private session mempool allocation failed");
+
+ ts_params->qp_conf.mp_session =
+ rte_cryptodev_sym_session_pool_create("test_sess_mp",
+ MAX_NB_SESSIONS, 0, 0, 0, SOCKET_ID_ANY);
+
+ TEST_ASSERT_NOT_NULL(ts_params->qp_conf.mp_session,
+ "session mempool allocation failed");
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_configure(dev_id,
+ &ts_params->conf),
+ "Failed to configure cryptodev %u with %u qps",
+ dev_id, ts_params->conf.nb_queue_pairs);
+
+ ts_params->qp_conf.nb_descriptors = DEFAULT_NUM_OPS_INFLIGHT;
+
+ TEST_ASSERT_SUCCESS(rte_cryptodev_queue_pair_setup(
+ dev_id, 0, &ts_params->qp_conf,
+ rte_cryptodev_socket_id(dev_id)),
+ "Failed to setup queue pair %u on cryptodev %u",
+ 0, dev_id);
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+
+ if (ts_params->mbuf_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+ rte_mempool_free(ts_params->mbuf_pool);
+ ts_params->mbuf_pool = NULL;
+ }
+
+ if (ts_params->cop_mpool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_OP_POOL count %u\n",
+ rte_mempool_avail_count(ts_params->cop_mpool));
+ rte_mempool_free(ts_params->cop_mpool);
+ ts_params->cop_mpool = NULL;
+ }
+
+ /* Free session mempools */
+ if (ts_params->qp_conf.mp_session != NULL) {
+ rte_mempool_free(ts_params->qp_conf.mp_session);
+ ts_params->qp_conf.mp_session = NULL;
+ }
+
+ if (ts_params->qp_conf.mp_session_private != NULL) {
+ rte_mempool_free(ts_params->qp_conf.mp_session_private);
+ ts_params->qp_conf.mp_session_private = NULL;
+ }
+}
+
+static int
+ut_setup(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ /* Clear unit test parameters before running test */
+ memset(ut_params, 0, sizeof(*ut_params));
+
+ /* Reconfigure device to default parameters */
+ ts_params->conf.socket_id = SOCKET_ID_ANY;
+
+ /* Start the device */
+ TEST_ASSERT_SUCCESS(rte_cryptodev_start(ts_params->valid_dev),
+ "Failed to start cryptodev %u",
+ ts_params->valid_dev);
+
+ return TEST_SUCCESS;
+}
+
+static void
+ut_teardown(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ int i;
+
+ for (i = 0; i < BURST_SIZE; i++) {
+ /* free crypto operation structure */
+ if (ut_params->cop[i]) {
+ rte_crypto_op_free(ut_params->cop[i]);
+ ut_params->cop[i] = NULL;
+ }
+
+ /*
+ * free mbuf - both obuf and ibuf are usually the same,
+ * so check if they point at the same address is necessary,
+ * to avoid freeing the mbuf twice.
+ */
+ if (ut_params->obuf[i]) {
+ rte_pktmbuf_free(ut_params->obuf[i]);
+ if (ut_params->ibuf[i] == ut_params->obuf[i])
+ ut_params->ibuf[i] = NULL;
+ ut_params->obuf[i] = NULL;
+ }
+ if (ut_params->ibuf[i]) {
+ rte_pktmbuf_free(ut_params->ibuf[i]);
+ ut_params->ibuf[i] = NULL;
+ }
+
+ if (ut_params->testbuf[i]) {
+ rte_pktmbuf_free(ut_params->testbuf[i]);
+ ut_params->testbuf[i] = NULL;
+ }
+ }
+
+ if (ts_params->mbuf_pool != NULL)
+ RTE_LOG(DEBUG, USER1, "CRYPTO_MBUFPOOL count %u\n",
+ rte_mempool_avail_count(ts_params->mbuf_pool));
+
+ /* Stop the device */
+ rte_cryptodev_stop(ts_params->valid_dev);
+}
+
+#define IPSEC_MAX_PAD_SIZE UINT8_MAX
+
+static const uint8_t esp_pad_bytes[IPSEC_MAX_PAD_SIZE] = {
+ 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,
+};
+
+/* ***** data for tests ***** */
+
+const char null_plain_data[] =
+ "Network Security People Have A Strange Sense Of Humor unlike Other "
+ "People who have a normal sense of humour";
+
+const char null_encrypted_data[] =
+ "Network Security People Have A Strange Sense Of Humor unlike Other "
+ "People who have a normal sense of humour";
+
+struct rte_ipv4_hdr ipv4_outer = {
+ .version_ihl = IPVERSION << 4 |
+ sizeof(ipv4_outer) / RTE_IPV4_IHL_MULTIPLIER,
+ .time_to_live = IPDEFTTL,
+ .next_proto_id = IPPROTO_ESP,
+ .src_addr = RTE_IPV4(192, 168, 1, 100),
+ .dst_addr = RTE_IPV4(192, 168, 2, 100),
+};
+
+static struct rte_mbuf *
+setup_test_string(struct rte_mempool *mpool,
+ const char *string, size_t len, uint8_t blocksize)
+{
+ struct rte_mbuf *m = rte_pktmbuf_alloc(mpool);
+ size_t t_len = len - (blocksize ? (len % blocksize) : 0);
+
+ if (m) {
+ memset(m->buf_addr, 0, m->buf_len);
+ char *dst = rte_pktmbuf_append(m, t_len);
+
+ if (!dst) {
+ rte_pktmbuf_free(m);
+ return NULL;
+ }
+ if (string != NULL)
+ rte_memcpy(dst, string, t_len);
+ else
+ memset(dst, 0, t_len);
+ }
+
+ return m;
+}
+
+static struct rte_mbuf *
+setup_test_string_tunneled(struct rte_mempool *mpool, const char *string,
+ size_t len, uint32_t spi, uint32_t seq)
+{
+ struct rte_mbuf *m = rte_pktmbuf_alloc(mpool);
+ uint32_t hdrlen = sizeof(struct rte_ipv4_hdr) +
+ sizeof(struct rte_esp_hdr);
+ uint32_t taillen = sizeof(struct rte_esp_tail);
+ uint32_t t_len = len + hdrlen + taillen;
+ uint32_t padlen;
+
+ struct rte_esp_hdr esph = {
+ .spi = rte_cpu_to_be_32(spi),
+ .seq = rte_cpu_to_be_32(seq)
+ };
+
+ padlen = RTE_ALIGN(t_len, 4) - t_len;
+ t_len += padlen;
+
+ struct rte_esp_tail espt = {
+ .pad_len = padlen,
+ .next_proto = IPPROTO_IPIP,
+ };
+
+ if (m == NULL)
+ return NULL;
+
+ memset(m->buf_addr, 0, m->buf_len);
+ char *dst = rte_pktmbuf_append(m, t_len);
+
+ if (!dst) {
+ rte_pktmbuf_free(m);
+ return NULL;
+ }
+ /* copy outer IP and ESP header */
+ ipv4_outer.total_length = rte_cpu_to_be_16(t_len);
+ ipv4_outer.packet_id = rte_cpu_to_be_16(seq);
+ rte_memcpy(dst, &ipv4_outer, sizeof(ipv4_outer));
+ dst += sizeof(ipv4_outer);
+ m->l3_len = sizeof(ipv4_outer);
+ rte_memcpy(dst, &esph, sizeof(esph));
+ dst += sizeof(esph);
+
+ if (string != NULL) {
+ /* copy payload */
+ rte_memcpy(dst, string, len);
+ dst += len;
+ /* copy pad bytes */
+ rte_memcpy(dst, esp_pad_bytes, padlen);
+ dst += padlen;
+ /* copy ESP tail header */
+ rte_memcpy(dst, &espt, sizeof(espt));
+ } else
+ memset(dst, 0, t_len);
+
+ return m;
+}
+
+static int
+create_dummy_sec_session(struct ipsec_unitest_params *ut,
+ struct rte_cryptodev_qp_conf *qp, uint32_t j)
+{
+ static struct rte_security_session_conf conf;
+
+ ut->ss[j].security.ses = rte_security_session_create(&dummy_sec_ctx,
+ &conf, qp->mp_session_private);
+
+ if (ut->ss[j].security.ses == NULL)
+ return -ENOMEM;
+
+ ut->ss[j].security.ctx = &dummy_sec_ctx;
+ ut->ss[j].security.ol_flags = 0;
+ return 0;
+}
+
+static int
+create_crypto_session(struct ipsec_unitest_params *ut,
+ struct rte_cryptodev_qp_conf *qp, uint8_t dev_id, uint32_t j)
+{
+ int32_t rc;
+ struct rte_cryptodev_sym_session *s;
+
+ s = rte_cryptodev_sym_session_create(qp->mp_session);
+ if (s == NULL)
+ return -ENOMEM;
+
+ /* initiliaze SA crypto session for device */
+ rc = rte_cryptodev_sym_session_init(dev_id, s,
+ ut->crypto_xforms, qp->mp_session_private);
+ if (rc == 0) {
+ ut->ss[j].crypto.ses = s;
+ return 0;
+ } else {
+ /* failure, do cleanup */
+ rte_cryptodev_sym_session_clear(dev_id, s);
+ rte_cryptodev_sym_session_free(s);
+ return rc;
+ }
+}
+
+static int
+create_session(struct ipsec_unitest_params *ut,
+ struct rte_cryptodev_qp_conf *qp, uint8_t crypto_dev, uint32_t j)
+{
+ if (ut->ss[j].type == RTE_SECURITY_ACTION_TYPE_NONE)
+ return create_crypto_session(ut, qp, crypto_dev, j);
+ else
+ return create_dummy_sec_session(ut, qp, j);
+}
+
+static int
+fill_ipsec_param(uint32_t replay_win_sz, uint64_t flags)
+{
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ struct rte_ipsec_sa_prm *prm = &ut_params->sa_prm;
+ const struct supported_auth_algo *auth_algo;
+ const struct supported_cipher_algo *cipher_algo;
+
+ memset(prm, 0, sizeof(*prm));
+
+ prm->userdata = 1;
+ prm->flags = flags;
+
+ /* setup ipsec xform */
+ prm->ipsec_xform = ut_params->ipsec_xform;
+ prm->ipsec_xform.salt = (uint32_t)rte_rand();
+ prm->ipsec_xform.replay_win_sz = replay_win_sz;
+
+ /* setup tunnel related fields */
+ prm->tun.hdr_len = sizeof(ipv4_outer);
+ prm->tun.next_proto = IPPROTO_IPIP;
+ prm->tun.hdr = &ipv4_outer;
+
+ /* setup crypto section */
+ if (uparams.aead != 0) {
+ /* TODO: will need to fill out with other test cases */
+ } else {
+ if (uparams.auth == 0 && uparams.cipher == 0)
+ return TEST_FAILED;
+
+ auth_algo = find_match_auth_algo(uparams.auth_algo);
+ cipher_algo = find_match_cipher_algo(uparams.cipher_algo);
+
+ fill_crypto_xform(ut_params, auth_algo, cipher_algo);
+ }
+
+ prm->crypto_xform = ut_params->crypto_xforms;
+ return TEST_SUCCESS;
+}
+
+static int
+create_sa(enum rte_security_session_action_type action_type,
+ uint32_t replay_win_sz, uint64_t flags, uint32_t j)
+{
+ struct ipsec_testsuite_params *ts = &testsuite_params;
+ struct ipsec_unitest_params *ut = &unittest_params;
+ size_t sz;
+ int rc;
+
+ memset(&ut->ss[j], 0, sizeof(ut->ss[j]));
+
+ rc = fill_ipsec_param(replay_win_sz, flags);
+ if (rc != 0)
+ return TEST_FAILED;
+
+ /* create rte_ipsec_sa*/
+ sz = rte_ipsec_sa_size(&ut->sa_prm);
+ TEST_ASSERT(sz > 0, "rte_ipsec_sa_size() failed\n");
+
+ ut->ss[j].sa = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_NOT_NULL(ut->ss[j].sa,
+ "failed to allocate memory for rte_ipsec_sa\n");
+
+ ut->ss[j].type = action_type;
+ rc = create_session(ut, &ts->qp_conf, ts->valid_dev, j);
+ if (rc != 0)
+ return TEST_FAILED;
+
+ rc = rte_ipsec_sa_init(ut->ss[j].sa, &ut->sa_prm, sz);
+ rc = (rc > 0 && (uint32_t)rc <= sz) ? 0 : -EINVAL;
+ if (rc == 0)
+ rc = rte_ipsec_session_prepare(&ut->ss[j]);
+
+ return rc;
+}
+
+static int
+crypto_dequeue_burst(uint16_t num_pkts)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint32_t pkt_cnt, k;
+ int i;
+
+ for (i = 0, pkt_cnt = 0;
+ i < DEQUEUE_COUNT && pkt_cnt != num_pkts; i++) {
+ k = rte_cryptodev_dequeue_burst(ts_params->valid_dev, 0,
+ &ut_params->cop[pkt_cnt], num_pkts - pkt_cnt);
+ pkt_cnt += k;
+ rte_delay_us(1);
+ }
+
+ if (pkt_cnt != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_cryptodev_dequeue_burst fail\n");
+ return TEST_FAILED;
+ }
+ return TEST_SUCCESS;
+}
+
+static int
+crypto_ipsec(uint16_t num_pkts)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint32_t k, ng;
+ struct rte_ipsec_group grp[1];
+
+ /* call crypto prepare */
+ k = rte_ipsec_pkt_crypto_prepare(&ut_params->ss[0], ut_params->ibuf,
+ ut_params->cop, num_pkts);
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_prepare fail\n");
+ return TEST_FAILED;
+ }
+
+ k = rte_cryptodev_enqueue_burst(ts_params->valid_dev, 0,
+ ut_params->cop, num_pkts);
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_cryptodev_enqueue_burst fail\n");
+ return TEST_FAILED;
+ }
+
+ if (crypto_dequeue_burst(num_pkts) == TEST_FAILED)
+ return TEST_FAILED;
+
+ ng = rte_ipsec_pkt_crypto_group(
+ (const struct rte_crypto_op **)(uintptr_t)ut_params->cop,
+ ut_params->obuf, grp, num_pkts);
+ if (ng != 1 ||
+ grp[0].m[0] != ut_params->obuf[0] ||
+ grp[0].cnt != num_pkts ||
+ grp[0].id.ptr != &ut_params->ss[0]) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_group fail\n");
+ return TEST_FAILED;
+ }
+
+ /* call crypto process */
+ k = rte_ipsec_pkt_process(grp[0].id.ptr, grp[0].m, grp[0].cnt);
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_process fail\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+lksd_proto_ipsec(uint16_t num_pkts)
+{
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint32_t i, k, ng;
+ struct rte_ipsec_group grp[1];
+
+ /* call crypto prepare */
+ k = rte_ipsec_pkt_crypto_prepare(&ut_params->ss[0], ut_params->ibuf,
+ ut_params->cop, num_pkts);
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_prepare fail\n");
+ return TEST_FAILED;
+ }
+
+ /* check crypto ops */
+ for (i = 0; i != num_pkts; i++) {
+ TEST_ASSERT_EQUAL(ut_params->cop[i]->type,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ "%s: invalid crypto op type for %u-th packet\n",
+ __func__, i);
+ TEST_ASSERT_EQUAL(ut_params->cop[i]->status,
+ RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
+ "%s: invalid crypto op status for %u-th packet\n",
+ __func__, i);
+ TEST_ASSERT_EQUAL(ut_params->cop[i]->sess_type,
+ RTE_CRYPTO_OP_SECURITY_SESSION,
+ "%s: invalid crypto op sess_type for %u-th packet\n",
+ __func__, i);
+ TEST_ASSERT_EQUAL(ut_params->cop[i]->sym->m_src,
+ ut_params->ibuf[i],
+ "%s: invalid crypto op m_src for %u-th packet\n",
+ __func__, i);
+ }
+
+ /* update crypto ops, pretend all finished ok */
+ for (i = 0; i != num_pkts; i++)
+ ut_params->cop[i]->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+
+ ng = rte_ipsec_pkt_crypto_group(
+ (const struct rte_crypto_op **)(uintptr_t)ut_params->cop,
+ ut_params->obuf, grp, num_pkts);
+ if (ng != 1 ||
+ grp[0].m[0] != ut_params->obuf[0] ||
+ grp[0].cnt != num_pkts ||
+ grp[0].id.ptr != &ut_params->ss[0]) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_group fail\n");
+ return TEST_FAILED;
+ }
+
+ /* call crypto process */
+ k = rte_ipsec_pkt_process(grp[0].id.ptr, grp[0].m, grp[0].cnt);
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_process fail\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+dump_grp_pkt(uint32_t i, struct rte_ipsec_group *grp, uint32_t k)
+{
+ RTE_LOG(ERR, USER1,
+ "After rte_ipsec_pkt_process grp[%d].cnt=%d k=%d fail\n",
+ i, grp[i].cnt, k);
+ RTE_LOG(ERR, USER1,
+ "After rte_ipsec_pkt_process grp[%d].m=%p grp[%d].m[%d]=%p\n",
+ i, grp[i].m, i, k, grp[i].m[k]);
+
+ rte_pktmbuf_dump(stdout, grp[i].m[k], grp[i].m[k]->data_len);
+}
+
+static int
+crypto_ipsec_2sa(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ struct rte_ipsec_group grp[BURST_SIZE];
+ uint32_t k, ng, i, r;
+
+ for (i = 0; i < BURST_SIZE; i++) {
+ r = i % 2;
+ /* call crypto prepare */
+ k = rte_ipsec_pkt_crypto_prepare(&ut_params->ss[r],
+ ut_params->ibuf + i, ut_params->cop + i, 1);
+ if (k != 1) {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_crypto_prepare fail\n");
+ return TEST_FAILED;
+ }
+ k = rte_cryptodev_enqueue_burst(ts_params->valid_dev, 0,
+ ut_params->cop + i, 1);
+ if (k != 1) {
+ RTE_LOG(ERR, USER1,
+ "rte_cryptodev_enqueue_burst fail\n");
+ return TEST_FAILED;
+ }
+ }
+
+ if (crypto_dequeue_burst(BURST_SIZE) == TEST_FAILED)
+ return TEST_FAILED;
+
+ ng = rte_ipsec_pkt_crypto_group(
+ (const struct rte_crypto_op **)(uintptr_t)ut_params->cop,
+ ut_params->obuf, grp, BURST_SIZE);
+ if (ng != BURST_SIZE) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_group fail ng=%d\n",
+ ng);
+ return TEST_FAILED;
+ }
+
+ /* call crypto process */
+ for (i = 0; i < ng; i++) {
+ k = rte_ipsec_pkt_process(grp[i].id.ptr, grp[i].m, grp[i].cnt);
+ if (k != grp[i].cnt) {
+ dump_grp_pkt(i, grp, k);
+ return TEST_FAILED;
+ }
+ }
+ return TEST_SUCCESS;
+}
+
+#define PKT_4 4
+#define PKT_12 12
+#define PKT_21 21
+
+static uint32_t
+crypto_ipsec_4grp(uint32_t pkt_num)
+{
+ uint32_t sa_ind;
+
+ /* group packets in 4 different size groups groups, 2 per SA */
+ if (pkt_num < PKT_4)
+ sa_ind = 0;
+ else if (pkt_num < PKT_12)
+ sa_ind = 1;
+ else if (pkt_num < PKT_21)
+ sa_ind = 0;
+ else
+ sa_ind = 1;
+
+ return sa_ind;
+}
+
+static uint32_t
+crypto_ipsec_4grp_check_mbufs(uint32_t grp_ind, struct rte_ipsec_group *grp)
+{
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint32_t i, j;
+ uint32_t rc = 0;
+
+ if (grp_ind == 0) {
+ for (i = 0, j = 0; i < PKT_4; i++, j++)
+ if (grp[grp_ind].m[i] != ut_params->obuf[j]) {
+ rc = TEST_FAILED;
+ break;
+ }
+ } else if (grp_ind == 1) {
+ for (i = 0, j = PKT_4; i < (PKT_12 - PKT_4); i++, j++) {
+ if (grp[grp_ind].m[i] != ut_params->obuf[j]) {
+ rc = TEST_FAILED;
+ break;
+ }
+ }
+ } else if (grp_ind == 2) {
+ for (i = 0, j = PKT_12; i < (PKT_21 - PKT_12); i++, j++)
+ if (grp[grp_ind].m[i] != ut_params->obuf[j]) {
+ rc = TEST_FAILED;
+ break;
+ }
+ } else if (grp_ind == 3) {
+ for (i = 0, j = PKT_21; i < (BURST_SIZE - PKT_21); i++, j++)
+ if (grp[grp_ind].m[i] != ut_params->obuf[j]) {
+ rc = TEST_FAILED;
+ break;
+ }
+ } else
+ rc = TEST_FAILED;
+
+ return rc;
+}
+
+static uint32_t
+crypto_ipsec_4grp_check_cnt(uint32_t grp_ind, struct rte_ipsec_group *grp)
+{
+ uint32_t rc = 0;
+
+ if (grp_ind == 0) {
+ if (grp[grp_ind].cnt != PKT_4)
+ rc = TEST_FAILED;
+ } else if (grp_ind == 1) {
+ if (grp[grp_ind].cnt != PKT_12 - PKT_4)
+ rc = TEST_FAILED;
+ } else if (grp_ind == 2) {
+ if (grp[grp_ind].cnt != PKT_21 - PKT_12)
+ rc = TEST_FAILED;
+ } else if (grp_ind == 3) {
+ if (grp[grp_ind].cnt != BURST_SIZE - PKT_21)
+ rc = TEST_FAILED;
+ } else
+ rc = TEST_FAILED;
+
+ return rc;
+}
+
+static int
+crypto_ipsec_2sa_4grp(void)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ struct rte_ipsec_group grp[BURST_SIZE];
+ uint32_t k, ng, i, j;
+ uint32_t rc = 0;
+
+ for (i = 0; i < BURST_SIZE; i++) {
+ j = crypto_ipsec_4grp(i);
+
+ /* call crypto prepare */
+ k = rte_ipsec_pkt_crypto_prepare(&ut_params->ss[j],
+ ut_params->ibuf + i, ut_params->cop + i, 1);
+ if (k != 1) {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_crypto_prepare fail\n");
+ return TEST_FAILED;
+ }
+ k = rte_cryptodev_enqueue_burst(ts_params->valid_dev, 0,
+ ut_params->cop + i, 1);
+ if (k != 1) {
+ RTE_LOG(ERR, USER1,
+ "rte_cryptodev_enqueue_burst fail\n");
+ return TEST_FAILED;
+ }
+ }
+
+ if (crypto_dequeue_burst(BURST_SIZE) == TEST_FAILED)
+ return TEST_FAILED;
+
+ ng = rte_ipsec_pkt_crypto_group(
+ (const struct rte_crypto_op **)(uintptr_t)ut_params->cop,
+ ut_params->obuf, grp, BURST_SIZE);
+ if (ng != 4) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_group fail ng=%d\n",
+ ng);
+ return TEST_FAILED;
+ }
+
+ /* call crypto process */
+ for (i = 0; i < ng; i++) {
+ k = rte_ipsec_pkt_process(grp[i].id.ptr, grp[i].m, grp[i].cnt);
+ if (k != grp[i].cnt) {
+ dump_grp_pkt(i, grp, k);
+ return TEST_FAILED;
+ }
+ rc = crypto_ipsec_4grp_check_cnt(i, grp);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1,
+ "crypto_ipsec_4grp_check_cnt fail\n");
+ return TEST_FAILED;
+ }
+ rc = crypto_ipsec_4grp_check_mbufs(i, grp);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1,
+ "crypto_ipsec_4grp_check_mbufs fail\n");
+ return TEST_FAILED;
+ }
+ }
+ return TEST_SUCCESS;
+}
+
+static void
+test_ipsec_reorder_inb_pkt_burst(uint16_t num_pkts)
+{
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ struct rte_mbuf *ibuf_tmp[BURST_SIZE];
+ uint16_t j;
+
+ /* reorder packets and create gaps in sequence numbers */
+ static const uint32_t reorder[BURST_SIZE] = {
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ };
+
+ if (num_pkts != BURST_SIZE)
+ return;
+
+ for (j = 0; j != BURST_SIZE; j++)
+ ibuf_tmp[j] = ut_params->ibuf[reorder[j]];
+
+ memcpy(ut_params->ibuf, ibuf_tmp, sizeof(ut_params->ibuf));
+}
+
+static int
+test_ipsec_crypto_op_alloc(uint16_t num_pkts)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ int rc = 0;
+ uint16_t j;
+
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->cop[j] = rte_crypto_op_alloc(ts_params->cop_mpool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+ if (ut_params->cop[j] == NULL) {
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate symmetric crypto op\n");
+ rc = TEST_FAILED;
+ }
+ }
+
+ return rc;
+}
+
+static void
+test_ipsec_dump_buffers(struct ipsec_unitest_params *ut_params, int i)
+{
+ uint16_t j = ut_params->pkt_index;
+
+ printf("\ntest config: num %d\n", i);
+ printf(" replay_win_sz %u\n", test_cfg[i].replay_win_sz);
+ printf(" esn %u\n", test_cfg[i].esn);
+ printf(" flags 0x%" PRIx64 "\n", test_cfg[i].flags);
+ printf(" pkt_sz %zu\n", test_cfg[i].pkt_sz);
+ printf(" num_pkts %u\n\n", test_cfg[i].num_pkts);
+
+ if (ut_params->ibuf[j]) {
+ printf("ibuf[%u] data:\n", j);
+ rte_pktmbuf_dump(stdout, ut_params->ibuf[j],
+ ut_params->ibuf[j]->data_len);
+ }
+ if (ut_params->obuf[j]) {
+ printf("obuf[%u] data:\n", j);
+ rte_pktmbuf_dump(stdout, ut_params->obuf[j],
+ ut_params->obuf[j]->data_len);
+ }
+ if (ut_params->testbuf[j]) {
+ printf("testbuf[%u] data:\n", j);
+ rte_pktmbuf_dump(stdout, ut_params->testbuf[j],
+ ut_params->testbuf[j]->data_len);
+ }
+}
+
+static void
+destroy_dummy_sec_session(struct ipsec_unitest_params *ut,
+ uint32_t j)
+{
+ rte_security_session_destroy(&dummy_sec_ctx,
+ ut->ss[j].security.ses);
+ ut->ss[j].security.ctx = NULL;
+}
+
+static void
+destroy_crypto_session(struct ipsec_unitest_params *ut,
+ uint8_t crypto_dev, uint32_t j)
+{
+ rte_cryptodev_sym_session_clear(crypto_dev, ut->ss[j].crypto.ses);
+ rte_cryptodev_sym_session_free(ut->ss[j].crypto.ses);
+ memset(&ut->ss[j], 0, sizeof(ut->ss[j]));
+}
+
+static void
+destroy_session(struct ipsec_unitest_params *ut,
+ uint8_t crypto_dev, uint32_t j)
+{
+ if (ut->ss[j].type == RTE_SECURITY_ACTION_TYPE_NONE)
+ return destroy_crypto_session(ut, crypto_dev, j);
+ else
+ return destroy_dummy_sec_session(ut, j);
+}
+
+static void
+destroy_sa(uint32_t j)
+{
+ struct ipsec_unitest_params *ut = &unittest_params;
+ struct ipsec_testsuite_params *ts = &testsuite_params;
+
+ rte_ipsec_sa_fini(ut->ss[j].sa);
+ rte_free(ut->ss[j].sa);
+
+ destroy_session(ut, ts->valid_dev, j);
+}
+
+static int
+crypto_inb_burst_null_null_check(struct ipsec_unitest_params *ut_params, int i,
+ uint16_t num_pkts)
+{
+ uint16_t j;
+
+ for (j = 0; j < num_pkts && num_pkts <= BURST_SIZE; j++) {
+ ut_params->pkt_index = j;
+
+ /* compare the data buffers */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(null_plain_data,
+ rte_pktmbuf_mtod(ut_params->obuf[j], void *),
+ test_cfg[i].pkt_sz,
+ "input and output data does not match\n");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ ut_params->obuf[j]->pkt_len,
+ "data_len is not equal to pkt_len");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ test_cfg[i].pkt_sz,
+ "data_len is not equal to input data");
+ }
+
+ return 0;
+}
+
+static int
+test_ipsec_crypto_inb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ /* packet with sequence number 0 is invalid */
+ ut_params->ibuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI, j + 1);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+
+ if (rc == 0) {
+ if (test_cfg[i].reorder_pkts)
+ test_ipsec_reorder_inb_pkt_burst(num_pkts);
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+ }
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(num_pkts);
+ if (rc == 0)
+ rc = crypto_inb_burst_null_null_check(
+ ut_params, i, num_pkts);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_crypto_inb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_crypto_inb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+crypto_outb_burst_null_null_check(struct ipsec_unitest_params *ut_params,
+ uint16_t num_pkts)
+{
+ void *obuf_data;
+ void *testbuf_data;
+ uint16_t j;
+
+ for (j = 0; j < num_pkts && num_pkts <= BURST_SIZE; j++) {
+ ut_params->pkt_index = j;
+
+ testbuf_data = rte_pktmbuf_mtod(ut_params->testbuf[j], void *);
+ obuf_data = rte_pktmbuf_mtod(ut_params->obuf[j], void *);
+ /* compare the buffer data */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(testbuf_data, obuf_data,
+ ut_params->obuf[j]->pkt_len,
+ "test and output data does not match\n");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ ut_params->testbuf[j]->data_len,
+ "obuf data_len is not equal to testbuf data_len");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->pkt_len,
+ ut_params->testbuf[j]->pkt_len,
+ "obuf pkt_len is not equal to testbuf pkt_len");
+ }
+
+ return 0;
+}
+
+static int
+test_ipsec_crypto_outb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int32_t rc;
+
+ /* create rte_ipsec_sa*/
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate input mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->ibuf[j] = setup_test_string(ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ else {
+ /* Generate test mbuf data */
+ /* packet with sequence number 0 is invalid */
+ ut_params->testbuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz,
+ OUTBOUND_SPI, j + 1);
+ if (ut_params->testbuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == 0)
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(num_pkts);
+ if (rc == 0)
+ rc = crypto_outb_burst_null_null_check(ut_params,
+ num_pkts);
+ else
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_crypto_outb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = OUTBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_crypto_outb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+inline_inb_burst_null_null_check(struct ipsec_unitest_params *ut_params, int i,
+ uint16_t num_pkts)
+{
+ void *ibuf_data;
+ void *obuf_data;
+ uint16_t j;
+
+ for (j = 0; j < num_pkts && num_pkts <= BURST_SIZE; j++) {
+ ut_params->pkt_index = j;
+
+ /* compare the buffer data */
+ ibuf_data = rte_pktmbuf_mtod(ut_params->ibuf[j], void *);
+ obuf_data = rte_pktmbuf_mtod(ut_params->obuf[j], void *);
+
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(ibuf_data, obuf_data,
+ ut_params->ibuf[j]->data_len,
+ "input and output data does not match\n");
+ TEST_ASSERT_EQUAL(ut_params->ibuf[j]->data_len,
+ ut_params->obuf[j]->data_len,
+ "ibuf data_len is not equal to obuf data_len");
+ TEST_ASSERT_EQUAL(ut_params->ibuf[j]->pkt_len,
+ ut_params->obuf[j]->pkt_len,
+ "ibuf pkt_len is not equal to obuf pkt_len");
+ TEST_ASSERT_EQUAL(ut_params->ibuf[j]->data_len,
+ test_cfg[i].pkt_sz,
+ "data_len is not equal input data");
+ }
+ return 0;
+}
+
+static int
+test_ipsec_inline_crypto_inb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int32_t rc;
+ uint32_t n;
+
+ /* create rte_ipsec_sa*/
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate inbound mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->ibuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz,
+ INBOUND_SPI, j + 1);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ else {
+ /* Generate test mbuf data */
+ ut_params->obuf[j] = setup_test_string(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->obuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == 0) {
+ n = rte_ipsec_pkt_process(&ut_params->ss[0], ut_params->ibuf,
+ num_pkts);
+ if (n == num_pkts)
+ rc = inline_inb_burst_null_null_check(ut_params, i,
+ num_pkts);
+ else {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_process failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_inline_crypto_inb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_inline_crypto_inb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_inline_proto_inb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int32_t rc;
+ uint32_t n;
+
+ /* create rte_ipsec_sa*/
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate inbound mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->ibuf[j] = setup_test_string(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ else {
+ /* Generate test mbuf data */
+ ut_params->obuf[j] = setup_test_string(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->obuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == 0) {
+ n = rte_ipsec_pkt_process(&ut_params->ss[0], ut_params->ibuf,
+ num_pkts);
+ if (n == num_pkts)
+ rc = inline_inb_burst_null_null_check(ut_params, i,
+ num_pkts);
+ else {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_process failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_inline_proto_inb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_inline_proto_inb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+inline_outb_burst_null_null_check(struct ipsec_unitest_params *ut_params,
+ uint16_t num_pkts)
+{
+ void *obuf_data;
+ void *ibuf_data;
+ uint16_t j;
+
+ for (j = 0; j < num_pkts && num_pkts <= BURST_SIZE; j++) {
+ ut_params->pkt_index = j;
+
+ /* compare the buffer data */
+ ibuf_data = rte_pktmbuf_mtod(ut_params->ibuf[j], void *);
+ obuf_data = rte_pktmbuf_mtod(ut_params->obuf[j], void *);
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(ibuf_data, obuf_data,
+ ut_params->ibuf[j]->data_len,
+ "input and output data does not match\n");
+ TEST_ASSERT_EQUAL(ut_params->ibuf[j]->data_len,
+ ut_params->obuf[j]->data_len,
+ "ibuf data_len is not equal to obuf data_len");
+ TEST_ASSERT_EQUAL(ut_params->ibuf[j]->pkt_len,
+ ut_params->obuf[j]->pkt_len,
+ "ibuf pkt_len is not equal to obuf pkt_len");
+
+ /* check mbuf ol_flags */
+ TEST_ASSERT(ut_params->ibuf[j]->ol_flags & PKT_TX_SEC_OFFLOAD,
+ "ibuf PKT_TX_SEC_OFFLOAD is not set");
+ }
+ return 0;
+}
+
+static int
+test_ipsec_inline_crypto_outb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int32_t rc;
+ uint32_t n;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->ibuf[j] = setup_test_string(ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+
+ if (rc == 0) {
+ /* Generate test tunneled mbuf data for comparison */
+ ut_params->obuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz,
+ OUTBOUND_SPI, j + 1);
+ if (ut_params->obuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == 0) {
+ n = rte_ipsec_pkt_process(&ut_params->ss[0], ut_params->ibuf,
+ num_pkts);
+ if (n == num_pkts)
+ rc = inline_outb_burst_null_null_check(ut_params,
+ num_pkts);
+ else {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_process failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_inline_crypto_outb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = OUTBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_inline_crypto_outb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_inline_proto_outb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int32_t rc;
+ uint32_t n;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ ut_params->ibuf[j] = setup_test_string(ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+
+ if (rc == 0) {
+ /* Generate test tunneled mbuf data for comparison */
+ ut_params->obuf[j] = setup_test_string(
+ ts_params->mbuf_pool,
+ null_plain_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->obuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == 0) {
+ n = rte_ipsec_pkt_process(&ut_params->ss[0], ut_params->ibuf,
+ num_pkts);
+ if (n == num_pkts)
+ rc = inline_outb_burst_null_null_check(ut_params,
+ num_pkts);
+ else {
+ RTE_LOG(ERR, USER1,
+ "rte_ipsec_pkt_process failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_inline_proto_outb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = OUTBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_inline_proto_outb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_lksd_proto_inb_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j;
+ int rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ /* packet with sequence number 0 is invalid */
+ ut_params->ibuf[j] = setup_test_string(ts_params->mbuf_pool,
+ null_encrypted_data, test_cfg[i].pkt_sz, 0);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+
+ if (rc == 0) {
+ if (test_cfg[i].reorder_pkts)
+ test_ipsec_reorder_inb_pkt_burst(num_pkts);
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+ }
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = lksd_proto_ipsec(num_pkts);
+ if (rc == 0)
+ rc = crypto_inb_burst_null_null_check(ut_params, i,
+ num_pkts);
+ else {
+ RTE_LOG(ERR, USER1, "%s failed, cfg %d\n",
+ __func__, i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ return rc;
+}
+
+static int
+test_ipsec_lksd_proto_inb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_lksd_proto_inb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_lksd_proto_outb_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_lksd_proto_inb_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+replay_inb_null_null_check(struct ipsec_unitest_params *ut_params, int i,
+ int num_pkts)
+{
+ uint16_t j;
+
+ for (j = 0; j < num_pkts; j++) {
+ /* compare the buffer data */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(null_plain_data,
+ rte_pktmbuf_mtod(ut_params->obuf[j], void *),
+ test_cfg[i].pkt_sz,
+ "input and output data does not match\n");
+
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ ut_params->obuf[j]->pkt_len,
+ "data_len is not equal to pkt_len");
+ }
+
+ return 0;
+}
+
+static int
+test_ipsec_replay_inb_inside_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ int rc;
+
+ /* create rte_ipsec_sa*/
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate inbound mbuf data */
+ ut_params->ibuf[0] = setup_test_string_tunneled(ts_params->mbuf_pool,
+ null_encrypted_data, test_cfg[i].pkt_sz, INBOUND_SPI, 1);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(ut_params, i, 1);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if ((rc == 0) && (test_cfg[i].replay_win_sz != 0)) {
+ /* generate packet with seq number inside the replay window */
+ if (ut_params->ibuf[0]) {
+ rte_pktmbuf_free(ut_params->ibuf[0]);
+ ut_params->ibuf[0] = 0;
+ }
+
+ ut_params->ibuf[0] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI,
+ test_cfg[i].replay_win_sz);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(
+ ut_params, i, 1);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed\n");
+ rc = TEST_FAILED;
+ }
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_inside_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_replay_inb_inside_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_outside_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ int rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ ut_params->ibuf[0] = setup_test_string_tunneled(ts_params->mbuf_pool,
+ null_encrypted_data, test_cfg[i].pkt_sz, INBOUND_SPI,
+ test_cfg[i].replay_win_sz + 2);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(ut_params, i, 1);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if ((rc == 0) && (test_cfg[i].replay_win_sz != 0)) {
+ /* generate packet with seq number outside the replay window */
+ if (ut_params->ibuf[0]) {
+ rte_pktmbuf_free(ut_params->ibuf[0]);
+ ut_params->ibuf[0] = 0;
+ }
+ ut_params->ibuf[0] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI, 1);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0) {
+ if (test_cfg[i].esn == 0) {
+ RTE_LOG(ERR, USER1,
+ "packet is not outside the replay window, cfg %d pkt0_seq %u pkt1_seq %u\n",
+ i,
+ test_cfg[i].replay_win_sz + 2,
+ 1);
+ rc = TEST_FAILED;
+ }
+ } else {
+ RTE_LOG(ERR, USER1,
+ "packet is outside the replay window, cfg %d pkt0_seq %u pkt1_seq %u\n",
+ i, test_cfg[i].replay_win_sz + 2, 1);
+ rc = 0;
+ }
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_outside_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_replay_inb_outside_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_repeat_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ int rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ ut_params->ibuf[0] = setup_test_string_tunneled(ts_params->mbuf_pool,
+ null_encrypted_data, test_cfg[i].pkt_sz, INBOUND_SPI, 1);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(ut_params, i, 1);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if ((rc == 0) && (test_cfg[i].replay_win_sz != 0)) {
+ /*
+ * generate packet with repeat seq number in the replay
+ * window
+ */
+ if (ut_params->ibuf[0]) {
+ rte_pktmbuf_free(ut_params->ibuf[0]);
+ ut_params->ibuf[0] = 0;
+ }
+
+ ut_params->ibuf[0] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI, 1);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0) {
+ RTE_LOG(ERR, USER1,
+ "packet is not repeated in the replay window, cfg %d seq %u\n",
+ i, 1);
+ rc = TEST_FAILED;
+ } else {
+ RTE_LOG(ERR, USER1,
+ "packet is repeated in the replay window, cfg %d seq %u\n",
+ i, 1);
+ rc = 0;
+ }
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_repeat_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_replay_inb_repeat_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_inside_burst_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ int rc;
+ int j;
+
+ /* create rte_ipsec_sa*/
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* Generate inbound mbuf data */
+ ut_params->ibuf[0] = setup_test_string_tunneled(ts_params->mbuf_pool,
+ null_encrypted_data, test_cfg[i].pkt_sz, INBOUND_SPI, 1);
+ if (ut_params->ibuf[0] == NULL)
+ rc = TEST_FAILED;
+ else
+ rc = test_ipsec_crypto_op_alloc(1);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(1);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(ut_params, i, 1);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if ((rc == 0) && (test_cfg[i].replay_win_sz != 0)) {
+ /*
+ * generate packet(s) with seq number(s) inside the
+ * replay window
+ */
+ if (ut_params->ibuf[0]) {
+ rte_pktmbuf_free(ut_params->ibuf[0]);
+ ut_params->ibuf[0] = 0;
+ }
+
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ /* packet with sequence number 1 already processed */
+ ut_params->ibuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI, j + 2);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+
+ if (rc == 0) {
+ if (test_cfg[i].reorder_pkts)
+ test_ipsec_reorder_inb_pkt_burst(num_pkts);
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+ }
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec(num_pkts);
+ if (rc == 0)
+ rc = replay_inb_null_null_check(
+ ut_params, i, num_pkts);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed\n");
+ rc = TEST_FAILED;
+ }
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+
+ return rc;
+}
+
+static int
+test_ipsec_replay_inb_inside_burst_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_replay_inb_inside_burst_null_null(i);
+ }
+
+ return rc;
+}
+
+
+static int
+crypto_inb_burst_2sa_null_null_check(struct ipsec_unitest_params *ut_params,
+ int i)
+{
+ uint16_t j;
+
+ for (j = 0; j < BURST_SIZE; j++) {
+ ut_params->pkt_index = j;
+
+ /* compare the data buffers */
+ TEST_ASSERT_BUFFERS_ARE_EQUAL(null_plain_data,
+ rte_pktmbuf_mtod(ut_params->obuf[j], void *),
+ test_cfg[i].pkt_sz,
+ "input and output data does not match\n");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ ut_params->obuf[j]->pkt_len,
+ "data_len is not equal to pkt_len");
+ TEST_ASSERT_EQUAL(ut_params->obuf[j]->data_len,
+ test_cfg[i].pkt_sz,
+ "data_len is not equal to input data");
+ }
+
+ return 0;
+}
+
+static int
+test_ipsec_crypto_inb_burst_2sa_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j, r;
+ int rc = 0;
+
+ if (num_pkts != BURST_SIZE)
+ return rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa 0 failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* create second rte_ipsec_sa */
+ ut_params->ipsec_xform.spi = INBOUND_SPI + 1;
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 1);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa 1 failed, cfg %d\n", i);
+ destroy_sa(0);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ r = j % 2;
+ /* packet with sequence number 0 is invalid */
+ ut_params->ibuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI + r, j + 1);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+
+ if (rc == 0)
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec_2sa();
+ if (rc == 0)
+ rc = crypto_inb_burst_2sa_null_null_check(
+ ut_params, i);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ destroy_sa(1);
+ return rc;
+}
+
+static int
+test_ipsec_crypto_inb_burst_2sa_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_crypto_inb_burst_2sa_null_null(i);
+ }
+
+ return rc;
+}
+
+static int
+test_ipsec_crypto_inb_burst_2sa_4grp_null_null(int i)
+{
+ struct ipsec_testsuite_params *ts_params = &testsuite_params;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+ uint16_t num_pkts = test_cfg[i].num_pkts;
+ uint16_t j, k;
+ int rc = 0;
+
+ if (num_pkts != BURST_SIZE)
+ return rc;
+
+ /* create rte_ipsec_sa */
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa 0 failed, cfg %d\n", i);
+ return TEST_FAILED;
+ }
+
+ /* create second rte_ipsec_sa */
+ ut_params->ipsec_xform.spi = INBOUND_SPI + 1;
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE,
+ test_cfg[i].replay_win_sz, test_cfg[i].flags, 1);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "create_sa 1 failed, cfg %d\n", i);
+ destroy_sa(0);
+ return TEST_FAILED;
+ }
+
+ /* Generate test mbuf data */
+ for (j = 0; j < num_pkts && rc == 0; j++) {
+ k = crypto_ipsec_4grp(j);
+
+ /* packet with sequence number 0 is invalid */
+ ut_params->ibuf[j] = setup_test_string_tunneled(
+ ts_params->mbuf_pool, null_encrypted_data,
+ test_cfg[i].pkt_sz, INBOUND_SPI + k, j + 1);
+ if (ut_params->ibuf[j] == NULL)
+ rc = TEST_FAILED;
+ }
+
+ if (rc == 0)
+ rc = test_ipsec_crypto_op_alloc(num_pkts);
+
+ if (rc == 0) {
+ /* call ipsec library api */
+ rc = crypto_ipsec_2sa_4grp();
+ if (rc == 0)
+ rc = crypto_inb_burst_2sa_null_null_check(
+ ut_params, i);
+ else {
+ RTE_LOG(ERR, USER1, "crypto_ipsec failed, cfg %d\n",
+ i);
+ rc = TEST_FAILED;
+ }
+ }
+
+ if (rc == TEST_FAILED)
+ test_ipsec_dump_buffers(ut_params, i);
+
+ destroy_sa(0);
+ destroy_sa(1);
+ return rc;
+}
+
+static int
+test_ipsec_crypto_inb_burst_2sa_4grp_null_null_wrapper(void)
+{
+ int i;
+ int rc = 0;
+ struct ipsec_unitest_params *ut_params = &unittest_params;
+
+ ut_params->ipsec_xform.spi = INBOUND_SPI;
+ ut_params->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ ut_params->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ ut_params->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ ut_params->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+
+ for (i = 0; i < num_cfg && rc == 0; i++) {
+ ut_params->ipsec_xform.options.esn = test_cfg[i].esn;
+ rc = test_ipsec_crypto_inb_burst_2sa_4grp_null_null(i);
+ }
+
+ return rc;
+}
+
+static struct unit_test_suite ipsec_testsuite = {
+ .suite_name = "IPsec NULL Unit Test Suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_crypto_inb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_crypto_outb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_inline_crypto_inb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_inline_crypto_outb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_inline_proto_inb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_inline_proto_outb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_lksd_proto_inb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_lksd_proto_outb_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_replay_inb_inside_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_replay_inb_outside_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_replay_inb_repeat_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_replay_inb_inside_burst_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_crypto_inb_burst_2sa_null_null_wrapper),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_ipsec_crypto_inb_burst_2sa_4grp_null_null_wrapper),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_ipsec(void)
+{
+ return unit_test_suite_runner(&ipsec_testsuite);
+}
+
+REGISTER_TEST_COMMAND(ipsec_autotest, test_ipsec);
diff --git a/src/spdk/dpdk/app/test/test_ipsec_perf.c b/src/spdk/dpdk/app/test/test_ipsec_perf.c
new file mode 100644
index 000000000..92106bf37
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ipsec_perf.c
@@ -0,0 +1,614 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <rte_ip.h>
+#include <rte_malloc.h>
+#include <rte_ring.h>
+#include <rte_mbuf.h>
+#include <rte_cycles.h>
+#include <rte_ipsec.h>
+#include <rte_random.h>
+
+#include "test.h"
+#include "test_cryptodev.h"
+
+#define RING_SIZE 4096
+#define BURST_SIZE 64
+#define NUM_MBUF 4095
+#define DEFAULT_SPI 7
+
+struct ipsec_test_cfg {
+ uint32_t replay_win_sz;
+ uint32_t esn;
+ uint64_t flags;
+ enum rte_crypto_sym_xform_type type;
+};
+
+struct rte_mempool *mbuf_pool, *cop_pool;
+
+struct stats_counter {
+ uint64_t nb_prepare_call;
+ uint64_t nb_prepare_pkt;
+ uint64_t nb_process_call;
+ uint64_t nb_process_pkt;
+ uint64_t prepare_ticks_elapsed;
+ uint64_t process_ticks_elapsed;
+};
+
+struct ipsec_sa {
+ struct rte_ipsec_session ss[2];
+ struct rte_ipsec_sa_prm sa_prm;
+ struct rte_security_ipsec_xform ipsec_xform;
+ struct rte_crypto_sym_xform cipher_xform;
+ struct rte_crypto_sym_xform auth_xform;
+ struct rte_crypto_sym_xform aead_xform;
+ struct rte_crypto_sym_xform *crypto_xforms;
+ struct rte_crypto_op *cop[BURST_SIZE];
+ enum rte_crypto_sym_xform_type type;
+ struct stats_counter cnt;
+ uint32_t replay_win_sz;
+ uint32_t sa_flags;
+};
+
+static const struct ipsec_test_cfg test_cfg[] = {
+ {0, 0, 0, RTE_CRYPTO_SYM_XFORM_AEAD},
+ {0, 0, 0, RTE_CRYPTO_SYM_XFORM_CIPHER},
+ {128, 1, 0, RTE_CRYPTO_SYM_XFORM_AEAD},
+ {128, 1, 0, RTE_CRYPTO_SYM_XFORM_CIPHER},
+
+};
+
+static struct rte_ipv4_hdr ipv4_outer = {
+ .version_ihl = IPVERSION << 4 |
+ sizeof(ipv4_outer) / RTE_IPV4_IHL_MULTIPLIER,
+ .time_to_live = IPDEFTTL,
+ .next_proto_id = IPPROTO_ESP,
+ .src_addr = RTE_IPV4(192, 168, 1, 100),
+ .dst_addr = RTE_IPV4(192, 168, 2, 100),
+};
+
+static struct rte_ring *ring_inb_prepare;
+static struct rte_ring *ring_inb_process;
+static struct rte_ring *ring_outb_prepare;
+static struct rte_ring *ring_outb_process;
+
+struct supported_cipher_algo {
+ const char *keyword;
+ enum rte_crypto_cipher_algorithm algo;
+ uint16_t iv_len;
+ uint16_t block_size;
+ uint16_t key_len;
+};
+
+struct supported_auth_algo {
+ const char *keyword;
+ enum rte_crypto_auth_algorithm algo;
+ uint16_t digest_len;
+ uint16_t key_len;
+ uint8_t key_not_req;
+};
+
+struct supported_aead_algo {
+ const char *keyword;
+ enum rte_crypto_aead_algorithm algo;
+ uint16_t iv_len;
+ uint16_t block_size;
+ uint16_t digest_len;
+ uint16_t key_len;
+ uint8_t aad_len;
+};
+
+const struct supported_cipher_algo cipher_algo[] = {
+ {
+ .keyword = "aes-128-cbc",
+ .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .iv_len = 16,
+ .block_size = 16,
+ .key_len = 16
+ }
+};
+
+const struct supported_auth_algo auth_algo[] = {
+ {
+ .keyword = "sha1-hmac",
+ .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+ .digest_len = 12,
+ .key_len = 20
+ }
+};
+
+const struct supported_aead_algo aead_algo[] = {
+ {
+ .keyword = "aes-128-gcm",
+ .algo = RTE_CRYPTO_AEAD_AES_GCM,
+ .iv_len = 8,
+ .block_size = 4,
+ .key_len = 20,
+ .digest_len = 16,
+ .aad_len = 8,
+ }
+};
+
+static struct rte_mbuf *generate_mbuf_data(struct rte_mempool *mpool)
+{
+ struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mpool);
+
+ if (mbuf) {
+ mbuf->data_len = 64;
+ mbuf->pkt_len = 64;
+ }
+
+ return mbuf;
+}
+
+static int
+fill_ipsec_param(struct ipsec_sa *sa)
+{
+ struct rte_ipsec_sa_prm *prm = &sa->sa_prm;
+
+ memset(prm, 0, sizeof(*prm));
+
+ prm->flags = sa->sa_flags;
+
+ /* setup ipsec xform */
+ prm->ipsec_xform = sa->ipsec_xform;
+ prm->ipsec_xform.salt = (uint32_t)rte_rand();
+ prm->ipsec_xform.replay_win_sz = sa->replay_win_sz;
+
+ /* setup tunnel related fields */
+ prm->tun.hdr_len = sizeof(ipv4_outer);
+ prm->tun.next_proto = IPPROTO_IPIP;
+ prm->tun.hdr = &ipv4_outer;
+
+ if (sa->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
+ sa->aead_xform.type = sa->type;
+ sa->aead_xform.aead.algo = aead_algo->algo;
+ sa->aead_xform.next = NULL;
+ sa->aead_xform.aead.digest_length = aead_algo->digest_len;
+ sa->aead_xform.aead.iv.offset = IV_OFFSET;
+ sa->aead_xform.aead.iv.length = 12;
+
+ if (sa->ipsec_xform.direction ==
+ RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ sa->aead_xform.aead.op = RTE_CRYPTO_AEAD_OP_DECRYPT;
+ } else {
+ sa->aead_xform.aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
+ }
+
+ sa->crypto_xforms = &sa->aead_xform;
+ } else {
+ sa->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+ sa->cipher_xform.cipher.algo = cipher_algo->algo;
+ sa->cipher_xform.cipher.iv.offset = IV_OFFSET;
+ sa->cipher_xform.cipher.iv.length = 12;
+ sa->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+ sa->auth_xform.auth.algo = auth_algo->algo;
+ sa->auth_xform.auth.digest_length = auth_algo->digest_len;
+
+
+ if (sa->ipsec_xform.direction ==
+ RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+ sa->cipher_xform.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_DECRYPT;
+ sa->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY;
+ sa->cipher_xform.next = NULL;
+ sa->auth_xform.next = &sa->cipher_xform;
+ sa->crypto_xforms = &sa->auth_xform;
+ } else {
+ sa->cipher_xform.cipher.op =
+ RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+ sa->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+ sa->auth_xform.next = NULL;
+ sa->cipher_xform.next = &sa->auth_xform;
+ sa->crypto_xforms = &sa->cipher_xform;
+ }
+ }
+
+ prm->crypto_xform = sa->crypto_xforms;
+
+ return TEST_SUCCESS;
+}
+
+static int
+create_sa(enum rte_security_session_action_type action_type,
+ struct ipsec_sa *sa)
+{
+ static struct rte_cryptodev_sym_session dummy_ses;
+ size_t sz;
+ int rc;
+
+ memset(&sa->ss[0], 0, sizeof(sa->ss[0]));
+
+ rc = fill_ipsec_param(sa);
+ if (rc != 0) {
+ printf("failed to fill ipsec param\n");
+ return TEST_FAILED;
+ }
+
+ sz = rte_ipsec_sa_size(&sa->sa_prm);
+ TEST_ASSERT(sz > 0, "rte_ipsec_sa_size() failed\n");
+
+ sa->ss[0].sa = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
+ TEST_ASSERT_NOT_NULL(sa->ss[0].sa,
+ "failed to allocate memory for rte_ipsec_sa\n");
+
+ sa->ss[0].type = action_type;
+ sa->ss[0].crypto.ses = &dummy_ses;
+
+ rc = rte_ipsec_sa_init(sa->ss[0].sa, &sa->sa_prm, sz);
+ rc = (rc > 0 && (uint32_t)rc <= sz) ? 0 : -EINVAL;
+
+ if (rc == 0)
+ rc = rte_ipsec_session_prepare(&sa->ss[0]);
+ else
+ return TEST_FAILED;
+
+ return TEST_SUCCESS;
+}
+
+static int
+packet_prepare(struct rte_mbuf **buf, struct ipsec_sa *sa,
+ uint16_t num_pkts)
+{
+ uint64_t time_stamp;
+ uint16_t k = 0, i;
+
+ for (i = 0; i < num_pkts; i++) {
+
+ sa->cop[i] = rte_crypto_op_alloc(cop_pool,
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+
+ if (sa->cop[i] == NULL) {
+
+ RTE_LOG(ERR, USER1,
+ "Failed to allocate symmetric crypto op\n");
+
+ return k;
+ }
+ }
+
+ time_stamp = rte_rdtsc_precise();
+
+ k = rte_ipsec_pkt_crypto_prepare(&sa->ss[0], buf,
+ sa->cop, num_pkts);
+
+ time_stamp = rte_rdtsc_precise() - time_stamp;
+
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_crypto_prepare fail\n");
+ return k;
+ }
+
+ sa->cnt.prepare_ticks_elapsed += time_stamp;
+ sa->cnt.nb_prepare_call++;
+ sa->cnt.nb_prepare_pkt += k;
+
+ for (i = 0; i < num_pkts; i++)
+ rte_crypto_op_free(sa->cop[i]);
+
+ return k;
+}
+
+static int
+packet_process(struct rte_mbuf **buf, struct ipsec_sa *sa,
+ uint16_t num_pkts)
+{
+ uint64_t time_stamp;
+ uint16_t k = 0;
+
+ time_stamp = rte_rdtsc_precise();
+
+ k = rte_ipsec_pkt_process(&sa->ss[0], buf, num_pkts);
+
+ time_stamp = rte_rdtsc_precise() - time_stamp;
+
+ if (k != num_pkts) {
+ RTE_LOG(ERR, USER1, "rte_ipsec_pkt_process fail\n");
+ return k;
+ }
+
+ sa->cnt.process_ticks_elapsed += time_stamp;
+ sa->cnt.nb_process_call++;
+ sa->cnt.nb_process_pkt += k;
+
+ return k;
+}
+
+static int
+create_traffic(struct ipsec_sa *sa, struct rte_ring *deq_ring,
+ struct rte_ring *enq_ring, struct rte_ring *ring)
+{
+ struct rte_mbuf *mbuf[BURST_SIZE];
+ uint16_t num_pkts, n;
+
+ while (rte_ring_empty(deq_ring) == 0) {
+
+ num_pkts = rte_ring_sc_dequeue_burst(deq_ring, (void **)mbuf,
+ RTE_DIM(mbuf), NULL);
+
+ if (num_pkts == 0)
+ return TEST_FAILED;
+
+ n = packet_prepare(mbuf, sa, num_pkts);
+ if (n != num_pkts)
+ return TEST_FAILED;
+
+ num_pkts = rte_ring_sp_enqueue_burst(enq_ring, (void **)mbuf,
+ num_pkts, NULL);
+ if (num_pkts == 0)
+ return TEST_FAILED;
+ }
+
+ deq_ring = enq_ring;
+ enq_ring = ring;
+
+ while (rte_ring_empty(deq_ring) == 0) {
+
+ num_pkts = rte_ring_sc_dequeue_burst(deq_ring, (void **)mbuf,
+ RTE_DIM(mbuf), NULL);
+ if (num_pkts == 0)
+ return TEST_FAILED;
+
+ n = packet_process(mbuf, sa, num_pkts);
+ if (n != num_pkts)
+ return TEST_FAILED;
+
+ num_pkts = rte_ring_sp_enqueue_burst(enq_ring, (void **)mbuf,
+ num_pkts, NULL);
+ if (num_pkts == 0)
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+fill_ipsec_sa_out(const struct ipsec_test_cfg *test_cfg,
+ struct ipsec_sa *sa)
+{
+ sa->ipsec_xform.spi = DEFAULT_SPI;
+ sa->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
+ sa->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ sa->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ sa->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+ sa->ipsec_xform.options.esn = test_cfg->esn;
+ sa->type = test_cfg->type;
+ sa->replay_win_sz = test_cfg->replay_win_sz;
+ sa->sa_flags = test_cfg->flags;
+ sa->cnt.nb_prepare_call = 0;
+ sa->cnt.nb_prepare_pkt = 0;
+ sa->cnt.nb_process_call = 0;
+ sa->cnt.nb_process_pkt = 0;
+ sa->cnt.process_ticks_elapsed = 0;
+ sa->cnt.prepare_ticks_elapsed = 0;
+
+}
+
+static void
+fill_ipsec_sa_in(const struct ipsec_test_cfg *test_cfg,
+ struct ipsec_sa *sa)
+{
+ sa->ipsec_xform.spi = DEFAULT_SPI;
+ sa->ipsec_xform.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
+ sa->ipsec_xform.proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP;
+ sa->ipsec_xform.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+ sa->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
+ sa->ipsec_xform.options.esn = test_cfg->esn;
+ sa->type = test_cfg->type;
+ sa->replay_win_sz = test_cfg->replay_win_sz;
+ sa->sa_flags = test_cfg->flags;
+ sa->cnt.nb_prepare_call = 0;
+ sa->cnt.nb_prepare_pkt = 0;
+ sa->cnt.nb_process_call = 0;
+ sa->cnt.nb_process_pkt = 0;
+ sa->cnt.process_ticks_elapsed = 0;
+ sa->cnt.prepare_ticks_elapsed = 0;
+}
+
+static int
+init_sa_session(const struct ipsec_test_cfg *test_cfg,
+ struct ipsec_sa *sa_out, struct ipsec_sa *sa_in)
+{
+
+ int rc;
+
+ fill_ipsec_sa_in(test_cfg, sa_in);
+ fill_ipsec_sa_out(test_cfg, sa_out);
+
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE, sa_out);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "out bound create_sa failed, cfg\n");
+ return TEST_FAILED;
+ }
+
+ rc = create_sa(RTE_SECURITY_ACTION_TYPE_NONE, sa_in);
+ if (rc != 0) {
+ RTE_LOG(ERR, USER1, "out bound create_sa failed, cfg\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+testsuite_setup(void)
+{
+ struct rte_mbuf *mbuf;
+ int i;
+
+ mbuf_pool = rte_pktmbuf_pool_create("IPSEC_PERF_MBUFPOOL",
+ NUM_MBUFS, MBUF_CACHE_SIZE, 0, MBUF_SIZE,
+ rte_socket_id());
+ if (mbuf_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create MBUFPOOL\n");
+ return TEST_FAILED;
+ }
+
+ cop_pool = rte_crypto_op_pool_create(
+ "MBUF_CRYPTO_SYM_OP_POOL",
+ RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ NUM_MBUFS, MBUF_CACHE_SIZE,
+ DEFAULT_NUM_XFORMS *
+ sizeof(struct rte_crypto_sym_xform) +
+ MAXIMUM_IV_LENGTH,
+ rte_socket_id());
+ if (cop_pool == NULL) {
+ RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
+ return TEST_FAILED;
+ }
+
+ ring_inb_prepare = rte_ring_create("ipsec_test_ring_inb_prepare",
+ RING_SIZE, SOCKET_ID_ANY, 0);
+ if (ring_inb_prepare == NULL)
+ return TEST_FAILED;
+
+ ring_inb_process = rte_ring_create("ipsec_test_ring_inb_process",
+ RING_SIZE, SOCKET_ID_ANY, 0);
+ if (ring_inb_process == NULL)
+ return TEST_FAILED;
+
+ ring_outb_prepare = rte_ring_create("ipsec_test_ring_outb_prepare",
+ RING_SIZE, SOCKET_ID_ANY, 0);
+ if (ring_outb_prepare == NULL)
+ return TEST_FAILED;
+
+ ring_outb_process = rte_ring_create("ipsec_test_ring_outb_process",
+ RING_SIZE, SOCKET_ID_ANY, 0);
+ if (ring_outb_process == NULL)
+ return TEST_FAILED;
+
+ for (i = 0; i < NUM_MBUF; i++) {
+ mbuf = generate_mbuf_data(mbuf_pool);
+
+ if (mbuf && rte_ring_sp_enqueue_bulk(ring_inb_prepare,
+ (void **)&mbuf, 1, NULL))
+ continue;
+ else
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+measure_performance(struct ipsec_sa *sa_out, struct ipsec_sa *sa_in)
+{
+ uint64_t time_diff = 0;
+ uint64_t begin = 0;
+ uint64_t hz = rte_get_timer_hz();
+
+ begin = rte_get_timer_cycles();
+
+ do {
+ if (create_traffic(sa_out, ring_inb_prepare, ring_inb_process,
+ ring_outb_prepare) < 0)
+ return TEST_FAILED;
+
+ if (create_traffic(sa_in, ring_outb_prepare, ring_outb_process,
+ ring_inb_prepare) < 0)
+ return TEST_FAILED;
+
+ time_diff = rte_get_timer_cycles() - begin;
+
+ } while (time_diff < (hz * 10));
+
+ return TEST_SUCCESS;
+}
+
+static void
+print_metrics(const struct ipsec_test_cfg *test_cfg,
+ struct ipsec_sa *sa_out, struct ipsec_sa *sa_in)
+{
+ printf("\nMetrics of libipsec prepare/process api:\n");
+
+ printf("replay window size = %u\n", test_cfg->replay_win_sz);
+ if (test_cfg->esn)
+ printf("replay esn is enabled\n");
+ else
+ printf("replay esn is disabled\n");
+ if (test_cfg->type == RTE_CRYPTO_SYM_XFORM_AEAD)
+ printf("AEAD algo is AES_GCM\n");
+ else
+ printf("CIPHER/AUTH algo is AES_CBC/SHA1\n");
+
+
+ printf("avg cycles for a pkt prepare in outbound is = %.2Lf\n",
+ (long double)sa_out->cnt.prepare_ticks_elapsed
+ / sa_out->cnt.nb_prepare_pkt);
+ printf("avg cycles for a pkt process in outbound is = %.2Lf\n",
+ (long double)sa_out->cnt.process_ticks_elapsed
+ / sa_out->cnt.nb_process_pkt);
+ printf("avg cycles for a pkt prepare in inbound is = %.2Lf\n",
+ (long double)sa_in->cnt.prepare_ticks_elapsed
+ / sa_in->cnt.nb_prepare_pkt);
+ printf("avg cycles for a pkt process in inbound is = %.2Lf\n",
+ (long double)sa_in->cnt.process_ticks_elapsed
+ / sa_in->cnt.nb_process_pkt);
+
+}
+
+static void
+testsuite_teardown(void)
+{
+ if (mbuf_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "MBUFPOOL count %u\n",
+ rte_mempool_avail_count(mbuf_pool));
+ rte_mempool_free(mbuf_pool);
+ mbuf_pool = NULL;
+ }
+
+ if (cop_pool != NULL) {
+ RTE_LOG(DEBUG, USER1, "CRYPTO_OP_POOL count %u\n",
+ rte_mempool_avail_count(cop_pool));
+ rte_mempool_free(cop_pool);
+ cop_pool = NULL;
+ }
+
+ rte_ring_free(ring_inb_prepare);
+ rte_ring_free(ring_inb_process);
+ rte_ring_free(ring_outb_prepare);
+ rte_ring_free(ring_outb_process);
+
+ ring_inb_prepare = NULL;
+ ring_inb_process = NULL;
+ ring_outb_prepare = NULL;
+ ring_outb_process = NULL;
+}
+
+static int
+test_libipsec_perf(void)
+{
+ struct ipsec_sa sa_out;
+ struct ipsec_sa sa_in;
+ uint32_t i;
+ int ret;
+
+ if (testsuite_setup() < 0) {
+ testsuite_teardown();
+ return TEST_FAILED;
+ }
+
+ for (i = 0; i < RTE_DIM(test_cfg) ; i++) {
+
+ ret = init_sa_session(&test_cfg[i], &sa_out, &sa_in);
+ if (ret != 0) {
+ testsuite_teardown();
+ return TEST_FAILED;
+ }
+
+ if (measure_performance(&sa_out, &sa_in) < 0) {
+ testsuite_teardown();
+ return TEST_FAILED;
+ }
+
+ print_metrics(&test_cfg[i], &sa_out, &sa_in);
+ }
+
+ testsuite_teardown();
+
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(ipsec_perf_autotest, test_libipsec_perf);
diff --git a/src/spdk/dpdk/app/test/test_ipsec_sad.c b/src/spdk/dpdk/app/test/test_ipsec_sad.c
new file mode 100644
index 000000000..491164689
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ipsec_sad.c
@@ -0,0 +1,887 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_ipsec_sad.h>
+#include <rte_memory.h>
+
+#include "test.h"
+#include "test_xmmt_ops.h"
+
+typedef int32_t (*rte_ipsec_sad_test)(void);
+
+static int32_t test_create_invalid(void);
+static int32_t test_find_existing(void);
+static int32_t test_multiple_create(void);
+static int32_t test_add_invalid(void);
+static int32_t test_delete_invalid(void);
+static int32_t test_lookup_invalid(void);
+static int32_t test_lookup_basic(void);
+static int32_t test_lookup_adv(void);
+static int32_t test_lookup_order(void);
+
+#define MAX_SA 100000
+#define PASS 0
+#define SPI 0xdead /* spi to install */
+#define DIP 0xbeef /* dip to install */
+#define SIP 0xf00d /* sip to install */
+#define BAD 0xbad /* some random value not installed into the table */
+
+/*
+ * Check that rte_ipsec_sad_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_create_invalid(void)
+{
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+
+ /* name == NULL */
+ sad = rte_ipsec_sad_create(NULL, &config);
+ RTE_TEST_ASSERT(sad == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* max_sa for every type = 0 */
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = 0;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT(sad == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+
+ /* socket_id < -1 is invalid */
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.socket_id = -2;
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT(sad == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.socket_id = SOCKET_ID_ANY;
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Test rte_ipsec_sad_find_existing()
+ * Create SAD and try to find it by it's name
+ */
+int32_t
+test_find_existing(void)
+{
+ const char *name1 = "sad_one";
+ const char *name2 = "sad_two";
+ struct rte_ipsec_sad *one, *two, *tmp;
+ struct rte_ipsec_sad_conf config;
+
+ config.socket_id = SOCKET_ID_ANY;
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
+ one = rte_ipsec_sad_create(name1, &config);
+ RTE_TEST_ASSERT_NOT_NULL(one, "Failed to create SAD\n");
+ two = rte_ipsec_sad_create(name2, &config);
+ RTE_TEST_ASSERT_NOT_NULL(two, "Failed to create SAD\n");
+
+ /* Find non existing */
+ tmp = rte_ipsec_sad_find_existing("sad_three");
+ RTE_TEST_ASSERT(tmp == NULL,
+ "rte_ipsec_sad_find_existing returns invalid SAD\n");
+
+ tmp = rte_ipsec_sad_find_existing(name1);
+ RTE_TEST_ASSERT(tmp == one,
+ "rte_ipsec_sad_find_existing returns invalid SAD\n");
+
+ tmp = rte_ipsec_sad_find_existing(name2);
+ RTE_TEST_ASSERT(tmp == two,
+ "rte_ipsec_sad_find_existing returns invalid SAD\n");
+
+ rte_ipsec_sad_destroy(one);
+ rte_ipsec_sad_destroy(two);
+ return TEST_SUCCESS;
+}
+
+/*
+ * Create ipsec sad then delete it 10 times
+ * Use a slightly different max_sa each time
+ */
+int32_t
+test_multiple_create(void)
+{
+ int i;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+
+ config.socket_id = SOCKET_ID_ANY;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+
+ for (i = 0; i < 10; i++) {
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA - i;
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+ rte_ipsec_sad_destroy(sad);
+ }
+ return TEST_SUCCESS;
+}
+
+static int32_t
+__test_add_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+ uint64_t tmp;
+ void *sa = &tmp;
+
+ /* sad == NULL*/
+ status = rte_ipsec_sad_add(NULL, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ /* key == NULL*/
+ status = rte_ipsec_sad_add(sad, NULL, RTE_IPSEC_SAD_SPI_DIP_SIP, sa);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* len is incorrect*/
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP + 1, sa);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* sa == NULL*/
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, NULL);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* sa is not aligned*/
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, (void *)((uint8_t *)sa + 1));
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ rte_ipsec_sad_destroy(sad);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_ipsec_sad_add fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_add_invalid(void)
+{
+ int status;
+ struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
+ struct rte_ipsec_sadv6_key tuple_v6 = {10, {20, }, {30, } };
+
+ status = __test_add_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
+ if (status != TEST_SUCCESS)
+ return status;
+
+ status = __test_add_invalid(1, (union rte_ipsec_sad_key *)&tuple_v6);
+
+ return status;
+
+}
+
+static int32_t
+__test_delete_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+
+ /* sad == NULL*/
+ status = rte_ipsec_sad_del(NULL, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ /* key == NULL*/
+ status = rte_ipsec_sad_del(sad, NULL, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* len is incorrect */
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP + 1);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ rte_ipsec_sad_destroy(sad);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_ipsec_sad_delete fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_delete_invalid(void)
+{
+ int status;
+ struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
+ struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
+ {0xf0, 0x0d, } };
+
+ status = __test_delete_invalid(0, (union rte_ipsec_sad_key *)&tuple_v4);
+ if (status != TEST_SUCCESS)
+ return status;
+
+ status = __test_delete_invalid(1, (union rte_ipsec_sad_key *)&tuple_v6);
+
+ return status;
+}
+
+static int32_t
+__test_lookup_invalid(int ipv6, union rte_ipsec_sad_key *tuple)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+ const union rte_ipsec_sad_key *key_arr[] = {tuple};
+ void *sa[1];
+
+ status = rte_ipsec_sad_lookup(NULL, key_arr, sa, 1);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ status = rte_ipsec_sad_lookup(sad, NULL, sa, 1);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, NULL, 1);
+ RTE_TEST_ASSERT(status < 0,
+ "Call succeeded with invalid parameters\n");
+
+ rte_ipsec_sad_destroy(sad);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_ipsec_sad_lookup fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_lookup_invalid(void)
+{
+ int status;
+ struct rte_ipsec_sadv4_key tuple_v4 = {10, 20, 30};
+ struct rte_ipsec_sadv6_key tuple_v6 = {10, {20, }, {30, } };
+
+ status = __test_lookup_invalid(0,
+ (union rte_ipsec_sad_key *)&tuple_v4);
+ if (status != TEST_SUCCESS)
+ return status;
+
+ status = __test_lookup_invalid(1,
+ (union rte_ipsec_sad_key *)&tuple_v6);
+
+ return status;
+}
+
+static int32_t
+__test_lookup_basic(int ipv6, union rte_ipsec_sad_key *tuple,
+ union rte_ipsec_sad_key *tuple_1)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+ const union rte_ipsec_sad_key *key_arr[] = {tuple};
+
+ uint64_t tmp;
+ void *sa[1];
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
+ RTE_TEST_ASSERT((status == 0) && (sa[0] == NULL),
+ "Lookup returns an unexpected result\n");
+
+ sa[0] = &tmp;
+ status = rte_ipsec_sad_add(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY, sa[0]);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
+ RTE_TEST_ASSERT((status == 1) && (sa[0] == &tmp),
+ "Lookup returns an unexpected result\n");
+
+ key_arr[0] = tuple_1;
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
+ RTE_TEST_ASSERT((status == 1) && (sa[0] == &tmp),
+ "Lookup returns an unexpected result\n");
+ key_arr[0] = tuple;
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 1);
+ RTE_TEST_ASSERT((status == 0) && (sa[0] == NULL),
+ "Lookup returns an unexpected result\n");
+
+ rte_ipsec_sad_destroy(sad);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Lookup missing key, then add it as RTE_IPSEC_SAD_SPI_ONLY, lookup it again,
+ * lookup different key with the same SPI, then delete it and repeat lookup
+ */
+int32_t
+test_lookup_basic(void)
+{
+ int status;
+ struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
+ struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, BAD, BAD};
+ struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
+ {0xf0, 0x0d, } };
+ struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0x0b, 0xad, },
+ {0x0b, 0xad, } };
+
+ status = __test_lookup_basic(0, (union rte_ipsec_sad_key *)&tuple_v4,
+ (union rte_ipsec_sad_key *)&tuple_v4_1);
+ if (status != TEST_SUCCESS)
+ return status;
+
+ status = __test_lookup_basic(1, (union rte_ipsec_sad_key *)&tuple_v6,
+ (union rte_ipsec_sad_key *)&tuple_v6_1);
+
+ return status;
+}
+
+static int32_t
+__test_lookup_adv(int ipv6, union rte_ipsec_sad_key *tuple,
+ const union rte_ipsec_sad_key **key_arr)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+ uint64_t tmp1, tmp2, tmp3;
+ void *install_sa;
+ void *sa[4];
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ /* lookup with empty table */
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 0, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* lookup with one RTE_IPSEC_SAD_SPI_ONLY rule */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failde to delete a rule\n");
+
+ /* lookup with one RTE_IPSEC_SAD_SPI_DIP rule */
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ /* lookup with one RTE_IPSEC_SAD_SPI_DIP_SIP rule */
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ /* lookup with two RTE_IPSEC_SAD_ONLY and RTE_IPSEC_SAD_DIP rules */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ /* lookup with two RTE_IPSEC_SAD_ONLY and RTE_IPSEC_SAD_DIP_SIP rules */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ /* lookup with two RTE_IPSEC_SAD_DIP and RTE_IPSEC_SAD_DIP_SIP rules */
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ /*
+ * lookup with three RTE_IPSEC_SAD_DIP, RTE_IPSEC_SAD_DIP and
+ * RTE_IPSEC_SAD_DIP_SIP rules
+ */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 4);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[3] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ rte_ipsec_sad_destroy(sad);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Lookup different keys in a table with:
+ * - RTE_IPSEC_SAD_SPI_ONLY
+ * - RTE_IPSEC_SAD_SPI_DIP
+ * - RTE_IPSEC_SAD_SPI_SIP
+ * - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP
+ * - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP_SIP
+ * - RTE_IPSEC_SAD_SPI_DIP/RTE_IPSEC_SAD_SPI_DIP_SIP
+ * - RTE_IPSEC_SAD_SPI_ONLY/RTE_IPSEC_SAD_SPI_DIP/RTE_IPSEC_SAD_SPI_DIP_SIP
+ * length of rule installed.
+ */
+int32_t
+test_lookup_adv(void)
+{
+ int status;
+ /* key to install*/
+ struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
+ struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, DIP, BAD};
+ struct rte_ipsec_sadv4_key tuple_v4_2 = {SPI, BAD, SIP};
+ struct rte_ipsec_sadv4_key tuple_v4_3 = {BAD, DIP, SIP};
+
+ /* key to install*/
+ struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
+ {0xf0, 0x0d, } };
+ struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0xbe, 0xef, },
+ {0x0b, 0xad, } };
+ struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI, {0x0b, 0xad, },
+ {0xf0, 0x0d, } };
+ struct rte_ipsec_sadv6_key tuple_v6_3 = {BAD, {0xbe, 0xef, },
+ {0xf0, 0x0d, } };
+
+ const union rte_ipsec_sad_key *key_arr[] = {
+ (union rte_ipsec_sad_key *)&tuple_v4,
+ (union rte_ipsec_sad_key *)&tuple_v4_1,
+ (union rte_ipsec_sad_key *)&tuple_v4_2,
+ (union rte_ipsec_sad_key *)&tuple_v4_3
+ };
+
+ status = __test_lookup_adv(0, (union rte_ipsec_sad_key *)&tuple_v4,
+ key_arr);
+ if (status != TEST_SUCCESS)
+ return status;
+ key_arr[0] = (union rte_ipsec_sad_key *)&tuple_v6;
+ key_arr[1] = (union rte_ipsec_sad_key *)&tuple_v6_1;
+ key_arr[2] = (union rte_ipsec_sad_key *)&tuple_v6_2;
+ key_arr[3] = (union rte_ipsec_sad_key *)&tuple_v6_3;
+ status = __test_lookup_adv(1, (union rte_ipsec_sad_key *)&tuple_v6,
+ key_arr);
+
+ return status;
+}
+
+
+static int32_t
+__test_lookup_order(int ipv6, union rte_ipsec_sad_key *tuple,
+ union rte_ipsec_sad_key *tuple_1, union rte_ipsec_sad_key *tuple_2)
+{
+ int status;
+ struct rte_ipsec_sad *sad = NULL;
+ struct rte_ipsec_sad_conf config;
+ const union rte_ipsec_sad_key *key_arr[] = {tuple, tuple_1, tuple_2,};
+ uint64_t tmp1, tmp2, tmp3;
+ void *install_sa;
+ void *sa[3];
+
+ config.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP] = MAX_SA;
+ config.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = MAX_SA;
+ config.socket_id = SOCKET_ID_ANY;
+ config.flags = 0;
+ if (ipv6)
+ config.flags = RTE_IPSEC_SAD_FLAG_IPV6;
+ sad = rte_ipsec_sad_create(__func__, &config);
+ RTE_TEST_ASSERT_NOT_NULL(sad, "Failed to create SAD\n");
+
+ /* install RTE_IPSEC_SAD_SPI_ONLY */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp1,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+
+ /* add RTE_IPSEC_SAD_SPI_DIP */
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+
+ /* add RTE_IPSEC_SAD_SPI_DIP_SIP */
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+
+ /* delete RTE_IPSEC_SAD_SPI_ONLY */
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_ONLY);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* delete RTE_IPSEC_SAD_SPI_DIP */
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* delete RTE_IPSEC_SAD_SPI_DIP_SIP */
+ status = rte_ipsec_sad_del(sad, tuple, RTE_IPSEC_SAD_SPI_DIP_SIP);
+ RTE_TEST_ASSERT(status == 0, "Failed to delete a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 0, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* add RTE_IPSEC_SAD_SPI_DIP_SIP */
+ install_sa = &tmp3;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP_SIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 1, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == NULL,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* add RTE_IPSEC_SAD_SPI_DIP */
+ install_sa = &tmp2;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_DIP, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 2, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == NULL,
+ "Lookup returns an unexpected result\n");
+
+ /* add RTE_IPSEC_SAD_SPI_ONLY */
+ install_sa = &tmp1;
+ status = rte_ipsec_sad_add(sad, tuple,
+ RTE_IPSEC_SAD_SPI_ONLY, install_sa);
+ RTE_TEST_ASSERT(status == 0, "Failed to add a rule\n");
+
+ status = rte_ipsec_sad_lookup(sad, key_arr, sa, 3);
+ RTE_TEST_ASSERT(status == 3, "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[0] == &tmp3,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[1] == &tmp2,
+ "Lookup returns an unexpected result\n");
+ RTE_TEST_ASSERT(sa[2] == &tmp1,
+ "Lookup returns an unexpected result\n");
+
+ rte_ipsec_sad_destroy(sad);
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check an order of add and delete
+ */
+int32_t
+test_lookup_order(void)
+{
+ int status;
+ /* key to install*/
+ struct rte_ipsec_sadv4_key tuple_v4 = {SPI, DIP, SIP};
+ struct rte_ipsec_sadv4_key tuple_v4_1 = {SPI, DIP, BAD};
+ struct rte_ipsec_sadv4_key tuple_v4_2 = {SPI, BAD, SIP};
+ /* key to install*/
+ struct rte_ipsec_sadv6_key tuple_v6 = {SPI, {0xbe, 0xef, },
+ {0xf0, 0x0d, } };
+ struct rte_ipsec_sadv6_key tuple_v6_1 = {SPI, {0xbe, 0xef, },
+ {0x0b, 0xad, } };
+ struct rte_ipsec_sadv6_key tuple_v6_2 = {SPI, {0x0b, 0xad, },
+ {0xf0, 0x0d, } };
+
+ status = __test_lookup_order(0, (union rte_ipsec_sad_key *)&tuple_v4,
+ (union rte_ipsec_sad_key *)&tuple_v4_1,
+ (union rte_ipsec_sad_key *)&tuple_v4_2);
+ if (status != TEST_SUCCESS)
+ return status;
+
+ status = __test_lookup_order(1, (union rte_ipsec_sad_key *)&tuple_v6,
+ (union rte_ipsec_sad_key *)&tuple_v6_1,
+ (union rte_ipsec_sad_key *)&tuple_v6_2);
+ return status;
+}
+
+static struct unit_test_suite ipsec_sad_tests = {
+ .suite_name = "ipsec sad autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_create_invalid),
+ TEST_CASE(test_find_existing),
+ TEST_CASE(test_multiple_create),
+ TEST_CASE(test_add_invalid),
+ TEST_CASE(test_delete_invalid),
+ TEST_CASE(test_lookup_invalid),
+ TEST_CASE(test_lookup_basic),
+ TEST_CASE(test_lookup_adv),
+ TEST_CASE(test_lookup_order),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_ipsec_sad(void)
+{
+ return unit_test_suite_runner(&ipsec_sad_tests);
+}
+
+REGISTER_TEST_COMMAND(ipsec_sad_autotest, test_ipsec_sad);
diff --git a/src/spdk/dpdk/app/test/test_kni.c b/src/spdk/dpdk/app/test/test_kni.c
new file mode 100644
index 000000000..e47ab36e0
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_kni.c
@@ -0,0 +1,765 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <dirent.h>
+
+#include "test.h"
+
+#if !defined(RTE_EXEC_ENV_LINUX) || !defined(RTE_LIBRTE_KNI)
+
+static int
+test_kni(void)
+{
+ printf("KNI not supported, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+#else
+
+#include <rte_string_fns.h>
+#include <rte_mempool.h>
+#include <rte_ethdev.h>
+#include <rte_bus_pci.h>
+#include <rte_cycles.h>
+#include <rte_kni.h>
+
+#define NB_MBUF 8192
+#define MAX_PACKET_SZ 2048
+#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM)
+#define PKT_BURST_SZ 32
+#define MEMPOOL_CACHE_SZ PKT_BURST_SZ
+#define SOCKET 0
+#define NB_RXD 1024
+#define NB_TXD 1024
+#define KNI_TIMEOUT_MS 5000 /* ms */
+
+#define IFCONFIG "/sbin/ifconfig "
+#define TEST_KNI_PORT "test_kni_port"
+#define KNI_MODULE_PATH "/sys/module/rte_kni"
+#define KNI_MODULE_PARAM_LO KNI_MODULE_PATH"/parameters/lo_mode"
+#define KNI_TEST_MAX_PORTS 4
+/* The threshold number of mbufs to be transmitted or received. */
+#define KNI_NUM_MBUF_THRESHOLD 100
+static int kni_pkt_mtu = 0;
+
+struct test_kni_stats {
+ volatile uint64_t ingress;
+ volatile uint64_t egress;
+};
+
+static const struct rte_eth_rxconf rx_conf = {
+ .rx_thresh = {
+ .pthresh = 8,
+ .hthresh = 8,
+ .wthresh = 4,
+ },
+ .rx_free_thresh = 0,
+};
+
+static const struct rte_eth_txconf tx_conf = {
+ .tx_thresh = {
+ .pthresh = 36,
+ .hthresh = 0,
+ .wthresh = 0,
+ },
+ .tx_free_thresh = 0,
+ .tx_rs_thresh = 0,
+};
+
+static const struct rte_eth_conf port_conf = {
+ .txmode = {
+ .mq_mode = ETH_DCB_NONE,
+ },
+};
+
+static struct rte_kni_ops kni_ops = {
+ .change_mtu = NULL,
+ .config_network_if = NULL,
+ .config_mac_address = NULL,
+ .config_promiscusity = NULL,
+};
+
+static unsigned lcore_master, lcore_ingress, lcore_egress;
+static struct rte_kni *test_kni_ctx;
+static struct test_kni_stats stats;
+
+static volatile uint32_t test_kni_processing_flag;
+
+static struct rte_mempool *
+test_kni_create_mempool(void)
+{
+ struct rte_mempool * mp;
+
+ mp = rte_mempool_lookup("kni_mempool");
+ if (!mp)
+ mp = rte_pktmbuf_pool_create("kni_mempool",
+ NB_MBUF,
+ MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ,
+ SOCKET);
+
+ return mp;
+}
+
+static struct rte_mempool *
+test_kni_lookup_mempool(void)
+{
+ return rte_mempool_lookup("kni_mempool");
+}
+/* Callback for request of changing MTU */
+static int
+kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
+{
+ printf("Change MTU of port %d to %u\n", port_id, new_mtu);
+ kni_pkt_mtu = new_mtu;
+ printf("Change MTU of port %d to %i successfully.\n",
+ port_id, kni_pkt_mtu);
+ return 0;
+}
+
+static int
+test_kni_link_change(void)
+{
+ int ret;
+ int pid;
+
+ pid = fork();
+ if (pid < 0) {
+ printf("Error: Failed to fork a process\n");
+ return -1;
+ }
+
+ if (pid == 0) {
+ printf("Starting KNI Link status change tests.\n");
+ if (system(IFCONFIG TEST_KNI_PORT" up") == -1) {
+ ret = -1;
+ goto error;
+ }
+
+ ret = rte_kni_update_link(test_kni_ctx, 1);
+ if (ret < 0) {
+ printf("Failed to change link state to Up ret=%d.\n",
+ ret);
+ goto error;
+ }
+ rte_delay_ms(1000);
+ printf("KNI: Set LINKUP, previous state=%d\n", ret);
+
+ ret = rte_kni_update_link(test_kni_ctx, 0);
+ if (ret != 1) {
+ printf(
+ "Failed! Previous link state should be 1, returned %d.\n",
+ ret);
+ goto error;
+ }
+ rte_delay_ms(1000);
+ printf("KNI: Set LINKDOWN, previous state=%d\n", ret);
+
+ ret = rte_kni_update_link(test_kni_ctx, 1);
+ if (ret != 0) {
+ printf(
+ "Failed! Previous link state should be 0, returned %d.\n",
+ ret);
+ goto error;
+ }
+ printf("KNI: Set LINKUP, previous state=%d\n", ret);
+
+ ret = 0;
+ rte_delay_ms(1000);
+
+error:
+ if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
+ ret = -1;
+
+ printf("KNI: Link status change tests: %s.\n",
+ (ret == 0) ? "Passed" : "Failed");
+ exit(ret);
+ } else {
+ int p_ret, status;
+
+ while (1) {
+ p_ret = waitpid(pid, &status, WNOHANG);
+ if (p_ret != 0) {
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ return -1;
+ }
+ rte_delay_ms(10);
+ rte_kni_handle_request(test_kni_ctx);
+ }
+ }
+}
+/**
+ * This loop fully tests the basic functions of KNI. e.g. transmitting,
+ * receiving to, from kernel space, and kernel requests.
+ *
+ * This is the loop to transmit/receive mbufs to/from kernel interface with
+ * supported by KNI kernel module. The ingress lcore will allocate mbufs and
+ * transmit them to kernel space; while the egress lcore will receive the mbufs
+ * from kernel space and free them.
+ * On the master lcore, several commands will be run to check handling the
+ * kernel requests. And it will finally set the flag to exit the KNI
+ * transmitting/receiving to/from the kernel space.
+ *
+ * Note: To support this testing, the KNI kernel module needs to be insmodded
+ * in one of its loopback modes.
+ */
+static int
+test_kni_loop(__rte_unused void *arg)
+{
+ int ret = 0;
+ unsigned nb_rx, nb_tx, num, i;
+ const unsigned lcore_id = rte_lcore_id();
+ struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
+
+ if (lcore_id == lcore_master) {
+ rte_delay_ms(KNI_TIMEOUT_MS);
+ /* tests of handling kernel request */
+ if (system(IFCONFIG TEST_KNI_PORT" up") == -1)
+ ret = -1;
+ if (system(IFCONFIG TEST_KNI_PORT" mtu 1400") == -1)
+ ret = -1;
+ if (system(IFCONFIG TEST_KNI_PORT" down") == -1)
+ ret = -1;
+ rte_delay_ms(KNI_TIMEOUT_MS);
+ test_kni_processing_flag = 1;
+ } else if (lcore_id == lcore_ingress) {
+ struct rte_mempool *mp = test_kni_lookup_mempool();
+
+ if (mp == NULL)
+ return -1;
+
+ while (1) {
+ if (test_kni_processing_flag)
+ break;
+
+ for (nb_rx = 0; nb_rx < PKT_BURST_SZ; nb_rx++) {
+ pkts_burst[nb_rx] = rte_pktmbuf_alloc(mp);
+ if (!pkts_burst[nb_rx])
+ break;
+ }
+
+ num = rte_kni_tx_burst(test_kni_ctx, pkts_burst,
+ nb_rx);
+ stats.ingress += num;
+ rte_kni_handle_request(test_kni_ctx);
+ if (num < nb_rx) {
+ for (i = num; i < nb_rx; i++) {
+ rte_pktmbuf_free(pkts_burst[i]);
+ }
+ }
+ rte_delay_ms(10);
+ }
+ } else if (lcore_id == lcore_egress) {
+ while (1) {
+ if (test_kni_processing_flag)
+ break;
+ num = rte_kni_rx_burst(test_kni_ctx, pkts_burst,
+ PKT_BURST_SZ);
+ stats.egress += num;
+ for (nb_tx = 0; nb_tx < num; nb_tx++)
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ rte_delay_ms(10);
+ }
+ }
+
+ return ret;
+}
+
+static int
+test_kni_allocate_lcores(void)
+{
+ unsigned i, count = 0;
+
+ lcore_master = rte_get_master_lcore();
+ printf("master lcore: %u\n", lcore_master);
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ if (count >=2 )
+ break;
+ if (rte_lcore_is_enabled(i) && i != lcore_master) {
+ count ++;
+ if (count == 1)
+ lcore_ingress = i;
+ else if (count == 2)
+ lcore_egress = i;
+ }
+ }
+ printf("count: %u\n", count);
+
+ return count == 2 ? 0 : -1;
+}
+
+static int
+test_kni_register_handler_mp(void)
+{
+#define TEST_KNI_HANDLE_REQ_COUNT 10 /* 5s */
+#define TEST_KNI_HANDLE_REQ_INTERVAL 500 /* ms */
+#define TEST_KNI_MTU 1450
+#define TEST_KNI_MTU_STR " 1450"
+ int pid;
+
+ pid = fork();
+ if (pid < 0) {
+ printf("Failed to fork a process\n");
+ return -1;
+ } else if (pid == 0) {
+ int i;
+ struct rte_kni *kni = rte_kni_get(TEST_KNI_PORT);
+ struct rte_kni_ops ops = {
+ .change_mtu = kni_change_mtu,
+ .config_network_if = NULL,
+ .config_mac_address = NULL,
+ .config_promiscusity = NULL,
+ };
+
+ if (!kni) {
+ printf("Failed to get KNI named %s\n", TEST_KNI_PORT);
+ exit(-1);
+ }
+
+ kni_pkt_mtu = 0;
+
+ /* Check with the invalid parameters */
+ if (rte_kni_register_handlers(kni, NULL) == 0) {
+ printf("Unexpectedly register successuflly "
+ "with NULL ops pointer\n");
+ exit(-1);
+ }
+ if (rte_kni_register_handlers(NULL, &ops) == 0) {
+ printf("Unexpectedly register successfully "
+ "to NULL KNI device pointer\n");
+ exit(-1);
+ }
+
+ if (rte_kni_register_handlers(kni, &ops)) {
+ printf("Fail to register ops\n");
+ exit(-1);
+ }
+
+ /* Check registering again after it has been registered */
+ if (rte_kni_register_handlers(kni, &ops) == 0) {
+ printf("Unexpectedly register successfully after "
+ "it has already been registered\n");
+ exit(-1);
+ }
+
+ /**
+ * Handle the request of setting MTU,
+ * with registered handlers.
+ */
+ for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
+ rte_kni_handle_request(kni);
+ if (kni_pkt_mtu == TEST_KNI_MTU)
+ break;
+ rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
+ }
+ if (i >= TEST_KNI_HANDLE_REQ_COUNT) {
+ printf("MTU has not been set\n");
+ exit(-1);
+ }
+
+ kni_pkt_mtu = 0;
+ if (rte_kni_unregister_handlers(kni) < 0) {
+ printf("Fail to unregister ops\n");
+ exit(-1);
+ }
+
+ /* Check with invalid parameter */
+ if (rte_kni_unregister_handlers(NULL) == 0) {
+ exit(-1);
+ }
+
+ /**
+ * Handle the request of setting MTU,
+ * without registered handlers.
+ */
+ for (i = 0; i < TEST_KNI_HANDLE_REQ_COUNT; i++) {
+ rte_kni_handle_request(kni);
+ if (kni_pkt_mtu != 0)
+ break;
+ rte_delay_ms(TEST_KNI_HANDLE_REQ_INTERVAL);
+ }
+ if (kni_pkt_mtu != 0) {
+ printf("MTU shouldn't be set\n");
+ exit(-1);
+ }
+
+ exit(0);
+ } else {
+ int p_ret, status;
+
+ rte_delay_ms(1000);
+ if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
+ == -1)
+ return -1;
+
+ rte_delay_ms(1000);
+ if (system(IFCONFIG TEST_KNI_PORT " mtu" TEST_KNI_MTU_STR)
+ == -1)
+ return -1;
+
+ p_ret = wait(&status);
+ if (!WIFEXITED(status)) {
+ printf("Child process (%d) exit abnormally\n", p_ret);
+ return -1;
+ }
+ if (WEXITSTATUS(status) != 0) {
+ printf("Child process exit with failure\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_kni_processing(uint16_t port_id, struct rte_mempool *mp)
+{
+ int ret = 0;
+ unsigned i;
+ struct rte_kni *kni;
+ struct rte_kni_conf conf;
+ struct rte_eth_dev_info info;
+ struct rte_kni_ops ops;
+ const struct rte_pci_device *pci_dev;
+ const struct rte_bus *bus = NULL;
+
+ if (!mp)
+ return -1;
+
+ memset(&conf, 0, sizeof(conf));
+ memset(&info, 0, sizeof(info));
+ memset(&ops, 0, sizeof(ops));
+
+ ret = rte_eth_dev_info_get(port_id, &info);
+ if (ret != 0) {
+ printf("Error during getting device (port %u) info: %s\n",
+ port_id, strerror(-ret));
+ return -1;
+ }
+
+ if (info.device)
+ bus = rte_bus_find_by_device(info.device);
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(info.device);
+ conf.addr = pci_dev->addr;
+ conf.id = pci_dev->id;
+ }
+ snprintf(conf.name, sizeof(conf.name), TEST_KNI_PORT);
+
+ /* core id 1 configured for kernel thread */
+ conf.core_id = 1;
+ conf.force_bind = 1;
+ conf.mbuf_size = MAX_PACKET_SZ;
+ conf.group_id = port_id;
+
+ ops = kni_ops;
+ ops.port_id = port_id;
+
+ /* basic test of kni processing */
+ kni = rte_kni_alloc(mp, &conf, &ops);
+ if (!kni) {
+ printf("fail to create kni\n");
+ return -1;
+ }
+
+ test_kni_ctx = kni;
+ test_kni_processing_flag = 0;
+ stats.ingress = 0;
+ stats.egress = 0;
+
+ /**
+ * Check multiple processes support on
+ * registerring/unregisterring handlers.
+ */
+ if (test_kni_register_handler_mp() < 0) {
+ printf("fail to check multiple process support\n");
+ ret = -1;
+ goto fail_kni;
+ }
+
+ ret = test_kni_link_change();
+ if (ret != 0)
+ goto fail_kni;
+
+ rte_eal_mp_remote_launch(test_kni_loop, NULL, CALL_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ if (rte_eal_wait_lcore(i) < 0) {
+ ret = -1;
+ goto fail_kni;
+ }
+ }
+ /**
+ * Check if the number of mbufs received from kernel space is equal
+ * to that of transmitted to kernel space
+ */
+ if (stats.ingress < KNI_NUM_MBUF_THRESHOLD ||
+ stats.egress < KNI_NUM_MBUF_THRESHOLD) {
+ printf("The ingress/egress number should not be "
+ "less than %u\n", (unsigned)KNI_NUM_MBUF_THRESHOLD);
+ ret = -1;
+ goto fail_kni;
+ }
+
+ if (rte_kni_release(kni) < 0) {
+ printf("fail to release kni\n");
+ return -1;
+ }
+ test_kni_ctx = NULL;
+
+ /* test of reusing memzone */
+ kni = rte_kni_alloc(mp, &conf, &ops);
+ if (!kni) {
+ printf("fail to create kni\n");
+ return -1;
+ }
+
+ /* Release the kni for following testing */
+ if (rte_kni_release(kni) < 0) {
+ printf("fail to release kni\n");
+ return -1;
+ }
+
+ return ret;
+fail_kni:
+ if (rte_kni_release(kni) < 0) {
+ printf("fail to release kni\n");
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int
+test_kni(void)
+{
+ int ret = -1;
+ uint16_t port_id;
+ struct rte_kni *kni;
+ struct rte_mempool *mp;
+ struct rte_kni_conf conf;
+ struct rte_eth_dev_info info;
+ struct rte_kni_ops ops;
+ const struct rte_pci_device *pci_dev;
+ const struct rte_bus *bus;
+ FILE *fd;
+ DIR *dir;
+ char buf[16];
+
+ dir = opendir(KNI_MODULE_PATH);
+ if (!dir) {
+ if (errno == ENOENT) {
+ printf("Cannot run UT due to missing rte_kni module\n");
+ return TEST_SKIPPED;
+ }
+ printf("opendir: %s", strerror(errno));
+ return -1;
+ }
+ closedir(dir);
+
+ /* Initialize KNI subsytem */
+ rte_kni_init(KNI_TEST_MAX_PORTS);
+
+ if (test_kni_allocate_lcores() < 0) {
+ printf("No enough lcores for kni processing\n");
+ return -1;
+ }
+
+ mp = test_kni_create_mempool();
+ if (!mp) {
+ printf("fail to create mempool for kni\n");
+ return -1;
+ }
+
+ /* configuring port 0 for the test is enough */
+ port_id = 0;
+ ret = rte_eth_dev_configure(port_id, 1, 1, &port_conf);
+ if (ret < 0) {
+ printf("fail to configure port %d\n", port_id);
+ return -1;
+ }
+
+ ret = rte_eth_rx_queue_setup(port_id, 0, NB_RXD, SOCKET, &rx_conf, mp);
+ if (ret < 0) {
+ printf("fail to setup rx queue for port %d\n", port_id);
+ return -1;
+ }
+
+ ret = rte_eth_tx_queue_setup(port_id, 0, NB_TXD, SOCKET, &tx_conf);
+ if (ret < 0) {
+ printf("fail to setup tx queue for port %d\n", port_id);
+ return -1;
+ }
+
+ ret = rte_eth_dev_start(port_id);
+ if (ret < 0) {
+ printf("fail to start port %d\n", port_id);
+ return -1;
+ }
+ ret = rte_eth_promiscuous_enable(port_id);
+ if (ret != 0) {
+ printf("fail to enable promiscuous mode for port %d: %s\n",
+ port_id, rte_strerror(-ret));
+ return -1;
+ }
+
+ /* basic test of kni processing */
+ fd = fopen(KNI_MODULE_PARAM_LO, "r");
+ if (fd == NULL) {
+ printf("fopen: %s", strerror(errno));
+ return -1;
+ }
+ memset(&buf, 0, sizeof(buf));
+ if (fgets(buf, sizeof(buf), fd)) {
+ if (!strncmp(buf, "lo_mode_fifo", strlen("lo_mode_fifo")) ||
+ !strncmp(buf, "lo_mode_fifo_skb",
+ strlen("lo_mode_fifo_skb"))) {
+ ret = test_kni_processing(port_id, mp);
+ if (ret < 0) {
+ fclose(fd);
+ goto fail;
+ }
+ } else
+ printf("test_kni_processing skipped because of missing rte_kni module lo_mode argument\n");
+ }
+ fclose(fd);
+
+ /* test of allocating KNI with NULL mempool pointer */
+ memset(&info, 0, sizeof(info));
+ memset(&conf, 0, sizeof(conf));
+ memset(&ops, 0, sizeof(ops));
+
+ ret = rte_eth_dev_info_get(port_id, &info);
+ if (ret != 0) {
+ printf("Error during getting device (port %u) info: %s\n",
+ port_id, strerror(-ret));
+ return -1;
+ }
+
+ if (info.device)
+ bus = rte_bus_find_by_device(info.device);
+ else
+ bus = NULL;
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(info.device);
+ conf.addr = pci_dev->addr;
+ conf.id = pci_dev->id;
+ }
+ conf.group_id = port_id;
+ conf.mbuf_size = MAX_PACKET_SZ;
+
+ ops = kni_ops;
+ ops.port_id = port_id;
+ kni = rte_kni_alloc(NULL, &conf, &ops);
+ if (kni) {
+ ret = -1;
+ printf("unexpectedly creates kni successfully with NULL "
+ "mempool pointer\n");
+ goto fail;
+ }
+
+ /* test of allocating KNI without configurations */
+ kni = rte_kni_alloc(mp, NULL, NULL);
+ if (kni) {
+ ret = -1;
+ printf("Unexpectedly allocate KNI device successfully "
+ "without configurations\n");
+ goto fail;
+ }
+
+ /* test of allocating KNI without a name */
+ memset(&conf, 0, sizeof(conf));
+ memset(&info, 0, sizeof(info));
+ memset(&ops, 0, sizeof(ops));
+
+ ret = rte_eth_dev_info_get(port_id, &info);
+ if (ret != 0) {
+ printf("Error during getting device (port %u) info: %s\n",
+ port_id, strerror(-ret));
+ ret = -1;
+ goto fail;
+ }
+
+ if (info.device)
+ bus = rte_bus_find_by_device(info.device);
+ else
+ bus = NULL;
+ if (bus && !strcmp(bus->name, "pci")) {
+ pci_dev = RTE_DEV_TO_PCI(info.device);
+ conf.addr = pci_dev->addr;
+ conf.id = pci_dev->id;
+ }
+ conf.group_id = port_id;
+ conf.mbuf_size = MAX_PACKET_SZ;
+
+ ops = kni_ops;
+ ops.port_id = port_id;
+ kni = rte_kni_alloc(mp, &conf, &ops);
+ if (kni) {
+ ret = -1;
+ printf("Unexpectedly allocate a KNI device successfully "
+ "without a name\n");
+ goto fail;
+ }
+
+ /* test of releasing NULL kni context */
+ ret = rte_kni_release(NULL);
+ if (ret == 0) {
+ ret = -1;
+ printf("unexpectedly release kni successfully\n");
+ goto fail;
+ }
+
+ /* test of handling request on NULL device pointer */
+ ret = rte_kni_handle_request(NULL);
+ if (ret == 0) {
+ ret = -1;
+ printf("Unexpectedly handle request on NULL device pointer\n");
+ goto fail;
+ }
+
+ /* test of getting KNI device with pointer to NULL */
+ kni = rte_kni_get(NULL);
+ if (kni) {
+ ret = -1;
+ printf("Unexpectedly get a KNI device with "
+ "NULL name pointer\n");
+ goto fail;
+ }
+
+ /* test of getting KNI device with an zero length name string */
+ memset(&conf, 0, sizeof(conf));
+ kni = rte_kni_get(conf.name);
+ if (kni) {
+ ret = -1;
+ printf("Unexpectedly get a KNI device with "
+ "zero length name string\n");
+ goto fail;
+ }
+
+ /* test of getting KNI device with an invalid string name */
+ memset(&conf, 0, sizeof(conf));
+ snprintf(conf.name, sizeof(conf.name), "testing");
+ kni = rte_kni_get(conf.name);
+ if (kni) {
+ ret = -1;
+ printf("Unexpectedly get a KNI device with "
+ "a never used name string\n");
+ goto fail;
+ }
+ ret = 0;
+
+fail:
+ rte_eth_dev_stop(port_id);
+
+ return ret;
+}
+
+#endif
+
+REGISTER_TEST_COMMAND(kni_autotest, test_kni);
diff --git a/src/spdk/dpdk/app/test/test_kvargs.c b/src/spdk/dpdk/app/test/test_kvargs.c
new file mode 100644
index 000000000..2a2dae43a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_kvargs.c
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014 6WIND S.A.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_kvargs.h>
+
+#include "test.h"
+
+/* incrementd in handler, to check it is properly called once per
+ * key/value association */
+static unsigned count;
+
+/* this handler increment the "count" variable at each call and check
+ * that the key is "check" and the value is "value%d" */
+static int check_handler(const char *key, const char *value,
+ __rte_unused void *opaque)
+{
+ char buf[16];
+
+ /* we check that the value is "check" */
+ if (strcmp(key, "check"))
+ return -1;
+
+ /* we check that the value is "value$(count)" */
+ snprintf(buf, sizeof(buf), "value%d", count);
+ if (strncmp(buf, value, sizeof(buf)))
+ return -1;
+
+ count ++;
+ return 0;
+}
+
+/* test a valid case */
+static int test_valid_kvargs(void)
+{
+ struct rte_kvargs *kvlist;
+ const char *args;
+ const char *valid_keys_list[] = { "foo", "check", NULL };
+ const char **valid_keys;
+
+ /* empty args is valid */
+ args = "";
+ valid_keys = NULL;
+ kvlist = rte_kvargs_parse(args, valid_keys);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error");
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ /* first test without valid_keys */
+ args = "foo=1234,check=value0,check=value1";
+ valid_keys = NULL;
+ kvlist = rte_kvargs_parse(args, valid_keys);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error");
+ goto fail;
+ }
+ /* call check_handler() for all entries with key="check" */
+ count = 0;
+ if (rte_kvargs_process(kvlist, "check", check_handler, NULL) < 0) {
+ printf("rte_kvargs_process() error\n");
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ if (count != 2) {
+ printf("invalid count value %d after rte_kvargs_process(check)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ count = 0;
+ /* call check_handler() for all entries with key="unexistant_key" */
+ if (rte_kvargs_process(kvlist, "unexistant_key", check_handler, NULL) < 0) {
+ printf("rte_kvargs_process() error\n");
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ if (count != 0) {
+ printf("invalid count value %d after rte_kvargs_process(unexistant_key)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ /* count all entries with key="foo" */
+ count = rte_kvargs_count(kvlist, "foo");
+ if (count != 1) {
+ printf("invalid count value %d after rte_kvargs_count(foo)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ /* count all entries */
+ count = rte_kvargs_count(kvlist, NULL);
+ if (count != 3) {
+ printf("invalid count value %d after rte_kvargs_count(NULL)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ /* count all entries with key="unexistant_key" */
+ count = rte_kvargs_count(kvlist, "unexistant_key");
+ if (count != 0) {
+ printf("invalid count value %d after rte_kvargs_count(unexistant_key)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ /* second test using valid_keys */
+ args = "foo=droids,check=value0,check=value1,check=wrong_value";
+ valid_keys = valid_keys_list;
+ kvlist = rte_kvargs_parse(args, valid_keys);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error");
+ goto fail;
+ }
+ /* call check_handler() on all entries with key="check", it
+ * should fail as the value is not recognized by the handler */
+ if (rte_kvargs_process(kvlist, "check", check_handler, NULL) == 0) {
+ printf("rte_kvargs_process() is success bu should not\n");
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ count = rte_kvargs_count(kvlist, "check");
+ if (count != 3) {
+ printf("invalid count value %d after rte_kvargs_count(check)\n",
+ count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ /* third test using list as value */
+ args = "foo=[0,1],check=value2";
+ valid_keys = valid_keys_list;
+ kvlist = rte_kvargs_parse(args, valid_keys);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error\n");
+ goto fail;
+ }
+ if (strcmp(kvlist->pairs[0].value, "[0,1]") != 0) {
+ printf("wrong value %s", kvlist->pairs[0].value);
+ goto fail;
+ }
+ count = kvlist->count;
+ if (count != 2) {
+ printf("invalid count value %d\n", count);
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ /* test using empty string (it is valid) */
+ args = "";
+ kvlist = rte_kvargs_parse(args, NULL);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error\n");
+ goto fail;
+ }
+ if (rte_kvargs_count(kvlist, NULL) != 0) {
+ printf("invalid count value\n");
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ /* test using empty elements (it is valid) */
+ args = "foo=1,,check=value2,,";
+ kvlist = rte_kvargs_parse(args, NULL);
+ if (kvlist == NULL) {
+ printf("rte_kvargs_parse() error\n");
+ goto fail;
+ }
+ if (rte_kvargs_count(kvlist, NULL) != 2) {
+ printf("invalid count value\n");
+ goto fail;
+ }
+ if (rte_kvargs_count(kvlist, "foo") != 1) {
+ printf("invalid count value for 'foo'\n");
+ goto fail;
+ }
+ if (rte_kvargs_count(kvlist, "check") != 1) {
+ printf("invalid count value for 'check'\n");
+ goto fail;
+ }
+ rte_kvargs_free(kvlist);
+
+ return 0;
+
+ fail:
+ printf("while processing <%s>", args);
+ if (valid_keys != NULL && *valid_keys != NULL) {
+ printf(" using valid_keys=<%s", *valid_keys);
+ while (*(++valid_keys) != NULL)
+ printf(",%s", *valid_keys);
+ printf(">");
+ }
+ printf("\n");
+ return -1;
+}
+
+/* test several error cases */
+static int test_invalid_kvargs(void)
+{
+ struct rte_kvargs *kvlist;
+ /* list of argument that should fail */
+ const char *args_list[] = {
+ "wrong-key=x", /* key not in valid_keys_list */
+ "foo=1,foo=", /* empty value */
+ "foo=1,foo", /* no value */
+ "foo=1,=2", /* no key */
+ "foo=[1,2", /* no closing bracket in value */
+ ",=", /* also test with a smiley */
+ "foo=[", /* no value in list and no closing bracket */
+ NULL };
+ const char **args;
+ const char *valid_keys_list[] = { "foo", "check", NULL };
+ const char **valid_keys = valid_keys_list;
+
+ for (args = args_list; *args != NULL; args++) {
+
+ kvlist = rte_kvargs_parse(*args, valid_keys);
+ if (kvlist != NULL) {
+ printf("rte_kvargs_parse() returned 0 (but should not)\n");
+ rte_kvargs_free(kvlist);
+ goto fail;
+ }
+ }
+ return 0;
+
+ fail:
+ printf("while processing <%s>", *args);
+ if (valid_keys != NULL && *valid_keys != NULL) {
+ printf(" using valid_keys=<%s", *valid_keys);
+ while (*(++valid_keys) != NULL)
+ printf(",%s", *valid_keys);
+ printf(">");
+ }
+ printf("\n");
+ return -1;
+}
+
+static int
+test_kvargs(void)
+{
+ printf("== test valid case ==\n");
+ if (test_valid_kvargs() < 0)
+ return -1;
+ printf("== test invalid case ==\n");
+ if (test_invalid_kvargs() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(kvargs_autotest, test_kvargs);
diff --git a/src/spdk/dpdk/app/test/test_latencystats.c b/src/spdk/dpdk/app/test/test_latencystats.c
new file mode 100644
index 000000000..427339904
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_latencystats.c
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <rte_latencystats.h>
+#include "rte_lcore.h"
+#include "rte_metrics.h"
+
+#include "sample_packet_forward.h"
+#include "test.h"
+
+#define NUM_STATS 4
+#define LATENCY_NUM_PACKETS 10
+#define QUEUE_ID 0
+
+static uint16_t portid;
+static struct rte_ring *ring;
+
+static struct rte_metric_name lat_stats_strings[] = {
+ {"min_latency_ns"},
+ {"avg_latency_ns"},
+ {"max_latency_ns"},
+ {"jitter_ns"},
+};
+
+/* Test case for latency init with metrics init */
+static int test_latency_init(void)
+{
+ int ret = 0;
+
+ /* Metrics Initialization */
+ rte_metrics_init(rte_socket_id());
+
+ ret = rte_latencystats_init(1, NULL);
+ TEST_ASSERT(ret >= 0, "Test Failed: rte_latencystats_init failed");
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to update the latency stats */
+static int test_latency_update(void)
+{
+ int ret = 0;
+
+ ret = rte_latencystats_update();
+ TEST_ASSERT(ret >= 0, "Test Failed: rte_latencystats_update failed");
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to uninit latency stats */
+static int test_latency_uninit(void)
+{
+ int ret = 0;
+
+ ret = rte_latencystats_uninit();
+ TEST_ASSERT(ret >= 0, "Test Failed: rte_latencystats_uninit failed");
+
+ ret = rte_metrics_deinit();
+ TEST_ASSERT(ret >= 0, "Test Failed: rte_metrics_deinit failed");
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to get names of latency stats */
+static int test_latencystats_get_names(void)
+{
+ int ret = 0, i = 0;
+ int size = 0;
+ struct rte_metric_name names[NUM_STATS];
+
+ size_t m_size = sizeof(struct rte_metric_name);
+ for (i = 0; i < NUM_STATS; i++)
+ memset(&names[i], 0, m_size);
+
+ /* Success Test: Valid names and size */
+ size = NUM_STATS;
+ ret = rte_latencystats_get_names(names, size);
+ for (i = 0; i <= NUM_STATS; i++) {
+ if (strcmp(lat_stats_strings[i].name, names[i].name) == 0)
+ printf(" %s\n", names[i].name);
+ else
+ printf("Failed: Names are not matched\n");
+ }
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get metrics names");
+
+ /* Failure Test: Invalid names and valid size */
+ ret = rte_latencystats_get_names(NULL, size);
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get the metrics count,"
+ "Actual: %d Expected: %d", ret, NUM_STATS);
+
+ /* Failure Test: Valid names and invalid size */
+ size = 0;
+ ret = rte_latencystats_get_names(names, size);
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get the metrics count,"
+ "Actual: %d Expected: %d", ret, NUM_STATS);
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to get latency stats values */
+static int test_latencystats_get(void)
+{
+ int ret = 0, i = 0;
+ int size = 0;
+ struct rte_metric_value values[NUM_STATS];
+
+ size_t v_size = sizeof(struct rte_metric_value);
+ for (i = 0; i < NUM_STATS; i++)
+ memset(&values[i], 0, v_size);
+
+ /* Success Test: Valid values and valid size */
+ size = NUM_STATS;
+ ret = rte_latencystats_get(values, size);
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get latency metrics"
+ " values");
+
+ /* Failure Test: Invalid values and valid size */
+ ret = rte_latencystats_get(NULL, size);
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get the stats count,"
+ "Actual: %d Expected: %d", ret, NUM_STATS);
+
+ /* Failure Test: Valid values and invalid size */
+ size = 0;
+ ret = rte_latencystats_get(values, size);
+ TEST_ASSERT((ret == NUM_STATS), "Test Failed to get the stats count,"
+ "Actual: %d Expected: %d", ret, NUM_STATS);
+
+ return TEST_SUCCESS;
+}
+
+static int test_latency_ring_setup(void)
+{
+ test_ring_setup(&ring, &portid);
+
+ return TEST_SUCCESS;
+}
+
+static void test_latency_ring_free(void)
+{
+ test_ring_free(ring);
+ test_vdev_uninit("net_ring_net_ringa");
+}
+
+static int test_latency_packet_forward(void)
+{
+ int ret;
+ struct rte_mbuf *pbuf[LATENCY_NUM_PACKETS] = { };
+ struct rte_mempool *mp;
+ char poolname[] = "mbuf_pool";
+
+ ret = test_get_mbuf_from_pool(&mp, pbuf, poolname);
+ if (ret < 0) {
+ printf("allocate mbuf pool Failed\n");
+ return TEST_FAILED;
+ }
+ ret = test_packet_forward(pbuf, portid, QUEUE_ID);
+ if (ret < 0)
+ printf("send pkts Failed\n");
+ test_put_mbuf_to_pool(mp, pbuf);
+
+ return TEST_SUCCESS;
+}
+
+static struct
+unit_test_suite latencystats_testsuite = {
+ .suite_name = "Latency Stats Unit Test Suite",
+ .setup = test_latency_ring_setup,
+ .teardown = test_latency_ring_free,
+ .unit_test_cases = {
+
+ /* Test Case 1: To check latency init with
+ * metrics init
+ */
+ TEST_CASE_ST(NULL, NULL, test_latency_init),
+
+ /* Test Case 2: Do packet forwarding for metrics
+ * calculation and check the latency metrics values
+ * are updated
+ */
+ TEST_CASE_ST(test_latency_packet_forward, NULL,
+ test_latency_update),
+ /* Test Case 3: To check whether latency stats names
+ * are retrieved
+ */
+ TEST_CASE_ST(NULL, NULL, test_latencystats_get_names),
+
+ /* Test Case 4: To check whether latency stats
+ * values are retrieved
+ */
+ TEST_CASE_ST(NULL, NULL, test_latencystats_get),
+
+ /* Test Case 5: To check uninit of latency test */
+ TEST_CASE_ST(NULL, NULL, test_latency_uninit),
+
+ TEST_CASES_END()
+ }
+};
+
+static int test_latencystats(void)
+{
+ return unit_test_suite_runner(&latencystats_testsuite);
+}
+
+REGISTER_TEST_COMMAND(latencystats_autotest, test_latencystats);
diff --git a/src/spdk/dpdk/app/test/test_link_bonding.c b/src/spdk/dpdk/app/test/test_link_bonding.c
new file mode 100644
index 000000000..3a46f943f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_link_bonding.c
@@ -0,0 +1,5153 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include "unistd.h"
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+#include <rte_cycles.h>
+#include <rte_byteorder.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
+#include <rte_log.h>
+#include <rte_lcore.h>
+#include <rte_memory.h>
+#include <rte_string_fns.h>
+#include <rte_eth_bond.h>
+
+#include "virtual_pmd.h"
+#include "packet_burst_generator.h"
+
+#include "test.h"
+
+#define TEST_MAX_NUMBER_OF_PORTS (6)
+
+#define RX_RING_SIZE 1024
+#define RX_FREE_THRESH 32
+#define RX_PTHRESH 8
+#define RX_HTHRESH 8
+#define RX_WTHRESH 0
+
+#define TX_RING_SIZE 1024
+#define TX_FREE_THRESH 32
+#define TX_PTHRESH 32
+#define TX_HTHRESH 0
+#define TX_WTHRESH 0
+#define TX_RSBIT_THRESH 32
+
+#define MBUF_CACHE_SIZE (250)
+#define BURST_SIZE (32)
+
+#define RTE_TEST_RX_DESC_MAX (2048)
+#define RTE_TEST_TX_DESC_MAX (2048)
+#define MAX_PKT_BURST (512)
+#define DEF_PKT_BURST (16)
+
+#define BONDED_DEV_NAME ("net_bonding_ut")
+
+#define INVALID_SOCKET_ID (-1)
+#define INVALID_PORT_ID (-1)
+#define INVALID_BONDING_MODE (-1)
+
+
+uint8_t slave_mac[] = {0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 };
+uint8_t bonded_mac[] = {0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+
+struct link_bonding_unittest_params {
+ int16_t bonded_port_id;
+ int16_t slave_port_ids[TEST_MAX_NUMBER_OF_PORTS];
+ uint16_t bonded_slave_count;
+ uint8_t bonding_mode;
+
+ uint16_t nb_rx_q;
+ uint16_t nb_tx_q;
+
+ struct rte_mempool *mbuf_pool;
+
+ struct rte_ether_addr *default_slave_mac;
+ struct rte_ether_addr *default_bonded_mac;
+
+ /* Packet Headers */
+ struct rte_ether_hdr *pkt_eth_hdr;
+ struct rte_ipv4_hdr *pkt_ipv4_hdr;
+ struct rte_ipv6_hdr *pkt_ipv6_hdr;
+ struct rte_udp_hdr *pkt_udp_hdr;
+
+};
+
+static struct rte_ipv4_hdr pkt_ipv4_hdr;
+static struct rte_ipv6_hdr pkt_ipv6_hdr;
+static struct rte_udp_hdr pkt_udp_hdr;
+
+static struct link_bonding_unittest_params default_params = {
+ .bonded_port_id = -1,
+ .slave_port_ids = { -1 },
+ .bonded_slave_count = 0,
+ .bonding_mode = BONDING_MODE_ROUND_ROBIN,
+
+ .nb_rx_q = 1,
+ .nb_tx_q = 1,
+
+ .mbuf_pool = NULL,
+
+ .default_slave_mac = (struct rte_ether_addr *)slave_mac,
+ .default_bonded_mac = (struct rte_ether_addr *)bonded_mac,
+
+ .pkt_eth_hdr = NULL,
+ .pkt_ipv4_hdr = &pkt_ipv4_hdr,
+ .pkt_ipv6_hdr = &pkt_ipv6_hdr,
+ .pkt_udp_hdr = &pkt_udp_hdr
+
+};
+
+static struct link_bonding_unittest_params *test_params = &default_params;
+
+static uint8_t src_mac[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+static uint8_t dst_mac_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+static uint8_t dst_mac_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAB };
+
+static uint32_t src_addr = IPV4_ADDR(192, 168, 1, 98);
+static uint32_t dst_addr_0 = IPV4_ADDR(192, 168, 1, 98);
+static uint32_t dst_addr_1 = IPV4_ADDR(193, 166, 10, 97);
+
+static uint8_t src_ipv6_addr[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
+ 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA };
+static uint8_t dst_ipv6_addr_0[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
+ 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA, 0xFF, 0xAA };
+static uint8_t dst_ipv6_addr_1[] = { 0xFF, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF,
+ 0xAA, 0xFF, 0xAA, 0xFF, 0xAA , 0xFF, 0xAA , 0xFF, 0xAB };
+
+static uint16_t src_port = 1024;
+static uint16_t dst_port_0 = 1024;
+static uint16_t dst_port_1 = 2024;
+
+static uint16_t vlan_id = 0x100;
+
+static struct rte_eth_conf default_pmd_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .split_hdr_size = 0,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ .lpbk_mode = 0,
+};
+
+static const struct rte_eth_rxconf rx_conf_default = {
+ .rx_thresh = {
+ .pthresh = RX_PTHRESH,
+ .hthresh = RX_HTHRESH,
+ .wthresh = RX_WTHRESH,
+ },
+ .rx_free_thresh = RX_FREE_THRESH,
+ .rx_drop_en = 0,
+};
+
+static struct rte_eth_txconf tx_conf_default = {
+ .tx_thresh = {
+ .pthresh = TX_PTHRESH,
+ .hthresh = TX_HTHRESH,
+ .wthresh = TX_WTHRESH,
+ },
+ .tx_free_thresh = TX_FREE_THRESH,
+ .tx_rs_thresh = TX_RSBIT_THRESH,
+};
+
+static void free_virtualpmd_tx_queue(void);
+
+
+
+static int
+configure_ethdev(uint16_t port_id, uint8_t start, uint8_t en_isr)
+{
+ int q_id;
+
+ if (en_isr)
+ default_pmd_conf.intr_conf.lsc = 1;
+ else
+ default_pmd_conf.intr_conf.lsc = 0;
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_configure(port_id, test_params->nb_rx_q,
+ test_params->nb_tx_q, &default_pmd_conf),
+ "rte_eth_dev_configure for port %d failed", port_id);
+
+ for (q_id = 0; q_id < test_params->nb_rx_q; q_id++)
+ TEST_ASSERT_SUCCESS(rte_eth_rx_queue_setup(port_id, q_id, RX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), &rx_conf_default,
+ test_params->mbuf_pool) ,
+ "rte_eth_rx_queue_setup for port %d failed", port_id);
+
+ for (q_id = 0; q_id < test_params->nb_tx_q; q_id++)
+ TEST_ASSERT_SUCCESS(rte_eth_tx_queue_setup(port_id, q_id, TX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), &tx_conf_default),
+ "rte_eth_tx_queue_setup for port %d failed", port_id);
+
+ if (start)
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(port_id),
+ "rte_eth_dev_start for port %d failed", port_id);
+
+ return 0;
+}
+
+static int slaves_initialized;
+static int mac_slaves_initialized;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cvar = PTHREAD_COND_INITIALIZER;
+
+
+static int
+test_setup(void)
+{
+ int i, nb_mbuf_per_pool;
+ struct rte_ether_addr *mac_addr = (struct rte_ether_addr *)slave_mac;
+
+ /* Allocate ethernet packet header with space for VLAN header */
+ if (test_params->pkt_eth_hdr == NULL) {
+ test_params->pkt_eth_hdr = malloc(sizeof(struct rte_ether_hdr) +
+ sizeof(struct rte_vlan_hdr));
+
+ TEST_ASSERT_NOT_NULL(test_params->pkt_eth_hdr,
+ "Ethernet header struct allocation failed!");
+ }
+
+ nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + DEF_PKT_BURST +
+ RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST;
+ if (test_params->mbuf_pool == NULL) {
+ test_params->mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",
+ nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ TEST_ASSERT_NOT_NULL(test_params->mbuf_pool,
+ "rte_mempool_create failed");
+ }
+
+ /* Create / Initialize virtual eth devs */
+ if (!slaves_initialized) {
+ for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++) {
+ char pmd_name[RTE_ETH_NAME_MAX_LEN];
+
+ mac_addr->addr_bytes[RTE_ETHER_ADDR_LEN-1] = i;
+
+ snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_%d", i);
+
+ test_params->slave_port_ids[i] = virtual_ethdev_create(pmd_name,
+ mac_addr, rte_socket_id(), 1);
+ TEST_ASSERT(test_params->slave_port_ids[i] >= 0,
+ "Failed to create virtual virtual ethdev %s", pmd_name);
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(
+ test_params->slave_port_ids[i], 1, 0),
+ "Failed to configure virtual ethdev %s", pmd_name);
+ }
+ slaves_initialized = 1;
+ }
+
+ return 0;
+}
+
+static int
+test_create_bonded_device(void)
+{
+ int current_slave_count;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ /* Don't try to recreate bonded device if re-running test suite*/
+ if (test_params->bonded_port_id == -1) {
+ test_params->bonded_port_id = rte_eth_bond_create(BONDED_DEV_NAME,
+ test_params->bonding_mode, rte_socket_id());
+
+ TEST_ASSERT(test_params->bonded_port_id >= 0,
+ "Failed to create bonded ethdev %s", BONDED_DEV_NAME);
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
+ "Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
+ }
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
+ test_params->bonding_mode), "Failed to set ethdev %d to mode %d",
+ test_params->bonded_port_id, test_params->bonding_mode);
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(current_slave_count, 0,
+ "Number of slaves %d is great than expected %d.",
+ current_slave_count, 0);
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(current_slave_count, 0,
+ "Number of active slaves %d is great than expected %d.",
+ current_slave_count, 0);
+
+ return 0;
+}
+
+
+static int
+test_create_bonded_device_with_invalid_params(void)
+{
+ int port_id;
+
+ test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
+
+ /* Invalid name */
+ port_id = rte_eth_bond_create(NULL, test_params->bonding_mode,
+ rte_socket_id());
+ TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly");
+
+ test_params->bonding_mode = INVALID_BONDING_MODE;
+
+ /* Invalid bonding mode */
+ port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
+ rte_socket_id());
+ TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly.");
+
+ test_params->bonding_mode = BONDING_MODE_ROUND_ROBIN;
+
+ /* Invalid socket id */
+ port_id = rte_eth_bond_create(BONDED_DEV_NAME, test_params->bonding_mode,
+ INVALID_SOCKET_ID);
+ TEST_ASSERT(port_id < 0, "Created bonded device unexpectedly.");
+
+ return 0;
+}
+
+static int
+test_add_slave_to_bonded_device(void)
+{
+ int current_slave_count;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
+ test_params->slave_port_ids[test_params->bonded_slave_count]),
+ "Failed to add slave (%d) to bonded port (%d).",
+ test_params->slave_port_ids[test_params->bonded_slave_count],
+ test_params->bonded_port_id);
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count + 1,
+ "Number of slaves (%d) is greater than expected (%d).",
+ current_slave_count, test_params->bonded_slave_count + 1);
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, 0,
+ "Number of active slaves (%d) is not as expected (%d).\n",
+ current_slave_count, 0);
+
+ test_params->bonded_slave_count++;
+
+ return 0;
+}
+
+static int
+test_add_slave_to_invalid_bonded_device(void)
+{
+ /* Invalid port ID */
+ TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->bonded_port_id + 5,
+ test_params->slave_port_ids[test_params->bonded_slave_count]),
+ "Expected call to failed as invalid port specified.");
+
+ /* Non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_slave_add(test_params->slave_port_ids[0],
+ test_params->slave_port_ids[test_params->bonded_slave_count]),
+ "Expected call to failed as invalid port specified.");
+
+ return 0;
+}
+
+
+static int
+test_remove_slave_from_bonded_device(void)
+{
+ int current_slave_count;
+ struct rte_ether_addr read_mac_addr, *mac_addr;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params->bonded_port_id,
+ test_params->slave_port_ids[test_params->bonded_slave_count-1]),
+ "Failed to remove slave %d from bonded port (%d).",
+ test_params->slave_port_ids[test_params->bonded_slave_count-1],
+ test_params->bonded_port_id);
+
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count - 1,
+ "Number of slaves (%d) is great than expected (%d).\n",
+ current_slave_count, test_params->bonded_slave_count - 1);
+
+
+ mac_addr = (struct rte_ether_addr *)slave_mac;
+ mac_addr->addr_bytes[RTE_ETHER_ADDR_LEN-1] =
+ test_params->bonded_slave_count-1;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(
+ test_params->slave_port_ids[test_params->bonded_slave_count-1],
+ &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[test_params->bonded_slave_count-1]);
+ TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)),
+ "bonded port mac address not set to that of primary port\n");
+
+ rte_eth_stats_reset(
+ test_params->slave_port_ids[test_params->bonded_slave_count-1]);
+
+ virtual_ethdev_simulate_link_status_interrupt(test_params->bonded_port_id,
+ 0);
+
+ test_params->bonded_slave_count--;
+
+ return 0;
+}
+
+static int
+test_remove_slave_from_invalid_bonded_device(void)
+{
+ /* Invalid port ID */
+ TEST_ASSERT_FAIL(rte_eth_bond_slave_remove(
+ test_params->bonded_port_id + 5,
+ test_params->slave_port_ids[test_params->bonded_slave_count - 1]),
+ "Expected call to failed as invalid port specified.");
+
+ /* Non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_slave_remove(
+ test_params->slave_port_ids[0],
+ test_params->slave_port_ids[test_params->bonded_slave_count - 1]),
+ "Expected call to failed as invalid port specified.");
+
+ return 0;
+}
+
+static int bonded_id = 2;
+
+static int
+test_add_already_bonded_slave_to_bonded_device(void)
+{
+ int port_id, current_slave_count;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+ char pmd_name[RTE_ETH_NAME_MAX_LEN];
+
+ test_add_slave_to_bonded_device();
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, 1,
+ "Number of slaves (%d) is not that expected (%d).",
+ current_slave_count, 1);
+
+ snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN, "%s_%d", BONDED_DEV_NAME, ++bonded_id);
+
+ port_id = rte_eth_bond_create(pmd_name, test_params->bonding_mode,
+ rte_socket_id());
+ TEST_ASSERT(port_id >= 0, "Failed to create bonded device.");
+
+ TEST_ASSERT(rte_eth_bond_slave_add(port_id,
+ test_params->slave_port_ids[test_params->bonded_slave_count - 1])
+ < 0,
+ "Added slave (%d) to bonded port (%d) unexpectedly.",
+ test_params->slave_port_ids[test_params->bonded_slave_count-1],
+ port_id);
+
+ return test_remove_slave_from_bonded_device();
+}
+
+
+static int
+test_get_slaves_from_bonded_device(void)
+{
+ int current_slave_count;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave to bonded device");
+
+ /* Invalid port id */
+ current_slave_count = rte_eth_bond_slaves_get(INVALID_PORT_ID, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid port id unexpectedly succeeded");
+
+ current_slave_count = rte_eth_bond_active_slaves_get(INVALID_PORT_ID,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid port id unexpectedly succeeded");
+
+ /* Invalid slaves pointer */
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ NULL, RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid slave array unexpectedly succeeded");
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, NULL, RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid slave array unexpectedly succeeded");
+
+ /* non bonded device*/
+ current_slave_count = rte_eth_bond_slaves_get(
+ test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid port id unexpectedly succeeded");
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->slave_port_ids[0], NULL, RTE_MAX_ETHPORTS);
+ TEST_ASSERT(current_slave_count < 0,
+ "Invalid port id unexpectedly succeeded");
+
+ TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
+ "Failed to remove slaves from bonded device");
+
+ return 0;
+}
+
+
+static int
+test_add_remove_multiple_slaves_to_from_bonded_device(void)
+{
+ int i;
+
+ for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++)
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave to bonded device");
+
+ for (i = 0; i < TEST_MAX_NUMBER_OF_PORTS; i++)
+ TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
+ "Failed to remove slaves from bonded device");
+
+ return 0;
+}
+
+static void
+enable_bonded_slaves(void)
+{
+ int i;
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ virtual_ethdev_tx_burst_fn_set_success(test_params->slave_port_ids[i],
+ 1);
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 1);
+ }
+}
+
+static int
+test_start_bonded_device(void)
+{
+ struct rte_eth_link link_status;
+
+ int current_slave_count, current_bonding_mode, primary_port;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+ int retval;
+
+ /* Add slave to bonded device*/
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave to bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded pmd eth device %d.",
+ test_params->bonded_port_id);
+
+ /* Change link status of virtual pmd so it will be added to the active
+ * slave list of the bonded device*/
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[test_params->bonded_slave_count-1], 1);
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
+ "Number of slaves (%d) is not expected value (%d).",
+ current_slave_count, test_params->bonded_slave_count);
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
+ "Number of active slaves (%d) is not expected value (%d).",
+ current_slave_count, test_params->bonded_slave_count);
+
+ current_bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(current_bonding_mode, test_params->bonding_mode,
+ "Bonded device mode (%d) is not expected value (%d).\n",
+ current_bonding_mode, test_params->bonding_mode);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0],
+ "Primary port (%d) is not expected value (%d).",
+ primary_port, test_params->slave_port_ids[0]);
+
+ retval = rte_eth_link_get(test_params->bonded_port_id, &link_status);
+ TEST_ASSERT(retval >= 0,
+ "Bonded port (%d) link get failed: %s\n",
+ test_params->bonded_port_id, rte_strerror(-retval));
+ TEST_ASSERT_EQUAL(link_status.link_status, 1,
+ "Bonded port (%d) status (%d) is not expected value (%d).\n",
+ test_params->bonded_port_id, link_status.link_status, 1);
+
+ return 0;
+}
+
+static int
+test_stop_bonded_device(void)
+{
+ int current_slave_count;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ struct rte_eth_link link_status;
+ int retval;
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ retval = rte_eth_link_get(test_params->bonded_port_id, &link_status);
+ TEST_ASSERT(retval >= 0,
+ "Bonded port (%d) link get failed: %s\n",
+ test_params->bonded_port_id, rte_strerror(-retval));
+ TEST_ASSERT_EQUAL(link_status.link_status, 0,
+ "Bonded port (%d) status (%d) is not expected value (%d).",
+ test_params->bonded_port_id, link_status.link_status, 0);
+
+ current_slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, test_params->bonded_slave_count,
+ "Number of slaves (%d) is not expected value (%d).",
+ current_slave_count, test_params->bonded_slave_count);
+
+ current_slave_count = rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(current_slave_count, 0,
+ "Number of active slaves (%d) is not expected value (%d).",
+ current_slave_count, 0);
+
+ return 0;
+}
+
+static int
+remove_slaves_and_stop_bonded_device(void)
+{
+ /* Clean up and remove slaves from bonded device */
+ free_virtualpmd_tx_queue();
+ while (test_params->bonded_slave_count > 0)
+ TEST_ASSERT_SUCCESS(test_remove_slave_from_bonded_device(),
+ "test_remove_slave_from_bonded_device failed");
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+ rte_eth_stats_reset(test_params->bonded_port_id);
+ rte_eth_bond_mac_address_reset(test_params->bonded_port_id);
+
+ return 0;
+}
+
+static int
+test_set_bonding_mode(void)
+{
+ int i, bonding_mode;
+
+ int bonding_modes[] = { BONDING_MODE_ROUND_ROBIN,
+ BONDING_MODE_ACTIVE_BACKUP,
+ BONDING_MODE_BALANCE,
+ BONDING_MODE_BROADCAST
+ };
+
+ /* Test supported link bonding modes */
+ for (i = 0; i < (int)RTE_DIM(bonding_modes); i++) {
+ /* Invalid port ID */
+ TEST_ASSERT_FAIL(rte_eth_bond_mode_set(INVALID_PORT_ID,
+ bonding_modes[i]),
+ "Expected call to failed as invalid port (%d) specified.",
+ INVALID_PORT_ID);
+
+ /* Non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_mode_set(test_params->slave_port_ids[0],
+ bonding_modes[i]),
+ "Expected call to failed as invalid port (%d) specified.",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
+ bonding_modes[i]),
+ "Failed to set link bonding mode on port (%d) to (%d).",
+ test_params->bonded_port_id, bonding_modes[i]);
+
+ bonding_mode = rte_eth_bond_mode_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(bonding_mode, bonding_modes[i],
+ "Link bonding mode (%d) of port (%d) is not expected value (%d).",
+ bonding_mode, test_params->bonded_port_id,
+ bonding_modes[i]);
+
+ /* Invalid port ID */
+ bonding_mode = rte_eth_bond_mode_get(INVALID_PORT_ID);
+ TEST_ASSERT(bonding_mode < 0,
+ "Expected call to failed as invalid port (%d) specified.",
+ INVALID_PORT_ID);
+
+ /* Non bonded device */
+ bonding_mode = rte_eth_bond_mode_get(test_params->slave_port_ids[0]);
+ TEST_ASSERT(bonding_mode < 0,
+ "Expected call to failed as invalid port (%d) specified.",
+ test_params->slave_port_ids[0]);
+ }
+
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_set_primary_slave(void)
+{
+ int i, j, retval;
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr *expected_mac_addr;
+
+ /* Add 4 slaves to bonded device */
+ for (i = test_params->bonded_slave_count; i < 4; i++)
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave to bonded device.");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
+ BONDING_MODE_ROUND_ROBIN),
+ "Failed to set link bonding mode on port (%d) to (%d).",
+ test_params->bonded_port_id, BONDING_MODE_ROUND_ROBIN);
+
+ /* Invalid port ID */
+ TEST_ASSERT_FAIL(rte_eth_bond_primary_set(INVALID_PORT_ID,
+ test_params->slave_port_ids[i]),
+ "Expected call to failed as invalid port specified.");
+
+ /* Non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_primary_set(test_params->slave_port_ids[i],
+ test_params->slave_port_ids[i]),
+ "Expected call to failed as invalid port specified.");
+
+ /* Set slave as primary
+ * Verify slave it is now primary slave
+ * Verify that MAC address of bonded device is that of primary slave
+ * Verify that MAC address of all bonded slaves are that of primary slave
+ */
+ for (i = 0; i < 4; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[i]),
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[i]);
+
+ retval = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT(retval >= 0,
+ "Failed to read primary port from bonded port (%d)\n",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_EQUAL(retval, test_params->slave_port_ids[i],
+ "Bonded port (%d) primary port (%d) not expected value (%d)\n",
+ test_params->bonded_port_id, retval,
+ test_params->slave_port_ids[i]);
+
+ /* stop/start bonded eth dev to apply new MAC */
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded port %d",
+ test_params->bonded_port_id);
+
+ expected_mac_addr = (struct rte_ether_addr *)&slave_mac;
+ expected_mac_addr->addr_bytes[RTE_ETHER_ADDR_LEN-1] = i;
+
+ /* Check primary slave MAC */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port mac address not set to that of primary port\n");
+
+ /* Check bonded MAC */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&read_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port mac address not set to that of primary port\n");
+
+ /* Check other slaves MACs */
+ for (j = 0; j < 4; j++) {
+ if (j != i) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[j],
+ &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[j]);
+ TEST_ASSERT_SUCCESS(memcmp(expected_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port mac address not set to that of primary "
+ "port");
+ }
+ }
+ }
+
+
+ /* Test with none existent port */
+ TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->bonded_port_id + 10),
+ "read primary port from expectedly");
+
+ /* Test with slave port */
+ TEST_ASSERT_FAIL(rte_eth_bond_primary_get(test_params->slave_port_ids[0]),
+ "read primary port from expectedly\n");
+
+ TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
+ "Failed to stop and remove slaves from bonded device");
+
+ /* No slaves */
+ TEST_ASSERT(rte_eth_bond_primary_get(test_params->bonded_port_id) < 0,
+ "read primary port from expectedly\n");
+
+ return 0;
+}
+
+static int
+test_set_explicit_bonded_mac(void)
+{
+ int i;
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr *mac_addr;
+
+ uint8_t explicit_bonded_mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x01 };
+
+ mac_addr = (struct rte_ether_addr *)explicit_bonded_mac;
+
+ /* Invalid port ID */
+ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(INVALID_PORT_ID, mac_addr),
+ "Expected call to failed as invalid port specified.");
+
+ /* Non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(
+ test_params->slave_port_ids[0], mac_addr),
+ "Expected call to failed as invalid port specified.");
+
+ /* NULL MAC address */
+ TEST_ASSERT_FAIL(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id, NULL),
+ "Expected call to failed as NULL MAC specified");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id, mac_addr),
+ "Failed to set MAC address on bonded port (%d)",
+ test_params->bonded_port_id);
+
+ /* Add 4 slaves to bonded device */
+ for (i = test_params->bonded_slave_count; i < 4; i++) {
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave to bonded device.\n");
+ }
+
+ /* Check bonded MAC */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr, sizeof(read_mac_addr)),
+ "bonded port mac address not set to that of primary port");
+
+ /* Check other slaves MACs */
+ for (i = 0; i < 4; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port mac address not set to that of primary port");
+ }
+
+ /* test resetting mac address on bonded device */
+ TEST_ASSERT_SUCCESS(
+ rte_eth_bond_mac_address_reset(test_params->bonded_port_id),
+ "Failed to reset MAC address on bonded port (%d)",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_FAIL(
+ rte_eth_bond_mac_address_reset(test_params->slave_port_ids[0]),
+ "Reset MAC address on bonded port (%d) unexpectedly",
+ test_params->slave_port_ids[1]);
+
+ /* test resetting mac address on bonded device with no slaves */
+ TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
+ "Failed to remove slaves and stop bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_reset(test_params->bonded_port_id),
+ "Failed to reset MAC address on bonded port (%d)",
+ test_params->bonded_port_id);
+
+ return 0;
+}
+
+#define BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT (3)
+
+static int
+test_set_bonded_port_initialization_mac_assignment(void)
+{
+ int i, slave_count;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+ static int bonded_port_id = -1;
+ static int slave_port_ids[BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT];
+
+ struct rte_ether_addr slave_mac_addr, bonded_mac_addr, read_mac_addr;
+
+ /* Initialize default values for MAC addresses */
+ memcpy(&slave_mac_addr, slave_mac, sizeof(struct rte_ether_addr));
+ memcpy(&bonded_mac_addr, slave_mac, sizeof(struct rte_ether_addr));
+
+ /*
+ * 1. a - Create / configure bonded / slave ethdevs
+ */
+ if (bonded_port_id == -1) {
+ bonded_port_id = rte_eth_bond_create("net_bonding_mac_ass_test",
+ BONDING_MODE_ACTIVE_BACKUP, rte_socket_id());
+ TEST_ASSERT(bonded_port_id > 0, "failed to create bonded device");
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(bonded_port_id, 0, 0),
+ "Failed to configure bonded ethdev");
+ }
+
+ if (!mac_slaves_initialized) {
+ for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) {
+ char pmd_name[RTE_ETH_NAME_MAX_LEN];
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] =
+ i + 100;
+
+ snprintf(pmd_name, RTE_ETH_NAME_MAX_LEN,
+ "eth_slave_%d", i);
+
+ slave_port_ids[i] = virtual_ethdev_create(pmd_name,
+ &slave_mac_addr, rte_socket_id(), 1);
+
+ TEST_ASSERT(slave_port_ids[i] >= 0,
+ "Failed to create slave ethdev %s",
+ pmd_name);
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(slave_port_ids[i], 1, 0),
+ "Failed to configure virtual ethdev %s",
+ pmd_name);
+ }
+ mac_slaves_initialized = 1;
+ }
+
+
+ /*
+ * 2. Add slave ethdevs to bonded device
+ */
+ for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(bonded_port_id,
+ slave_port_ids[i]),
+ "Failed to add slave (%d) to bonded port (%d).",
+ slave_port_ids[i], bonded_port_id);
+ }
+
+ slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT, slave_count,
+ "Number of slaves (%d) is not as expected (%d)",
+ slave_count, BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT);
+
+
+ /*
+ * 3. Set explicit MAC address on bonded ethdev
+ */
+ bonded_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-2] = 0xFF;
+ bonded_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 0xAA;
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ bonded_port_id, &bonded_mac_addr),
+ "Failed to set MAC address on bonded port (%d)",
+ bonded_port_id);
+
+
+ /* 4. a - Start bonded ethdev
+ * b - Enable slave devices
+ * c - Verify bonded/slaves ethdev MAC addresses
+ */
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id),
+ "Failed to start bonded pmd eth device %d.",
+ bonded_port_id);
+
+ for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) {
+ virtual_ethdev_simulate_link_status_interrupt(
+ slave_port_ids[i], 1);
+ }
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port mac address not as expected");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 0 mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 1 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 1 mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 2 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[2]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 2 mac address not as expected");
+
+
+ /* 7. a - Change primary port
+ * b - Stop / Start bonded port
+ * d - Verify slave ethdev MAC addresses
+ */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(bonded_port_id,
+ slave_port_ids[2]),
+ "failed to set primary port on bonded device.");
+
+ rte_eth_dev_stop(bonded_port_id);
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(bonded_port_id),
+ "Failed to start bonded pmd eth device %d.",
+ bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 0 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 0 mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 1 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 1 mac address not as expected");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[2]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 2 mac address not as expected");
+
+ /* 6. a - Stop bonded ethdev
+ * b - remove slave ethdevs
+ * c - Verify slave ethdevs MACs are restored
+ */
+ rte_eth_dev_stop(bonded_port_id);
+
+ for (i = 0; i < BONDED_INIT_MAC_ASSIGNMENT_SLAVE_COUNT; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(bonded_port_id,
+ slave_port_ids[i]),
+ "Failed to remove slave %d from bonded port (%d).",
+ slave_port_ids[i], bonded_port_id);
+ }
+
+ slave_count = rte_eth_bond_slaves_get(bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(slave_count, 0,
+ "Number of slaves (%d) is great than expected (%d).",
+ slave_count, 0);
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 0 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 0 mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 1 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 1 mac address not as expected");
+
+ slave_mac_addr.addr_bytes[RTE_ETHER_ADDR_LEN-1] = 2 + 100;
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(slave_port_ids[2], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ slave_port_ids[2]);
+ TEST_ASSERT_SUCCESS(memcmp(&slave_mac_addr, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port 2 mac address not as expected");
+
+ return 0;
+}
+
+
+static int
+initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr,
+ uint16_t number_of_slaves, uint8_t enable_slave)
+{
+ /* Configure bonded device */
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
+ bond_en_isr), "Failed to configure bonding port (%d) in mode %d "
+ "with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
+ number_of_slaves);
+
+ /* Add slaves to bonded device */
+ while (number_of_slaves > test_params->bonded_slave_count)
+ TEST_ASSERT_SUCCESS(test_add_slave_to_bonded_device(),
+ "Failed to add slave (%d to bonding port (%d).",
+ test_params->bonded_slave_count - 1,
+ test_params->bonded_port_id);
+
+ /* Set link bonding mode */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mode_set(test_params->bonded_port_id,
+ bonding_mode),
+ "Failed to set link bonding mode on port (%d) to (%d).",
+ test_params->bonded_port_id, bonding_mode);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded pmd eth device %d.",
+ test_params->bonded_port_id);
+
+ if (enable_slave)
+ enable_bonded_slaves();
+
+ return 0;
+}
+
+static int
+test_adding_slave_after_bonded_device_started(void)
+{
+ int i;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 4, 0),
+ "Failed to add slaves to bonded device");
+
+ /* Enabled slave devices */
+ for (i = 0; i < test_params->bonded_slave_count + 1; i++) {
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 1);
+ }
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
+ test_params->slave_port_ids[test_params->bonded_slave_count]),
+ "Failed to add slave to bonded port.\n");
+
+ rte_eth_stats_reset(
+ test_params->slave_port_ids[test_params->bonded_slave_count]);
+
+ test_params->bonded_slave_count++;
+
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_STATUS_INTERRUPT_SLAVE_COUNT 4
+#define TEST_LSC_WAIT_TIMEOUT_US 500000
+
+int test_lsc_interrupt_count;
+
+
+static int
+test_bonding_lsc_event_callback(uint16_t port_id __rte_unused,
+ enum rte_eth_event_type type __rte_unused,
+ void *param __rte_unused,
+ void *ret_param __rte_unused)
+{
+ pthread_mutex_lock(&mutex);
+ test_lsc_interrupt_count++;
+
+ pthread_cond_signal(&cvar);
+ pthread_mutex_unlock(&mutex);
+
+ return 0;
+}
+
+static inline int
+lsc_timeout(int wait_us)
+{
+ int retval = 0;
+
+ struct timespec ts;
+ struct timeval tp;
+
+ gettimeofday(&tp, NULL);
+
+ /* Convert from timeval to timespec */
+ ts.tv_sec = tp.tv_sec;
+ ts.tv_nsec = tp.tv_usec * 1000;
+ ts.tv_nsec += wait_us * 1000;
+ /* Normalize tv_nsec to [0,999999999L] */
+ while (ts.tv_nsec > 1000000000L) {
+ ts.tv_nsec -= 1000000000L;
+ ts.tv_sec += 1;
+ }
+
+ pthread_mutex_lock(&mutex);
+ if (test_lsc_interrupt_count < 1)
+ retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
+
+ pthread_mutex_unlock(&mutex);
+
+ if (retval == 0 && test_lsc_interrupt_count < 1)
+ return -1;
+
+ return retval;
+}
+
+static int
+test_status_interrupt(void)
+{
+ int slave_count;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ /* initialized bonding device with T slaves */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 1,
+ TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1),
+ "Failed to initialise bonded device");
+
+ test_lsc_interrupt_count = 0;
+
+ /* register link status change interrupt callback */
+ rte_eth_dev_callback_register(test_params->bonded_port_id,
+ RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+ &test_params->bonded_port_id);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT,
+ "Number of active slaves (%d) is not as expected (%d)",
+ slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT);
+
+ /* Bring all 4 slaves link status to down and test that we have received a
+ * lsc interrupts */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[2], 0);
+
+ TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
+ "Received a link status change interrupt unexpectedly");
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_US) == 0,
+ "timed out waiting for interrupt");
+
+ TEST_ASSERT(test_lsc_interrupt_count > 0,
+ "Did not receive link status change interrupt");
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+
+ TEST_ASSERT_EQUAL(slave_count, 0,
+ "Number of active slaves (%d) is not as expected (%d)",
+ slave_count, 0);
+
+ /* bring one slave port up so link status will change */
+ test_lsc_interrupt_count = 0;
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 1);
+
+ TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_US) == 0,
+ "timed out waiting for interrupt");
+
+ /* test that we have received another lsc interrupt */
+ TEST_ASSERT(test_lsc_interrupt_count > 0,
+ "Did not receive link status change interrupt");
+
+ /* Verify that calling the same slave lsc interrupt doesn't cause another
+ * lsc interrupt from bonded device */
+ test_lsc_interrupt_count = 0;
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 1);
+
+ TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_US) != 0,
+ "received unexpected interrupt");
+
+ TEST_ASSERT_EQUAL(test_lsc_interrupt_count, 0,
+ "Did not receive link status change interrupt");
+
+
+ /* unregister lsc callback before exiting */
+ rte_eth_dev_callback_unregister(test_params->bonded_port_id,
+ RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+ &test_params->bonded_port_id);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size,
+ uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac,
+ uint8_t toggle_ip_addr, uint16_t toggle_udp_port)
+{
+ uint16_t pktlen, generated_burst_size, ether_type;
+ void *ip_hdr;
+
+ if (ipv4)
+ ether_type = RTE_ETHER_TYPE_IPV4;
+ else
+ ether_type = RTE_ETHER_TYPE_IPV6;
+
+ if (toggle_dst_mac)
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_1,
+ ether_type, vlan, vlan_id);
+ else
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ ether_type, vlan, vlan_id);
+
+
+ if (toggle_udp_port)
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_1, 64);
+ else
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_0, 64);
+
+ if (ipv4) {
+ if (toggle_ip_addr)
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_1, pktlen);
+ else
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_0, pktlen);
+
+ ip_hdr = test_params->pkt_ipv4_hdr;
+ } else {
+ if (toggle_ip_addr)
+ pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
+ (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_1,
+ pktlen);
+ else
+ pktlen = initialize_ipv6_header(test_params->pkt_ipv6_hdr,
+ (uint8_t *)src_ipv6_addr, (uint8_t *)dst_ipv6_addr_0,
+ pktlen);
+
+ ip_hdr = test_params->pkt_ipv6_hdr;
+ }
+
+ /* Generate burst of packets to transmit */
+ generated_burst_size = generate_packet_burst(test_params->mbuf_pool,
+ pkts_burst, test_params->pkt_eth_hdr, vlan, ip_hdr, ipv4,
+ test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN_128,
+ 1);
+ TEST_ASSERT_EQUAL(generated_burst_size, burst_size,
+ "Failed to generate packet burst");
+
+ return generated_burst_size;
+}
+
+/** Round Robin Mode Tests */
+
+static int
+test_roundrobin_tx_burst(void)
+{
+ int i, burst_size;
+ struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 2, 1),
+ "Failed to initialise bonded device");
+
+ burst_size = 20 * test_params->bonded_slave_count;
+
+ TEST_ASSERT(burst_size <= MAX_PKT_BURST,
+ "Burst size specified is greater than supported.");
+
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0),
+ burst_size, "failed to generate test burst");
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, pkt_burst, burst_size), burst_size,
+ "tx burst failed");
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ burst_size);
+
+ /* Verify slave ports tx stats */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)burst_size / test_params->bonded_slave_count,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)\n",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ burst_size / test_params->bonded_slave_count);
+ }
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
+ pkt_burst, burst_size), 0,
+ "tx burst return unexpected value");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
+{
+ int i, refcnt;
+
+ for (i = 0; i < nb_mbufs; i++) {
+ refcnt = rte_mbuf_refcnt_read(mbufs[i]);
+ TEST_ASSERT_EQUAL(refcnt, val,
+ "mbuf ref count (%d)is not the expected value (%d)",
+ refcnt, val);
+ }
+ return 0;
+}
+
+static void
+free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)
+{
+ int i;
+
+ for (i = 0; i < nb_mbufs; i++)
+ rte_pktmbuf_free(mbufs[i]);
+}
+
+#define TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT (2)
+#define TEST_RR_SLAVE_TX_FAIL_BURST_SIZE (64)
+#define TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT (22)
+#define TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (1)
+
+static int
+test_roundrobin_tx_burst_slave_tx_fail(void)
+{
+ struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
+ struct rte_mbuf *expected_tx_fail_pkts[MAX_PKT_BURST];
+
+ struct rte_eth_stats port_stats;
+
+ int i, first_fail_idx, tx_count;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0,
+ TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
+ "Failed to initialise bonded device");
+
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(pkt_burst,
+ TEST_RR_SLAVE_TX_FAIL_BURST_SIZE, 0, 1, 0, 0, 0),
+ TEST_RR_SLAVE_TX_FAIL_BURST_SIZE,
+ "Failed to generate test packet burst");
+
+ /* Copy references to packets which we expect not to be transmitted */
+ first_fail_idx = (TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
+ (TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT *
+ TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)) +
+ TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX;
+
+ for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
+ expected_tx_fail_pkts[i] = pkt_burst[first_fail_idx +
+ (i * TEST_RR_SLAVE_TX_FAIL_SLAVE_COUNT)];
+ }
+
+ /* Set virtual slave to only fail transmission of
+ * TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT packets in burst */
+ virtual_ethdev_tx_burst_fn_set_success(
+ test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
+ 0);
+
+ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
+ test_params->slave_port_ids[TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
+ TEST_RR_SLAVE_TX_FAIL_BURST_SIZE);
+
+ TEST_ASSERT_EQUAL(tx_count, TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
+ "Transmitted (%d) an unexpected (%d) number of packets", tx_count,
+ TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ /* Verify that failed packet are expected failed packets */
+ for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
+ TEST_ASSERT_EQUAL(expected_tx_fail_pkts[i], pkt_burst[i + tx_count],
+ "expected mbuf (%d) pointer %p not expected pointer %p",
+ i, expected_tx_fail_pkts[i], pkt_burst[i + tx_count]);
+ }
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT,
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ TEST_RR_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ /* Verify slave ports tx stats */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ int slave_expected_tx_count;
+
+ rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
+
+ slave_expected_tx_count = TEST_RR_SLAVE_TX_FAIL_BURST_SIZE /
+ test_params->bonded_slave_count;
+
+ if (i == TEST_RR_SLAVE_TX_FAIL_FAILING_SLAVE_IDX)
+ slave_expected_tx_count = slave_expected_tx_count -
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT;
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)slave_expected_tx_count,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[i],
+ (unsigned int)port_stats.opackets, slave_expected_tx_count);
+ }
+
+ /* Verify that all mbufs have a ref value of zero */
+ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkt_burst[tx_count],
+ TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
+ "mbufs refcnts not as expected");
+ free_mbufs(&pkt_burst[tx_count], TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_roundrobin_rx_burst_on_single_slave(void)
+{
+ struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+
+ struct rte_eth_stats port_stats;
+
+ int i, j, burst_size = 25;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ gen_pkt_burst, burst_size, 0, 1, 0, 0, 0), burst_size,
+ "burst generation failed");
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ /* Add rx data to slave */
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[0], burst_size);
+
+ /* Call rx burst on bonded device */
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst,
+ MAX_PKT_BURST), burst_size,
+ "round-robin rx burst failed");
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.ipackets, burst_size);
+
+
+
+ /* Verify bonded slave devices rx count */
+ /* Verify slave ports tx stats */
+ for (j = 0; j < test_params->bonded_slave_count; j++) {
+ rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
+
+ if (i == j) {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Slave Port (%d) ipackets value (%u) not as expected"
+ " (%d)", test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, burst_size);
+ } else {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as expected"
+ " (%d)", test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, 0);
+ }
+
+ /* Reset bonded slaves stats */
+ rte_eth_stats_reset(test_params->slave_port_ids[j]);
+ }
+ /* reset bonded device stats */
+ rte_eth_stats_reset(test_params->bonded_port_id);
+ }
+
+ /* free mbufs */
+ for (i = 0; i < MAX_PKT_BURST; i++) {
+ if (rx_pkt_burst[i] != NULL)
+ rte_pktmbuf_free(rx_pkt_burst[i]);
+ }
+
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT (3)
+
+static int
+test_roundrobin_rx_burst_on_multiple_slaves(void)
+{
+ struct rte_mbuf *gen_pkt_burst[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
+
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ int burst_size[TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT] = { 15, 13, 36 };
+ int i, nb_rx;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Generate test bursts of packets to transmit */
+ for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[i][0], burst_size[i], 0, 1, 0, 0, 0),
+ burst_size[i], "burst generation failed");
+ }
+
+ /* Add rx data to slaves */
+ for (i = 0; i < TEST_ROUNDROBIN_TX_BURST_SLAVE_COUNT; i++) {
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[i][0], burst_size[i]);
+ }
+
+ /* Call rx burst on bonded device */
+ /* Send burst on bonded port */
+ nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
+ MAX_PKT_BURST);
+ TEST_ASSERT_EQUAL(nb_rx , burst_size[0] + burst_size[1] + burst_size[2],
+ "round-robin rx burst failed (%d != %d)\n", nb_rx,
+ burst_size[0] + burst_size[1] + burst_size[2]);
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets,
+ (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]),
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
+ burst_size[0] + burst_size[1] + burst_size[2]);
+
+ /* Verify bonded slave devices rx counts */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0],
+ (unsigned int)port_stats.ipackets, burst_size[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets,
+ burst_size[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[2],
+ (unsigned int)port_stats.ipackets, burst_size[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[3],
+ (unsigned int)port_stats.ipackets, 0);
+
+ /* free mbufs */
+ for (i = 0; i < MAX_PKT_BURST; i++) {
+ if (rx_pkt_burst[i] != NULL)
+ rte_pktmbuf_free(rx_pkt_burst[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_roundrobin_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_2;
+
+ int i;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_2),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[2]);
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Verify that all MACs are the same as first slave added to bonded dev */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[2]),
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address has changed to that of primary"
+ " port without stop/start toggle of bonded device",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* stop / start bonded device and verify that primary MAC address is
+ * propagate to bonded device and slaves */
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(
+ memcmp(&expected_mac_addr_2, &read_mac_addr, sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of new primary port",
+ test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_2, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of new primary"
+ " port", test_params->slave_port_ids[i]);
+ }
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "Failed to set MAC");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of new primary port",
+ test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)), "slave port (%d) mac address not set to"
+ " that of new primary port\n", test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_roundrobin_verify_promiscuous_enable_disable(void)
+{
+ int i, promiscuous_en;
+ int ret;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, 4, 1),
+ "Failed to initialize bonded device with slaves");
+
+ ret = rte_eth_promiscuous_enable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(promiscuous_en, 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_EQUAL(promiscuous_en, 1,
+ "slave port (%d) promiscuous mode not enabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ ret = rte_eth_promiscuous_disable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to disable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(promiscuous_en, 0,
+ "Port (%d) promiscuous mode not disabled\n",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_EQUAL(promiscuous_en, 0,
+ "Port (%d) promiscuous mode not disabled\n",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_RR_LINK_STATUS_SLAVE_COUNT (4)
+#define TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT (2)
+
+static int
+test_roundrobin_verify_slave_link_status_change_behaviour(void)
+{
+ struct rte_mbuf *tx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_mbuf *gen_pkt_burst[TEST_RR_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+
+ struct rte_eth_stats port_stats;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count;
+
+ /* NULL all pointers in array to simplify cleanup */
+ memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
+
+ /* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
+ * in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ROUND_ROBIN, 0, TEST_RR_LINK_STATUS_SLAVE_COUNT, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Verify Current Slaves Count /Active Slave Count is */
+ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT,
+ "Number of slaves (%d) is not as expected (%d).",
+ slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, TEST_RR_LINK_STATUS_SLAVE_COUNT);
+
+ /* Set 2 slaves eth_devs link status to down */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count,
+ TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT,
+ "Number of active slaves (%d) is not as expected (%d).\n",
+ slave_count, TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT);
+
+ burst_size = 20;
+
+ /* Verify that pkts are not sent on slaves with link status down:
+ *
+ * 1. Generate test burst of traffic
+ * 2. Transmit burst on bonded eth_dev
+ * 3. Verify stats for bonded eth_dev (opackets = burst_size)
+ * 4. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
+ */
+ TEST_ASSERT_EQUAL(
+ generate_test_burst(tx_pkt_burst, burst_size, 0, 1, 0, 0, 0),
+ burst_size, "generate_test_burst failed");
+
+ rte_eth_stats_reset(test_params->bonded_port_id);
+
+
+ TEST_ASSERT_EQUAL(
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, tx_pkt_burst,
+ burst_size), burst_size, "rte_eth_tx_burst failed");
+
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "Port (%d) opackets stats (%d) not expected (%d) value",
+ test_params->bonded_port_id, (int)port_stats.opackets,
+ burst_size);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
+ "Port (%d) opackets stats (%d) not expected (%d) value",
+ test_params->slave_port_ids[0], (int)port_stats.opackets, 10);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
+ "Port (%d) opackets stats (%d) not expected (%d) value",
+ test_params->slave_port_ids[1], (int)port_stats.opackets, 0);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)10,
+ "Port (%d) opackets stats (%d) not expected (%d) value",
+ test_params->slave_port_ids[2], (int)port_stats.opackets, 10);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)0,
+ "Port (%d) opackets stats (%d) not expected (%d) value",
+ test_params->slave_port_ids[3], (int)port_stats.opackets, 0);
+
+ /* Verify that pkts are not sent on slaves with link status down:
+ *
+ * 1. Generate test bursts of traffic
+ * 2. Add bursts on to virtual eth_devs
+ * 3. Rx burst on bonded eth_dev, expected (burst_ size *
+ * TEST_RR_LINK_STATUS_EXPECTED_ACTIVE_SLAVE_COUNT) received
+ * 4. Verify stats for bonded eth_dev
+ * 6. Verify stats for slave eth_devs (s0 = 10, s1 = 0, s2 = 10, s3 = 0)
+ */
+ for (i = 0; i < TEST_RR_LINK_STATUS_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0),
+ burst_size, "failed to generate packet burst");
+
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[i][0], burst_size);
+ }
+
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
+ burst_size + burst_size,
+ "rte_eth_rx_burst failed");
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets , (uint64_t)(burst_size + burst_size),
+ "(%d) port_stats.ipackets not as expected\n",
+ test_params->bonded_port_id);
+
+ /* free mbufs */
+ for (i = 0; i < MAX_PKT_BURST; i++) {
+ if (rx_pkt_burst[i] != NULL)
+ rte_pktmbuf_free(rx_pkt_burst[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT (2)
+
+uint8_t polling_slave_mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00 };
+
+
+int polling_test_slaves[TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT] = { -1, -1 };
+
+static int
+test_roundrobin_verfiy_polling_slave_link_status_change(void)
+{
+ struct rte_ether_addr *mac_addr =
+ (struct rte_ether_addr *)polling_slave_mac;
+ char slave_name[RTE_ETH_NAME_MAX_LEN];
+
+ int i;
+
+ for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
+ /* Generate slave name / MAC address */
+ snprintf(slave_name, RTE_ETH_NAME_MAX_LEN, "eth_virt_poll_%d", i);
+ mac_addr->addr_bytes[RTE_ETHER_ADDR_LEN-1] = i;
+
+ /* Create slave devices with no ISR Support */
+ if (polling_test_slaves[i] == -1) {
+ polling_test_slaves[i] = virtual_ethdev_create(slave_name, mac_addr,
+ rte_socket_id(), 0);
+ TEST_ASSERT(polling_test_slaves[i] >= 0,
+ "Failed to create virtual virtual ethdev %s\n", slave_name);
+
+ /* Configure slave */
+ TEST_ASSERT_SUCCESS(configure_ethdev(polling_test_slaves[i], 0, 0),
+ "Failed to configure virtual ethdev %s(%d)", slave_name,
+ polling_test_slaves[i]);
+ }
+
+ /* Add slave to bonded device */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params->bonded_port_id,
+ polling_test_slaves[i]),
+ "Failed to add slave %s(%d) to bonded device %d",
+ slave_name, polling_test_slaves[i],
+ test_params->bonded_port_id);
+ }
+
+ /* Initialize bonded device */
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 1, 1),
+ "Failed to configure bonded device %d",
+ test_params->bonded_port_id);
+
+
+ /* Register link status change interrupt callback */
+ rte_eth_dev_callback_register(test_params->bonded_port_id,
+ RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+ &test_params->bonded_port_id);
+
+ /* link status change callback for first slave link up */
+ test_lsc_interrupt_count = 0;
+
+ virtual_ethdev_set_link_status(polling_test_slaves[0], 1);
+
+ TEST_ASSERT_SUCCESS(lsc_timeout(15000), "timed out waiting for interrupt");
+
+
+ /* no link status change callback for second slave link up */
+ test_lsc_interrupt_count = 0;
+
+ virtual_ethdev_set_link_status(polling_test_slaves[1], 1);
+
+ TEST_ASSERT_FAIL(lsc_timeout(15000), "unexpectedly succeeded");
+
+ /* link status change callback for both slave links down */
+ test_lsc_interrupt_count = 0;
+
+ virtual_ethdev_set_link_status(polling_test_slaves[0], 0);
+ virtual_ethdev_set_link_status(polling_test_slaves[1], 0);
+
+ TEST_ASSERT_SUCCESS(lsc_timeout(20000), "timed out waiting for interrupt");
+
+ /* Un-Register link status change interrupt callback */
+ rte_eth_dev_callback_unregister(test_params->bonded_port_id,
+ RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+ &test_params->bonded_port_id);
+
+
+ /* Clean up and remove slaves from bonded device */
+ for (i = 0; i < TEST_RR_POLLING_LINK_STATUS_SLAVE_COUNT; i++) {
+
+ TEST_ASSERT_SUCCESS(
+ rte_eth_bond_slave_remove(test_params->bonded_port_id,
+ polling_test_slaves[i]),
+ "Failed to remove slave %d from bonded port (%d)",
+ polling_test_slaves[i], test_params->bonded_port_id);
+ }
+
+ return remove_slaves_and_stop_bonded_device();
+}
+
+
+/** Active Backup Mode Tests */
+
+static int
+test_activebackup_tx_burst(void)
+{
+ int i, pktlen, primary_port, burst_size;
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0, 1, 1),
+ "Failed to initialize bonded device with slaves");
+
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_0, 16);
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_0, pktlen);
+
+ burst_size = 20 * test_params->bonded_slave_count;
+
+ TEST_ASSERT(burst_size < MAX_PKT_BURST,
+ "Burst size specified is greater than supported.");
+
+ /* Generate a burst of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, pkts_burst,
+ test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
+ test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN, 1),
+ burst_size, "failed to generate burst correctly");
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
+ burst_size), burst_size, "tx burst failed");
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ burst_size);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+
+ /* Verify slave ports tx stats */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
+ if (test_params->slave_port_ids[i] == primary_port) {
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.opackets,
+ burst_size / test_params->bonded_slave_count);
+ } else {
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.opackets, 0);
+ }
+ }
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
+ pkts_burst, burst_size), 0, "Sending empty burst failed");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT (4)
+
+static int
+test_activebackup_rx_burst(void)
+{
+ struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+
+ struct rte_eth_stats port_stats;
+
+ int primary_port;
+
+ int i, j, burst_size = 17;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0,
+ TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1),
+ "Failed to initialize bonded device with slaves");
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT(primary_port >= 0,
+ "failed to get primary slave for bonded port (%d)",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0),
+ burst_size, "burst generation failed");
+
+ /* Add rx data to slave */
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[0], burst_size);
+
+ /* Call rx burst on bonded device */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0,
+ &rx_pkt_burst[0], MAX_PKT_BURST), burst_size,
+ "rte_eth_rx_burst failed");
+
+ if (test_params->slave_port_ids[i] == primary_port) {
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.ipackets, burst_size);
+
+ /* Verify bonded slave devices rx count */
+ for (j = 0; j < test_params->bonded_slave_count; j++) {
+ rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
+ if (i == j) {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Slave Port (%d) ipackets value (%u) not as "
+ "expected (%d)", test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, burst_size);
+ } else {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as "
+ "expected (%d)\n", test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, 0);
+ }
+ }
+ } else {
+ for (j = 0; j < test_params->bonded_slave_count; j++) {
+ rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as expected "
+ "(%d)", test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, 0);
+ }
+ }
+
+ /* free mbufs */
+ for (i = 0; i < MAX_PKT_BURST; i++) {
+ if (rx_pkt_burst[i] != NULL) {
+ rte_pktmbuf_free(rx_pkt_burst[i]);
+ rx_pkt_burst[i] = NULL;
+ }
+ }
+
+ /* reset bonded device stats */
+ rte_eth_stats_reset(test_params->bonded_port_id);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_activebackup_verify_promiscuous_enable_disable(void)
+{
+ int i, primary_port, promiscuous_en;
+ int ret;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0, 4, 1),
+ "Failed to initialize bonded device with slaves");
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT(primary_port >= 0,
+ "failed to get primary slave for bonded port (%d)",
+ test_params->bonded_port_id);
+
+ ret = rte_eth_promiscuous_enable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ if (primary_port == test_params->slave_port_ids[i]) {
+ TEST_ASSERT_EQUAL(promiscuous_en, 1,
+ "slave port (%d) promiscuous mode not enabled",
+ test_params->slave_port_ids[i]);
+ } else {
+ TEST_ASSERT_EQUAL(promiscuous_en, 0,
+ "slave port (%d) promiscuous mode enabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ }
+
+ ret = rte_eth_promiscuous_disable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to disable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0,
+ "Port (%d) promiscuous mode not disabled\n",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_EQUAL(promiscuous_en, 0,
+ "slave port (%d) promiscuous mode not disabled\n",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_activebackup_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_1;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+
+ /* Initialize bonded device with 2 slaves in active backup mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Verify that bonded MACs is that of first slave and that the other slave
+ * MAC hasn't been changed */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[1]);
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_EQUAL(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[1]), 0,
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[1]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[1]);
+
+ /* stop / start bonded device and verify that primary MAC address is
+ * propagated to bonded device and slaves */
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[1]);
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "failed to set MAC address");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of bonded port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of bonded port",
+ test_params->slave_port_ids[1]);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_activebackup_verify_slave_link_status_change_failover(void)
+{
+ struct rte_mbuf *pkt_burst[TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count, primary_port;
+
+ burst_size = 21;
+
+ memset(pkt_burst, 0, sizeof(pkt_burst));
+
+ /* Generate packet burst for testing */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0,
+ TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Verify Current Slaves Count /Active Slave Count is */
+ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 4,
+ "Number of slaves (%d) is not as expected (%d).",
+ slave_count, 4);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 4,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 4);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0],
+ "Primary port not as expected");
+
+ /* Bring 2 slaves down and verify active slave count */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 2);
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 1);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 1);
+
+
+ /* Bring primary port down, verify that active slave count is 3 and primary
+ * has changed */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS),
+ 3,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 3);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[2],
+ "Primary port not as expected");
+
+ /* Verify that pkts are sent on new primary slave */
+
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkt_burst[0][0],
+ burst_size), burst_size, "rte_eth_tx_burst failed");
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[3]);
+
+ /* Generate packet burst for testing */
+
+ for (i = 0; i < TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ virtual_ethdev_add_mbufs_to_rx_queue(
+ test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size);
+ }
+
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
+ burst_size, "rte_eth_rx_burst\n");
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "(%d) port_stats.ipackets not as expected",
+ test_params->bonded_port_id);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[3]);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+/** Balance Mode Tests */
+
+static int
+test_balance_xmit_policy_configuration(void)
+{
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ /* Invalid port id */
+ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set(
+ INVALID_PORT_ID, BALANCE_XMIT_POLICY_LAYER2),
+ "Expected call to failed as invalid port specified.");
+
+ /* Set xmit policy on non bonded device */
+ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_set(
+ test_params->slave_port_ids[0], BALANCE_XMIT_POLICY_LAYER2),
+ "Expected call to failed as invalid port specified.");
+
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
+ "Failed to set balance xmit policy.");
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
+ BALANCE_XMIT_POLICY_LAYER2, "balance xmit policy not as expected.");
+
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23),
+ "Failed to set balance xmit policy.");
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
+ BALANCE_XMIT_POLICY_LAYER23,
+ "balance xmit policy not as expected.");
+
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34),
+ "Failed to set balance xmit policy.");
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_xmit_policy_get(test_params->bonded_port_id),
+ BALANCE_XMIT_POLICY_LAYER34,
+ "balance xmit policy not as expected.");
+
+ /* Invalid port id */
+ TEST_ASSERT_FAIL(rte_eth_bond_xmit_policy_get(INVALID_PORT_ID),
+ "Expected call to failed as invalid port specified.");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT (2)
+
+static int
+test_balance_l2_tx_burst(void)
+{
+ struct rte_mbuf *pkts_burst[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
+ int burst_size[TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT] = { 10, 15 };
+
+ uint16_t pktlen;
+ int i;
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
+ "Failed to set balance xmit policy.");
+
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_0, 16);
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_0, pktlen);
+
+ /* Generate a burst 1 of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[0][0],
+ test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
+ test_params->pkt_udp_hdr, burst_size[0],
+ PACKET_BURST_GEN_PKT_LEN, 1), burst_size[0],
+ "failed to generate packet burst");
+
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_1,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+
+ /* Generate a burst 2 of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool, &pkts_burst[1][0],
+ test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr, 1,
+ test_params->pkt_udp_hdr, burst_size[1],
+ PACKET_BURST_GEN_PKT_LEN, 1), burst_size[1],
+ "failed to generate packet burst");
+
+ /* Send burst 1 on bonded port */
+ for (i = 0; i < TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
+ &pkts_burst[i][0], burst_size[i]),
+ burst_size[i], "Failed to transmit packet burst");
+ }
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)(burst_size[0] + burst_size[1]),
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ burst_size[0] + burst_size[1]);
+
+
+ /* Verify slave ports tx stats */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[0],
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
+ burst_size[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size[1],
+ "Slave Port (%d) opackets value (%u) not as expected (%d)\n",
+ test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
+ burst_size[1]);
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkts_burst[0][0], burst_size[0]),
+ 0, "Expected zero packet");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
+ uint8_t toggle_mac_addr, uint8_t toggle_ip_addr)
+{
+ int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
+
+ struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
+ struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
+
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, 2, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER23),
+ "Failed to set balance xmit policy.");
+
+ burst_size_1 = 20;
+ burst_size_2 = 10;
+
+ TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST,
+ "Burst size specified is greater than supported.");
+
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0),
+ burst_size_1, "failed to generate packet burst");
+
+ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2, vlan_enabled, ipv4,
+ toggle_mac_addr, toggle_ip_addr, 0), burst_size_2,
+ "failed to generate packet burst");
+
+ /* Send burst 1 on bonded port */
+ nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
+ burst_size_1);
+ TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed");
+
+ /* Send burst 2 on bonded port */
+ nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
+ burst_size_2);
+ TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed");
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2),
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ nb_tx_1 + nb_tx_2);
+
+ /* Verify slave ports tx stats */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
+ nb_tx_1);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
+ nb_tx_2);
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, pkts_burst_1,
+ burst_size_1), 0, "Expected zero packet");
+
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_balance_l23_tx_burst_ipv4_toggle_ip_addr(void)
+{
+ return balance_l23_tx_burst(0, 1, 0, 1);
+}
+
+static int
+test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr(void)
+{
+ return balance_l23_tx_burst(1, 1, 0, 1);
+}
+
+static int
+test_balance_l23_tx_burst_ipv6_toggle_ip_addr(void)
+{
+ return balance_l23_tx_burst(0, 0, 0, 1);
+}
+
+static int
+test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr(void)
+{
+ return balance_l23_tx_burst(1, 0, 0, 1);
+}
+
+static int
+test_balance_l23_tx_burst_toggle_mac_addr(void)
+{
+ return balance_l23_tx_burst(0, 0, 1, 0);
+}
+
+static int
+balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
+ uint8_t toggle_mac_addr, uint8_t toggle_ip_addr,
+ uint8_t toggle_udp_port)
+{
+ int i, burst_size_1, burst_size_2, nb_tx_1, nb_tx_2;
+
+ struct rte_mbuf *pkts_burst_1[MAX_PKT_BURST];
+ struct rte_mbuf *pkts_burst_2[MAX_PKT_BURST];
+
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, 2, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER34),
+ "Failed to set balance xmit policy.");
+
+ burst_size_1 = 20;
+ burst_size_2 = 10;
+
+ TEST_ASSERT(burst_size_1 < MAX_PKT_BURST || burst_size_2 < MAX_PKT_BURST,
+ "Burst size specified is greater than supported.");
+
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ pkts_burst_1, burst_size_1, vlan_enabled, ipv4, 0, 0, 0),
+ burst_size_1, "failed to generate burst");
+
+ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2, burst_size_2,
+ vlan_enabled, ipv4, toggle_mac_addr, toggle_ip_addr,
+ toggle_udp_port), burst_size_2, "failed to generate burst");
+
+ /* Send burst 1 on bonded port */
+ nb_tx_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
+ burst_size_1);
+ TEST_ASSERT_EQUAL(nb_tx_1, burst_size_1, "tx burst failed");
+
+ /* Send burst 2 on bonded port */
+ nb_tx_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
+ burst_size_2);
+ TEST_ASSERT_EQUAL(nb_tx_2, burst_size_2, "tx burst failed");
+
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(nb_tx_1 + nb_tx_2),
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ nb_tx_1 + nb_tx_2);
+
+ /* Verify slave ports tx stats */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_1,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0], (unsigned int)port_stats.opackets,
+ nb_tx_1);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)nb_tx_2,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[1], (unsigned int)port_stats.opackets,
+ nb_tx_2);
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, pkts_burst_1,
+ burst_size_1), 0, "Expected zero packet");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_balance_l34_tx_burst_ipv4_toggle_ip_addr(void)
+{
+ return balance_l34_tx_burst(0, 1, 0, 1, 0);
+}
+
+static int
+test_balance_l34_tx_burst_ipv4_toggle_udp_port(void)
+{
+ return balance_l34_tx_burst(0, 1, 0, 0, 1);
+}
+
+static int
+test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr(void)
+{
+ return balance_l34_tx_burst(1, 1, 0, 1, 0);
+}
+
+static int
+test_balance_l34_tx_burst_ipv6_toggle_ip_addr(void)
+{
+ return balance_l34_tx_burst(0, 0, 0, 1, 0);
+}
+
+static int
+test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr(void)
+{
+ return balance_l34_tx_burst(1, 0, 0, 1, 0);
+}
+
+static int
+test_balance_l34_tx_burst_ipv6_toggle_udp_port(void)
+{
+ return balance_l34_tx_burst(0, 0, 0, 0, 1);
+}
+
+#define TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT (2)
+#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 (40)
+#define TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2 (20)
+#define TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT (25)
+#define TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX (0)
+
+static int
+test_balance_tx_burst_slave_tx_fail(void)
+{
+ struct rte_mbuf *pkts_burst_1[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1];
+ struct rte_mbuf *pkts_burst_2[TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2];
+
+ struct rte_mbuf *expected_fail_pkts[TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT];
+
+ struct rte_eth_stats port_stats;
+
+ int i, first_tx_fail_idx, tx_count_1, tx_count_2;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0,
+ TEST_BAL_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
+ "Failed to initialise bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
+ "Failed to set balance xmit policy.");
+
+
+ /* Generate test bursts for transmission */
+ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_1,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1, 0, 0, 0, 0, 0),
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1,
+ "Failed to generate test packet burst 1");
+
+ first_tx_fail_idx = TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT;
+
+ /* copy mbuf referneces for expected transmission failures */
+ for (i = 0; i < TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT; i++)
+ expected_fail_pkts[i] = pkts_burst_1[i + first_tx_fail_idx];
+
+ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst_2,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2, 0, 0, 1, 0, 0),
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
+ "Failed to generate test packet burst 2");
+
+
+ /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
+ * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
+ virtual_ethdev_tx_burst_fn_set_success(
+ test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
+ 0);
+
+ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
+ test_params->slave_port_ids[TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX],
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+
+ /* Transmit burst 1 */
+ tx_count_1 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_1,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1);
+
+ TEST_ASSERT_EQUAL(tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
+ "Transmitted (%d) packets, expected to transmit (%d) packets",
+ tx_count_1, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ /* Verify that failed packet are expected failed packets */
+ for (i = 0; i < TEST_RR_SLAVE_TX_FAIL_PACKETS_COUNT; i++) {
+ TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst_1[i + tx_count_1],
+ "expected mbuf (%d) pointer %p not expected pointer %p",
+ i, expected_fail_pkts[i], pkts_burst_1[i + tx_count_1]);
+ }
+
+ /* Transmit burst 2 */
+ tx_count_2 = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst_2,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
+
+ TEST_ASSERT_EQUAL(tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
+ "Transmitted (%d) packets, expected to transmit (%d) packets",
+ tx_count_2, TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
+
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)((TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2),
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ (TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT) +
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
+
+ /* Verify slave ports tx stats */
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0],
+ (unsigned int)port_stats.opackets,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_1 -
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+
+
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[1],
+ (unsigned int)port_stats.opackets,
+ TEST_BAL_SLAVE_TX_FAIL_BURST_SIZE_2);
+
+ /* Verify that all mbufs have a ref value of zero */
+ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst_1[tx_count_1],
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT, 1),
+ "mbufs refcnts not as expected");
+
+ free_mbufs(&pkts_burst_1[tx_count_1],
+ TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_BALANCE_RX_BURST_SLAVE_COUNT (3)
+
+static int
+test_balance_rx_burst(void)
+{
+ struct rte_mbuf *gen_pkt_burst[TEST_BALANCE_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
+
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ int burst_size[TEST_BALANCE_RX_BURST_SLAVE_COUNT] = { 10, 5, 30 };
+ int i, j;
+
+ memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, 3, 1),
+ "Failed to initialise bonded device");
+
+ /* Generate test bursts of packets to transmit */
+ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[i][0], burst_size[i], 0, 0, 1,
+ 0, 0), burst_size[i],
+ "failed to generate packet burst");
+ }
+
+ /* Add rx data to slaves */
+ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[i][0], burst_size[i]);
+ }
+
+ /* Call rx burst on bonded device */
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(test_params->bonded_port_id, 0,
+ rx_pkt_burst, MAX_PKT_BURST),
+ burst_size[0] + burst_size[1] + burst_size[2],
+ "balance rx burst failed\n");
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets,
+ (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]),
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
+ burst_size[0] + burst_size[1] + burst_size[2]);
+
+
+ /* Verify bonded slave devices rx counts */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0],
+ (unsigned int)port_stats.ipackets, burst_size[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[1], (unsigned int)port_stats.ipackets,
+ burst_size[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets,
+ burst_size[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets,
+ 0);
+
+ /* free mbufs */
+ for (i = 0; i < TEST_BALANCE_RX_BURST_SLAVE_COUNT; i++) {
+ for (j = 0; j < MAX_PKT_BURST; j++) {
+ if (gen_pkt_burst[i][j] != NULL) {
+ rte_pktmbuf_free(gen_pkt_burst[i][j]);
+ gen_pkt_burst[i][j] = NULL;
+ }
+ }
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_balance_verify_promiscuous_enable_disable(void)
+{
+ int i;
+ int ret;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, 4, 1),
+ "Failed to initialise bonded device");
+
+ ret = rte_eth_promiscuous_enable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ ret = rte_eth_promiscuous_disable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to disable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_balance_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_1;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+
+ /* Initialize bonded device with 2 slaves in active backup mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, 2, 1),
+ "Failed to initialise bonded device");
+
+ /* Verify that bonded MACs is that of first slave and that the other slave
+ * MAC hasn't been changed */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[1]);
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[1]),
+ "Failed to set bonded port (%d) primary port to (%d)\n",
+ test_params->bonded_port_id, test_params->slave_port_ids[1]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[1]);
+
+ /* stop / start bonded device and verify that primary MAC address is
+ * propagated to bonded device and slaves */
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[1]);
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "failed to set MAC");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of bonded port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected\n",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of bonded port",
+ test_params->slave_port_ids[1]);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_BALANCE_LINK_STATUS_SLAVE_COUNT (4)
+
+static int
+test_balance_verify_slave_link_status_change_behaviour(void)
+{
+ struct rte_mbuf *pkt_burst[TEST_BALANCE_LINK_STATUS_SLAVE_COUNT][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count;
+
+ memset(pkt_burst, 0, sizeof(pkt_burst));
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BALANCE, 0, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1),
+ "Failed to initialise bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_xmit_policy_set(
+ test_params->bonded_port_id, BALANCE_XMIT_POLICY_LAYER2),
+ "Failed to set balance xmit policy.");
+
+
+ /* Verify Current Slaves Count /Active Slave Count is */
+ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT,
+ "Number of slaves (%d) is not as expected (%d).",
+ slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, TEST_BALANCE_LINK_STATUS_SLAVE_COUNT);
+
+ /* Set 2 slaves link status to down */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 2);
+
+ /* Send to sets of packet burst and verify that they are balanced across
+ * slaves */
+ burst_size = 21;
+
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size),
+ burst_size, "rte_eth_tx_burst failed");
+
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size),
+ burst_size, "rte_eth_tx_burst failed");
+
+
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size),
+ "(%d) port_stats.opackets (%d) not as expected (%d).",
+ test_params->bonded_port_id, (int)port_stats.opackets,
+ burst_size + burst_size);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets (%d) not as expected (%d).",
+ test_params->slave_port_ids[0], (int)port_stats.opackets,
+ burst_size);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets (%d) not as expected (%d).",
+ test_params->slave_port_ids[2], (int)port_stats.opackets,
+ burst_size);
+
+ /* verify that all packets get send on primary slave when no other slaves
+ * are available */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[2], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 1,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 1);
+
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[1][0], burst_size, 0, 1, 1, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkt_burst[1][0], burst_size),
+ burst_size, "rte_eth_tx_burst failed");
+
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)(burst_size + burst_size + burst_size),
+ "(%d) port_stats.opackets (%d) not as expected (%d).\n",
+ test_params->bonded_port_id, (int)port_stats.opackets,
+ burst_size + burst_size + burst_size);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size + burst_size),
+ "(%d) port_stats.opackets (%d) not as expected (%d).",
+ test_params->slave_port_ids[0], (int)port_stats.opackets,
+ burst_size + burst_size);
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 1);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[2], 1);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 1);
+
+ for (i = 0; i < TEST_BALANCE_LINK_STATUS_SLAVE_COUNT; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "Failed to generate packet burst");
+
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &pkt_burst[i][0], burst_size);
+ }
+
+ /* Verify that pkts are not received on slaves with link status down */
+
+ rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
+ MAX_PKT_BURST);
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size * 3),
+ "(%d) port_stats.ipackets (%d) not as expected (%d)\n",
+ test_params->bonded_port_id, (int)port_stats.ipackets,
+ burst_size * 3);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_broadcast_tx_burst(void)
+{
+ int i, pktlen, burst_size;
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+
+ struct rte_eth_stats port_stats;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 2, 1),
+ "Failed to initialise bonded device");
+
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_0, 16);
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_0, pktlen);
+
+ burst_size = 20 * test_params->bonded_slave_count;
+
+ TEST_ASSERT(burst_size < MAX_PKT_BURST,
+ "Burst size specified is greater than supported.");
+
+ /* Generate a burst of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_packet_burst(test_params->mbuf_pool,
+ pkts_burst, test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
+ 1, test_params->pkt_udp_hdr, burst_size, PACKET_BURST_GEN_PKT_LEN,
+ 1), burst_size, "Failed to generate packet burst");
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
+ pkts_burst, burst_size), burst_size,
+ "Bonded Port (%d) rx burst failed, packets transmitted value "
+ "not as expected (%d)",
+ test_params->bonded_port_id, burst_size);
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)burst_size * test_params->bonded_slave_count,
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ burst_size);
+
+ /* Verify slave ports tx stats */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "Slave Port (%d) opackets value (%u) not as expected (%d)\n",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.opackets, burst_size);
+ }
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, pkts_burst, burst_size), 0,
+ "transmitted an unexpected number of packets");
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+
+#define TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT (3)
+#define TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE (40)
+#define TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT (15)
+#define TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT (10)
+
+static int
+test_broadcast_tx_burst_slave_tx_fail(void)
+{
+ struct rte_mbuf *pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE];
+ struct rte_mbuf *expected_fail_pkts[TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT];
+
+ struct rte_eth_stats port_stats;
+
+ int i, tx_count;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0,
+ TEST_BCAST_SLAVE_TX_FAIL_SLAVE_COUNT, 1),
+ "Failed to initialise bonded device");
+
+ /* Generate test bursts for transmission */
+ TEST_ASSERT_EQUAL(generate_test_burst(pkts_burst,
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE, 0, 0, 0, 0, 0),
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE,
+ "Failed to generate test packet burst");
+
+ for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
+ expected_fail_pkts[i] = pkts_burst[TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT + i];
+ }
+
+ /* Set virtual slave TEST_BAL_SLAVE_TX_FAIL_FAILING_SLAVE_IDX to only fail
+ * transmission of TEST_BAL_SLAVE_TX_FAIL_PACKETS_COUNT packets of burst */
+ virtual_ethdev_tx_burst_fn_set_success(
+ test_params->slave_port_ids[0],
+ 0);
+ virtual_ethdev_tx_burst_fn_set_success(
+ test_params->slave_port_ids[1],
+ 0);
+ virtual_ethdev_tx_burst_fn_set_success(
+ test_params->slave_port_ids[2],
+ 0);
+
+ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
+ test_params->slave_port_ids[0],
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
+
+ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
+ test_params->slave_port_ids[1],
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
+
+ virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(
+ test_params->slave_port_ids[2],
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
+
+ /* Transmit burst */
+ tx_count = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkts_burst,
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE);
+
+ TEST_ASSERT_EQUAL(tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
+ "Transmitted (%d) packets, expected to transmit (%d) packets",
+ tx_count, TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
+
+ /* Verify that failed packet are expected failed packets */
+ for (i = 0; i < TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT; i++) {
+ TEST_ASSERT_EQUAL(expected_fail_pkts[i], pkts_burst[i + tx_count],
+ "expected mbuf (%d) pointer %p not expected pointer %p",
+ i, expected_fail_pkts[i], pkts_burst[i + tx_count]);
+ }
+
+ /* Verify slave ports tx stats */
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
+ "Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
+
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT,
+ "Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+
+ TEST_ASSERT_EQUAL(port_stats.opackets,
+ (uint64_t)TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT,
+ "Port (%d) opackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.opackets,
+ TEST_BCAST_SLAVE_TX_FAIL_BURST_SIZE -
+ TEST_BCAST_SLAVE_TX_FAIL_MAX_PACKETS_COUNT);
+
+
+ /* Verify that all mbufs who transmission failed have a ref value of one */
+ TEST_ASSERT_SUCCESS(verify_mbufs_ref_count(&pkts_burst[tx_count],
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT, 1),
+ "mbufs refcnts not as expected");
+
+ free_mbufs(&pkts_burst[tx_count],
+ TEST_BCAST_SLAVE_TX_FAIL_MIN_PACKETS_COUNT);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define BROADCAST_RX_BURST_NUM_OF_SLAVES (3)
+
+static int
+test_broadcast_rx_burst(void)
+{
+ struct rte_mbuf *gen_pkt_burst[BROADCAST_RX_BURST_NUM_OF_SLAVES][MAX_PKT_BURST];
+
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ int burst_size[BROADCAST_RX_BURST_NUM_OF_SLAVES] = { 10, 5, 30 };
+ int i, j;
+
+ memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 3, 1),
+ "Failed to initialise bonded device");
+
+ /* Generate test bursts of packets to transmit */
+ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[i][0], burst_size[i], 0, 0, 1, 0, 0),
+ burst_size[i], "failed to generate packet burst");
+ }
+
+ /* Add rx data to slave 0 */
+ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[i][0], burst_size[i]);
+ }
+
+
+ /* Call rx burst on bonded device */
+ /* Send burst on bonded port */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
+ burst_size[0] + burst_size[1] + burst_size[2],
+ "rx burst failed");
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets,
+ (uint64_t)(burst_size[0] + burst_size[1] + burst_size[2]),
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->bonded_port_id, (unsigned int)port_stats.ipackets,
+ burst_size[0] + burst_size[1] + burst_size[2]);
+
+
+ /* Verify bonded slave devices rx counts */
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[0],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets,
+ burst_size[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[1],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[0], (unsigned int)port_stats.ipackets,
+ burst_size[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size[2],
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[2], (unsigned int)port_stats.ipackets,
+ burst_size[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, 0,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)",
+ test_params->slave_port_ids[3], (unsigned int)port_stats.ipackets,
+ 0);
+
+ /* free mbufs allocate for rx testing */
+ for (i = 0; i < BROADCAST_RX_BURST_NUM_OF_SLAVES; i++) {
+ for (j = 0; j < MAX_PKT_BURST; j++) {
+ if (gen_pkt_burst[i][j] != NULL) {
+ rte_pktmbuf_free(gen_pkt_burst[i][j]);
+ gen_pkt_burst[i][j] = NULL;
+ }
+ }
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_broadcast_verify_promiscuous_enable_disable(void)
+{
+ int i;
+ int ret;
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 4, 1),
+ "Failed to initialise bonded device");
+
+ ret = rte_eth_promiscuous_enable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 1,
+ "Port (%d) promiscuous mode not enabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ ret = rte_eth_promiscuous_disable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to disable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(test_params->bonded_port_id), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_EQUAL(rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]), 0,
+ "Port (%d) promiscuous mode not disabled",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_broadcast_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_1;
+
+ int i;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[2]);
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, 4, 1),
+ "Failed to initialise bonded device");
+
+ /* Verify that all MACs are the same as first slave added to bonded
+ * device */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[2]),
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address has changed to that of primary "
+ "port without stop/start toggle of bonded device",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* stop / start bonded device and verify that primary MAC address is
+ * propagated to bonded device and slaves */
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start bonded device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of new primary port",
+ test_params->slave_port_ids[i]);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of new primary "
+ "port", test_params->slave_port_ids[i]);
+ }
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "Failed to set MAC address");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of new primary port",
+ test_params->slave_port_ids[i]);
+
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[i], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_SUCCESS(memcmp(bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of new primary "
+ "port", test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define BROADCAST_LINK_STATUS_NUM_OF_SLAVES (4)
+static int
+test_broadcast_verify_slave_link_status_change_behaviour(void)
+{
+ struct rte_mbuf *pkt_burst[BROADCAST_LINK_STATUS_NUM_OF_SLAVES][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count;
+
+ memset(pkt_burst, 0, sizeof(pkt_burst));
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_BROADCAST, 0, BROADCAST_LINK_STATUS_NUM_OF_SLAVES,
+ 1), "Failed to initialise bonded device");
+
+ /* Verify Current Slaves Count /Active Slave Count is */
+ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 4,
+ "Number of slaves (%d) is not as expected (%d).",
+ slave_count, 4);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 4,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 4);
+
+ /* Set 2 slaves link status to down */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 2,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 2);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++)
+ rte_eth_stats_reset(test_params->slave_port_ids[i]);
+
+ /* Verify that pkts are not sent on slaves with link status down */
+ burst_size = 21;
+
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[0][0], burst_size, 0, 0, 1, 0, 0), burst_size,
+ "generate_test_burst failed");
+
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(test_params->bonded_port_id, 0,
+ &pkt_burst[0][0], burst_size), burst_size,
+ "rte_eth_tx_burst failed\n");
+
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)(burst_size * slave_count),
+ "(%d) port_stats.opackets (%d) not as expected (%d)\n",
+ test_params->bonded_port_id, (int)port_stats.opackets,
+ burst_size * slave_count);
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (uint64_t)burst_size,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[2]);
+
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, 0,
+ "(%d) port_stats.opackets not as expected",
+ test_params->slave_port_ids[3]);
+
+
+ for (i = 0; i < BROADCAST_LINK_STATUS_NUM_OF_SLAVES; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[i][0], burst_size, 0, 0, 1, 0, 0),
+ burst_size, "failed to generate packet burst");
+
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &pkt_burst[i][0], burst_size);
+ }
+
+ /* Verify that pkts are not received on slaves with link status down */
+ TEST_ASSERT_EQUAL(rte_eth_rx_burst(
+ test_params->bonded_port_id, 0, rx_pkt_burst, MAX_PKT_BURST),
+ burst_size + burst_size, "rte_eth_rx_burst failed");
+
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)(burst_size + burst_size),
+ "(%d) port_stats.ipackets not as expected\n",
+ test_params->bonded_port_id);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_reconfigure_bonded_device(void)
+{
+ test_params->nb_rx_q = 4;
+ test_params->nb_tx_q = 4;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
+ "failed to reconfigure bonded device");
+
+ test_params->nb_rx_q = 2;
+ test_params->nb_tx_q = 2;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
+ "failed to reconfigure bonded device with less rx/tx queues");
+
+ return 0;
+}
+
+
+static int
+test_close_bonded_device(void)
+{
+ rte_eth_dev_close(test_params->bonded_port_id);
+ return 0;
+}
+
+static void
+testsuite_teardown(void)
+{
+ free(test_params->pkt_eth_hdr);
+ test_params->pkt_eth_hdr = NULL;
+
+ /* Clean up and remove slaves from bonded device */
+ remove_slaves_and_stop_bonded_device();
+}
+
+static void
+free_virtualpmd_tx_queue(void)
+{
+ int i, slave_port, to_free_cnt;
+ struct rte_mbuf *pkts_to_free[MAX_PKT_BURST];
+
+ /* Free tx queue of virtual pmd */
+ for (slave_port = 0; slave_port < test_params->bonded_slave_count;
+ slave_port++) {
+ to_free_cnt = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_port],
+ pkts_to_free, MAX_PKT_BURST);
+ for (i = 0; i < to_free_cnt; i++)
+ rte_pktmbuf_free(pkts_to_free[i]);
+ }
+}
+
+static int
+test_tlb_tx_burst(void)
+{
+ int i, burst_size, nb_tx;
+ uint64_t nb_tx2 = 0;
+ struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
+ struct rte_eth_stats port_stats[32];
+ uint64_t sum_ports_opackets = 0, all_bond_opackets = 0, all_bond_obytes = 0;
+ uint16_t pktlen;
+
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves
+ (BONDING_MODE_TLB, 1, 3, 1),
+ "Failed to initialise bonded device");
+
+ burst_size = 20 * test_params->bonded_slave_count;
+
+ TEST_ASSERT(burst_size < MAX_PKT_BURST,
+ "Burst size specified is greater than supported.\n");
+
+
+ /* Generate bursts of packets */
+ for (i = 0; i < 400000; i++) {
+ /*test two types of mac src own(bonding) and others */
+ if (i % 2 == 0) {
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+ } else {
+ initialize_eth_header(test_params->pkt_eth_hdr,
+ (struct rte_ether_addr *)test_params->default_slave_mac,
+ (struct rte_ether_addr *)dst_mac_0,
+ RTE_ETHER_TYPE_IPV4, 0, 0);
+ }
+ pktlen = initialize_udp_header(test_params->pkt_udp_hdr, src_port,
+ dst_port_0, 16);
+ pktlen = initialize_ipv4_header(test_params->pkt_ipv4_hdr, src_addr,
+ dst_addr_0, pktlen);
+ generate_packet_burst(test_params->mbuf_pool, pkt_burst,
+ test_params->pkt_eth_hdr, 0, test_params->pkt_ipv4_hdr,
+ 1, test_params->pkt_udp_hdr, burst_size, 60, 1);
+ /* Send burst on bonded port */
+ nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
+ burst_size);
+ nb_tx2 += nb_tx;
+
+ free_virtualpmd_tx_queue();
+
+ TEST_ASSERT_EQUAL(nb_tx, burst_size,
+ "number of packet not equal burst size");
+
+ rte_delay_us(5);
+ }
+
+
+ /* Verify bonded port tx stats */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats[0]);
+
+ all_bond_opackets = port_stats[0].opackets;
+ all_bond_obytes = port_stats[0].obytes;
+
+ TEST_ASSERT_EQUAL(port_stats[0].opackets, (uint64_t)nb_tx2,
+ "Bonded Port (%d) opackets value (%u) not as expected (%d)\n",
+ test_params->bonded_port_id, (unsigned int)port_stats[0].opackets,
+ burst_size);
+
+
+ /* Verify slave ports tx stats */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ rte_eth_stats_get(test_params->slave_port_ids[i], &port_stats[i]);
+ sum_ports_opackets += port_stats[i].opackets;
+ }
+
+ TEST_ASSERT_EQUAL(sum_ports_opackets, (uint64_t)all_bond_opackets,
+ "Total packets sent by slaves is not equal to packets sent by bond interface");
+
+ /* checking if distribution of packets is balanced over slaves */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ TEST_ASSERT(port_stats[i].obytes > 0 &&
+ port_stats[i].obytes < all_bond_obytes,
+ "Packets are not balanced over slaves");
+ }
+
+ /* Put all slaves down and try and transmit */
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[i], 0);
+ }
+
+ /* Send burst on bonded port */
+ nb_tx = rte_eth_tx_burst(test_params->bonded_port_id, 0, pkt_burst,
+ burst_size);
+ TEST_ASSERT_EQUAL(nb_tx, 0, " bad number of packet in burst");
+
+ /* Clean ugit checkout masterp and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT (4)
+
+static int
+test_tlb_rx_burst(void)
+{
+ struct rte_mbuf *gen_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+
+ struct rte_eth_stats port_stats;
+
+ int primary_port;
+
+ uint16_t i, j, nb_rx, burst_size = 17;
+
+ /* Initialize bonded device with 4 slaves in transmit load balancing mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_TLB,
+ TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT, 1, 1),
+ "Failed to initialize bonded device");
+
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT(primary_port >= 0,
+ "failed to get primary slave for bonded port (%d)",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ /* Generate test bursts of packets to transmit */
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &gen_pkt_burst[0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "burst generation failed");
+
+ /* Add rx data to slave */
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[i],
+ &gen_pkt_burst[0], burst_size);
+
+ /* Call rx burst on bonded device */
+ nb_rx = rte_eth_rx_burst(test_params->bonded_port_id, 0,
+ &rx_pkt_burst[0], MAX_PKT_BURST);
+
+ TEST_ASSERT_EQUAL(nb_rx, burst_size, "rte_eth_rx_burst failed\n");
+
+ if (test_params->slave_port_ids[i] == primary_port) {
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Bonded Port (%d) ipackets value (%u) not as expected (%d)\n",
+ test_params->bonded_port_id,
+ (unsigned int)port_stats.ipackets, burst_size);
+
+ /* Verify bonded slave devices rx count */
+ for (j = 0; j < test_params->bonded_slave_count; j++) {
+ rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
+ if (i == j) {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
+ test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, burst_size);
+ } else {
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)0,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
+ test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, 0);
+ }
+ }
+ } else {
+ for (j = 0; j < test_params->bonded_slave_count; j++) {
+ rte_eth_stats_get(test_params->slave_port_ids[j], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)0,
+ "Slave Port (%d) ipackets value (%u) not as expected (%d)\n",
+ test_params->slave_port_ids[i],
+ (unsigned int)port_stats.ipackets, 0);
+ }
+ }
+
+ /* free mbufs */
+ for (i = 0; i < burst_size; i++)
+ rte_pktmbuf_free(rx_pkt_burst[i]);
+
+ /* reset bonded device stats */
+ rte_eth_stats_reset(test_params->bonded_port_id);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_tlb_verify_promiscuous_enable_disable(void)
+{
+ int i, primary_port, promiscuous_en;
+ int ret;
+
+ /* Initialize bonded device with 4 slaves in transmit load balancing mode */
+ TEST_ASSERT_SUCCESS( initialize_bonded_device_with_slaves(
+ BONDING_MODE_TLB, 0, 4, 1),
+ "Failed to initialize bonded device");
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT(primary_port >= 0,
+ "failed to get primary slave for bonded port (%d)",
+ test_params->bonded_port_id);
+
+ ret = rte_eth_promiscuous_enable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(promiscuous_en, (int)1,
+ "Port (%d) promiscuous mode not enabled\n",
+ test_params->bonded_port_id);
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ if (primary_port == test_params->slave_port_ids[i]) {
+ TEST_ASSERT_EQUAL(promiscuous_en, (int)1,
+ "Port (%d) promiscuous mode not enabled\n",
+ test_params->bonded_port_id);
+ } else {
+ TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
+ "Port (%d) promiscuous mode enabled\n",
+ test_params->bonded_port_id);
+ }
+
+ }
+
+ ret = rte_eth_promiscuous_disable(test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed to disable promiscuous mode for port %d: %s\n",
+ test_params->bonded_port_id, rte_strerror(-ret));
+
+ promiscuous_en = rte_eth_promiscuous_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
+ "Port (%d) promiscuous mode not disabled\n",
+ test_params->bonded_port_id);
+
+ for (i = 0; i < test_params->bonded_slave_count; i++) {
+ promiscuous_en = rte_eth_promiscuous_get(
+ test_params->slave_port_ids[i]);
+ TEST_ASSERT_EQUAL(promiscuous_en, (int)0,
+ "slave port (%d) promiscuous mode not disabled\n",
+ test_params->slave_port_ids[i]);
+ }
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_tlb_verify_mac_assignment(void)
+{
+ struct rte_ether_addr read_mac_addr;
+ struct rte_ether_addr expected_mac_addr_0, expected_mac_addr_1;
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &expected_mac_addr_0),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+
+ /* Initialize bonded device with 2 slaves in active backup mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_TLB, 0, 2, 1),
+ "Failed to initialize bonded device");
+
+ /* Verify that bonded MACs is that of first slave and that the other slave
+ * MAC hasn't been changed */
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[1]);
+
+ /* change primary and verify that MAC addresses haven't changed */
+ TEST_ASSERT_EQUAL(rte_eth_bond_primary_set(test_params->bonded_port_id,
+ test_params->slave_port_ids[1]), 0,
+ "Failed to set bonded port (%d) primary port to (%d)",
+ test_params->bonded_port_id, test_params->slave_port_ids[1]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[1]);
+
+ /* stop / start bonded device and verify that primary MAC address is
+ * propagated to bonded device and slaves */
+
+ rte_eth_dev_stop(test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params->bonded_port_id),
+ "Failed to start device");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of primary port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_1, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of primary port",
+ test_params->slave_port_ids[1]);
+
+
+ /* Set explicit MAC address */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_mac_address_set(
+ test_params->bonded_port_id,
+ (struct rte_ether_addr *)bonded_mac),
+ "failed to set MAC address");
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->bonded_port_id, &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->bonded_port_id);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "bonded port (%d) mac address not set to that of bonded port",
+ test_params->bonded_port_id);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[0], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[0]);
+ TEST_ASSERT_SUCCESS(memcmp(&expected_mac_addr_0, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not as expected",
+ test_params->slave_port_ids[0]);
+
+ TEST_ASSERT_SUCCESS(rte_eth_macaddr_get(test_params->slave_port_ids[1], &read_mac_addr),
+ "Failed to get mac address (port %d)",
+ test_params->slave_port_ids[1]);
+ TEST_ASSERT_SUCCESS(memcmp(&bonded_mac, &read_mac_addr,
+ sizeof(read_mac_addr)),
+ "slave port (%d) mac address not set to that of bonded port",
+ test_params->slave_port_ids[1]);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static int
+test_tlb_verify_slave_link_status_change_failover(void)
+{
+ struct rte_mbuf *pkt_burst[TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT][MAX_PKT_BURST];
+ struct rte_mbuf *rx_pkt_burst[MAX_PKT_BURST] = { NULL };
+ struct rte_eth_stats port_stats;
+
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+
+ int i, burst_size, slave_count, primary_port;
+
+ burst_size = 21;
+
+ memset(pkt_burst, 0, sizeof(pkt_burst));
+
+
+
+ /* Initialize bonded device with 4 slaves in round robin mode */
+ TEST_ASSERT_SUCCESS(initialize_bonded_device_with_slaves(
+ BONDING_MODE_TLB, 0,
+ TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT, 1),
+ "Failed to initialize bonded device with slaves");
+
+ /* Verify Current Slaves Count /Active Slave Count is */
+ slave_count = rte_eth_bond_slaves_get(test_params->bonded_port_id, slaves,
+ RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, 4,
+ "Number of slaves (%d) is not as expected (%d).\n",
+ slave_count, 4);
+
+ slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+ slaves, RTE_MAX_ETHPORTS);
+ TEST_ASSERT_EQUAL(slave_count, (int)4,
+ "Number of slaves (%d) is not as expected (%d).\n",
+ slave_count, 4);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[0],
+ "Primary port not as expected");
+
+ /* Bring 2 slaves down and verify active slave count */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 0);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 2,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 2);
+
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[1], 1);
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[3], 1);
+
+
+ /* Bring primary port down, verify that active slave count is 3 and primary
+ * has changed */
+ virtual_ethdev_simulate_link_status_interrupt(
+ test_params->slave_port_ids[0], 0);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_active_slaves_get(
+ test_params->bonded_port_id, slaves, RTE_MAX_ETHPORTS), 3,
+ "Number of active slaves (%d) is not as expected (%d).",
+ slave_count, 3);
+
+ primary_port = rte_eth_bond_primary_get(test_params->bonded_port_id);
+ TEST_ASSERT_EQUAL(primary_port, test_params->slave_port_ids[2],
+ "Primary port not as expected");
+ rte_delay_us(500000);
+ /* Verify that pkts are sent on new primary slave */
+ for (i = 0; i < 4; i++) {
+ TEST_ASSERT_EQUAL(generate_test_burst(
+ &pkt_burst[0][0], burst_size, 0, 1, 0, 0, 0), burst_size,
+ "generate_test_burst failed\n");
+ TEST_ASSERT_EQUAL(rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, &pkt_burst[0][0], burst_size), burst_size,
+ "rte_eth_tx_burst failed\n");
+ rte_delay_us(11000);
+ }
+
+ rte_eth_stats_get(test_params->slave_port_ids[0], &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.opackets, (int8_t)0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[0]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[1], &port_stats);
+ TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[1]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[2], &port_stats);
+ TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[2]);
+
+ rte_eth_stats_get(test_params->slave_port_ids[3], &port_stats);
+ TEST_ASSERT_NOT_EQUAL(port_stats.opackets, (int8_t)0,
+ "(%d) port_stats.opackets not as expected\n",
+ test_params->slave_port_ids[3]);
+
+
+ /* Generate packet burst for testing */
+
+ for (i = 0; i < TEST_ADAPTIVE_TRANSMIT_LOAD_BALANCING_RX_BURST_SLAVE_COUNT; i++) {
+ if (generate_test_burst(&pkt_burst[i][0], burst_size, 0, 1, 0, 0, 0) !=
+ burst_size)
+ return -1;
+
+ virtual_ethdev_add_mbufs_to_rx_queue(
+ test_params->slave_port_ids[i], &pkt_burst[i][0], burst_size);
+ }
+
+ if (rte_eth_rx_burst(test_params->bonded_port_id, 0, rx_pkt_burst,
+ MAX_PKT_BURST) != burst_size) {
+ printf("rte_eth_rx_burst\n");
+ return -1;
+
+ }
+
+ /* Verify bonded device rx count */
+ rte_eth_stats_get(test_params->bonded_port_id, &port_stats);
+ TEST_ASSERT_EQUAL(port_stats.ipackets, (uint64_t)burst_size,
+ "(%d) port_stats.ipackets not as expected\n",
+ test_params->bonded_port_id);
+
+ /* Clean up and remove slaves from bonded device */
+ return remove_slaves_and_stop_bonded_device();
+}
+
+#define TEST_ALB_SLAVE_COUNT 2
+
+static uint8_t mac_client1[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 1};
+static uint8_t mac_client2[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 2};
+static uint8_t mac_client3[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 3};
+static uint8_t mac_client4[] = {0x00, 0xAA, 0x55, 0xFF, 0xCC, 4};
+
+static uint32_t ip_host = IPV4_ADDR(192, 168, 0, 0);
+static uint32_t ip_client1 = IPV4_ADDR(192, 168, 0, 1);
+static uint32_t ip_client2 = IPV4_ADDR(192, 168, 0, 2);
+static uint32_t ip_client3 = IPV4_ADDR(192, 168, 0, 3);
+static uint32_t ip_client4 = IPV4_ADDR(192, 168, 0, 4);
+
+static int
+test_alb_change_mac_in_reply_sent(void)
+{
+ struct rte_mbuf *pkt;
+ struct rte_mbuf *pkts_sent[MAX_PKT_BURST];
+
+ struct rte_ether_hdr *eth_pkt;
+ struct rte_arp_hdr *arp_pkt;
+
+ int slave_idx, nb_pkts, pkt_idx;
+ int retval = 0;
+
+ struct rte_ether_addr bond_mac, client_mac;
+ struct rte_ether_addr *slave_mac1, *slave_mac2;
+
+ TEST_ASSERT_SUCCESS(
+ initialize_bonded_device_with_slaves(BONDING_MODE_ALB,
+ 0, TEST_ALB_SLAVE_COUNT, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ /* Flush tx queue */
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0);
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count;
+ slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent,
+ MAX_PKT_BURST);
+ }
+
+ rte_ether_addr_copy(
+ rte_eth_devices[test_params->bonded_port_id].data->mac_addrs,
+ &bond_mac);
+
+ /*
+ * Generating four packets with different mac and ip addresses and sending
+ * them through the bonding port.
+ */
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client1, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client1,
+ RTE_ARP_OP_REPLY);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client2, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client2,
+ RTE_ARP_OP_REPLY);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client3, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client3,
+ RTE_ARP_OP_REPLY);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client4, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &bond_mac, &client_mac, ip_host, ip_client4,
+ RTE_ARP_OP_REPLY);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, &pkt, 1);
+
+ slave_mac1 =
+ rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs;
+ slave_mac2 =
+ rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs;
+
+ /*
+ * Checking if packets are properly distributed on bonding ports. Packets
+ * 0 and 2 should be sent on port 0 and packets 1 and 3 on port 1.
+ */
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent,
+ MAX_PKT_BURST);
+
+ for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) {
+ eth_pkt = rte_pktmbuf_mtod(
+ pkts_sent[pkt_idx], struct rte_ether_hdr *);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+
+ if (slave_idx%2 == 0) {
+ if (!rte_is_same_ether_addr(slave_mac1,
+ &arp_pkt->arp_data.arp_sha)) {
+ retval = -1;
+ goto test_end;
+ }
+ } else {
+ if (!rte_is_same_ether_addr(slave_mac2,
+ &arp_pkt->arp_data.arp_sha)) {
+ retval = -1;
+ goto test_end;
+ }
+ }
+ }
+ }
+
+test_end:
+ retval += remove_slaves_and_stop_bonded_device();
+ return retval;
+}
+
+static int
+test_alb_reply_from_client(void)
+{
+ struct rte_ether_hdr *eth_pkt;
+ struct rte_arp_hdr *arp_pkt;
+
+ struct rte_mbuf *pkt;
+ struct rte_mbuf *pkts_sent[MAX_PKT_BURST];
+
+ int slave_idx, nb_pkts, pkt_idx, nb_pkts_sum = 0;
+ int retval = 0;
+
+ struct rte_ether_addr bond_mac, client_mac;
+ struct rte_ether_addr *slave_mac1, *slave_mac2;
+
+ TEST_ASSERT_SUCCESS(
+ initialize_bonded_device_with_slaves(BONDING_MODE_ALB,
+ 0, TEST_ALB_SLAVE_COUNT, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ /* Flush tx queue */
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0);
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent,
+ MAX_PKT_BURST);
+ }
+
+ rte_ether_addr_copy(
+ rte_eth_devices[test_params->bonded_port_id].data->mac_addrs,
+ &bond_mac);
+
+ /*
+ * Generating four packets with different mac and ip addresses and placing
+ * them in the rx queue to be received by the bonding driver on rx_burst.
+ */
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client1, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host,
+ RTE_ARP_OP_REPLY);
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt,
+ 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client2, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client2, ip_host,
+ RTE_ARP_OP_REPLY);
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt,
+ 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client3, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client3, ip_host,
+ RTE_ARP_OP_REPLY);
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt,
+ 1);
+
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client4, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_ARP, 0, 0);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+ initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client4, ip_host,
+ RTE_ARP_OP_REPLY);
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt,
+ 1);
+
+ /*
+ * Issue rx_burst and tx_burst to force bonding driver to send update ARP
+ * packets to every client in alb table.
+ */
+ rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0);
+
+ slave_mac1 = rte_eth_devices[test_params->slave_port_ids[0]].data->mac_addrs;
+ slave_mac2 = rte_eth_devices[test_params->slave_port_ids[1]].data->mac_addrs;
+
+ /*
+ * Checking if update ARP packets were properly send on slave ports.
+ */
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent, MAX_PKT_BURST);
+ nb_pkts_sum += nb_pkts;
+
+ for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) {
+ eth_pkt = rte_pktmbuf_mtod(
+ pkts_sent[pkt_idx], struct rte_ether_hdr *);
+ arp_pkt = (struct rte_arp_hdr *)((char *)eth_pkt +
+ sizeof(struct rte_ether_hdr));
+
+ if (slave_idx%2 == 0) {
+ if (!rte_is_same_ether_addr(slave_mac1,
+ &arp_pkt->arp_data.arp_sha)) {
+ retval = -1;
+ goto test_end;
+ }
+ } else {
+ if (!rte_is_same_ether_addr(slave_mac2,
+ &arp_pkt->arp_data.arp_sha)) {
+ retval = -1;
+ goto test_end;
+ }
+ }
+ }
+ }
+
+ /* Check if proper number of packets was send */
+ if (nb_pkts_sum < 4) {
+ retval = -1;
+ goto test_end;
+ }
+
+test_end:
+ retval += remove_slaves_and_stop_bonded_device();
+ return retval;
+}
+
+static int
+test_alb_receive_vlan_reply(void)
+{
+ struct rte_ether_hdr *eth_pkt;
+ struct rte_vlan_hdr *vlan_pkt;
+ struct rte_arp_hdr *arp_pkt;
+
+ struct rte_mbuf *pkt;
+ struct rte_mbuf *pkts_sent[MAX_PKT_BURST];
+
+ int slave_idx, nb_pkts, pkt_idx;
+ int retval = 0;
+
+ struct rte_ether_addr bond_mac, client_mac;
+
+ TEST_ASSERT_SUCCESS(
+ initialize_bonded_device_with_slaves(BONDING_MODE_ALB,
+ 0, TEST_ALB_SLAVE_COUNT, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ /* Flush tx queue */
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0);
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent,
+ MAX_PKT_BURST);
+ }
+
+ rte_ether_addr_copy(
+ rte_eth_devices[test_params->bonded_port_id].data->mac_addrs,
+ &bond_mac);
+
+ /*
+ * Generating packet with double VLAN header and placing it in the rx queue.
+ */
+ pkt = rte_pktmbuf_alloc(test_params->mbuf_pool);
+ memcpy(client_mac.addr_bytes, mac_client1, RTE_ETHER_ADDR_LEN);
+ eth_pkt = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ initialize_eth_header(eth_pkt, &bond_mac, &client_mac,
+ RTE_ETHER_TYPE_VLAN, 0, 0);
+ vlan_pkt = (struct rte_vlan_hdr *)((char *)(eth_pkt + 1));
+ vlan_pkt->vlan_tci = rte_cpu_to_be_16(1);
+ vlan_pkt->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
+ vlan_pkt = vlan_pkt+1;
+ vlan_pkt->vlan_tci = rte_cpu_to_be_16(2);
+ vlan_pkt->eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP);
+ arp_pkt = (struct rte_arp_hdr *)((char *)(vlan_pkt + 1));
+ initialize_arp_header(arp_pkt, &client_mac, &bond_mac, ip_client1, ip_host,
+ RTE_ARP_OP_REPLY);
+ virtual_ethdev_add_mbufs_to_rx_queue(test_params->slave_port_ids[0], &pkt,
+ 1);
+
+ rte_eth_rx_burst(test_params->bonded_port_id, 0, pkts_sent, MAX_PKT_BURST);
+ rte_eth_tx_burst(test_params->bonded_port_id, 0, NULL, 0);
+
+ /*
+ * Checking if VLAN headers in generated ARP Update packet are correct.
+ */
+ for (slave_idx = 0; slave_idx < test_params->bonded_slave_count; slave_idx++) {
+ nb_pkts = virtual_ethdev_get_mbufs_from_tx_queue(
+ test_params->slave_port_ids[slave_idx], pkts_sent,
+ MAX_PKT_BURST);
+
+ for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) {
+ eth_pkt = rte_pktmbuf_mtod(
+ pkts_sent[pkt_idx], struct rte_ether_hdr *);
+ vlan_pkt = (struct rte_vlan_hdr *)(
+ (char *)(eth_pkt + 1));
+ if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(1)) {
+ retval = -1;
+ goto test_end;
+ }
+ if (vlan_pkt->eth_proto != rte_cpu_to_be_16(
+ RTE_ETHER_TYPE_VLAN)) {
+ retval = -1;
+ goto test_end;
+ }
+ vlan_pkt = vlan_pkt+1;
+ if (vlan_pkt->vlan_tci != rte_cpu_to_be_16(2)) {
+ retval = -1;
+ goto test_end;
+ }
+ if (vlan_pkt->eth_proto != rte_cpu_to_be_16(
+ RTE_ETHER_TYPE_ARP)) {
+ retval = -1;
+ goto test_end;
+ }
+ }
+ }
+
+test_end:
+ retval += remove_slaves_and_stop_bonded_device();
+ return retval;
+}
+
+static int
+test_alb_ipv4_tx(void)
+{
+ int burst_size, retval, pkts_send;
+ struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
+
+ retval = 0;
+
+ TEST_ASSERT_SUCCESS(
+ initialize_bonded_device_with_slaves(BONDING_MODE_ALB,
+ 0, TEST_ALB_SLAVE_COUNT, 1),
+ "Failed to initialize_bonded_device_with_slaves.");
+
+ burst_size = 32;
+
+ /* Generate test bursts of packets to transmit */
+ if (generate_test_burst(pkt_burst, burst_size, 0, 1, 0, 0, 0) != burst_size) {
+ retval = -1;
+ goto test_end;
+ }
+
+ /*
+ * Checking if ipv4 traffic is transmitted via TLB policy.
+ */
+ pkts_send = rte_eth_tx_burst(
+ test_params->bonded_port_id, 0, pkt_burst, burst_size);
+ if (pkts_send != burst_size) {
+ retval = -1;
+ goto test_end;
+ }
+
+test_end:
+ retval += remove_slaves_and_stop_bonded_device();
+ return retval;
+}
+
+static struct unit_test_suite link_bonding_test_suite = {
+ .suite_name = "Link Bonding Unit Test Suite",
+ .setup = test_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE(test_create_bonded_device),
+ TEST_CASE(test_create_bonded_device_with_invalid_params),
+ TEST_CASE(test_add_slave_to_bonded_device),
+ TEST_CASE(test_add_slave_to_invalid_bonded_device),
+ TEST_CASE(test_remove_slave_from_bonded_device),
+ TEST_CASE(test_remove_slave_from_invalid_bonded_device),
+ TEST_CASE(test_get_slaves_from_bonded_device),
+ TEST_CASE(test_add_already_bonded_slave_to_bonded_device),
+ TEST_CASE(test_add_remove_multiple_slaves_to_from_bonded_device),
+ TEST_CASE(test_start_bonded_device),
+ TEST_CASE(test_stop_bonded_device),
+ TEST_CASE(test_set_bonding_mode),
+ TEST_CASE(test_set_primary_slave),
+ TEST_CASE(test_set_explicit_bonded_mac),
+ TEST_CASE(test_set_bonded_port_initialization_mac_assignment),
+ TEST_CASE(test_status_interrupt),
+ TEST_CASE(test_adding_slave_after_bonded_device_started),
+ TEST_CASE(test_roundrobin_tx_burst),
+ TEST_CASE(test_roundrobin_tx_burst_slave_tx_fail),
+ TEST_CASE(test_roundrobin_rx_burst_on_single_slave),
+ TEST_CASE(test_roundrobin_rx_burst_on_multiple_slaves),
+ TEST_CASE(test_roundrobin_verify_promiscuous_enable_disable),
+ TEST_CASE(test_roundrobin_verify_mac_assignment),
+ TEST_CASE(test_roundrobin_verify_slave_link_status_change_behaviour),
+ TEST_CASE(test_roundrobin_verfiy_polling_slave_link_status_change),
+ TEST_CASE(test_activebackup_tx_burst),
+ TEST_CASE(test_activebackup_rx_burst),
+ TEST_CASE(test_activebackup_verify_promiscuous_enable_disable),
+ TEST_CASE(test_activebackup_verify_mac_assignment),
+ TEST_CASE(test_activebackup_verify_slave_link_status_change_failover),
+ TEST_CASE(test_balance_xmit_policy_configuration),
+ TEST_CASE(test_balance_l2_tx_burst),
+ TEST_CASE(test_balance_l23_tx_burst_ipv4_toggle_ip_addr),
+ TEST_CASE(test_balance_l23_tx_burst_vlan_ipv4_toggle_ip_addr),
+ TEST_CASE(test_balance_l23_tx_burst_ipv6_toggle_ip_addr),
+ TEST_CASE(test_balance_l23_tx_burst_vlan_ipv6_toggle_ip_addr),
+ TEST_CASE(test_balance_l23_tx_burst_toggle_mac_addr),
+ TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_ip_addr),
+ TEST_CASE(test_balance_l34_tx_burst_ipv4_toggle_udp_port),
+ TEST_CASE(test_balance_l34_tx_burst_vlan_ipv4_toggle_ip_addr),
+ TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_ip_addr),
+ TEST_CASE(test_balance_l34_tx_burst_vlan_ipv6_toggle_ip_addr),
+ TEST_CASE(test_balance_l34_tx_burst_ipv6_toggle_udp_port),
+ TEST_CASE(test_balance_tx_burst_slave_tx_fail),
+ TEST_CASE(test_balance_rx_burst),
+ TEST_CASE(test_balance_verify_promiscuous_enable_disable),
+ TEST_CASE(test_balance_verify_mac_assignment),
+ TEST_CASE(test_balance_verify_slave_link_status_change_behaviour),
+ TEST_CASE(test_tlb_tx_burst),
+ TEST_CASE(test_tlb_rx_burst),
+ TEST_CASE(test_tlb_verify_mac_assignment),
+ TEST_CASE(test_tlb_verify_promiscuous_enable_disable),
+ TEST_CASE(test_tlb_verify_slave_link_status_change_failover),
+ TEST_CASE(test_alb_change_mac_in_reply_sent),
+ TEST_CASE(test_alb_reply_from_client),
+ TEST_CASE(test_alb_receive_vlan_reply),
+ TEST_CASE(test_alb_ipv4_tx),
+ TEST_CASE(test_broadcast_tx_burst),
+ TEST_CASE(test_broadcast_tx_burst_slave_tx_fail),
+ TEST_CASE(test_broadcast_rx_burst),
+ TEST_CASE(test_broadcast_verify_promiscuous_enable_disable),
+ TEST_CASE(test_broadcast_verify_mac_assignment),
+ TEST_CASE(test_broadcast_verify_slave_link_status_change_behaviour),
+ TEST_CASE(test_reconfigure_bonded_device),
+ TEST_CASE(test_close_bonded_device),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+
+static int
+test_link_bonding(void)
+{
+ return unit_test_suite_runner(&link_bonding_test_suite);
+}
+
+REGISTER_TEST_COMMAND(link_bonding_autotest, test_link_bonding);
diff --git a/src/spdk/dpdk/app/test/test_link_bonding_mode4.c b/src/spdk/dpdk/app/test/test_link_bonding_mode4.c
new file mode 100644
index 000000000..cf12f026d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_link_bonding_mode4.c
@@ -0,0 +1,1675 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <rte_cycles.h>
+#include <sys/queue.h>
+
+#include <rte_byteorder.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_lcore.h>
+#include <rte_memory.h>
+
+#include <rte_string_fns.h>
+
+#include <rte_eth_ring.h>
+#include <rte_errno.h>
+#include <rte_eth_bond.h>
+#include <rte_eth_bond_8023ad.h>
+
+#include "packet_burst_generator.h"
+
+#include "test.h"
+
+#define SLAVE_COUNT (4)
+
+#define RX_RING_SIZE 1024
+#define TX_RING_SIZE 1024
+
+#define MBUF_CACHE_SIZE (250)
+#define BURST_SIZE (32)
+
+#define TEST_RX_DESC_MAX (2048)
+#define TEST_TX_DESC_MAX (2048)
+#define MAX_PKT_BURST (32)
+#define DEF_PKT_BURST (16)
+
+#define BONDED_DEV_NAME ("net_bonding_m4_bond_dev")
+
+#define SLAVE_DEV_NAME_FMT ("net_virt_%d")
+#define SLAVE_RX_QUEUE_FMT ("net_virt_%d_rx")
+#define SLAVE_TX_QUEUE_FMT ("net_virt_%d_tx")
+
+#define INVALID_SOCKET_ID (-1)
+#define INVALID_PORT_ID (0xFF)
+#define INVALID_BONDING_MODE (-1)
+
+static const struct rte_ether_addr slave_mac_default = {
+ { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 }
+};
+
+static const struct rte_ether_addr parnter_mac_default = {
+ { 0x22, 0xBB, 0xFF, 0xBB, 0x00, 0x00 }
+};
+
+static const struct rte_ether_addr parnter_system = {
+ { 0x33, 0xFF, 0xBB, 0xFF, 0x00, 0x00 }
+};
+
+static const struct rte_ether_addr slow_protocol_mac_addr = {
+ { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 }
+};
+
+struct slave_conf {
+ struct rte_ring *rx_queue;
+ struct rte_ring *tx_queue;
+ uint16_t port_id;
+ uint8_t bonded : 1;
+
+ uint8_t lacp_parnter_state;
+};
+
+struct ether_vlan_hdr {
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_vlan_hdr vlan_hdr;
+};
+
+struct link_bonding_unittest_params {
+ uint8_t bonded_port_id;
+ struct slave_conf slave_ports[SLAVE_COUNT];
+
+ struct rte_mempool *mbuf_pool;
+};
+
+#define TEST_DEFAULT_SLAVE_COUNT RTE_DIM(test_params.slave_ports)
+#define TEST_RX_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
+#define TEST_TX_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
+#define TEST_MARKER_SLAVE_COUT TEST_DEFAULT_SLAVE_COUNT
+#define TEST_EXPIRED_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
+#define TEST_PROMISC_SLAVE_COUNT TEST_DEFAULT_SLAVE_COUNT
+
+static struct link_bonding_unittest_params test_params = {
+ .bonded_port_id = INVALID_PORT_ID,
+ .slave_ports = { [0 ... SLAVE_COUNT - 1] = { .port_id = INVALID_PORT_ID} },
+
+ .mbuf_pool = NULL,
+};
+
+static struct rte_eth_conf default_pmd_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ .lpbk_mode = 0,
+};
+
+static uint8_t lacpdu_rx_count[RTE_MAX_ETHPORTS] = {0, };
+
+#define FOR_EACH(_i, _item, _array, _size) \
+ for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
+
+/* Macro for iterating over every port that can be used as a slave
+ * in this test.
+ * _i variable used as an index in test_params->slave_ports
+ * _slave pointer to &test_params->slave_ports[_idx]
+ */
+#define FOR_EACH_PORT(_i, _port) \
+ FOR_EACH(_i, _port, test_params.slave_ports, \
+ RTE_DIM(test_params.slave_ports))
+
+/* Macro for iterating over every port that can be used as a slave
+ * in this test and satisfy given condition.
+ *
+ * _i variable used as an index in test_params->slave_ports
+ * _slave pointer to &test_params->slave_ports[_idx]
+ * _condition condition that need to be checked
+ */
+#define FOR_EACH_PORT_IF(_i, _port, _condition) FOR_EACH_PORT((_i), (_port)) \
+ if (!!(_condition))
+
+/* Macro for iterating over every port that is currently a slave of a bonded
+ * device.
+ * _i variable used as an index in test_params->slave_ports
+ * _slave pointer to &test_params->slave_ports[_idx]
+ * */
+#define FOR_EACH_SLAVE(_i, _slave) \
+ FOR_EACH_PORT_IF(_i, _slave, (_slave)->bonded != 0)
+
+/*
+ * Returns packets from slaves TX queue.
+ * slave slave port
+ * buffer for packets
+ * size size of buffer
+ * return number of packets or negative error number
+ */
+static int
+slave_get_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size)
+{
+ return rte_ring_dequeue_burst(slave->tx_queue, (void **)buf,
+ size, NULL);
+}
+
+/*
+ * Injects given packets into slaves RX queue.
+ * slave slave port
+ * buffer for packets
+ * size number of packets to be injected
+ * return number of queued packets or negative error number
+ */
+static int
+slave_put_pkts(struct slave_conf *slave, struct rte_mbuf **buf, uint16_t size)
+{
+ return rte_ring_enqueue_burst(slave->rx_queue, (void **)buf,
+ size, NULL);
+}
+
+static uint16_t
+bond_rx(struct rte_mbuf **buf, uint16_t size)
+{
+ return rte_eth_rx_burst(test_params.bonded_port_id, 0, buf, size);
+}
+
+static uint16_t
+bond_tx(struct rte_mbuf **buf, uint16_t size)
+{
+ return rte_eth_tx_burst(test_params.bonded_port_id, 0, buf, size);
+}
+
+static void
+free_pkts(struct rte_mbuf **pkts, uint16_t count)
+{
+ uint16_t i;
+
+ for (i = 0; i < count; i++) {
+ if (pkts[i] != NULL)
+ rte_pktmbuf_free(pkts[i]);
+ }
+}
+
+static int
+configure_ethdev(uint16_t port_id, uint8_t start)
+{
+ TEST_ASSERT(rte_eth_dev_configure(port_id, 1, 1, &default_pmd_conf) == 0,
+ "Failed to configure device %u", port_id);
+
+ TEST_ASSERT(rte_eth_rx_queue_setup(port_id, 0, RX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), NULL, test_params.mbuf_pool) == 0,
+ "Failed to setup rx queue.");
+
+ TEST_ASSERT(rte_eth_tx_queue_setup(port_id, 0, TX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), NULL) == 0,
+ "Failed to setup tx queue.");
+
+ if (start) {
+ TEST_ASSERT(rte_eth_dev_start(port_id) == 0,
+ "Failed to start device (%d).", port_id);
+ }
+ return 0;
+}
+
+static int
+add_slave(struct slave_conf *slave, uint8_t start)
+{
+ struct rte_ether_addr addr, addr_check;
+ int retval;
+
+ /* Some sanity check */
+ RTE_VERIFY(test_params.slave_ports <= slave &&
+ slave - test_params.slave_ports < (int)RTE_DIM(test_params.slave_ports));
+ RTE_VERIFY(slave->bonded == 0);
+ RTE_VERIFY(slave->port_id != INVALID_PORT_ID);
+
+ rte_ether_addr_copy(&slave_mac_default, &addr);
+ addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id;
+
+ rte_eth_dev_mac_addr_remove(slave->port_id, &addr);
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_mac_addr_add(slave->port_id, &addr, 0),
+ "Failed to set slave MAC address");
+
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bonded_port_id,
+ slave->port_id),
+ "Failed to add slave (idx=%u, id=%u) to bonding (id=%u)",
+ (uint8_t)(slave - test_params.slave_ports), slave->port_id,
+ test_params.bonded_port_id);
+
+ slave->bonded = 1;
+ if (start) {
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(slave->port_id),
+ "Failed to start slave %u", slave->port_id);
+ }
+
+ retval = rte_eth_macaddr_get(slave->port_id, &addr_check);
+ TEST_ASSERT_SUCCESS(retval, "Failed to get slave mac address: %s",
+ strerror(-retval));
+ TEST_ASSERT_EQUAL(rte_is_same_ether_addr(&addr, &addr_check), 1,
+ "Slave MAC address is not as expected");
+
+ RTE_VERIFY(slave->lacp_parnter_state == 0);
+ return 0;
+}
+
+static int
+remove_slave(struct slave_conf *slave)
+{
+ ptrdiff_t slave_idx = slave - test_params.slave_ports;
+
+ RTE_VERIFY(test_params.slave_ports <= slave &&
+ slave_idx < (ptrdiff_t)RTE_DIM(test_params.slave_ports));
+
+ RTE_VERIFY(slave->bonded == 1);
+ RTE_VERIFY(slave->port_id != INVALID_PORT_ID);
+
+ TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0,
+ "Slave %u tx queue not empty while removing from bonding.",
+ slave->port_id);
+
+ TEST_ASSERT_EQUAL(rte_ring_count(slave->rx_queue), 0,
+ "Slave %u tx queue not empty while removing from bonding.",
+ slave->port_id);
+
+ TEST_ASSERT_EQUAL(rte_eth_bond_slave_remove(test_params.bonded_port_id,
+ slave->port_id), 0,
+ "Failed to remove slave (idx=%u, id=%u) from bonding (id=%u)",
+ (uint8_t)slave_idx, slave->port_id,
+ test_params.bonded_port_id);
+
+ slave->bonded = 0;
+ slave->lacp_parnter_state = 0;
+ return 0;
+}
+
+static void
+lacp_recv_cb(uint16_t slave_id, struct rte_mbuf *lacp_pkt)
+{
+ struct rte_ether_hdr *hdr;
+ struct slow_protocol_frame *slow_hdr;
+
+ RTE_VERIFY(lacp_pkt != NULL);
+
+ hdr = rte_pktmbuf_mtod(lacp_pkt, struct rte_ether_hdr *);
+ RTE_VERIFY(hdr->ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW));
+
+ slow_hdr = rte_pktmbuf_mtod(lacp_pkt, struct slow_protocol_frame *);
+ RTE_VERIFY(slow_hdr->slow_protocol.subtype == SLOW_SUBTYPE_LACP);
+
+ lacpdu_rx_count[slave_id]++;
+ rte_pktmbuf_free(lacp_pkt);
+}
+
+static int
+initialize_bonded_device_with_slaves(uint16_t slave_count, uint8_t external_sm)
+{
+ uint8_t i;
+ int ret;
+
+ RTE_VERIFY(test_params.bonded_port_id != INVALID_PORT_ID);
+
+ for (i = 0; i < slave_count; i++) {
+ TEST_ASSERT_SUCCESS(add_slave(&test_params.slave_ports[i], 1),
+ "Failed to add port %u to bonded device.\n",
+ test_params.slave_ports[i].port_id);
+ }
+
+ /* Reset mode 4 configuration */
+ rte_eth_bond_8023ad_setup(test_params.bonded_port_id, NULL);
+ ret = rte_eth_promiscuous_disable(test_params.bonded_port_id);
+ TEST_ASSERT_SUCCESS(ret,
+ "Failed disable promiscuous mode for port %d: %s",
+ test_params.bonded_port_id, rte_strerror(-ret));
+
+ if (external_sm) {
+ struct rte_eth_bond_8023ad_conf conf;
+
+ rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
+ conf.slowrx_cb = lacp_recv_cb;
+ rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf);
+
+ }
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bonded_port_id),
+ "Failed to start bonded device");
+
+ return TEST_SUCCESS;
+}
+
+static int
+remove_slaves_and_stop_bonded_device(void)
+{
+ struct slave_conf *slave;
+ int retval;
+ uint16_t slaves[RTE_MAX_ETHPORTS];
+ uint16_t i;
+
+ rte_eth_dev_stop(test_params.bonded_port_id);
+
+ FOR_EACH_SLAVE(i, slave)
+ remove_slave(slave);
+
+ retval = rte_eth_bond_slaves_get(test_params.bonded_port_id, slaves,
+ RTE_DIM(slaves));
+
+ TEST_ASSERT_EQUAL(retval, 0,
+ "Expected bonded device %u have 0 slaves but returned %d.",
+ test_params.bonded_port_id, retval);
+
+ FOR_EACH_PORT(i, slave) {
+ rte_eth_dev_stop(slave->port_id);
+
+ TEST_ASSERT(slave->bonded == 0,
+ "Port id=%u is still marked as enslaved.", slave->port_id);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_setup(void)
+{
+ int retval, nb_mbuf_per_pool;
+ char name[RTE_ETH_NAME_MAX_LEN];
+ struct slave_conf *port;
+ const uint8_t socket_id = rte_socket_id();
+ uint16_t i;
+
+ if (test_params.mbuf_pool == NULL) {
+ nb_mbuf_per_pool = TEST_RX_DESC_MAX + DEF_PKT_BURST +
+ TEST_TX_DESC_MAX + MAX_PKT_BURST;
+ test_params.mbuf_pool = rte_pktmbuf_pool_create("TEST_MODE4",
+ nb_mbuf_per_pool, MBUF_CACHE_SIZE, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE, socket_id);
+
+ TEST_ASSERT(test_params.mbuf_pool != NULL,
+ "rte_mempool_create failed\n");
+ }
+
+ /* Create / initialize ring eth devs. */
+ FOR_EACH_PORT(i, port) {
+ port = &test_params.slave_ports[i];
+
+ if (port->rx_queue == NULL) {
+ retval = snprintf(name, RTE_DIM(name), SLAVE_RX_QUEUE_FMT, i);
+ TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long");
+ port->rx_queue = rte_ring_create(name, RX_RING_SIZE, socket_id, 0);
+ TEST_ASSERT(port->rx_queue != NULL,
+ "Failed to allocate rx ring '%s': %s", name,
+ rte_strerror(rte_errno));
+ }
+
+ if (port->tx_queue == NULL) {
+ retval = snprintf(name, RTE_DIM(name), SLAVE_TX_QUEUE_FMT, i);
+ TEST_ASSERT(retval <= (int)RTE_DIM(name) - 1, "Name too long");
+ port->tx_queue = rte_ring_create(name, TX_RING_SIZE, socket_id, 0);
+ TEST_ASSERT_NOT_NULL(port->tx_queue,
+ "Failed to allocate tx ring '%s': %s", name,
+ rte_strerror(rte_errno));
+ }
+
+ if (port->port_id == INVALID_PORT_ID) {
+ retval = snprintf(name, RTE_DIM(name), SLAVE_DEV_NAME_FMT, i);
+ TEST_ASSERT(retval < (int)RTE_DIM(name) - 1, "Name too long");
+ retval = rte_eth_from_rings(name, &port->rx_queue, 1,
+ &port->tx_queue, 1, socket_id);
+ TEST_ASSERT(retval >= 0,
+ "Failed to create ring ethdev '%s'\n", name);
+
+ port->port_id = rte_eth_dev_count_avail() - 1;
+ }
+
+ retval = configure_ethdev(port->port_id, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n",
+ name);
+ }
+
+ if (test_params.bonded_port_id == INVALID_PORT_ID) {
+ retval = rte_eth_bond_create(BONDED_DEV_NAME, BONDING_MODE_8023AD,
+ socket_id);
+
+ TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s",
+ BONDED_DEV_NAME);
+
+ test_params.bonded_port_id = retval;
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bonded_port_id, 0),
+ "Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
+ } else if (rte_eth_bond_mode_get(test_params.bonded_port_id) !=
+ BONDING_MODE_8023AD) {
+ TEST_ASSERT(rte_eth_bond_mode_set(test_params.bonded_port_id,
+ BONDING_MODE_8023AD) == 0,
+ "Failed to set ethdev %d to mode %d",
+ test_params.bonded_port_id, BONDING_MODE_8023AD);
+ }
+
+ return 0;
+}
+
+static void
+testsuite_teardown(void)
+{
+ struct slave_conf *port;
+ uint8_t i;
+
+ /* Only stop ports.
+ * Any cleanup/reset state is done when particular test is
+ * started. */
+
+ rte_eth_dev_stop(test_params.bonded_port_id);
+
+ FOR_EACH_PORT(i, port)
+ rte_eth_dev_stop(port->port_id);
+}
+
+/*
+ * Check if given LACP packet. If it is, make make replay packet to force
+ * COLLECTING state.
+ * return 0 when pkt is LACP frame, 1 if it is not slow frame, 2 if it is slow
+ * frame but not LACP
+ */
+static int
+make_lacp_reply(struct slave_conf *slave, struct rte_mbuf *pkt)
+{
+ struct rte_ether_hdr *hdr;
+ struct slow_protocol_frame *slow_hdr;
+ struct lacpdu *lacp;
+
+ /* look for LACP */
+ hdr = rte_pktmbuf_mtod(pkt, struct rte_ether_hdr *);
+ if (hdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW))
+ return 1;
+
+ slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *);
+ /* ignore packets of other types */
+ if (slow_hdr->slow_protocol.subtype != SLOW_SUBTYPE_LACP)
+ return 2;
+
+ slow_hdr = rte_pktmbuf_mtod(pkt, struct slow_protocol_frame *);
+
+ /* Change source address to partner address */
+ rte_ether_addr_copy(&parnter_mac_default, &slow_hdr->eth_hdr.s_addr);
+ slow_hdr->eth_hdr.s_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] =
+ slave->port_id;
+
+ lacp = (struct lacpdu *) &slow_hdr->slow_protocol;
+ /* Save last received state */
+ slave->lacp_parnter_state = lacp->actor.state;
+ /* Change it into LACP replay by matching parameters. */
+ memcpy(&lacp->partner.port_params, &lacp->actor.port_params,
+ sizeof(struct port_params));
+
+ lacp->partner.state = lacp->actor.state;
+
+ rte_ether_addr_copy(&parnter_system, &lacp->actor.port_params.system);
+ lacp->actor.state = STATE_LACP_ACTIVE |
+ STATE_SYNCHRONIZATION |
+ STATE_AGGREGATION |
+ STATE_COLLECTING |
+ STATE_DISTRIBUTING;
+
+ return 0;
+}
+
+/*
+ * Reads packets from given slave, search for LACP packet and reply them.
+ *
+ * Receives burst of packets from slave. Looks for LACP packet. Drops
+ * all other packets. Prepares response LACP and sends it back.
+ *
+ * return number of LACP received and replied, -1 on error.
+ */
+static int
+bond_handshake_reply(struct slave_conf *slave)
+{
+ int retval;
+ struct rte_mbuf *rx_buf[MAX_PKT_BURST];
+ struct rte_mbuf *lacp_tx_buf[MAX_PKT_BURST];
+ uint16_t lacp_tx_buf_cnt = 0, i;
+
+ retval = slave_get_pkts(slave, rx_buf, RTE_DIM(rx_buf));
+ TEST_ASSERT(retval >= 0, "Getting slave %u packets failed.",
+ slave->port_id);
+
+ for (i = 0; i < (uint16_t)retval; i++) {
+ if (make_lacp_reply(slave, rx_buf[i]) == 0) {
+ /* reply with actor's LACP */
+ lacp_tx_buf[lacp_tx_buf_cnt++] = rx_buf[i];
+ } else
+ rte_pktmbuf_free(rx_buf[i]);
+ }
+
+ if (lacp_tx_buf_cnt == 0)
+ return 0;
+
+ retval = slave_put_pkts(slave, lacp_tx_buf, lacp_tx_buf_cnt);
+ if (retval <= lacp_tx_buf_cnt) {
+ /* retval might be negative */
+ for (i = RTE_MAX(0, retval); retval < lacp_tx_buf_cnt; retval++)
+ rte_pktmbuf_free(lacp_tx_buf[i]);
+ }
+
+ TEST_ASSERT_EQUAL(retval, lacp_tx_buf_cnt,
+ "Failed to equeue lacp packets into slave %u tx queue.",
+ slave->port_id);
+
+ return lacp_tx_buf_cnt;
+}
+
+/*
+ * Function check if given slave tx queue contains packets that make mode 4
+ * handshake complete. It will drain slave queue.
+ * return 0 if handshake not completed, 1 if handshake was complete,
+ */
+static int
+bond_handshake_done(struct slave_conf *slave)
+{
+ const uint8_t expected_state = STATE_LACP_ACTIVE | STATE_SYNCHRONIZATION |
+ STATE_AGGREGATION | STATE_COLLECTING | STATE_DISTRIBUTING;
+
+ return slave->lacp_parnter_state == expected_state;
+}
+
+static unsigned
+bond_get_update_timeout_ms(void)
+{
+ struct rte_eth_bond_8023ad_conf conf;
+
+ if (rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf) < 0) {
+ RTE_LOG(DEBUG, EAL, "Failed to get bonding configuration: "
+ "%s at %d\n", __func__, __LINE__);
+ RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__);
+ return 0;
+ }
+
+ return conf.update_timeout_ms;
+}
+
+/*
+ * Exchanges LACP packets with partner to achieve dynamic port configuration.
+ * return TEST_SUCCESS if initial handshake succeed, TEST_FAILED otherwise.
+ */
+static int
+bond_handshake(void)
+{
+ struct slave_conf *slave;
+ struct rte_mbuf *buf[MAX_PKT_BURST];
+ uint16_t nb_pkts;
+ uint8_t all_slaves_done, i, j;
+ uint8_t status[RTE_DIM(test_params.slave_ports)] = { 0 };
+ const unsigned delay = bond_get_update_timeout_ms();
+
+ /* Exchange LACP frames */
+ all_slaves_done = 0;
+ for (i = 0; i < 30 && all_slaves_done == 0; ++i) {
+ rte_delay_ms(delay);
+
+ all_slaves_done = 1;
+ FOR_EACH_SLAVE(j, slave) {
+ /* If response already send, skip slave */
+ if (status[j] != 0)
+ continue;
+
+ if (bond_handshake_reply(slave) < 0) {
+ all_slaves_done = 0;
+ break;
+ }
+
+ status[j] = bond_handshake_done(slave);
+ if (status[j] == 0)
+ all_slaves_done = 0;
+ }
+
+ nb_pkts = bond_tx(NULL, 0);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly");
+
+ nb_pkts = bond_rx(buf, RTE_DIM(buf));
+ free_pkts(buf, nb_pkts);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly");
+ }
+ /* If response didn't send - report failure */
+ TEST_ASSERT_EQUAL(all_slaves_done, 1, "Bond handshake failed\n");
+
+ /* If flags doesn't match - report failure */
+ return all_slaves_done == 1 ? TEST_SUCCESS : TEST_FAILED;
+}
+
+#define TEST_LACP_SLAVE_COUT RTE_DIM(test_params.slave_ports)
+static int
+test_mode4_lacp(void)
+{
+ int retval;
+
+ retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ /* Test LACP handshake function */
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+static int
+test_mode4_agg_mode_selection(void)
+{
+ int retval;
+ /* Test and verify for Stable mode */
+ retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+
+ retval = rte_eth_bond_8023ad_agg_selection_set(
+ test_params.bonded_port_id, AGG_STABLE);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bond aggregation mode");
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+
+ retval = rte_eth_bond_8023ad_agg_selection_get(
+ test_params.bonded_port_id);
+ TEST_ASSERT_EQUAL(retval, AGG_STABLE,
+ "Wrong agg mode received from bonding device");
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+
+ /* test and verify for Bandwidth mode */
+ retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+
+ retval = rte_eth_bond_8023ad_agg_selection_set(
+ test_params.bonded_port_id,
+ AGG_BANDWIDTH);
+ TEST_ASSERT_SUCCESS(retval,
+ "Failed to initialize bond aggregation mode");
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ retval = rte_eth_bond_8023ad_agg_selection_get(
+ test_params.bonded_port_id);
+ TEST_ASSERT_EQUAL(retval, AGG_BANDWIDTH,
+ "Wrong agg mode received from bonding device");
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ /* test and verify selection for count mode */
+ retval = initialize_bonded_device_with_slaves(TEST_LACP_SLAVE_COUT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+
+ retval = rte_eth_bond_8023ad_agg_selection_set(
+ test_params.bonded_port_id, AGG_COUNT);
+ TEST_ASSERT_SUCCESS(retval,
+ "Failed to initialize bond aggregation mode");
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ retval = rte_eth_bond_8023ad_agg_selection_get(
+ test_params.bonded_port_id);
+ TEST_ASSERT_EQUAL(retval, AGG_COUNT,
+ "Wrong agg mode received from bonding device");
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+static int
+generate_packets(struct rte_ether_addr *src_mac,
+ struct rte_ether_addr *dst_mac, uint16_t count, struct rte_mbuf **buf)
+{
+ uint16_t pktlen = PACKET_BURST_GEN_PKT_LEN;
+ uint8_t vlan_enable = 0;
+ uint16_t vlan_id = 0;
+ uint8_t ip4_type = 1; /* 0 - ipv6 */
+
+ uint16_t src_port = 10, dst_port = 20;
+
+ uint32_t ip_src[4] = { [0 ... 2] = 0xDEADBEEF, [3] = RTE_IPV4(192, 168, 0, 1) };
+ uint32_t ip_dst[4] = { [0 ... 2] = 0xFEEDFACE, [3] = RTE_IPV4(192, 168, 0, 2) };
+
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_udp_hdr pkt_udp_hdr;
+ union {
+ struct rte_ipv4_hdr v4;
+ struct rte_ipv6_hdr v6;
+ } pkt_ip_hdr;
+
+ int retval;
+
+ initialize_eth_header(&pkt_eth_hdr, src_mac, dst_mac, ip4_type,
+ vlan_enable, vlan_id);
+
+ if (ip4_type)
+ initialize_ipv4_header(&pkt_ip_hdr.v4, ip_src[3], ip_dst[3], pktlen);
+ else
+ initialize_ipv6_header(&pkt_ip_hdr.v6, (uint8_t *)ip_src,
+ (uint8_t *)&ip_dst, pktlen);
+
+ initialize_udp_header(&pkt_udp_hdr, src_port, dst_port, 16);
+
+ retval = generate_packet_burst(test_params.mbuf_pool, buf,
+ &pkt_eth_hdr, vlan_enable, &pkt_ip_hdr, 1, &pkt_udp_hdr,
+ count, pktlen, 1);
+
+ if (retval > 0 && retval != count)
+ free_pkts(&buf[count - retval], retval);
+
+ TEST_ASSERT_EQUAL(retval, count, "Failed to generate %u packets",
+ count);
+
+ return count;
+}
+
+static int
+generate_and_put_packets(struct slave_conf *slave,
+ struct rte_ether_addr *src_mac,
+ struct rte_ether_addr *dst_mac, uint16_t count)
+{
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ int retval;
+
+ retval = generate_packets(src_mac, dst_mac, count, pkts);
+ if (retval != (int)count)
+ return retval;
+
+ retval = slave_put_pkts(slave, pkts, count);
+ if (retval > 0 && retval != count)
+ free_pkts(&pkts[retval], count - retval);
+
+ TEST_ASSERT_EQUAL(retval, count,
+ "Failed to enqueue packets into slave %u RX queue", slave->port_id);
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_mode4_rx(void)
+{
+ struct slave_conf *slave;
+ uint16_t i, j;
+
+ uint16_t expected_pkts_cnt;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ int retval;
+ unsigned delay;
+
+ struct rte_ether_hdr *hdr;
+
+ struct rte_ether_addr src_mac = {
+ { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
+ struct rte_ether_addr dst_mac;
+ struct rte_ether_addr bonded_mac;
+
+ retval = initialize_bonded_device_with_slaves(TEST_PROMISC_SLAVE_COUNT,
+ 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac);
+ TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s",
+ strerror(-retval));
+ rte_ether_addr_copy(&bonded_mac, &dst_mac);
+
+ /* Assert that dst address is not bonding address. Do not set the
+ * least significant bit of the zero byte as this would create a
+ * multicast address.
+ */
+ dst_mac.addr_bytes[0] += 2;
+
+ /* First try with promiscuous mode enabled.
+ * Add 2 packets to each slave. First with bonding MAC address, second with
+ * different. Check if we received all of them. */
+ retval = rte_eth_promiscuous_enable(test_params.bonded_port_id);
+ TEST_ASSERT_SUCCESS(retval,
+ "Failed to enable promiscuous mode for port %d: %s",
+ test_params.bonded_port_id, rte_strerror(-retval));
+
+ expected_pkts_cnt = 0;
+ FOR_EACH_SLAVE(i, slave) {
+ retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
+ slave->port_id);
+
+ retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
+ slave->port_id);
+
+ /* Expect 2 packets per slave */
+ expected_pkts_cnt += 2;
+ }
+
+ retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
+ RTE_DIM(pkts));
+
+ if (retval == expected_pkts_cnt) {
+ int cnt[2] = { 0, 0 };
+
+ for (i = 0; i < expected_pkts_cnt; i++) {
+ hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *);
+ cnt[rte_is_same_ether_addr(&hdr->d_addr,
+ &bonded_mac)]++;
+ }
+
+ free_pkts(pkts, expected_pkts_cnt);
+
+ /* For division by 2 expected_pkts_cnt must be even */
+ RTE_VERIFY((expected_pkts_cnt & 1) == 0);
+ TEST_ASSERT(cnt[0] == expected_pkts_cnt / 2 &&
+ cnt[1] == expected_pkts_cnt / 2,
+ "Expected %u packets with the same MAC and %u with different but "
+ "got %u with the same and %u with different MAC",
+ expected_pkts_cnt / 2, expected_pkts_cnt / 2, cnt[1], cnt[0]);
+ } else if (retval > 0)
+ free_pkts(pkts, retval);
+
+ TEST_ASSERT_EQUAL(retval, expected_pkts_cnt,
+ "Expected %u packets but received only %d", expected_pkts_cnt, retval);
+
+ /* Now, disable promiscuous mode. When promiscuous mode is disabled we
+ * expect to receive only packets that are directed to bonding port. */
+ retval = rte_eth_promiscuous_disable(test_params.bonded_port_id);
+ TEST_ASSERT_SUCCESS(retval,
+ "Failed to disable promiscuous mode for port %d: %s",
+ test_params.bonded_port_id, rte_strerror(-retval));
+
+ expected_pkts_cnt = 0;
+ FOR_EACH_SLAVE(i, slave) {
+ retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
+ slave->port_id);
+
+ retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to enqueue packets to slave %u",
+ slave->port_id);
+
+ /* Expect only one packet per slave */
+ expected_pkts_cnt += 1;
+ }
+
+ retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
+ RTE_DIM(pkts));
+
+ if (retval == expected_pkts_cnt) {
+ int eq_cnt = 0;
+
+ for (i = 0; i < expected_pkts_cnt; i++) {
+ hdr = rte_pktmbuf_mtod(pkts[i], struct rte_ether_hdr *);
+ eq_cnt += rte_is_same_ether_addr(&hdr->d_addr,
+ &bonded_mac);
+ }
+
+ free_pkts(pkts, expected_pkts_cnt);
+ TEST_ASSERT_EQUAL(eq_cnt, expected_pkts_cnt, "Packet address mismatch");
+ } else if (retval > 0)
+ free_pkts(pkts, retval);
+
+ TEST_ASSERT_EQUAL(retval, expected_pkts_cnt,
+ "Expected %u packets but received only %d", expected_pkts_cnt, retval);
+
+ /* Link down test: simulate link down for first slave. */
+ delay = bond_get_update_timeout_ms();
+
+ uint8_t slave_down_id = INVALID_PORT_ID;
+
+ /* Find first slave and make link down on it*/
+ FOR_EACH_SLAVE(i, slave) {
+ rte_eth_dev_set_link_down(slave->port_id);
+ slave_down_id = slave->port_id;
+ break;
+ }
+
+ RTE_VERIFY(slave_down_id != INVALID_PORT_ID);
+
+ /* Give some time to rearrange bonding */
+ for (i = 0; i < 3; i++) {
+ rte_delay_ms(delay);
+ bond_handshake();
+ }
+
+ TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
+
+ /* Put packet to each slave */
+ FOR_EACH_SLAVE(i, slave) {
+ void *pkt = NULL;
+
+ dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id;
+ retval = generate_and_put_packets(slave, &src_mac, &dst_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst.");
+
+ src_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = slave->port_id;
+ retval = generate_and_put_packets(slave, &src_mac, &bonded_mac, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to generate test packet burst.");
+
+ retval = bond_rx(pkts, RTE_DIM(pkts));
+
+ /* Clean anything */
+ if (retval > 0)
+ free_pkts(pkts, retval);
+
+ while (rte_ring_dequeue(slave->rx_queue, (void **)&pkt) == 0)
+ rte_pktmbuf_free(pkt);
+
+ if (slave_down_id == slave->port_id)
+ TEST_ASSERT_EQUAL(retval, 0, "Packets received unexpectedly.");
+ else
+ TEST_ASSERT_NOT_EQUAL(retval, 0,
+ "Expected to receive some packets on slave %u.",
+ slave->port_id);
+ rte_eth_dev_start(slave->port_id);
+
+ for (j = 0; j < 5; j++) {
+ TEST_ASSERT(bond_handshake_reply(slave) >= 0,
+ "Handshake after link up");
+
+ if (bond_handshake_done(slave) == 1)
+ break;
+ }
+
+ TEST_ASSERT(j < 5, "Failed to aggregate slave after link up");
+ }
+
+ remove_slaves_and_stop_bonded_device();
+ return TEST_SUCCESS;
+}
+
+static int
+test_mode4_tx_burst(void)
+{
+ struct slave_conf *slave;
+ uint16_t i, j;
+
+ uint16_t exp_pkts_cnt, pkts_cnt = 0;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ int retval;
+ unsigned delay;
+
+ struct rte_ether_addr dst_mac = {
+ { 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } };
+ struct rte_ether_addr bonded_mac;
+
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ retval = rte_eth_macaddr_get(test_params.bonded_port_id, &bonded_mac);
+ TEST_ASSERT_SUCCESS(retval, "Failed to get mac address: %s",
+ strerror(-retval));
+ /* Prepare burst */
+ for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) {
+ dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt;
+ retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]);
+
+ if (retval != 1)
+ free_pkts(pkts, pkts_cnt);
+
+ TEST_ASSERT_EQUAL(retval, 1, "Failed to generate packet %u", pkts_cnt);
+ }
+ exp_pkts_cnt = pkts_cnt;
+
+ /* Transmit packets on bonded device */
+ retval = bond_tx(pkts, pkts_cnt);
+ if (retval > 0 && retval < pkts_cnt)
+ free_pkts(&pkts[retval], pkts_cnt - retval);
+
+ TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed");
+
+ /* Check if packets were transmitted properly. Every slave should have
+ * at least one packet, and sum must match. Under normal operation
+ * there should be no LACP nor MARKER frames. */
+ pkts_cnt = 0;
+ FOR_EACH_SLAVE(i, slave) {
+ uint16_t normal_cnt, slow_cnt;
+
+ retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts));
+ normal_cnt = 0;
+ slow_cnt = 0;
+
+ for (j = 0; j < retval; j++) {
+ if (make_lacp_reply(slave, pkts[j]) == 1)
+ normal_cnt++;
+ else
+ slow_cnt++;
+ }
+
+ free_pkts(pkts, normal_cnt + slow_cnt);
+ TEST_ASSERT_EQUAL(slow_cnt, 0,
+ "slave %u unexpectedly transmitted %d SLOW packets", slave->port_id,
+ slow_cnt);
+
+ TEST_ASSERT_NOT_EQUAL(normal_cnt, 0,
+ "slave %u did not transmitted any packets", slave->port_id);
+
+ pkts_cnt += normal_cnt;
+ }
+
+ TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt,
+ "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt);
+
+ /* Link down test:
+ * simulate link down for first slave. */
+ delay = bond_get_update_timeout_ms();
+
+ uint8_t slave_down_id = INVALID_PORT_ID;
+
+ FOR_EACH_SLAVE(i, slave) {
+ rte_eth_dev_set_link_down(slave->port_id);
+ slave_down_id = slave->port_id;
+ break;
+ }
+
+ RTE_VERIFY(slave_down_id != INVALID_PORT_ID);
+
+ /* Give some time to rearrange bonding. */
+ for (i = 0; i < 3; i++) {
+ bond_handshake();
+ rte_delay_ms(delay);
+ }
+
+ TEST_ASSERT_SUCCESS(bond_handshake(), "Handshake after link down failed");
+
+ /* Prepare burst. */
+ for (pkts_cnt = 0; pkts_cnt < RTE_DIM(pkts); pkts_cnt++) {
+ dst_mac.addr_bytes[RTE_ETHER_ADDR_LEN - 1] = pkts_cnt;
+ retval = generate_packets(&bonded_mac, &dst_mac, 1, &pkts[pkts_cnt]);
+
+ if (retval != 1)
+ free_pkts(pkts, pkts_cnt);
+
+ TEST_ASSERT_EQUAL(retval, 1, "Failed to generate test packet %u",
+ pkts_cnt);
+ }
+ exp_pkts_cnt = pkts_cnt;
+
+ /* Transmit packets on bonded device. */
+ retval = bond_tx(pkts, pkts_cnt);
+ if (retval > 0 && retval < pkts_cnt)
+ free_pkts(&pkts[retval], pkts_cnt - retval);
+
+ TEST_ASSERT_EQUAL(retval, pkts_cnt, "TX on bonded device failed");
+
+ /* Check if packets was transmitted properly. Every slave should have
+ * at least one packet, and sum must match. Under normal operation
+ * there should be no LACP nor MARKER frames. */
+ pkts_cnt = 0;
+ FOR_EACH_SLAVE(i, slave) {
+ uint16_t normal_cnt, slow_cnt;
+
+ retval = slave_get_pkts(slave, pkts, RTE_DIM(pkts));
+ normal_cnt = 0;
+ slow_cnt = 0;
+
+ for (j = 0; j < retval; j++) {
+ if (make_lacp_reply(slave, pkts[j]) == 1)
+ normal_cnt++;
+ else
+ slow_cnt++;
+ }
+
+ free_pkts(pkts, normal_cnt + slow_cnt);
+
+ if (slave_down_id == slave->port_id) {
+ TEST_ASSERT_EQUAL(normal_cnt + slow_cnt, 0,
+ "slave %u enexpectedly transmitted %u packets",
+ normal_cnt + slow_cnt, slave->port_id);
+ } else {
+ TEST_ASSERT_EQUAL(slow_cnt, 0,
+ "slave %u unexpectedly transmitted %d SLOW packets",
+ slave->port_id, slow_cnt);
+
+ TEST_ASSERT_NOT_EQUAL(normal_cnt, 0,
+ "slave %u did not transmitted any packets", slave->port_id);
+ }
+
+ pkts_cnt += normal_cnt;
+ }
+
+ TEST_ASSERT_EQUAL(exp_pkts_cnt, pkts_cnt,
+ "Expected %u packets but transmitted only %d", exp_pkts_cnt, pkts_cnt);
+
+ return remove_slaves_and_stop_bonded_device();
+}
+
+static void
+init_marker(struct rte_mbuf *pkt, struct slave_conf *slave)
+{
+ struct marker_header *marker_hdr = rte_pktmbuf_mtod(pkt,
+ struct marker_header *);
+
+ /* Copy multicast destination address */
+ rte_ether_addr_copy(&slow_protocol_mac_addr,
+ &marker_hdr->eth_hdr.d_addr);
+
+ /* Init source address */
+ rte_ether_addr_copy(&parnter_mac_default, &marker_hdr->eth_hdr.s_addr);
+ marker_hdr->eth_hdr.s_addr.addr_bytes[RTE_ETHER_ADDR_LEN - 1] =
+ slave->port_id;
+
+ marker_hdr->eth_hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_SLOW);
+
+ marker_hdr->marker.subtype = SLOW_SUBTYPE_MARKER;
+ marker_hdr->marker.version_number = 1;
+ marker_hdr->marker.tlv_type_marker = MARKER_TLV_TYPE_INFO;
+ marker_hdr->marker.info_length =
+ offsetof(struct marker, reserved_90) -
+ offsetof(struct marker, requester_port);
+ RTE_VERIFY(marker_hdr->marker.info_length == 16);
+ marker_hdr->marker.requester_port = slave->port_id + 1;
+ marker_hdr->marker.tlv_type_terminator = TLV_TYPE_TERMINATOR_INFORMATION;
+ marker_hdr->marker.terminator_length = 0;
+}
+
+static int
+test_mode4_marker(void)
+{
+ struct slave_conf *slave;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ struct rte_mbuf *marker_pkt;
+ struct marker_header *marker_hdr;
+
+ unsigned delay;
+ int retval;
+ uint16_t nb_pkts;
+ uint8_t i, j;
+ const uint16_t ethtype_slow_be = rte_be_to_cpu_16(RTE_ETHER_TYPE_SLOW);
+
+ retval = initialize_bonded_device_with_slaves(TEST_MARKER_SLAVE_COUT,
+ 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ /* Test LACP handshake function */
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ delay = bond_get_update_timeout_ms();
+ FOR_EACH_SLAVE(i, slave) {
+ marker_pkt = rte_pktmbuf_alloc(test_params.mbuf_pool);
+ TEST_ASSERT_NOT_NULL(marker_pkt, "Failed to allocate marker packet");
+ init_marker(marker_pkt, slave);
+
+ retval = slave_put_pkts(slave, &marker_pkt, 1);
+ if (retval != 1)
+ rte_pktmbuf_free(marker_pkt);
+
+ TEST_ASSERT_EQUAL(retval, 1,
+ "Failed to send marker packet to slave %u", slave->port_id);
+
+ for (j = 0; j < 20; ++j) {
+ rte_delay_ms(delay);
+ retval = rte_eth_rx_burst(test_params.bonded_port_id, 0, pkts,
+ RTE_DIM(pkts));
+
+ if (retval > 0)
+ free_pkts(pkts, retval);
+
+ TEST_ASSERT_EQUAL(retval, 0, "Received packets unexpectedly");
+
+ retval = rte_eth_tx_burst(test_params.bonded_port_id, 0, NULL, 0);
+ TEST_ASSERT_EQUAL(retval, 0,
+ "Requested TX of 0 packets but %d transmitted", retval);
+
+ /* Check if LACP packet was send by state machines
+ First and only packet must be a maker response */
+ retval = slave_get_pkts(slave, pkts, MAX_PKT_BURST);
+ if (retval == 0)
+ continue;
+ if (retval > 1)
+ free_pkts(pkts, retval);
+
+ TEST_ASSERT_EQUAL(retval, 1, "failed to get slave packets");
+ nb_pkts = retval;
+
+ marker_hdr = rte_pktmbuf_mtod(pkts[0], struct marker_header *);
+ /* Check if it's slow packet*/
+ if (marker_hdr->eth_hdr.ether_type != ethtype_slow_be)
+ retval = -1;
+ /* Check if it's marker packet */
+ else if (marker_hdr->marker.subtype != SLOW_SUBTYPE_MARKER)
+ retval = -2;
+ else if (marker_hdr->marker.tlv_type_marker != MARKER_TLV_TYPE_RESP)
+ retval = -3;
+
+ free_pkts(pkts, nb_pkts);
+
+ TEST_ASSERT_NOT_EQUAL(retval, -1, "Unexpected protocol type");
+ TEST_ASSERT_NOT_EQUAL(retval, -2, "Unexpected sub protocol type");
+ TEST_ASSERT_NOT_EQUAL(retval, -3, "Unexpected marker type");
+ break;
+ }
+
+ TEST_ASSERT(j < 20, "Marker response not found");
+ }
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_mode4_expired(void)
+{
+ struct slave_conf *slave, *exp_slave = NULL;
+ struct rte_mbuf *pkts[MAX_PKT_BURST];
+ int retval;
+ uint32_t old_delay;
+
+ uint8_t i;
+ uint16_t j;
+
+ struct rte_eth_bond_8023ad_conf conf;
+
+ retval = initialize_bonded_device_with_slaves(TEST_EXPIRED_SLAVE_COUNT,
+ 0);
+ /* Set custom timeouts to make test last shorter. */
+ rte_eth_bond_8023ad_conf_get(test_params.bonded_port_id, &conf);
+ conf.fast_periodic_ms = 100;
+ conf.slow_periodic_ms = 600;
+ conf.short_timeout_ms = 300;
+ conf.long_timeout_ms = 900;
+ conf.aggregate_wait_timeout_ms = 200;
+ conf.tx_period_ms = 100;
+ old_delay = conf.update_timeout_ms;
+ conf.update_timeout_ms = 10;
+ rte_eth_bond_8023ad_setup(test_params.bonded_port_id, &conf);
+
+ /* Wait for new settings to be applied. */
+ for (i = 0; i < old_delay/conf.update_timeout_ms * 2; i++) {
+ FOR_EACH_SLAVE(j, slave)
+ bond_handshake_reply(slave);
+
+ rte_delay_ms(conf.update_timeout_ms);
+ }
+
+ retval = bond_handshake();
+ TEST_ASSERT_SUCCESS(retval, "Initial handshake failed");
+
+ /* Find first slave */
+ FOR_EACH_SLAVE(i, slave) {
+ exp_slave = slave;
+ break;
+ }
+
+ RTE_VERIFY(exp_slave != NULL);
+
+ /* When one of partners do not send or respond to LACP frame in
+ * conf.long_timeout_ms time, internal state machines should detect this
+ * and transit to expired state. */
+ for (j = 0; j < conf.long_timeout_ms/conf.update_timeout_ms + 2; j++) {
+ rte_delay_ms(conf.update_timeout_ms);
+
+ retval = bond_tx(NULL, 0);
+ TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets",
+ retval);
+
+ FOR_EACH_SLAVE(i, slave) {
+ retval = bond_handshake_reply(slave);
+ TEST_ASSERT(retval >= 0, "Handshake failed");
+
+ /* Remove replay for slave that suppose to be expired. */
+ if (slave == exp_slave) {
+ while (rte_ring_count(slave->rx_queue) > 0) {
+ void *pkt = NULL;
+
+ rte_ring_dequeue(slave->rx_queue, &pkt);
+ rte_pktmbuf_free(pkt);
+ }
+ }
+ }
+
+ retval = bond_rx(pkts, RTE_DIM(pkts));
+ if (retval > 0)
+ free_pkts(pkts, retval);
+
+ TEST_ASSERT_EQUAL(retval, 0, "Unexpectedly received %d packets",
+ retval);
+ }
+
+ /* After test only expected slave should be in EXPIRED state */
+ FOR_EACH_SLAVE(i, slave) {
+ if (slave == exp_slave)
+ TEST_ASSERT(slave->lacp_parnter_state & STATE_EXPIRED,
+ "Slave %u should be in expired.", slave->port_id);
+ else
+ TEST_ASSERT_EQUAL(bond_handshake_done(slave), 1,
+ "Slave %u should be operational.", slave->port_id);
+ }
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_mode4_ext_ctrl(void)
+{
+ /*
+ * configure bonded interface without the external sm enabled
+ * . try to transmit lacpdu (should fail)
+ * . try to set collecting and distributing flags (should fail)
+ * reconfigure w/external sm
+ * . transmit one lacpdu on each slave using new api
+ * . make sure each slave receives one lacpdu using the callback api
+ * . transmit one data pdu on each slave (should fail)
+ * . enable distribution and collection, send one data pdu each again
+ */
+
+ int retval;
+ struct slave_conf *slave = NULL;
+ uint8_t i;
+
+ struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
+ struct rte_ether_addr src_mac, dst_mac;
+ struct lacpdu_header lacpdu = {
+ .lacpdu = {
+ .subtype = SLOW_SUBTYPE_LACP,
+ },
+ };
+
+ rte_ether_addr_copy(&parnter_system, &src_mac);
+ rte_ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
+
+ initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
+ RTE_ETHER_TYPE_SLOW, 0, 0);
+
+ for (i = 0; i < SLAVE_COUNT; i++) {
+ lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
+ rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
+ &lacpdu, sizeof(lacpdu));
+ rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
+ }
+
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ FOR_EACH_SLAVE(i, slave) {
+ TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_slowtx(
+ test_params.bonded_port_id,
+ slave->port_id, lacp_tx_buf[i]),
+ "Slave should not allow manual LACP xmit");
+ TEST_ASSERT_FAIL(rte_eth_bond_8023ad_ext_collect(
+ test_params.bonded_port_id,
+ slave->port_id, 1),
+ "Slave should not allow external state controls");
+ }
+
+ free_pkts(lacp_tx_buf, RTE_DIM(lacp_tx_buf));
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Bonded device cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+
+static int
+test_mode4_ext_lacp(void)
+{
+ int retval;
+ struct slave_conf *slave = NULL;
+ uint8_t all_slaves_done = 0, i;
+ uint16_t nb_pkts;
+ const unsigned int delay = bond_get_update_timeout_ms();
+
+ struct rte_mbuf *lacp_tx_buf[SLAVE_COUNT];
+ struct rte_mbuf *buf[SLAVE_COUNT];
+ struct rte_ether_addr src_mac, dst_mac;
+ struct lacpdu_header lacpdu = {
+ .lacpdu = {
+ .subtype = SLOW_SUBTYPE_LACP,
+ },
+ };
+
+ rte_ether_addr_copy(&parnter_system, &src_mac);
+ rte_ether_addr_copy(&slow_protocol_mac_addr, &dst_mac);
+
+ initialize_eth_header(&lacpdu.eth_hdr, &src_mac, &dst_mac,
+ RTE_ETHER_TYPE_SLOW, 0, 0);
+
+ for (i = 0; i < SLAVE_COUNT; i++) {
+ lacp_tx_buf[i] = rte_pktmbuf_alloc(test_params.mbuf_pool);
+ rte_memcpy(rte_pktmbuf_mtod(lacp_tx_buf[i], char *),
+ &lacpdu, sizeof(lacpdu));
+ rte_pktmbuf_pkt_len(lacp_tx_buf[i]) = sizeof(lacpdu);
+ }
+
+ retval = initialize_bonded_device_with_slaves(TEST_TX_SLAVE_COUNT, 1);
+ TEST_ASSERT_SUCCESS(retval, "Failed to initialize bonded device");
+
+ memset(lacpdu_rx_count, 0, sizeof(lacpdu_rx_count));
+
+ /* Wait for new settings to be applied. */
+ for (i = 0; i < 30; ++i)
+ rte_delay_ms(delay);
+
+ FOR_EACH_SLAVE(i, slave) {
+ retval = rte_eth_bond_8023ad_ext_slowtx(
+ test_params.bonded_port_id,
+ slave->port_id, lacp_tx_buf[i]);
+ TEST_ASSERT_SUCCESS(retval,
+ "Slave should allow manual LACP xmit");
+ }
+
+ nb_pkts = bond_tx(NULL, 0);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets transmitted unexpectedly");
+
+ FOR_EACH_SLAVE(i, slave) {
+ nb_pkts = slave_get_pkts(slave, buf, RTE_DIM(buf));
+ TEST_ASSERT_EQUAL(nb_pkts, 1, "found %u packets on slave %d\n",
+ nb_pkts, i);
+ slave_put_pkts(slave, buf, nb_pkts);
+ }
+
+ nb_pkts = bond_rx(buf, RTE_DIM(buf));
+ free_pkts(buf, nb_pkts);
+ TEST_ASSERT_EQUAL(nb_pkts, 0, "Packets received unexpectedly");
+
+ /* wait for the periodic callback to run */
+ for (i = 0; i < 30 && all_slaves_done == 0; ++i) {
+ uint8_t s, total = 0;
+
+ rte_delay_ms(delay);
+ FOR_EACH_SLAVE(s, slave) {
+ total += lacpdu_rx_count[slave->port_id];
+ }
+
+ if (total >= SLAVE_COUNT)
+ all_slaves_done = 1;
+ }
+
+ FOR_EACH_SLAVE(i, slave) {
+ TEST_ASSERT_EQUAL(lacpdu_rx_count[slave->port_id], 1,
+ "Slave port %u should have received 1 lacpdu (count=%u)",
+ slave->port_id,
+ lacpdu_rx_count[slave->port_id]);
+ }
+
+ retval = remove_slaves_and_stop_bonded_device();
+ TEST_ASSERT_SUCCESS(retval, "Test cleanup failed.");
+
+ return TEST_SUCCESS;
+}
+
+static int
+check_environment(void)
+{
+ struct slave_conf *port;
+ uint8_t i, env_state;
+ uint16_t slaves[RTE_DIM(test_params.slave_ports)];
+ int slaves_count;
+
+ env_state = 0;
+ FOR_EACH_PORT(i, port) {
+ if (rte_ring_count(port->rx_queue) != 0)
+ env_state |= 0x01;
+
+ if (rte_ring_count(port->tx_queue) != 0)
+ env_state |= 0x02;
+
+ if (port->bonded != 0)
+ env_state |= 0x04;
+
+ if (port->lacp_parnter_state != 0)
+ env_state |= 0x08;
+
+ if (env_state != 0)
+ break;
+ }
+
+ slaves_count = rte_eth_bond_slaves_get(test_params.bonded_port_id,
+ slaves, RTE_DIM(slaves));
+
+ if (slaves_count != 0)
+ env_state |= 0x10;
+
+ TEST_ASSERT_EQUAL(env_state, 0,
+ "Environment not clean (port %u):%s%s%s%s%s",
+ port->port_id,
+ env_state & 0x01 ? " slave rx queue not clean" : "",
+ env_state & 0x02 ? " slave tx queue not clean" : "",
+ env_state & 0x04 ? " port marked as enslaved" : "",
+ env_state & 0x80 ? " slave state is not reset" : "",
+ env_state & 0x10 ? " slave count not equal 0" : ".");
+
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_mode4_executor(int (*test_func)(void))
+{
+ struct slave_conf *port;
+ int test_result;
+ uint8_t i;
+ void *pkt;
+
+ /* Check if environment is clean. Fail to launch a test if there was
+ * a critical error before that prevented to reset environment. */
+ TEST_ASSERT_SUCCESS(check_environment(),
+ "Refusing to launch test in dirty environment.");
+
+ RTE_VERIFY(test_func != NULL);
+ test_result = (*test_func)();
+
+ /* If test succeed check if environment wast left in good condition. */
+ if (test_result == TEST_SUCCESS)
+ test_result = check_environment();
+
+ /* Reset environment in case test failed to do that. */
+ if (test_result != TEST_SUCCESS) {
+ TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
+ "Failed to stop bonded device");
+
+ FOR_EACH_PORT(i, port) {
+ while (rte_ring_count(port->rx_queue) != 0) {
+ if (rte_ring_dequeue(port->rx_queue, &pkt) == 0)
+ rte_pktmbuf_free(pkt);
+ }
+
+ while (rte_ring_count(port->tx_queue) != 0) {
+ if (rte_ring_dequeue(port->tx_queue, &pkt) == 0)
+ rte_pktmbuf_free(pkt);
+ }
+ }
+ }
+
+ return test_result;
+}
+
+static int
+test_mode4_agg_mode_selection_wrapper(void){
+ return test_mode4_executor(&test_mode4_agg_mode_selection);
+}
+
+static int
+test_mode4_lacp_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_lacp);
+}
+
+static int
+test_mode4_marker_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_marker);
+}
+
+static int
+test_mode4_rx_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_rx);
+}
+
+static int
+test_mode4_tx_burst_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_tx_burst);
+}
+
+static int
+test_mode4_expired_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_expired);
+}
+
+static int
+test_mode4_ext_ctrl_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_ext_ctrl);
+}
+
+static int
+test_mode4_ext_lacp_wrapper(void)
+{
+ return test_mode4_executor(&test_mode4_ext_lacp);
+}
+
+static struct unit_test_suite link_bonding_mode4_test_suite = {
+ .suite_name = "Link Bonding mode 4 Unit Test Suite",
+ .setup = test_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_NAMED("test_mode4_agg_mode_selection",
+ test_mode4_agg_mode_selection_wrapper),
+ TEST_CASE_NAMED("test_mode4_lacp", test_mode4_lacp_wrapper),
+ TEST_CASE_NAMED("test_mode4_rx", test_mode4_rx_wrapper),
+ TEST_CASE_NAMED("test_mode4_tx_burst", test_mode4_tx_burst_wrapper),
+ TEST_CASE_NAMED("test_mode4_marker", test_mode4_marker_wrapper),
+ TEST_CASE_NAMED("test_mode4_expired", test_mode4_expired_wrapper),
+ TEST_CASE_NAMED("test_mode4_ext_ctrl",
+ test_mode4_ext_ctrl_wrapper),
+ TEST_CASE_NAMED("test_mode4_ext_lacp",
+ test_mode4_ext_lacp_wrapper),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_link_bonding_mode4(void)
+{
+ return unit_test_suite_runner(&link_bonding_mode4_test_suite);
+}
+
+REGISTER_TEST_COMMAND(link_bonding_mode4_autotest, test_link_bonding_mode4);
diff --git a/src/spdk/dpdk/app/test/test_link_bonding_rssconf.c b/src/spdk/dpdk/app/test/test_link_bonding_rssconf.c
new file mode 100644
index 000000000..1a9571e5c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_link_bonding_rssconf.c
@@ -0,0 +1,662 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <rte_cycles.h>
+#include <sys/queue.h>
+
+#include <rte_byteorder.h>
+#include <rte_common.h>
+#include <rte_debug.h>
+#include <rte_ethdev.h>
+#include <rte_log.h>
+#include <rte_lcore.h>
+#include <rte_memory.h>
+#include <rte_bus_vdev.h>
+
+#include <rte_string_fns.h>
+#include <rte_errno.h>
+#include <rte_eth_bond.h>
+
+#include "test.h"
+
+#define SLAVE_COUNT (4)
+
+#define RXTX_RING_SIZE 1024
+#define RXTX_QUEUE_COUNT 4
+
+#define BONDED_DEV_NAME ("net_bonding_rss")
+
+#define SLAVE_DEV_NAME_FMT ("net_null%d")
+#define SLAVE_RXTX_QUEUE_FMT ("rssconf_slave%d_q%d")
+
+#define NUM_MBUFS 8191
+#define MBUF_SIZE (1600 + RTE_PKTMBUF_HEADROOM)
+#define MBUF_CACHE_SIZE 250
+#define BURST_SIZE 32
+
+#define INVALID_SOCKET_ID (-1)
+#define INVALID_PORT_ID (0xFF)
+#define INVALID_BONDING_MODE (-1)
+
+struct slave_conf {
+ uint16_t port_id;
+ struct rte_eth_dev_info dev_info;
+
+ struct rte_eth_rss_conf rss_conf;
+ uint8_t rss_key[40];
+ struct rte_eth_rss_reta_entry64 reta_conf[512 / RTE_RETA_GROUP_SIZE];
+
+ uint8_t is_slave;
+ struct rte_ring *rxtx_queue[RXTX_QUEUE_COUNT];
+};
+
+struct link_bonding_rssconf_unittest_params {
+ uint8_t bond_port_id;
+ struct rte_eth_dev_info bond_dev_info;
+ struct rte_eth_rss_reta_entry64 bond_reta_conf[512 / RTE_RETA_GROUP_SIZE];
+ struct slave_conf slave_ports[SLAVE_COUNT];
+
+ struct rte_mempool *mbuf_pool;
+};
+
+static struct link_bonding_rssconf_unittest_params test_params = {
+ .bond_port_id = INVALID_PORT_ID,
+ .slave_ports = {
+ [0 ... SLAVE_COUNT - 1] = { .port_id = INVALID_PORT_ID, .is_slave = 0}
+ },
+ .mbuf_pool = NULL,
+};
+
+/**
+ * Default port configuration with RSS turned off
+ */
+static struct rte_eth_conf default_pmd_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ .lpbk_mode = 0,
+};
+
+static struct rte_eth_conf rss_pmd_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_RSS,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IPV6,
+ },
+ },
+ .lpbk_mode = 0,
+};
+
+#define FOR_EACH(_i, _item, _array, _size) \
+ for (_i = 0, _item = &_array[0]; _i < _size && (_item = &_array[_i]); _i++)
+
+/* Macro for iterating over every port that can be used as a slave
+ * in this test.
+ * _i variable used as an index in test_params->slave_ports
+ * _slave pointer to &test_params->slave_ports[_idx]
+ */
+#define FOR_EACH_PORT(_i, _port) \
+ FOR_EACH(_i, _port, test_params.slave_ports, \
+ RTE_DIM(test_params.slave_ports))
+
+static int
+configure_ethdev(uint16_t port_id, struct rte_eth_conf *eth_conf,
+ uint8_t start)
+{
+ int rxq, txq;
+
+ TEST_ASSERT(rte_eth_dev_configure(port_id, RXTX_QUEUE_COUNT,
+ RXTX_QUEUE_COUNT, eth_conf) == 0, "Failed to configure device %u",
+ port_id);
+
+ for (rxq = 0; rxq < RXTX_QUEUE_COUNT; rxq++) {
+ TEST_ASSERT(rte_eth_rx_queue_setup(port_id, rxq, RXTX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), NULL,
+ test_params.mbuf_pool) == 0, "Failed to setup rx queue.");
+ }
+
+ for (txq = 0; txq < RXTX_QUEUE_COUNT; txq++) {
+ TEST_ASSERT(rte_eth_tx_queue_setup(port_id, txq, RXTX_RING_SIZE,
+ rte_eth_dev_socket_id(port_id), NULL) == 0,
+ "Failed to setup tx queue.");
+ }
+
+ if (start) {
+ TEST_ASSERT(rte_eth_dev_start(port_id) == 0,
+ "Failed to start device (%d).", port_id);
+ }
+
+ return 0;
+}
+
+/**
+ * Remove all slaves from bonding
+ */
+static int
+remove_slaves(void)
+{
+ unsigned n;
+ struct slave_conf *port;
+
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+ if (port->is_slave) {
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(
+ test_params.bond_port_id, port->port_id),
+ "Cannot remove slave %d from bonding", port->port_id);
+ port->is_slave = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int
+remove_slaves_and_stop_bonded_device(void)
+{
+ TEST_ASSERT_SUCCESS(remove_slaves(), "Removing slaves");
+ rte_eth_dev_stop(test_params.bond_port_id);
+ return TEST_SUCCESS;
+}
+
+/**
+ * Add all slaves to bonding
+ */
+static int
+bond_slaves(void)
+{
+ unsigned n;
+ struct slave_conf *port;
+
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+ if (!port->is_slave) {
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bond_port_id,
+ port->port_id), "Cannot attach slave %d to the bonding",
+ port->port_id);
+ port->is_slave = 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Set all RETA values in port_id to value
+ */
+static int
+reta_set(uint16_t port_id, uint8_t value, int reta_size)
+{
+ struct rte_eth_rss_reta_entry64 reta_conf[512/RTE_RETA_GROUP_SIZE];
+ int i, j;
+
+ for (i = 0; i < reta_size / RTE_RETA_GROUP_SIZE; i++) {
+ /* select all fields to set */
+ reta_conf[i].mask = ~0LL;
+ for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
+ reta_conf[i].reta[j] = value;
+ }
+
+ return rte_eth_dev_rss_reta_update(port_id, reta_conf, reta_size);
+}
+
+/**
+ * Check if slaves RETA is synchronized with bonding port. Returns 1 if slave
+ * port is synced with bonding port.
+ */
+static int
+reta_check_synced(struct slave_conf *port)
+{
+ unsigned i;
+
+ for (i = 0; i < test_params.bond_dev_info.reta_size;
+ i++) {
+
+ int index = i / RTE_RETA_GROUP_SIZE;
+ int shift = i % RTE_RETA_GROUP_SIZE;
+
+ if (port->reta_conf[index].reta[shift] !=
+ test_params.bond_reta_conf[index].reta[shift])
+ return 0;
+
+ }
+
+ return 1;
+}
+
+/**
+ * Fetch bonding ports RETA
+ */
+static int
+bond_reta_fetch(void) {
+ unsigned j;
+
+ for (j = 0; j < test_params.bond_dev_info.reta_size / RTE_RETA_GROUP_SIZE;
+ j++)
+ test_params.bond_reta_conf[j].mask = ~0LL;
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(test_params.bond_port_id,
+ test_params.bond_reta_conf, test_params.bond_dev_info.reta_size),
+ "Cannot take bonding ports RSS configuration");
+ return 0;
+}
+
+/**
+ * Fetch slaves RETA
+ */
+static int
+slave_reta_fetch(struct slave_conf *port) {
+ unsigned j;
+
+ for (j = 0; j < port->dev_info.reta_size / RTE_RETA_GROUP_SIZE; j++)
+ port->reta_conf[j].mask = ~0LL;
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_rss_reta_query(port->port_id,
+ port->reta_conf, port->dev_info.reta_size),
+ "Cannot take bonding ports RSS configuration");
+ return 0;
+}
+
+/**
+ * Remove and add slave to check if slaves configuration is synced with
+ * the bonding ports values after adding new slave.
+ */
+static int
+slave_remove_and_add(void)
+{
+ struct slave_conf *port = &(test_params.slave_ports[0]);
+
+ /* 1. Remove first slave from bonding */
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_remove(test_params.bond_port_id,
+ port->port_id), "Cannot remove slave #d from bonding");
+
+ /* 2. Change removed (ex-)slave and bonding configuration to different
+ * values
+ */
+ reta_set(test_params.bond_port_id, 1, test_params.bond_dev_info.reta_size);
+ bond_reta_fetch();
+
+ reta_set(port->port_id, 2, port->dev_info.reta_size);
+ slave_reta_fetch(port);
+
+ TEST_ASSERT(reta_check_synced(port) == 0,
+ "Removed slave didn't should be synchronized with bonding port");
+
+ /* 3. Add (ex-)slave and check if configuration changed*/
+ TEST_ASSERT_SUCCESS(rte_eth_bond_slave_add(test_params.bond_port_id,
+ port->port_id), "Cannot add slave");
+
+ bond_reta_fetch();
+ slave_reta_fetch(port);
+
+ return reta_check_synced(port);
+}
+
+/**
+ * Test configuration propagation over slaves.
+ */
+static int
+test_propagate(void)
+{
+ unsigned i;
+ uint8_t n;
+ struct slave_conf *port;
+ uint8_t bond_rss_key[40];
+ struct rte_eth_rss_conf bond_rss_conf;
+
+ int retval = 0;
+ uint64_t rss_hf = 0;
+ uint64_t default_rss_hf = 0;
+
+ retval = rte_eth_dev_info_get(test_params.bond_port_id,
+ &test_params.bond_dev_info);
+ TEST_ASSERT((retval == 0),
+ "Error during getting device (port %u) info: %s\n",
+ test_params.bond_port_id, strerror(-retval));
+
+ /*
+ * Test hash function propagation
+ */
+ for (i = 0; i < sizeof(test_params.bond_dev_info.flow_type_rss_offloads)*8;
+ i++) {
+
+ rss_hf = test_params.bond_dev_info.flow_type_rss_offloads & (1<<i);
+ if (rss_hf) {
+ bond_rss_conf.rss_key = NULL;
+ bond_rss_conf.rss_hf = rss_hf;
+
+ retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id,
+ &bond_rss_conf);
+ TEST_ASSERT_SUCCESS(retval, "Cannot set slaves hash function");
+
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+
+ retval = rte_eth_dev_rss_hash_conf_get(port->port_id,
+ &port->rss_conf);
+ TEST_ASSERT_SUCCESS(retval,
+ "Cannot take slaves RSS configuration");
+
+ TEST_ASSERT(port->rss_conf.rss_hf == rss_hf,
+ "Hash function not propagated for slave %d",
+ port->port_id);
+ }
+
+ default_rss_hf = rss_hf;
+ }
+
+ }
+
+ /*
+ * Test key propagation
+ */
+ for (i = 1; i < 10; i++) {
+
+ /* Set all keys to zero */
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+ memset(port->rss_conf.rss_key, 0, 40);
+ retval = rte_eth_dev_rss_hash_update(port->port_id,
+ &port->rss_conf);
+ TEST_ASSERT_SUCCESS(retval, "Cannot set slaves RSS keys");
+ }
+
+ memset(bond_rss_key, i, sizeof(bond_rss_key));
+ bond_rss_conf.rss_hf = default_rss_hf,
+ bond_rss_conf.rss_key = bond_rss_key;
+ bond_rss_conf.rss_key_len = 40;
+
+ retval = rte_eth_dev_rss_hash_update(test_params.bond_port_id,
+ &bond_rss_conf);
+ TEST_ASSERT_SUCCESS(retval, "Cannot set bonded port RSS keys");
+
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+
+ retval = rte_eth_dev_rss_hash_conf_get(port->port_id,
+ &(port->rss_conf));
+
+ TEST_ASSERT_SUCCESS(retval,
+ "Cannot take slaves RSS configuration");
+
+ /* compare keys */
+ retval = memcmp(port->rss_conf.rss_key, bond_rss_key,
+ sizeof(bond_rss_key));
+ TEST_ASSERT(retval == 0, "Key value not propagated for slave %d",
+ port->port_id);
+ }
+ }
+
+ /*
+ * Test RETA propagation
+ */
+ for (i = 0; i < RXTX_QUEUE_COUNT; i++) {
+
+ /* Set all keys to zero */
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+ retval = reta_set(port->port_id, (i + 1) % RXTX_QUEUE_COUNT,
+ port->dev_info.reta_size);
+ TEST_ASSERT_SUCCESS(retval, "Cannot set slaves RETA");
+ }
+
+ TEST_ASSERT_SUCCESS(reta_set(test_params.bond_port_id,
+ i % RXTX_QUEUE_COUNT, test_params.bond_dev_info.reta_size),
+ "Cannot set bonded port RETA");
+
+ bond_reta_fetch();
+
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+
+ slave_reta_fetch(port);
+ TEST_ASSERT(reta_check_synced(port) == 1, "RETAs inconsistent");
+ }
+ }
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test propagation logic, when RX_RSS mq_mode is turned on for bonding port
+ */
+static int
+test_rss(void)
+{
+ /**
+ * Configure bonding port in RSS mq mode
+ */
+ int ret;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
+ &rss_pmd_conf, 0), "Failed to configure bonding device\n");
+
+ ret = rte_eth_dev_info_get(test_params.bond_port_id,
+ &test_params.bond_dev_info);
+ TEST_ASSERT((ret == 0),
+ "Error during getting device (port %u) info: %s\n",
+ test_params.bond_port_id, strerror(-ret));
+
+ TEST_ASSERT_SUCCESS(bond_slaves(), "Bonding slaves failed");
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id),
+ "Failed to start bonding port (%d).", test_params.bond_port_id);
+
+ TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed");
+
+ TEST_ASSERT(slave_remove_and_add() == 1, "New slave should be synced");
+
+ remove_slaves_and_stop_bonded_device();
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test propagation logic, when RX_RSS mq_mode is turned off for bonding port
+ */
+static int
+test_rss_lazy(void)
+{
+ int ret;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
+ &default_pmd_conf, 0), "Failed to configure bonding device\n");
+
+ ret = rte_eth_dev_info_get(test_params.bond_port_id,
+ &test_params.bond_dev_info);
+ TEST_ASSERT((ret == 0),
+ "Error during getting device (port %u) info: %s\n",
+ test_params.bond_port_id, strerror(-ret));
+
+ TEST_ASSERT_SUCCESS(bond_slaves(), "Bonding slaves failed");
+
+ TEST_ASSERT_SUCCESS(rte_eth_dev_start(test_params.bond_port_id),
+ "Failed to start bonding port (%d).", test_params.bond_port_id);
+
+ TEST_ASSERT_SUCCESS(test_propagate(), "Propagation test failed");
+
+ TEST_ASSERT(slave_remove_and_add() == 0, "New slave shouldn't be synced");
+
+ remove_slaves_and_stop_bonded_device();
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_setup(void)
+{
+ unsigned n;
+ int retval;
+ int port_id;
+ char name[256];
+ struct slave_conf *port;
+ struct rte_ether_addr mac_addr = { .addr_bytes = {0} };
+
+ if (test_params.mbuf_pool == NULL) {
+
+ test_params.mbuf_pool = rte_pktmbuf_pool_create(
+ "RSS_MBUF_POOL", NUM_MBUFS * SLAVE_COUNT,
+ MBUF_CACHE_SIZE, 0, MBUF_SIZE, rte_socket_id());
+
+ TEST_ASSERT(test_params.mbuf_pool != NULL,
+ "rte_pktmbuf_pool_create failed\n");
+ }
+
+ /* Create / initialize ring eth devs. */
+ FOR_EACH_PORT(n, port) {
+ port = &test_params.slave_ports[n];
+
+ port_id = rte_eth_dev_count_avail();
+ snprintf(name, sizeof(name), SLAVE_DEV_NAME_FMT, port_id);
+
+ retval = rte_vdev_init(name, "size=64,copy=0");
+ TEST_ASSERT_SUCCESS(retval, "Failed to create null device '%s'\n",
+ name);
+
+ port->port_id = port_id;
+
+ port->rss_conf.rss_key = port->rss_key;
+ port->rss_conf.rss_key_len = 40;
+
+ retval = configure_ethdev(port->port_id, &default_pmd_conf, 0);
+ TEST_ASSERT_SUCCESS(retval, "Failed to configure virtual ethdev %s\n",
+ name);
+
+ /* assign a non-zero MAC */
+ mac_addr.addr_bytes[5] = 0x10 + port->port_id;
+ rte_eth_dev_default_mac_addr_set(port->port_id, &mac_addr);
+
+ rte_eth_dev_info_get(port->port_id, &port->dev_info);
+ retval = rte_eth_dev_info_get(port->port_id, &port->dev_info);
+ TEST_ASSERT((retval == 0),
+ "Error during getting device (port %u) info: %s\n",
+ test_params.bond_port_id, strerror(-retval));
+ }
+
+ if (test_params.bond_port_id == INVALID_PORT_ID) {
+ retval = rte_eth_bond_create(BONDED_DEV_NAME, 0, rte_socket_id());
+
+ TEST_ASSERT(retval >= 0, "Failed to create bonded ethdev %s",
+ BONDED_DEV_NAME);
+
+ test_params.bond_port_id = retval;
+
+ TEST_ASSERT_SUCCESS(configure_ethdev(test_params.bond_port_id,
+ &default_pmd_conf, 0), "Failed to configure bonding device\n");
+
+ retval = rte_eth_dev_info_get(test_params.bond_port_id,
+ &test_params.bond_dev_info);
+ TEST_ASSERT((retval == 0),
+ "Error during getting device (port %u) info: %s\n",
+ test_params.bond_port_id, strerror(-retval));
+ }
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ struct slave_conf *port;
+ uint8_t i;
+
+ /* Only stop ports.
+ * Any cleanup/reset state is done when particular test is
+ * started. */
+
+ rte_eth_dev_stop(test_params.bond_port_id);
+
+ FOR_EACH_PORT(i, port)
+ rte_eth_dev_stop(port->port_id);
+}
+
+static int
+check_environment(void)
+{
+ return TEST_SUCCESS;
+}
+
+static int
+test_rssconf_executor(int (*test_func)(void))
+{
+ int test_result;
+
+ /* Check if environment is clean. Fail to launch a test if there was
+ * a critical error before that prevented to reset environment. */
+ TEST_ASSERT_SUCCESS(check_environment(),
+ "Refusing to launch test in dirty environment.");
+
+ RTE_VERIFY(test_func != NULL);
+ test_result = (*test_func)();
+
+ /* If test succeed check if environment wast left in good condition. */
+ if (test_result == TEST_SUCCESS)
+ test_result = check_environment();
+
+ /* Reset environment in case test failed to do that. */
+ if (test_result != TEST_SUCCESS) {
+ TEST_ASSERT_SUCCESS(remove_slaves_and_stop_bonded_device(),
+ "Failed to stop bonded device");
+ }
+
+ return test_result;
+}
+
+static int
+test_setup_wrapper(void)
+{
+ return test_rssconf_executor(&test_setup);
+}
+
+static int
+test_rss_wrapper(void)
+{
+ return test_rssconf_executor(&test_rss);
+}
+
+static int
+test_rss_lazy_wrapper(void)
+{
+ return test_rssconf_executor(&test_rss_lazy);
+}
+
+static struct unit_test_suite link_bonding_rssconf_test_suite = {
+ .suite_name = "RSS Dynamic Configuration for Bonding Unit Test Suite",
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_NAMED("test_setup", test_setup_wrapper),
+ TEST_CASE_NAMED("test_rss", test_rss_wrapper),
+ TEST_CASE_NAMED("test_rss_lazy", test_rss_lazy_wrapper),
+
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_link_bonding_rssconf(void)
+{
+ return unit_test_suite_runner(&link_bonding_rssconf_test_suite);
+}
+
+REGISTER_TEST_COMMAND(link_bonding_rssconf_autotest, test_link_bonding_rssconf);
diff --git a/src/spdk/dpdk/app/test/test_logs.c b/src/spdk/dpdk/app/test/test_logs.c
new file mode 100644
index 000000000..425ae03cb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_logs.c
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+
+#include "test.h"
+
+/* for legacy log test */
+#define RTE_LOGTYPE_TESTAPP1 RTE_LOGTYPE_USER1
+#define RTE_LOGTYPE_TESTAPP2 RTE_LOGTYPE_USER2
+
+/*
+ * Logs
+ * ====
+ *
+ * - Enable log types.
+ * - Set log level.
+ * - Send logs with different types and levels, some should not be displayed.
+ */
+static int
+test_legacy_logs(void)
+{
+ printf("== static log types\n");
+
+ /* set logtype level low to so we can test global level */
+ rte_log_set_level(RTE_LOGTYPE_TESTAPP1, RTE_LOG_DEBUG);
+ rte_log_set_level(RTE_LOGTYPE_TESTAPP2, RTE_LOG_DEBUG);
+
+ /* log in error level */
+ rte_log_set_global_level(RTE_LOG_ERR);
+ RTE_LOG(ERR, TESTAPP1, "error message\n");
+ RTE_LOG(CRIT, TESTAPP1, "critical message\n");
+
+ /* log in critical level */
+ rte_log_set_global_level(RTE_LOG_CRIT);
+ RTE_LOG(ERR, TESTAPP2, "error message (not displayed)\n");
+ RTE_LOG(CRIT, TESTAPP2, "critical message\n");
+
+ /* bump up single log type level above global to test it */
+ rte_log_set_level(RTE_LOGTYPE_TESTAPP2, RTE_LOG_EMERG);
+
+ /* log in error level */
+ rte_log_set_global_level(RTE_LOG_ERR);
+ RTE_LOG(ERR, TESTAPP1, "error message\n");
+ RTE_LOG(ERR, TESTAPP2, "error message (not displayed)\n");
+
+ return 0;
+}
+
+static int
+test_logs(void)
+{
+ int logtype1, logtype2;
+ int ret;
+
+ printf("== dynamic log types\n");
+
+ logtype1 = rte_log_register("logtype1");
+ if (logtype1 < 0) {
+ printf("Cannot register logtype1\n");
+ return -1;
+ }
+ logtype2 = rte_log_register("logtype2");
+ if (logtype2 < 0) {
+ printf("Cannot register logtype2\n");
+ return -1;
+ }
+
+ /* set logtype level low to so we can test global level */
+ rte_log_set_level(logtype1, RTE_LOG_DEBUG);
+ rte_log_set_level(logtype2, RTE_LOG_DEBUG);
+
+ /* log in error level */
+ rte_log_set_global_level(RTE_LOG_ERR);
+ rte_log(RTE_LOG_ERR, logtype1, "error message\n");
+ rte_log(RTE_LOG_CRIT, logtype1, "critical message\n");
+
+ /* log in critical level */
+ rte_log_set_global_level(RTE_LOG_CRIT);
+ rte_log(RTE_LOG_ERR, logtype2, "error message (not displayed)\n");
+ rte_log(RTE_LOG_CRIT, logtype2, "critical message\n");
+
+ /* bump up single log type level above global to test it */
+ rte_log_set_level(logtype2, RTE_LOG_EMERG);
+
+ /* log in error level */
+ rte_log_set_global_level(RTE_LOG_ERR);
+ rte_log(RTE_LOG_ERR, logtype1, "error message\n");
+ rte_log(RTE_LOG_ERR, logtype2, "error message (not displayed)\n");
+
+ ret = test_legacy_logs();
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(logs_autotest, test_logs);
diff --git a/src/spdk/dpdk/app/test/test_lpm.c b/src/spdk/dpdk/app/test/test_lpm.c
new file mode 100644
index 000000000..3a3fd097f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_lpm.c
@@ -0,0 +1,1289 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_lpm.h>
+
+#include "test.h"
+#include "test_xmmt_ops.h"
+
+#define TEST_LPM_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d: \n", __LINE__); \
+ return -1; \
+ } \
+} while(0)
+
+typedef int32_t (*rte_lpm_test)(void);
+
+static int32_t test0(void);
+static int32_t test1(void);
+static int32_t test2(void);
+static int32_t test3(void);
+static int32_t test4(void);
+static int32_t test5(void);
+static int32_t test6(void);
+static int32_t test7(void);
+static int32_t test8(void);
+static int32_t test9(void);
+static int32_t test10(void);
+static int32_t test11(void);
+static int32_t test12(void);
+static int32_t test13(void);
+static int32_t test14(void);
+static int32_t test15(void);
+static int32_t test16(void);
+static int32_t test17(void);
+static int32_t test18(void);
+
+rte_lpm_test tests[] = {
+/* Test Cases */
+ test0,
+ test1,
+ test2,
+ test3,
+ test4,
+ test5,
+ test6,
+ test7,
+ test8,
+ test9,
+ test10,
+ test11,
+ test12,
+ test13,
+ test14,
+ test15,
+ test16,
+ test17,
+ test18
+};
+
+#define MAX_DEPTH 32
+#define MAX_RULES 256
+#define NUMBER_TBL8S 256
+#define PASS 0
+
+/*
+ * Check that rte_lpm_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test0(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm_create: lpm name == NULL */
+ lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* rte_lpm_create: max_rules = 0 */
+ /* Note: __func__ inserts the function name, in this case "test0". */
+ config.max_rules = 0;
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* socket_id < -1 is invalid */
+ config.max_rules = MAX_RULES;
+ lpm = rte_lpm_create(__func__, -2, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ return PASS;
+}
+
+/*
+ * Create lpm table then delete lpm table 100 times
+ * Use a slightly different rules size each time
+ * */
+int32_t
+test1(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ int32_t i;
+
+ /* rte_lpm_free: Free NULL */
+ for (i = 0; i < 100; i++) {
+ config.max_rules = MAX_RULES - i;
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ rte_lpm_free(lpm);
+ }
+
+ /* Can not test free so return success */
+ return PASS;
+}
+
+/*
+ * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test2(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ rte_lpm_free(lpm);
+ rte_lpm_free(NULL);
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm_add fails gracefully for incorrect user input arguments
+ */
+int32_t
+test3(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop = 100;
+ uint8_t depth = 24;
+ int32_t status = 0;
+
+ /* rte_lpm_add: lpm == NULL */
+ status = rte_lpm_add(NULL, ip, depth, next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm_add: depth < 1 */
+ status = rte_lpm_add(lpm, ip, 0, next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm_add: depth > MAX_DEPTH */
+ status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm_delete fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test4(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0);
+ uint8_t depth = 24;
+ int32_t status = 0;
+
+ /* rte_lpm_delete: lpm == NULL */
+ status = rte_lpm_delete(NULL, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm_delete: depth < 1 */
+ status = rte_lpm_delete(lpm, ip, 0);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm_delete: depth > MAX_DEPTH */
+ status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm_lookup fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test5(void)
+{
+#if defined(RTE_LIBRTE_LPM_DEBUG)
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_return = 0;
+ int32_t status = 0;
+
+ /* rte_lpm_lookup: lpm == NULL */
+ status = rte_lpm_lookup(NULL, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm_lookup: depth < 1 */
+ status = rte_lpm_lookup(lpm, ip, NULL);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm_free(lpm);
+#endif
+ return PASS;
+}
+
+
+
+/*
+ * Call add, lookup and delete for a single rule with depth <= 24
+ */
+int32_t
+test6(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
+ uint8_t depth = 24;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth > 24
+ */
+
+int32_t
+test7(void)
+{
+ xmm_t ipx4;
+ uint32_t hop[4];
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
+ uint8_t depth = 32;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
+ rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+ TEST_LPM_ASSERT(hop[0] == next_hop_add);
+ TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Use rte_lpm_add to add rules which effect only the second half of the lpm
+ * table. Use all possible depths ranging from 1..32. Set the next hop = to the
+ * depth. Check lookup hit for on every add and check for lookup miss on the
+ * first half of the lpm table after each add. Finally delete all rules going
+ * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
+ * delete. The lookup should return the next_hop_add value related to the
+ * previous depth value (i.e. depth -1).
+ */
+int32_t
+test8(void)
+{
+ xmm_t ipx4;
+ uint32_t hop[4];
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip1 = RTE_IPV4(127, 255, 255, 255), ip2 = RTE_IPV4(128, 0, 0, 0);
+ uint32_t next_hop_add, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Loop with rte_lpm_add. */
+ for (depth = 1; depth <= 32; depth++) {
+ /* Let the next_hop_add value = depth. Just for change. */
+ next_hop_add = depth;
+
+ status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ /* Check IP in first half of tbl24 which should be empty. */
+ status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+
+ ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
+ rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+ TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[1] == next_hop_add);
+ TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[3] == next_hop_add);
+ }
+
+ /* Loop with rte_lpm_delete. */
+ for (depth = 32; depth >= 1; depth--) {
+ next_hop_add = (uint8_t) (depth - 1);
+
+ status = rte_lpm_delete(lpm, ip2, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
+
+ if (depth != 1) {
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+ } else {
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
+ rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+ if (depth != 1) {
+ TEST_LPM_ASSERT(hop[0] == next_hop_add);
+ TEST_LPM_ASSERT(hop[1] == next_hop_add);
+ } else {
+ TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
+ }
+ TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
+ }
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * - Add & lookup to hit invalid TBL24 entry
+ * - Add & lookup to hit valid TBL24 entry not extended
+ * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
+ * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
+ *
+ */
+int32_t
+test9(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, ip_1, ip_2;
+ uint8_t depth, depth_1, depth_2;
+ uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
+ int32_t status = 0;
+
+ /* Add & lookup to hit invalid TBL24 entry */
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add & lookup to hit valid TBL24 entry not extended */
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 23;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ depth = 24;
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ depth = 24;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 23;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
+ * entry */
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ip = RTE_IPV4(128, 0, 0, 5);
+ depth = 32;
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
+ * entry */
+ ip_1 = RTE_IPV4(128, 0, 0, 0);
+ depth_1 = 25;
+ next_hop_add_1 = 101;
+
+ ip_2 = RTE_IPV4(128, 0, 0, 5);
+ depth_2 = 32;
+ next_hop_add_2 = 102;
+
+ next_hop_return = 0;
+
+ status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+ status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
+
+ status = rte_lpm_delete(lpm, ip_2, depth_2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+ status = rte_lpm_delete(lpm, ip_1, depth_1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+
+/*
+ * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
+ * lookup)
+ * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
+ * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
+ * delete & lookup)
+ * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
+ * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
+ * - Delete a rule that is not present in the TBL24 & lookup
+ * - Delete a rule that is not present in the TBL8 & lookup
+ *
+ */
+int32_t
+test10(void)
+{
+
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, next_hop_add, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ /* Add rule that covers a TBL24 range previously invalid & lookup
+ * (& delete & lookup) */
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 16;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 25;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add rule that extends a TBL24 valid entry & lookup for both rules
+ * (& delete & lookup) */
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ ip = RTE_IPV4(128, 0, 0, 10);
+ depth = 32;
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ next_hop_add = 100;
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ ip = RTE_IPV4(128, 0, 0, 10);
+ depth = 32;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add rule that updates the next hop in TBL24 & lookup
+ * (& delete & lookup) */
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Add rule that updates the next hop in TBL8 & lookup
+ * (& delete & lookup) */
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Delete a rule that is not present in the TBL24 & lookup */
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_delete_all(lpm);
+
+ /* Delete a rule that is not present in the TBL8 & lookup */
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 32;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add two rules, lookup to hit the more specific one, lookup to hit the less
+ * specific one delete the less specific rule and lookup previous values again;
+ * add a more specific rule than the existing rule, lookup again
+ *
+ * */
+int32_t
+test11(void)
+{
+
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, next_hop_add, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ ip = RTE_IPV4(128, 0, 0, 10);
+ depth = 32;
+ next_hop_add = 101;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ next_hop_add = 100;
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ ip = RTE_IPV4(128, 0, 0, 10);
+ depth = 32;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
+ * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
+ * and contraction.
+ *
+ * */
+
+int32_t
+test12(void)
+{
+ xmm_t ipx4;
+ uint32_t hop[4];
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, i, next_hop_add, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ for (i = 0; i < 1000; i++) {
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+
+ ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
+ rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
+ TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[1] == next_hop_add);
+ TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
+ TEST_LPM_ASSERT(hop[3] == next_hop_add);
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
+ * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
+ * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
+ * extension and contraction.
+ *
+ * */
+
+int32_t
+test13(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ ip = RTE_IPV4(128, 0, 0, 0);
+ depth = 24;
+ next_hop_add_1 = 100;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+ depth = 32;
+ next_hop_add_2 = 101;
+
+ for (i = 0; i < 1000; i++) {
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add_2));
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add_1));
+ }
+
+ depth = 24;
+
+ status = rte_lpm_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
+ * No more tbl8 extensions will be allowed. Now add one more rule that required
+ * a tbl8 extension and get fail.
+ * */
+int32_t
+test14(void)
+{
+
+ /* We only use depth = 32 in the loop below so we must make sure
+ * that we have enough storage for all rules at that depth*/
+
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = 256 * 32;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ uint32_t ip, next_hop_add, next_hop_return;
+ uint8_t depth;
+ int32_t status = 0;
+
+ /* Add enough space for 256 rules for every depth */
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ depth = 32;
+ next_hop_add = 100;
+ ip = RTE_IPV4(0, 0, 0, 0);
+
+ /* Add 256 rules that require a tbl8 extension */
+ for (; ip <= RTE_IPV4(0, 0, 255, 0); ip += 256) {
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+ }
+
+ /* All tbl8 extensions have been used above. Try to add one more and
+ * we get a fail */
+ ip = RTE_IPV4(1, 0, 0, 0);
+ depth = 32;
+
+ status = rte_lpm_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Sequence of operations for find existing lpm table
+ *
+ * - create table
+ * - find existing table: hit
+ * - find non-existing table: miss
+ *
+ */
+int32_t
+test15(void)
+{
+ struct rte_lpm *lpm = NULL, *result = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = 256 * 32;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* Create lpm */
+ lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Try to find existing lpm */
+ result = rte_lpm_find_existing("lpm_find_existing");
+ TEST_LPM_ASSERT(result == lpm);
+
+ /* Try to find non-existing lpm */
+ result = rte_lpm_find_existing("lpm_find_non_existing");
+ TEST_LPM_ASSERT(result == NULL);
+
+ /* Cleanup. */
+ rte_lpm_delete_all(lpm);
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * test failure condition of overloading the tbl8 so no more will fit
+ * Check we get an error return value in that case
+ */
+int32_t
+test16(void)
+{
+ uint32_t ip;
+ struct rte_lpm_config config;
+
+ config.max_rules = 256 * 32;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+
+ /* ip loops through all possibilities for top 24 bits of address */
+ for (ip = 0; ip < 0xFFFFFF; ip++) {
+ /* add an entry within a different tbl8 each time, since
+ * depth >24 and the top 24 bits are different */
+ if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
+ break;
+ }
+
+ if (ip != NUMBER_TBL8S) {
+ printf("Error, unexpected failure with filling tbl8 groups\n");
+ printf("Failed after %u additions, expected after %u\n",
+ (unsigned)ip, (unsigned)NUMBER_TBL8S);
+ }
+
+ rte_lpm_free(lpm);
+ return 0;
+}
+
+/*
+ * Test for overwriting of tbl8:
+ * - add rule /32 and lookup
+ * - add new rule /24 and lookup
+ * - add third rule /25 and lookup
+ * - lookup /32 and /24 rule to ensure the table has not been overwritten.
+ */
+int32_t
+test17(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+ const uint32_t ip_10_32 = RTE_IPV4(10, 10, 10, 2);
+ const uint32_t ip_10_24 = RTE_IPV4(10, 10, 10, 0);
+ const uint32_t ip_20_25 = RTE_IPV4(10, 10, 20, 2);
+ const uint8_t d_ip_10_32 = 32,
+ d_ip_10_24 = 24,
+ d_ip_20_25 = 25;
+ const uint32_t next_hop_ip_10_32 = 100,
+ next_hop_ip_10_24 = 105,
+ next_hop_ip_20_25 = 111;
+ uint32_t next_hop_return = 0;
+ int32_t status = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
+ next_hop_ip_10_32)) < 0)
+ return -1;
+
+ status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+ uint32_t test_hop_10_32 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+ if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
+ next_hop_ip_10_24)) < 0)
+ return -1;
+
+ status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+ uint32_t test_hop_10_24 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+ if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
+ next_hop_ip_20_25)) < 0)
+ return -1;
+
+ status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
+ uint32_t test_hop_20_25 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
+
+ if (test_hop_10_32 == test_hop_10_24) {
+ printf("Next hop return equal\n");
+ return -1;
+ }
+
+ if (test_hop_10_24 == test_hop_20_25) {
+ printf("Next hop return equal\n");
+ return -1;
+ }
+
+ status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+ status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+ rte_lpm_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Test for recycle of tbl8
+ * - step 1: add a rule with depth=28 (> 24)
+ * - step 2: add a rule with same 24-bit prefix and depth=23 (< 24)
+ * - step 3: delete the first rule
+ * - step 4: check tbl8 is freed
+ * - step 5: add a rule same as the first one (depth=28)
+ * - step 6: check same tbl8 is allocated
+ * - step 7: add a rule with same 24-bit prefix and depth=24
+ * - step 8: delete the rule (depth=28) added in step 5
+ * - step 9: check tbl8 is freed
+ * - step 10: add a rule with same 24-bit prefix and depth = 28
+ * - setp 11: check same tbl8 is allocated again
+ */
+int32_t
+test18(void)
+{
+#define group_idx next_hop
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+ uint32_t ip, next_hop;
+ uint8_t depth;
+ uint32_t tbl8_group_index;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ ip = RTE_IPV4(192, 168, 100, 100);
+ depth = 28;
+ next_hop = 1;
+ rte_lpm_add(lpm, ip, depth, next_hop);
+
+ TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
+ tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
+
+ depth = 23;
+ next_hop = 2;
+ rte_lpm_add(lpm, ip, depth, next_hop);
+ TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
+
+ depth = 28;
+ rte_lpm_delete(lpm, ip, depth);
+
+ TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
+
+ next_hop = 3;
+ rte_lpm_add(lpm, ip, depth, next_hop);
+
+ TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
+ TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
+
+ depth = 24;
+ next_hop = 4;
+ rte_lpm_add(lpm, ip, depth, next_hop);
+ TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
+
+ depth = 28;
+ rte_lpm_delete(lpm, ip, depth);
+
+ TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
+
+ next_hop = 5;
+ rte_lpm_add(lpm, ip, depth, next_hop);
+
+ TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
+ TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
+
+ rte_lpm_free(lpm);
+#undef group_idx
+ return PASS;
+}
+
+/*
+ * Do all unit tests.
+ */
+
+static int
+test_lpm(void)
+{
+ unsigned i;
+ int status, global_status = 0;
+
+ for (i = 0; i < RTE_DIM(tests); i++) {
+ status = tests[i]();
+ if (status < 0) {
+ printf("ERROR: LPM Test %u: FAIL\n", i);
+ global_status = status;
+ }
+ }
+
+ return global_status;
+}
+
+REGISTER_TEST_COMMAND(lpm_autotest, test_lpm);
diff --git a/src/spdk/dpdk/app/test/test_lpm6.c b/src/spdk/dpdk/app/test/test_lpm6.c
new file mode 100644
index 000000000..0d664546f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_lpm6.c
@@ -0,0 +1,1795 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_lpm6.h>
+
+#include "test.h"
+#include "test_lpm6_data.h"
+
+#define TEST_LPM_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d: \n", __LINE__); \
+ return -1; \
+ } \
+} while(0)
+
+typedef int32_t (* rte_lpm6_test)(void);
+
+static int32_t test0(void);
+static int32_t test1(void);
+static int32_t test2(void);
+static int32_t test3(void);
+static int32_t test4(void);
+static int32_t test5(void);
+static int32_t test6(void);
+static int32_t test7(void);
+static int32_t test8(void);
+static int32_t test9(void);
+static int32_t test10(void);
+static int32_t test11(void);
+static int32_t test12(void);
+static int32_t test13(void);
+static int32_t test14(void);
+static int32_t test15(void);
+static int32_t test16(void);
+static int32_t test17(void);
+static int32_t test18(void);
+static int32_t test19(void);
+static int32_t test20(void);
+static int32_t test21(void);
+static int32_t test22(void);
+static int32_t test23(void);
+static int32_t test24(void);
+static int32_t test25(void);
+static int32_t test26(void);
+static int32_t test27(void);
+static int32_t test28(void);
+
+rte_lpm6_test tests6[] = {
+/* Test Cases */
+ test0,
+ test1,
+ test2,
+ test3,
+ test4,
+ test5,
+ test6,
+ test7,
+ test8,
+ test9,
+ test10,
+ test11,
+ test12,
+ test13,
+ test14,
+ test15,
+ test16,
+ test17,
+ test18,
+ test19,
+ test20,
+ test21,
+ test22,
+ test23,
+ test24,
+ test25,
+ test26,
+ test27,
+ test28,
+};
+
+#define MAX_DEPTH 128
+#define MAX_RULES 1000000
+#define NUMBER_TBL8S (1 << 16)
+#define MAX_NUM_TBL8S (1 << 21)
+#define PASS 0
+
+static void
+IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
+ uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
+ uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
+ uint8_t b16)
+{
+ ip[0] = b1;
+ ip[1] = b2;
+ ip[2] = b3;
+ ip[3] = b4;
+ ip[4] = b5;
+ ip[5] = b6;
+ ip[6] = b7;
+ ip[7] = b8;
+ ip[8] = b9;
+ ip[9] = b10;
+ ip[10] = b11;
+ ip[11] = b12;
+ ip[12] = b13;
+ ip[13] = b14;
+ ip[14] = b15;
+ ip[15] = b16;
+}
+
+/*
+ * Check that rte_lpm6_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test0(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_create: lpm name == NULL */
+ lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* rte_lpm6_create: max_rules = 0 */
+ /* Note: __func__ inserts the function name, in this case "test0". */
+ config.max_rules = 0;
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* socket_id < -1 is invalid */
+ config.max_rules = MAX_RULES;
+ lpm = rte_lpm6_create(__func__, -2, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
+ config.number_tbl8s = MAX_NUM_TBL8S + 1;
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ /* rte_lpm6_create: config = NULL */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
+ TEST_LPM_ASSERT(lpm == NULL);
+
+ return PASS;
+}
+
+/*
+ * Creates two different LPM tables. Tries to create a third one with the same
+ * name as the first one and expects the create function to return the same
+ * pointer.
+ */
+int32_t
+test1(void)
+{
+ struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
+ struct rte_lpm6_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_create: lpm name == LPM1 */
+ lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm1 != NULL);
+
+ /* rte_lpm6_create: lpm name == LPM2 */
+ lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm2 != NULL);
+
+ /* rte_lpm6_create: lpm name == LPM2 */
+ lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm3 == NULL);
+
+ rte_lpm6_free(lpm1);
+ rte_lpm6_free(lpm2);
+
+ return PASS;
+}
+
+/*
+ * Create lpm table then delete lpm table 20 times
+ * Use a slightly different rules size each time
+ */
+int32_t
+test2(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ int32_t i;
+
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_free: Free NULL */
+ for (i = 0; i < 20; i++) {
+ config.max_rules = MAX_RULES - i;
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ rte_lpm6_free(lpm);
+ }
+
+ /* Can not test free so return success */
+ return PASS;
+}
+
+/*
+ * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test3(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ rte_lpm6_free(lpm);
+ rte_lpm6_free(NULL);
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
+ */
+int32_t
+test4(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 24, next_hop = 100;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_add: lpm == NULL */
+ status = rte_lpm6_add(NULL, ip, depth, next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm6_add: depth < 1 */
+ status = rte_lpm6_add(lpm, ip, 0, next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm6_add: depth > MAX_DEPTH */
+ status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm6_delete fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test5(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 24;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm_delete: lpm == NULL */
+ status = rte_lpm6_delete(NULL, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm_delete: depth < 1 */
+ status = rte_lpm6_delete(lpm, ip, 0);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm_delete: depth > MAX_DEPTH */
+ status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Check that rte_lpm6_lookup fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test6(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint32_t next_hop_return = 0;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_lookup: lpm == NULL */
+ status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm6_lookup: ip = NULL */
+ status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm6_lookup: next_hop = NULL */
+ status = rte_lpm6_lookup(lpm, ip, NULL);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
+ * input arguments
+ */
+int32_t
+test7(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[10][16];
+ int32_t next_hop_return[10];
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_lookup: lpm == NULL */
+ status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm6_lookup: ip = NULL */
+ status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm6_lookup: next_hop = NULL */
+ status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
+ * input arguments
+ */
+int32_t
+test8(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[10][16];
+ uint8_t depth[10];
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* rte_lpm6_delete: lpm == NULL */
+ status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ /*Create vaild lpm to use in rest of test. */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* rte_lpm6_delete: ip = NULL */
+ status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ /* rte_lpm6_delete: next_hop = NULL */
+ status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
+ TEST_LPM_ASSERT(status < 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth < 24.
+ * Check all the combinations for the first three bytes that result in a hit.
+ * Delete the rule and check that the same test returs a miss.
+ */
+int32_t
+test9(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 16;
+ uint32_t next_hop_add = 100, next_hop_return = 0;
+ int32_t status = 0;
+ uint8_t i;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ for (i = 0; i < UINT8_MAX; i++) {
+ ip[2] = i;
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+ }
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ for (i = 0; i < UINT8_MAX; i++) {
+ ip[2] = i;
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
+ * another one and expects success.
+ */
+int32_t
+test10(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth;
+ uint32_t next_hop_add = 100;
+ int32_t status = 0;
+ int i;
+
+ config.max_rules = 127;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ for (i = 1; i < 128; i++) {
+ depth = (uint8_t)i;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+ }
+
+ depth = 128;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == -ENOSPC);
+
+ depth = 127;
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 128;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Creates an LPM table with a small number of tbl8s and exhaust them in the
+ * middle of the process of creating a rule.
+ */
+int32_t
+test11(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth;
+ uint32_t next_hop_add = 100;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = 16;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ depth = 128;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ ip[0] = 1;
+ depth = 25;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 33;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 41;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 49;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == -ENOSPC);
+
+ depth = 41;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Creates an LPM table with a small number of tbl8s and exhaust them in the
+ * middle of the process of adding a rule when there is already an existing rule
+ * in that position and needs to be extended.
+ */
+int32_t
+test12(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth;
+ uint32_t next_hop_add = 100;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = 16;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ depth = 128;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ ip[0] = 1;
+ depth = 41;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 49;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == -ENOSPC);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
+ * Delete one of the rules and tries to add the third one again.
+ */
+int32_t
+test13(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth;
+ uint32_t next_hop_add = 100;
+ int32_t status = 0;
+
+ config.max_rules = 2;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ depth = 1;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 2;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 3;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == -ENOSPC);
+
+ depth = 2;
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 3;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add 2^12 routes with different first 12 bits and depth 25.
+ * Add one more route with the same depth and check that results in a failure.
+ * After that delete the last rule and create the one that was attempted to be
+ * created. This checks tbl8 exhaustion.
+ */
+int32_t
+test14(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 25;
+ uint32_t next_hop_add = 100;
+ int32_t status = 0;
+ int i;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = 256;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ for (i = 0; i < 256; i++) {
+ ip[0] = (uint8_t)i;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+ }
+
+ ip[0] = 255;
+ ip[1] = 1;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == -ENOSPC);
+
+ ip[0] = 255;
+ ip[1] = 0;
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ ip[0] = 255;
+ ip[1] = 1;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth = 24
+ */
+int32_t
+test15(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 24;
+ uint32_t next_hop_add = 100, next_hop_return = 0;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with depth > 24
+ */
+int32_t
+test16(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth = 128;
+ uint32_t next_hop_add = 100, next_hop_return = 0;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Use rte_lpm6_add to add rules which effect only the second half of the lpm
+ * table. Use all possible depths ranging from 1..32. Set the next hop = to the
+ * depth. Check lookup hit for on every add and check for lookup miss on the
+ * first half of the lpm table after each add. Finally delete all rules going
+ * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
+ * delete. The lookup should return the next_hop_add value related to the
+ * previous depth value (i.e. depth -1).
+ */
+int32_t
+test17(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255};
+ uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t depth;
+ uint32_t next_hop_add, next_hop_return;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Loop with rte_lpm6_add. */
+ for (depth = 1; depth <= 16; depth++) {
+ /* Let the next_hop_add value = depth. Just for change. */
+ next_hop_add = depth;
+
+ status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ /* Check IP in first half of tbl24 which should be empty. */
+ status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+ }
+
+ /* Loop with rte_lpm6_delete. */
+ for (depth = 16; depth >= 1; depth--) {
+ next_hop_add = (depth - 1);
+
+ status = rte_lpm6_delete(lpm, ip2, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
+
+ if (depth != 1) {
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+ }
+ else {
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * - Add & lookup to hit invalid TBL24 entry
+ * - Add & lookup to hit valid TBL24 entry not extended
+ * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
+ * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
+ */
+int32_t
+test18(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[16], ip_1[16], ip_2[16];
+ uint8_t depth, depth_1, depth_2;
+ uint32_t next_hop_add, next_hop_add_1,
+ next_hop_add_2, next_hop_return;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* Add & lookup to hit invalid TBL24 entry */
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /* Add & lookup to hit valid TBL24 entry not extended */
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 23;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ depth = 24;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ depth = 24;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 23;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
+ * entry.
+ */
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
+ * entry
+ */
+ IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth_1 = 25;
+ next_hop_add_1 = 101;
+
+ IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth_2 = 32;
+ next_hop_add_2 = 102;
+
+ next_hop_return = 0;
+
+ status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+ status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
+
+ status = rte_lpm6_delete(lpm, ip_2, depth_2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
+
+ status = rte_lpm6_delete(lpm, ip_1, depth_1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
+ * lookup)
+ * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
+ * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
+ * delete & lookup)
+ * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
+ * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
+ * - Delete a rule that is not present in the TBL24 & lookup
+ * - Delete a rule that is not present in the TBL8 & lookup
+ */
+int32_t
+test19(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[16];
+ uint8_t depth;
+ uint32_t next_hop_add, next_hop_return;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* Add rule that covers a TBL24 range previously invalid & lookup
+ * (& delete & lookup)
+ */
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 16;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 25;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ rte_lpm6_delete_all(lpm);
+
+ /*
+ * Add rule that extends a TBL24 valid entry & lookup for both rules
+ * (& delete & lookup)
+ */
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ next_hop_add = 100;
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /*
+ * Add rule that updates the next hop in TBL24 & lookup
+ * (& delete & lookup)
+ */
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /*
+ * Add rule that updates the next hop in TBL8 & lookup
+ * (& delete & lookup)
+ */
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /* Delete a rule that is not present in the TBL24 & lookup */
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_delete_all(lpm);
+
+ /* Delete a rule that is not present in the TBL8 & lookup */
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 32;
+ next_hop_add = 100;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status < 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add two rules, lookup to hit the more specific one, lookup to hit the less
+ * specific one delete the less specific rule and lookup previous values again;
+ * add a more specific rule than the existing rule, lookup again
+ */
+int32_t
+test20(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[16];
+ uint8_t depth;
+ uint32_t next_hop_add, next_hop_return;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
+ depth = 128;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ next_hop_add = 100;
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 24;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
+ depth = 128;
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Adds 3 rules and look them up through the lookup_bulk function.
+ * Includes in the lookup a fourth IP address that won't match
+ * and checks that the result is as expected.
+ */
+int32_t
+test21(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip_batch[4][16];
+ uint8_t depth;
+ uint32_t next_hop_add;
+ int32_t next_hop_return[4];
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 48;
+ next_hop_add = 100;
+
+ status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 48;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 48;
+ next_hop_add = 102;
+
+ status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 4);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
+ && next_hop_return[1] == 101 && next_hop_return[2] == 102
+ && next_hop_return[3] == -1);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Adds 5 rules and look them up.
+ * Use the delete_bulk function to delete two of them. Lookup again.
+ * Use the delete_bulk function to delete one more. Lookup again.
+ * Use the delete_bulk function to delete two more, one invalid. Lookup again.
+ * Use the delete_bulk function to delete the remaining one. Lookup again.
+ */
+int32_t
+test22(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip_batch[5][16];
+ uint8_t depth[5];
+ uint32_t next_hop_add;
+ int32_t next_hop_return[5];
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Adds 5 rules and look them up */
+
+ IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth[0] = 48;
+ next_hop_add = 101;
+
+ status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth[1] = 48;
+ next_hop_add = 102;
+
+ status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth[2] = 48;
+ next_hop_add = 103;
+
+ status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth[3] = 48;
+ next_hop_add = 104;
+
+ status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth[4] = 48;
+ next_hop_add = 105;
+
+ status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 5);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
+ && next_hop_return[1] == 102 && next_hop_return[2] == 103
+ && next_hop_return[3] == 104 && next_hop_return[4] == 105);
+
+ /* Use the delete_bulk function to delete two of them. Lookup again */
+
+ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 5);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
+ && next_hop_return[1] == -1 && next_hop_return[2] == 103
+ && next_hop_return[3] == 104 && next_hop_return[4] == 105);
+
+ /* Use the delete_bulk function to delete one more. Lookup again */
+
+ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 5);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
+ && next_hop_return[1] == -1 && next_hop_return[2] == -1
+ && next_hop_return[3] == 104 && next_hop_return[4] == 105);
+
+ /* Use the delete_bulk function to delete two, one invalid. Lookup again */
+
+ IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
+ TEST_LPM_ASSERT(status == 0);
+
+ IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 5);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
+ && next_hop_return[1] == -1 && next_hop_return[2] == -1
+ && next_hop_return[3] == -1 && next_hop_return[4] == 105);
+
+ /* Use the delete_bulk function to delete the remaining one. Lookup again */
+
+ status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
+ next_hop_return, 5);
+ TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
+ && next_hop_return[1] == -1 && next_hop_return[2] == -1
+ && next_hop_return[3] == -1 && next_hop_return[4] == -1);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
+ * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
+ * and contraction.
+ */
+int32_t
+test23(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint32_t i;
+ uint8_t ip[16];
+ uint8_t depth;
+ uint32_t next_hop_add, next_hop_return;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ depth = 128;
+ next_hop_add = 100;
+
+ for (i = 0; i < 30; i++) {
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT(status == -ENOENT);
+ }
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Sequence of operations for find existing lpm table
+ *
+ * - create table
+ * - find existing table: hit
+ * - find non-existing table: miss
+ */
+int32_t
+test24(void)
+{
+ struct rte_lpm6 *lpm = NULL, *result = NULL;
+ struct rte_lpm6_config config;
+
+ config.max_rules = 256 * 32;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ /* Create lpm */
+ lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Try to find existing lpm */
+ result = rte_lpm6_find_existing("lpm_find_existing");
+ TEST_LPM_ASSERT(result == lpm);
+
+ /* Try to find non-existing lpm */
+ result = rte_lpm6_find_existing("lpm_find_non_existing");
+ TEST_LPM_ASSERT(result == NULL);
+
+ /* Cleanup. */
+ rte_lpm6_delete_all(lpm);
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add a set of random routes with random depths.
+ * Lookup different IP addresses that match the routes previously added.
+ * Checks that the next hop is the expected one.
+ * The routes, IP addresses and expected result for every case have been
+ * precalculated by using a python script and stored in a .h file.
+ */
+int32_t
+test25(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[16];
+ uint32_t i;
+ uint8_t depth;
+ uint32_t next_hop_add, next_hop_return, next_hop_expected;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ for (i = 0; i < 1000; i++) {
+ memcpy(ip, large_route_table[i].ip, 16);
+ depth = large_route_table[i].depth;
+ next_hop_add = large_route_table[i].next_hop;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+ }
+
+ /* generate large IPS table and expected next_hops */
+ generate_large_ips_table(1);
+
+ for (i = 0; i < 100000; i++) {
+ memcpy(ip, large_ips_table[i].ip, 16);
+ next_hop_expected = large_ips_table[i].next_hop;
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) &&
+ (next_hop_return == next_hop_expected));
+ }
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Test for overwriting of tbl8:
+ * - add rule /32 and lookup
+ * - add new rule /24 and lookup
+ * - add third rule /25 and lookup
+ * - lookup /32 and /24 rule to ensure the table has not been overwritten.
+ */
+int32_t
+test26(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t d_ip_10_32 = 32;
+ uint8_t d_ip_10_24 = 24;
+ uint8_t d_ip_20_25 = 25;
+ uint32_t next_hop_ip_10_32 = 100;
+ uint32_t next_hop_ip_10_24 = 105;
+ uint32_t next_hop_ip_20_25 = 111;
+ uint32_t next_hop_return = 0;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
+ next_hop_ip_10_32)) < 0)
+ return -1;
+
+ status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
+ uint32_t test_hop_10_32 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+ if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
+ next_hop_ip_10_24)) < 0)
+ return -1;
+
+ status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
+ uint32_t test_hop_10_24 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+ if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
+ next_hop_ip_20_25)) < 0)
+ return -1;
+
+ status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
+ uint32_t test_hop_20_25 = next_hop_return;
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
+
+ if (test_hop_10_32 == test_hop_10_24) {
+ printf("Next hop return equal\n");
+ return -1;
+ }
+
+ if (test_hop_10_24 == test_hop_20_25){
+ printf("Next hop return equal\n");
+ return -1;
+ }
+
+ status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
+
+ status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
+ TEST_LPM_ASSERT(status == 0);
+ TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Add a rule that reaches the end of the tree.
+ * Add a rule that is more generic than the first one.
+ * Check every possible combination that produces a match for the second rule.
+ * This tests tbl expansion.
+ */
+int32_t
+test27(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
+ uint8_t depth = 128;
+ uint32_t next_hop_add = 100, next_hop_return;
+ int32_t status = 0;
+ int i, j;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ depth = 128;
+ next_hop_add = 128;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ depth = 112;
+ next_hop_add = 112;
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ for (i = 0; i < 256; i++) {
+ ip[14] = (uint8_t)i;
+ for (j = 0; j < 256; j++) {
+ ip[15] = (uint8_t)j;
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ if (i == 0 && j == 0)
+ TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
+ else
+ TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
+ }
+ }
+
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Call add, lookup and delete for a single rule with maximum 21bit next_hop
+ * size.
+ * Check that next_hop returned from lookup is equal to provisioned value.
+ * Delete the rule and check that the same test returs a miss.
+ */
+int32_t
+test28(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t depth = 16;
+ uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
+ int32_t status = 0;
+
+ config.max_rules = MAX_RULES;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
+ TEST_LPM_ASSERT(status == 0);
+
+ status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
+ TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
+
+ status = rte_lpm6_delete(lpm, ip, depth);
+ TEST_LPM_ASSERT(status == 0);
+ rte_lpm6_free(lpm);
+
+ return PASS;
+}
+
+/*
+ * Do all unit tests.
+ */
+static int
+test_lpm6(void)
+{
+ unsigned i;
+ int status = -1, global_status = 0;
+
+ for (i = 0; i < RTE_DIM(tests6); i++) {
+ printf("# test %02d\n", i);
+ status = tests6[i]();
+
+ if (status < 0) {
+ printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
+ global_status = status;
+ }
+ }
+
+ return global_status;
+}
+
+REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);
diff --git a/src/spdk/dpdk/app/test/test_lpm6_data.h b/src/spdk/dpdk/app/test/test_lpm6_data.h
new file mode 100644
index 000000000..c3894f730
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_lpm6_data.h
@@ -0,0 +1,1158 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+#ifndef _TEST_LPM_ROUTES_H_
+#define _TEST_LPM_ROUTES_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+struct rules_tbl_entry {
+ uint8_t ip[16];
+ uint8_t depth;
+ uint8_t next_hop;
+};
+
+struct ips_tbl_entry {
+ uint8_t ip[16];
+ uint8_t next_hop;
+};
+
+/* this large_route_table[ ] is the same as the one with same name
+ * in previous test_lpm6_routes.h . Because this table has only 1000
+ * lines, keeping it doesn't make LPM6 test case so large and also
+ * make the algorithm to generate rule table unnecessary and the
+ * algorithm to genertate test input IPv6 and associated expected
+ * next_hop much simple.
+ */
+
+static struct rules_tbl_entry large_route_table[] = {
+ {{66, 70, 154, 143, 197, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 146},
+ {{107, 79, 18, 235, 142, 84, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 141},
+ {{247, 132, 113, 1, 215, 247, 183, 239, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 23},
+ {{48, 19, 41, 12, 76, 101, 114, 160, 45, 103, 134, 146, 128, 0, 0, 0}, 97, 252},
+ {{5, 70, 208, 170, 19, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 6},
+ {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 137},
+ {{12, 188, 26, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 9},
+ {{1, 235, 101, 202, 26, 92, 23, 22, 179, 223, 128, 0, 0, 0, 0, 0}, 82, 9},
+ {{215, 19, 224, 102, 45, 133, 102, 249, 56, 20, 214, 219, 93, 125, 52, 0}, 120, 163},
+ {{178, 183, 109, 64, 136, 84, 11, 53, 217, 102, 0, 0, 0, 0, 0, 0}, 79, 197},
+ {{212, 39, 158, 71, 253, 98, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 249},
+ {{92, 58, 159, 130, 105, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 88},
+ {{118, 140, 65, 198, 212, 93, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 104},
+ {{86, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 36},
+ {{79, 135, 242, 193, 197, 11, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 239},
+ {{163, 228, 239, 80, 41, 66, 176, 176, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 201},
+ {{31, 9, 231, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 94},
+ {{108, 144, 205, 39, 215, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 241},
+ {{247, 217, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 239},
+ {{24, 186, 73, 182, 240, 251, 125, 165, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 151},
+ {{245, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 137},
+ {{44, 94, 138, 224, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 231},
+ {{184, 221, 109, 135, 225, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 11},
+ {{51, 179, 136, 184, 30, 118, 24, 16, 26, 161, 206, 101, 0, 0, 0, 0}, 96, 20},
+ {{48, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 68},
+ {{143, 235, 237, 220, 89, 119, 187, 143, 209, 94, 46, 58, 120, 0, 0, 0}, 101, 64},
+ {{121, 190, 90, 177, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 217},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 101},
+ {{111, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 58},
+ {{162, 23, 52, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 254},
+ {{76, 103, 44, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 148},
+ {{80, 85, 219, 214, 12, 4, 65, 129, 162, 148, 208, 78, 39, 69, 94, 184}, 126, 126},
+ {{80, 54, 251, 28, 152, 23, 244, 192, 151, 83, 6, 144, 223, 213, 224, 128}, 123, 76},
+ {{39, 232, 237, 103, 191, 188, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 240},
+ {{20, 231, 89, 210, 167, 173, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 33},
+ {{125, 67, 198, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 47},
+ {{26, 239, 153, 5, 213, 121, 31, 114, 161, 46, 84, 15, 148, 160, 0, 0}, 109, 41},
+ {{102, 212, 159, 118, 223, 115, 134, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 72},
+ {{85, 181, 241, 127, 3, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 43},
+ {{61, 199, 131, 226, 3, 230, 94, 119, 240, 0, 0, 0, 0, 0, 0, 0}, 68, 26},
+ {{0, 143, 160, 184, 162, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 139},
+ {{170, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 219},
+ {{61, 122, 24, 251, 124, 122, 202, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 105},
+ {{33, 219, 226, 3, 180, 190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 210},
+ {{51, 251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 151},
+ {{106, 185, 11, 122, 197, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 28},
+ {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 64},
+ {{239, 195, 77, 239, 131, 156, 2, 246, 191, 178, 204, 160, 21, 213, 30, 128}, 121, 9},
+ {{141, 207, 181, 99, 55, 245, 151, 228, 65, 50, 85, 16, 0, 0, 0, 0}, 92, 250},
+ {{110, 159, 230, 251, 224, 210, 58, 49, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 200},
+ {{134, 26, 104, 32, 129, 41, 201, 50, 164, 69, 178, 156, 156, 133, 8, 218}, 127, 132},
+ {{253, 207, 116, 105, 210, 166, 186, 99, 182, 0, 0, 0, 0, 0, 0, 0}, 71, 182},
+ {{211, 73, 38, 80, 183, 168, 52, 138, 25, 214, 112, 8, 252, 0, 0, 0}, 102, 7},
+ {{200, 244, 108, 238, 164, 141, 215, 39, 233, 249, 120, 80, 112, 0, 0, 0}, 100, 146},
+ {{107, 44, 250, 202, 64, 37, 107, 105, 140, 0, 0, 0, 0, 0, 0, 0}, 70, 98},
+ {{93, 86, 56, 27, 159, 195, 126, 39, 240, 201, 48, 0, 0, 0, 0, 0}, 86, 179},
+ {{32, 202, 214, 242, 39, 141, 61, 146, 138, 96, 0, 0, 0, 0, 0, 0}, 77, 245},
+ {{167, 77, 249, 28, 210, 196, 227, 241, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 2},
+ {{241, 59, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5},
+ {{143, 68, 146, 210, 173, 155, 251, 173, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 169},
+ {{167, 180, 226, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 52},
+ {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 177},
+ {{238, 9, 168, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 74},
+ {{203, 148, 16, 96, 125, 18, 86, 1, 91, 244, 251, 20, 31, 14, 75, 128}, 122, 212},
+ {{111, 227, 137, 94, 65, 21, 77, 137, 119, 130, 159, 19, 159, 45, 18, 192}, 122, 238},
+ {{59, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 18},
+ {{110, 192, 255, 120, 84, 215, 3, 130, 38, 224, 0, 0, 0, 0, 0, 0}, 75, 155},
+ {{152, 79, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97},
+ {{118, 186, 157, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8},
+ {{70, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 123},
+ {{253, 119, 114, 227, 18, 243, 81, 61, 238, 107, 190, 144, 0, 0, 0, 0}, 92, 11},
+ {{166, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 211},
+ {{43, 95, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 116},
+ {{94, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 57},
+ {{182, 251, 195, 132, 66, 7, 208, 146, 223, 231, 211, 181, 25, 176, 0, 0}, 108, 178},
+ {{152, 166, 111, 233, 194, 17, 230, 41, 221, 253, 69, 123, 108, 0, 0, 0}, 102, 93},
+ {{106, 141, 235, 190, 82, 241, 152, 186, 195, 81, 86, 144, 0, 0, 0, 0}, 92, 3},
+ {{32, 81, 210, 153, 151, 29, 11, 62, 127, 177, 194, 254, 103, 83, 58, 128}, 121, 162},
+ {{79, 112, 224, 26, 174, 39, 98, 181, 115, 57, 209, 189, 136, 48, 0, 0}, 109, 125},
+ {{106, 197, 83, 151, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 33},
+ {{190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 254},
+ {{156, 73, 249, 148, 55, 192, 20, 42, 142, 128, 0, 0, 0, 0, 0, 0}, 74, 66},
+ {{64, 107, 36, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 4},
+ {{115, 148, 71, 250, 158, 174, 168, 249, 106, 110, 196, 0, 0, 0, 0, 0}, 86, 122},
+ {{18, 139, 152, 44, 38, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 59},
+ {{55, 229, 117, 106, 146, 95, 74, 220, 122, 0, 84, 202, 183, 138, 120, 0}, 117, 99},
+ {{153, 211, 3, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 41},
+ {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 112},
+ {{49, 192, 102, 142, 216, 3, 114, 64, 165, 128, 168, 0, 0, 0, 0, 0}, 85, 255},
+ {{201, 143, 240, 240, 209, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 106},
+ {{158, 19, 164, 196, 87, 162, 33, 120, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 170},
+ {{5, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 86},
+ {{34, 170, 246, 62, 198, 85, 193, 227, 252, 68, 0, 0, 0, 0, 0, 0}, 79, 155},
+ {{21, 52, 9, 86, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 65},
+ {{203, 81, 49, 171, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 39},
+ {{211, 218, 87, 244, 93, 181, 118, 41, 156, 143, 254, 0, 0, 0, 0, 0}, 90, 162},
+ {{77, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 69},
+ {{158, 219, 219, 39, 4, 219, 100, 63, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 163},
+ {{61, 50, 232, 1, 185, 252, 243, 54, 189, 240, 170, 192, 0, 0, 0, 0}, 90, 116},
+ {{241, 143, 33, 19, 247, 55, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 19},
+ {{61, 28, 61, 252, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 48},
+ {{102, 112, 194, 108, 90, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 230},
+ {{74, 88, 58, 66, 172, 41, 144, 204, 195, 240, 0, 0, 0, 0, 0, 0}, 78, 155},
+ {{44, 148, 187, 58, 190, 59, 190, 187, 124, 138, 222, 131, 0, 0, 0, 0}, 96, 158},
+ {{67, 7, 216, 139, 93, 224, 20, 135, 186, 86, 209, 111, 60, 80, 0, 0}, 113, 252},
+ {{209, 26, 12, 174, 5, 101, 164, 181, 237, 63, 192, 57, 54, 120, 0, 0}, 110, 176},
+ {{4, 66, 232, 52, 239, 56, 48, 58, 192, 0, 0, 0, 0, 0, 0, 0}, 66, 211},
+ {{158, 165, 2, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 15},
+ {{85, 204, 245, 198, 68, 44, 39, 71, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 95},
+ {{181, 134, 25, 87, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 169},
+ {{26, 230, 61, 36, 79, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 249},
+ {{5, 170, 198, 139, 65, 186, 188, 45, 42, 253, 165, 89, 206, 0, 0, 0}, 105, 61},
+ {{211, 245, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 63},
+ {{117, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 43},
+ {{103, 17, 123, 102, 70, 206, 90, 92, 124, 198, 0, 0, 0, 0, 0, 0}, 81, 228},
+ {{192, 237, 88, 244, 53, 30, 61, 160, 143, 64, 0, 0, 0, 0, 0, 0}, 78, 165},
+ {{199, 82, 217, 183, 2, 179, 195, 6, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 3},
+ {{157, 230, 79, 162, 57, 125, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 211},
+ {{27, 67, 64, 235, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 210},
+ {{72, 158, 163, 106, 193, 137, 190, 7, 250, 165, 249, 73, 64, 0, 0, 0}, 99, 61},
+ {{34, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 120},
+ {{215, 141, 95, 192, 189, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 94},
+ {{31, 181, 56, 141, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 153},
+ {{153, 73, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 221},
+ {{162, 107, 41, 189, 165, 155, 22, 139, 165, 72, 96, 0, 0, 0, 0, 0}, 87, 163},
+ {{218, 17, 204, 165, 217, 251, 107, 45, 29, 15, 192, 167, 75, 0, 0, 0}, 106, 188},
+ {{200, 124, 238, 213, 35, 228, 94, 141, 86, 187, 101, 60, 115, 52, 131, 16}, 124, 15},
+ {{74, 237, 160, 56, 141, 217, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 28},
+ {{163, 47, 242, 103, 173, 217, 88, 154, 38, 200, 32, 0, 0, 0, 0, 0}, 84, 240},
+ {{20, 227, 128, 28, 144, 147, 22, 13, 94, 129, 107, 88, 0, 0, 0, 0}, 93, 59},
+ {{95, 144, 229, 107, 218, 125, 204, 233, 161, 42, 180, 64, 0, 0, 0, 0}, 90, 195},
+ {{155, 220, 83, 208, 108, 16, 134, 156, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 10},
+ {{179, 138, 55, 80, 190, 153, 12, 237, 22, 120, 69, 0, 0, 0, 0, 0}, 88, 206},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 137},
+ {{3, 119, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 225},
+ {{13, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 223},
+ {{117, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 29},
+ {{164, 19, 195, 47, 136, 190, 156, 255, 30, 74, 143, 134, 162, 0, 0, 0}, 103, 166},
+ {{40, 235, 94, 135, 135, 230, 71, 33, 64, 233, 0, 0, 0, 0, 0, 0}, 80, 178},
+ {{222, 151, 166, 97, 129, 250, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 38},
+ {{174, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 141},
+ {{6, 189, 100, 150, 250, 13, 46, 98, 228, 139, 50, 52, 52, 196, 128, 0}, 116, 230},
+ {{75, 252, 89, 205, 37, 52, 106, 79, 188, 120, 54, 119, 160, 0, 0, 0}, 99, 124},
+ {{38, 18, 146, 6, 63, 64, 231, 10, 152, 199, 5, 143, 147, 4, 252, 0}, 118, 54},
+ {{111, 119, 169, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 162},
+ {{105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 32},
+ {{143, 57, 57, 101, 98, 182, 74, 227, 205, 143, 253, 237, 8, 0, 0, 0}, 102, 237},
+ {{30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 215},
+ {{14, 232, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 138},
+ {{14, 53, 67, 216, 229, 155, 149, 139, 31, 253, 184, 126, 133, 108, 40, 0}, 118, 73},
+ {{22, 58, 40, 143, 188, 132, 239, 14, 181, 252, 81, 192, 0, 0, 0, 0}, 90, 43},
+ {{11, 222, 185, 243, 248, 150, 79, 230, 214, 213, 3, 23, 193, 196, 0, 0}, 112, 88},
+ {{14, 226, 198, 117, 84, 93, 22, 96, 77, 241, 173, 68, 68, 204, 72, 0}, 119, 91},
+ {{15, 103, 247, 219, 150, 142, 92, 50, 144, 0, 0, 0, 0, 0, 0, 0}, 69, 140},
+ {{0, 213, 77, 244, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 65},
+ {{178, 174, 174, 239, 72, 181, 36, 217, 40, 169, 12, 104, 149, 157, 125, 128}, 122, 201},
+ {{118, 53, 55, 17, 97, 227, 243, 176, 2, 0, 0, 0, 0, 0, 0, 0}, 72, 69},
+ {{21, 253, 4, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 170},
+ {{5, 249, 186, 133, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 192},
+ {{47, 79, 35, 66, 11, 178, 161, 28, 87, 180, 45, 128, 0, 0, 0, 0}, 89, 21},
+ {{242, 227, 20, 73, 150, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 35},
+ {{121, 169, 102, 118, 157, 192, 154, 186, 126, 0, 0, 0, 0, 0, 0, 0}, 71, 235},
+ {{9, 138, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 240},
+ {{45, 173, 14, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 136},
+ {{127, 47, 51, 201, 236, 45, 142, 80, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 186},
+ {{247, 233, 34, 38, 181, 207, 127, 20, 224, 118, 59, 148, 0, 0, 0, 0}, 95, 174},
+ {{126, 187, 198, 104, 245, 223, 219, 18, 31, 124, 0, 0, 0, 0, 0, 0}, 79, 153},
+ {{3, 163, 107, 228, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 35, 118},
+ {{167, 109, 2, 95, 11, 62, 45, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 113},
+ {{76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 58},
+ {{58, 190, 204, 151, 222, 147, 47, 78, 38, 203, 9, 17, 64, 0, 0, 0}, 101, 206},
+ {{254, 220, 254, 220, 204, 79, 35, 127, 242, 63, 106, 232, 127, 180, 0, 0}, 111, 42},
+ {{77, 156, 8, 209, 181, 37, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230},
+ {{65, 89, 137, 76, 208, 199, 166, 90, 128, 0, 0, 0, 0, 0, 0, 0}, 67, 6},
+ {{47, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 254},
+ {{172, 154, 12, 108, 77, 37, 106, 8, 234, 7, 248, 212, 112, 160, 0, 0}, 108, 214},
+ {{254, 117, 239, 244, 154, 89, 166, 241, 12, 108, 127, 153, 206, 160, 0, 0}, 107, 43},
+ {{113, 160, 206, 52, 143, 12, 9, 148, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 178},
+ {{178, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 179},
+ {{229, 177, 28, 106, 59, 75, 182, 241, 36, 79, 224, 0, 0, 0, 0, 0}, 87, 236},
+ {{156, 72, 93, 193, 50, 235, 75, 228, 88, 115, 89, 119, 128, 0, 0, 0}, 98, 184},
+ {{28, 232, 28, 249, 83, 105, 211, 7, 136, 147, 231, 64, 0, 0, 0, 0}, 91, 95},
+ {{217, 33, 23, 107, 74, 42, 135, 197, 144, 34, 40, 243, 13, 126, 36, 136}, 127, 152},
+ {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 113},
+ {{85, 172, 121, 126, 213, 57, 225, 54, 197, 73, 85, 251, 9, 64, 0, 0}, 108, 137},
+ {{104, 46, 25, 71, 86, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 224},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 61},
+ {{241, 113, 254, 106, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 205},
+ {{29, 36, 12, 244, 197, 127, 240, 8, 167, 134, 154, 248, 199, 123, 143, 240}, 124, 170},
+ {{58, 29, 129, 94, 43, 139, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 117},
+ {{213, 124, 147, 196, 7, 82, 67, 70, 228, 0, 0, 0, 0, 0, 0, 0}, 70, 225},
+ {{164, 168, 161, 140, 87, 85, 250, 41, 34, 0, 0, 0, 0, 0, 0, 0}, 72, 34},
+ {{186, 142, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 5},
+ {{237, 249, 9, 70, 247, 97, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 92},
+ {{155, 92, 145, 218, 125, 226, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 230},
+ {{35, 169, 62, 156, 86, 4, 125, 219, 119, 113, 191, 75, 198, 113, 0, 0}, 112, 61},
+ {{207, 63, 96, 186, 26, 68, 115, 161, 163, 59, 190, 166, 18, 78, 232, 0}, 117, 221},
+ {{86, 40, 200, 199, 247, 86, 159, 179, 191, 184, 117, 173, 211, 158, 0, 128}, 121, 105},
+ {{104, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 181},
+ {{205, 35, 123, 178, 36, 64, 62, 153, 195, 250, 0, 0, 0, 0, 0, 0}, 79, 110},
+ {{117, 40, 57, 157, 138, 160, 223, 59, 155, 145, 64, 0, 0, 0, 0, 0}, 86, 103},
+ {{74, 166, 140, 146, 74, 72, 229, 99, 167, 124, 107, 117, 217, 14, 246, 64}, 123, 218},
+ {{12, 222, 244, 183, 83, 146, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 146},
+ {{11, 98, 146, 110, 95, 96, 80, 142, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 90},
+ {{235, 5, 187, 199, 30, 170, 82, 187, 228, 159, 22, 25, 204, 112, 0, 0}, 108, 197},
+ {{35, 96, 146, 145, 155, 116, 252, 181, 29, 205, 230, 246, 30, 0, 0, 0}, 103, 158},
+ {{174, 38, 56, 244, 227, 102, 252, 237, 128, 86, 0, 0, 0, 0, 0, 0}, 81, 118},
+ {{65, 134, 37, 58, 90, 125, 60, 84, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 95},
+ {{253, 117, 135, 98, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 152},
+ {{111, 115, 188, 184, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 239},
+ {{202, 24, 89, 9, 149, 45, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 48},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 228},
+ {{244, 98, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 247},
+ {{151, 167, 43, 178, 116, 194, 173, 126, 236, 98, 40, 0, 0, 0, 0, 0}, 85, 12},
+ {{60, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 129},
+ {{208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 50},
+ {{126, 11, 216, 242, 7, 45, 121, 208, 110, 135, 210, 75, 59, 182, 228, 42}, 128, 250},
+ {{217, 26, 184, 146, 3, 18, 240, 15, 135, 8, 0, 0, 0, 0, 0, 0}, 77, 249},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230},
+ {{145, 28, 29, 184, 2, 85, 234, 135, 98, 111, 136, 32, 0, 0, 0, 0}, 92, 228},
+ {{108, 104, 255, 254, 34, 95, 72, 157, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 181},
+ {{153, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 206},
+ {{22, 250, 130, 201, 132, 248, 189, 108, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 122},
+ {{158, 165, 234, 18, 44, 61, 82, 61, 235, 0, 0, 0, 0, 0, 0, 0}, 72, 81},
+ {{236, 57, 124, 110, 124, 218, 82, 70, 142, 78, 18, 128, 0, 0, 0, 0}, 95, 175},
+ {{94, 209, 200, 201, 149, 162, 248, 134, 239, 226, 1, 237, 16, 134, 56, 0}, 118, 170},
+ {{187, 42, 31, 144, 236, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 174},
+ {{90, 214, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 104},
+ {{194, 220, 211, 212, 211, 32, 196, 98, 71, 62, 153, 103, 80, 35, 128, 0}, 114, 113},
+ {{24, 255, 158, 64, 180, 148, 10, 81, 243, 247, 0, 0, 0, 0, 0, 0}, 80, 89},
+ {{231, 155, 100, 242, 112, 160, 160, 95, 98, 253, 219, 21, 239, 90, 0, 0}, 113, 151},
+ {{225, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 108},
+ {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 224},
+ {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 95},
+ {{72, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 173},
+ {{185, 51, 51, 167, 18, 44, 36, 59, 35, 135, 20, 104, 0, 0, 0, 0}, 93, 176},
+ {{57, 146, 252, 60, 197, 68, 39, 162, 80, 198, 137, 50, 97, 92, 124, 0}, 119, 84},
+ {{254, 46, 242, 105, 86, 94, 96, 14, 130, 176, 0, 0, 0, 0, 0, 0}, 78, 104},
+ {{247, 202, 176, 76, 69, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 236},
+ {{50, 233, 203, 77, 42, 21, 115, 163, 166, 138, 192, 52, 178, 37, 112, 0}, 116, 153},
+ {{62, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 190},
+ {{53, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 202},
+ {{198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 54},
+ {{189, 234, 106, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 156},
+ {{110, 24, 228, 65, 216, 147, 9, 48, 60, 179, 172, 91, 115, 185, 227, 96}, 126, 245},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 6, 218},
+ {{74, 177, 89, 218, 248, 18, 176, 39, 118, 173, 201, 152, 0, 0, 0, 0}, 93, 72},
+ {{31, 13, 153, 92, 27, 122, 150, 232, 88, 95, 202, 171, 208, 158, 0, 0}, 112, 183},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 183},
+ {{63, 37, 46, 158, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 241},
+ {{53, 209, 59, 13, 202, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 106},
+ {{184, 44, 149, 221, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 180},
+ {{222, 134, 37, 62, 223, 193, 39, 246, 15, 151, 200, 146, 0, 0, 0, 0}, 96, 142},
+ {{199, 176, 189, 37, 233, 177, 252, 216, 94, 175, 253, 119, 96, 0, 0, 0}, 100, 6},
+ {{44, 195, 201, 106, 209, 120, 122, 38, 43, 30, 142, 22, 196, 175, 100, 0}, 118, 33},
+ {{33, 166, 10, 174, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 224},
+ {{54, 1, 189, 195, 133, 49, 36, 80, 138, 200, 0, 0, 0, 0, 0, 0}, 78, 14},
+ {{241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 149},
+ {{221, 131, 4, 247, 112, 89, 187, 119, 219, 80, 122, 156, 216, 160, 0, 0}, 108, 131},
+ {{102, 20, 46, 129, 202, 247, 129, 1, 237, 71, 103, 58, 217, 44, 4, 0}, 121, 133},
+ {{107, 156, 151, 44, 215, 98, 171, 126, 85, 32, 42, 128, 0, 0, 0, 0}, 89, 33},
+ {{54, 25, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 204},
+ {{149, 211, 242, 14, 112, 219, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 43},
+ {{95, 26, 143, 193, 8, 76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 168},
+ {{63, 102, 244, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 180},
+ {{64, 85, 124, 226, 59, 239, 64, 130, 68, 122, 93, 74, 32, 37, 0, 0}, 112, 208},
+ {{113, 90, 253, 149, 3, 218, 34, 215, 3, 143, 192, 64, 0, 0, 0, 0}, 90, 25},
+ {{75, 231, 33, 5, 11, 94, 117, 104, 150, 60, 72, 161, 96, 38, 0, 0}, 111, 50},
+ {{52, 13, 248, 1, 251, 14, 50, 29, 212, 123, 130, 177, 101, 96, 0, 0}, 109, 110},
+ {{248, 221, 150, 132, 252, 82, 96, 2, 80, 232, 97, 239, 253, 64, 0, 0}, 109, 21},
+ {{136, 77, 164, 161, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 147},
+ {{1, 33, 66, 254, 144, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 56},
+ {{181, 25, 186, 225, 109, 190, 76, 158, 118, 122, 20, 64, 125, 55, 8, 0}, 117, 144},
+ {{191, 187, 160, 140, 17, 6, 80, 120, 236, 212, 104, 144, 128, 0, 0, 0}, 100, 198},
+ {{201, 61, 150, 254, 70, 77, 214, 211, 171, 163, 245, 64, 0, 0, 0, 0}, 90, 235},
+ {{143, 226, 190, 50, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 105},
+ {{65, 168, 226, 36, 201, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 138},
+ {{136, 40, 65, 90, 47, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 122},
+ {{94, 189, 224, 200, 170, 11, 79, 172, 0, 0, 0, 0, 0, 0, 0, 0}, 65, 193},
+ {{236, 41, 169, 234, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 231},
+ {{1, 40, 140, 95, 81, 173, 250, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 250},
+ {{83, 176, 146, 112, 89, 156, 57, 220, 125, 48, 44, 0, 0, 0, 0, 0}, 86, 24},
+ {{76, 125, 228, 249, 243, 160, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 191},
+ {{10, 203, 204, 49, 212, 115, 125, 4, 239, 122, 81, 34, 1, 198, 216, 0}, 117, 111},
+ {{74, 214, 23, 44, 211, 40, 161, 61, 237, 190, 155, 59, 173, 42, 0, 0}, 111, 205},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 133},
+ {{127, 0, 130, 61, 209, 5, 232, 35, 35, 42, 114, 52, 169, 234, 191, 0}, 122, 122},
+ {{201, 107, 210, 13, 187, 62, 145, 28, 31, 189, 56, 0, 0, 0, 0, 0}, 87, 227},
+ {{147, 171, 63, 145, 47, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 53},
+ {{93, 232, 10, 97, 21, 243, 213, 135, 200, 0, 0, 0, 0, 0, 0, 0}, 72, 224},
+ {{144, 121, 41, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 199},
+ {{116, 105, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 79},
+ {{142, 149, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 19},
+ {{97, 0, 228, 158, 50, 233, 251, 249, 0, 66, 197, 226, 0, 0, 0, 0}, 96, 211},
+ {{114, 228, 199, 155, 175, 104, 26, 213, 66, 249, 120, 218, 164, 252, 212, 0}, 120, 6},
+ {{224, 166, 76, 200, 121, 60, 110, 65, 60, 95, 137, 190, 92, 218, 218, 0}, 121, 143},
+ {{139, 219, 92, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 135},
+ {{203, 237, 64, 189, 28, 13, 75, 197, 219, 243, 172, 3, 142, 32, 0, 0}, 109, 21},
+ {{237, 186, 88, 254, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 220},
+ {{182, 230, 93, 162, 129, 25, 56, 196, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 151},
+ {{245, 45, 69, 226, 90, 212, 254, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 111},
+ {{107, 229, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 63},
+ {{119, 208, 177, 235, 222, 252, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 112},
+ {{178, 151, 220, 162, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 48},
+ {{109, 26, 95, 170, 166, 151, 137, 83, 226, 82, 5, 114, 253, 210, 18, 12}, 126, 100},
+ {{126, 27, 252, 19, 219, 129, 121, 48, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 156},
+ {{211, 195, 152, 145, 154, 93, 228, 215, 135, 101, 28, 82, 0, 0, 0, 0}, 95, 120},
+ {{252, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 5},
+ {{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 103},
+ {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 84},
+ {{225, 179, 43, 43, 222, 145, 205, 238, 164, 158, 147, 229, 56, 0, 0, 0}, 101, 24},
+ {{208, 127, 151, 24, 64, 113, 47, 85, 209, 79, 144, 0, 0, 0, 0, 0}, 86, 81},
+ {{178, 144, 203, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 96},
+ {{56, 227, 139, 4, 86, 87, 180, 1, 215, 167, 237, 156, 111, 64, 47, 0}, 121, 6},
+ {{80, 76, 204, 119, 172, 169, 254, 81, 104, 166, 219, 44, 173, 161, 212, 0}, 119, 40},
+ {{129, 141, 139, 34, 241, 101, 223, 144, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 143},
+ {{85, 102, 137, 98, 65, 103, 54, 142, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 69},
+ {{56, 31, 159, 13, 201, 139, 161, 31, 89, 137, 4, 0, 0, 0, 0, 0}, 92, 48},
+ {{229, 221, 54, 216, 223, 27, 196, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 115},
+ {{5, 144, 176, 43, 180, 187, 20, 49, 59, 73, 108, 34, 83, 32, 192, 0}, 115, 130},
+ {{24, 217, 205, 193, 74, 123, 160, 106, 103, 74, 200, 0, 0, 0, 0, 0}, 86, 57},
+ {{247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 97},
+ {{12, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 146},
+ {{160, 28, 201, 119, 148, 93, 251, 118, 28, 179, 123, 52, 71, 232, 48, 0}, 117, 194},
+ {{152, 126, 17, 54, 101, 56, 130, 1, 205, 41, 207, 90, 151, 123, 128, 0}, 114, 129},
+ {{77, 165, 29, 239, 95, 242, 34, 1, 11, 204, 135, 239, 128, 0, 0, 0}, 97, 159},
+ {{183, 108, 146, 118, 74, 190, 7, 141, 9, 92, 2, 2, 8, 218, 120, 0}, 117, 242},
+ {{37, 152, 29, 239, 242, 53, 56, 143, 219, 22, 14, 158, 49, 0, 0, 0}, 104, 162},
+ {{198, 53, 241, 102, 240, 244, 97, 203, 62, 128, 213, 214, 220, 0, 0, 0}, 102, 140},
+ {{144, 89, 48, 42, 249, 231, 189, 178, 232, 199, 30, 58, 63, 57, 0, 0}, 113, 77},
+ {{68, 212, 177, 123, 44, 224, 19, 172, 89, 87, 192, 0, 0, 0, 0, 0}, 82, 121},
+ {{252, 29, 179, 224, 4, 121, 205, 67, 152, 0, 0, 0, 0, 0, 0, 0}, 69, 102},
+ {{28, 110, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 28},
+ {{24, 88, 231, 1, 4, 71, 71, 241, 252, 14, 197, 0, 0, 0, 0, 0}, 89, 154},
+ {{63, 131, 43, 76, 58, 140, 163, 74, 158, 80, 0, 0, 0, 0, 0, 0}, 76, 39},
+ {{56, 28, 147, 149, 98, 93, 216, 216, 203, 156, 0, 0, 0, 0, 0, 0}, 78, 163},
+ {{134, 169, 6, 103, 161, 244, 134, 117, 16, 0, 0, 0, 0, 0, 0, 0}, 68, 42},
+ {{143, 247, 125, 190, 106, 50, 204, 98, 250, 151, 161, 96, 0, 0, 0, 0}, 92, 207},
+ {{235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 25},
+ {{46, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 150},
+ {{171, 35, 128, 117, 74, 29, 199, 67, 109, 176, 0, 0, 0, 0, 0, 0}, 76, 103},
+ {{220, 233, 236, 112, 135, 136, 215, 43, 42, 0, 0, 0, 0, 0, 0, 0}, 71, 155},
+ {{228, 11, 144, 117, 206, 192, 118, 25, 141, 78, 4, 105, 0, 0, 0, 0}, 96, 142},
+ {{195, 67, 194, 229, 14, 53, 129, 7, 30, 208, 38, 100, 182, 59, 0, 0}, 112, 2},
+ {{25, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 59},
+ {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 112},
+ {{26, 203, 217, 152, 16, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 166},
+ {{250, 213, 14, 235, 110, 171, 174, 23, 102, 128, 0, 0, 0, 0, 0, 0}, 73, 62},
+ {{175, 230, 160, 13, 187, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 176},
+ {{92, 155, 156, 93, 191, 73, 28, 82, 187, 129, 57, 5, 16, 0, 0, 0}, 100, 6},
+ {{45, 203, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 26},
+ {{120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 6},
+ {{216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 13},
+ {{135, 215, 0, 71, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 41},
+ {{221, 149, 1, 40, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 135},
+ {{95, 143, 255, 194, 2, 157, 191, 113, 10, 229, 204, 56, 0, 0, 0, 0}, 93, 171},
+ {{202, 212, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 20},
+ {{147, 203, 238, 120, 194, 23, 25, 58, 208, 177, 169, 0, 0, 0, 0, 0}, 89, 119},
+ {{137, 170, 113, 252, 215, 194, 224, 146, 233, 87, 86, 192, 26, 46, 0, 0}, 112, 49},
+ {{224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 141},
+ {{250, 90, 241, 174, 163, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 132},
+ {{66, 190, 202, 144, 122, 86, 22, 103, 107, 164, 57, 54, 228, 128, 0, 0}, 105, 176},
+ {{76, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 186},
+ {{120, 246, 1, 52, 187, 163, 78, 105, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 93},
+ {{137, 242, 136, 71, 98, 10, 53, 97, 160, 85, 132, 127, 185, 222, 0, 0}, 111, 242},
+ {{255, 133, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 163},
+ {{128, 177, 92, 155, 91, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 184},
+ {{45, 120, 186, 192, 240, 199, 178, 95, 32, 0, 0, 0, 0, 0, 0, 0}, 68, 188},
+ {{151, 98, 103, 254, 90, 6, 10, 109, 14, 158, 69, 29, 140, 237, 40, 232}, 126, 193},
+ {{148, 164, 81, 85, 76, 14, 84, 64, 89, 176, 0, 0, 0, 0, 0, 0}, 78, 63},
+ {{145, 187, 165, 136, 88, 30, 107, 191, 205, 120, 119, 216, 158, 123, 64, 0}, 115, 160},
+ {{78, 120, 28, 243, 216, 180, 87, 19, 253, 16, 110, 33, 228, 24, 232, 0}, 117, 251},
+ {{74, 6, 166, 166, 183, 157, 96, 84, 151, 0, 0, 0, 0, 0, 0, 0}, 72, 228},
+ {{89, 96, 4, 221, 214, 253, 58, 49, 9, 0, 0, 0, 0, 0, 0, 0}, 72, 168},
+ {{97, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 194},
+ {{213, 215, 45, 200, 170, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 166},
+ {{5, 14, 92, 0, 28, 245, 130, 202, 32, 40, 207, 77, 166, 170, 246, 64}, 122, 210},
+ {{77, 45, 43, 71, 202, 0, 157, 146, 59, 91, 225, 0, 0, 0, 0, 0}, 89, 254},
+ {{101, 174, 94, 168, 162, 171, 71, 12, 16, 224, 0, 0, 0, 0, 0, 0}, 75, 49},
+ {{58, 17, 187, 194, 87, 73, 215, 103, 180, 12, 40, 66, 0, 0, 0, 0}, 96, 95},
+ {{160, 91, 68, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 193},
+ {{94, 112, 249, 13, 167, 245, 101, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 155},
+ {{236, 194, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 15, 133},
+ {{168, 243, 103, 221, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 10},
+ {{86, 194, 218, 188, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 31},
+ {{232, 3, 134, 67, 63, 196, 86, 14, 170, 243, 77, 134, 187, 140, 72, 18}, 127, 98},
+ {{55, 253, 19, 201, 199, 71, 229, 218, 54, 64, 12, 162, 0, 0, 0, 0}, 96, 22},
+ {{142, 34, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 214},
+ {{213, 16, 208, 50, 100, 33, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 217},
+ {{117, 237, 132, 185, 184, 246, 79, 42, 103, 98, 162, 243, 128, 0, 0, 0}, 98, 102},
+ {{120, 25, 214, 222, 61, 157, 203, 102, 3, 146, 192, 0, 0, 0, 0, 0}, 83, 169},
+ {{222, 46, 254, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 152},
+ {{254, 70, 158, 171, 11, 245, 223, 97, 70, 17, 27, 192, 186, 0, 0, 0}, 103, 214},
+ {{192, 128, 228, 17, 68, 20, 44, 31, 52, 34, 212, 1, 224, 0, 0, 0}, 99, 178},
+ {{237, 229, 203, 8, 121, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 164},
+ {{6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 15},
+ {{71, 197, 251, 122, 138, 232, 12, 241, 116, 240, 0, 0, 0, 0, 0, 0}, 76, 94},
+ {{18, 241, 135, 210, 233, 54, 121, 185, 4, 0, 0, 0, 0, 0, 0, 0}, 70, 239},
+ {{32, 50, 213, 63, 73, 217, 180, 21, 187, 128, 0, 0, 0, 0, 0, 0}, 73, 82},
+ {{203, 166, 233, 73, 92, 182, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54},
+ {{56, 162, 126, 4, 18, 195, 192, 64, 164, 156, 119, 196, 64, 0, 0, 0}, 98, 47},
+ {{120, 87, 81, 136, 180, 179, 68, 148, 243, 38, 80, 0, 0, 0, 0, 0}, 84, 214},
+ {{64, 244, 193, 50, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 215},
+ {{91, 168, 253, 158, 131, 83, 159, 163, 113, 169, 112, 0, 0, 0, 0, 0}, 84, 153},
+ {{159, 103, 102, 132, 111, 46, 18, 77, 36, 15, 137, 33, 177, 31, 243, 192}, 122, 245},
+ {{123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 118},
+ {{67, 81, 226, 190, 7, 79, 71, 250, 155, 245, 44, 81, 215, 213, 171, 224}, 123, 128},
+ {{103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 7},
+ {{246, 44, 168, 200, 198, 238, 52, 196, 125, 115, 0, 0, 0, 0, 0, 0}, 80, 152},
+ {{205, 14, 186, 252, 239, 213, 59, 119, 105, 37, 140, 209, 4, 231, 0, 0}, 114, 248},
+ {{70, 91, 254, 106, 94, 71, 170, 19, 158, 242, 192, 0, 0, 0, 0, 0}, 85, 143},
+ {{250, 86, 233, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 159},
+ {{122, 222, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 11},
+ {{27, 224, 235, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 110},
+ {{239, 100, 224, 3, 46, 127, 150, 251, 204, 120, 228, 64, 0, 0, 0, 0}, 97, 181},
+ {{144, 115, 182, 206, 146, 13, 21, 111, 37, 70, 179, 129, 173, 82, 93, 128}, 121, 4},
+ {{73, 190, 57, 243, 49, 51, 15, 209, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 101},
+ {{18, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 38},
+ {{23, 37, 236, 177, 186, 7, 209, 135, 114, 44, 0, 0, 0, 0, 0, 0}, 78, 57},
+ {{200, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 142},
+ {{181, 255, 153, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 184},
+ {{135, 168, 6, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 91},
+ {{200, 224, 33, 245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 224},
+ {{70, 111, 10, 62, 200, 224, 38, 204, 14, 164, 0, 0, 0, 0, 0, 0}, 78, 114},
+ {{158, 133, 252, 18, 242, 12, 16, 60, 5, 52, 251, 179, 38, 235, 12, 0}, 118, 184},
+ {{2, 23, 116, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 215},
+ {{33, 25, 170, 74, 215, 134, 151, 181, 175, 232, 20, 155, 189, 242, 13, 0}, 120, 167},
+ {{160, 186, 218, 183, 167, 84, 59, 152, 13, 137, 80, 128, 0, 0, 0, 0}, 89, 233},
+ {{32, 141, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 101},
+ {{207, 24, 202, 226, 191, 136, 78, 124, 160, 0, 0, 0, 0, 0, 0, 0}, 67, 139},
+ {{210, 173, 172, 27, 197, 57, 114, 146, 169, 32, 0, 0, 0, 0, 0, 0}, 79, 32},
+ {{95, 113, 12, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 57},
+ {{129, 108, 186, 28, 19, 229, 96, 134, 199, 254, 199, 64, 0, 0, 0, 0}, 91, 151},
+ {{103, 226, 38, 123, 35, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 0},
+ {{41, 117, 43, 35, 208, 115, 73, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 227},
+ {{42, 220, 61, 34, 199, 183, 42, 16, 223, 135, 0, 135, 213, 150, 100, 0}, 118, 124},
+ {{165, 227, 96, 243, 112, 171, 117, 106, 50, 37, 82, 60, 80, 0, 0, 0}, 104, 228},
+ {{158, 60, 111, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64},
+ {{124, 108, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 179},
+ {{232, 68, 132, 159, 156, 103, 95, 190, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 107},
+ {{70, 77, 240, 209, 72, 63, 63, 45, 125, 79, 77, 41, 13, 0, 0, 0}, 104, 206},
+ {{146, 254, 7, 5, 68, 240, 67, 237, 112, 0, 0, 0, 0, 0, 0, 0}, 68, 95},
+ {{162, 223, 117, 27, 2, 156, 94, 170, 157, 114, 162, 50, 0, 0, 0, 0}, 96, 219},
+ {{161, 62, 191, 68, 239, 73, 100, 37, 168, 254, 139, 202, 252, 65, 74, 0}, 119, 138},
+ {{248, 122, 115, 81, 15, 158, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 84},
+ {{8, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 161},
+ {{142, 96, 105, 133, 251, 57, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 25},
+ {{138, 196, 139, 131, 233, 93, 65, 242, 86, 169, 7, 72, 82, 128, 0, 0}, 107, 113},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 46},
+ {{175, 151, 75, 238, 26, 12, 100, 186, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 72},
+ {{82, 205, 211, 176, 170, 79, 57, 153, 161, 218, 32, 48, 0, 0, 0, 0}, 93, 230},
+ {{227, 123, 232, 74, 236, 202, 211, 121, 200, 8, 59, 189, 81, 219, 144, 0}, 117, 142},
+ {{205, 196, 89, 90, 103, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 134},
+ {{63, 145, 23, 127, 102, 216, 49, 36, 168, 164, 59, 133, 18, 146, 0, 0}, 112, 100},
+ {{213, 72, 154, 16, 230, 236, 218, 203, 223, 51, 31, 251, 103, 64, 0, 0}, 109, 45},
+ {{126, 148, 232, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 219},
+ {{160, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 52},
+ {{137, 38, 146, 20, 99, 188, 83, 123, 159, 159, 64, 0, 0, 0, 0, 0}, 83, 240},
+ {{123, 228, 36, 44, 242, 29, 51, 228, 140, 60, 237, 0, 0, 0, 0, 0}, 90, 13},
+ {{163, 169, 25, 89, 190, 114, 165, 158, 140, 210, 192, 0, 0, 0, 0, 0}, 84, 191},
+ {{225, 38, 70, 89, 218, 236, 60, 5, 69, 163, 248, 50, 163, 64, 0, 0}, 106, 95},
+ {{91, 94, 36, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 65},
+ {{209, 238, 110, 0, 2, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 195},
+ {{57, 17, 224, 164, 69, 95, 138, 172, 111, 55, 239, 167, 160, 0, 0, 0}, 103, 21},
+ {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 114},
+ {{102, 96, 223, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 92},
+ {{137, 204, 150, 75, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 237},
+ {{136, 56, 252, 240, 85, 48, 248, 231, 17, 49, 47, 238, 15, 233, 159, 184}, 125, 172},
+ {{57, 31, 132, 123, 234, 255, 37, 82, 167, 204, 37, 158, 128, 0, 0, 0}, 98, 116},
+ {{55, 198, 139, 219, 161, 156, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 54},
+ {{44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 203},
+ {{53, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 74},
+ {{227, 62, 107, 236, 118, 156, 60, 34, 31, 179, 76, 221, 0, 0, 0, 0}, 96, 220},
+ {{105, 40, 240, 216, 91, 61, 19, 128, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 219},
+ {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 179},
+ {{118, 142, 251, 249, 128, 105, 113, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 194},
+ {{101, 70, 196, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 187},
+ {{245, 173, 165, 177, 200, 161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 79},
+ {{0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 87},
+ {{92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 126},
+ {{125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 106},
+ {{56, 59, 35, 82, 101, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 96},
+ {{184, 72, 77, 251, 8, 166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 45},
+ {{143, 74, 132, 205, 218, 247, 30, 160, 145, 199, 138, 12, 89, 220, 0, 0}, 110, 8},
+ {{30, 178, 111, 225, 73, 79, 173, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 226},
+ {{224, 48, 154, 231, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 222},
+ {{123, 144, 170, 143, 85, 169, 130, 245, 214, 0, 0, 0, 0, 0, 0, 0}, 71, 218},
+ {{166, 224, 212, 100, 149, 55, 35, 210, 246, 108, 41, 245, 127, 174, 128, 0}, 116, 59},
+ {{75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 80},
+ {{197, 128, 190, 87, 47, 53, 92, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 177},
+ {{249, 10, 76, 217, 225, 20, 124, 205, 44, 159, 190, 8, 0, 0, 0, 0}, 98, 44},
+ {{180, 226, 0, 167, 137, 232, 174, 120, 113, 95, 22, 184, 0, 0, 0, 0}, 93, 206},
+ {{123, 153, 102, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 64},
+ {{5, 144, 206, 158, 239, 189, 171, 120, 69, 46, 128, 237, 0, 0, 0, 0}, 96, 236},
+ {{159, 235, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 101},
+ {{42, 194, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 49},
+ {{205, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 179},
+ {{19, 65, 141, 20, 127, 77, 70, 205, 151, 115, 157, 23, 118, 128, 0, 0}, 109, 112},
+ {{96, 11, 214, 40, 245, 251, 61, 64, 128, 241, 183, 183, 0, 0, 0, 0}, 96, 31},
+ {{120, 4, 235, 112, 34, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 111},
+ {{110, 127, 207, 76, 100, 148, 130, 206, 249, 2, 104, 0, 0, 0, 0, 0}, 86, 65},
+ {{226, 190, 191, 249, 173, 96, 127, 200, 62, 20, 0, 0, 0, 0, 0, 0}, 78, 222},
+ {{89, 88, 182, 14, 78, 122, 213, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 4},
+ {{167, 94, 163, 227, 28, 111, 117, 103, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 67},
+ {{57, 220, 53, 116, 243, 184, 242, 134, 16, 70, 83, 61, 161, 128, 0, 0}, 109, 197},
+ {{63, 235, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 121},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 167},
+ {{15, 159, 42, 167, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 140},
+ {{216, 252, 113, 40, 239, 46, 172, 48, 103, 250, 82, 179, 136, 64, 0, 0}, 106, 193},
+ {{158, 147, 16, 44, 124, 56, 44, 48, 138, 64, 169, 0, 0, 0, 0, 0}, 90, 47},
+ {{238, 238, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 187},
+ {{63, 159, 177, 162, 106, 212, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 102},
+ {{59, 40, 252, 185, 187, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 237},
+ {{2, 218, 11, 68, 173, 196, 16, 223, 2, 18, 122, 215, 154, 0, 0, 0}, 103, 237},
+ {{3, 9, 206, 73, 108, 196, 183, 119, 141, 162, 10, 180, 115, 32, 0, 0}, 107, 115},
+ {{17, 227, 208, 146, 63, 201, 73, 239, 29, 79, 80, 0, 0, 0, 0, 0}, 84, 217},
+ {{115, 180, 176, 241, 52, 209, 6, 64, 189, 76, 0, 0, 0, 0, 0, 0}, 79, 21},
+ {{191, 88, 98, 245, 91, 46, 137, 254, 170, 80, 11, 55, 212, 28, 128, 0}, 113, 3},
+ {{97, 141, 171, 175, 22, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 62},
+ {{32, 204, 102, 191, 164, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 80},
+ {{29, 133, 210, 252, 124, 66, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 184},
+ {{207, 179, 54, 144, 116, 67, 29, 64, 13, 199, 0, 0, 0, 0, 0, 0}, 80, 197},
+ {{129, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 63},
+ {{50, 152, 249, 143, 174, 234, 240, 48, 158, 255, 80, 105, 0, 0, 0, 0}, 99, 62},
+ {{105, 208, 95, 218, 44, 11, 87, 134, 109, 18, 138, 66, 17, 69, 128, 0}, 114, 231},
+ {{151, 79, 158, 220, 122, 101, 210, 164, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 158},
+ {{236, 97, 87, 155, 254, 137, 122, 208, 168, 201, 194, 118, 224, 0, 0, 0}, 101, 118},
+ {{14, 229, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 237},
+ {{46, 154, 50, 80, 92, 147, 158, 86, 1, 112, 0, 0, 0, 0, 0, 0}, 79, 15},
+ {{88, 131, 21, 84, 62, 86, 7, 110, 142, 251, 242, 110, 194, 175, 247, 0}, 122, 84},
+ {{229, 216, 111, 92, 173, 32, 63, 70, 36, 84, 6, 74, 136, 166, 38, 0}, 119, 205},
+ {{121, 147, 216, 245, 37, 189, 146, 63, 145, 74, 128, 0, 0, 0, 0, 0}, 82, 220},
+ {{44, 26, 254, 11, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 42},
+ {{209, 114, 97, 249, 227, 159, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 144},
+ {{184, 244, 43, 117, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 74},
+ {{60, 81, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 89},
+ {{18, 40, 21, 113, 226, 91, 195, 88, 161, 19, 142, 0, 0, 0, 0, 0}, 88, 77},
+ {{57, 0, 212, 158, 56, 51, 108, 198, 59, 5, 137, 196, 0, 0, 0, 0}, 94, 2},
+ {{168, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 75},
+ {{64, 181, 254, 103, 1, 230, 117, 199, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 18},
+ {{212, 48, 214, 127, 78, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 246},
+ {{155, 185, 236, 163, 204, 49, 129, 120, 183, 47, 10, 243, 65, 92, 192, 0}, 114, 10},
+ {{94, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 207},
+ {{19, 210, 136, 113, 73, 79, 132, 196, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 41},
+ {{24, 203, 246, 242, 241, 223, 150, 237, 213, 202, 11, 128, 0, 0, 0, 0}, 89, 102},
+ {{115, 59, 171, 221, 172, 181, 170, 67, 115, 205, 44, 107, 162, 67, 56, 0}, 118, 118},
+ {{250, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 146},
+ {{203, 240, 28, 158, 182, 12, 86, 182, 142, 47, 143, 57, 239, 0, 0, 0}, 104, 122},
+ {{196, 218, 109, 52, 2, 0, 64, 153, 34, 250, 240, 185, 117, 0, 0, 0}, 107, 6},
+ {{137, 131, 191, 40, 72, 209, 74, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 18},
+ {{236, 126, 167, 37, 185, 20, 34, 207, 76, 0, 0, 0, 0, 0, 0, 0}, 70, 83},
+ {{129, 192, 245, 137, 251, 52, 75, 68, 81, 112, 146, 133, 64, 0, 0, 0}, 99, 90},
+ {{7, 31, 148, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 140},
+ {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 242},
+ {{167, 50, 202, 179, 74, 146, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31},
+ {{44, 188, 186, 250, 229, 71, 28, 118, 35, 253, 245, 191, 199, 18, 0, 0}, 111, 9},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 230},
+ {{156, 163, 215, 175, 71, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 50},
+ {{67, 24, 151, 198, 242, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 41, 34},
+ {{134, 107, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 11},
+ {{35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 8, 71},
+ {{46, 196, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 146},
+ {{82, 172, 8, 26, 154, 34, 125, 188, 5, 149, 159, 44, 78, 222, 236, 176}, 124, 249},
+ {{78, 157, 79, 70, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 143},
+ {{231, 5, 210, 247, 198, 5, 157, 191, 206, 225, 149, 142, 207, 40, 0, 0}, 110, 17},
+ {{38, 254, 235, 199, 191, 60, 43, 159, 190, 243, 203, 185, 184, 218, 132, 0}, 119, 60},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 1, 162},
+ {{95, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 5},
+ {{17, 128, 244, 178, 160, 78, 83, 92, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 139},
+ {{18, 102, 62, 251, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 8},
+ {{30, 75, 108, 40, 231, 166, 233, 220, 163, 176, 252, 210, 60, 30, 128, 0}, 114, 246},
+ {{18, 3, 207, 64, 25, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 171},
+ {{52, 83, 235, 61, 164, 236, 83, 173, 143, 105, 14, 0, 0, 0, 0, 0}, 88, 206},
+ {{166, 175, 186, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 163},
+ {{221, 154, 82, 98, 41, 126, 85, 52, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 166},
+ {{94, 84, 182, 120, 204, 232, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 128},
+ {{27, 174, 227, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 59},
+ {{218, 12, 4, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 179},
+ {{9, 5, 190, 195, 60, 216, 80, 150, 128, 117, 86, 128, 128, 112, 98, 208}, 124, 87},
+ {{7, 226, 104, 112, 212, 9, 172, 124, 209, 121, 170, 229, 44, 178, 128, 0}, 114, 29},
+ {{47, 71, 174, 76, 52, 83, 23, 18, 106, 48, 56, 32, 0, 0, 0, 0}, 91, 184},
+ {{51, 168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 45},
+ {{28, 182, 167, 124, 28, 22, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 144},
+ {{34, 61, 14, 51, 253, 17, 19, 170, 49, 206, 188, 207, 247, 167, 192, 0}, 114, 119},
+ {{2, 235, 18, 14, 195, 66, 237, 30, 0, 0, 0, 0, 0, 0, 0, 0}, 64, 113},
+ {{51, 182, 142, 133, 127, 96, 159, 132, 99, 161, 64, 0, 0, 0, 0, 0}, 82, 50},
+ {{170, 145, 230, 123, 215, 189, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 207},
+ {{151, 166, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 3},
+ {{16, 141, 196, 129, 132, 207, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 13},
+ {{205, 25, 184, 191, 201, 206, 109, 224, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 42},
+ {{48, 114, 33, 103, 247, 255, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 31},
+ {{179, 156, 119, 146, 125, 21, 42, 146, 237, 213, 191, 132, 0, 0, 0, 0}, 94, 30},
+ {{179, 129, 186, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 94},
+ {{17, 179, 217, 188, 128, 212, 4, 4, 152, 0, 0, 0, 0, 0, 0, 0}, 71, 190},
+ {{132, 63, 74, 89, 209, 64, 63, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 238},
+ {{16, 50, 248, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 20},
+ {{189, 96, 58, 53, 191, 235, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 84},
+ {{111, 98, 6, 65, 35, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 108},
+ {{118, 223, 83, 220, 110, 122, 23, 112, 185, 155, 73, 0, 0, 0, 0, 0}, 89, 136},
+ {{173, 191, 150, 197, 204, 35, 169, 79, 31, 214, 251, 240, 0, 0, 0, 0}, 93, 196},
+ {{26, 76, 129, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 67},
+ {{231, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 12, 104},
+ {{93, 172, 223, 252, 203, 0, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 15},
+ {{53, 142, 203, 124, 104, 51, 241, 12, 161, 17, 101, 245, 120, 110, 192, 199}, 128, 237},
+ {{9, 77, 120, 197, 193, 10, 237, 174, 233, 2, 165, 11, 229, 47, 144, 0}, 116, 224},
+ {{99, 161, 189, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 179},
+ {{18, 8, 76, 66, 2, 185, 206, 132, 224, 0, 0, 0, 0, 0, 0, 0}, 67, 84},
+ {{169, 53, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 65},
+ {{136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 178},
+ {{131, 162, 144, 124, 12, 98, 242, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 154},
+ {{75, 50, 129, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 27, 106},
+ {{212, 183, 40, 225, 152, 136, 174, 91, 0, 0, 0, 0, 0, 0, 0, 0}, 67, 125},
+ {{158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 118},
+ {{7, 48, 132, 149, 169, 212, 198, 137, 202, 0, 0, 0, 0, 0, 0, 0}, 73, 52},
+ {{173, 195, 129, 163, 141, 249, 40, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 173},
+ {{109, 79, 75, 219, 205, 182, 22, 245, 223, 17, 146, 78, 109, 119, 128, 0}, 113, 8},
+ {{174, 195, 24, 182, 215, 198, 214, 86, 34, 128, 0, 0, 0, 0, 0, 0}, 74, 211},
+ {{22, 40, 51, 109, 70, 91, 152, 56, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 253},
+ {{169, 115, 246, 126, 65, 118, 219, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 47},
+ {{154, 37, 70, 124, 107, 123, 232, 241, 164, 142, 71, 226, 182, 126, 0, 0}, 112, 73},
+ {{6, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 192},
+ {{216, 167, 158, 158, 222, 19, 96, 28, 40, 6, 70, 12, 147, 27, 85, 240}, 128, 55},
+ {{72, 222, 52, 69, 69, 206, 163, 106, 235, 206, 80, 128, 0, 0, 0, 0}, 94, 147},
+ {{150, 112, 106, 56, 15, 243, 154, 97, 134, 110, 160, 20, 183, 144, 234, 8}, 125, 86},
+ {{58, 186, 106, 58, 124, 171, 53, 85, 33, 100, 64, 0, 0, 0, 0, 0}, 82, 16},
+ {{7, 195, 22, 31, 62, 217, 209, 46, 90, 49, 189, 50, 168, 126, 0, 0}, 111, 167},
+ {{92, 44, 159, 198, 185, 94, 231, 177, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 148},
+ {{169, 108, 190, 162, 23, 39, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 66},
+ {{161, 5, 3, 11, 158, 157, 166, 212, 246, 22, 140, 101, 92, 0, 0, 0}, 104, 70},
+ {{71, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 166},
+ {{48, 136, 194, 145, 57, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 109},
+ {{144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 226},
+ {{223, 209, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 8},
+ {{154, 79, 170, 9, 43, 139, 249, 176, 186, 72, 216, 0, 0, 0, 0, 0}, 85, 218},
+ {{1, 8, 123, 205, 167, 134, 128, 102, 10, 72, 0, 0, 0, 0, 0, 0}, 78, 54},
+ {{31, 105, 48, 77, 103, 187, 99, 67, 96, 0, 0, 0, 0, 0, 0, 0}, 67, 48},
+ {{14, 73, 54, 76, 232, 35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 244},
+ {{14, 109, 251, 190, 36, 253, 99, 120, 94, 64, 0, 0, 0, 0, 0, 0}, 74, 50},
+ {{122, 170, 9, 134, 124, 91, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 173},
+ {{246, 10, 85, 88, 82, 217, 95, 56, 216, 203, 160, 0, 0, 0, 0, 0}, 84, 245},
+ {{77, 100, 114, 207, 150, 177, 69, 134, 74, 131, 147, 117, 177, 64, 210, 128}, 121, 54},
+ {{171, 123, 22, 138, 132, 229, 250, 81, 186, 227, 146, 27, 170, 205, 128, 0}, 113, 86},
+ {{128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 115},
+ {{12, 35, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 144},
+ {{255, 124, 179, 165, 169, 250, 66, 171, 223, 125, 247, 0, 0, 0, 0, 0}, 89, 171},
+ {{244, 235, 211, 10, 251, 255, 206, 6, 198, 12, 50, 136, 0, 0, 0, 0}, 93, 231},
+ {{221, 77, 237, 41, 50, 33, 103, 24, 25, 127, 208, 0, 0, 0, 0, 0}, 88, 34},
+ {{216, 69, 47, 53, 117, 24, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 225},
+ {{180, 87, 25, 236, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 174},
+ {{110, 32, 24, 34, 116, 133, 245, 128, 123, 95, 125, 122, 100, 129, 128, 0}, 113, 37},
+ {{27, 117, 179, 112, 133, 137, 110, 193, 246, 201, 219, 65, 56, 234, 106, 128}, 121, 39},
+ {{186, 117, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 59},
+ {{243, 119, 54, 16, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 96},
+ {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 147},
+ {{78, 48, 117, 200, 245, 118, 115, 240, 170, 125, 84, 103, 33, 168, 0, 0}, 110, 56},
+ {{201, 253, 184, 254, 143, 81, 95, 42, 243, 147, 96, 145, 23, 26, 0, 0}, 111, 234},
+ {{41, 215, 84, 136, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 199},
+ {{91, 244, 137, 184, 231, 95, 135, 10, 184, 0, 0, 0, 0, 0, 0, 0}, 69, 191},
+ {{113, 31, 181, 245, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 235},
+ {{181, 216, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 45},
+ {{87, 26, 119, 229, 97, 255, 9, 43, 32, 0, 0, 0, 0, 0, 0, 0}, 67, 164},
+ {{205, 112, 67, 163, 196, 148, 5, 105, 8, 138, 144, 3, 171, 213, 159, 128}, 121, 130},
+ {{136, 27, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 166},
+ {{2, 175, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 140},
+ {{222, 131, 85, 218, 16, 229, 44, 230, 243, 76, 250, 139, 1, 203, 108, 0}, 118, 47},
+ {{101, 180, 77, 142, 194, 73, 196, 246, 107, 100, 194, 72, 204, 124, 0, 0}, 111, 148},
+ {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 103},
+ {{46, 62, 191, 130, 110, 128, 235, 62, 68, 39, 58, 152, 207, 204, 96, 0}, 116, 94},
+ {{111, 11, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 85},
+ {{58, 43, 14, 93, 102, 210, 117, 208, 222, 171, 130, 41, 16, 16, 0, 0}, 109, 250},
+ {{141, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 153},
+ {{170, 153, 160, 170, 144, 235, 122, 8, 106, 34, 24, 32, 102, 57, 12, 168}, 125, 182},
+ {{34, 113, 163, 107, 61, 177, 39, 172, 242, 2, 130, 0, 0, 0, 0, 0}, 94, 23},
+ {{222, 191, 239, 110, 162, 191, 195, 181, 80, 50, 85, 240, 88, 32, 0, 0}, 108, 38},
+ {{179, 82, 253, 151, 212, 0, 72, 253, 175, 22, 34, 78, 53, 32, 0, 0}, 110, 121},
+ {{10, 162, 20, 46, 164, 64, 88, 1, 202, 204, 124, 0, 0, 0, 0, 0}, 87, 146},
+ {{210, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 138},
+ {{183, 200, 1, 2, 51, 6, 66, 142, 20, 77, 48, 244, 0, 0, 0, 0}, 94, 149},
+ {{29, 20, 224, 57, 204, 161, 131, 254, 53, 133, 163, 0, 0, 0, 0, 0}, 88, 232},
+ {{75, 58, 170, 52, 146, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 255},
+ {{92, 21, 1, 113, 185, 88, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 148},
+ {{103, 180, 222, 187, 129, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 117},
+ {{32, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 237},
+ {{7, 60, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 113},
+ {{167, 122, 205, 185, 21, 199, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 162},
+ {{21, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 225},
+ {{92, 159, 167, 169, 136, 176, 95, 255, 87, 137, 112, 16, 0, 0, 0, 0}, 92, 210},
+ {{84, 120, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 34},
+ {{126, 5, 126, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 224},
+ {{4, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 143},
+ {{239, 154, 181, 182, 189, 211, 244, 53, 144, 0, 0, 0, 0, 0, 0, 0}, 68, 216},
+ {{254, 188, 139, 167, 135, 47, 147, 239, 187, 106, 228, 156, 234, 234, 102, 0}, 120, 239},
+ {{225, 168, 138, 92, 193, 255, 47, 233, 11, 154, 205, 86, 209, 88, 0, 0}, 111, 54},
+ {{223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 35},
+ {{235, 252, 115, 10, 151, 104, 193, 207, 38, 228, 229, 245, 42, 13, 108, 0}, 119, 230},
+ {{1, 137, 53, 36, 210, 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 234},
+ {{149, 182, 72, 197, 92, 229, 9, 10, 220, 128, 72, 19, 4, 58, 192, 0}, 115, 70},
+ {{105, 73, 57, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 246},
+ {{189, 61, 230, 24, 235, 82, 58, 102, 97, 111, 121, 252, 156, 94, 191, 166}, 127, 217},
+ {{193, 108, 231, 86, 140, 14, 192, 4, 135, 80, 129, 166, 158, 61, 230, 20}, 128, 201},
+ {{110, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 17, 49},
+ {{3, 102, 36, 231, 15, 242, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 2},
+ {{81, 189, 220, 168, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 64},
+ {{168, 75, 133, 180, 91, 165, 77, 232, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 239},
+ {{106, 179, 186, 109, 81, 234, 233, 167, 101, 160, 90, 102, 174, 234, 208, 0}, 116, 47},
+ {{46, 105, 234, 21, 23, 247, 169, 33, 47, 5, 0, 0, 0, 0, 0, 0}, 80, 43},
+ {{152, 144, 100, 142, 129, 23, 227, 50, 67, 81, 249, 116, 0, 0, 0, 0}, 94, 17},
+ {{109, 74, 145, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 5},
+ {{100, 243, 22, 230, 38, 44, 128, 86, 132, 57, 0, 0, 0, 0, 0, 0}, 81, 240},
+ {{153, 251, 115, 65, 104, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 197},
+ {{43, 113, 60, 224, 36, 20, 42, 161, 24, 223, 192, 0, 0, 0, 0, 0}, 84, 192},
+ {{61, 77, 121, 176, 138, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 160},
+ {{119, 194, 146, 49, 59, 242, 25, 220, 122, 104, 80, 0, 0, 0, 0, 0}, 84, 199},
+ {{254, 162, 155, 47, 187, 3, 1, 114, 142, 191, 152, 44, 144, 26, 202, 0}, 127, 217},
+ {{176, 1, 114, 42, 191, 145, 43, 1, 141, 18, 64, 0, 0, 0, 0, 0}, 83, 75},
+ {{170, 244, 67, 132, 145, 163, 76, 213, 85, 237, 248, 22, 207, 64, 0, 0}, 106, 222},
+ {{102, 190, 58, 32, 75, 15, 89, 163, 64, 7, 168, 0, 0, 0, 0, 0}, 85, 39},
+ {{124, 170, 35, 47, 152, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 9},
+ {{192, 221, 20, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 217},
+ {{208, 178, 136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 142},
+ {{188, 68, 77, 30, 68, 153, 102, 180, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 18},
+ {{114, 178, 121, 188, 205, 233, 35, 77, 34, 197, 158, 174, 101, 0, 0, 0}, 104, 180},
+ {{195, 98, 67, 12, 13, 43, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 205},
+ {{146, 190, 42, 222, 14, 54, 28, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 251},
+ {{185, 202, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 178},
+ {{138, 30, 129, 95, 224, 161, 120, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 198},
+ {{69, 181, 5, 227, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 84},
+ {{90, 180, 0, 164, 227, 75, 174, 119, 128, 0, 0, 0, 0, 0, 0, 0}, 66, 128},
+ {{20, 60, 58, 119, 245, 177, 162, 186, 13, 112, 211, 239, 128, 0, 0, 0}, 97, 75},
+ {{158, 124, 157, 25, 230, 139, 51, 212, 76, 109, 236, 210, 48, 0, 0, 0}, 101, 192},
+ {{125, 108, 242, 36, 94, 13, 36, 106, 90, 51, 83, 217, 131, 151, 0, 0}, 114, 60},
+ {{222, 218, 162, 158, 15, 53, 191, 178, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 169},
+ {{104, 202, 127, 109, 73, 16, 17, 12, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 10},
+ {{172, 171, 246, 26, 176, 34, 22, 152, 246, 56, 173, 120, 105, 60, 92, 0}, 118, 64},
+ {{190, 22, 171, 206, 109, 186, 179, 128, 253, 182, 108, 212, 220, 167, 171, 180}, 127, 182},
+ {{119, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 29},
+ {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 39},
+ {{170, 144, 64, 2, 107, 166, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 93},
+ {{234, 9, 96, 20, 156, 157, 1, 34, 88, 0, 0, 0, 0, 0, 0, 0}, 75, 228},
+ {{147, 237, 16, 120, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 236},
+ {{182, 189, 162, 158, 223, 90, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 190},
+ {{116, 148, 142, 240, 10, 253, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 217},
+ {{211, 73, 140, 69, 252, 27, 75, 46, 37, 6, 147, 32, 0, 0, 0, 0}, 93, 74},
+ {{148, 61, 120, 49, 220, 65, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 180},
+ {{172, 35, 202, 180, 129, 75, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 91},
+ {{215, 109, 147, 157, 32, 28, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 230},
+ {{151, 26, 182, 112, 205, 220, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 175},
+ {{73, 91, 93, 61, 196, 3, 66, 26, 149, 96, 0, 0, 0, 0, 0, 0}, 75, 171},
+ {{203, 163, 52, 247, 28, 119, 56, 223, 138, 70, 174, 97, 77, 59, 46, 0}, 120, 202},
+ {{251, 50, 228, 178, 202, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 113},
+ {{217, 159, 164, 199, 14, 237, 170, 184, 100, 231, 92, 222, 0, 0, 0, 0}, 96, 187},
+ {{16, 161, 85, 193, 202, 21, 3, 155, 63, 116, 124, 203, 34, 13, 215, 0}, 120, 38},
+ {{111, 52, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 35},
+ {{69, 12, 116, 151, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 115},
+ {{187, 60, 97, 40, 112, 101, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 18},
+ {{230, 194, 136, 255, 206, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 34},
+ {{179, 239, 170, 107, 3, 13, 212, 67, 177, 69, 8, 0, 0, 0, 0, 0}, 87, 75},
+ {{11, 58, 130, 89, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 232},
+ {{217, 178, 43, 203, 234, 20, 234, 186, 157, 88, 146, 192, 0, 0, 0, 0}, 91, 154},
+ {{6, 180, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 195},
+ {{157, 154, 218, 158, 39, 224, 103, 230, 164, 0, 0, 0, 0, 0, 0, 0}, 70, 122},
+ {{225, 10, 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 97},
+ {{16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 220},
+ {{166, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 80},
+ {{29, 190, 131, 215, 232, 246, 41, 226, 52, 192, 0, 0, 0, 0, 0, 0}, 77, 133},
+ {{138, 74, 163, 93, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 38, 93},
+ {{229, 64, 97, 41, 28, 243, 249, 185, 97, 35, 49, 27, 175, 24, 0, 0}, 110, 176},
+ {{6, 73, 94, 160, 186, 216, 84, 117, 233, 169, 146, 234, 0, 0, 0, 0}, 95, 68},
+ {{163, 40, 242, 81, 224, 35, 72, 194, 176, 78, 224, 174, 12, 0, 0, 0}, 103, 247},
+ {{2, 205, 40, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 240},
+ {{174, 225, 240, 160, 212, 8, 246, 67, 36, 0, 0, 0, 0, 0, 0, 0}, 74, 83},
+ {{5, 117, 182, 141, 166, 249, 196, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 132},
+ {{46, 152, 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 217},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 214},
+ {{233, 202, 159, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 193},
+ {{172, 54, 159, 5, 14, 245, 106, 182, 2, 0, 0, 0, 0, 0, 0, 0}, 71, 61},
+ {{241, 222, 251, 114, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 65},
+ {{31, 243, 190, 4, 207, 198, 249, 59, 167, 127, 93, 64, 0, 0, 0, 0}, 91, 108},
+ {{201, 35, 222, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 244},
+ {{187, 105, 13, 114, 238, 197, 145, 23, 169, 116, 91, 28, 0, 0, 0, 0}, 95, 194},
+ {{251, 251, 121, 168, 152, 178, 147, 188, 229, 123, 154, 242, 190, 165, 173, 48}, 124, 82},
+ {{66, 187, 191, 164, 31, 196, 40, 186, 148, 115, 134, 57, 222, 254, 48, 0}, 116, 45},
+ {{209, 17, 111, 41, 154, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 224},
+ {{40, 245, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 17},
+ {{72, 121, 151, 83, 170, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 133},
+ {{171, 172, 101, 238, 201, 148, 23, 81, 4, 11, 64, 0, 0, 0, 0, 0}, 85, 125},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 42},
+ {{20, 46, 27, 93, 195, 184, 6, 162, 109, 225, 22, 152, 0, 0, 0, 0}, 96, 140},
+ {{243, 122, 30, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 91},
+ {{89, 250, 80, 72, 148, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 48, 92},
+ {{187, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 125},
+ {{172, 160, 143, 114, 128, 239, 174, 133, 176, 154, 159, 134, 10, 0, 0, 0}, 106, 249},
+ {{254, 202, 113, 112, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 202},
+ {{80, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 107},
+ {{222, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 13, 124},
+ {{219, 138, 253, 12, 188, 197, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 57},
+ {{124, 41, 173, 8, 202, 192, 61, 254, 174, 48, 239, 112, 0, 0, 0, 0}, 92, 181},
+ {{195, 236, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 107},
+ {{83, 82, 42, 244, 136, 191, 197, 81, 91, 154, 216, 85, 29, 150, 198, 22}, 128, 101},
+ {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 102},
+ {{44, 30, 219, 248, 214, 88, 225, 132, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 136},
+ {{41, 171, 206, 178, 195, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 114},
+ {{159, 15, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 215},
+ {{42, 188, 37, 174, 86, 40, 4, 84, 174, 216, 0, 0, 0, 0, 0, 0}, 79, 249},
+ {{185, 227, 85, 177, 219, 95, 250, 227, 69, 154, 118, 0, 0, 0, 0, 0}, 88, 29},
+ {{22, 185, 238, 100, 25, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 44, 71},
+ {{122, 149, 117, 77, 88, 250, 187, 203, 136, 22, 85, 42, 105, 234, 79, 8}, 127, 112},
+ {{93, 152, 229, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 31, 72},
+ {{129, 37, 165, 167, 241, 24, 37, 40, 2, 128, 0, 0, 0, 0, 0, 0}, 73, 155},
+ {{30, 202, 177, 3, 253, 202, 164, 248, 0, 0, 0, 0, 0, 0, 0, 0}, 61, 66},
+ {{176, 25, 220, 120, 194, 228, 10, 45, 225, 142, 192, 96, 0, 0, 0, 0}, 91, 77},
+ {{96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 109},
+ {{82, 56, 12, 204, 61, 45, 147, 240, 221, 0, 0, 0, 0, 0, 0, 0}, 72, 37},
+ {{242, 38, 240, 41, 140, 75, 250, 37, 175, 115, 97, 224, 0, 0, 0, 0}, 91, 56},
+ {{251, 192, 23, 90, 135, 56, 252, 56, 79, 219, 80, 167, 22, 0, 0, 0}, 103, 5},
+ {{62, 128, 139, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 15},
+ {{214, 1, 84, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 183},
+ {{207, 90, 237, 137, 171, 140, 227, 88, 250, 26, 197, 162, 163, 0, 0, 0}, 105, 171},
+ {{196, 151, 235, 232, 114, 248, 1, 207, 193, 184, 186, 71, 157, 0, 0, 0}, 112, 202},
+ {{152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 136},
+ {{9, 174, 211, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 37, 107},
+ {{89, 150, 95, 28, 209, 13, 125, 159, 254, 244, 110, 0, 0, 0, 0, 0}, 87, 193},
+ {{23, 28, 202, 10, 90, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 4},
+ {{48, 25, 180, 9, 84, 236, 6, 144, 30, 198, 41, 56, 0, 0, 0, 0}, 96, 68},
+ {{252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 7, 40},
+ {{20, 165, 57, 130, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 255},
+ {{167, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 108},
+ {{91, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 219},
+ {{24, 46, 9, 4, 170, 150, 56, 130, 127, 120, 118, 104, 168, 48, 0, 0}, 108, 12},
+ {{156, 60, 245, 247, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 84},
+ {{148, 104, 187, 174, 129, 28, 127, 162, 92, 222, 52, 18, 0, 0, 0, 0}, 96, 33},
+ {{38, 253, 182, 153, 233, 194, 159, 41, 94, 193, 254, 160, 0, 0, 0, 0}, 91, 199},
+ {{156, 77, 105, 235, 145, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 52},
+ {{100, 211, 238, 147, 65, 222, 99, 73, 252, 113, 46, 113, 52, 136, 0, 0}, 113, 184},
+ {{13, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 124},
+ {{29, 240, 141, 230, 78, 237, 25, 135, 131, 6, 65, 77, 77, 248, 0, 0}, 109, 128},
+ {{15, 192, 109, 31, 149, 221, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 255},
+ {{80, 185, 170, 71, 41, 58, 158, 106, 253, 7, 2, 184, 173, 0, 0, 0}, 105, 146},
+ {{16, 229, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 24, 172},
+ {{169, 2, 153, 9, 169, 203, 245, 154, 184, 0, 0, 0, 0, 0, 0, 0}, 70, 116},
+ {{144, 135, 239, 164, 142, 187, 64, 109, 0, 0, 0, 0, 0, 0, 0, 0}, 66, 189},
+ {{170, 78, 252, 227, 242, 199, 130, 251, 200, 0, 0, 0, 0, 0, 0, 0}, 70, 10},
+ {{232, 18, 15, 126, 166, 126, 58, 25, 209, 62, 76, 79, 0, 0, 0, 0}, 98, 184},
+ {{170, 82, 72, 53, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 33, 98},
+ {{152, 100, 37, 122, 242, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 37},
+ {{174, 231, 230, 33, 71, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 174},
+ {{74, 225, 252, 153, 202, 8, 162, 39, 64, 0, 0, 0, 0, 0, 0, 0}, 67, 251},
+ {{167, 186, 101, 187, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 115},
+ {{83, 7, 21, 122, 243, 67, 171, 146, 145, 160, 168, 103, 223, 64, 0, 0}, 107, 252},
+ {{83, 132, 219, 86, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 176},
+ {{22, 113, 72, 102, 73, 16, 236, 57, 197, 122, 31, 0, 0, 0, 0, 0}, 91, 155},
+ {{250, 59, 64, 35, 72, 112, 159, 85, 200, 5, 193, 39, 152, 185, 148, 16}, 124, 36},
+ {{220, 21, 48, 164, 224, 121, 17, 69, 10, 118, 106, 0, 0, 0, 0, 0}, 88, 202},
+ {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 5, 208},
+ {{247, 64, 83, 125, 195, 225, 50, 76, 18, 104, 0, 0, 0, 0, 0, 0}, 77, 158},
+ {{78, 91, 31, 202, 189, 25, 13, 133, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 136},
+ {{105, 197, 26, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 191},
+ {{14, 31, 154, 242, 241, 231, 55, 151, 223, 56, 134, 255, 113, 206, 69, 0}, 120, 126},
+ {{247, 193, 58, 176, 16, 71, 31, 120, 213, 104, 231, 83, 26, 118, 91, 135}, 128, 139},
+ {{136, 32, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 25, 216},
+ {{100, 238, 112, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 29, 93},
+ {{80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 196},
+ {{233, 224, 254, 57, 33, 205, 140, 217, 181, 72, 0, 0, 0, 0, 0, 0}, 81, 119},
+ {{107, 75, 65, 158, 128, 142, 191, 188, 188, 240, 148, 243, 116, 0, 0, 0}, 104, 93},
+ {{39, 70, 120, 114, 69, 237, 95, 48, 233, 176, 91, 154, 0, 0, 0, 0}, 96, 183},
+ {{10, 61, 43, 101, 64, 102, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 207},
+ {{151, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 102},
+ {{210, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 19, 36},
+ {{52, 222, 249, 31, 108, 137, 199, 1, 242, 173, 184, 144, 0, 0, 0, 0}, 93, 41},
+ {{123, 111, 88, 192, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 70},
+ {{180, 82, 188, 125, 140, 8, 196, 74, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 218},
+ {{77, 158, 34, 101, 196, 102, 56, 220, 42, 143, 181, 187, 240, 64, 161, 0}, 120, 226},
+ {{88, 220, 222, 38, 23, 108, 5, 148, 185, 110, 20, 14, 67, 61, 0, 0}, 114, 25},
+ {{90, 65, 220, 165, 197, 133, 110, 92, 228, 19, 2, 17, 0, 0, 0, 0}, 98, 6},
+ {{35, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 26},
+ {{103, 123, 49, 209, 228, 229, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 149},
+ {{50, 244, 58, 191, 95, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 46, 127},
+ {{140, 169, 75, 77, 78, 86, 40, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 62, 144},
+ {{99, 176, 175, 83, 114, 50, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 56, 213},
+ {{19, 208, 211, 76, 85, 176, 247, 64, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 115},
+ {{153, 28, 188, 113, 211, 116, 7, 178, 136, 205, 96, 0, 0, 0, 0, 0}, 83, 146},
+ {{160, 180, 220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 58},
+ {{234, 6, 112, 19, 61, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 222},
+ {{97, 110, 34, 117, 149, 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 16},
+ {{99, 173, 119, 73, 250, 30, 144, 30, 128, 0, 0, 0, 0, 0, 0, 0}, 65, 169},
+ {{169, 134, 111, 89, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 175},
+ {{134, 80, 227, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 3},
+ {{231, 243, 35, 80, 75, 207, 128, 137, 54, 170, 71, 238, 0, 0, 0, 0}, 96, 2},
+ {{189, 190, 121, 135, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 193},
+ {{143, 155, 216, 193, 239, 205, 204, 153, 143, 236, 69, 23, 200, 211, 0, 0}, 118, 151},
+ {{32, 1, 115, 244, 33, 219, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 182},
+ {{220, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 148},
+ {{206, 87, 135, 235, 116, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 42, 53},
+ {{152, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 11, 87},
+ {{58, 146, 188, 233, 230, 236, 192, 214, 168, 128, 0, 0, 0, 0, 0, 0}, 73, 235},
+ {{84, 220, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 51},
+ {{106, 145, 142, 42, 186, 186, 58, 1, 48, 98, 165, 131, 48, 156, 192, 0}, 116, 11},
+ {{53, 219, 120, 242, 166, 214, 81, 130, 64, 0, 0, 0, 0, 0, 0, 0}, 68, 28},
+ {{240, 120, 76, 163, 32, 197, 181, 251, 98, 220, 29, 226, 0, 0, 0, 0}, 96, 73},
+ {{234, 197, 12, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 216},
+ {{191, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 16, 99},
+ {{200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 35},
+ {{29, 129, 47, 83, 19, 75, 158, 1, 28, 24, 26, 147, 82, 119, 140, 100}, 127, 195},
+ {{241, 174, 26, 53, 152, 112, 200, 134, 84, 187, 177, 176, 42, 64, 0, 0}, 108, 176},
+ {{77, 171, 145, 48, 195, 84, 190, 36, 122, 199, 18, 0, 0, 0, 0, 0}, 87, 217},
+ {{105, 104, 135, 53, 226, 118, 238, 169, 9, 253, 132, 162, 217, 123, 191, 96}, 126, 244},
+ {{160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 125},
+ {{41, 85, 143, 128, 91, 137, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 219},
+ {{116, 110, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 165},
+ {{75, 213, 44, 16, 43, 157, 34, 171, 98, 117, 109, 151, 5, 60, 224, 0}, 117, 6},
+ {{229, 23, 116, 61, 80, 139, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 53, 47},
+ {{83, 123, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 23, 73},
+ {{151, 243, 45, 217, 216, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 47, 98},
+ {{171, 184, 110, 211, 237, 114, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 52, 21},
+ {{7, 246, 199, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 32, 142},
+ {{103, 47, 70, 17, 31, 232, 44, 75, 145, 155, 100, 216, 0, 0, 0, 0}, 93, 34},
+ {{65, 170, 169, 100, 167, 147, 142, 251, 20, 64, 0, 0, 0, 0, 0, 0}, 74, 41},
+ {{235, 6, 229, 248, 151, 137, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 55, 80},
+ {{156, 39, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 22, 11},
+ {{92, 188, 82, 192, 142, 249, 190, 128, 0, 0, 0, 0, 0, 0, 0, 0}, 58, 254},
+ {{253, 218, 181, 46, 134, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 45, 95},
+ {{189, 19, 31, 244, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 40, 8},
+ {{30, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 14, 212},
+ {{81, 226, 13, 173, 79, 123, 223, 124, 108, 80, 83, 238, 0, 0, 0, 0}, 95, 217},
+ {{126, 211, 206, 82, 147, 215, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 15},
+ {{42, 229, 135, 197, 196, 243, 94, 181, 133, 34, 16, 0, 0, 0, 0, 0}, 84, 66},
+ {{68, 210, 158, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 122},
+ {{183, 63, 223, 94, 81, 41, 203, 20, 236, 212, 220, 199, 0, 0, 0, 0}, 97, 12},
+ {{131, 146, 2, 125, 174, 43, 231, 20, 194, 0, 0, 0, 0, 0, 0, 0}, 71, 171},
+ {{31, 180, 246, 158, 28, 192, 236, 39, 237, 55, 74, 195, 171, 192, 0, 0}, 106, 42},
+ {{179, 10, 70, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 28, 194},
+ {{147, 51, 85, 185, 234, 209, 236, 87, 147, 17, 7, 68, 148, 32, 0, 0}, 107, 237},
+ {{177, 178, 6, 40, 46, 166, 87, 198, 214, 234, 23, 224, 0, 0, 0, 0}, 93, 151},
+ {{201, 53, 40, 20, 49, 4, 38, 139, 133, 217, 214, 134, 89, 200, 0, 0}, 109, 238},
+ {{4, 26, 181, 37, 206, 129, 233, 32, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 128},
+ {{81, 58, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 227},
+ {{18, 238, 250, 161, 57, 246, 208, 118, 14, 76, 73, 25, 65, 22, 152, 120}, 127, 138},
+ {{31, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 60},
+ {{115, 195, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 18, 148},
+ {{116, 22, 75, 33, 16, 129, 35, 124, 10, 112, 31, 213, 181, 108, 177, 46}, 128, 129},
+ {{117, 214, 20, 80, 83, 51, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 202},
+ {{120, 75, 124, 149, 120, 123, 242, 151, 181, 164, 128, 0, 0, 0, 0, 0}, 81, 88},
+ {{87, 238, 168, 62, 88, 166, 52, 104, 219, 169, 93, 128, 0, 0, 0, 0}, 90, 3},
+ {{237, 44, 224, 146, 52, 85, 245, 192, 65, 137, 37, 95, 156, 176, 0, 0}, 108, 243},
+ {{214, 241, 51, 63, 73, 61, 193, 165, 23, 108, 0, 0, 0, 0, 0, 0}, 80, 95},
+ {{87, 242, 21, 157, 45, 188, 36, 62, 66, 243, 64, 0, 0, 0, 0, 0}, 87, 255},
+ {{0, 97, 220, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 48},
+ {{227, 206, 189, 31, 222, 8, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 50, 38},
+ {{174, 27, 0, 16, 13, 150, 33, 122, 154, 59, 236, 35, 248, 178, 64, 0}, 115, 20},
+ {{39, 20, 125, 69, 252, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 41},
+ {{141, 232, 1, 12, 125, 229, 168, 14, 125, 116, 180, 0, 0, 0, 0, 0}, 92, 133},
+ {{93, 238, 40, 228, 254, 203, 251, 6, 60, 82, 243, 242, 0, 0, 0, 0}, 95, 189},
+ {{44, 115, 200, 17, 146, 223, 115, 253, 126, 206, 152, 90, 0, 0, 0, 0}, 95, 151},
+ {{213, 58, 235, 255, 6, 163, 61, 10, 224, 0, 0, 0, 0, 0, 0, 0}, 68, 100},
+ {{25, 86, 139, 116, 190, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 49, 118},
+ {{113, 40, 65, 141, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 34, 164},
+ {{149, 205, 200, 186, 19, 126, 215, 199, 94, 37, 100, 32, 128, 0, 0, 0}, 98, 71},
+ {{39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 251},
+ {{81, 87, 80, 173, 163, 166, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 51},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 185},
+ {{140, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 144},
+ {{6, 42, 1, 178, 250, 53, 186, 178, 114, 121, 192, 0, 0, 0, 0, 0}, 84, 51},
+ {{2, 17, 234, 51, 169, 5, 219, 149, 245, 237, 4, 0, 0, 0, 0, 0}, 87, 32},
+ {{112, 187, 173, 17, 229, 171, 225, 170, 8, 0, 0, 0, 0, 0, 0, 0}, 70, 137},
+ {{203, 71, 140, 237, 113, 96, 123, 16, 0, 0, 0, 0, 0, 0, 0, 0}, 60, 2},
+ {{99, 138, 207, 2, 244, 25, 211, 98, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 163},
+ {{114, 42, 98, 246, 252, 48, 233, 118, 63, 226, 157, 226, 192, 0, 0, 0}, 100, 162},
+ {{161, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10, 192},
+ {{233, 70, 240, 45, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 36, 185},
+ {{28, 123, 31, 176, 235, 229, 169, 192, 0, 0, 0, 0, 0, 0, 0, 0}, 59, 51},
+ {{146, 197, 243, 235, 243, 56, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 93},
+ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 159},
+ {{141, 92, 13, 27, 87, 241, 171, 143, 220, 0, 0, 0, 0, 0, 0, 0}, 72, 189},
+ {{164, 151, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 21, 248},
+ {{35, 188, 248, 79, 39, 151, 232, 215, 248, 245, 185, 144, 78, 102, 173, 128}, 123, 38},
+ {{193, 232, 166, 60, 62, 80, 230, 225, 165, 240, 0, 0, 0, 0, 0, 0}, 76, 167},
+ {{109, 229, 118, 155, 43, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 28},
+ {{160, 62, 63, 212, 218, 138, 154, 108, 163, 127, 197, 237, 183, 44, 140, 192}, 125, 37},
+ {{196, 37, 51, 146, 26, 85, 53, 31, 216, 141, 52, 218, 153, 32, 0, 0}, 107, 234},
+ {{228, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 9, 70},
+ {{154, 248, 20, 242, 154, 244, 63, 17, 121, 52, 70, 84, 118, 208, 0, 0}, 108, 50},
+ {{41, 100, 27, 84, 106, 112, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 51, 171},
+ {{81, 99, 197, 139, 30, 150, 230, 216, 81, 190, 84, 165, 29, 64, 128, 0}, 113, 236},
+ {{112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 4, 3},
+ {{164, 119, 253, 126, 160, 249, 183, 191, 119, 111, 224, 0, 0, 0, 0, 0}, 86, 64},
+ {{138, 58, 198, 254, 0, 197, 60, 91, 132, 199, 181, 251, 78, 160, 0, 0}, 108, 213},
+ {{209, 89, 168, 236, 146, 169, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 54, 15},
+ {{131, 210, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 20, 145},
+ {{165, 190, 157, 7, 131, 5, 147, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 57, 27},
+ {{179, 226, 57, 204, 187, 70, 52, 81, 119, 162, 229, 42, 47, 185, 9, 162}, 127, 75},
+ {{98, 235, 155, 51, 107, 167, 127, 137, 254, 246, 162, 171, 180, 13, 233, 0}, 123, 76},
+ {{107, 79, 76, 90, 94, 151, 155, 31, 33, 115, 19, 204, 98, 115, 0, 0}, 113, 247},
+ {{143, 46, 30, 175, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 43, 121},
+ {{155, 85, 217, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 30, 214},
+ {{58, 62, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 26, 221},
+ {{92, 155, 53, 3, 39, 108, 155, 200, 0, 0, 0, 0, 0, 0, 0, 0}, 63, 102},
+ {{64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, 191},
+ {{63, 134, 251, 59, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 39, 197},
+ {{234, 149, 220, 106, 0, 144, 214, 128, 35, 102, 0, 0, 0, 0, 0, 0}, 79, 106},
+};
+
+#define NUM_ROUTE_ENTRIES RTE_DIM(large_route_table)
+
+#define NUM_IPS_ENTRIES (NUM_ROUTE_ENTRIES * 100)
+
+/* clear the previous large_ips_table and reduce LPM6 test case much smaller,
+ * keep same size as previous one to make test case run similar input data.
+ */
+static struct ips_tbl_entry large_ips_table[NUM_IPS_ENTRIES];
+
+/* let the most significant depth bits of ip_out[] same as ip_in[]
+ * in the same bit position. ip_out[] and ip_in[] are IPv6 address.
+ */
+static inline void mask_ip6_prefix(uint8_t *ip_out,
+ const uint8_t *ip_in, uint8_t depth)
+{
+ int k;
+ uint8_t mask_in, mask_out;
+
+ for (k = 0; k < 16; k++) {
+ if (depth >= 8)
+ ip_out[k] = ip_in[k];
+ else if (depth > 0) {
+ mask_in = (uint8_t)((unsigned int)(-1) << (8 - depth));
+ mask_out = ~mask_in;
+ ip_out[k] = (ip_in[k] & mask_in)
+ | (ip_out[k] & mask_out);
+ } else
+ return;
+
+ depth -= 8;
+ }
+}
+
+/* check if IPv6 address ip[] match the rule with IPv6 address ip_rule[]
+ * and depth. if matched, return 0, else return -1.
+ */
+static inline int check_lpm6_rule(uint8_t *ip,
+ const uint8_t *ip_rule, uint8_t depth)
+{
+ int k;
+ uint8_t mask;
+
+ for (k = 0; k < 16; k++) {
+ if (depth >= 8) {
+ if (ip[k] != ip_rule[k])
+ return -1;
+ } else if (depth > 0) {
+ mask = (uint8_t)((unsigned int)(-1) << (8 - depth));
+ if ((ip[k] & mask) == (ip_rule[k] & mask))
+ return 0;
+ else
+ return -1;
+ } else
+ return 0;
+
+ depth -= 8;
+ }
+
+ return 0;
+}
+
+/* check input IPv6 address ip[] with each one in rule[] and
+ * output the *next_hop from the matched item in rule[] with
+ * longest depth. The count of items in rule[ ] is rule_num.
+ * if found that some item in rule[] is matched return 0,
+ * else return -1;
+ */
+static int get_next_hop(uint8_t *ip, uint8_t *next_hop,
+ const struct rules_tbl_entry *rule, int rule_num)
+{
+ int i;
+ int result;
+ uint8_t max_depth = 0;
+
+ for (i = 0; i < rule_num; i++) {
+ if (rule[i].depth >= max_depth) {
+ result = check_lpm6_rule(ip, rule[i].ip, rule[i].depth);
+ if (result == 0) {
+ *next_hop = rule[i].next_hop;
+ max_depth = rule[i].depth;
+ }
+ }
+ }
+
+ if (max_depth > 0)
+ return 0;
+ else
+ return -1;
+}
+
+/* the implementation of algorithm to generate large IPS table
+ * at run time. if gen_expected_nex_hop is non-zero, the expected
+ * next_hop of the IPv6 address of each item in IPS table is computed.
+ */
+static void generate_large_ips_table(int gen_expected_next_hop)
+{
+ uint32_t i, j, k;
+
+ for (i = 0; i < NUM_IPS_ENTRIES; i++) {
+ for (j = 0; j < 16; j++)
+ large_ips_table[i].ip[j] = lrand48();
+ }
+
+ for (k = j = 0, i = 0; i < NUM_IPS_ENTRIES; i++) {
+ mask_ip6_prefix(large_ips_table[i].ip,
+ large_route_table[j].ip, large_route_table[j].depth);
+ k++;
+ if (k == (NUM_IPS_ENTRIES / NUM_ROUTE_ENTRIES)) {
+ j++;
+ k = 0;
+ }
+ if (j == NUM_ROUTE_ENTRIES)
+ j = 0;
+ }
+
+ if (gen_expected_next_hop == 0)
+ return;
+
+ for (k = 0; k < NUM_IPS_ENTRIES; k++)
+ get_next_hop(large_ips_table[k].ip,
+ &(large_ips_table[k].next_hop),
+ large_route_table,
+ NUM_ROUTE_ENTRIES);
+
+}
+
+#endif /* _TEST_LPM_ROUTES_H_ */
diff --git a/src/spdk/dpdk/app/test/test_lpm6_perf.c b/src/spdk/dpdk/app/test/test_lpm6_perf.c
new file mode 100644
index 000000000..0b43ad824
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_lpm6_perf.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_memory.h>
+#include <rte_lpm6.h>
+
+#include "test.h"
+#include "test_lpm6_data.h"
+
+#define TEST_LPM_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d: \n", __LINE__); \
+ return -1; \
+ } \
+} while(0)
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE 100000
+#define NUMBER_TBL8S (1 << 16)
+
+static void
+print_route_distribution(const struct rules_tbl_entry *table, uint32_t n)
+{
+ unsigned i, j;
+
+ printf("Route distribution per prefix width: \n");
+ printf("DEPTH QUANTITY (PERCENT)\n");
+ printf("--------------------------- \n");
+
+ /* Count depths. */
+ for(i = 1; i <= 128; i++) {
+ unsigned depth_counter = 0;
+ double percent_hits;
+
+ for (j = 0; j < n; j++)
+ if (table[j].depth == (uint8_t) i)
+ depth_counter++;
+
+ percent_hits = ((double)depth_counter)/((double)n) * 100;
+ printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
+ }
+ printf("\n");
+}
+
+static int
+test_lpm6_perf(void)
+{
+ struct rte_lpm6 *lpm = NULL;
+ struct rte_lpm6_config config;
+ uint64_t begin, total_time;
+ unsigned i, j;
+ uint32_t next_hop_add = 0xAA, next_hop_return = 0;
+ int status = 0;
+ int64_t count = 0;
+
+ config.max_rules = 1000000;
+ config.number_tbl8s = NUMBER_TBL8S;
+ config.flags = 0;
+
+ rte_srand(rte_rdtsc());
+
+ printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
+
+ print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES);
+
+ /* Only generate IPv6 address of each item in large IPS table,
+ * here next_hop is not needed.
+ */
+ generate_large_ips_table(0);
+
+ lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Measure add. */
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ if (rte_lpm6_add(lpm, large_route_table[i].ip,
+ large_route_table[i].depth, next_hop_add) == 0)
+ status++;
+ }
+ /* End Timer. */
+ total_time = rte_rdtsc() - begin;
+
+ printf("Unique added entries = %d\n", status);
+ printf("Average LPM Add: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ /* Measure single Lookup */
+ total_time = 0;
+ count = 0;
+
+ for (i = 0; i < ITERATIONS; i ++) {
+ begin = rte_rdtsc();
+
+ for (j = 0; j < NUM_IPS_ENTRIES; j ++) {
+ if (rte_lpm6_lookup(lpm, large_ips_table[j].ip,
+ &next_hop_return) != 0)
+ count++;
+ }
+
+ total_time += rte_rdtsc() - begin;
+
+ }
+ printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Measure bulk Lookup */
+ total_time = 0;
+ count = 0;
+
+ uint8_t ip_batch[NUM_IPS_ENTRIES][16];
+ int32_t next_hops[NUM_IPS_ENTRIES];
+
+ for (i = 0; i < NUM_IPS_ENTRIES; i++)
+ memcpy(ip_batch[i], large_ips_table[i].ip, 16);
+
+ for (i = 0; i < ITERATIONS; i ++) {
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+ rte_lpm6_lookup_bulk_func(lpm, ip_batch, next_hops, NUM_IPS_ENTRIES);
+ total_time += rte_rdtsc() - begin;
+
+ for (j = 0; j < NUM_IPS_ENTRIES; j++)
+ if (next_hops[j] < 0)
+ count++;
+ }
+ printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Delete */
+ status = 0;
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ /* rte_lpm_delete(lpm, ip, depth) */
+ status += rte_lpm6_delete(lpm, large_route_table[i].ip,
+ large_route_table[i].depth);
+ }
+
+ total_time += rte_rdtsc() - begin;
+
+ printf("Average LPM Delete: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ rte_lpm6_delete_all(lpm);
+ rte_lpm6_free(lpm);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(lpm6_perf_autotest, test_lpm6_perf);
diff --git a/src/spdk/dpdk/app/test/test_lpm_perf.c b/src/spdk/dpdk/app/test/test_lpm_perf.c
new file mode 100644
index 000000000..489719c40
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_lpm_perf.c
@@ -0,0 +1,484 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_branch_prediction.h>
+#include <rte_ip.h>
+#include <rte_lpm.h>
+
+#include "test.h"
+#include "test_xmmt_ops.h"
+
+#define TEST_LPM_ASSERT(cond) do { \
+ if (!(cond)) { \
+ printf("Error at line %d: \n", __LINE__); \
+ return -1; \
+ } \
+} while(0)
+
+#define ITERATIONS (1 << 10)
+#define BATCH_SIZE (1 << 12)
+#define BULK_SIZE 32
+
+#define MAX_RULE_NUM (1200000)
+
+struct route_rule {
+ uint32_t ip;
+ uint8_t depth;
+};
+
+static struct route_rule large_route_table[MAX_RULE_NUM];
+
+static uint32_t num_route_entries;
+#define NUM_ROUTE_ENTRIES num_route_entries
+
+enum {
+ IP_CLASS_A,
+ IP_CLASS_B,
+ IP_CLASS_C
+};
+
+/* struct route_rule_count defines the total number of rules in following a/b/c
+ * each item in a[]/b[]/c[] is the number of common IP address class A/B/C, not
+ * including the ones for private local network.
+ */
+struct route_rule_count {
+ uint32_t a[RTE_LPM_MAX_DEPTH];
+ uint32_t b[RTE_LPM_MAX_DEPTH];
+ uint32_t c[RTE_LPM_MAX_DEPTH];
+};
+
+/* All following numbers of each depth of each common IP class are just
+ * got from previous large constant table in app/test/test_lpm_routes.h .
+ * In order to match similar performance, they keep same depth and IP
+ * address coverage as previous constant table. These numbers don't
+ * include any private local IP address. As previous large const rule
+ * table was just dumped from a real router, there are no any IP address
+ * in class C or D.
+ */
+static struct route_rule_count rule_count = {
+ .a = { /* IP class A in which the most significant bit is 0 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 1, /* depth = 3 */
+ 0, /* depth = 4 */
+ 2, /* depth = 5 */
+ 1, /* depth = 6 */
+ 3, /* depth = 7 */
+ 185, /* depth = 8 */
+ 26, /* depth = 9 */
+ 16, /* depth = 10 */
+ 39, /* depth = 11 */
+ 144, /* depth = 12 */
+ 233, /* depth = 13 */
+ 528, /* depth = 14 */
+ 866, /* depth = 15 */
+ 3856, /* depth = 16 */
+ 3268, /* depth = 17 */
+ 5662, /* depth = 18 */
+ 17301, /* depth = 19 */
+ 22226, /* depth = 20 */
+ 11147, /* depth = 21 */
+ 16746, /* depth = 22 */
+ 17120, /* depth = 23 */
+ 77578, /* depth = 24 */
+ 401, /* depth = 25 */
+ 656, /* depth = 26 */
+ 1107, /* depth = 27 */
+ 1121, /* depth = 28 */
+ 2316, /* depth = 29 */
+ 717, /* depth = 30 */
+ 10, /* depth = 31 */
+ 66 /* depth = 32 */
+ },
+ .b = { /* IP class A in which the most 2 significant bits are 10 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 0, /* depth = 3 */
+ 0, /* depth = 4 */
+ 1, /* depth = 5 */
+ 1, /* depth = 6 */
+ 1, /* depth = 7 */
+ 3, /* depth = 8 */
+ 3, /* depth = 9 */
+ 30, /* depth = 10 */
+ 25, /* depth = 11 */
+ 168, /* depth = 12 */
+ 305, /* depth = 13 */
+ 569, /* depth = 14 */
+ 1129, /* depth = 15 */
+ 50800, /* depth = 16 */
+ 1645, /* depth = 17 */
+ 1820, /* depth = 18 */
+ 3506, /* depth = 19 */
+ 3258, /* depth = 20 */
+ 3424, /* depth = 21 */
+ 4971, /* depth = 22 */
+ 6885, /* depth = 23 */
+ 39771, /* depth = 24 */
+ 424, /* depth = 25 */
+ 170, /* depth = 26 */
+ 433, /* depth = 27 */
+ 92, /* depth = 28 */
+ 366, /* depth = 29 */
+ 377, /* depth = 30 */
+ 2, /* depth = 31 */
+ 200 /* depth = 32 */
+ },
+ .c = { /* IP class A in which the most 3 significant bits are 110 */
+ 0, /* depth = 1 */
+ 0, /* depth = 2 */
+ 0, /* depth = 3 */
+ 0, /* depth = 4 */
+ 0, /* depth = 5 */
+ 0, /* depth = 6 */
+ 0, /* depth = 7 */
+ 12, /* depth = 8 */
+ 8, /* depth = 9 */
+ 9, /* depth = 10 */
+ 33, /* depth = 11 */
+ 69, /* depth = 12 */
+ 237, /* depth = 13 */
+ 1007, /* depth = 14 */
+ 1717, /* depth = 15 */
+ 14663, /* depth = 16 */
+ 8070, /* depth = 17 */
+ 16185, /* depth = 18 */
+ 48261, /* depth = 19 */
+ 36870, /* depth = 20 */
+ 33960, /* depth = 21 */
+ 50638, /* depth = 22 */
+ 61422, /* depth = 23 */
+ 466549, /* depth = 24 */
+ 1829, /* depth = 25 */
+ 4824, /* depth = 26 */
+ 4927, /* depth = 27 */
+ 5914, /* depth = 28 */
+ 10254, /* depth = 29 */
+ 4905, /* depth = 30 */
+ 1, /* depth = 31 */
+ 716 /* depth = 32 */
+ }
+};
+
+static void generate_random_rule_prefix(uint32_t ip_class, uint8_t depth)
+{
+/* IP address class A, the most significant bit is 0 */
+#define IP_HEAD_MASK_A 0x00000000
+#define IP_HEAD_BIT_NUM_A 1
+
+/* IP address class B, the most significant 2 bits are 10 */
+#define IP_HEAD_MASK_B 0x80000000
+#define IP_HEAD_BIT_NUM_B 2
+
+/* IP address class C, the most significant 3 bits are 110 */
+#define IP_HEAD_MASK_C 0xC0000000
+#define IP_HEAD_BIT_NUM_C 3
+
+ uint32_t class_depth;
+ uint32_t range;
+ uint32_t mask;
+ uint32_t step;
+ uint32_t start;
+ uint32_t fixed_bit_num;
+ uint32_t ip_head_mask;
+ uint32_t rule_num;
+ uint32_t k;
+ struct route_rule *ptr_rule;
+
+ if (ip_class == IP_CLASS_A) { /* IP Address class A */
+ fixed_bit_num = IP_HEAD_BIT_NUM_A;
+ ip_head_mask = IP_HEAD_MASK_A;
+ rule_num = rule_count.a[depth - 1];
+ } else if (ip_class == IP_CLASS_B) { /* IP Address class B */
+ fixed_bit_num = IP_HEAD_BIT_NUM_B;
+ ip_head_mask = IP_HEAD_MASK_B;
+ rule_num = rule_count.b[depth - 1];
+ } else { /* IP Address class C */
+ fixed_bit_num = IP_HEAD_BIT_NUM_C;
+ ip_head_mask = IP_HEAD_MASK_C;
+ rule_num = rule_count.c[depth - 1];
+ }
+
+ if (rule_num == 0)
+ return;
+
+ /* the number of rest bits which don't include the most significant
+ * fixed bits for this IP address class
+ */
+ class_depth = depth - fixed_bit_num;
+
+ /* range is the maximum number of rules for this depth and
+ * this IP address class
+ */
+ range = 1 << class_depth;
+
+ /* only mask the most depth significant generated bits
+ * except fixed bits for IP address class
+ */
+ mask = range - 1;
+
+ /* Widen coverage of IP address in generated rules */
+ if (range <= rule_num)
+ step = 1;
+ else
+ step = round((double)range / rule_num);
+
+ /* Only generate rest bits except the most significant
+ * fixed bits for IP address class
+ */
+ start = lrand48() & mask;
+ ptr_rule = &large_route_table[num_route_entries];
+ for (k = 0; k < rule_num; k++) {
+ ptr_rule->ip = (start << (RTE_LPM_MAX_DEPTH - depth))
+ | ip_head_mask;
+ ptr_rule->depth = depth;
+ ptr_rule++;
+ start = (start + step) & mask;
+ }
+ num_route_entries += rule_num;
+}
+
+static void insert_rule_in_random_pos(uint32_t ip, uint8_t depth)
+{
+ uint32_t pos;
+ int try_count = 0;
+ struct route_rule tmp;
+
+ do {
+ pos = lrand48();
+ try_count++;
+ } while ((try_count < 10) && (pos > num_route_entries));
+
+ if ((pos > num_route_entries) || (pos >= MAX_RULE_NUM))
+ pos = num_route_entries >> 1;
+
+ tmp = large_route_table[pos];
+ large_route_table[pos].ip = ip;
+ large_route_table[pos].depth = depth;
+ if (num_route_entries < MAX_RULE_NUM)
+ large_route_table[num_route_entries++] = tmp;
+}
+
+static void generate_large_route_rule_table(void)
+{
+ uint32_t ip_class;
+ uint8_t depth;
+
+ num_route_entries = 0;
+ memset(large_route_table, 0, sizeof(large_route_table));
+
+ for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
+ for (depth = 1; depth <= RTE_LPM_MAX_DEPTH; depth++) {
+ generate_random_rule_prefix(ip_class, depth);
+ }
+ }
+
+ /* Add following rules to keep same as previous large constant table,
+ * they are 4 rules with private local IP address and 1 all-zeros prefix
+ * with depth = 8.
+ */
+ insert_rule_in_random_pos(RTE_IPV4(0, 0, 0, 0), 8);
+ insert_rule_in_random_pos(RTE_IPV4(10, 2, 23, 147), 32);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 100, 10), 24);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 25, 100), 24);
+ insert_rule_in_random_pos(RTE_IPV4(192, 168, 129, 124), 32);
+}
+
+static void
+print_route_distribution(const struct route_rule *table, uint32_t n)
+{
+ unsigned i, j;
+
+ printf("Route distribution per prefix width: \n");
+ printf("DEPTH QUANTITY (PERCENT)\n");
+ printf("--------------------------- \n");
+
+ /* Count depths. */
+ for (i = 1; i <= 32; i++) {
+ unsigned depth_counter = 0;
+ double percent_hits;
+
+ for (j = 0; j < n; j++)
+ if (table[j].depth == (uint8_t) i)
+ depth_counter++;
+
+ percent_hits = ((double)depth_counter)/((double)n) * 100;
+ printf("%.2u%15u (%.2f)\n", i, depth_counter, percent_hits);
+ }
+ printf("\n");
+}
+
+static int
+test_lpm_perf(void)
+{
+ struct rte_lpm *lpm = NULL;
+ struct rte_lpm_config config;
+
+ config.max_rules = 2000000;
+ config.number_tbl8s = 2048;
+ config.flags = 0;
+ uint64_t begin, total_time, lpm_used_entries = 0;
+ unsigned i, j;
+ uint32_t next_hop_add = 0xAA, next_hop_return = 0;
+ int status = 0;
+ uint64_t cache_line_counter = 0;
+ int64_t count = 0;
+
+ rte_srand(rte_rdtsc());
+
+ generate_large_route_rule_table();
+
+ printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
+
+ print_route_distribution(large_route_table, (uint32_t) NUM_ROUTE_ENTRIES);
+
+ lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
+ TEST_LPM_ASSERT(lpm != NULL);
+
+ /* Measue add. */
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ if (rte_lpm_add(lpm, large_route_table[i].ip,
+ large_route_table[i].depth, next_hop_add) == 0)
+ status++;
+ }
+ /* End Timer. */
+ total_time = rte_rdtsc() - begin;
+
+ printf("Unique added entries = %d\n", status);
+ /* Obtain add statistics. */
+ for (i = 0; i < RTE_LPM_TBL24_NUM_ENTRIES; i++) {
+ if (lpm->tbl24[i].valid)
+ lpm_used_entries++;
+
+ if (i % 32 == 0) {
+ if ((uint64_t)count < lpm_used_entries) {
+ cache_line_counter++;
+ count = lpm_used_entries;
+ }
+ }
+ }
+
+ printf("Used table 24 entries = %u (%g%%)\n",
+ (unsigned) lpm_used_entries,
+ (lpm_used_entries * 100.0) / RTE_LPM_TBL24_NUM_ENTRIES);
+ printf("64 byte Cache entries used = %u (%u bytes)\n",
+ (unsigned) cache_line_counter, (unsigned) cache_line_counter * 64);
+
+ printf("Average LPM Add: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ /* Measure single Lookup */
+ total_time = 0;
+ count = 0;
+
+ for (i = 0; i < ITERATIONS; i++) {
+ static uint32_t ip_batch[BATCH_SIZE];
+
+ for (j = 0; j < BATCH_SIZE; j++)
+ ip_batch[j] = rte_rand();
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+
+ for (j = 0; j < BATCH_SIZE; j++) {
+ if (rte_lpm_lookup(lpm, ip_batch[j], &next_hop_return) != 0)
+ count++;
+ }
+
+ total_time += rte_rdtsc() - begin;
+
+ }
+ printf("Average LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Measure bulk Lookup */
+ total_time = 0;
+ count = 0;
+ for (i = 0; i < ITERATIONS; i++) {
+ static uint32_t ip_batch[BATCH_SIZE];
+ uint32_t next_hops[BULK_SIZE];
+
+ /* Create array of random IP addresses */
+ for (j = 0; j < BATCH_SIZE; j++)
+ ip_batch[j] = rte_rand();
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+ for (j = 0; j < BATCH_SIZE; j += BULK_SIZE) {
+ unsigned k;
+ rte_lpm_lookup_bulk(lpm, &ip_batch[j], next_hops, BULK_SIZE);
+ for (k = 0; k < BULK_SIZE; k++)
+ if (unlikely(!(next_hops[k] & RTE_LPM_LOOKUP_SUCCESS)))
+ count++;
+ }
+
+ total_time += rte_rdtsc() - begin;
+ }
+ printf("BULK LPM Lookup: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Measure LookupX4 */
+ total_time = 0;
+ count = 0;
+ for (i = 0; i < ITERATIONS; i++) {
+ static uint32_t ip_batch[BATCH_SIZE];
+ uint32_t next_hops[4];
+
+ /* Create array of random IP addresses */
+ for (j = 0; j < BATCH_SIZE; j++)
+ ip_batch[j] = rte_rand();
+
+ /* Lookup per batch */
+ begin = rte_rdtsc();
+ for (j = 0; j < BATCH_SIZE; j += RTE_DIM(next_hops)) {
+ unsigned k;
+ xmm_t ipx4;
+
+ ipx4 = vect_loadu_sil128((xmm_t *)(ip_batch + j));
+ ipx4 = *(xmm_t *)(ip_batch + j);
+ rte_lpm_lookupx4(lpm, ipx4, next_hops, UINT32_MAX);
+ for (k = 0; k < RTE_DIM(next_hops); k++)
+ if (unlikely(next_hops[k] == UINT32_MAX))
+ count++;
+ }
+
+ total_time += rte_rdtsc() - begin;
+ }
+ printf("LPM LookupX4: %.1f cycles (fails = %.1f%%)\n",
+ (double)total_time / ((double)ITERATIONS * BATCH_SIZE),
+ (count * 100.0) / (double)(ITERATIONS * BATCH_SIZE));
+
+ /* Measure Delete */
+ status = 0;
+ begin = rte_rdtsc();
+
+ for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+ /* rte_lpm_delete(lpm, ip, depth) */
+ status += rte_lpm_delete(lpm, large_route_table[i].ip,
+ large_route_table[i].depth);
+ }
+
+ total_time = rte_rdtsc() - begin;
+
+ printf("Average LPM Delete: %g cycles\n",
+ (double)total_time / NUM_ROUTE_ENTRIES);
+
+ rte_lpm_delete_all(lpm);
+ rte_lpm_free(lpm);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(lpm_perf_autotest, test_lpm_perf);
diff --git a/src/spdk/dpdk/app/test/test_malloc.c b/src/spdk/dpdk/app/test/test_malloc.c
new file mode 100644
index 000000000..71b3cfdde
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_malloc.c
@@ -0,0 +1,1080 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/queue.h>
+#include <unistd.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+#define N 10000
+
+
+static int
+is_mem_on_socket(int32_t socket);
+
+static int32_t
+addr_to_socket(void *addr);
+
+/*
+ * Malloc
+ * ======
+ *
+ * Allocate some dynamic memory from heap (3 areas). Check that areas
+ * don't overlap and that alignment constraints match. This test is
+ * done many times on different lcores simultaneously.
+ */
+
+/* Test if memory overlaps: return 1 if true, or 0 if false. */
+static int
+is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2)
+{
+ unsigned long ptr1 = (unsigned long)p1;
+ unsigned long ptr2 = (unsigned long)p2;
+
+ if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1)
+ return 1;
+ else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2)
+ return 1;
+ return 0;
+}
+
+static int
+is_aligned(void *p, int align)
+{
+ unsigned long addr = (unsigned long)p;
+ unsigned mask = align - 1;
+
+ if (addr & mask)
+ return 0;
+ return 1;
+}
+
+static int
+test_align_overlap_per_lcore(__rte_unused void *arg)
+{
+ const unsigned align1 = 8,
+ align2 = 64,
+ align3 = 2048;
+ unsigned i,j;
+ void *p1 = NULL, *p2 = NULL, *p3 = NULL;
+ int ret = 0;
+
+ for (i = 0; i < N; i++) {
+ p1 = rte_zmalloc("dummy", 1000, align1);
+ if (!p1){
+ printf("rte_zmalloc returned NULL (i=%u)\n", i);
+ ret = -1;
+ break;
+ }
+ for(j = 0; j < 1000 ; j++) {
+ if( *(char *)p1 != 0) {
+ printf("rte_zmalloc didn't zero the allocated memory\n");
+ ret = -1;
+ }
+ }
+ p2 = rte_malloc("dummy", 1000, align2);
+ if (!p2){
+ printf("rte_malloc returned NULL (i=%u)\n", i);
+ ret = -1;
+ rte_free(p1);
+ break;
+ }
+ p3 = rte_malloc("dummy", 1000, align3);
+ if (!p3){
+ printf("rte_malloc returned NULL (i=%u)\n", i);
+ ret = -1;
+ rte_free(p1);
+ rte_free(p2);
+ break;
+ }
+ if (is_memory_overlap(p1, 1000, p2, 1000)) {
+ printf("p1 and p2 overlaps\n");
+ ret = -1;
+ }
+ if (is_memory_overlap(p2, 1000, p3, 1000)) {
+ printf("p2 and p3 overlaps\n");
+ ret = -1;
+ }
+ if (is_memory_overlap(p1, 1000, p3, 1000)) {
+ printf("p1 and p3 overlaps\n");
+ ret = -1;
+ }
+ if (!is_aligned(p1, align1)) {
+ printf("p1 is not aligned\n");
+ ret = -1;
+ }
+ if (!is_aligned(p2, align2)) {
+ printf("p2 is not aligned\n");
+ ret = -1;
+ }
+ if (!is_aligned(p3, align3)) {
+ printf("p3 is not aligned\n");
+ ret = -1;
+ }
+ rte_free(p1);
+ rte_free(p2);
+ rte_free(p3);
+ }
+ rte_malloc_dump_stats(stdout, "dummy");
+
+ return ret;
+}
+
+static int
+test_reordered_free_per_lcore(__rte_unused void *arg)
+{
+ const unsigned align1 = 8,
+ align2 = 64,
+ align3 = 2048;
+ unsigned i,j;
+ void *p1, *p2, *p3;
+ int ret = 0;
+
+ for (i = 0; i < 30; i++) {
+ p1 = rte_zmalloc("dummy", 1000, align1);
+ if (!p1){
+ printf("rte_zmalloc returned NULL (i=%u)\n", i);
+ ret = -1;
+ break;
+ }
+ for(j = 0; j < 1000 ; j++) {
+ if( *(char *)p1 != 0) {
+ printf("rte_zmalloc didn't zero the allocated memory\n");
+ ret = -1;
+ }
+ }
+ /* use calloc to allocate 1000 16-byte items this time */
+ p2 = rte_calloc("dummy", 1000, 16, align2);
+ /* for third request use regular malloc again */
+ p3 = rte_malloc("dummy", 1000, align3);
+ if (!p2 || !p3){
+ printf("rte_malloc returned NULL (i=%u)\n", i);
+ ret = -1;
+ break;
+ }
+ if (is_memory_overlap(p1, 1000, p2, 1000)) {
+ printf("p1 and p2 overlaps\n");
+ ret = -1;
+ }
+ if (is_memory_overlap(p2, 1000, p3, 1000)) {
+ printf("p2 and p3 overlaps\n");
+ ret = -1;
+ }
+ if (is_memory_overlap(p1, 1000, p3, 1000)) {
+ printf("p1 and p3 overlaps\n");
+ ret = -1;
+ }
+ if (!is_aligned(p1, align1)) {
+ printf("p1 is not aligned\n");
+ ret = -1;
+ }
+ if (!is_aligned(p2, align2)) {
+ printf("p2 is not aligned\n");
+ ret = -1;
+ }
+ if (!is_aligned(p3, align3)) {
+ printf("p3 is not aligned\n");
+ ret = -1;
+ }
+ /* try freeing in every possible order */
+ switch (i%6){
+ case 0:
+ rte_free(p1);
+ rte_free(p2);
+ rte_free(p3);
+ break;
+ case 1:
+ rte_free(p1);
+ rte_free(p3);
+ rte_free(p2);
+ break;
+ case 2:
+ rte_free(p2);
+ rte_free(p1);
+ rte_free(p3);
+ break;
+ case 3:
+ rte_free(p2);
+ rte_free(p3);
+ rte_free(p1);
+ break;
+ case 4:
+ rte_free(p3);
+ rte_free(p1);
+ rte_free(p2);
+ break;
+ case 5:
+ rte_free(p3);
+ rte_free(p2);
+ rte_free(p1);
+ break;
+ }
+ }
+ rte_malloc_dump_stats(stdout, "dummy");
+
+ return ret;
+}
+
+/* test function inside the malloc lib*/
+static int
+test_str_to_size(void)
+{
+ struct {
+ const char *str;
+ uint64_t value;
+ } test_values[] =
+ {{ "5G", (uint64_t)5 * 1024 * 1024 *1024 },
+ {"0x20g", (uint64_t)0x20 * 1024 * 1024 *1024},
+ {"10M", 10 * 1024 * 1024},
+ {"050m", 050 * 1024 * 1024},
+ {"8K", 8 * 1024},
+ {"15k", 15 * 1024},
+ {"0200", 0200},
+ {"0x103", 0x103},
+ {"432", 432},
+ {"-1", 0}, /* negative values return 0 */
+ {" -2", 0},
+ {" -3MB", 0},
+ {"18446744073709551616", 0} /* ULLONG_MAX + 1 == out of range*/
+ };
+ unsigned i;
+ for (i = 0; i < RTE_DIM(test_values); i++)
+ if (rte_str_to_size(test_values[i].str) != test_values[i].value)
+ return -1;
+ return 0;
+}
+
+static int
+test_multi_alloc_statistics(void)
+{
+ int socket = 0;
+ struct rte_malloc_socket_stats pre_stats, post_stats ,first_stats, second_stats;
+ size_t size = 2048;
+ int align = 1024;
+ int overhead = 0;
+
+ /* Dynamically calculate the overhead by allocating one cacheline and
+ * then comparing what was allocated from the heap.
+ */
+ rte_malloc_get_socket_stats(socket, &pre_stats);
+
+ void *dummy = rte_malloc_socket(NULL, RTE_CACHE_LINE_SIZE, 0, socket);
+ if (dummy == NULL)
+ return -1;
+
+ rte_malloc_get_socket_stats(socket, &post_stats);
+
+ /* after subtracting cache line, remainder is overhead */
+ overhead = post_stats.heap_allocsz_bytes - pre_stats.heap_allocsz_bytes;
+ overhead -= RTE_CACHE_LINE_SIZE;
+
+ rte_free(dummy);
+
+ /* Now start the real tests */
+ rte_malloc_get_socket_stats(socket, &pre_stats);
+
+ void *p1 = rte_malloc_socket("stats", size , align, socket);
+ if (!p1)
+ return -1;
+ rte_free(p1);
+ rte_malloc_dump_stats(stdout, "stats");
+
+ rte_malloc_get_socket_stats(socket,&post_stats);
+ /* Check statistics reported are correct */
+ /* All post stats should be equal to pre stats after alloc freed */
+ if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) &&
+ (post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) &&
+ (post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&&
+ (post_stats.alloc_count!=pre_stats.alloc_count)&&
+ (post_stats.free_count!=pre_stats.free_count)) {
+ printf("Malloc statistics are incorrect - freed alloc\n");
+ return -1;
+ }
+ /* Check two consecutive allocations */
+ size = 1024;
+ align = 0;
+ rte_malloc_get_socket_stats(socket,&pre_stats);
+ void *p2 = rte_malloc_socket("add", size ,align, socket);
+ if (!p2)
+ return -1;
+ rte_malloc_get_socket_stats(socket,&first_stats);
+
+ void *p3 = rte_malloc_socket("add2", size,align, socket);
+ if (!p3)
+ return -1;
+
+ rte_malloc_get_socket_stats(socket,&second_stats);
+
+ rte_free(p2);
+ rte_free(p3);
+
+ /* After freeing both allocations check stats return to original */
+ rte_malloc_get_socket_stats(socket, &post_stats);
+
+ if(second_stats.heap_totalsz_bytes != first_stats.heap_totalsz_bytes) {
+ printf("Incorrect heap statistics: Total size \n");
+ return -1;
+ }
+ /* Check allocated size is equal to two additions plus overhead */
+ if(second_stats.heap_allocsz_bytes !=
+ size + overhead + first_stats.heap_allocsz_bytes) {
+ printf("Incorrect heap statistics: Allocated size \n");
+ return -1;
+ }
+ /* Check that allocation count increments correctly i.e. +1 */
+ if (second_stats.alloc_count != first_stats.alloc_count + 1) {
+ printf("Incorrect heap statistics: Allocated count \n");
+ return -1;
+ }
+
+ if (second_stats.free_count != first_stats.free_count){
+ printf("Incorrect heap statistics: Free count \n");
+ return -1;
+ }
+
+ /* Make sure that we didn't touch our greatest chunk: 2 * 11M) */
+ if (post_stats.greatest_free_size != pre_stats.greatest_free_size) {
+ printf("Incorrect heap statistics: Greatest free size \n");
+ return -1;
+ }
+ /* Free size must equal the original free size minus the new allocation*/
+ if (first_stats.heap_freesz_bytes <= second_stats.heap_freesz_bytes) {
+ printf("Incorrect heap statistics: Free size \n");
+ return -1;
+ }
+
+ if ((post_stats.heap_totalsz_bytes != pre_stats.heap_totalsz_bytes) &&
+ (post_stats.heap_freesz_bytes!=pre_stats.heap_freesz_bytes) &&
+ (post_stats.heap_allocsz_bytes!=pre_stats.heap_allocsz_bytes)&&
+ (post_stats.alloc_count!=pre_stats.alloc_count)&&
+ (post_stats.free_count!=pre_stats.free_count)) {
+ printf("Malloc statistics are incorrect - freed alloc\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_realloc_socket(int socket)
+{
+ const char hello_str[] = "Hello, world!";
+ const unsigned size1 = 1024;
+ const unsigned size2 = size1 + 1024;
+ const unsigned size3 = size2;
+ const unsigned size4 = size3 + 1024;
+
+ /* test data is the same even if element is moved*/
+ char *ptr1 = rte_zmalloc_socket(
+ NULL, size1, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr1){
+ printf("NULL pointer returned from rte_zmalloc\n");
+ return -1;
+ }
+ strlcpy(ptr1, hello_str, size1);
+ char *ptr2 = rte_realloc_socket(
+ ptr1, size2, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr2){
+ rte_free(ptr1);
+ printf("NULL pointer returned from rte_realloc\n");
+ return -1;
+ }
+ if (ptr1 == ptr2){
+ printf("unexpected - ptr1 == ptr2\n");
+ }
+ if (strcmp(ptr2, hello_str) != 0){
+ printf("Error - lost data from pointed area\n");
+ rte_free(ptr2);
+ return -1;
+ }
+ unsigned i;
+ for (i = strnlen(hello_str, sizeof(hello_str)); i < size1; i++)
+ if (ptr2[i] != 0){
+ printf("Bad data in realloc\n");
+ rte_free(ptr2);
+ return -1;
+ }
+ /* now allocate third element, free the second
+ * and resize third. It should not move. (ptr1 is now invalid)
+ */
+ char *ptr3 = rte_zmalloc_socket(
+ NULL, size3, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr3){
+ printf("NULL pointer returned from rte_zmalloc\n");
+ rte_free(ptr2);
+ return -1;
+ }
+ for (i = 0; i < size3; i++)
+ if (ptr3[i] != 0){
+ printf("Bad data in zmalloc\n");
+ rte_free(ptr3);
+ rte_free(ptr2);
+ return -1;
+ }
+ rte_free(ptr2);
+ /* first resize to half the size of the freed block */
+ char *ptr4 = rte_realloc_socket(
+ ptr3, size4, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr4){
+ printf("NULL pointer returned from rte_realloc\n");
+ rte_free(ptr3);
+ return -1;
+ }
+ if (ptr3 != ptr4){
+ printf("Unexpected - ptr4 != ptr3\n");
+ rte_free(ptr4);
+ return -1;
+ }
+ /* now resize again to the full size of the freed block */
+ ptr4 = rte_realloc_socket(ptr3, size3 + size2 + size1,
+ RTE_CACHE_LINE_SIZE, socket);
+ if (ptr3 != ptr4){
+ printf("Unexpected - ptr4 != ptr3 on second resize\n");
+ rte_free(ptr4);
+ return -1;
+ }
+ rte_free(ptr4);
+
+ /* now try a resize to a smaller size, see if it works */
+ const unsigned size5 = 1024;
+ const unsigned size6 = size5 / 2;
+ char *ptr5 = rte_malloc_socket(
+ NULL, size5, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr5){
+ printf("NULL pointer returned from rte_malloc\n");
+ return -1;
+ }
+ char *ptr6 = rte_realloc_socket(
+ ptr5, size6, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr6){
+ printf("NULL pointer returned from rte_realloc\n");
+ rte_free(ptr5);
+ return -1;
+ }
+ if (ptr5 != ptr6){
+ printf("Error, resizing to a smaller size moved data\n");
+ rte_free(ptr6);
+ return -1;
+ }
+ rte_free(ptr6);
+
+ /* check for behaviour changing alignment */
+ const unsigned size7 = 1024;
+ const unsigned orig_align = RTE_CACHE_LINE_SIZE;
+ unsigned new_align = RTE_CACHE_LINE_SIZE * 2;
+ char *ptr7 = rte_malloc_socket(NULL, size7, orig_align, socket);
+ if (!ptr7){
+ printf("NULL pointer returned from rte_malloc\n");
+ return -1;
+ }
+ /* calc an alignment we don't already have */
+ while(RTE_PTR_ALIGN(ptr7, new_align) == ptr7)
+ new_align *= 2;
+ char *ptr8 = rte_realloc_socket(ptr7, size7, new_align, socket);
+ if (!ptr8){
+ printf("NULL pointer returned from rte_realloc\n");
+ rte_free(ptr7);
+ return -1;
+ }
+ if (RTE_PTR_ALIGN(ptr8, new_align) != ptr8){
+ printf("Failure to re-align data\n");
+ rte_free(ptr8);
+ return -1;
+ }
+ rte_free(ptr8);
+
+ /* test behaviour when there is a free block after current one,
+ * but its not big enough
+ */
+ unsigned size9 = 1024, size10 = 1024;
+ unsigned size11 = size9 + size10 + 256;
+ char *ptr9 = rte_malloc_socket(
+ NULL, size9, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr9){
+ printf("NULL pointer returned from rte_malloc\n");
+ return -1;
+ }
+ char *ptr10 = rte_malloc_socket(
+ NULL, size10, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr10){
+ printf("NULL pointer returned from rte_malloc\n");
+ return -1;
+ }
+ rte_free(ptr9);
+ char *ptr11 = rte_realloc_socket(
+ ptr10, size11, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr11){
+ printf("NULL pointer returned from rte_realloc\n");
+ rte_free(ptr10);
+ return -1;
+ }
+ if (ptr11 == ptr10){
+ printf("Error, unexpected that realloc has not created new buffer\n");
+ rte_free(ptr11);
+ return -1;
+ }
+ rte_free(ptr11);
+
+ /* check we don't crash if we pass null to realloc
+ * We should get a malloc of the size requested*/
+ const size_t size12 = 1024;
+ size_t size12_check;
+ char *ptr12 = rte_realloc_socket(
+ NULL, size12, RTE_CACHE_LINE_SIZE, socket);
+ if (!ptr12){
+ printf("NULL pointer returned from rte_realloc\n");
+ return -1;
+ }
+ if (rte_malloc_validate(ptr12, &size12_check) < 0 ||
+ size12_check != size12){
+ rte_free(ptr12);
+ return -1;
+ }
+ rte_free(ptr12);
+
+ /* do the same, but for regular memory */
+ ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE);
+ if (!ptr12) {
+ printf("NULL pointer returned from rte_realloc\n");
+ return -1;
+ }
+ if (rte_malloc_validate(ptr12, &size12_check) < 0 ||
+ size12_check != size12) {
+ rte_free(ptr12);
+ return -1;
+ }
+ rte_free(ptr12);
+
+ return 0;
+}
+
+static int
+test_realloc_numa(void)
+{
+ /* check realloc_socket part */
+ int32_t socket_count = 0, socket_allocated, socket;
+ void *ptr1, *ptr2;
+ int ret = -1;
+ size_t size = 1024;
+
+ ptr1 = NULL;
+ for (socket = 0; socket < RTE_MAX_NUMA_NODES; socket++) {
+ if (is_mem_on_socket(socket)) {
+ int j = 2;
+
+ socket_count++;
+ while (j--) {
+ /* j == 1 -> resizing */
+ ptr2 = rte_realloc_socket(ptr1, size,
+ RTE_CACHE_LINE_SIZE,
+ socket);
+ if (ptr2 == NULL) {
+ printf("NULL pointer returned from rte_realloc_socket\n");
+ goto end;
+ }
+
+ ptr1 = ptr2;
+ socket_allocated = addr_to_socket(ptr2);
+ if (socket_allocated != socket) {
+ printf("Requested socket (%d) doesn't mach allocated one (%d)\n",
+ socket, socket_allocated);
+ goto end;
+ }
+ size += RTE_CACHE_LINE_SIZE;
+ }
+ }
+ }
+
+ /* Print warnign if only a single socket, but don't fail the test */
+ if (socket_count < 2)
+ printf("WARNING: realloc_socket test needs memory on multiple sockets!\n");
+
+ ret = 0;
+end:
+ rte_free(ptr1);
+ return ret;
+}
+
+static int
+test_realloc(void)
+{
+ const char *heap_name = "realloc_heap";
+ int realloc_heap_socket;
+ unsigned int mem_sz = 1U << 13; /* 8K */
+ unsigned int page_sz = sysconf(_SC_PAGESIZE);
+ void *mem;
+ int ret;
+
+ /* page size may be bigger than total mem size, so adjust */
+ mem_sz = RTE_MAX(mem_sz, page_sz);
+
+ /*
+ * the realloc tests depend on specific layout of underlying memory, so
+ * to prevent accidental failures to do fragmented main heap, we will
+ * do all of our tests on an artificially created memory.
+ */
+ if (rte_malloc_heap_create(heap_name) != 0) {
+ printf("Failed to create external heap\n");
+ ret = -1;
+ goto end;
+ }
+ realloc_heap_socket = rte_malloc_heap_get_socket(heap_name);
+
+ mem = mmap(NULL, mem_sz, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (mem == MAP_FAILED) {
+ printf("Failed to allocate memory for external heap\n");
+ ret = -1;
+ goto heap_destroy;
+ }
+
+ if (rte_malloc_heap_memory_add(
+ heap_name, mem, mem_sz, NULL, 0, page_sz) != 0) {
+ printf("Failed to add memory to external heap\n");
+ ret = -1;
+ goto mem_free;
+ }
+
+ /* run the socket-bound tests */
+ ret = test_realloc_socket(realloc_heap_socket);
+ if (ret != 0)
+ goto mem_remove;
+
+ /* now, run the NUMA node tests */
+ ret = test_realloc_numa();
+
+mem_remove:
+ rte_malloc_heap_memory_remove(heap_name, mem, mem_sz);
+mem_free:
+ munmap(mem, mem_sz);
+heap_destroy:
+ rte_malloc_heap_destroy(heap_name);
+end:
+ return ret;
+}
+
+static int
+test_random_alloc_free(void *_ __rte_unused)
+{
+ struct mem_list {
+ struct mem_list *next;
+ char data[0];
+ } *list_head = NULL;
+ unsigned i;
+ unsigned count = 0;
+
+ rte_srand((unsigned)rte_rdtsc());
+
+ for (i = 0; i < N; i++){
+ unsigned free_mem = 0;
+ size_t allocated_size;
+ while (!free_mem){
+ const unsigned mem_size = sizeof(struct mem_list) + \
+ rte_rand() % (64 * 1024);
+ const unsigned align = 1 << (rte_rand() % 12); /* up to 4k alignment */
+ struct mem_list *entry = rte_malloc(NULL,
+ mem_size, align);
+ if (entry == NULL)
+ return -1;
+ if (RTE_PTR_ALIGN(entry, align)!= entry)
+ return -1;
+ if (rte_malloc_validate(entry, &allocated_size) == -1
+ || allocated_size < mem_size)
+ return -1;
+ memset(entry->data, rte_lcore_id(),
+ mem_size - sizeof(*entry));
+ entry->next = list_head;
+ if (rte_malloc_validate(entry, NULL) == -1)
+ return -1;
+ list_head = entry;
+
+ count++;
+ /* switch to freeing the memory with a 20% probability */
+ free_mem = ((rte_rand() % 10) >= 8);
+ }
+ while (list_head){
+ struct mem_list *entry = list_head;
+ list_head = list_head->next;
+ rte_free(entry);
+ }
+ }
+ printf("Lcore %u allocated/freed %u blocks\n", rte_lcore_id(), count);
+ return 0;
+}
+
+#define err_return() do { \
+ printf("%s: %d - Error\n", __func__, __LINE__); \
+ goto err_return; \
+} while (0)
+
+static int
+test_rte_malloc_validate(void)
+{
+ const size_t request_size = 1024;
+ size_t allocated_size;
+ char *data_ptr = rte_malloc(NULL, request_size, RTE_CACHE_LINE_SIZE);
+#ifdef RTE_MALLOC_DEBUG
+ int retval;
+ char *over_write_vals = NULL;
+#endif
+
+ if (data_ptr == NULL) {
+ printf("%s: %d - Allocation error\n", __func__, __LINE__);
+ return -1;
+ }
+
+ /* check that a null input returns -1 */
+ if (rte_malloc_validate(NULL, NULL) != -1)
+ err_return();
+
+ /* check that we get ok on a valid pointer */
+ if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
+ err_return();
+
+ /* check that the returned size is ok */
+ if (allocated_size < request_size)
+ err_return();
+
+#ifdef RTE_MALLOC_DEBUG
+
+ /****** change the header to be bad */
+ char save_buf[64];
+ over_write_vals = (char *)((uintptr_t)data_ptr - sizeof(save_buf));
+ /* first save the data as a backup before overwriting it */
+ memcpy(save_buf, over_write_vals, sizeof(save_buf));
+ memset(over_write_vals, 1, sizeof(save_buf));
+ /* then run validate */
+ retval = rte_malloc_validate(data_ptr, NULL);
+ /* finally restore the data again */
+ memcpy(over_write_vals, save_buf, sizeof(save_buf));
+ /* check we previously had an error */
+ if (retval != -1)
+ err_return();
+
+ /* check all ok again */
+ if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
+ err_return();
+
+ /**** change the trailer to be bad */
+ over_write_vals = (char *)((uintptr_t)data_ptr + allocated_size);
+ /* first save the data as a backup before overwriting it */
+ memcpy(save_buf, over_write_vals, sizeof(save_buf));
+ memset(over_write_vals, 1, sizeof(save_buf));
+ /* then run validate */
+ retval = rte_malloc_validate(data_ptr, NULL);
+ /* finally restore the data again */
+ memcpy(over_write_vals, save_buf, sizeof(save_buf));
+ if (retval != -1)
+ err_return();
+
+ /* check all ok again */
+ if (rte_malloc_validate(data_ptr, &allocated_size) < 0)
+ err_return();
+#endif
+
+ rte_free(data_ptr);
+ return 0;
+
+err_return:
+ /*clean up */
+ rte_free(data_ptr);
+ return -1;
+}
+
+static int
+test_zero_aligned_alloc(void)
+{
+ char *p1 = rte_malloc(NULL,1024, 0);
+ if (!p1)
+ goto err_return;
+ if (!rte_is_aligned(p1, RTE_CACHE_LINE_SIZE))
+ goto err_return;
+ rte_free(p1);
+ return 0;
+
+err_return:
+ /*clean up */
+ if (p1) rte_free(p1);
+ return -1;
+}
+
+static int
+test_malloc_bad_params(void)
+{
+ const char *type = NULL;
+ size_t size = 0;
+ unsigned align = RTE_CACHE_LINE_SIZE;
+
+ /* rte_malloc expected to return null with inappropriate size */
+ char *bad_ptr = rte_malloc(type, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ /* rte_realloc expected to return null with inappropriate size */
+ bad_ptr = rte_realloc(NULL, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ /* rte_malloc expected to return null with inappropriate alignment */
+ align = 17;
+ size = 1024;
+
+ bad_ptr = rte_malloc(type, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ /* rte_realloc expected to return null with inappropriate alignment */
+ bad_ptr = rte_realloc(NULL, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ /* rte_malloc expected to return null with size will cause overflow */
+ align = RTE_CACHE_LINE_SIZE;
+ size = (size_t)-8;
+
+ bad_ptr = rte_malloc(type, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ bad_ptr = rte_realloc(NULL, size, align);
+ if (bad_ptr != NULL)
+ goto err_return;
+
+ return 0;
+
+err_return:
+ /* clean up pointer */
+ if (bad_ptr)
+ rte_free(bad_ptr);
+ return -1;
+}
+
+static int
+check_socket_mem(const struct rte_memseg_list *msl, void *arg)
+{
+ int32_t *socket = arg;
+
+ if (msl->external)
+ return 0;
+
+ return *socket == msl->socket_id;
+}
+
+/* Check if memory is available on a specific socket */
+static int
+is_mem_on_socket(int32_t socket)
+{
+ return rte_memseg_list_walk(check_socket_mem, &socket);
+}
+
+
+/*
+ * Find what socket a memory address is on. Only works for addresses within
+ * memsegs, not heap or stack...
+ */
+static int32_t
+addr_to_socket(void * addr)
+{
+ const struct rte_memseg *ms = rte_mem_virt2memseg(addr, NULL);
+ return ms == NULL ? -1 : ms->socket_id;
+
+}
+
+/* Test using rte_[c|m|zm]alloc_socket() on a specific socket */
+static int
+test_alloc_single_socket(int32_t socket)
+{
+ const char *type = NULL;
+ const size_t size = 10;
+ const unsigned align = 0;
+ char *mem = NULL;
+ int32_t desired_socket = (socket == SOCKET_ID_ANY) ?
+ (int32_t)rte_socket_id() : socket;
+
+ /* Test rte_calloc_socket() */
+ mem = rte_calloc_socket(type, size, sizeof(char), align, socket);
+ if (mem == NULL)
+ return -1;
+ if (addr_to_socket(mem) != desired_socket) {
+ rte_free(mem);
+ return -1;
+ }
+ rte_free(mem);
+
+ /* Test rte_malloc_socket() */
+ mem = rte_malloc_socket(type, size, align, socket);
+ if (mem == NULL)
+ return -1;
+ if (addr_to_socket(mem) != desired_socket) {
+ return -1;
+ }
+ rte_free(mem);
+
+ /* Test rte_zmalloc_socket() */
+ mem = rte_zmalloc_socket(type, size, align, socket);
+ if (mem == NULL)
+ return -1;
+ if (addr_to_socket(mem) != desired_socket) {
+ rte_free(mem);
+ return -1;
+ }
+ rte_free(mem);
+
+ return 0;
+}
+
+static int
+test_alloc_socket(void)
+{
+ unsigned socket_count = 0;
+ unsigned i;
+
+ if (test_alloc_single_socket(SOCKET_ID_ANY) < 0)
+ return -1;
+
+ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) {
+ if (is_mem_on_socket(i)) {
+ socket_count++;
+ if (test_alloc_single_socket(i) < 0) {
+ printf("Fail: rte_malloc_socket(..., %u) did not succeed\n",
+ i);
+ return -1;
+ }
+ }
+ else {
+ if (test_alloc_single_socket(i) == 0) {
+ printf("Fail: rte_malloc_socket(..., %u) succeeded\n",
+ i);
+ return -1;
+ }
+ }
+ }
+
+ /* Print warnign if only a single socket, but don't fail the test */
+ if (socket_count < 2) {
+ printf("WARNING: alloc_socket test needs memory on multiple sockets!\n");
+ }
+
+ return 0;
+}
+
+static int
+test_malloc(void)
+{
+ unsigned lcore_id;
+ int ret = 0;
+
+ if (test_str_to_size() < 0){
+ printf("test_str_to_size() failed\n");
+ return -1;
+ }
+ else printf("test_str_to_size() passed\n");
+
+ if (test_zero_aligned_alloc() < 0){
+ printf("test_zero_aligned_alloc() failed\n");
+ return -1;
+ }
+ else printf("test_zero_aligned_alloc() passed\n");
+
+ if (test_malloc_bad_params() < 0){
+ printf("test_malloc_bad_params() failed\n");
+ return -1;
+ }
+ else printf("test_malloc_bad_params() passed\n");
+
+ if (test_realloc() < 0){
+ printf("test_realloc() failed\n");
+ return -1;
+ }
+ else printf("test_realloc() passed\n");
+
+ /*----------------------------*/
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id);
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ ret = -1;
+ }
+ if (ret < 0){
+ printf("test_align_overlap_per_lcore() failed\n");
+ return ret;
+ }
+ else printf("test_align_overlap_per_lcore() passed\n");
+
+ /*----------------------------*/
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id);
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ ret = -1;
+ }
+ if (ret < 0){
+ printf("test_reordered_free_per_lcore() failed\n");
+ return ret;
+ }
+ else printf("test_reordered_free_per_lcore() passed\n");
+
+ /*----------------------------*/
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id);
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ ret = -1;
+ }
+ if (ret < 0){
+ printf("test_random_alloc_free() failed\n");
+ return ret;
+ }
+ else printf("test_random_alloc_free() passed\n");
+
+ /*----------------------------*/
+ ret = test_rte_malloc_validate();
+ if (ret < 0){
+ printf("test_rte_malloc_validate() failed\n");
+ return ret;
+ }
+ else printf("test_rte_malloc_validate() passed\n");
+
+ ret = test_alloc_socket();
+ if (ret < 0){
+ printf("test_alloc_socket() failed\n");
+ return ret;
+ }
+ else printf("test_alloc_socket() passed\n");
+
+ ret = test_multi_alloc_statistics();
+ if (ret < 0) {
+ printf("test_multi_alloc_statistics() failed\n");
+ return ret;
+ }
+ else
+ printf("test_multi_alloc_statistics() passed\n");
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(malloc_autotest, test_malloc);
diff --git a/src/spdk/dpdk/app/test/test_mbuf.c b/src/spdk/dpdk/app/test/test_mbuf.c
new file mode 100644
index 000000000..71bdab691
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_mbuf.c
@@ -0,0 +1,2877 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_random.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_mbuf_dyn.h>
+
+#include "test.h"
+
+#define MEMPOOL_CACHE_SIZE 32
+#define MBUF_DATA_SIZE 2048
+#define NB_MBUF 128
+#define MBUF_TEST_DATA_LEN 1464
+#define MBUF_TEST_DATA_LEN2 50
+#define MBUF_TEST_DATA_LEN3 256
+#define MBUF_TEST_HDR1_LEN 20
+#define MBUF_TEST_HDR2_LEN 30
+#define MBUF_TEST_ALL_HDRS_LEN (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
+#define MBUF_TEST_SEG_SIZE 64
+#define MBUF_TEST_BURST 8
+#define EXT_BUF_TEST_DATA_LEN 1024
+#define MBUF_MAX_SEG 16
+#define MBUF_NO_HEADER 0
+#define MBUF_HEADER 1
+#define MBUF_NEG_TEST_READ 2
+#define VAL_NAME(flag) { flag, #flag }
+
+/* chain length in bulk test */
+#define CHAIN_LEN 16
+
+/* size of private data for mbuf in pktmbuf_pool2 */
+#define MBUF2_PRIV_SIZE 128
+
+#define REFCNT_MAX_ITER 64
+#define REFCNT_MAX_TIMEOUT 10
+#define REFCNT_MAX_REF (RTE_MAX_LCORE)
+#define REFCNT_MBUF_NUM 64
+#define REFCNT_RING_SIZE (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
+
+#define MAGIC_DATA 0x42424242
+
+#define MAKE_STRING(x) # x
+
+#ifdef RTE_MBUF_REFCNT_ATOMIC
+
+static volatile uint32_t refcnt_stop_slaves;
+static unsigned refcnt_lcore[RTE_MAX_LCORE];
+
+#endif
+
+/*
+ * MBUF
+ * ====
+ *
+ * #. Allocate a mbuf pool.
+ *
+ * - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
+ * bytes long.
+ *
+ * #. Test multiple allocations of mbufs from this pool.
+ *
+ * - Allocate NB_MBUF and store pointers in a table.
+ * - If an allocation fails, return an error.
+ * - Free all these mbufs.
+ * - Repeat the same test to check that mbufs were freed correctly.
+ *
+ * #. Test data manipulation in pktmbuf.
+ *
+ * - Alloc an mbuf.
+ * - Append data using rte_pktmbuf_append().
+ * - Test for error in rte_pktmbuf_append() when len is too large.
+ * - Trim data at the end of mbuf using rte_pktmbuf_trim().
+ * - Test for error in rte_pktmbuf_trim() when len is too large.
+ * - Prepend a header using rte_pktmbuf_prepend().
+ * - Test for error in rte_pktmbuf_prepend() when len is too large.
+ * - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
+ * - Test for error in rte_pktmbuf_adj() when len is too large.
+ * - Check that appended data is not corrupt.
+ * - Free the mbuf.
+ * - Between all these tests, check data_len and pkt_len, and
+ * that the mbuf is contiguous.
+ * - Repeat the test to check that allocation operations
+ * reinitialize the mbuf correctly.
+ *
+ * #. Test packet cloning
+ * - Clone a mbuf and verify the data
+ * - Clone the cloned mbuf and verify the data
+ * - Attach a mbuf to another that does not have the same priv_size.
+ */
+
+#define GOTO_FAIL(str, ...) do { \
+ printf("mbuf test FAILED (l.%d): <" str ">\n", \
+ __LINE__, ##__VA_ARGS__); \
+ goto fail; \
+} while(0)
+
+/*
+ * test data manipulation in mbuf with non-ascii data
+ */
+static int
+test_pktmbuf_with_non_ascii_data(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ char *data;
+
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("Cannot allocate mbuf");
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("Bad length");
+
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
+ if (data == NULL)
+ GOTO_FAIL("Cannot append data");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad data length");
+ memset(data, 0xff, rte_pktmbuf_pkt_len(m));
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+ rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
+
+ rte_pktmbuf_free(m);
+
+ return 0;
+
+fail:
+ if(m) {
+ rte_pktmbuf_free(m);
+ }
+ return -1;
+}
+
+/*
+ * test data manipulation in mbuf
+ */
+static int
+test_one_pktmbuf(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ char *data, *data2, *hdr;
+ unsigned i;
+
+ printf("Test pktmbuf API\n");
+
+ /* alloc a mbuf */
+
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("Cannot allocate mbuf");
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("Bad length");
+
+ rte_pktmbuf_dump(stdout, m, 0);
+
+ /* append data */
+
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
+ if (data == NULL)
+ GOTO_FAIL("Cannot append data");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad data length");
+ memset(data, 0x66, rte_pktmbuf_pkt_len(m));
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+ rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
+ rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
+
+ /* this append should fail */
+
+ data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
+ if (data2 != NULL)
+ GOTO_FAIL("Append should not succeed");
+
+ /* append some more data */
+
+ data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
+ if (data2 == NULL)
+ GOTO_FAIL("Cannot append data");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("Bad data length");
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+
+ /* trim data at the end of mbuf */
+
+ if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
+ GOTO_FAIL("Cannot trim data");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad data length");
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+
+ /* this trim should fail */
+
+ if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
+ GOTO_FAIL("trim should not succeed");
+
+ /* prepend one header */
+
+ hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
+ if (hdr == NULL)
+ GOTO_FAIL("Cannot prepend");
+ if (data - hdr != MBUF_TEST_HDR1_LEN)
+ GOTO_FAIL("Prepend failed");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
+ GOTO_FAIL("Bad data length");
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+ memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
+
+ /* prepend another header */
+
+ hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
+ if (hdr == NULL)
+ GOTO_FAIL("Cannot prepend");
+ if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
+ GOTO_FAIL("Prepend failed");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
+ GOTO_FAIL("Bad data length");
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+ memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
+
+ rte_mbuf_sanity_check(m, 1);
+ rte_mbuf_sanity_check(m, 0);
+ rte_pktmbuf_dump(stdout, m, 0);
+
+ /* this prepend should fail */
+
+ hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
+ if (hdr != NULL)
+ GOTO_FAIL("prepend should not succeed");
+
+ /* remove data at beginning of mbuf (adj) */
+
+ if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
+ GOTO_FAIL("rte_pktmbuf_adj failed");
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad pkt length");
+ if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
+ GOTO_FAIL("Bad data length");
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+
+ /* this adj should fail */
+
+ if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
+ GOTO_FAIL("rte_pktmbuf_adj should not succeed");
+
+ /* check data */
+
+ if (!rte_pktmbuf_is_contiguous(m))
+ GOTO_FAIL("Buffer should be continuous");
+
+ for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
+ if (data[i] != 0x66)
+ GOTO_FAIL("Data corrupted at offset %u", i);
+ }
+
+ /* free mbuf */
+
+ rte_pktmbuf_free(m);
+ m = NULL;
+ return 0;
+
+fail:
+ if (m)
+ rte_pktmbuf_free(m);
+ return -1;
+}
+
+static uint16_t
+testclone_refcnt_read(struct rte_mbuf *m)
+{
+ return RTE_MBUF_HAS_PINNED_EXTBUF(m) ?
+ rte_mbuf_ext_refcnt_read(m->shinfo) :
+ rte_mbuf_refcnt_read(m);
+}
+
+static int
+testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool,
+ struct rte_mempool *clone_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct rte_mbuf *clone = NULL;
+ struct rte_mbuf *clone2 = NULL;
+ unaligned_uint32_t *data;
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("ooops not allocating mbuf");
+
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("Bad length");
+
+ rte_pktmbuf_append(m, sizeof(uint32_t));
+ data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
+ *data = MAGIC_DATA;
+
+ /* clone the allocated mbuf */
+ clone = rte_pktmbuf_clone(m, clone_pool);
+ if (clone == NULL)
+ GOTO_FAIL("cannot clone data\n");
+
+ data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone\n");
+
+ if (testclone_refcnt_read(m) != 2)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ /* free the clone */
+ rte_pktmbuf_free(clone);
+ clone = NULL;
+
+ /* same test with a chained mbuf */
+ m->next = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m->next == NULL)
+ GOTO_FAIL("Next Pkt Null\n");
+ m->nb_segs = 2;
+
+ rte_pktmbuf_append(m->next, sizeof(uint32_t));
+ m->pkt_len = 2 * sizeof(uint32_t);
+
+ data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
+ *data = MAGIC_DATA;
+
+ clone = rte_pktmbuf_clone(m, clone_pool);
+ if (clone == NULL)
+ GOTO_FAIL("cannot clone data\n");
+
+ data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone\n");
+
+ data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone->next\n");
+
+ if (testclone_refcnt_read(m) != 2)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ if (testclone_refcnt_read(m->next) != 2)
+ GOTO_FAIL("invalid refcnt in m->next\n");
+
+ /* try to clone the clone */
+
+ clone2 = rte_pktmbuf_clone(clone, clone_pool);
+ if (clone2 == NULL)
+ GOTO_FAIL("cannot clone the clone\n");
+
+ data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone2\n");
+
+ data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone2->next\n");
+
+ if (testclone_refcnt_read(m) != 3)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ if (testclone_refcnt_read(m->next) != 3)
+ GOTO_FAIL("invalid refcnt in m->next\n");
+
+ /* free mbuf */
+ rte_pktmbuf_free(m);
+ rte_pktmbuf_free(clone);
+ rte_pktmbuf_free(clone2);
+
+ m = NULL;
+ clone = NULL;
+ clone2 = NULL;
+ printf("%s ok\n", __func__);
+ return 0;
+
+fail:
+ if (m)
+ rte_pktmbuf_free(m);
+ if (clone)
+ rte_pktmbuf_free(clone);
+ if (clone2)
+ rte_pktmbuf_free(clone2);
+ return -1;
+}
+
+static int
+test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool,
+ struct rte_mempool *clone_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct rte_mbuf *copy = NULL;
+ struct rte_mbuf *copy2 = NULL;
+ struct rte_mbuf *clone = NULL;
+ unaligned_uint32_t *data;
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("ooops not allocating mbuf");
+
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("Bad length");
+
+ rte_pktmbuf_append(m, sizeof(uint32_t));
+ data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
+ *data = MAGIC_DATA;
+
+ /* copy the allocated mbuf */
+ copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
+ if (copy == NULL)
+ GOTO_FAIL("cannot copy data\n");
+
+ if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
+ GOTO_FAIL("copy length incorrect\n");
+
+ if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
+ GOTO_FAIL("copy data length incorrect\n");
+
+ data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in copy\n");
+
+ /* free the copy */
+ rte_pktmbuf_free(copy);
+ copy = NULL;
+
+ /* same test with a cloned mbuf */
+ clone = rte_pktmbuf_clone(m, clone_pool);
+ if (clone == NULL)
+ GOTO_FAIL("cannot clone data\n");
+
+ if ((!RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
+ !RTE_MBUF_CLONED(clone)) ||
+ (RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
+ !RTE_MBUF_HAS_EXTBUF(clone)))
+ GOTO_FAIL("clone did not give a cloned mbuf\n");
+
+ copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
+ if (copy == NULL)
+ GOTO_FAIL("cannot copy cloned mbuf\n");
+
+ if (RTE_MBUF_CLONED(copy))
+ GOTO_FAIL("copy of clone is cloned?\n");
+
+ if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
+ GOTO_FAIL("copy clone length incorrect\n");
+
+ if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
+ GOTO_FAIL("copy clone data length incorrect\n");
+
+ data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
+ if (*data != MAGIC_DATA)
+ GOTO_FAIL("invalid data in clone copy\n");
+ rte_pktmbuf_free(clone);
+ rte_pktmbuf_free(copy);
+ copy = NULL;
+ clone = NULL;
+
+
+ /* same test with a chained mbuf */
+ m->next = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m->next == NULL)
+ GOTO_FAIL("Next Pkt Null\n");
+ m->nb_segs = 2;
+
+ rte_pktmbuf_append(m->next, sizeof(uint32_t));
+ m->pkt_len = 2 * sizeof(uint32_t);
+ data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
+ *data = MAGIC_DATA + 1;
+
+ copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
+ if (copy == NULL)
+ GOTO_FAIL("cannot copy data\n");
+
+ if (rte_pktmbuf_pkt_len(copy) != 2 * sizeof(uint32_t))
+ GOTO_FAIL("chain copy length incorrect\n");
+
+ if (rte_pktmbuf_data_len(copy) != 2 * sizeof(uint32_t))
+ GOTO_FAIL("chain copy data length incorrect\n");
+
+ data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
+ if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA + 1)
+ GOTO_FAIL("invalid data in copy\n");
+
+ rte_pktmbuf_free(copy2);
+
+ /* test offset copy */
+ copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
+ sizeof(uint32_t), UINT32_MAX);
+ if (copy2 == NULL)
+ GOTO_FAIL("cannot copy the copy\n");
+
+ if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
+ GOTO_FAIL("copy with offset, length incorrect\n");
+
+ if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
+ GOTO_FAIL("copy with offset, data length incorrect\n");
+
+ data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
+ if (data[0] != MAGIC_DATA + 1)
+ GOTO_FAIL("copy with offset, invalid data\n");
+
+ rte_pktmbuf_free(copy2);
+
+ /* test truncation copy */
+ copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
+ 0, sizeof(uint32_t));
+ if (copy2 == NULL)
+ GOTO_FAIL("cannot copy the copy\n");
+
+ if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
+ GOTO_FAIL("copy with truncate, length incorrect\n");
+
+ if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
+ GOTO_FAIL("copy with truncate, data length incorrect\n");
+
+ data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
+ if (data[0] != MAGIC_DATA)
+ GOTO_FAIL("copy with truncate, invalid data\n");
+
+ /* free mbuf */
+ rte_pktmbuf_free(m);
+ rte_pktmbuf_free(copy);
+ rte_pktmbuf_free(copy2);
+
+ m = NULL;
+ copy = NULL;
+ copy2 = NULL;
+ printf("%s ok\n", __func__);
+ return 0;
+
+fail:
+ if (m)
+ rte_pktmbuf_free(m);
+ if (copy)
+ rte_pktmbuf_free(copy);
+ if (copy2)
+ rte_pktmbuf_free(copy2);
+ return -1;
+}
+
+static int
+test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
+ struct rte_mempool *pktmbuf_pool2)
+{
+ struct rte_mbuf *m = NULL;
+ struct rte_mbuf *clone = NULL;
+ struct rte_mbuf *clone2 = NULL;
+ char *data, *c_data, *c_data2;
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("cannot allocate mbuf");
+
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("Bad length");
+
+ data = rte_pktmbuf_mtod(m, char *);
+
+ /* allocate a new mbuf from the second pool, and attach it to the first
+ * mbuf */
+ clone = rte_pktmbuf_alloc(pktmbuf_pool2);
+ if (clone == NULL)
+ GOTO_FAIL("cannot allocate mbuf from second pool\n");
+
+ /* check data room size and priv size, and erase priv */
+ if (rte_pktmbuf_data_room_size(clone->pool) != 0)
+ GOTO_FAIL("data room size should be 0\n");
+ if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
+ GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
+ memset(clone + 1, 0, MBUF2_PRIV_SIZE);
+
+ /* save data pointer to compare it after detach() */
+ c_data = rte_pktmbuf_mtod(clone, char *);
+ if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
+ GOTO_FAIL("bad data pointer in clone");
+ if (rte_pktmbuf_headroom(clone) != 0)
+ GOTO_FAIL("bad headroom in clone");
+
+ rte_pktmbuf_attach(clone, m);
+
+ if (rte_pktmbuf_mtod(clone, char *) != data)
+ GOTO_FAIL("clone was not attached properly\n");
+ if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
+ GOTO_FAIL("bad headroom in clone after attach");
+ if (rte_mbuf_refcnt_read(m) != 2)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ /* allocate a new mbuf from the second pool, and attach it to the first
+ * cloned mbuf */
+ clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
+ if (clone2 == NULL)
+ GOTO_FAIL("cannot allocate clone2 from second pool\n");
+
+ /* check data room size and priv size, and erase priv */
+ if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
+ GOTO_FAIL("data room size should be 0\n");
+ if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
+ GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
+ memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
+
+ /* save data pointer to compare it after detach() */
+ c_data2 = rte_pktmbuf_mtod(clone2, char *);
+ if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
+ GOTO_FAIL("bad data pointer in clone2");
+ if (rte_pktmbuf_headroom(clone2) != 0)
+ GOTO_FAIL("bad headroom in clone2");
+
+ rte_pktmbuf_attach(clone2, clone);
+
+ if (rte_pktmbuf_mtod(clone2, char *) != data)
+ GOTO_FAIL("clone2 was not attached properly\n");
+ if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
+ GOTO_FAIL("bad headroom in clone2 after attach");
+ if (rte_mbuf_refcnt_read(m) != 3)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ /* detach the clones */
+ rte_pktmbuf_detach(clone);
+ if (c_data != rte_pktmbuf_mtod(clone, char *))
+ GOTO_FAIL("clone was not detached properly\n");
+ if (rte_mbuf_refcnt_read(m) != 2)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ rte_pktmbuf_detach(clone2);
+ if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
+ GOTO_FAIL("clone2 was not detached properly\n");
+ if (rte_mbuf_refcnt_read(m) != 1)
+ GOTO_FAIL("invalid refcnt in m\n");
+
+ /* free the clones and the initial mbuf */
+ rte_pktmbuf_free(clone2);
+ rte_pktmbuf_free(clone);
+ rte_pktmbuf_free(m);
+ printf("%s ok\n", __func__);
+ return 0;
+
+fail:
+ if (m)
+ rte_pktmbuf_free(m);
+ if (clone)
+ rte_pktmbuf_free(clone);
+ if (clone2)
+ rte_pktmbuf_free(clone2);
+ return -1;
+}
+
+/*
+ * test allocation and free of mbufs
+ */
+static int
+test_pktmbuf_pool(struct rte_mempool *pktmbuf_pool)
+{
+ unsigned i;
+ struct rte_mbuf *m[NB_MBUF];
+ int ret = 0;
+
+ for (i=0; i<NB_MBUF; i++)
+ m[i] = NULL;
+
+ /* alloc NB_MBUF mbufs */
+ for (i=0; i<NB_MBUF; i++) {
+ m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m[i] == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ ret = -1;
+ }
+ }
+ struct rte_mbuf *extra = NULL;
+ extra = rte_pktmbuf_alloc(pktmbuf_pool);
+ if(extra != NULL) {
+ printf("Error pool not empty");
+ ret = -1;
+ }
+ extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
+ if(extra != NULL) {
+ printf("Error pool not empty");
+ ret = -1;
+ }
+ /* free them */
+ for (i=0; i<NB_MBUF; i++) {
+ if (m[i] != NULL)
+ rte_pktmbuf_free(m[i]);
+ }
+
+ return ret;
+}
+
+/*
+ * test bulk allocation and bulk free of mbufs
+ */
+static int
+test_pktmbuf_pool_bulk(void)
+{
+ struct rte_mempool *pool = NULL;
+ struct rte_mempool *pool2 = NULL;
+ unsigned int i;
+ struct rte_mbuf *m;
+ struct rte_mbuf *mbufs[NB_MBUF];
+ int ret = 0;
+
+ /* We cannot use the preallocated mbuf pools because their caches
+ * prevent us from bulk allocating all objects in them.
+ * So we create our own mbuf pools without caches.
+ */
+ printf("Create mbuf pools for bulk allocation.\n");
+ pool = rte_pktmbuf_pool_create("test_pktmbuf_bulk",
+ NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
+ if (pool == NULL) {
+ printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
+ rte_errno);
+ goto err;
+ }
+ pool2 = rte_pktmbuf_pool_create("test_pktmbuf_bulk2",
+ NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
+ if (pool2 == NULL) {
+ printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
+ rte_errno);
+ goto err;
+ }
+
+ /* Preconditions: Mempools must be full. */
+ if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
+ printf("Test precondition failed: mempools not full\n");
+ goto err;
+ }
+ if (!(rte_mempool_avail_count(pool) == NB_MBUF &&
+ rte_mempool_avail_count(pool2) == NB_MBUF)) {
+ printf("Test precondition failed: mempools: %u+%u != %u+%u",
+ rte_mempool_avail_count(pool),
+ rte_mempool_avail_count(pool2),
+ NB_MBUF, NB_MBUF);
+ goto err;
+ }
+
+ printf("Test single bulk alloc, followed by multiple bulk free.\n");
+
+ /* Bulk allocate all mbufs in the pool, in one go. */
+ ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ /* Test that they have been removed from the pool. */
+ if (!rte_mempool_empty(pool)) {
+ printf("mempool not empty\n");
+ goto err;
+ }
+ /* Bulk free all mbufs, in four steps. */
+ RTE_BUILD_BUG_ON(NB_MBUF % 4 != 0);
+ for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
+ rte_pktmbuf_free_bulk(&mbufs[i], NB_MBUF / 4);
+ /* Test that they have been returned to the pool. */
+ if (rte_mempool_avail_count(pool) != i + NB_MBUF / 4) {
+ printf("mempool avail count incorrect\n");
+ goto err;
+ }
+ }
+
+ printf("Test multiple bulk alloc, followed by single bulk free.\n");
+
+ /* Bulk allocate all mbufs in the pool, in four steps. */
+ for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
+ ret = rte_pktmbuf_alloc_bulk(pool, &mbufs[i], NB_MBUF / 4);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ }
+ /* Test that they have been removed from the pool. */
+ if (!rte_mempool_empty(pool)) {
+ printf("mempool not empty\n");
+ goto err;
+ }
+ /* Bulk free all mbufs, in one go. */
+ rte_pktmbuf_free_bulk(mbufs, NB_MBUF);
+ /* Test that they have been returned to the pool. */
+ if (!rte_mempool_full(pool)) {
+ printf("mempool not full\n");
+ goto err;
+ }
+
+ printf("Test bulk free of single long chain.\n");
+
+ /* Bulk allocate all mbufs in the pool, in one go. */
+ ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
+ if (ret != 0) {
+ printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
+ goto err;
+ }
+ /* Create a long mbuf chain. */
+ for (i = 1; i < NB_MBUF; i++) {
+ ret = rte_pktmbuf_chain(mbufs[0], mbufs[i]);
+ if (ret != 0) {
+ printf("rte_pktmbuf_chain() failed: %d\n", ret);
+ goto err;
+ }
+ mbufs[i] = NULL;
+ }
+ /* Free the mbuf chain containing all the mbufs. */
+ rte_pktmbuf_free_bulk(mbufs, 1);
+ /* Test that they have been returned to the pool. */
+ if (!rte_mempool_full(pool)) {
+ printf("mempool not full\n");
+ goto err;
+ }
+
+ printf("Test bulk free of multiple chains using multiple pools.\n");
+
+ /* Create mbuf chains containing mbufs from different pools. */
+ RTE_BUILD_BUG_ON(CHAIN_LEN % 2 != 0);
+ RTE_BUILD_BUG_ON(NB_MBUF % (CHAIN_LEN / 2) != 0);
+ for (i = 0; i < NB_MBUF * 2; i++) {
+ m = rte_pktmbuf_alloc((i & 4) ? pool2 : pool);
+ if (m == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ goto err;
+ }
+ if ((i % CHAIN_LEN) == 0)
+ mbufs[i / CHAIN_LEN] = m;
+ else
+ rte_pktmbuf_chain(mbufs[i / CHAIN_LEN], m);
+ }
+ /* Test that both pools have been emptied. */
+ if (!(rte_mempool_empty(pool) && rte_mempool_empty(pool2))) {
+ printf("mempools not empty\n");
+ goto err;
+ }
+ /* Free one mbuf chain. */
+ rte_pktmbuf_free_bulk(mbufs, 1);
+ /* Test that the segments have been returned to the pools. */
+ if (!(rte_mempool_avail_count(pool) == CHAIN_LEN / 2 &&
+ rte_mempool_avail_count(pool2) == CHAIN_LEN / 2)) {
+ printf("all segments of first mbuf have not been returned\n");
+ goto err;
+ }
+ /* Free the remaining mbuf chains. */
+ rte_pktmbuf_free_bulk(&mbufs[1], NB_MBUF * 2 / CHAIN_LEN - 1);
+ /* Test that they have been returned to the pools. */
+ if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
+ printf("mempools not full\n");
+ goto err;
+ }
+
+ ret = 0;
+ goto done;
+
+err:
+ ret = -1;
+
+done:
+ printf("Free mbuf pools for bulk allocation.\n");
+ rte_mempool_free(pool);
+ rte_mempool_free(pool2);
+ return ret;
+}
+
+/*
+ * test that the pointer to the data on a packet mbuf is set properly
+ */
+static int
+test_pktmbuf_pool_ptr(struct rte_mempool *pktmbuf_pool)
+{
+ unsigned i;
+ struct rte_mbuf *m[NB_MBUF];
+ int ret = 0;
+
+ for (i=0; i<NB_MBUF; i++)
+ m[i] = NULL;
+
+ /* alloc NB_MBUF mbufs */
+ for (i=0; i<NB_MBUF; i++) {
+ m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m[i] == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ ret = -1;
+ break;
+ }
+ m[i]->data_off += 64;
+ }
+
+ /* free them */
+ for (i=0; i<NB_MBUF; i++) {
+ if (m[i] != NULL)
+ rte_pktmbuf_free(m[i]);
+ }
+
+ for (i=0; i<NB_MBUF; i++)
+ m[i] = NULL;
+
+ /* alloc NB_MBUF mbufs */
+ for (i=0; i<NB_MBUF; i++) {
+ m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m[i] == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ ret = -1;
+ break;
+ }
+ if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
+ printf("invalid data_off\n");
+ ret = -1;
+ }
+ }
+
+ /* free them */
+ for (i=0; i<NB_MBUF; i++) {
+ if (m[i] != NULL)
+ rte_pktmbuf_free(m[i]);
+ }
+
+ return ret;
+}
+
+static int
+test_pktmbuf_free_segment(struct rte_mempool *pktmbuf_pool)
+{
+ unsigned i;
+ struct rte_mbuf *m[NB_MBUF];
+ int ret = 0;
+
+ for (i=0; i<NB_MBUF; i++)
+ m[i] = NULL;
+
+ /* alloc NB_MBUF mbufs */
+ for (i=0; i<NB_MBUF; i++) {
+ m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m[i] == NULL) {
+ printf("rte_pktmbuf_alloc() failed (%u)\n", i);
+ ret = -1;
+ }
+ }
+
+ /* free them */
+ for (i=0; i<NB_MBUF; i++) {
+ if (m[i] != NULL) {
+ struct rte_mbuf *mb, *mt;
+
+ mb = m[i];
+ while(mb != NULL) {
+ mt = mb;
+ mb = mb->next;
+ rte_pktmbuf_free_seg(mt);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Stress test for rte_mbuf atomic refcnt.
+ * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
+ * For more efficiency, recommended to run with RTE_LIBRTE_MBUF_DEBUG defined.
+ */
+
+#ifdef RTE_MBUF_REFCNT_ATOMIC
+
+static int
+test_refcnt_slave(void *arg)
+{
+ unsigned lcore, free;
+ void *mp = 0;
+ struct rte_ring *refcnt_mbuf_ring = arg;
+
+ lcore = rte_lcore_id();
+ printf("%s started at lcore %u\n", __func__, lcore);
+
+ free = 0;
+ while (refcnt_stop_slaves == 0) {
+ if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
+ free++;
+ rte_pktmbuf_free(mp);
+ }
+ }
+
+ refcnt_lcore[lcore] += free;
+ printf("%s finished at lcore %u, "
+ "number of freed mbufs: %u\n",
+ __func__, lcore, free);
+ return 0;
+}
+
+static void
+test_refcnt_iter(unsigned int lcore, unsigned int iter,
+ struct rte_mempool *refcnt_pool,
+ struct rte_ring *refcnt_mbuf_ring)
+{
+ uint16_t ref;
+ unsigned i, n, tref, wn;
+ struct rte_mbuf *m;
+
+ tref = 0;
+
+ /* For each mbuf in the pool:
+ * - allocate mbuf,
+ * - increment it's reference up to N+1,
+ * - enqueue it N times into the ring for slave cores to free.
+ */
+ for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
+ i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
+ i++) {
+ ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
+ tref += ref;
+ if ((ref & 1) != 0) {
+ rte_pktmbuf_refcnt_update(m, ref);
+ while (ref-- != 0)
+ rte_ring_enqueue(refcnt_mbuf_ring, m);
+ } else {
+ while (ref-- != 0) {
+ rte_pktmbuf_refcnt_update(m, 1);
+ rte_ring_enqueue(refcnt_mbuf_ring, m);
+ }
+ }
+ rte_pktmbuf_free(m);
+ }
+
+ if (i != n)
+ rte_panic("(lcore=%u, iter=%u): was able to allocate only "
+ "%u from %u mbufs\n", lcore, iter, i, n);
+
+ /* wait till slave lcores will consume all mbufs */
+ while (!rte_ring_empty(refcnt_mbuf_ring))
+ ;
+
+ /* check that all mbufs are back into mempool by now */
+ for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
+ if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
+ refcnt_lcore[lcore] += tref;
+ printf("%s(lcore=%u, iter=%u) completed, "
+ "%u references processed\n",
+ __func__, lcore, iter, tref);
+ return;
+ }
+ rte_delay_ms(100);
+ }
+
+ rte_panic("(lcore=%u, iter=%u): after %us only "
+ "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
+}
+
+static int
+test_refcnt_master(struct rte_mempool *refcnt_pool,
+ struct rte_ring *refcnt_mbuf_ring)
+{
+ unsigned i, lcore;
+
+ lcore = rte_lcore_id();
+ printf("%s started at lcore %u\n", __func__, lcore);
+
+ for (i = 0; i != REFCNT_MAX_ITER; i++)
+ test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
+
+ refcnt_stop_slaves = 1;
+ rte_wmb();
+
+ printf("%s finished at lcore %u\n", __func__, lcore);
+ return 0;
+}
+
+#endif
+
+static int
+test_refcnt_mbuf(void)
+{
+#ifdef RTE_MBUF_REFCNT_ATOMIC
+ unsigned int master, slave, tref;
+ int ret = -1;
+ struct rte_mempool *refcnt_pool = NULL;
+ struct rte_ring *refcnt_mbuf_ring = NULL;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for test_refcnt_mbuf, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ printf("starting %s, at %u lcores\n", __func__, rte_lcore_count());
+
+ /* create refcnt pool & ring if they don't exist */
+
+ refcnt_pool = rte_pktmbuf_pool_create(MAKE_STRING(refcnt_pool),
+ REFCNT_MBUF_NUM, 0, 0, 0,
+ SOCKET_ID_ANY);
+ if (refcnt_pool == NULL) {
+ printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
+ __func__);
+ return -1;
+ }
+
+ refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
+ rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
+ RING_F_SP_ENQ);
+ if (refcnt_mbuf_ring == NULL) {
+ printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
+ "\n", __func__);
+ goto err;
+ }
+
+ refcnt_stop_slaves = 0;
+ memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
+
+ rte_eal_mp_remote_launch(test_refcnt_slave, refcnt_mbuf_ring,
+ SKIP_MASTER);
+
+ test_refcnt_master(refcnt_pool, refcnt_mbuf_ring);
+
+ rte_eal_mp_wait_lcore();
+
+ /* check that we porcessed all references */
+ tref = 0;
+ master = rte_get_master_lcore();
+
+ RTE_LCORE_FOREACH_SLAVE(slave)
+ tref += refcnt_lcore[slave];
+
+ if (tref != refcnt_lcore[master])
+ rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
+ tref, refcnt_lcore[master]);
+
+ rte_mempool_dump(stdout, refcnt_pool);
+ rte_ring_dump(stdout, refcnt_mbuf_ring);
+
+ ret = 0;
+
+err:
+ rte_mempool_free(refcnt_pool);
+ rte_ring_free(refcnt_mbuf_ring);
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+/* use fork() to test mbuf errors panic */
+static int
+verify_mbuf_check_panics(struct rte_mbuf *buf)
+{
+ int pid;
+ int status;
+
+ pid = fork();
+
+ if (pid == 0) {
+ rte_mbuf_sanity_check(buf, 1); /* should panic */
+ exit(0); /* return normally if it doesn't panic */
+ } else if (pid < 0){
+ printf("Fork Failed\n");
+ return -1;
+ }
+ wait(&status);
+ if(status == 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *buf;
+ struct rte_mbuf badbuf;
+
+ printf("Checking rte_mbuf_sanity_check for failure conditions\n");
+
+ /* get a good mbuf to use to make copies */
+ buf = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (buf == NULL)
+ return -1;
+
+ printf("Checking good mbuf initially\n");
+ if (verify_mbuf_check_panics(buf) != -1)
+ return -1;
+
+ printf("Now checking for error conditions\n");
+
+ if (verify_mbuf_check_panics(NULL)) {
+ printf("Error with NULL mbuf test\n");
+ return -1;
+ }
+
+ badbuf = *buf;
+ badbuf.pool = NULL;
+ if (verify_mbuf_check_panics(&badbuf)) {
+ printf("Error with bad-pool mbuf test\n");
+ return -1;
+ }
+
+ badbuf = *buf;
+ badbuf.buf_iova = 0;
+ if (verify_mbuf_check_panics(&badbuf)) {
+ printf("Error with bad-physaddr mbuf test\n");
+ return -1;
+ }
+
+ badbuf = *buf;
+ badbuf.buf_addr = NULL;
+ if (verify_mbuf_check_panics(&badbuf)) {
+ printf("Error with bad-addr mbuf test\n");
+ return -1;
+ }
+
+ badbuf = *buf;
+ badbuf.refcnt = 0;
+ if (verify_mbuf_check_panics(&badbuf)) {
+ printf("Error with bad-refcnt(0) mbuf test\n");
+ return -1;
+ }
+
+ badbuf = *buf;
+ badbuf.refcnt = UINT16_MAX;
+ if (verify_mbuf_check_panics(&badbuf)) {
+ printf("Error with bad-refcnt(MAX) mbuf test\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_mbuf_linearize(struct rte_mempool *pktmbuf_pool, int pkt_len,
+ int nb_segs)
+{
+
+ struct rte_mbuf *m = NULL, *mbuf = NULL;
+ uint8_t *data;
+ int data_len = 0;
+ int remain;
+ int seg, seg_len;
+ int i;
+
+ if (pkt_len < 1) {
+ printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+ return -1;
+ }
+
+ if (nb_segs < 1) {
+ printf("Number of segments must be 1 or more (is %d)\n",
+ nb_segs);
+ return -1;
+ }
+
+ seg_len = pkt_len / nb_segs;
+ if (seg_len == 0)
+ seg_len = 1;
+
+ remain = pkt_len;
+
+ /* Create chained mbuf_src and fill it generated data */
+ for (seg = 0; remain > 0; seg++) {
+
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL) {
+ printf("Cannot create segment for source mbuf");
+ goto fail;
+ }
+
+ /* Make sure if tailroom is zeroed */
+ memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+ rte_pktmbuf_tailroom(m));
+
+ data_len = remain;
+ if (data_len > seg_len)
+ data_len = seg_len;
+
+ data = (uint8_t *)rte_pktmbuf_append(m, data_len);
+ if (data == NULL) {
+ printf("Cannot append %d bytes to the mbuf\n",
+ data_len);
+ goto fail;
+ }
+
+ for (i = 0; i < data_len; i++)
+ data[i] = (seg * seg_len + i) % 0x0ff;
+
+ if (seg == 0)
+ mbuf = m;
+ else
+ rte_pktmbuf_chain(mbuf, m);
+
+ remain -= data_len;
+ }
+
+ /* Create destination buffer to store coalesced data */
+ if (rte_pktmbuf_linearize(mbuf)) {
+ printf("Mbuf linearization failed\n");
+ goto fail;
+ }
+
+ if (!rte_pktmbuf_is_contiguous(mbuf)) {
+ printf("Source buffer should be contiguous after "
+ "linearization\n");
+ goto fail;
+ }
+
+ data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+
+ for (i = 0; i < pkt_len; i++)
+ if (data[i] != (i % 0x0ff)) {
+ printf("Incorrect data in linearized mbuf\n");
+ goto fail;
+ }
+
+ rte_pktmbuf_free(mbuf);
+ return 0;
+
+fail:
+ if (mbuf)
+ rte_pktmbuf_free(mbuf);
+ return -1;
+}
+
+static int
+test_mbuf_linearize_check(struct rte_mempool *pktmbuf_pool)
+{
+ struct test_mbuf_array {
+ int size;
+ int nb_segs;
+ } mbuf_array[] = {
+ { 128, 1 },
+ { 64, 64 },
+ { 512, 10 },
+ { 250, 11 },
+ { 123, 8 },
+ };
+ unsigned int i;
+
+ printf("Test mbuf linearize API\n");
+
+ for (i = 0; i < RTE_DIM(mbuf_array); i++)
+ if (test_mbuf_linearize(pktmbuf_pool, mbuf_array[i].size,
+ mbuf_array[i].nb_segs)) {
+ printf("Test failed for %d, %d\n", mbuf_array[i].size,
+ mbuf_array[i].nb_segs);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Helper function for test_tx_ofload
+ */
+static inline void
+set_tx_offload(struct rte_mbuf *mb, uint64_t il2, uint64_t il3, uint64_t il4,
+ uint64_t tso, uint64_t ol3, uint64_t ol2)
+{
+ mb->l2_len = il2;
+ mb->l3_len = il3;
+ mb->l4_len = il4;
+ mb->tso_segsz = tso;
+ mb->outer_l3_len = ol3;
+ mb->outer_l2_len = ol2;
+}
+
+static int
+test_tx_offload(void)
+{
+ struct rte_mbuf *mb;
+ uint64_t tm, v1, v2;
+ size_t sz;
+ uint32_t i;
+
+ static volatile struct {
+ uint16_t l2;
+ uint16_t l3;
+ uint16_t l4;
+ uint16_t tso;
+ } txof;
+
+ const uint32_t num = 0x10000;
+
+ txof.l2 = rte_rand() % (1 << RTE_MBUF_L2_LEN_BITS);
+ txof.l3 = rte_rand() % (1 << RTE_MBUF_L3_LEN_BITS);
+ txof.l4 = rte_rand() % (1 << RTE_MBUF_L4_LEN_BITS);
+ txof.tso = rte_rand() % (1 << RTE_MBUF_TSO_SEGSZ_BITS);
+
+ printf("%s started, tx_offload = {\n"
+ "\tl2_len=%#hx,\n"
+ "\tl3_len=%#hx,\n"
+ "\tl4_len=%#hx,\n"
+ "\ttso_segsz=%#hx,\n"
+ "\touter_l3_len=%#x,\n"
+ "\touter_l2_len=%#x,\n"
+ "};\n",
+ __func__,
+ txof.l2, txof.l3, txof.l4, txof.tso, txof.l3, txof.l2);
+
+ sz = sizeof(*mb) * num;
+ mb = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
+ if (mb == NULL) {
+ printf("%s failed, out of memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ memset(mb, 0, sz);
+ tm = rte_rdtsc_precise();
+
+ for (i = 0; i != num; i++)
+ set_tx_offload(mb + i, txof.l2, txof.l3, txof.l4,
+ txof.tso, txof.l3, txof.l2);
+
+ tm = rte_rdtsc_precise() - tm;
+ printf("%s set tx_offload by bit-fields: %u iterations, %"
+ PRIu64 " cycles, %#Lf cycles/iter\n",
+ __func__, num, tm, (long double)tm / num);
+
+ v1 = mb[rte_rand() % num].tx_offload;
+
+ memset(mb, 0, sz);
+ tm = rte_rdtsc_precise();
+
+ for (i = 0; i != num; i++)
+ mb[i].tx_offload = rte_mbuf_tx_offload(txof.l2, txof.l3,
+ txof.l4, txof.tso, txof.l3, txof.l2, 0);
+
+ tm = rte_rdtsc_precise() - tm;
+ printf("%s set raw tx_offload: %u iterations, %"
+ PRIu64 " cycles, %#Lf cycles/iter\n",
+ __func__, num, tm, (long double)tm / num);
+
+ v2 = mb[rte_rand() % num].tx_offload;
+
+ rte_free(mb);
+
+ printf("%s finished\n"
+ "expected tx_offload value: 0x%" PRIx64 ";\n"
+ "rte_mbuf_tx_offload value: 0x%" PRIx64 ";\n",
+ __func__, v1, v2);
+
+ return (v1 == v2) ? 0 : -EINVAL;
+}
+
+static int
+test_get_rx_ol_flag_list(void)
+{
+ int len = 6, ret = 0;
+ char buf[256] = "";
+ int buflen = 0;
+
+ /* Test case to check with null buffer */
+ ret = rte_get_rx_ol_flag_list(0, NULL, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ /* Test case to check with zero buffer len */
+ ret = rte_get_rx_ol_flag_list(PKT_RX_L4_CKSUM_MASK, buf, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != 0)
+ GOTO_FAIL("%s buffer should be empty, received = %d\n",
+ __func__, buflen);
+
+ /* Test case to check with reduced buffer len */
+ ret = rte_get_rx_ol_flag_list(0, buf, len);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != (len - 1))
+ GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
+ "received = %d\n", __func__,
+ (len - 1), buflen);
+
+ /* Test case to check with zero mask value */
+ ret = rte_get_rx_ol_flag_list(0, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ /* Test case to check with valid mask value */
+ ret = rte_get_rx_ol_flag_list(PKT_RX_SEC_OFFLOAD, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int
+test_get_tx_ol_flag_list(void)
+{
+ int len = 6, ret = 0;
+ char buf[256] = "";
+ int buflen = 0;
+
+ /* Test case to check with null buffer */
+ ret = rte_get_tx_ol_flag_list(0, NULL, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ /* Test case to check with zero buffer len */
+ ret = rte_get_tx_ol_flag_list(PKT_TX_IP_CKSUM, buf, 0);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != 0) {
+ GOTO_FAIL("%s buffer should be empty, received = %d\n",
+ __func__, buflen);
+ }
+
+ /* Test case to check with reduced buffer len */
+ ret = rte_get_tx_ol_flag_list(0, buf, len);
+ if (ret != -1)
+ GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen != (len - 1))
+ GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
+ "received = %d\n", __func__,
+ (len - 1), buflen);
+
+ /* Test case to check with zero mask value */
+ ret = rte_get_tx_ol_flag_list(0, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ /* Test case to check with valid mask value */
+ ret = rte_get_tx_ol_flag_list(PKT_TX_UDP_CKSUM, buf, sizeof(buf));
+ if (ret != 0)
+ GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
+
+ buflen = strlen(buf);
+ if (buflen == 0)
+ GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
+ "non-zero, buffer should not be empty");
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+struct flag_name {
+ uint64_t flag;
+ const char *name;
+};
+
+static int
+test_get_rx_ol_flag_name(void)
+{
+ uint16_t i;
+ const char *flag_str = NULL;
+ const struct flag_name rx_flags[] = {
+ VAL_NAME(PKT_RX_VLAN),
+ VAL_NAME(PKT_RX_RSS_HASH),
+ VAL_NAME(PKT_RX_FDIR),
+ VAL_NAME(PKT_RX_L4_CKSUM_BAD),
+ VAL_NAME(PKT_RX_L4_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_L4_CKSUM_NONE),
+ VAL_NAME(PKT_RX_IP_CKSUM_BAD),
+ VAL_NAME(PKT_RX_IP_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_IP_CKSUM_NONE),
+ VAL_NAME(PKT_RX_EIP_CKSUM_BAD),
+ VAL_NAME(PKT_RX_VLAN_STRIPPED),
+ VAL_NAME(PKT_RX_IEEE1588_PTP),
+ VAL_NAME(PKT_RX_IEEE1588_TMST),
+ VAL_NAME(PKT_RX_FDIR_ID),
+ VAL_NAME(PKT_RX_FDIR_FLX),
+ VAL_NAME(PKT_RX_QINQ_STRIPPED),
+ VAL_NAME(PKT_RX_LRO),
+ VAL_NAME(PKT_RX_TIMESTAMP),
+ VAL_NAME(PKT_RX_SEC_OFFLOAD),
+ VAL_NAME(PKT_RX_SEC_OFFLOAD_FAILED),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_BAD),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_GOOD),
+ VAL_NAME(PKT_RX_OUTER_L4_CKSUM_INVALID),
+ };
+
+ /* Test case to check with valid flag */
+ for (i = 0; i < RTE_DIM(rx_flags); i++) {
+ flag_str = rte_get_rx_ol_flag_name(rx_flags[i].flag);
+ if (flag_str == NULL)
+ GOTO_FAIL("%s: Expected flagname = %s; received null\n",
+ __func__, rx_flags[i].name);
+ if (strcmp(flag_str, rx_flags[i].name) != 0)
+ GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
+ __func__, rx_flags[i].name, flag_str);
+ }
+ /* Test case to check with invalid flag */
+ flag_str = rte_get_rx_ol_flag_name(0);
+ if (flag_str != NULL) {
+ GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
+ __func__, flag_str);
+ }
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int
+test_get_tx_ol_flag_name(void)
+{
+ uint16_t i;
+ const char *flag_str = NULL;
+ const struct flag_name tx_flags[] = {
+ VAL_NAME(PKT_TX_VLAN),
+ VAL_NAME(PKT_TX_IP_CKSUM),
+ VAL_NAME(PKT_TX_TCP_CKSUM),
+ VAL_NAME(PKT_TX_SCTP_CKSUM),
+ VAL_NAME(PKT_TX_UDP_CKSUM),
+ VAL_NAME(PKT_TX_IEEE1588_TMST),
+ VAL_NAME(PKT_TX_TCP_SEG),
+ VAL_NAME(PKT_TX_IPV4),
+ VAL_NAME(PKT_TX_IPV6),
+ VAL_NAME(PKT_TX_OUTER_IP_CKSUM),
+ VAL_NAME(PKT_TX_OUTER_IPV4),
+ VAL_NAME(PKT_TX_OUTER_IPV6),
+ VAL_NAME(PKT_TX_TUNNEL_VXLAN),
+ VAL_NAME(PKT_TX_TUNNEL_GRE),
+ VAL_NAME(PKT_TX_TUNNEL_IPIP),
+ VAL_NAME(PKT_TX_TUNNEL_GENEVE),
+ VAL_NAME(PKT_TX_TUNNEL_MPLSINUDP),
+ VAL_NAME(PKT_TX_TUNNEL_VXLAN_GPE),
+ VAL_NAME(PKT_TX_TUNNEL_IP),
+ VAL_NAME(PKT_TX_TUNNEL_UDP),
+ VAL_NAME(PKT_TX_QINQ),
+ VAL_NAME(PKT_TX_MACSEC),
+ VAL_NAME(PKT_TX_SEC_OFFLOAD),
+ VAL_NAME(PKT_TX_UDP_SEG),
+ VAL_NAME(PKT_TX_OUTER_UDP_CKSUM),
+ };
+
+ /* Test case to check with valid flag */
+ for (i = 0; i < RTE_DIM(tx_flags); i++) {
+ flag_str = rte_get_tx_ol_flag_name(tx_flags[i].flag);
+ if (flag_str == NULL)
+ GOTO_FAIL("%s: Expected flagname = %s; received null\n",
+ __func__, tx_flags[i].name);
+ if (strcmp(flag_str, tx_flags[i].name) != 0)
+ GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
+ __func__, tx_flags[i].name, flag_str);
+ }
+ /* Test case to check with invalid flag */
+ flag_str = rte_get_tx_ol_flag_name(0);
+ if (flag_str != NULL) {
+ GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
+ __func__, flag_str);
+ }
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+static int
+test_mbuf_validate_tx_offload(const char *test_name,
+ struct rte_mempool *pktmbuf_pool,
+ uint64_t ol_flags,
+ uint16_t segsize,
+ int expected_retval)
+{
+ struct rte_mbuf *m = NULL;
+ int ret = 0;
+
+ /* alloc a mbuf and do sanity check */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+ m->ol_flags = ol_flags;
+ m->tso_segsz = segsize;
+ ret = rte_validate_tx_offload(m);
+ if (ret != expected_retval)
+ GOTO_FAIL("%s(%s): expected ret val: %d; received: %d\n",
+ __func__, test_name, expected_retval, ret);
+ rte_pktmbuf_free(m);
+ m = NULL;
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+static int
+test_mbuf_validate_tx_offload_one(struct rte_mempool *pktmbuf_pool)
+{
+ /* test to validate tx offload flags */
+ uint64_t ol_flags = 0;
+
+ /* test to validate if IP checksum is counted only for IPV4 packet */
+ /* set both IP checksum and IPV6 flags */
+ ol_flags |= PKT_TX_IP_CKSUM;
+ ol_flags |= PKT_TX_IPV6;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_CKSUM_IPV6_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP cksum is set incorrect.\n", __func__);
+ /* resetting ol_flags for next testcase */
+ ol_flags = 0;
+
+ /* test to validate if IP type is set when required */
+ ol_flags |= PKT_TX_L4_MASK;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
+
+ /* test if IP type is set when TCP SEG is on */
+ ol_flags |= PKT_TX_TCP_SEG;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm IP type (IPV4/IPV6) is set */
+ ol_flags = PKT_TX_L4_MASK;
+ ol_flags |= PKT_TX_IPV6;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_SET",
+ pktmbuf_pool,
+ ol_flags, 0, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ ol_flags = 0;
+ /* test to check TSO segment size is non-zero */
+ ol_flags |= PKT_TX_IPV4;
+ ol_flags |= PKT_TX_TCP_SEG;
+ /* set 0 tso segment size */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_NULL_TSO_SEGSZ",
+ pktmbuf_pool,
+ ol_flags, 0, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: tso segment size is null.\n", __func__);
+
+ /* retain IPV4 and PKT_TX_TCP_SEG mask */
+ /* set valid tso segment size but IP CKSUM not set */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: IP CKSUM is not set.\n", __func__);
+
+ /* test to validate if IP checksum is set for TSO capability */
+ /* retain IPV4, TCP_SEG, tso_seg size */
+ ol_flags |= PKT_TX_IP_CKSUM;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ /* test to confirm TSO for IPV6 type */
+ ol_flags = 0;
+ ol_flags |= PKT_TX_IPV6;
+ ol_flags |= PKT_TX_TCP_SEG;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IPV6_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: TSO req not met.\n", __func__);
+
+ ol_flags = 0;
+ /* test if outer IP checksum set for non outer IPv4 packet */
+ ol_flags |= PKT_TX_IPV6;
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, -EINVAL) < 0)
+ GOTO_FAIL("%s failed: Outer IP cksum set.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm outer IP checksum is set for outer IPV4 packet */
+ ol_flags |= PKT_TX_OUTER_IP_CKSUM;
+ ol_flags |= PKT_TX_OUTER_IPV4;
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+
+ ol_flags = 0;
+ /* test to confirm if packets with no TX_OFFLOAD_MASK are skipped */
+ if (test_mbuf_validate_tx_offload("MBUF_TEST_OL_MASK_NOT_SET",
+ pktmbuf_pool,
+ ol_flags, 512, 0) < 0)
+ GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
+ return 0;
+fail:
+ return -1;
+}
+
+/*
+ * Test for allocating a bulk of mbufs
+ * define an array with positive sizes for mbufs allocations.
+ */
+static int
+test_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
+{
+ int ret = 0;
+ unsigned int idx, loop;
+ unsigned int alloc_counts[] = {
+ 0,
+ MEMPOOL_CACHE_SIZE - 1,
+ MEMPOOL_CACHE_SIZE + 1,
+ MEMPOOL_CACHE_SIZE * 1.5,
+ MEMPOOL_CACHE_SIZE * 2,
+ MEMPOOL_CACHE_SIZE * 2 - 1,
+ MEMPOOL_CACHE_SIZE * 2 + 1,
+ MEMPOOL_CACHE_SIZE,
+ };
+
+ /* allocate a large array of mbuf pointers */
+ struct rte_mbuf *mbufs[NB_MBUF] = { 0 };
+ for (idx = 0; idx < RTE_DIM(alloc_counts); idx++) {
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
+ alloc_counts[idx]);
+ if (ret == 0) {
+ for (loop = 0; loop < alloc_counts[idx] &&
+ mbufs[loop] != NULL; loop++)
+ rte_pktmbuf_free(mbufs[loop]);
+ } else if (ret != 0) {
+ printf("%s: Bulk alloc failed count(%u); ret val(%d)\n",
+ __func__, alloc_counts[idx], ret);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Negative testing for allocating a bulk of mbufs
+ */
+static int
+test_neg_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
+{
+ int ret = 0;
+ unsigned int idx, loop;
+ unsigned int neg_alloc_counts[] = {
+ MEMPOOL_CACHE_SIZE - NB_MBUF,
+ NB_MBUF + 1,
+ NB_MBUF * 8,
+ UINT_MAX
+ };
+ struct rte_mbuf *mbufs[NB_MBUF * 8] = { 0 };
+
+ for (idx = 0; idx < RTE_DIM(neg_alloc_counts); idx++) {
+ ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
+ neg_alloc_counts[idx]);
+ if (ret == 0) {
+ printf("%s: Bulk alloc must fail! count(%u); ret(%d)\n",
+ __func__, neg_alloc_counts[idx], ret);
+ for (loop = 0; loop < neg_alloc_counts[idx] &&
+ mbufs[loop] != NULL; loop++)
+ rte_pktmbuf_free(mbufs[loop]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Test to read mbuf packet using rte_pktmbuf_read
+ */
+static int
+test_pktmbuf_read(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ char *data = NULL;
+ const char *data_copy = NULL;
+ int off;
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ memset(data, 0xfe, MBUF_TEST_DATA_LEN2);
+
+ /* read the data from mbuf */
+ data_copy = rte_pktmbuf_read(m, 0, MBUF_TEST_DATA_LEN2, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading data!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xfe)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+ rte_pktmbuf_free(m);
+ m = NULL;
+
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+/*
+ * Test to read mbuf packet data from offset
+ */
+static int
+test_pktmbuf_read_from_offset(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct ether_hdr *hdr = NULL;
+ char *data = NULL;
+ const char *data_copy = NULL;
+ unsigned int off;
+ unsigned int hdr_len = sizeof(struct rte_ether_hdr);
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ /* prepend an ethernet header */
+ hdr = (struct ether_hdr *)rte_pktmbuf_prepend(m, hdr_len);
+ if (hdr == NULL)
+ GOTO_FAIL("%s: Cannot prepend header\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != hdr_len)
+ GOTO_FAIL("%s: Bad pkt length", __func__);
+ if (rte_pktmbuf_data_len(m) != hdr_len)
+ GOTO_FAIL("%s: Bad data length", __func__);
+ memset(hdr, 0xde, hdr_len);
+
+ /* read mbuf header info from 0 offset */
+ data_copy = rte_pktmbuf_read(m, 0, hdr_len, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading header!\n", __func__);
+ for (off = 0; off < hdr_len; off++) {
+ if (data_copy[off] != (char)0xde)
+ GOTO_FAIL("Header info corrupted at offset %u", off);
+ }
+
+ /* append sample data after ethernet header */
+ data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ if (rte_pktmbuf_data_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Bad data length\n", __func__);
+ memset(data, 0xcc, MBUF_TEST_DATA_LEN2);
+
+ /* read mbuf data after header info */
+ data_copy = rte_pktmbuf_read(m, hdr_len, MBUF_TEST_DATA_LEN2, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading header data!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* partial reading of mbuf data */
+ data_copy = rte_pktmbuf_read(m, hdr_len + 5, MBUF_TEST_DATA_LEN2 - 5,
+ NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ if (strlen(data_copy) != MBUF_TEST_DATA_LEN2 - 5)
+ GOTO_FAIL("%s: Incorrect data length!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2 - 5; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* read length greater than mbuf data_len */
+ if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_data_len(m) + 1,
+ NULL) != NULL)
+ GOTO_FAIL("%s: Requested len is larger than mbuf data len!\n",
+ __func__);
+
+ /* read length greater than mbuf pkt_len */
+ if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_pkt_len(m) + 1,
+ NULL) != NULL)
+ GOTO_FAIL("%s: Requested len is larger than mbuf pkt len!\n",
+ __func__);
+
+ /* read data of zero len from valid offset */
+ data_copy = rte_pktmbuf_read(m, hdr_len, 0, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ if (strlen(data_copy) != MBUF_TEST_DATA_LEN2)
+ GOTO_FAIL("%s: Corrupted data content!\n", __func__);
+ for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
+ if (data_copy[off] != (char)0xcc)
+ GOTO_FAIL("Data corrupted at offset %u", off);
+ }
+
+ /* read data of zero length from zero offset */
+ data_copy = rte_pktmbuf_read(m, 0, 0, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ /* check if the received address is the beginning of header info */
+ if (hdr != (const struct ether_hdr *)data_copy)
+ GOTO_FAIL("%s: Corrupted data address!\n", __func__);
+
+ /* read data of max length from valid offset */
+ data_copy = rte_pktmbuf_read(m, hdr_len, UINT_MAX, NULL);
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+ /* check if the received address is the beginning of data segment */
+ if (data_copy != data)
+ GOTO_FAIL("%s: Corrupted data address!\n", __func__);
+
+ /* try to read from mbuf with max size offset */
+ data_copy = rte_pktmbuf_read(m, UINT_MAX, 0, NULL);
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+
+ /* try to read from mbuf with max size offset and len */
+ data_copy = rte_pktmbuf_read(m, UINT_MAX, UINT_MAX, NULL);
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
+
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+
+ rte_pktmbuf_free(m);
+ m = NULL;
+
+ return 0;
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+struct test_case {
+ unsigned int seg_count;
+ unsigned int flags;
+ uint32_t read_off;
+ uint32_t read_len;
+ unsigned int seg_lengths[MBUF_MAX_SEG];
+};
+
+/* create a mbuf with different sized segments
+ * and fill with data [0x00 0x01 0x02 ...]
+ */
+static struct rte_mbuf *
+create_packet(struct rte_mempool *pktmbuf_pool,
+ struct test_case *test_data)
+{
+ uint16_t i, ret, seg, seg_len = 0;
+ uint32_t last_index = 0;
+ unsigned int seg_lengths[MBUF_MAX_SEG];
+ unsigned int hdr_len;
+ struct rte_mbuf *pkt = NULL;
+ struct rte_mbuf *pkt_seg = NULL;
+ char *hdr = NULL;
+ char *data = NULL;
+
+ memcpy(seg_lengths, test_data->seg_lengths,
+ sizeof(unsigned int)*test_data->seg_count);
+ for (seg = 0; seg < test_data->seg_count; seg++) {
+ hdr_len = 0;
+ seg_len = seg_lengths[seg];
+ pkt_seg = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (pkt_seg == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(pkt_seg, 0);
+ /* Add header only for the first segment */
+ if (test_data->flags == MBUF_HEADER && seg == 0) {
+ hdr_len = sizeof(struct rte_ether_hdr);
+ /* prepend a header and fill with dummy data */
+ hdr = (char *)rte_pktmbuf_prepend(pkt_seg, hdr_len);
+ if (hdr == NULL)
+ GOTO_FAIL("%s: Cannot prepend header\n",
+ __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len)
+ GOTO_FAIL("%s: Bad pkt length", __func__);
+ if (rte_pktmbuf_data_len(pkt_seg) != hdr_len)
+ GOTO_FAIL("%s: Bad data length", __func__);
+ for (i = 0; i < hdr_len; i++)
+ hdr[i] = (last_index + i) % 0xffff;
+ last_index += hdr_len;
+ }
+ /* skip appending segment with 0 length */
+ if (seg_len == 0)
+ continue;
+ data = rte_pktmbuf_append(pkt_seg, seg_len);
+ if (data == NULL)
+ GOTO_FAIL("%s: Cannot append data segment\n", __func__);
+ if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len + seg_len)
+ GOTO_FAIL("%s: Bad packet segment length: %d\n",
+ __func__, rte_pktmbuf_pkt_len(pkt_seg));
+ if (rte_pktmbuf_data_len(pkt_seg) != hdr_len + seg_len)
+ GOTO_FAIL("%s: Bad data length\n", __func__);
+ for (i = 0; i < seg_len; i++)
+ data[i] = (last_index + i) % 0xffff;
+ /* to fill continuous data from one seg to another */
+ last_index += i;
+ /* create chained mbufs */
+ if (seg == 0)
+ pkt = pkt_seg;
+ else {
+ ret = rte_pktmbuf_chain(pkt, pkt_seg);
+ if (ret != 0)
+ GOTO_FAIL("%s:FAIL: Chained mbuf creation %d\n",
+ __func__, ret);
+ }
+
+ pkt_seg = pkt_seg->next;
+ }
+ return pkt;
+fail:
+ if (pkt != NULL) {
+ rte_pktmbuf_free(pkt);
+ pkt = NULL;
+ }
+ if (pkt_seg != NULL) {
+ rte_pktmbuf_free(pkt_seg);
+ pkt_seg = NULL;
+ }
+ return NULL;
+}
+
+static int
+test_pktmbuf_read_from_chain(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m;
+ struct test_case test_cases[] = {
+ {
+ .seg_lengths = { 100, 100, 100 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 300
+ },
+ {
+ .seg_lengths = { 100, 125, 150 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 99,
+ .read_len = 201
+ },
+ {
+ .seg_lengths = { 100, 100 },
+ .seg_count = 2,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 100
+ },
+ {
+ .seg_lengths = { 100, 200 },
+ .seg_count = 2,
+ .flags = MBUF_HEADER,
+ .read_off = sizeof(struct rte_ether_hdr),
+ .read_len = 150
+ },
+ {
+ .seg_lengths = { 1000, 100 },
+ .seg_count = 2,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 0,
+ .read_len = 1000
+ },
+ {
+ .seg_lengths = { 1024, 0, 100 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 100,
+ .read_len = 1001
+ },
+ {
+ .seg_lengths = { 1000, 1, 1000 },
+ .seg_count = 3,
+ .flags = MBUF_NO_HEADER,
+ .read_off = 1000,
+ .read_len = 2
+ },
+ {
+ .seg_lengths = { MBUF_TEST_DATA_LEN,
+ MBUF_TEST_DATA_LEN2,
+ MBUF_TEST_DATA_LEN3, 800, 10 },
+ .seg_count = 5,
+ .flags = MBUF_NEG_TEST_READ,
+ .read_off = 1000,
+ .read_len = MBUF_DATA_SIZE
+ },
+ };
+
+ uint32_t i, pos;
+ const char *data_copy = NULL;
+ char data_buf[MBUF_DATA_SIZE];
+
+ memset(data_buf, 0, MBUF_DATA_SIZE);
+
+ for (i = 0; i < RTE_DIM(test_cases); i++) {
+ m = create_packet(pktmbuf_pool, &test_cases[i]);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+
+ data_copy = rte_pktmbuf_read(m, test_cases[i].read_off,
+ test_cases[i].read_len, data_buf);
+ if (test_cases[i].flags == MBUF_NEG_TEST_READ) {
+ if (data_copy != NULL)
+ GOTO_FAIL("%s: mbuf data read should fail!\n",
+ __func__);
+ else {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ continue;
+ }
+ }
+ if (data_copy == NULL)
+ GOTO_FAIL("%s: Error in reading packet data!\n",
+ __func__);
+ for (pos = 0; pos < test_cases[i].read_len; pos++) {
+ if (data_copy[pos] !=
+ (char)((test_cases[i].read_off + pos)
+ % 0xffff))
+ GOTO_FAIL("Data corrupted at offset %u is %2X",
+ pos, data_copy[pos]);
+ }
+ rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return 0;
+
+fail:
+ if (m != NULL) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ return -1;
+}
+
+/* Define a free call back function to be used for external buffer */
+static void
+ext_buf_free_callback_fn(void *addr __rte_unused, void *opaque)
+{
+ void *ext_buf_addr = opaque;
+
+ if (ext_buf_addr == NULL) {
+ printf("External buffer address is invalid\n");
+ return;
+ }
+ rte_free(ext_buf_addr);
+ ext_buf_addr = NULL;
+ printf("External buffer freed via callback\n");
+}
+
+/*
+ * Test to initialize shared data in external buffer before attaching to mbuf
+ * - Allocate mbuf with no data.
+ * - Allocate external buffer with size should be large enough to accommodate
+ * rte_mbuf_ext_shared_info.
+ * - Invoke pktmbuf_ext_shinfo_init_helper to initialize shared data.
+ * - Invoke rte_pktmbuf_attach_extbuf to attach external buffer to the mbuf.
+ * - Clone another mbuf and attach the same external buffer to it.
+ * - Invoke rte_pktmbuf_detach_extbuf to detach the external buffer from mbuf.
+ */
+static int
+test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool *pktmbuf_pool)
+{
+ struct rte_mbuf *m = NULL;
+ struct rte_mbuf *clone = NULL;
+ struct rte_mbuf_ext_shared_info *ret_shinfo = NULL;
+ rte_iova_t buf_iova;
+ void *ext_buf_addr = NULL;
+ uint16_t buf_len = EXT_BUF_TEST_DATA_LEN +
+ sizeof(struct rte_mbuf_ext_shared_info);
+
+ /* alloc a mbuf */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(m) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+ rte_mbuf_sanity_check(m, 0);
+
+ ext_buf_addr = rte_malloc("External buffer", buf_len,
+ RTE_CACHE_LINE_SIZE);
+ if (ext_buf_addr == NULL)
+ GOTO_FAIL("%s: External buffer allocation failed\n", __func__);
+
+ ret_shinfo = rte_pktmbuf_ext_shinfo_init_helper(ext_buf_addr, &buf_len,
+ ext_buf_free_callback_fn, ext_buf_addr);
+ if (ret_shinfo == NULL)
+ GOTO_FAIL("%s: Shared info initialization failed!\n", __func__);
+
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
+ GOTO_FAIL("%s: External refcount is not 1\n", __func__);
+
+ if (rte_mbuf_refcnt_read(m) != 1)
+ GOTO_FAIL("%s: Invalid refcnt in mbuf\n", __func__);
+
+ buf_iova = rte_mempool_virt2iova(ext_buf_addr);
+ rte_pktmbuf_attach_extbuf(m, ext_buf_addr, buf_iova, buf_len,
+ ret_shinfo);
+ if (m->ol_flags != EXT_ATTACHED_MBUF)
+ GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
+ __func__);
+
+ /* allocate one more mbuf */
+ clone = rte_pktmbuf_clone(m, pktmbuf_pool);
+ if (clone == NULL)
+ GOTO_FAIL("%s: mbuf clone allocation failed!\n", __func__);
+ if (rte_pktmbuf_pkt_len(clone) != 0)
+ GOTO_FAIL("%s: Bad packet length\n", __func__);
+
+ /* attach the same external buffer to the cloned mbuf */
+ rte_pktmbuf_attach_extbuf(clone, ext_buf_addr, buf_iova, buf_len,
+ ret_shinfo);
+ if (clone->ol_flags != EXT_ATTACHED_MBUF)
+ GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
+ __func__);
+
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ /* test to manually update ext_buf_ref_cnt from 2 to 3*/
+ rte_mbuf_ext_refcnt_update(ret_shinfo, 1);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 3)
+ GOTO_FAIL("%s: Update ext_buf ref_cnt failed\n", __func__);
+
+ /* reset the ext_refcnt before freeing the external buffer */
+ rte_mbuf_ext_refcnt_set(ret_shinfo, 2);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
+ GOTO_FAIL("%s: set ext_buf ref_cnt failed\n", __func__);
+
+ /* detach the external buffer from mbufs */
+ rte_pktmbuf_detach_extbuf(m);
+ /* check if ref cnt is decremented */
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ rte_pktmbuf_detach_extbuf(clone);
+ if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 0)
+ GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
+
+ rte_pktmbuf_free(m);
+ m = NULL;
+ rte_pktmbuf_free(clone);
+ clone = NULL;
+
+ return 0;
+
+fail:
+ if (m) {
+ rte_pktmbuf_free(m);
+ m = NULL;
+ }
+ if (clone) {
+ rte_pktmbuf_free(clone);
+ clone = NULL;
+ }
+ if (ext_buf_addr != NULL) {
+ rte_free(ext_buf_addr);
+ ext_buf_addr = NULL;
+ }
+ return -1;
+}
+
+/*
+ * Test the mbuf pool with pinned external data buffers
+ * - Allocate memory zone for external buffer
+ * - Create the mbuf pool with pinned external buffer
+ * - Check the created pool with relevant mbuf pool unit tests
+ */
+static int
+test_pktmbuf_ext_pinned_buffer(struct rte_mempool *std_pool)
+{
+
+ struct rte_pktmbuf_extmem ext_mem;
+ struct rte_mempool *pinned_pool = NULL;
+ const struct rte_memzone *mz = NULL;
+
+ printf("Test mbuf pool with external pinned data buffers\n");
+
+ /* Allocate memzone for the external data buffer */
+ mz = rte_memzone_reserve("pinned_pool",
+ NB_MBUF * MBUF_DATA_SIZE,
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB | RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL)
+ GOTO_FAIL("%s: Memzone allocation failed\n", __func__);
+
+ /* Create the mbuf pool with pinned external data buffer */
+ ext_mem.buf_ptr = mz->addr;
+ ext_mem.buf_iova = mz->iova;
+ ext_mem.buf_len = mz->len;
+ ext_mem.elt_size = MBUF_DATA_SIZE;
+
+ pinned_pool = rte_pktmbuf_pool_create_extbuf("test_pinned_pool",
+ NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
+ MBUF_DATA_SIZE, SOCKET_ID_ANY,
+ &ext_mem, 1);
+ if (pinned_pool == NULL)
+ GOTO_FAIL("%s: Mbuf pool with pinned external"
+ " buffer creation failed\n", __func__);
+ /* test multiple mbuf alloc */
+ if (test_pktmbuf_pool(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_pool(pinned) failed\n",
+ __func__);
+
+ /* do it another time to check that all mbufs were freed */
+ if (test_pktmbuf_pool(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_pool(pinned) failed (2)\n",
+ __func__);
+
+ /* test that the data pointer on a packet mbuf is set properly */
+ if (test_pktmbuf_pool_ptr(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_pool_ptr(pinned) failed\n",
+ __func__);
+
+ /* test data manipulation in mbuf with non-ascii data */
+ if (test_pktmbuf_with_non_ascii_data(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_with_non_ascii_data(pinned)"
+ " failed\n", __func__);
+
+ /* test free pktmbuf segment one by one */
+ if (test_pktmbuf_free_segment(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_free_segment(pinned) failed\n",
+ __func__);
+
+ if (testclone_testupdate_testdetach(pinned_pool, std_pool) < 0)
+ GOTO_FAIL("%s: testclone_and_testupdate(pinned) failed\n",
+ __func__);
+
+ if (test_pktmbuf_copy(pinned_pool, std_pool) < 0)
+ GOTO_FAIL("%s: test_pktmbuf_copy(pinned) failed\n",
+ __func__);
+
+ if (test_failing_mbuf_sanity_check(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_failing_mbuf_sanity_check(pinned)"
+ " failed\n", __func__);
+
+ if (test_mbuf_linearize_check(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_mbuf_linearize_check(pinned) failed\n",
+ __func__);
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_pktmbuf_alloc_bulk(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_alloc_bulk(pinned) failed\n",
+ __func__);
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_neg_pktmbuf_alloc_bulk(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_neg_rte_pktmbuf_alloc_bulk(pinned)"
+ " failed\n", __func__);
+
+ /* test to read mbuf packet */
+ if (test_pktmbuf_read(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read(pinned) failed\n",
+ __func__);
+
+ /* test to read mbuf packet from offset */
+ if (test_pktmbuf_read_from_offset(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read_from_offset(pinned)"
+ " failed\n", __func__);
+
+ /* test to read data from chain of mbufs with data segments */
+ if (test_pktmbuf_read_from_chain(pinned_pool) < 0)
+ GOTO_FAIL("%s: test_rte_pktmbuf_read_from_chain(pinned)"
+ " failed\n", __func__);
+
+ RTE_SET_USED(std_pool);
+ rte_mempool_free(pinned_pool);
+ rte_memzone_free(mz);
+ return 0;
+
+fail:
+ rte_mempool_free(pinned_pool);
+ rte_memzone_free(mz);
+ return -1;
+}
+
+static int
+test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
+{
+ const struct rte_mbuf_dynfield dynfield = {
+ .name = "test-dynfield",
+ .size = sizeof(uint8_t),
+ .align = __alignof__(uint8_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield2 = {
+ .name = "test-dynfield2",
+ .size = sizeof(uint16_t),
+ .align = __alignof__(uint16_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield3 = {
+ .name = "test-dynfield3",
+ .size = sizeof(uint8_t),
+ .align = __alignof__(uint8_t),
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield_fail_big = {
+ .name = "test-dynfield-fail-big",
+ .size = 256,
+ .align = 1,
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynfield dynfield_fail_align = {
+ .name = "test-dynfield-fail-align",
+ .size = 1,
+ .align = 3,
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag = {
+ .name = "test-dynflag",
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag2 = {
+ .name = "test-dynflag2",
+ .flags = 0,
+ };
+ const struct rte_mbuf_dynflag dynflag3 = {
+ .name = "test-dynflag3",
+ .flags = 0,
+ };
+ struct rte_mbuf *m = NULL;
+ int offset, offset2, offset3;
+ int flag, flag2, flag3;
+ int ret;
+
+ printf("Test mbuf dynamic fields and flags\n");
+ rte_mbuf_dyn_dump(stdout);
+
+ offset = rte_mbuf_dynfield_register(&dynfield);
+ if (offset == -1)
+ GOTO_FAIL("failed to register dynamic field, offset=%d: %s",
+ offset, strerror(errno));
+
+ ret = rte_mbuf_dynfield_register(&dynfield);
+ if (ret != offset)
+ GOTO_FAIL("failed to lookup dynamic field, ret=%d: %s",
+ ret, strerror(errno));
+
+ offset2 = rte_mbuf_dynfield_register(&dynfield2);
+ if (offset2 == -1 || offset2 == offset || (offset2 & 1))
+ GOTO_FAIL("failed to register dynamic field 2, offset2=%d: %s",
+ offset2, strerror(errno));
+
+ offset3 = rte_mbuf_dynfield_register_offset(&dynfield3,
+ offsetof(struct rte_mbuf, dynfield1[1]));
+ if (offset3 != offsetof(struct rte_mbuf, dynfield1[1]))
+ GOTO_FAIL("failed to register dynamic field 3, offset=%d: %s",
+ offset3, strerror(errno));
+
+ printf("dynfield: offset=%d, offset2=%d, offset3=%d\n",
+ offset, offset2, offset3);
+
+ ret = rte_mbuf_dynfield_register(&dynfield_fail_big);
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (too big)");
+
+ ret = rte_mbuf_dynfield_register(&dynfield_fail_align);
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (bad alignment)");
+
+ ret = rte_mbuf_dynfield_register_offset(&dynfield_fail_align,
+ offsetof(struct rte_mbuf, ol_flags));
+ if (ret != -1)
+ GOTO_FAIL("dynamic field creation should fail (not avail)");
+
+ flag = rte_mbuf_dynflag_register(&dynflag);
+ if (flag == -1)
+ GOTO_FAIL("failed to register dynamic flag, flag=%d: %s",
+ flag, strerror(errno));
+
+ ret = rte_mbuf_dynflag_register(&dynflag);
+ if (ret != flag)
+ GOTO_FAIL("failed to lookup dynamic flag, ret=%d: %s",
+ ret, strerror(errno));
+
+ flag2 = rte_mbuf_dynflag_register(&dynflag2);
+ if (flag2 == -1 || flag2 == flag)
+ GOTO_FAIL("failed to register dynamic flag 2, flag2=%d: %s",
+ flag2, strerror(errno));
+
+ flag3 = rte_mbuf_dynflag_register_bitnum(&dynflag3,
+ rte_bsf64(PKT_LAST_FREE));
+ if (flag3 != rte_bsf64(PKT_LAST_FREE))
+ GOTO_FAIL("failed to register dynamic flag 3, flag2=%d: %s",
+ flag3, strerror(errno));
+
+ printf("dynflag: flag=%d, flag2=%d, flag3=%d\n", flag, flag2, flag3);
+
+ /* set, get dynamic field */
+ m = rte_pktmbuf_alloc(pktmbuf_pool);
+ if (m == NULL)
+ GOTO_FAIL("Cannot allocate mbuf");
+
+ *RTE_MBUF_DYNFIELD(m, offset, uint8_t *) = 1;
+ if (*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) != 1)
+ GOTO_FAIL("failed to read dynamic field");
+ *RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) = 1000;
+ if (*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) != 1000)
+ GOTO_FAIL("failed to read dynamic field");
+
+ /* set a dynamic flag */
+ m->ol_flags |= (1ULL << flag);
+
+ rte_mbuf_dyn_dump(stdout);
+ rte_pktmbuf_free(m);
+ return 0;
+fail:
+ rte_pktmbuf_free(m);
+ return -1;
+}
+
+static int
+test_mbuf(void)
+{
+ int ret = -1;
+ struct rte_mempool *pktmbuf_pool = NULL;
+ struct rte_mempool *pktmbuf_pool2 = NULL;
+
+
+ RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
+
+ /* create pktmbuf pool if it does not exist */
+ pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
+ NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
+ SOCKET_ID_ANY);
+
+ if (pktmbuf_pool == NULL) {
+ printf("cannot allocate mbuf pool\n");
+ goto err;
+ }
+
+ /* test registration of dynamic fields and flags */
+ if (test_mbuf_dyn(pktmbuf_pool) < 0) {
+ printf("mbuf dynflag test failed\n");
+ goto err;
+ }
+
+ /* create a specific pktmbuf pool with a priv_size != 0 and no data
+ * room size */
+ pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
+ NB_MBUF, MEMPOOL_CACHE_SIZE, MBUF2_PRIV_SIZE, 0,
+ SOCKET_ID_ANY);
+
+ if (pktmbuf_pool2 == NULL) {
+ printf("cannot allocate mbuf pool\n");
+ goto err;
+ }
+
+ /* test multiple mbuf alloc */
+ if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
+ printf("test_mbuf_pool() failed\n");
+ goto err;
+ }
+
+ /* do it another time to check that all mbufs were freed */
+ if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
+ printf("test_mbuf_pool() failed (2)\n");
+ goto err;
+ }
+
+ /* test bulk mbuf alloc and free */
+ if (test_pktmbuf_pool_bulk() < 0) {
+ printf("test_pktmbuf_pool_bulk() failed\n");
+ goto err;
+ }
+
+ /* test that the pointer to the data on a packet mbuf is set properly */
+ if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_pool_ptr() failed\n");
+ goto err;
+ }
+
+ /* test data manipulation in mbuf */
+ if (test_one_pktmbuf(pktmbuf_pool) < 0) {
+ printf("test_one_mbuf() failed\n");
+ goto err;
+ }
+
+
+ /*
+ * do it another time, to check that allocation reinitialize
+ * the mbuf correctly
+ */
+ if (test_one_pktmbuf(pktmbuf_pool) < 0) {
+ printf("test_one_mbuf() failed (2)\n");
+ goto err;
+ }
+
+ if (test_pktmbuf_with_non_ascii_data(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_with_non_ascii_data() failed\n");
+ goto err;
+ }
+
+ /* test free pktmbuf segment one by one */
+ if (test_pktmbuf_free_segment(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_free_segment() failed.\n");
+ goto err;
+ }
+
+ if (testclone_testupdate_testdetach(pktmbuf_pool, pktmbuf_pool) < 0) {
+ printf("testclone_and_testupdate() failed \n");
+ goto err;
+ }
+
+ if (test_pktmbuf_copy(pktmbuf_pool, pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_copy() failed\n");
+ goto err;
+ }
+
+ if (test_attach_from_different_pool(pktmbuf_pool, pktmbuf_pool2) < 0) {
+ printf("test_attach_from_different_pool() failed\n");
+ goto err;
+ }
+
+ if (test_refcnt_mbuf() < 0) {
+ printf("test_refcnt_mbuf() failed \n");
+ goto err;
+ }
+
+ if (test_failing_mbuf_sanity_check(pktmbuf_pool) < 0) {
+ printf("test_failing_mbuf_sanity_check() failed\n");
+ goto err;
+ }
+
+ if (test_mbuf_linearize_check(pktmbuf_pool) < 0) {
+ printf("test_mbuf_linearize_check() failed\n");
+ goto err;
+ }
+
+ if (test_tx_offload() < 0) {
+ printf("test_tx_offload() failed\n");
+ goto err;
+ }
+
+ if (test_get_rx_ol_flag_list() < 0) {
+ printf("test_rte_get_rx_ol_flag_list() failed\n");
+ goto err;
+ }
+
+ if (test_get_tx_ol_flag_list() < 0) {
+ printf("test_rte_get_tx_ol_flag_list() failed\n");
+ goto err;
+ }
+
+ if (test_get_rx_ol_flag_name() < 0) {
+ printf("test_rte_get_rx_ol_flag_name() failed\n");
+ goto err;
+ }
+
+ if (test_get_tx_ol_flag_name() < 0) {
+ printf("test_rte_get_tx_ol_flag_name() failed\n");
+ goto err;
+ }
+
+ if (test_mbuf_validate_tx_offload_one(pktmbuf_pool) < 0) {
+ printf("test_mbuf_validate_tx_offload_one() failed\n");
+ goto err;
+ }
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_alloc_bulk() failed\n");
+ goto err;
+ }
+
+ /* test for allocating a bulk of mbufs with various sizes */
+ if (test_neg_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
+ printf("test_neg_rte_pktmbuf_alloc_bulk() failed\n");
+ goto err;
+ }
+
+ /* test to read mbuf packet */
+ if (test_pktmbuf_read(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read() failed\n");
+ goto err;
+ }
+
+ /* test to read mbuf packet from offset */
+ if (test_pktmbuf_read_from_offset(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read_from_offset() failed\n");
+ goto err;
+ }
+
+ /* test to read data from chain of mbufs with data segments */
+ if (test_pktmbuf_read_from_chain(pktmbuf_pool) < 0) {
+ printf("test_rte_pktmbuf_read_from_chain() failed\n");
+ goto err;
+ }
+
+ /* test to initialize shared info. at the end of external buffer */
+ if (test_pktmbuf_ext_shinfo_init_helper(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_ext_shinfo_init_helper() failed\n");
+ goto err;
+ }
+
+ /* test the mbuf pool with pinned external data buffers */
+ if (test_pktmbuf_ext_pinned_buffer(pktmbuf_pool) < 0) {
+ printf("test_pktmbuf_ext_pinned_buffer() failed\n");
+ goto err;
+ }
+
+
+ ret = 0;
+err:
+ rte_mempool_free(pktmbuf_pool);
+ rte_mempool_free(pktmbuf_pool2);
+ return ret;
+}
+#undef GOTO_FAIL
+
+REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);
diff --git a/src/spdk/dpdk/app/test/test_mcslock.c b/src/spdk/dpdk/app/test/test_mcslock.c
new file mode 100644
index 000000000..ddccaafa9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_mcslock.c
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_mcslock.h>
+#include <rte_atomic.h>
+
+#include "test.h"
+
+/*
+ * RTE MCS lock test
+ * =================
+ *
+ * These tests are derived from spin lock test cases.
+ *
+ * - The functional test takes all of these locks and launches the
+ * ''test_mcslock_per_core()'' function on each core (except the master).
+ *
+ * - The function takes the global lock, display something, then releases
+ * the global lock on each core.
+ *
+ * - A load test is carried out, with all cores attempting to lock a single
+ * lock multiple times.
+ */
+
+RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_me);
+RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_try_me);
+RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_perf_me);
+
+rte_mcslock_t *p_ml;
+rte_mcslock_t *p_ml_try;
+rte_mcslock_t *p_ml_perf;
+
+static unsigned int count;
+
+static rte_atomic32_t synchro;
+
+static int
+test_mcslock_per_core(__rte_unused void *arg)
+{
+ /* Per core me node. */
+ rte_mcslock_t ml_me = RTE_PER_LCORE(_ml_me);
+
+ rte_mcslock_lock(&p_ml, &ml_me);
+ printf("MCS lock taken on core %u\n", rte_lcore_id());
+ rte_mcslock_unlock(&p_ml, &ml_me);
+ printf("MCS lock released on core %u\n", rte_lcore_id());
+
+ return 0;
+}
+
+static uint64_t time_count[RTE_MAX_LCORE] = {0};
+
+#define MAX_LOOP 1000000
+
+static int
+load_loop_fn(void *func_param)
+{
+ uint64_t time_diff = 0, begin;
+ uint64_t hz = rte_get_timer_hz();
+ volatile uint64_t lcount = 0;
+ const int use_lock = *(int *)func_param;
+ const unsigned int lcore = rte_lcore_id();
+
+ /**< Per core me node. */
+ rte_mcslock_t ml_perf_me = RTE_PER_LCORE(_ml_perf_me);
+
+ /* wait synchro */
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ begin = rte_get_timer_cycles();
+ while (lcount < MAX_LOOP) {
+ if (use_lock)
+ rte_mcslock_lock(&p_ml_perf, &ml_perf_me);
+
+ lcount++;
+ if (use_lock)
+ rte_mcslock_unlock(&p_ml_perf, &ml_perf_me);
+ }
+ time_diff = rte_get_timer_cycles() - begin;
+ time_count[lcore] = time_diff * 1000000 / hz;
+ return 0;
+}
+
+static int
+test_mcslock_perf(void)
+{
+ unsigned int i;
+ uint64_t total = 0;
+ int lock = 0;
+ const unsigned int lcore = rte_lcore_id();
+
+ printf("\nTest with no lock on single core...\n");
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(&lock);
+ printf("Core [%u] Cost Time = %"PRIu64" us\n",
+ lcore, time_count[lcore]);
+ memset(time_count, 0, sizeof(time_count));
+
+ printf("\nTest with lock on single core...\n");
+ lock = 1;
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(&lock);
+ printf("Core [%u] Cost Time = %"PRIu64" us\n",
+ lcore, time_count[lcore]);
+ memset(time_count, 0, sizeof(time_count));
+
+ printf("\nTest with lock on %u cores...\n", (rte_lcore_count()));
+
+ rte_atomic32_set(&synchro, 0);
+ rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER);
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(&lock);
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_LCORE_FOREACH(i) {
+ printf("Core [%u] Cost Time = %"PRIu64" us\n",
+ i, time_count[i]);
+ total += time_count[i];
+ }
+
+ printf("Total Cost Time = %"PRIu64" us\n", total);
+
+ return 0;
+}
+
+/*
+ * Use rte_mcslock_trylock() to trylock a mcs lock object,
+ * If it could not lock the object successfully, it would
+ * return immediately.
+ */
+static int
+test_mcslock_try(__rte_unused void *arg)
+{
+ /**< Per core me node. */
+ rte_mcslock_t ml_me = RTE_PER_LCORE(_ml_me);
+ rte_mcslock_t ml_try_me = RTE_PER_LCORE(_ml_try_me);
+
+ /* Locked ml_try in the master lcore, so it should fail
+ * when trying to lock it in the slave lcore.
+ */
+ if (rte_mcslock_trylock(&p_ml_try, &ml_try_me) == 0) {
+ rte_mcslock_lock(&p_ml, &ml_me);
+ count++;
+ rte_mcslock_unlock(&p_ml, &ml_me);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Test rte_eal_get_lcore_state() in addition to mcs locks
+ * as we have "waiting" then "running" lcores.
+ */
+static int
+test_mcslock(void)
+{
+ int ret = 0;
+ int i;
+
+ /* Define per core me node. */
+ rte_mcslock_t ml_me = RTE_PER_LCORE(_ml_me);
+ rte_mcslock_t ml_try_me = RTE_PER_LCORE(_ml_try_me);
+
+ /*
+ * Test mcs lock & unlock on each core
+ */
+
+ /* slave cores should be waiting: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+
+ rte_mcslock_lock(&p_ml, &ml_me);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_mcslock_per_core, NULL, i);
+ }
+
+ /* slave cores should be busy: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+
+ rte_mcslock_unlock(&p_ml, &ml_me);
+
+ rte_eal_mp_wait_lcore();
+
+ /*
+ * Test if it could return immediately from try-locking a locked object.
+ * Here it will lock the mcs lock object first, then launch all the
+ * slave lcores to trylock the same mcs lock object.
+ * All the slave lcores should give up try-locking a locked object and
+ * return immediately, and then increase the "count" initialized with
+ * zero by one per times.
+ * We can check if the "count" is finally equal to the number of all
+ * slave lcores to see if the behavior of try-locking a locked
+ * mcslock object is correct.
+ */
+ if (rte_mcslock_trylock(&p_ml_try, &ml_try_me) == 0)
+ return -1;
+
+ count = 0;
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_mcslock_try, NULL, i);
+ }
+ rte_eal_mp_wait_lcore();
+ rte_mcslock_unlock(&p_ml_try, &ml_try_me);
+
+ /* Test is_locked API */
+ if (rte_mcslock_is_locked(p_ml)) {
+ printf("mcslock is locked but it should not be\n");
+ return -1;
+ }
+
+ /* Counting the locked times in each core */
+ rte_mcslock_lock(&p_ml, &ml_me);
+ if (count != (rte_lcore_count() - 1))
+ ret = -1;
+ rte_mcslock_unlock(&p_ml, &ml_me);
+
+ /* mcs lock perf test */
+ if (test_mcslock_perf() < 0)
+ return -1;
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(mcslock_autotest, test_mcslock);
diff --git a/src/spdk/dpdk/app/test/test_member.c b/src/spdk/dpdk/app/test/test_member.c
new file mode 100644
index 000000000..40aa4c862
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_member.c
@@ -0,0 +1,715 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+/* This test is for membership library's simple feature test */
+
+#include <rte_memcpy.h>
+#include <rte_malloc.h>
+#include <rte_member.h>
+#include <rte_byteorder.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+struct rte_member_setsum *setsum_ht;
+struct rte_member_setsum *setsum_cache;
+struct rte_member_setsum *setsum_vbf;
+
+/* 5-tuple key type */
+struct flow_key {
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+ uint8_t proto;
+} __rte_packed;
+
+/* Set ID Macros for multimatch test usage */
+#define M_MATCH_S 1 /* Not start with 0 since by default 0 means no match */
+#define M_MATCH_E 15
+#define M_MATCH_STEP 2
+#define M_MATCH_CNT \
+ (1 + (M_MATCH_E - M_MATCH_S) / M_MATCH_STEP)
+
+
+#define NUM_SAMPLES 5
+#define MAX_MATCH 32
+
+/* Keys used by unit test functions */
+static struct flow_key keys[NUM_SAMPLES] = {
+ {
+ .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
+ .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
+ .port_src = 0x0908,
+ .port_dst = 0x0b0a,
+ .proto = 0x0c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10),
+ .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14),
+ .port_src = 0x1918,
+ .port_dst = 0x1b1a,
+ .proto = 0x1c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20),
+ .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24),
+ .port_src = 0x2928,
+ .port_dst = 0x2b2a,
+ .proto = 0x2c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30),
+ .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34),
+ .port_src = 0x3938,
+ .port_dst = 0x3b3a,
+ .proto = 0x3c,
+ },
+ {
+ .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40),
+ .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44),
+ .port_src = 0x4948,
+ .port_dst = 0x4b4a,
+ .proto = 0x4c,
+ }
+};
+
+uint32_t test_set[NUM_SAMPLES] = {1, 2, 3, 4, 5};
+
+#define ITERATIONS 3
+#define KEY_SIZE 4
+
+#define MAX_ENTRIES (1 << 16)
+uint8_t generated_keys[MAX_ENTRIES][KEY_SIZE];
+
+static struct rte_member_parameters params = {
+ .num_keys = MAX_ENTRIES, /* Total hash table entries. */
+ .key_len = KEY_SIZE, /* Length of hash key. */
+
+ /* num_set and false_positive_rate only relevant to vBF */
+ .num_set = 16,
+ .false_positive_rate = 0.03,
+ .prim_hash_seed = 1,
+ .sec_hash_seed = 11,
+ .socket_id = 0 /* NUMA Socket ID for memory. */
+};
+
+/*
+ * Sequence of operations for find existing setsummary
+ *
+ * - create setsum
+ * - find existing setsum: hit
+ * - find non-existing setsum: miss
+ *
+ */
+static int
+test_member_find_existing(void)
+{
+ struct rte_member_setsum *tmp_setsum = NULL, *result = NULL;
+ struct rte_member_parameters tmp_params = {
+ .name = "member_find_existing",
+ .num_keys = MAX_ENTRIES, /* Total hash table entries. */
+ .key_len = KEY_SIZE, /* Length of hash key. */
+ .type = RTE_MEMBER_TYPE_HT,
+ .num_set = 32,
+ .false_positive_rate = 0.03,
+ .prim_hash_seed = 1,
+ .sec_hash_seed = 11,
+ .socket_id = 0 /* NUMA Socket ID for memory. */
+ };
+
+ /* Create */
+ tmp_setsum = rte_member_create(&tmp_params);
+ TEST_ASSERT(tmp_setsum != NULL, "setsum creation failed");
+
+ /* Try to find existing hash table */
+ result = rte_member_find_existing("member_find_existing");
+ TEST_ASSERT(result == tmp_setsum, "could not find existing setsum");
+
+ /* Try to find non-existing hash table */
+ result = rte_member_find_existing("member_find_non_existing");
+ TEST_ASSERT(result == NULL, "found setsum that shouldn't exist");
+
+ /* Cleanup. */
+ rte_member_free(tmp_setsum);
+
+ return 0;
+}
+
+/*
+ * Test for bad creating parameters
+ */
+static int
+test_member_create_bad_param(void)
+{
+ struct rte_member_setsum *bad_setsum = NULL;
+ struct rte_member_parameters bad_params = {
+ .num_keys = MAX_ENTRIES, /* Total hash table entries. */
+ .key_len = KEY_SIZE, /* Length of hash key. */
+ .type = RTE_MEMBER_TYPE_HT,
+ .num_set = 32,
+ .false_positive_rate = 0.03,
+ .prim_hash_seed = 1,
+ .sec_hash_seed = 11,
+ .socket_id = 0 /* NUMA Socket ID for memory. */
+ };
+
+ printf("Expected error section begin...\n");
+ bad_params.name = "bad_param1";
+ bad_params.num_set = 0;
+ bad_params.type = RTE_MEMBER_TYPE_VBF;
+ /* Test with 0 set for vBF should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with invalid "
+ "number of set for vBF\n");
+ return -1;
+ }
+
+ bad_params.name = "bad_param2";
+ bad_params.false_positive_rate = 0;
+ bad_params.num_set = 32;
+ /* Test with 0 false positive for vBF should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with invalid "
+ "false positive rate for vBF\n");
+ return -1;
+ }
+
+ bad_params.name = "bad_param3";
+ bad_params.false_positive_rate = 0.03;
+ bad_params.num_keys = 0;
+ /* Test with 0 key per BF for vBF should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with invalid "
+ "num_keys for vBF\n");
+ return -1;
+ }
+
+ bad_params.name = "bad_param4";
+ bad_params.type = RTE_MEMBER_TYPE_HT;
+ bad_params.num_keys = RTE_MEMBER_BUCKET_ENTRIES / 2;
+ /* Test with less than 1 bucket for HTSS should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with too few "
+ "number of keys(entries) for HT\n");
+ return -1;
+ }
+
+ bad_params.name = "bad_param5";
+ bad_params.num_keys = RTE_MEMBER_ENTRIES_MAX + 1;
+ /* Test with more than maximum entries for HTSS should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with to many "
+ "number of keys(entries) for HT\n");
+ return -1;
+ }
+
+ bad_params.name = "bad_param5";
+ /* Test with same name should fail */
+ bad_setsum = rte_member_create(&bad_params);
+ if (bad_setsum != NULL) {
+ rte_member_free(bad_setsum);
+ printf("Impossible creating setsum successfully with existed "
+ "name\n");
+ return -1;
+ }
+ printf("Expected error section end...\n");
+ rte_member_free(bad_setsum);
+ return 0;
+}
+
+/* Create test setsummaries. */
+static int test_member_create(void)
+{
+ params.key_len = sizeof(struct flow_key);
+
+ params.name = "test_member_ht";
+ params.is_cache = 0;
+ params.type = RTE_MEMBER_TYPE_HT;
+ setsum_ht = rte_member_create(&params);
+
+ params.name = "test_member_cache";
+ params.is_cache = 1;
+ setsum_cache = rte_member_create(&params);
+
+ params.name = "test_member_vbf";
+ params.type = RTE_MEMBER_TYPE_VBF;
+ setsum_vbf = rte_member_create(&params);
+
+ if (setsum_ht == NULL || setsum_cache == NULL || setsum_vbf == NULL) {
+ printf("Creation of setsums fail\n");
+ return -1;
+ }
+ printf("Creation of setsums success\n");
+ return 0;
+}
+
+static int test_member_insert(void)
+{
+ int ret_ht, ret_cache, ret_vbf, i;
+
+ for (i = 0; i < NUM_SAMPLES; i++) {
+ ret_ht = rte_member_add(setsum_ht, &keys[i], test_set[i]);
+ ret_cache = rte_member_add(setsum_cache, &keys[i],
+ test_set[i]);
+ ret_vbf = rte_member_add(setsum_vbf, &keys[i], test_set[i]);
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,
+ "insert error");
+ }
+ printf("insert key success\n");
+ return 0;
+}
+
+static int test_member_lookup(void)
+{
+ int ret_ht, ret_cache, ret_vbf, i;
+ uint16_t set_ht, set_cache, set_vbf;
+ member_set_t set_ids_ht[NUM_SAMPLES] = {0};
+ member_set_t set_ids_cache[NUM_SAMPLES] = {0};
+ member_set_t set_ids_vbf[NUM_SAMPLES] = {0};
+
+ uint32_t num_key_ht = NUM_SAMPLES;
+ uint32_t num_key_cache = NUM_SAMPLES;
+ uint32_t num_key_vbf = NUM_SAMPLES;
+
+ const void *key_array[NUM_SAMPLES];
+
+ /* Single lookup test */
+ for (i = 0; i < NUM_SAMPLES; i++) {
+ ret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht);
+ ret_cache = rte_member_lookup(setsum_cache, &keys[i],
+ &set_cache);
+ ret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf);
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,
+ "single lookup function error");
+
+ TEST_ASSERT(set_ht == test_set[i] &&
+ set_cache == test_set[i] &&
+ set_vbf == test_set[i],
+ "single lookup set value error");
+ }
+ printf("lookup single key success\n");
+
+ /* Bulk lookup test */
+ for (i = 0; i < NUM_SAMPLES; i++)
+ key_array[i] = &keys[i];
+
+ ret_ht = rte_member_lookup_bulk(setsum_ht, key_array,
+ num_key_ht, set_ids_ht);
+
+ ret_cache = rte_member_lookup_bulk(setsum_cache, key_array,
+ num_key_cache, set_ids_cache);
+
+ ret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array,
+ num_key_vbf, set_ids_vbf);
+
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,
+ "bulk lookup function error");
+
+ for (i = 0; i < NUM_SAMPLES; i++) {
+ TEST_ASSERT((set_ids_ht[i] == test_set[i]) &&
+ (set_ids_cache[i] == test_set[i]) &&
+ (set_ids_vbf[i] == test_set[i]),
+ "bulk lookup result error");
+ }
+
+ return 0;
+}
+
+static int test_member_delete(void)
+{
+ int ret_ht, ret_cache, ret_vbf, i;
+ uint16_t set_ht, set_cache, set_vbf;
+ const void *key_array[NUM_SAMPLES];
+ member_set_t set_ids_ht[NUM_SAMPLES] = {0};
+ member_set_t set_ids_cache[NUM_SAMPLES] = {0};
+ member_set_t set_ids_vbf[NUM_SAMPLES] = {0};
+ uint32_t num_key_ht = NUM_SAMPLES;
+ uint32_t num_key_cache = NUM_SAMPLES;
+ uint32_t num_key_vbf = NUM_SAMPLES;
+
+ /* Delete part of all inserted keys */
+ for (i = 0; i < NUM_SAMPLES / 2; i++) {
+ ret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]);
+ ret_cache = rte_member_delete(setsum_cache, &keys[i],
+ test_set[i]);
+ ret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]);
+ /* VBF does not support delete yet, so return error code */
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,
+ "key deletion function error");
+ TEST_ASSERT(ret_vbf < 0,
+ "vbf does not support deletion, error");
+ }
+
+ for (i = 0; i < NUM_SAMPLES; i++)
+ key_array[i] = &keys[i];
+
+ ret_ht = rte_member_lookup_bulk(setsum_ht, key_array,
+ num_key_ht, set_ids_ht);
+
+ ret_cache = rte_member_lookup_bulk(setsum_cache, key_array,
+ num_key_cache, set_ids_cache);
+
+ ret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array,
+ num_key_vbf, set_ids_vbf);
+
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,
+ "bulk lookup function error");
+
+ for (i = 0; i < NUM_SAMPLES / 2; i++) {
+ TEST_ASSERT((set_ids_ht[i] == RTE_MEMBER_NO_MATCH) &&
+ (set_ids_cache[i] == RTE_MEMBER_NO_MATCH),
+ "bulk lookup result error");
+ }
+
+ for (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) {
+ TEST_ASSERT((set_ids_ht[i] == test_set[i]) &&
+ (set_ids_cache[i] == test_set[i]) &&
+ (set_ids_vbf[i] == test_set[i]),
+ "bulk lookup result error");
+ }
+
+ /* Delete the left of inserted keys */
+ for (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) {
+ ret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]);
+ ret_cache = rte_member_delete(setsum_cache, &keys[i],
+ test_set[i]);
+ ret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]);
+ /* VBF does not support delete yet, so return error code */
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,
+ "key deletion function error");
+ TEST_ASSERT(ret_vbf < 0,
+ "vbf does not support deletion, error");
+ }
+
+ for (i = 0; i < NUM_SAMPLES; i++) {
+ ret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht);
+ ret_cache = rte_member_lookup(setsum_cache, &keys[i],
+ &set_cache);
+ ret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf);
+ TEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,
+ "key lookup function error");
+ TEST_ASSERT(set_ht == RTE_MEMBER_NO_MATCH &&
+ ret_cache == RTE_MEMBER_NO_MATCH,
+ "key deletion failed");
+ }
+ /* Reset vbf for other following tests */
+ rte_member_reset(setsum_vbf);
+
+ printf("delete success\n");
+ return 0;
+}
+
+static int test_member_multimatch(void)
+{
+ int ret_ht, ret_vbf, ret_cache;
+ member_set_t set_ids_ht[MAX_MATCH] = {0};
+ member_set_t set_ids_vbf[MAX_MATCH] = {0};
+ member_set_t set_ids_cache[MAX_MATCH] = {0};
+
+ member_set_t set_ids_ht_m[NUM_SAMPLES][MAX_MATCH] = {{0} };
+ member_set_t set_ids_vbf_m[NUM_SAMPLES][MAX_MATCH] = {{0} };
+ member_set_t set_ids_cache_m[NUM_SAMPLES][MAX_MATCH] = {{0} };
+
+ uint32_t match_count_ht[NUM_SAMPLES];
+ uint32_t match_count_vbf[NUM_SAMPLES];
+ uint32_t match_count_cache[NUM_SAMPLES];
+
+ uint32_t num_key_ht = NUM_SAMPLES;
+ uint32_t num_key_vbf = NUM_SAMPLES;
+ uint32_t num_key_cache = NUM_SAMPLES;
+
+ const void *key_array[NUM_SAMPLES];
+
+ uint32_t i, j;
+
+ /* Same key at most inserted 2*entry_per_bucket times for HT mode */
+ for (i = M_MATCH_S; i <= M_MATCH_E; i += M_MATCH_STEP) {
+ for (j = 0; j < NUM_SAMPLES; j++) {
+ ret_ht = rte_member_add(setsum_ht, &keys[j], i);
+ ret_vbf = rte_member_add(setsum_vbf, &keys[j], i);
+ ret_cache = rte_member_add(setsum_cache, &keys[j], i);
+
+ TEST_ASSERT(ret_ht >= 0 && ret_vbf >= 0 &&
+ ret_cache >= 0,
+ "insert function error");
+ }
+ }
+
+ /* Single multimatch test */
+ for (i = 0; i < NUM_SAMPLES; i++) {
+ ret_vbf = rte_member_lookup_multi(setsum_vbf, &keys[i],
+ MAX_MATCH, set_ids_vbf);
+ ret_ht = rte_member_lookup_multi(setsum_ht, &keys[i],
+ MAX_MATCH, set_ids_ht);
+ ret_cache = rte_member_lookup_multi(setsum_cache, &keys[i],
+ MAX_MATCH, set_ids_cache);
+ /*
+ * For cache mode, keys overwrite when signature same.
+ * the mutimatch should work like single match.
+ */
+ TEST_ASSERT(ret_ht == M_MATCH_CNT && ret_vbf == M_MATCH_CNT &&
+ ret_cache == 1,
+ "single lookup_multi error");
+ TEST_ASSERT(set_ids_cache[0] == M_MATCH_E,
+ "single lookup_multi cache error");
+
+ for (j = 1; j <= M_MATCH_CNT; j++) {
+ TEST_ASSERT(set_ids_ht[j-1] == j * M_MATCH_STEP - 1 &&
+ set_ids_vbf[j-1] ==
+ j * M_MATCH_STEP - 1,
+ "single multimatch lookup error");
+ }
+ }
+ printf("lookup single key for multimatch success\n");
+
+ /* Bulk multimatch test */
+ for (i = 0; i < NUM_SAMPLES; i++)
+ key_array[i] = &keys[i];
+ ret_vbf = rte_member_lookup_multi_bulk(setsum_vbf,
+ &key_array[0], num_key_ht, MAX_MATCH, match_count_vbf,
+ (member_set_t *)set_ids_vbf_m);
+
+ ret_ht = rte_member_lookup_multi_bulk(setsum_ht,
+ &key_array[0], num_key_vbf, MAX_MATCH, match_count_ht,
+ (member_set_t *)set_ids_ht_m);
+
+ ret_cache = rte_member_lookup_multi_bulk(setsum_cache,
+ &key_array[0], num_key_cache, MAX_MATCH,
+ match_count_cache, (member_set_t *)set_ids_cache_m);
+
+
+ for (j = 0; j < NUM_SAMPLES; j++) {
+ TEST_ASSERT(match_count_ht[j] == M_MATCH_CNT,
+ "bulk multimatch lookup HT match count error");
+ TEST_ASSERT(match_count_vbf[j] == M_MATCH_CNT,
+ "bulk multimatch lookup vBF match count error");
+ TEST_ASSERT(match_count_cache[j] == 1,
+ "bulk multimatch lookup CACHE match count error");
+ TEST_ASSERT(set_ids_cache_m[j][0] == M_MATCH_E,
+ "bulk multimatch lookup CACHE set value error");
+
+ for (i = 1; i <= M_MATCH_CNT; i++) {
+ TEST_ASSERT(set_ids_ht_m[j][i-1] ==
+ i * M_MATCH_STEP - 1,
+ "bulk multimatch lookup HT set value error");
+ TEST_ASSERT(set_ids_vbf_m[j][i-1] ==
+ i * M_MATCH_STEP - 1,
+ "bulk multimatch lookup vBF set value error");
+ }
+ }
+
+ printf("lookup for bulk multimatch success\n");
+
+ return 0;
+}
+
+static int key_compare(const void *key1, const void *key2)
+{
+ return memcmp(key1, key2, KEY_SIZE);
+}
+
+static void
+setup_keys_and_data(void)
+{
+ unsigned int i, j;
+ int num_duplicates;
+
+ /* Reset all arrays */
+ for (i = 0; i < KEY_SIZE; i++)
+ generated_keys[0][i] = 0;
+
+ /* Generate a list of keys, some of which may be duplicates */
+ for (i = 0; i < MAX_ENTRIES; i++) {
+ for (j = 0; j < KEY_SIZE; j++)
+ generated_keys[i][j] = rte_rand() & 0xFF;
+ }
+
+ /* Remove duplicates from the keys array */
+ do {
+ num_duplicates = 0;
+ /* Sort the list of keys to make it easier to find duplicates */
+ qsort(generated_keys, MAX_ENTRIES, KEY_SIZE, key_compare);
+
+ /* Sift through the list of keys and look for duplicates */
+ int num_duplicates = 0;
+ for (i = 0; i < MAX_ENTRIES - 1; i++) {
+ if (memcmp(generated_keys[i], generated_keys[i + 1],
+ KEY_SIZE) == 0) {
+ /* This key already exists, try again */
+ num_duplicates++;
+ for (j = 0; j < KEY_SIZE; j++)
+ generated_keys[i][j] =
+ rte_rand() & 0xFF;
+ }
+ }
+ } while (num_duplicates != 0);
+}
+
+static inline int
+add_generated_keys(struct rte_member_setsum *setsum, unsigned int *added_keys)
+{
+ int ret = 0;
+
+ for (*added_keys = 0; ret >= 0 && *added_keys < MAX_ENTRIES;
+ (*added_keys)++) {
+ uint16_t set = (rte_rand() & 0xf) + 1;
+ ret = rte_member_add(setsum, &generated_keys[*added_keys], set);
+ }
+ return ret;
+}
+
+static inline int
+add_generated_keys_cache(struct rte_member_setsum *setsum,
+ unsigned int *added_keys)
+{
+ int ret = 0;
+
+ for (*added_keys = 0; ret == 0 && *added_keys < MAX_ENTRIES;
+ (*added_keys)++) {
+ uint16_t set = (rte_rand() & 0xf) + 1;
+ ret = rte_member_add(setsum, &generated_keys[*added_keys], set);
+ }
+ return ret;
+}
+
+static int
+test_member_loadfactor(void)
+{
+ unsigned int j;
+ unsigned int added_keys, average_keys_added = 0;
+ int ret;
+
+ setup_keys_and_data();
+
+ rte_member_free(setsum_ht);
+ rte_member_free(setsum_cache);
+ rte_member_free(setsum_vbf);
+
+ params.key_len = KEY_SIZE;
+ params.name = "test_member_ht";
+ params.is_cache = 0;
+ params.type = RTE_MEMBER_TYPE_HT;
+ setsum_ht = rte_member_create(&params);
+
+ params.name = "test_member_cache";
+ params.is_cache = 1;
+ setsum_cache = rte_member_create(&params);
+
+
+ if (setsum_ht == NULL || setsum_cache == NULL) {
+ printf("Creation of setsums fail\n");
+ return -1;
+ }
+ /* Test HT non-cache mode */
+ for (j = 0; j < ITERATIONS; j++) {
+ /* Add random entries until key cannot be added */
+ ret = add_generated_keys(setsum_ht, &added_keys);
+ if (ret != -ENOSPC) {
+ printf("Unexpected error when adding keys\n");
+ return -1;
+ }
+ average_keys_added += added_keys;
+
+ /* Reset the table */
+ rte_member_reset(setsum_ht);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nKeys inserted when no space(non-cache) = %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / params.num_keys * 100),
+ average_keys_added, params.num_keys);
+
+ /* Test cache mode */
+ added_keys = average_keys_added = 0;
+ for (j = 0; j < ITERATIONS; j++) {
+ /* Add random entries until key cannot be added */
+ ret = add_generated_keys_cache(setsum_cache, &added_keys);
+ if (ret != 1) {
+ printf("Unexpected error when adding keys\n");
+ return -1;
+ }
+ average_keys_added += added_keys;
+
+ /* Reset the table */
+ rte_member_reset(setsum_cache);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nKeys inserted when eviction happens(cache)= %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / params.num_keys * 100),
+ average_keys_added, params.num_keys);
+ return 0;
+}
+
+static void
+perform_free(void)
+{
+ rte_member_free(setsum_ht);
+ rte_member_free(setsum_cache);
+ rte_member_free(setsum_vbf);
+}
+
+static int
+test_member(void)
+{
+ if (test_member_create_bad_param() < 0)
+ return -1;
+
+ if (test_member_find_existing() < 0)
+ return -1;
+
+ if (test_member_create() < 0) {
+ perform_free();
+ return -1;
+ }
+ if (test_member_insert() < 0) {
+ perform_free();
+ return -1;
+ }
+ if (test_member_lookup() < 0) {
+ perform_free();
+ return -1;
+ }
+ if (test_member_delete() < 0) {
+ perform_free();
+ return -1;
+ }
+ if (test_member_multimatch() < 0) {
+ perform_free();
+ return -1;
+ }
+ if (test_member_loadfactor() < 0) {
+ rte_member_free(setsum_ht);
+ rte_member_free(setsum_cache);
+ return -1;
+ }
+
+ perform_free();
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(member_autotest, test_member);
diff --git a/src/spdk/dpdk/app/test/test_member_perf.c b/src/spdk/dpdk/app/test/test_member_perf.c
new file mode 100644
index 000000000..e2840f12d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_member_perf.c
@@ -0,0 +1,625 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_memcpy.h>
+#include <rte_thash.h>
+#include <rte_member.h>
+
+#include "test.h"
+
+#define NUM_KEYSIZES 10
+#define NUM_SHUFFLES 10
+#define MAX_KEYSIZE 64
+#define MAX_ENTRIES (1 << 19)
+#define KEYS_TO_ADD (MAX_ENTRIES * 75 / 100) /* 75% table utilization */
+#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */
+#define VBF_SET_CNT 16
+#define BURST_SIZE 64
+#define VBF_FALSE_RATE 0.03
+
+static unsigned int test_socket_id;
+
+enum sstype {
+ HT = 0,
+ CACHE,
+ VBF,
+ NUM_TYPE
+};
+
+enum operations {
+ ADD = 0,
+ LOOKUP,
+ LOOKUP_BULK,
+ LOOKUP_MULTI,
+ LOOKUP_MULTI_BULK,
+ DELETE,
+ LOOKUP_MISS,
+ NUM_OPERATIONS
+};
+
+struct member_perf_params {
+ struct rte_member_setsum *setsum[NUM_TYPE];
+ uint32_t key_size;
+ unsigned int cycle;
+};
+
+static uint32_t hashtest_key_lens[] = {
+ /* standard key sizes */
+ 4, 8, 16, 32, 48, 64,
+ /* IPv4 SRC + DST + protocol, unpadded */
+ 9,
+ /* IPv4 5-tuple, unpadded */
+ 13,
+ /* IPv6 5-tuple, unpadded */
+ 37,
+ /* IPv6 5-tuple, padded to 8-byte boundary */
+ 40
+};
+
+/* Array to store number of cycles per operation */
+static uint64_t cycles[NUM_TYPE][NUM_KEYSIZES][NUM_OPERATIONS];
+static uint64_t false_data[NUM_TYPE][NUM_KEYSIZES];
+static uint64_t false_data_bulk[NUM_TYPE][NUM_KEYSIZES];
+static uint64_t false_data_multi[NUM_TYPE][NUM_KEYSIZES];
+static uint64_t false_data_multi_bulk[NUM_TYPE][NUM_KEYSIZES];
+
+static uint64_t false_hit[NUM_TYPE][NUM_KEYSIZES];
+
+static member_set_t data[NUM_TYPE][/* Array to store the data */KEYS_TO_ADD];
+
+/* Array to store all input keys */
+static uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];
+
+/* Shuffle the keys that have been added, so lookups will be totally random */
+static void
+shuffle_input_keys(struct member_perf_params *params)
+{
+ member_set_t temp_data;
+ unsigned int i, j;
+ uint32_t swap_idx;
+ uint8_t temp_key[MAX_KEYSIZE];
+
+ for (i = KEYS_TO_ADD - 1; i > 0; i--) {
+ swap_idx = rte_rand() % i;
+ memcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]);
+ memcpy(keys[i], keys[swap_idx],
+ hashtest_key_lens[params->cycle]);
+ memcpy(keys[swap_idx], temp_key,
+ hashtest_key_lens[params->cycle]);
+ for (j = 0; j < NUM_TYPE; j++) {
+ temp_data = data[j][i];
+ data[j][i] = data[j][swap_idx];
+ data[j][swap_idx] = temp_data;
+ }
+ }
+}
+
+static int key_compare(const void *key1, const void *key2)
+{
+ return memcmp(key1, key2, MAX_KEYSIZE);
+}
+
+struct rte_member_parameters member_params = {
+ .num_keys = MAX_ENTRIES, /* Total hash table entries. */
+ .key_len = 4, /* Length of hash key. */
+
+ /* num_set and false_positive_rate only relevant to vBF */
+ .num_set = VBF_SET_CNT,
+ .false_positive_rate = 0.03,
+ .prim_hash_seed = 0,
+ .sec_hash_seed = 1,
+ .socket_id = 0, /* NUMA Socket ID for memory. */
+ };
+
+static int
+setup_keys_and_data(struct member_perf_params *params, unsigned int cycle,
+ int miss)
+{
+ unsigned int i, j;
+ int num_duplicates;
+
+ params->key_size = hashtest_key_lens[cycle];
+ params->cycle = cycle;
+
+ /* Reset all arrays */
+ for (i = 0; i < params->key_size; i++)
+ keys[0][i] = 0;
+
+ /* Generate a list of keys, some of which may be duplicates */
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ for (j = 0; j < params->key_size; j++)
+ keys[i][j] = rte_rand() & 0xFF;
+
+ data[HT][i] = data[CACHE][i] = (rte_rand() & 0x7FFE) + 1;
+ data[VBF][i] = rte_rand() % VBF_SET_CNT + 1;
+ }
+
+ /* Remove duplicates from the keys array */
+ do {
+ num_duplicates = 0;
+
+ /* Sort the list of keys to make it easier to find duplicates */
+ qsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare);
+
+ /* Sift through the list of keys and look for duplicates */
+ int num_duplicates = 0;
+ for (i = 0; i < KEYS_TO_ADD - 1; i++) {
+ if (memcmp(keys[i], keys[i + 1],
+ params->key_size) == 0) {
+ /* This key already exists, try again */
+ num_duplicates++;
+ for (j = 0; j < params->key_size; j++)
+ keys[i][j] = rte_rand() & 0xFF;
+ }
+ }
+ } while (num_duplicates != 0);
+
+ /* Shuffle the random values again */
+ shuffle_input_keys(params);
+
+ /* For testing miss lookup, we insert half and lookup the other half */
+ unsigned int entry_cnt, bf_key_cnt;
+ if (!miss) {
+ entry_cnt = MAX_ENTRIES;
+ bf_key_cnt = KEYS_TO_ADD;
+ } else {
+ entry_cnt = MAX_ENTRIES / 2;
+ bf_key_cnt = KEYS_TO_ADD / 2;
+ }
+ member_params.false_positive_rate = VBF_FALSE_RATE;
+ member_params.key_len = params->key_size;
+ member_params.socket_id = test_socket_id;
+ member_params.num_keys = entry_cnt;
+ member_params.name = "test_member_ht";
+ member_params.is_cache = 0;
+ member_params.type = RTE_MEMBER_TYPE_HT;
+ params->setsum[HT] = rte_member_create(&member_params);
+ if (params->setsum[HT] == NULL)
+ fprintf(stderr, "ht create fail\n");
+
+ member_params.name = "test_member_cache";
+ member_params.is_cache = 1;
+ params->setsum[CACHE] = rte_member_create(&member_params);
+ if (params->setsum[CACHE] == NULL)
+ fprintf(stderr, "CACHE create fail\n");
+
+ member_params.name = "test_member_vbf";
+ member_params.type = RTE_MEMBER_TYPE_VBF;
+ member_params.num_keys = bf_key_cnt;
+ params->setsum[VBF] = rte_member_create(&member_params);
+ if (params->setsum[VBF] == NULL)
+ fprintf(stderr, "VBF create fail\n");
+ for (i = 0; i < NUM_TYPE; i++) {
+ if (params->setsum[i] == NULL)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+timed_adds(struct member_perf_params *params, int type)
+{
+ const uint64_t start_tsc = rte_rdtsc();
+ unsigned int i, a;
+ int32_t ret;
+
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ ret = rte_member_add(params->setsum[type], &keys[i],
+ data[type][i]);
+ if (ret < 0) {
+ printf("Error %d in rte_member_add - key=0x", ret);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x", keys[i][a]);
+ printf(" value=%d, type: %d\n", data[type][i], type);
+
+ return -1;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][ADD] = time_taken / KEYS_TO_ADD;
+ return 0;
+}
+
+static int
+timed_lookups(struct member_perf_params *params, int type)
+{
+ unsigned int i, j;
+
+ false_data[type][params->cycle] = 0;
+
+ const uint64_t start_tsc = rte_rdtsc();
+ member_set_t result;
+ int ret;
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD; j++) {
+ ret = rte_member_lookup(params->setsum[type], &keys[j],
+ &result);
+ if (ret < 0) {
+ printf("lookup wrong internally");
+ return -1;
+ }
+ if (type == HT && result == RTE_MEMBER_NO_MATCH) {
+ printf("HT mode shouldn't have false negative");
+ return -1;
+ }
+ if (result != data[type][j])
+ false_data[type][params->cycle]++;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_lookups_bulk(struct member_perf_params *params, int type)
+{
+ unsigned int i, j, k;
+ member_set_t result[BURST_SIZE] = {0};
+ const void *keys_burst[BURST_SIZE];
+ int ret;
+
+ false_data_bulk[type][params->cycle] = 0;
+
+ const uint64_t start_tsc = rte_rdtsc();
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {
+ for (k = 0; k < BURST_SIZE; k++)
+ keys_burst[k] = keys[j * BURST_SIZE + k];
+
+ ret = rte_member_lookup_bulk(params->setsum[type],
+ keys_burst,
+ BURST_SIZE,
+ result);
+ if (ret <= 0) {
+ printf("lookup bulk has wrong return value\n");
+ return -1;
+ }
+ for (k = 0; k < BURST_SIZE; k++) {
+ uint32_t data_idx = j * BURST_SIZE + k;
+ if (type == HT && result[k] ==
+ RTE_MEMBER_NO_MATCH) {
+ printf("HT mode shouldn't have "
+ "false negative");
+ return -1;
+ }
+ if (result[k] != data[type][data_idx])
+ false_data_bulk[type][params->cycle]++;
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][LOOKUP_BULK] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_lookups_multimatch(struct member_perf_params *params, int type)
+{
+ unsigned int i, j;
+ member_set_t result[RTE_MEMBER_BUCKET_ENTRIES] = {0};
+ int ret;
+ false_data_multi[type][params->cycle] = 0;
+
+ const uint64_t start_tsc = rte_rdtsc();
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD; j++) {
+ ret = rte_member_lookup_multi(params->setsum[type],
+ &keys[j], RTE_MEMBER_BUCKET_ENTRIES, result);
+ if (type != CACHE && ret <= 0) {
+ printf("lookup multi has wrong return value %d,"
+ "type %d\n", ret, type);
+ }
+ if (type == HT && ret == 0) {
+ printf("HT mode shouldn't have false negative");
+ return -1;
+ }
+ /*
+ * For performance test purpose, we do not iterate all
+ * results here. We assume most likely each key can only
+ * find one match which is result[0].
+ */
+ if (result[0] != data[type][j])
+ false_data_multi[type][params->cycle]++;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_lookups_multimatch_bulk(struct member_perf_params *params, int type)
+{
+ unsigned int i, j, k;
+ member_set_t result[BURST_SIZE][RTE_MEMBER_BUCKET_ENTRIES] = {{0} };
+ const void *keys_burst[BURST_SIZE];
+ uint32_t match_count[BURST_SIZE];
+ int ret;
+
+ false_data_multi_bulk[type][params->cycle] = 0;
+
+ const uint64_t start_tsc = rte_rdtsc();
+
+ for (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {
+ for (k = 0; k < BURST_SIZE; k++)
+ keys_burst[k] = keys[j * BURST_SIZE + k];
+
+ ret = rte_member_lookup_multi_bulk(
+ params->setsum[type],
+ keys_burst, BURST_SIZE,
+ RTE_MEMBER_BUCKET_ENTRIES, match_count,
+ (member_set_t *)result);
+ if (ret < 0) {
+ printf("lookup multimatch bulk has wrong return"
+ " value\n");
+ return -1;
+ }
+ for (k = 0; k < BURST_SIZE; k++) {
+ if (type != CACHE && match_count[k] == 0) {
+ printf("lookup multimatch bulk get "
+ "wrong match count\n");
+ return -1;
+ }
+ if (type == HT && match_count[k] == 0) {
+ printf("HT mode shouldn't have "
+ "false negative");
+ return -1;
+ }
+ uint32_t data_idx = j * BURST_SIZE + k;
+ if (result[k][0] != data[type][data_idx])
+ false_data_multi_bulk[type][params->cycle]++;
+ }
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][LOOKUP_MULTI_BULK] = time_taken /
+ NUM_LOOKUPS;
+
+ return 0;
+}
+
+static int
+timed_deletes(struct member_perf_params *params, int type)
+{
+ unsigned int i;
+ int32_t ret;
+
+ if (type == VBF)
+ return 0;
+ const uint64_t start_tsc = rte_rdtsc();
+ for (i = 0; i < KEYS_TO_ADD; i++) {
+ ret = rte_member_delete(params->setsum[type], &keys[i],
+ data[type][i]);
+ if (type != CACHE && ret < 0) {
+ printf("delete error\n");
+ return -1;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][DELETE] = time_taken / KEYS_TO_ADD;
+
+ return 0;
+}
+
+static int
+timed_miss_lookup(struct member_perf_params *params, int type)
+{
+ unsigned int i, j;
+ int ret;
+
+ false_hit[type][params->cycle] = 0;
+
+ for (i = 0; i < KEYS_TO_ADD / 2; i++) {
+ ret = rte_member_add(params->setsum[type], &keys[i],
+ data[type][i]);
+ if (ret < 0) {
+ unsigned int a;
+ printf("Error %d in rte_member_add - key=0x", ret);
+ for (a = 0; a < params->key_size; a++)
+ printf("%02x", keys[i][a]);
+ printf(" value=%d, type: %d\n", data[type][i], type);
+
+ return -1;
+ }
+ }
+
+ const uint64_t start_tsc = rte_rdtsc();
+ member_set_t result;
+
+ for (i = 0; i < 2 * NUM_LOOKUPS / KEYS_TO_ADD; i++) {
+ for (j = KEYS_TO_ADD / 2; j < KEYS_TO_ADD; j++) {
+ ret = rte_member_lookup(params->setsum[type], &keys[j],
+ &result);
+ if (ret < 0) {
+ printf("lookup wrong internally");
+ return -1;
+ }
+ if (result != RTE_MEMBER_NO_MATCH)
+ false_hit[type][params->cycle]++;
+ }
+ }
+
+ const uint64_t end_tsc = rte_rdtsc();
+ const uint64_t time_taken = end_tsc - start_tsc;
+
+ cycles[type][params->cycle][LOOKUP_MISS] = time_taken / NUM_LOOKUPS;
+
+ return 0;
+}
+
+static void
+perform_frees(struct member_perf_params *params)
+{
+ int i;
+ for (i = 0; i < NUM_TYPE; i++) {
+ if (params->setsum[i] != NULL) {
+ rte_member_free(params->setsum[i]);
+ params->setsum[i] = NULL;
+ }
+ }
+}
+
+static int
+exit_with_fail(const char *testname, struct member_perf_params *params,
+ unsigned int i, unsigned int j)
+{
+ printf("<<<<<Test %s failed at keysize %d iteration %d type %d>>>>>\n",
+ testname, hashtest_key_lens[params->cycle], i, j);
+ perform_frees(params);
+ return -1;
+}
+
+static int
+run_all_tbl_perf_tests(void)
+{
+ unsigned int i, j, k;
+ struct member_perf_params params;
+
+ printf("Measuring performance, please wait\n");
+ fflush(stdout);
+
+ test_socket_id = rte_socket_id();
+
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ if (setup_keys_and_data(&params, i, 0) < 0) {
+ printf("Could not create keys/data/table\n");
+ return -1;
+ }
+ for (j = 0; j < NUM_TYPE; j++) {
+
+ if (timed_adds(&params, j) < 0)
+ return exit_with_fail("timed_adds", &params,
+ i, j);
+
+ for (k = 0; k < NUM_SHUFFLES; k++)
+ shuffle_input_keys(&params);
+
+ if (timed_lookups(&params, j) < 0)
+ return exit_with_fail("timed_lookups", &params,
+ i, j);
+
+ if (timed_lookups_bulk(&params, j) < 0)
+ return exit_with_fail("timed_lookups_bulk",
+ &params, i, j);
+
+ if (timed_lookups_multimatch(&params, j) < 0)
+ return exit_with_fail("timed_lookups_multi",
+ &params, i, j);
+
+ if (timed_lookups_multimatch_bulk(&params, j) < 0)
+ return exit_with_fail("timed_lookups_multi_bulk",
+ &params, i, j);
+
+ if (timed_deletes(&params, j) < 0)
+ return exit_with_fail("timed_deletes", &params,
+ i, j);
+
+ /* Print a dot to show progress on operations */
+ }
+ printf(".");
+ fflush(stdout);
+
+ perform_frees(&params);
+ }
+
+ /* Test false positive rate using un-inserted keys */
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ if (setup_keys_and_data(&params, i, 1) < 0) {
+ printf("Could not create keys/data/table\n");
+ return -1;
+ }
+ for (j = 0; j < NUM_TYPE; j++) {
+ if (timed_miss_lookup(&params, j) < 0)
+ return exit_with_fail("timed_miss_lookup",
+ &params, i, j);
+ }
+ perform_frees(&params);
+ }
+
+ printf("\nResults (in CPU cycles/operation)\n");
+ printf("-----------------------------------\n");
+ printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n",
+ "Keysize", "type", "Add", "Lookup", "Lookup_bulk",
+ "lookup_multi", "lookup_multi_bulk", "Delete",
+ "miss_lookup");
+ for (i = 0; i < NUM_KEYSIZES; i++) {
+ for (j = 0; j < NUM_TYPE; j++) {
+ printf("%-18d", hashtest_key_lens[i]);
+ printf("%-18d", j);
+ for (k = 0; k < NUM_OPERATIONS; k++)
+ printf("%-18"PRIu64, cycles[j][i][k]);
+ printf("\n");
+ }
+ }
+
+ printf("\nFalse results rate (and false positive rate)\n");
+ printf("-----------------------------------\n");
+ printf("\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s\n",
+ "Keysize", "type", "fr_single", "fr_bulk", "fr_multi",
+ "fr_multi_bulk", "false_positive_rate");
+ /* Key size not influence False rate so just print out one key size */
+ for (i = 0; i < 1; i++) {
+ for (j = 0; j < NUM_TYPE; j++) {
+ printf("%-18d", hashtest_key_lens[i]);
+ printf("%-18d", j);
+ printf("%-18f", (float)false_data[j][i] / NUM_LOOKUPS);
+ printf("%-18f", (float)false_data_bulk[j][i] /
+ NUM_LOOKUPS);
+ printf("%-18f", (float)false_data_multi[j][i] /
+ NUM_LOOKUPS);
+ printf("%-18f", (float)false_data_multi_bulk[j][i] /
+ NUM_LOOKUPS);
+ printf("%-18f", (float)false_hit[j][i] /
+ NUM_LOOKUPS);
+ printf("\n");
+ }
+ }
+ return 0;
+}
+
+static int
+test_member_perf(void)
+{
+
+ if (run_all_tbl_perf_tests() < 0)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(member_perf_autotest, test_member_perf);
diff --git a/src/spdk/dpdk/app/test/test_memcpy.c b/src/spdk/dpdk/app/test/test_memcpy.c
new file mode 100644
index 000000000..1ab86f496
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_memcpy.c
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rte_common.h>
+#include <rte_random.h>
+#include <rte_memcpy.h>
+
+#include "test.h"
+
+/*
+ * Set this to the maximum buffer size you want to test. If it is 0, then the
+ * values in the buf_sizes[] array below will be used.
+ */
+#define TEST_VALUE_RANGE 0
+
+/* List of buffer sizes to test */
+#if TEST_VALUE_RANGE == 0
+static size_t buf_sizes[] = {
+ 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 129, 255,
+ 256, 257, 320, 384, 511, 512, 513, 1023, 1024, 1025, 1518, 1522, 1600,
+ 2048, 3072, 4096, 5120, 6144, 7168, 8192
+};
+/* MUST be as large as largest packet size above */
+#define SMALL_BUFFER_SIZE 8192
+#else /* TEST_VALUE_RANGE != 0 */
+static size_t buf_sizes[TEST_VALUE_RANGE];
+#define SMALL_BUFFER_SIZE TEST_VALUE_RANGE
+#endif /* TEST_VALUE_RANGE == 0 */
+
+/* Data is aligned on this many bytes (power of 2) */
+#define ALIGNMENT_UNIT 32
+
+
+/*
+ * Create two buffers, and initialise one with random values. These are copied
+ * to the second buffer and then compared to see if the copy was successful.
+ * The bytes outside the copied area are also checked to make sure they were not
+ * changed.
+ */
+static int
+test_single_memcpy(unsigned int off_src, unsigned int off_dst, size_t size)
+{
+ unsigned int i;
+ uint8_t dest[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
+ uint8_t src[SMALL_BUFFER_SIZE + ALIGNMENT_UNIT];
+ void * ret;
+
+ /* Setup buffers */
+ for (i = 0; i < SMALL_BUFFER_SIZE + ALIGNMENT_UNIT; i++) {
+ dest[i] = 0;
+ src[i] = (uint8_t) rte_rand();
+ }
+
+ /* Do the copy */
+ ret = rte_memcpy(dest + off_dst, src + off_src, size);
+ if (ret != (dest + off_dst)) {
+ printf("rte_memcpy() returned %p, not %p\n",
+ ret, dest + off_dst);
+ }
+
+ /* Check nothing before offset is affected */
+ for (i = 0; i < off_dst; i++) {
+ if (dest[i] != 0) {
+ printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
+ "[modified before start of dst].\n",
+ (unsigned)size, off_src, off_dst);
+ return -1;
+ }
+ }
+
+ /* Check everything was copied */
+ for (i = 0; i < size; i++) {
+ if (dest[i + off_dst] != src[i + off_src]) {
+ printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
+ "[didn't copy byte %u].\n",
+ (unsigned)size, off_src, off_dst, i);
+ return -1;
+ }
+ }
+
+ /* Check nothing after copy was affected */
+ for (i = size; i < SMALL_BUFFER_SIZE; i++) {
+ if (dest[i + off_dst] != 0) {
+ printf("rte_memcpy() failed for %u bytes (offsets=%u,%u): "
+ "[copied too many].\n",
+ (unsigned)size, off_src, off_dst);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Check functionality for various buffer sizes and data offsets/alignments.
+ */
+static int
+func_test(void)
+{
+ unsigned int off_src, off_dst, i;
+ int ret;
+
+ for (off_src = 0; off_src < ALIGNMENT_UNIT; off_src++) {
+ for (off_dst = 0; off_dst < ALIGNMENT_UNIT; off_dst++) {
+ for (i = 0; i < RTE_DIM(buf_sizes); i++) {
+ ret = test_single_memcpy(off_src, off_dst,
+ buf_sizes[i]);
+ if (ret != 0)
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+test_memcpy(void)
+{
+ int ret;
+
+ ret = func_test();
+ if (ret != 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(memcpy_autotest, test_memcpy);
diff --git a/src/spdk/dpdk/app/test/test_memcpy_perf.c b/src/spdk/dpdk/app/test/test_memcpy_perf.c
new file mode 100644
index 000000000..00a2092b4
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_memcpy_perf.c
@@ -0,0 +1,350 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+
+#include <rte_memcpy.h>
+
+#include "test.h"
+
+/*
+ * Set this to the maximum buffer size you want to test. If it is 0, then the
+ * values in the buf_sizes[] array below will be used.
+ */
+#define TEST_VALUE_RANGE 0
+
+/* List of buffer sizes to test */
+#if TEST_VALUE_RANGE == 0
+static size_t buf_sizes[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128,
+ 129, 191, 192, 193, 255, 256, 257, 319, 320, 321, 383, 384, 385, 447, 448,
+ 449, 511, 512, 513, 767, 768, 769, 1023, 1024, 1025, 1518, 1522, 1536, 1600,
+ 2048, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192
+};
+/* MUST be as large as largest packet size above */
+#define SMALL_BUFFER_SIZE 8192
+#else /* TEST_VALUE_RANGE != 0 */
+static size_t buf_sizes[TEST_VALUE_RANGE];
+#define SMALL_BUFFER_SIZE TEST_VALUE_RANGE
+#endif /* TEST_VALUE_RANGE == 0 */
+
+
+/*
+ * Arrays of this size are used for measuring uncached memory accesses by
+ * picking a random location within the buffer. Make this smaller if there are
+ * memory allocation errors.
+ */
+#define LARGE_BUFFER_SIZE (100 * 1024 * 1024)
+
+/* How many times to run timing loop for performance tests */
+#define TEST_ITERATIONS 1000000
+#define TEST_BATCH_SIZE 100
+
+/* Data is aligned on this many bytes (power of 2) */
+#ifdef RTE_MACHINE_CPUFLAG_AVX512F
+#define ALIGNMENT_UNIT 64
+#elif defined RTE_MACHINE_CPUFLAG_AVX2
+#define ALIGNMENT_UNIT 32
+#else /* RTE_MACHINE_CPUFLAG */
+#define ALIGNMENT_UNIT 16
+#endif /* RTE_MACHINE_CPUFLAG */
+
+/*
+ * Pointers used in performance tests. The two large buffers are for uncached
+ * access where random addresses within the buffer are used for each
+ * memcpy. The two small buffers are for cached access.
+ */
+static uint8_t *large_buf_read, *large_buf_write;
+static uint8_t *small_buf_read, *small_buf_write;
+
+/* Initialise data buffers. */
+static int
+init_buffers(void)
+{
+ unsigned i;
+
+ large_buf_read = rte_malloc("memcpy", LARGE_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT);
+ if (large_buf_read == NULL)
+ goto error_large_buf_read;
+
+ large_buf_write = rte_malloc("memcpy", LARGE_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT);
+ if (large_buf_write == NULL)
+ goto error_large_buf_write;
+
+ small_buf_read = rte_malloc("memcpy", SMALL_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT);
+ if (small_buf_read == NULL)
+ goto error_small_buf_read;
+
+ small_buf_write = rte_malloc("memcpy", SMALL_BUFFER_SIZE + ALIGNMENT_UNIT, ALIGNMENT_UNIT);
+ if (small_buf_write == NULL)
+ goto error_small_buf_write;
+
+ for (i = 0; i < LARGE_BUFFER_SIZE; i++)
+ large_buf_read[i] = rte_rand();
+ for (i = 0; i < SMALL_BUFFER_SIZE; i++)
+ small_buf_read[i] = rte_rand();
+
+ return 0;
+
+error_small_buf_write:
+ rte_free(small_buf_read);
+error_small_buf_read:
+ rte_free(large_buf_write);
+error_large_buf_write:
+ rte_free(large_buf_read);
+error_large_buf_read:
+ printf("ERROR: not enough memory\n");
+ return -1;
+}
+
+/* Cleanup data buffers */
+static void
+free_buffers(void)
+{
+ rte_free(large_buf_read);
+ rte_free(large_buf_write);
+ rte_free(small_buf_read);
+ rte_free(small_buf_write);
+}
+
+/*
+ * Get a random offset into large array, with enough space needed to perform
+ * max copy size. Offset is aligned, uoffset is used for unalignment setting.
+ */
+static inline size_t
+get_rand_offset(size_t uoffset)
+{
+ return ((rte_rand() % (LARGE_BUFFER_SIZE - SMALL_BUFFER_SIZE)) &
+ ~(ALIGNMENT_UNIT - 1)) + uoffset;
+}
+
+/* Fill in source and destination addresses. */
+static inline void
+fill_addr_arrays(size_t *dst_addr, int is_dst_cached, size_t dst_uoffset,
+ size_t *src_addr, int is_src_cached, size_t src_uoffset)
+{
+ unsigned int i;
+
+ for (i = 0; i < TEST_BATCH_SIZE; i++) {
+ dst_addr[i] = (is_dst_cached) ? dst_uoffset : get_rand_offset(dst_uoffset);
+ src_addr[i] = (is_src_cached) ? src_uoffset : get_rand_offset(src_uoffset);
+ }
+}
+
+/*
+ * WORKAROUND: For some reason the first test doing an uncached write
+ * takes a very long time (~25 times longer than is expected). So we do
+ * it once without timing.
+ */
+static void
+do_uncached_write(uint8_t *dst, int is_dst_cached,
+ const uint8_t *src, int is_src_cached, size_t size)
+{
+ unsigned i, j;
+ size_t dst_addrs[TEST_BATCH_SIZE], src_addrs[TEST_BATCH_SIZE];
+
+ for (i = 0; i < (TEST_ITERATIONS / TEST_BATCH_SIZE); i++) {
+ fill_addr_arrays(dst_addrs, is_dst_cached, 0,
+ src_addrs, is_src_cached, 0);
+ for (j = 0; j < TEST_BATCH_SIZE; j++) {
+ rte_memcpy(dst+dst_addrs[j], src+src_addrs[j], size);
+ }
+ }
+}
+
+/*
+ * Run a single memcpy performance test. This is a macro to ensure that if
+ * the "size" parameter is a constant it won't be converted to a variable.
+ */
+#define SINGLE_PERF_TEST(dst, is_dst_cached, dst_uoffset, \
+ src, is_src_cached, src_uoffset, size) \
+do { \
+ unsigned int iter, t; \
+ size_t dst_addrs[TEST_BATCH_SIZE], src_addrs[TEST_BATCH_SIZE]; \
+ uint64_t start_time, total_time = 0; \
+ uint64_t total_time2 = 0; \
+ for (iter = 0; iter < (TEST_ITERATIONS / TEST_BATCH_SIZE); iter++) { \
+ fill_addr_arrays(dst_addrs, is_dst_cached, dst_uoffset, \
+ src_addrs, is_src_cached, src_uoffset); \
+ start_time = rte_rdtsc(); \
+ for (t = 0; t < TEST_BATCH_SIZE; t++) \
+ rte_memcpy(dst+dst_addrs[t], src+src_addrs[t], size); \
+ total_time += rte_rdtsc() - start_time; \
+ } \
+ for (iter = 0; iter < (TEST_ITERATIONS / TEST_BATCH_SIZE); iter++) { \
+ fill_addr_arrays(dst_addrs, is_dst_cached, dst_uoffset, \
+ src_addrs, is_src_cached, src_uoffset); \
+ start_time = rte_rdtsc(); \
+ for (t = 0; t < TEST_BATCH_SIZE; t++) \
+ memcpy(dst+dst_addrs[t], src+src_addrs[t], size); \
+ total_time2 += rte_rdtsc() - start_time; \
+ } \
+ printf("%3.0f -", (double)total_time / TEST_ITERATIONS); \
+ printf("%3.0f", (double)total_time2 / TEST_ITERATIONS); \
+ printf("(%6.2f%%) ", ((double)total_time - total_time2)*100/total_time2); \
+} while (0)
+
+/* Run aligned memcpy tests for each cached/uncached permutation */
+#define ALL_PERF_TESTS_FOR_SIZE(n) \
+do { \
+ if (__builtin_constant_p(n)) \
+ printf("\nC%6u", (unsigned)n); \
+ else \
+ printf("\n%7u", (unsigned)n); \
+ SINGLE_PERF_TEST(small_buf_write, 1, 0, small_buf_read, 1, 0, n); \
+ SINGLE_PERF_TEST(large_buf_write, 0, 0, small_buf_read, 1, 0, n); \
+ SINGLE_PERF_TEST(small_buf_write, 1, 0, large_buf_read, 0, 0, n); \
+ SINGLE_PERF_TEST(large_buf_write, 0, 0, large_buf_read, 0, 0, n); \
+} while (0)
+
+/* Run unaligned memcpy tests for each cached/uncached permutation */
+#define ALL_PERF_TESTS_FOR_SIZE_UNALIGNED(n) \
+do { \
+ if (__builtin_constant_p(n)) \
+ printf("\nC%6u", (unsigned)n); \
+ else \
+ printf("\n%7u", (unsigned)n); \
+ SINGLE_PERF_TEST(small_buf_write, 1, 1, small_buf_read, 1, 5, n); \
+ SINGLE_PERF_TEST(large_buf_write, 0, 1, small_buf_read, 1, 5, n); \
+ SINGLE_PERF_TEST(small_buf_write, 1, 1, large_buf_read, 0, 5, n); \
+ SINGLE_PERF_TEST(large_buf_write, 0, 1, large_buf_read, 0, 5, n); \
+} while (0)
+
+/* Run memcpy tests for constant length */
+#define ALL_PERF_TEST_FOR_CONSTANT \
+do { \
+ TEST_CONSTANT(6U); TEST_CONSTANT(64U); TEST_CONSTANT(128U); \
+ TEST_CONSTANT(192U); TEST_CONSTANT(256U); TEST_CONSTANT(512U); \
+ TEST_CONSTANT(768U); TEST_CONSTANT(1024U); TEST_CONSTANT(1536U); \
+} while (0)
+
+/* Run all memcpy tests for aligned constant cases */
+static inline void
+perf_test_constant_aligned(void)
+{
+#define TEST_CONSTANT ALL_PERF_TESTS_FOR_SIZE
+ ALL_PERF_TEST_FOR_CONSTANT;
+#undef TEST_CONSTANT
+}
+
+/* Run all memcpy tests for unaligned constant cases */
+static inline void
+perf_test_constant_unaligned(void)
+{
+#define TEST_CONSTANT ALL_PERF_TESTS_FOR_SIZE_UNALIGNED
+ ALL_PERF_TEST_FOR_CONSTANT;
+#undef TEST_CONSTANT
+}
+
+/* Run all memcpy tests for aligned variable cases */
+static inline void
+perf_test_variable_aligned(void)
+{
+ unsigned i;
+ for (i = 0; i < RTE_DIM(buf_sizes); i++) {
+ ALL_PERF_TESTS_FOR_SIZE((size_t)buf_sizes[i]);
+ }
+}
+
+/* Run all memcpy tests for unaligned variable cases */
+static inline void
+perf_test_variable_unaligned(void)
+{
+ unsigned i;
+ for (i = 0; i < RTE_DIM(buf_sizes); i++) {
+ ALL_PERF_TESTS_FOR_SIZE_UNALIGNED((size_t)buf_sizes[i]);
+ }
+}
+
+/* Run all memcpy tests */
+static int
+perf_test(void)
+{
+ int ret;
+ struct timeval tv_begin, tv_end;
+ double time_aligned, time_unaligned;
+ double time_aligned_const, time_unaligned_const;
+
+ ret = init_buffers();
+ if (ret != 0)
+ return ret;
+
+#if TEST_VALUE_RANGE != 0
+ /* Set up buf_sizes array, if required */
+ unsigned i;
+ for (i = 0; i < TEST_VALUE_RANGE; i++)
+ buf_sizes[i] = i;
+#endif
+
+ /* See function comment */
+ do_uncached_write(large_buf_write, 0, small_buf_read, 1, SMALL_BUFFER_SIZE);
+
+ printf("\n** rte_memcpy() - memcpy perf. tests (C = compile-time constant) **\n"
+ "======= ================= ================= ================= =================\n"
+ " Size Cache to cache Cache to mem Mem to cache Mem to mem\n"
+ "(bytes) (ticks) (ticks) (ticks) (ticks)\n"
+ "------- ----------------- ----------------- ----------------- -----------------");
+
+ printf("\n================================= %2dB aligned =================================",
+ ALIGNMENT_UNIT);
+ /* Do aligned tests where size is a variable */
+ gettimeofday(&tv_begin, NULL);
+ perf_test_variable_aligned();
+ gettimeofday(&tv_end, NULL);
+ time_aligned = (double)(tv_end.tv_sec - tv_begin.tv_sec)
+ + ((double)tv_end.tv_usec - tv_begin.tv_usec)/1000000;
+ printf("\n------- ----------------- ----------------- ----------------- -----------------");
+ /* Do aligned tests where size is a compile-time constant */
+ gettimeofday(&tv_begin, NULL);
+ perf_test_constant_aligned();
+ gettimeofday(&tv_end, NULL);
+ time_aligned_const = (double)(tv_end.tv_sec - tv_begin.tv_sec)
+ + ((double)tv_end.tv_usec - tv_begin.tv_usec)/1000000;
+ printf("\n================================== Unaligned ==================================");
+ /* Do unaligned tests where size is a variable */
+ gettimeofday(&tv_begin, NULL);
+ perf_test_variable_unaligned();
+ gettimeofday(&tv_end, NULL);
+ time_unaligned = (double)(tv_end.tv_sec - tv_begin.tv_sec)
+ + ((double)tv_end.tv_usec - tv_begin.tv_usec)/1000000;
+ printf("\n------- ----------------- ----------------- ----------------- -----------------");
+ /* Do unaligned tests where size is a compile-time constant */
+ gettimeofday(&tv_begin, NULL);
+ perf_test_constant_unaligned();
+ gettimeofday(&tv_end, NULL);
+ time_unaligned_const = (double)(tv_end.tv_sec - tv_begin.tv_sec)
+ + ((double)tv_end.tv_usec - tv_begin.tv_usec)/1000000;
+ printf("\n======= ================= ================= ================= =================\n\n");
+
+ printf("Test Execution Time (seconds):\n");
+ printf("Aligned variable copy size = %8.3f\n", time_aligned);
+ printf("Aligned constant copy size = %8.3f\n", time_aligned_const);
+ printf("Unaligned variable copy size = %8.3f\n", time_unaligned);
+ printf("Unaligned constant copy size = %8.3f\n", time_unaligned_const);
+ free_buffers();
+
+ return 0;
+}
+
+static int
+test_memcpy_perf(void)
+{
+ int ret;
+
+ ret = perf_test();
+ if (ret != 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(memcpy_perf_autotest, test_memcpy_perf);
diff --git a/src/spdk/dpdk/app/test/test_memory.c b/src/spdk/dpdk/app/test/test_memory.c
new file mode 100644
index 000000000..7d5ae99ba
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_memory.c
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_eal.h>
+#include <rte_memory.h>
+#include <rte_common.h>
+#include <rte_memzone.h>
+
+#include "test.h"
+
+/*
+ * Memory
+ * ======
+ *
+ * - Dump the mapped memory. The python-expect script checks that at
+ * least one line is dumped.
+ *
+ * - Check that memory size is different than 0.
+ *
+ * - Try to read all memory; it should not segfault.
+ */
+
+static int
+check_mem(const struct rte_memseg_list *msl __rte_unused,
+ const struct rte_memseg *ms, void *arg __rte_unused)
+{
+ volatile uint8_t *mem = (volatile uint8_t *) ms->addr;
+ size_t i, max = ms->len;
+
+ for (i = 0; i < max; i++, mem++)
+ *mem;
+ return 0;
+}
+
+static int
+check_seg_fds(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
+ void *arg __rte_unused)
+{
+ size_t offset;
+ int ret;
+
+ /* skip external segments */
+ if (msl->external)
+ return 0;
+
+ /* try segment fd first. we're in a callback, so thread-unsafe */
+ ret = rte_memseg_get_fd_thread_unsafe(ms);
+ if (ret < 0) {
+ /* ENOTSUP means segment is valid, but there is not support for
+ * segment fd API (e.g. on FreeBSD).
+ */
+ if (errno == ENOTSUP)
+ return 1;
+ /* all other errors are treated as failures */
+ return -1;
+ }
+
+ /* we're able to get memseg fd - try getting its offset */
+ ret = rte_memseg_get_fd_offset_thread_unsafe(ms, &offset);
+ if (ret < 0) {
+ if (errno == ENOTSUP)
+ return 1;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_memory(void)
+{
+ uint64_t s;
+ int ret;
+
+ /*
+ * dump the mapped memory: the python-expect script checks
+ * that at least one line is dumped
+ */
+ printf("Dump memory layout\n");
+ rte_dump_physmem_layout(stdout);
+
+ /* check that memory size is != 0 */
+ s = rte_eal_get_physmem_size();
+ if (s == 0) {
+ printf("No memory detected\n");
+ return -1;
+ }
+
+ /* try to read memory (should not segfault) */
+ rte_memseg_walk(check_mem, NULL);
+
+ /* check segment fd support */
+ ret = rte_memseg_walk(check_seg_fds, NULL);
+ if (ret == 1) {
+ printf("Segment fd API is unsupported\n");
+ } else if (ret == -1) {
+ printf("Error getting segment fd's\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(memory_autotest, test_memory);
diff --git a/src/spdk/dpdk/app/test/test_mempool.c b/src/spdk/dpdk/app/test/test_mempool.c
new file mode 100644
index 000000000..084842fda
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_mempool.c
@@ -0,0 +1,668 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_spinlock.h>
+#include <rte_malloc.h>
+#include <rte_mbuf_pool_ops.h>
+#include <rte_mbuf.h>
+
+#include "test.h"
+
+/*
+ * Mempool
+ * =======
+ *
+ * Basic tests: done on one core with and without cache:
+ *
+ * - Get one object, put one object
+ * - Get two objects, put two objects
+ * - Get all objects, test that their content is not modified and
+ * put them back in the pool.
+ */
+
+#define MEMPOOL_ELT_SIZE 2048
+#define MAX_KEEP 16
+#define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE))-1)
+
+#define LOG_ERR() printf("test failed at %s():%d\n", __func__, __LINE__)
+#define RET_ERR() do { \
+ LOG_ERR(); \
+ return -1; \
+ } while (0)
+#define GOTO_ERR(var, label) do { \
+ LOG_ERR(); \
+ var = -1; \
+ goto label; \
+ } while (0)
+
+static rte_atomic32_t synchro;
+
+/*
+ * save the object number in the first 4 bytes of object data. All
+ * other bytes are set to 0.
+ */
+static void
+my_obj_init(struct rte_mempool *mp, __rte_unused void *arg,
+ void *obj, unsigned i)
+{
+ uint32_t *objnum = obj;
+
+ memset(obj, 0, mp->elt_size);
+ *objnum = i;
+}
+
+/* basic tests (done on one core) */
+static int
+test_mempool_basic(struct rte_mempool *mp, int use_external_cache)
+{
+ uint32_t *objnum;
+ void **objtable;
+ void *obj, *obj2;
+ char *obj_data;
+ int ret = 0;
+ unsigned i, j;
+ int offset;
+ struct rte_mempool_cache *cache;
+
+ if (use_external_cache) {
+ /* Create a user-owned mempool cache. */
+ cache = rte_mempool_cache_create(RTE_MEMPOOL_CACHE_MAX_SIZE,
+ SOCKET_ID_ANY);
+ if (cache == NULL)
+ RET_ERR();
+ } else {
+ /* May be NULL if cache is disabled. */
+ cache = rte_mempool_default_cache(mp, rte_lcore_id());
+ }
+
+ /* dump the mempool status */
+ rte_mempool_dump(stdout, mp);
+
+ printf("get an object\n");
+ if (rte_mempool_generic_get(mp, &obj, 1, cache) < 0)
+ GOTO_ERR(ret, out);
+ rte_mempool_dump(stdout, mp);
+
+ /* tests that improve coverage */
+ printf("get object count\n");
+ /* We have to count the extra caches, one in this case. */
+ offset = use_external_cache ? 1 * cache->len : 0;
+ if (rte_mempool_avail_count(mp) + offset != MEMPOOL_SIZE - 1)
+ GOTO_ERR(ret, out);
+
+ printf("get private data\n");
+ if (rte_mempool_get_priv(mp) != (char *)mp +
+ MEMPOOL_HEADER_SIZE(mp, mp->cache_size))
+ GOTO_ERR(ret, out);
+
+#ifndef RTE_EXEC_ENV_FREEBSD /* rte_mem_virt2iova() not supported on bsd */
+ printf("get physical address of an object\n");
+ if (rte_mempool_virt2iova(obj) != rte_mem_virt2iova(obj))
+ GOTO_ERR(ret, out);
+#endif
+
+ printf("put the object back\n");
+ rte_mempool_generic_put(mp, &obj, 1, cache);
+ rte_mempool_dump(stdout, mp);
+
+ printf("get 2 objects\n");
+ if (rte_mempool_generic_get(mp, &obj, 1, cache) < 0)
+ GOTO_ERR(ret, out);
+ if (rte_mempool_generic_get(mp, &obj2, 1, cache) < 0) {
+ rte_mempool_generic_put(mp, &obj, 1, cache);
+ GOTO_ERR(ret, out);
+ }
+ rte_mempool_dump(stdout, mp);
+
+ printf("put the objects back\n");
+ rte_mempool_generic_put(mp, &obj, 1, cache);
+ rte_mempool_generic_put(mp, &obj2, 1, cache);
+ rte_mempool_dump(stdout, mp);
+
+ /*
+ * get many objects: we cannot get them all because the cache
+ * on other cores may not be empty.
+ */
+ objtable = malloc(MEMPOOL_SIZE * sizeof(void *));
+ if (objtable == NULL)
+ GOTO_ERR(ret, out);
+
+ for (i = 0; i < MEMPOOL_SIZE; i++) {
+ if (rte_mempool_generic_get(mp, &objtable[i], 1, cache) < 0)
+ break;
+ }
+
+ /*
+ * for each object, check that its content was not modified,
+ * and put objects back in pool
+ */
+ while (i--) {
+ obj = objtable[i];
+ obj_data = obj;
+ objnum = obj;
+ if (*objnum > MEMPOOL_SIZE) {
+ printf("bad object number(%d)\n", *objnum);
+ ret = -1;
+ break;
+ }
+ for (j = sizeof(*objnum); j < mp->elt_size; j++) {
+ if (obj_data[j] != 0)
+ ret = -1;
+ }
+
+ rte_mempool_generic_put(mp, &objtable[i], 1, cache);
+ }
+
+ free(objtable);
+ if (ret == -1)
+ printf("objects were modified!\n");
+
+out:
+ if (use_external_cache) {
+ rte_mempool_cache_flush(cache, mp);
+ rte_mempool_cache_free(cache);
+ }
+
+ return ret;
+}
+
+static int test_mempool_creation_with_exceeded_cache_size(void)
+{
+ struct rte_mempool *mp_cov;
+
+ mp_cov = rte_mempool_create("test_mempool_cache_too_big",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE + 32, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_cov != NULL) {
+ rte_mempool_free(mp_cov);
+ RET_ERR();
+ }
+
+ return 0;
+}
+
+static struct rte_mempool *mp_spsc;
+static rte_spinlock_t scsp_spinlock;
+static void *scsp_obj_table[MAX_KEEP];
+
+/*
+ * single producer function
+ */
+static int test_mempool_single_producer(void)
+{
+ unsigned int i;
+ void *obj = NULL;
+ uint64_t start_cycles, end_cycles;
+ uint64_t duration = rte_get_timer_hz() / 4;
+
+ start_cycles = rte_get_timer_cycles();
+ while (1) {
+ end_cycles = rte_get_timer_cycles();
+ /* duration uses up, stop producing */
+ if (start_cycles + duration < end_cycles)
+ break;
+ rte_spinlock_lock(&scsp_spinlock);
+ for (i = 0; i < MAX_KEEP; i ++) {
+ if (NULL != scsp_obj_table[i]) {
+ obj = scsp_obj_table[i];
+ break;
+ }
+ }
+ rte_spinlock_unlock(&scsp_spinlock);
+ if (i >= MAX_KEEP) {
+ continue;
+ }
+ if (rte_mempool_from_obj(obj) != mp_spsc) {
+ printf("obj not owned by this mempool\n");
+ RET_ERR();
+ }
+ rte_mempool_put(mp_spsc, obj);
+ rte_spinlock_lock(&scsp_spinlock);
+ scsp_obj_table[i] = NULL;
+ rte_spinlock_unlock(&scsp_spinlock);
+ }
+
+ return 0;
+}
+
+/*
+ * single consumer function
+ */
+static int test_mempool_single_consumer(void)
+{
+ unsigned int i;
+ void * obj;
+ uint64_t start_cycles, end_cycles;
+ uint64_t duration = rte_get_timer_hz() / 8;
+
+ start_cycles = rte_get_timer_cycles();
+ while (1) {
+ end_cycles = rte_get_timer_cycles();
+ /* duration uses up, stop consuming */
+ if (start_cycles + duration < end_cycles)
+ break;
+ rte_spinlock_lock(&scsp_spinlock);
+ for (i = 0; i < MAX_KEEP; i ++) {
+ if (NULL == scsp_obj_table[i])
+ break;
+ }
+ rte_spinlock_unlock(&scsp_spinlock);
+ if (i >= MAX_KEEP)
+ continue;
+ if (rte_mempool_get(mp_spsc, &obj) < 0)
+ break;
+ rte_spinlock_lock(&scsp_spinlock);
+ scsp_obj_table[i] = obj;
+ rte_spinlock_unlock(&scsp_spinlock);
+ }
+
+ return 0;
+}
+
+/*
+ * test function for mempool test based on singple consumer and single producer,
+ * can run on one lcore only
+ */
+static int
+test_mempool_launch_single_consumer(__rte_unused void *arg)
+{
+ return test_mempool_single_consumer();
+}
+
+static void
+my_mp_init(struct rte_mempool *mp, __rte_unused void *arg)
+{
+ printf("mempool name is %s\n", mp->name);
+ /* nothing to be implemented here*/
+ return ;
+}
+
+/*
+ * it tests the mempool operations based on singple producer and single consumer
+ */
+static int
+test_mempool_sp_sc(void)
+{
+ int ret = 0;
+ unsigned lcore_id = rte_lcore_id();
+ unsigned lcore_next;
+
+ /* create a mempool with single producer/consumer ring */
+ if (mp_spsc == NULL) {
+ mp_spsc = rte_mempool_create("test_mempool_sp_sc", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ my_mp_init, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY,
+ MEMPOOL_F_NO_CACHE_ALIGN | MEMPOOL_F_SP_PUT |
+ MEMPOOL_F_SC_GET);
+ if (mp_spsc == NULL)
+ RET_ERR();
+ }
+ if (rte_mempool_lookup("test_mempool_sp_sc") != mp_spsc) {
+ printf("Cannot lookup mempool from its name\n");
+ ret = -1;
+ goto err;
+ }
+ lcore_next = rte_get_next_lcore(lcore_id, 0, 1);
+ if (lcore_next >= RTE_MAX_LCORE) {
+ ret = -1;
+ goto err;
+ }
+ if (rte_eal_lcore_role(lcore_next) != ROLE_RTE) {
+ ret = -1;
+ goto err;
+ }
+ rte_spinlock_init(&scsp_spinlock);
+ memset(scsp_obj_table, 0, sizeof(scsp_obj_table));
+ rte_eal_remote_launch(test_mempool_launch_single_consumer, NULL,
+ lcore_next);
+ if (test_mempool_single_producer() < 0)
+ ret = -1;
+
+ if (rte_eal_wait_lcore(lcore_next) < 0)
+ ret = -1;
+
+err:
+ rte_mempool_free(mp_spsc);
+ mp_spsc = NULL;
+
+ return ret;
+}
+
+/*
+ * it tests some more basic of mempool
+ */
+static int
+test_mempool_basic_ex(struct rte_mempool *mp)
+{
+ unsigned i;
+ void **obj;
+ void *err_obj;
+ int ret = -1;
+
+ if (mp == NULL)
+ return ret;
+
+ obj = rte_calloc("test_mempool_basic_ex", MEMPOOL_SIZE,
+ sizeof(void *), 0);
+ if (obj == NULL) {
+ printf("test_mempool_basic_ex fail to rte_malloc\n");
+ return ret;
+ }
+ printf("test_mempool_basic_ex now mempool (%s) has %u free entries\n",
+ mp->name, rte_mempool_in_use_count(mp));
+ if (rte_mempool_full(mp) != 1) {
+ printf("test_mempool_basic_ex the mempool should be full\n");
+ goto fail_mp_basic_ex;
+ }
+
+ for (i = 0; i < MEMPOOL_SIZE; i ++) {
+ if (rte_mempool_get(mp, &obj[i]) < 0) {
+ printf("test_mp_basic_ex fail to get object for [%u]\n",
+ i);
+ goto fail_mp_basic_ex;
+ }
+ }
+ if (rte_mempool_get(mp, &err_obj) == 0) {
+ printf("test_mempool_basic_ex get an impossible obj\n");
+ goto fail_mp_basic_ex;
+ }
+ printf("number: %u\n", i);
+ if (rte_mempool_empty(mp) != 1) {
+ printf("test_mempool_basic_ex the mempool should be empty\n");
+ goto fail_mp_basic_ex;
+ }
+
+ for (i = 0; i < MEMPOOL_SIZE; i++)
+ rte_mempool_put(mp, obj[i]);
+
+ if (rte_mempool_full(mp) != 1) {
+ printf("test_mempool_basic_ex the mempool should be full\n");
+ goto fail_mp_basic_ex;
+ }
+
+ ret = 0;
+
+fail_mp_basic_ex:
+ if (obj != NULL)
+ rte_free((void *)obj);
+
+ return ret;
+}
+
+static int
+test_mempool_same_name_twice_creation(void)
+{
+ struct rte_mempool *mp_tc, *mp_tc2;
+
+ mp_tc = rte_mempool_create("test_mempool_same_name", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ NULL, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_tc == NULL)
+ RET_ERR();
+
+ mp_tc2 = rte_mempool_create("test_mempool_same_name", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ NULL, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_tc2 != NULL) {
+ rte_mempool_free(mp_tc);
+ rte_mempool_free(mp_tc2);
+ RET_ERR();
+ }
+
+ rte_mempool_free(mp_tc);
+ return 0;
+}
+
+static void
+walk_cb(struct rte_mempool *mp, void *userdata __rte_unused)
+{
+ printf("\t%s\n", mp->name);
+}
+
+struct mp_data {
+ int16_t ret;
+};
+
+static void
+test_mp_mem_init(struct rte_mempool *mp,
+ __rte_unused void *opaque,
+ __rte_unused struct rte_mempool_memhdr *memhdr,
+ __rte_unused unsigned int mem_idx)
+{
+ struct mp_data *data = opaque;
+
+ if (mp == NULL) {
+ data->ret = -1;
+ return;
+ }
+ /* nothing to be implemented here*/
+ data->ret = 0;
+}
+
+static int
+test_mempool(void)
+{
+ int ret = -1;
+ uint32_t nb_objs = 0;
+ uint32_t nb_mem_chunks = 0;
+ struct rte_mempool *mp_cache = NULL;
+ struct rte_mempool *mp_nocache = NULL;
+ struct rte_mempool *mp_stack_anon = NULL;
+ struct rte_mempool *mp_stack_mempool_iter = NULL;
+ struct rte_mempool *mp_stack = NULL;
+ struct rte_mempool *default_pool = NULL;
+ struct mp_data cb_arg = {
+ .ret = -1
+ };
+ const char *default_pool_ops = rte_mbuf_best_mempool_ops();
+
+ rte_atomic32_init(&synchro);
+
+ /* create a mempool (without cache) */
+ mp_nocache = rte_mempool_create("test_nocache", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_nocache == NULL) {
+ printf("cannot allocate mp_nocache mempool\n");
+ GOTO_ERR(ret, err);
+ }
+
+ /* create a mempool (with cache) */
+ mp_cache = rte_mempool_create("test_cache", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_cache == NULL) {
+ printf("cannot allocate mp_cache mempool\n");
+ GOTO_ERR(ret, err);
+ }
+
+ /* create an empty mempool */
+ mp_stack_anon = rte_mempool_create_empty("test_stack_anon",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_stack_anon == NULL)
+ GOTO_ERR(ret, err);
+
+ /* populate an empty mempool */
+ ret = rte_mempool_populate_anon(mp_stack_anon);
+ printf("%s ret = %d\n", __func__, ret);
+ if (ret < 0)
+ GOTO_ERR(ret, err);
+
+ /* Try to populate when already populated */
+ ret = rte_mempool_populate_anon(mp_stack_anon);
+ if (ret != 0)
+ GOTO_ERR(ret, err);
+
+ /* create a mempool */
+ mp_stack_mempool_iter = rte_mempool_create("test_iter_obj",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_stack_mempool_iter == NULL)
+ GOTO_ERR(ret, err);
+
+ /* test to initialize mempool objects and memory */
+ nb_objs = rte_mempool_obj_iter(mp_stack_mempool_iter, rte_pktmbuf_init,
+ NULL);
+ if (nb_objs == 0)
+ GOTO_ERR(ret, err);
+
+ nb_mem_chunks = rte_mempool_mem_iter(mp_stack_mempool_iter,
+ test_mp_mem_init, &cb_arg);
+ if (nb_mem_chunks == 0 || cb_arg.ret < 0)
+ GOTO_ERR(ret, err);
+
+ /* create a mempool with an external handler */
+ mp_stack = rte_mempool_create_empty("test_stack",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ SOCKET_ID_ANY, 0);
+
+ if (mp_stack == NULL) {
+ printf("cannot allocate mp_stack mempool\n");
+ GOTO_ERR(ret, err);
+ }
+ if (rte_mempool_set_ops_byname(mp_stack, "stack", NULL) < 0) {
+ printf("cannot set stack handler\n");
+ GOTO_ERR(ret, err);
+ }
+ if (rte_mempool_populate_default(mp_stack) < 0) {
+ printf("cannot populate mp_stack mempool\n");
+ GOTO_ERR(ret, err);
+ }
+ rte_mempool_obj_iter(mp_stack, my_obj_init, NULL);
+
+ /* Create a mempool based on Default handler */
+ printf("Testing %s mempool handler\n", default_pool_ops);
+ default_pool = rte_mempool_create_empty("default_pool",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ SOCKET_ID_ANY, 0);
+
+ if (default_pool == NULL) {
+ printf("cannot allocate default mempool\n");
+ GOTO_ERR(ret, err);
+ }
+ if (rte_mempool_set_ops_byname(default_pool,
+ default_pool_ops, NULL) < 0) {
+ printf("cannot set %s handler\n", default_pool_ops);
+ GOTO_ERR(ret, err);
+ }
+ if (rte_mempool_populate_default(default_pool) < 0) {
+ printf("cannot populate %s mempool\n", default_pool_ops);
+ GOTO_ERR(ret, err);
+ }
+ rte_mempool_obj_iter(default_pool, my_obj_init, NULL);
+
+ /* retrieve the mempool from its name */
+ if (rte_mempool_lookup("test_nocache") != mp_nocache) {
+ printf("Cannot lookup mempool from its name\n");
+ GOTO_ERR(ret, err);
+ }
+
+ printf("Walk into mempools:\n");
+ rte_mempool_walk(walk_cb, NULL);
+
+ rte_mempool_list_dump(stdout);
+
+ /* basic tests without cache */
+ if (test_mempool_basic(mp_nocache, 0) < 0)
+ GOTO_ERR(ret, err);
+
+ /* basic tests with cache */
+ if (test_mempool_basic(mp_cache, 0) < 0)
+ GOTO_ERR(ret, err);
+
+ /* basic tests with user-owned cache */
+ if (test_mempool_basic(mp_nocache, 1) < 0)
+ GOTO_ERR(ret, err);
+
+ /* more basic tests without cache */
+ if (test_mempool_basic_ex(mp_nocache) < 0)
+ GOTO_ERR(ret, err);
+
+ /* mempool operation test based on single producer and single comsumer */
+ if (test_mempool_sp_sc() < 0)
+ GOTO_ERR(ret, err);
+
+ if (test_mempool_creation_with_exceeded_cache_size() < 0)
+ GOTO_ERR(ret, err);
+
+ if (test_mempool_same_name_twice_creation() < 0)
+ GOTO_ERR(ret, err);
+
+ /* test the stack handler */
+ if (test_mempool_basic(mp_stack, 1) < 0)
+ GOTO_ERR(ret, err);
+
+ if (test_mempool_basic(default_pool, 1) < 0)
+ GOTO_ERR(ret, err);
+
+ rte_mempool_list_dump(stdout);
+
+ ret = 0;
+
+err:
+ rte_mempool_free(mp_nocache);
+ rte_mempool_free(mp_cache);
+ rte_mempool_free(mp_stack_anon);
+ rte_mempool_free(mp_stack_mempool_iter);
+ rte_mempool_free(mp_stack);
+ rte_mempool_free(default_pool);
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(mempool_autotest, test_mempool);
diff --git a/src/spdk/dpdk/app/test/test_mempool_perf.c b/src/spdk/dpdk/app/test/test_mempool_perf.c
new file mode 100644
index 000000000..60bda8aad
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_mempool_perf.c
@@ -0,0 +1,399 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_mempool.h>
+#include <rte_spinlock.h>
+#include <rte_malloc.h>
+#include <rte_mbuf_pool_ops.h>
+
+#include "test.h"
+
+/*
+ * Mempool performance
+ * =======
+ *
+ * Each core get *n_keep* objects per bulk of *n_get_bulk*. Then,
+ * objects are put back in the pool per bulk of *n_put_bulk*.
+ *
+ * This sequence is done during TIME_S seconds.
+ *
+ * This test is done on the following configurations:
+ *
+ * - Cores configuration (*cores*)
+ *
+ * - One core with cache
+ * - Two cores with cache
+ * - Max. cores with cache
+ * - One core without cache
+ * - Two cores without cache
+ * - Max. cores without cache
+ * - One core with user-owned cache
+ * - Two cores with user-owned cache
+ * - Max. cores with user-owned cache
+ *
+ * - Bulk size (*n_get_bulk*, *n_put_bulk*)
+ *
+ * - Bulk get from 1 to 32
+ * - Bulk put from 1 to 32
+ *
+ * - Number of kept objects (*n_keep*)
+ *
+ * - 32
+ * - 128
+ */
+
+#define N 65536
+#define TIME_S 5
+#define MEMPOOL_ELT_SIZE 2048
+#define MAX_KEEP 128
+#define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE))-1)
+
+#define LOG_ERR() printf("test failed at %s():%d\n", __func__, __LINE__)
+#define RET_ERR() do { \
+ LOG_ERR(); \
+ return -1; \
+ } while (0)
+#define GOTO_ERR(var, label) do { \
+ LOG_ERR(); \
+ var = -1; \
+ goto label; \
+ } while (0)
+
+static int use_external_cache;
+static unsigned external_cache_size = RTE_MEMPOOL_CACHE_MAX_SIZE;
+
+static rte_atomic32_t synchro;
+
+/* number of objects in one bulk operation (get or put) */
+static unsigned n_get_bulk;
+static unsigned n_put_bulk;
+
+/* number of objects retrived from mempool before putting them back */
+static unsigned n_keep;
+
+/* number of enqueues / dequeues */
+struct mempool_test_stats {
+ uint64_t enq_count;
+} __rte_cache_aligned;
+
+static struct mempool_test_stats stats[RTE_MAX_LCORE];
+
+/*
+ * save the object number in the first 4 bytes of object data. All
+ * other bytes are set to 0.
+ */
+static void
+my_obj_init(struct rte_mempool *mp, __rte_unused void *arg,
+ void *obj, unsigned i)
+{
+ uint32_t *objnum = obj;
+ memset(obj, 0, mp->elt_size);
+ *objnum = i;
+}
+
+static int
+per_lcore_mempool_test(void *arg)
+{
+ void *obj_table[MAX_KEEP];
+ unsigned i, idx;
+ struct rte_mempool *mp = arg;
+ unsigned lcore_id = rte_lcore_id();
+ int ret = 0;
+ uint64_t start_cycles, end_cycles;
+ uint64_t time_diff = 0, hz = rte_get_timer_hz();
+ struct rte_mempool_cache *cache;
+
+ if (use_external_cache) {
+ /* Create a user-owned mempool cache. */
+ cache = rte_mempool_cache_create(external_cache_size,
+ SOCKET_ID_ANY);
+ if (cache == NULL)
+ RET_ERR();
+ } else {
+ /* May be NULL if cache is disabled. */
+ cache = rte_mempool_default_cache(mp, lcore_id);
+ }
+
+ /* n_get_bulk and n_put_bulk must be divisors of n_keep */
+ if (((n_keep / n_get_bulk) * n_get_bulk) != n_keep)
+ GOTO_ERR(ret, out);
+ if (((n_keep / n_put_bulk) * n_put_bulk) != n_keep)
+ GOTO_ERR(ret, out);
+
+ stats[lcore_id].enq_count = 0;
+
+ /* wait synchro for slaves */
+ if (lcore_id != rte_get_master_lcore())
+ while (rte_atomic32_read(&synchro) == 0);
+
+ start_cycles = rte_get_timer_cycles();
+
+ while (time_diff/hz < TIME_S) {
+ for (i = 0; likely(i < (N/n_keep)); i++) {
+ /* get n_keep objects by bulk of n_bulk */
+ idx = 0;
+ while (idx < n_keep) {
+ ret = rte_mempool_generic_get(mp,
+ &obj_table[idx],
+ n_get_bulk,
+ cache);
+ if (unlikely(ret < 0)) {
+ rte_mempool_dump(stdout, mp);
+ /* in this case, objects are lost... */
+ GOTO_ERR(ret, out);
+ }
+ idx += n_get_bulk;
+ }
+
+ /* put the objects back */
+ idx = 0;
+ while (idx < n_keep) {
+ rte_mempool_generic_put(mp, &obj_table[idx],
+ n_put_bulk,
+ cache);
+ idx += n_put_bulk;
+ }
+ }
+ end_cycles = rte_get_timer_cycles();
+ time_diff = end_cycles - start_cycles;
+ stats[lcore_id].enq_count += N;
+ }
+
+out:
+ if (use_external_cache) {
+ rte_mempool_cache_flush(cache, mp);
+ rte_mempool_cache_free(cache);
+ }
+
+ return ret;
+}
+
+/* launch all the per-lcore test, and display the result */
+static int
+launch_cores(struct rte_mempool *mp, unsigned int cores)
+{
+ unsigned lcore_id;
+ uint64_t rate;
+ int ret;
+ unsigned cores_save = cores;
+
+ rte_atomic32_set(&synchro, 0);
+
+ /* reset stats */
+ memset(stats, 0, sizeof(stats));
+
+ printf("mempool_autotest cache=%u cores=%u n_get_bulk=%u "
+ "n_put_bulk=%u n_keep=%u ",
+ use_external_cache ?
+ external_cache_size : (unsigned) mp->cache_size,
+ cores, n_get_bulk, n_put_bulk, n_keep);
+
+ if (rte_mempool_avail_count(mp) != MEMPOOL_SIZE) {
+ printf("mempool is not full\n");
+ return -1;
+ }
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (cores == 1)
+ break;
+ cores--;
+ rte_eal_remote_launch(per_lcore_mempool_test,
+ mp, lcore_id);
+ }
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+
+ ret = per_lcore_mempool_test(mp);
+
+ cores = cores_save;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (cores == 1)
+ break;
+ cores--;
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ ret = -1;
+ }
+
+ if (ret < 0) {
+ printf("per-lcore test returned -1\n");
+ return -1;
+ }
+
+ rate = 0;
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++)
+ rate += (stats[lcore_id].enq_count / TIME_S);
+
+ printf("rate_persec=%" PRIu64 "\n", rate);
+
+ return 0;
+}
+
+/* for a given number of core, launch all test cases */
+static int
+do_one_mempool_test(struct rte_mempool *mp, unsigned int cores)
+{
+ unsigned bulk_tab_get[] = { 1, 4, 32, 0 };
+ unsigned bulk_tab_put[] = { 1, 4, 32, 0 };
+ unsigned keep_tab[] = { 32, 128, 0 };
+ unsigned *get_bulk_ptr;
+ unsigned *put_bulk_ptr;
+ unsigned *keep_ptr;
+ int ret;
+
+ for (get_bulk_ptr = bulk_tab_get; *get_bulk_ptr; get_bulk_ptr++) {
+ for (put_bulk_ptr = bulk_tab_put; *put_bulk_ptr; put_bulk_ptr++) {
+ for (keep_ptr = keep_tab; *keep_ptr; keep_ptr++) {
+
+ n_get_bulk = *get_bulk_ptr;
+ n_put_bulk = *put_bulk_ptr;
+ n_keep = *keep_ptr;
+ ret = launch_cores(mp, cores);
+
+ if (ret < 0)
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+test_mempool_perf(void)
+{
+ struct rte_mempool *mp_cache = NULL;
+ struct rte_mempool *mp_nocache = NULL;
+ struct rte_mempool *default_pool = NULL;
+ const char *default_pool_ops;
+ int ret = -1;
+
+ rte_atomic32_init(&synchro);
+
+ /* create a mempool (without cache) */
+ mp_nocache = rte_mempool_create("perf_test_nocache", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE, 0, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+ if (mp_nocache == NULL)
+ goto err;
+
+ /* create a mempool (with cache) */
+ mp_cache = rte_mempool_create("perf_test_cache", MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
+ NULL, NULL,
+ my_obj_init, NULL,
+ SOCKET_ID_ANY, 0);
+ if (mp_cache == NULL)
+ goto err;
+
+ default_pool_ops = rte_mbuf_best_mempool_ops();
+ /* Create a mempool based on Default handler */
+ default_pool = rte_mempool_create_empty("default_pool",
+ MEMPOOL_SIZE,
+ MEMPOOL_ELT_SIZE,
+ 0, 0,
+ SOCKET_ID_ANY, 0);
+
+ if (default_pool == NULL) {
+ printf("cannot allocate %s mempool\n", default_pool_ops);
+ goto err;
+ }
+
+ if (rte_mempool_set_ops_byname(default_pool, default_pool_ops, NULL)
+ < 0) {
+ printf("cannot set %s handler\n", default_pool_ops);
+ goto err;
+ }
+
+ if (rte_mempool_populate_default(default_pool) < 0) {
+ printf("cannot populate %s mempool\n", default_pool_ops);
+ goto err;
+ }
+
+ rte_mempool_obj_iter(default_pool, my_obj_init, NULL);
+
+ /* performance test with 1, 2 and max cores */
+ printf("start performance test (without cache)\n");
+
+ if (do_one_mempool_test(mp_nocache, 1) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_nocache, 2) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_nocache, rte_lcore_count()) < 0)
+ goto err;
+
+ /* performance test with 1, 2 and max cores */
+ printf("start performance test for %s (without cache)\n",
+ default_pool_ops);
+
+ if (do_one_mempool_test(default_pool, 1) < 0)
+ goto err;
+
+ if (do_one_mempool_test(default_pool, 2) < 0)
+ goto err;
+
+ if (do_one_mempool_test(default_pool, rte_lcore_count()) < 0)
+ goto err;
+
+ /* performance test with 1, 2 and max cores */
+ printf("start performance test (with cache)\n");
+
+ if (do_one_mempool_test(mp_cache, 1) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_cache, 2) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_cache, rte_lcore_count()) < 0)
+ goto err;
+
+ /* performance test with 1, 2 and max cores */
+ printf("start performance test (with user-owned cache)\n");
+ use_external_cache = 1;
+
+ if (do_one_mempool_test(mp_nocache, 1) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_nocache, 2) < 0)
+ goto err;
+
+ if (do_one_mempool_test(mp_nocache, rte_lcore_count()) < 0)
+ goto err;
+
+ rte_mempool_list_dump(stdout);
+
+ ret = 0;
+
+err:
+ rte_mempool_free(mp_cache);
+ rte_mempool_free(mp_nocache);
+ rte_mempool_free(default_pool);
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(mempool_perf_autotest, test_mempool_perf);
diff --git a/src/spdk/dpdk/app/test/test_memzone.c b/src/spdk/dpdk/app/test/test_memzone.c
new file mode 100644
index 000000000..0343b0326
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_memzone.c
@@ -0,0 +1,1129 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_random.h>
+#include <rte_cycles.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include "../../lib/librte_eal/common/malloc_elem.h"
+
+#include "test.h"
+
+/*
+ * Memzone
+ * =======
+ *
+ * - Search for three reserved zones or reserve them if they do not exist:
+ *
+ * - One is on any socket id.
+ * - The second is on socket 0.
+ * - The last one is on socket 1 (if socket 1 exists).
+ *
+ * - Check that the zones exist.
+ *
+ * - Check that the zones are cache-aligned.
+ *
+ * - Check that zones do not overlap.
+ *
+ * - Check that the zones are on the correct socket id.
+ *
+ * - Check that a lookup of the first zone returns the same pointer.
+ *
+ * - Check that it is not possible to create another zone with the
+ * same name as an existing zone.
+ *
+ * - Check flags for specific huge page size reservation
+ */
+
+#define TEST_MEMZONE_NAME(suffix) "MZ_TEST_" suffix
+
+/* Test if memory overlaps: return 1 if true, or 0 if false. */
+static int
+is_memory_overlap(rte_iova_t ptr1, size_t len1, rte_iova_t ptr2, size_t len2)
+{
+ if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1)
+ return 1;
+ else if (ptr2 < ptr1 && (ptr1 - ptr2) < len2)
+ return 1;
+ return 0;
+}
+
+static int
+test_memzone_invalid_alignment(void)
+{
+ const struct rte_memzone * mz;
+
+ mz = rte_memzone_lookup(TEST_MEMZONE_NAME("invalid_alignment"));
+ if (mz != NULL) {
+ printf("Zone with invalid alignment has been reserved\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve_aligned(TEST_MEMZONE_NAME("invalid_alignment"),
+ 100, SOCKET_ID_ANY, 0, 100);
+ if (mz != NULL) {
+ printf("Zone with invalid alignment has been reserved\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_memzone_reserving_zone_size_bigger_than_the_maximum(void)
+{
+ const struct rte_memzone * mz;
+
+ mz = rte_memzone_lookup(
+ TEST_MEMZONE_NAME("zone_size_bigger_than_the_maximum"));
+ if (mz != NULL) {
+ printf("zone_size_bigger_than_the_maximum has been reserved\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("zone_size_bigger_than_the_maximum"),
+ (size_t)-1, SOCKET_ID_ANY, 0);
+ if (mz != NULL) {
+ printf("It is impossible to reserve such big a memzone\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+struct walk_arg {
+ int hugepage_2MB_avail;
+ int hugepage_1GB_avail;
+ int hugepage_16MB_avail;
+ int hugepage_16GB_avail;
+};
+static int
+find_available_pagesz(const struct rte_memseg_list *msl, void *arg)
+{
+ struct walk_arg *wa = arg;
+
+ if (msl->external)
+ return 0;
+
+ if (msl->page_sz == RTE_PGSIZE_2M)
+ wa->hugepage_2MB_avail = 1;
+ if (msl->page_sz == RTE_PGSIZE_1G)
+ wa->hugepage_1GB_avail = 1;
+ if (msl->page_sz == RTE_PGSIZE_16M)
+ wa->hugepage_16MB_avail = 1;
+ if (msl->page_sz == RTE_PGSIZE_16G)
+ wa->hugepage_16GB_avail = 1;
+
+ return 0;
+}
+
+static int
+test_memzone_reserve_flags(void)
+{
+ const struct rte_memzone *mz;
+ struct walk_arg wa;
+ int hugepage_2MB_avail, hugepage_1GB_avail;
+ int hugepage_16MB_avail, hugepage_16GB_avail;
+ const size_t size = 100;
+
+ memset(&wa, 0, sizeof(wa));
+
+ rte_memseg_list_walk(find_available_pagesz, &wa);
+
+ hugepage_2MB_avail = wa.hugepage_2MB_avail;
+ hugepage_1GB_avail = wa.hugepage_1GB_avail;
+ hugepage_16MB_avail = wa.hugepage_16MB_avail;
+ hugepage_16GB_avail = wa.hugepage_16GB_avail;
+
+ /* Display the availability of 2MB ,1GB, 16MB, 16GB pages */
+ if (hugepage_2MB_avail)
+ printf("2MB Huge pages available\n");
+ if (hugepage_1GB_avail)
+ printf("1GB Huge pages available\n");
+ if (hugepage_16MB_avail)
+ printf("16MB Huge pages available\n");
+ if (hugepage_16GB_avail)
+ printf("16GB Huge pages available\n");
+ /*
+ * If 2MB pages available, check that a small memzone is correctly
+ * reserved from 2MB huge pages when requested by the RTE_MEMZONE_2MB flag.
+ * Also check that RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an
+ * available page size (i.e 1GB ) when 2MB pages are unavailable.
+ */
+ if (hugepage_2MB_avail) {
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_2M"),
+ size, SOCKET_ID_ANY, RTE_MEMZONE_2MB);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 2MB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_2M) {
+ printf("hugepage_sz not equal 2M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_2M_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 2MB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_2M) {
+ printf("hugepage_sz not equal 2M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ /* Check if 1GB huge pages are unavailable, that function fails unless
+ * HINT flag is indicated
+ */
+ if (!hugepage_1GB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_1G_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 1GB & HINT\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_2M) {
+ printf("hugepage_sz not equal 2M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_1G"), size,
+ SOCKET_ID_ANY, RTE_MEMZONE_1GB);
+ if (mz != NULL) {
+ printf("MEMZONE FLAG 1GB\n");
+ return -1;
+ }
+ }
+ }
+
+ /*As with 2MB tests above for 1GB huge page requests*/
+ if (hugepage_1GB_avail) {
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_1G"),
+ size, SOCKET_ID_ANY, RTE_MEMZONE_1GB);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 1GB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_1G) {
+ printf("hugepage_sz not equal 1G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_1G_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_1GB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 1GB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_1G) {
+ printf("hugepage_sz not equal 1G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ /* Check if 1GB huge pages are unavailable, that function fails unless
+ * HINT flag is indicated
+ */
+ if (!hugepage_2MB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_2M_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL){
+ printf("MEMZONE FLAG 2MB & HINT\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_1G) {
+ printf("hugepage_sz not equal 1G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_2M"), size,
+ SOCKET_ID_ANY, RTE_MEMZONE_2MB);
+ if (mz != NULL) {
+ printf("MEMZONE FLAG 2MB\n");
+ return -1;
+ }
+ }
+
+ if (hugepage_2MB_avail && hugepage_1GB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_2M_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_2MB|RTE_MEMZONE_1GB);
+ if (mz == NULL) {
+ printf("BOTH SIZES SET\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_1G &&
+ mz->hugepage_sz != RTE_PGSIZE_2M) {
+ printf("Wrong size when both sizes set\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ }
+ }
+ /*
+ * This option is for IBM Power. If 16MB pages available, check
+ * that a small memzone is correctly reserved from 16MB huge pages
+ * when requested by the RTE_MEMZONE_16MB flag. Also check that
+ * RTE_MEMZONE_SIZE_HINT_ONLY flag only defaults to an available
+ * page size (i.e 16GB ) when 16MB pages are unavailable.
+ */
+ if (hugepage_16MB_avail) {
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_16M"),
+ size, SOCKET_ID_ANY, RTE_MEMZONE_16MB);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16MB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16M) {
+ printf("hugepage_sz not equal 16M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16M_HINT"), size,
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_16MB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16MB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16M) {
+ printf("hugepage_sz not equal 16M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ /* Check if 1GB huge pages are unavailable, that function fails
+ * unless HINT flag is indicated
+ */
+ if (!hugepage_16GB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16G_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_16GB |
+ RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16GB & HINT\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16M) {
+ printf("hugepage_sz not equal 16M\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16G"),
+ size,
+ SOCKET_ID_ANY, RTE_MEMZONE_16GB);
+ if (mz != NULL) {
+ printf("MEMZONE FLAG 16GB\n");
+ return -1;
+ }
+ }
+ }
+ /*As with 16MB tests above for 16GB huge page requests*/
+ if (hugepage_16GB_avail) {
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("flag_zone_16G"),
+ size, SOCKET_ID_ANY, RTE_MEMZONE_16GB);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16GB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16G) {
+ printf("hugepage_sz not equal 16G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16G_HINT"), size,
+ SOCKET_ID_ANY,
+ RTE_MEMZONE_16GB|RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16GB\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16G) {
+ printf("hugepage_sz not equal 16G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ /* Check if 1GB huge pages are unavailable, that function fails
+ * unless HINT flag is indicated
+ */
+ if (!hugepage_16MB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16M_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_16MB |
+ RTE_MEMZONE_SIZE_HINT_ONLY);
+ if (mz == NULL) {
+ printf("MEMZONE FLAG 16MB & HINT\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16G) {
+ printf("hugepage_sz not equal 16G\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16M"),
+ size, SOCKET_ID_ANY, RTE_MEMZONE_16MB);
+ if (mz != NULL) {
+ printf("MEMZONE FLAG 16MB\n");
+ return -1;
+ }
+ }
+
+ if (hugepage_16MB_avail && hugepage_16GB_avail) {
+ mz = rte_memzone_reserve(
+ TEST_MEMZONE_NAME("flag_zone_16M_HINT"),
+ size, SOCKET_ID_ANY,
+ RTE_MEMZONE_16MB|RTE_MEMZONE_16GB);
+ if (mz == NULL) {
+ printf("BOTH SIZES SET\n");
+ return -1;
+ }
+ if (mz->hugepage_sz != RTE_PGSIZE_16G &&
+ mz->hugepage_sz != RTE_PGSIZE_16M) {
+ printf("Wrong size when both sizes set\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* Find the heap with the greatest free block size */
+static size_t
+find_max_block_free_size(unsigned int align, unsigned int socket_id)
+{
+ struct rte_malloc_socket_stats stats;
+ size_t len, overhead;
+
+ if (rte_malloc_get_socket_stats(socket_id, &stats) < 0)
+ return 0;
+
+ len = stats.greatest_free_size;
+ overhead = MALLOC_ELEM_OVERHEAD;
+
+ if (len == 0)
+ return 0;
+
+ align = RTE_CACHE_LINE_ROUNDUP(align);
+ overhead += align;
+
+ if (len < overhead)
+ return 0;
+
+ return len - overhead;
+}
+
+static int
+test_memzone_reserve_max(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < rte_socket_count(); i++) {
+ const struct rte_memzone *mz;
+ size_t maxlen;
+ int socket;
+
+ socket = rte_socket_id_by_idx(i);
+ maxlen = find_max_block_free_size(0, socket);
+
+ if (maxlen == 0) {
+ printf("There is no space left!\n");
+ return 0;
+ }
+
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("max_zone"), 0,
+ socket, 0);
+ if (mz == NULL) {
+ printf("Failed to reserve a big chunk of memory - %s\n",
+ rte_strerror(rte_errno));
+ rte_dump_physmem_layout(stdout);
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+
+ if (mz->len != maxlen) {
+ printf("Memzone reserve with 0 size did not return bigest block\n");
+ printf("Expected size = %zu, actual size = %zu\n",
+ maxlen, mz->len);
+ rte_dump_physmem_layout(stdout);
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_memzone_reserve_max_aligned(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < rte_socket_count(); i++) {
+ const struct rte_memzone *mz;
+ size_t maxlen, minlen = 0;
+ int socket;
+
+ socket = rte_socket_id_by_idx(i);
+
+ /* random alignment */
+ rte_srand((unsigned int)rte_rdtsc());
+ const unsigned int align = 1 << ((rte_rand() % 8) + 5); /* from 128 up to 4k alignment */
+
+ /* memzone size may be between size and size - align */
+ minlen = find_max_block_free_size(align, socket);
+ maxlen = find_max_block_free_size(0, socket);
+
+ if (minlen == 0 || maxlen == 0) {
+ printf("There is no space left for biggest %u-aligned memzone!\n",
+ align);
+ return 0;
+ }
+
+ mz = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("max_zone_aligned"),
+ 0, socket, 0, align);
+ if (mz == NULL) {
+ printf("Failed to reserve a big chunk of memory - %s\n",
+ rte_strerror(rte_errno));
+ rte_dump_physmem_layout(stdout);
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+ if (mz->addr != RTE_PTR_ALIGN(mz->addr, align)) {
+ printf("Memzone reserve with 0 size and alignment %u did not return aligned block\n",
+ align);
+ rte_dump_physmem_layout(stdout);
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+
+ if (mz->len < minlen || mz->len > maxlen) {
+ printf("Memzone reserve with 0 size and alignment %u did not return"
+ " bigest block\n", align);
+ printf("Expected size = %zu-%zu, actual size = %zu\n",
+ minlen, maxlen, mz->len);
+ rte_dump_physmem_layout(stdout);
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+test_memzone_aligned(void)
+{
+ const struct rte_memzone *memzone_aligned_32;
+ const struct rte_memzone *memzone_aligned_128;
+ const struct rte_memzone *memzone_aligned_256;
+ const struct rte_memzone *memzone_aligned_512;
+ const struct rte_memzone *memzone_aligned_1024;
+
+ /* memzone that should automatically be adjusted to align on 64 bytes */
+ memzone_aligned_32 = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("aligned_32"), 100, SOCKET_ID_ANY, 0,
+ 32);
+
+ /* memzone that is supposed to be aligned on a 128 byte boundary */
+ memzone_aligned_128 = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("aligned_128"), 100, SOCKET_ID_ANY, 0,
+ 128);
+
+ /* memzone that is supposed to be aligned on a 256 byte boundary */
+ memzone_aligned_256 = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("aligned_256"), 100, SOCKET_ID_ANY, 0,
+ 256);
+
+ /* memzone that is supposed to be aligned on a 512 byte boundary */
+ memzone_aligned_512 = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("aligned_512"), 100, SOCKET_ID_ANY, 0,
+ 512);
+
+ /* memzone that is supposed to be aligned on a 1024 byte boundary */
+ memzone_aligned_1024 = rte_memzone_reserve_aligned(
+ TEST_MEMZONE_NAME("aligned_1024"), 100, SOCKET_ID_ANY,
+ 0, 1024);
+
+ printf("check alignments and lengths\n");
+ if (memzone_aligned_32 == NULL) {
+ printf("Unable to reserve 64-byte aligned memzone!\n");
+ return -1;
+ }
+ if ((memzone_aligned_32->iova & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+ if (((uintptr_t) memzone_aligned_32->addr & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+ if ((memzone_aligned_32->len & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+
+ if (memzone_aligned_128 == NULL) {
+ printf("Unable to reserve 128-byte aligned memzone!\n");
+ return -1;
+ }
+ if ((memzone_aligned_128->iova & 127) != 0)
+ return -1;
+ if (((uintptr_t) memzone_aligned_128->addr & 127) != 0)
+ return -1;
+ if ((memzone_aligned_128->len & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+
+ if (memzone_aligned_256 == NULL) {
+ printf("Unable to reserve 256-byte aligned memzone!\n");
+ return -1;
+ }
+ if ((memzone_aligned_256->iova & 255) != 0)
+ return -1;
+ if (((uintptr_t) memzone_aligned_256->addr & 255) != 0)
+ return -1;
+ if ((memzone_aligned_256->len & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+
+ if (memzone_aligned_512 == NULL) {
+ printf("Unable to reserve 512-byte aligned memzone!\n");
+ return -1;
+ }
+ if ((memzone_aligned_512->iova & 511) != 0)
+ return -1;
+ if (((uintptr_t) memzone_aligned_512->addr & 511) != 0)
+ return -1;
+ if ((memzone_aligned_512->len & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+
+ if (memzone_aligned_1024 == NULL) {
+ printf("Unable to reserve 1024-byte aligned memzone!\n");
+ return -1;
+ }
+ if ((memzone_aligned_1024->iova & 1023) != 0)
+ return -1;
+ if (((uintptr_t) memzone_aligned_1024->addr & 1023) != 0)
+ return -1;
+ if ((memzone_aligned_1024->len & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+
+ /* check that zones don't overlap */
+ printf("check overlapping\n");
+ if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
+ memzone_aligned_128->iova, memzone_aligned_128->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
+ memzone_aligned_256->iova, memzone_aligned_256->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
+ memzone_aligned_512->iova, memzone_aligned_512->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_32->iova, memzone_aligned_32->len,
+ memzone_aligned_1024->iova, memzone_aligned_1024->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
+ memzone_aligned_256->iova, memzone_aligned_256->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
+ memzone_aligned_512->iova, memzone_aligned_512->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_128->iova, memzone_aligned_128->len,
+ memzone_aligned_1024->iova, memzone_aligned_1024->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len,
+ memzone_aligned_512->iova, memzone_aligned_512->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_256->iova, memzone_aligned_256->len,
+ memzone_aligned_1024->iova, memzone_aligned_1024->len))
+ return -1;
+ if (is_memory_overlap(memzone_aligned_512->iova, memzone_aligned_512->len,
+ memzone_aligned_1024->iova, memzone_aligned_1024->len))
+ return -1;
+
+ /* free all used zones */
+ if (rte_memzone_free(memzone_aligned_32)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone_aligned_128)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone_aligned_256)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone_aligned_512)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone_aligned_1024)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+check_memzone_bounded(const char *name, uint32_t len, uint32_t align,
+ uint32_t bound)
+{
+ const struct rte_memzone *mz;
+ rte_iova_t bmask;
+
+ bmask = ~((rte_iova_t)bound - 1);
+
+ if ((mz = rte_memzone_reserve_bounded(name, len, SOCKET_ID_ANY, 0,
+ align, bound)) == NULL) {
+ printf("%s(%s): memzone creation failed\n",
+ __func__, name);
+ return -1;
+ }
+
+ if ((mz->iova & ((rte_iova_t)align - 1)) != 0) {
+ printf("%s(%s): invalid phys addr alignment\n",
+ __func__, mz->name);
+ return -1;
+ }
+
+ if (((uintptr_t) mz->addr & ((uintptr_t)align - 1)) != 0) {
+ printf("%s(%s): invalid virtual addr alignment\n",
+ __func__, mz->name);
+ return -1;
+ }
+
+ if ((mz->len & RTE_CACHE_LINE_MASK) != 0 || mz->len < len ||
+ mz->len < RTE_CACHE_LINE_SIZE) {
+ printf("%s(%s): invalid length\n",
+ __func__, mz->name);
+ return -1;
+ }
+
+ if ((mz->iova & bmask) !=
+ ((mz->iova + mz->len - 1) & bmask)) {
+ printf("%s(%s): invalid memzone boundary %u crossed\n",
+ __func__, mz->name, bound);
+ return -1;
+ }
+
+ if (rte_memzone_free(mz)) {
+ printf("Fail memzone free\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_memzone_bounded(void)
+{
+ const struct rte_memzone *memzone_err;
+ int rc;
+
+ /* should fail as boundary is not power of two */
+ memzone_err = rte_memzone_reserve_bounded(
+ TEST_MEMZONE_NAME("bounded_error_31"), 100,
+ SOCKET_ID_ANY, 0, 32, UINT32_MAX);
+ if (memzone_err != NULL) {
+ printf("%s(%s)created a memzone with invalid boundary "
+ "conditions\n", __func__, memzone_err->name);
+ return -1;
+ }
+
+ /* should fail as len is greater then boundary */
+ memzone_err = rte_memzone_reserve_bounded(
+ TEST_MEMZONE_NAME("bounded_error_32"), 100,
+ SOCKET_ID_ANY, 0, 32, 32);
+ if (memzone_err != NULL) {
+ printf("%s(%s)created a memzone with invalid boundary "
+ "conditions\n", __func__, memzone_err->name);
+ return -1;
+ }
+
+ rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_128"), 100, 128,
+ 128);
+ if (rc != 0)
+ return rc;
+
+ rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_256"), 100, 256,
+ 128);
+ if (rc != 0)
+ return rc;
+
+ rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_1K"), 100, 64,
+ 1024);
+ if (rc != 0)
+ return rc;
+
+ rc = check_memzone_bounded(TEST_MEMZONE_NAME("bounded_1K_MAX"), 0, 64,
+ 1024);
+ if (rc != 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+test_memzone_free(void)
+{
+ const struct rte_memzone *mz[RTE_MAX_MEMZONE + 1];
+ int i;
+ char name[20];
+
+ mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0"), 2000,
+ SOCKET_ID_ANY, 0);
+ mz[1] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone1"), 4000,
+ SOCKET_ID_ANY, 0);
+
+ if (mz[0] > mz[1])
+ return -1;
+ if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0")))
+ return -1;
+ if (!rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1")))
+ return -1;
+
+ if (rte_memzone_free(mz[0])) {
+ printf("Fail memzone free - tempzone0\n");
+ return -1;
+ }
+ if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone0"))) {
+ printf("Found previously free memzone - tempzone0\n");
+ return -1;
+ }
+ mz[2] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone2"), 2000,
+ SOCKET_ID_ANY, 0);
+
+ if (mz[2] > mz[1]) {
+ printf("tempzone2 should have gotten the free entry from tempzone0\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz[2])) {
+ printf("Fail memzone free - tempzone2\n");
+ return -1;
+ }
+ if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone2"))) {
+ printf("Found previously free memzone - tempzone2\n");
+ return -1;
+ }
+ if (rte_memzone_free(mz[1])) {
+ printf("Fail memzone free - tempzone1\n");
+ return -1;
+ }
+ if (rte_memzone_lookup(TEST_MEMZONE_NAME("tempzone1"))) {
+ printf("Found previously free memzone - tempzone1\n");
+ return -1;
+ }
+
+ i = 0;
+ do {
+ snprintf(name, sizeof(name), TEST_MEMZONE_NAME("tempzone%u"),
+ i);
+ mz[i] = rte_memzone_reserve(name, 1, SOCKET_ID_ANY, 0);
+ } while (mz[i++] != NULL);
+
+ if (rte_memzone_free(mz[0])) {
+ printf("Fail memzone free - tempzone0\n");
+ return -1;
+ }
+ mz[0] = rte_memzone_reserve(TEST_MEMZONE_NAME("tempzone0new"), 0,
+ SOCKET_ID_ANY, 0);
+
+ if (mz[0] == NULL) {
+ printf("Fail to create memzone - tempzone0new - when MAX memzones were "
+ "created and one was free\n");
+ return -1;
+ }
+
+ for (i = i - 2; i >= 0; i--) {
+ if (rte_memzone_free(mz[i])) {
+ printf("Fail memzone free - tempzone%d\n", i);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int test_memzones_left;
+static int memzone_walk_cnt;
+static void memzone_walk_clb(const struct rte_memzone *mz,
+ void *arg __rte_unused)
+{
+ memzone_walk_cnt++;
+ if (!strncmp(TEST_MEMZONE_NAME(""), mz->name, RTE_MEMZONE_NAMESIZE))
+ test_memzones_left++;
+}
+
+static int
+test_memzone_basic(void)
+{
+ const struct rte_memzone *memzone1;
+ const struct rte_memzone *memzone2;
+ const struct rte_memzone *memzone3;
+ const struct rte_memzone *memzone4;
+ const struct rte_memzone *mz;
+ int memzone_cnt_after, memzone_cnt_expected;
+ int memzone_cnt_before;
+
+ memzone_walk_cnt = 0;
+ test_memzones_left = 0;
+ rte_memzone_walk(memzone_walk_clb, NULL);
+ memzone_cnt_before = memzone_walk_cnt;
+
+ memzone1 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100,
+ SOCKET_ID_ANY, 0);
+
+ memzone2 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone2"), 1000,
+ 0, 0);
+
+ memzone3 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone3"), 1000,
+ 1, 0);
+
+ memzone4 = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone4"), 1024,
+ SOCKET_ID_ANY, 0);
+
+ /* memzone3 may be NULL if we don't have NUMA */
+ if (memzone1 == NULL || memzone2 == NULL || memzone4 == NULL)
+ return -1;
+
+ /* check how many memzones we are expecting */
+ memzone_cnt_expected = memzone_cnt_before +
+ (memzone1 != NULL) + (memzone2 != NULL) +
+ (memzone3 != NULL) + (memzone4 != NULL);
+
+ memzone_walk_cnt = 0;
+ test_memzones_left = 0;
+ rte_memzone_walk(memzone_walk_clb, NULL);
+ memzone_cnt_after = memzone_walk_cnt;
+
+ if (memzone_cnt_after != memzone_cnt_expected)
+ return -1;
+
+
+ rte_memzone_dump(stdout);
+
+ /* check cache-line alignments */
+ printf("check alignments and lengths\n");
+
+ if ((memzone1->iova & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+ if ((memzone2->iova & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+ if (memzone3 != NULL && (memzone3->iova & RTE_CACHE_LINE_MASK) != 0)
+ return -1;
+ if ((memzone1->len & RTE_CACHE_LINE_MASK) != 0 || memzone1->len == 0)
+ return -1;
+ if ((memzone2->len & RTE_CACHE_LINE_MASK) != 0 || memzone2->len == 0)
+ return -1;
+ if (memzone3 != NULL && ((memzone3->len & RTE_CACHE_LINE_MASK) != 0 ||
+ memzone3->len == 0))
+ return -1;
+ if (memzone4->len != 1024)
+ return -1;
+
+ /* check that zones don't overlap */
+ printf("check overlapping\n");
+
+ if (is_memory_overlap(memzone1->iova, memzone1->len,
+ memzone2->iova, memzone2->len))
+ return -1;
+ if (memzone3 != NULL &&
+ is_memory_overlap(memzone1->iova, memzone1->len,
+ memzone3->iova, memzone3->len))
+ return -1;
+ if (memzone3 != NULL &&
+ is_memory_overlap(memzone2->iova, memzone2->len,
+ memzone3->iova, memzone3->len))
+ return -1;
+
+ printf("check socket ID\n");
+
+ /* memzone2 must be on socket id 0 and memzone3 on socket 1 */
+ if (memzone2->socket_id != 0)
+ return -1;
+ if (memzone3 != NULL && memzone3->socket_id != 1)
+ return -1;
+
+ printf("test zone lookup\n");
+ mz = rte_memzone_lookup(TEST_MEMZONE_NAME("testzone1"));
+ if (mz != memzone1)
+ return -1;
+
+ printf("test duplcate zone name\n");
+ mz = rte_memzone_reserve(TEST_MEMZONE_NAME("testzone1"), 100,
+ SOCKET_ID_ANY, 0);
+ if (mz != NULL)
+ return -1;
+
+ if (rte_memzone_free(memzone1)) {
+ printf("Fail memzone free - memzone1\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone2)) {
+ printf("Fail memzone free - memzone2\n");
+ return -1;
+ }
+ if (memzone3 && rte_memzone_free(memzone3)) {
+ printf("Fail memzone free - memzone3\n");
+ return -1;
+ }
+ if (rte_memzone_free(memzone4)) {
+ printf("Fail memzone free - memzone4\n");
+ return -1;
+ }
+
+ memzone_walk_cnt = 0;
+ test_memzones_left = 0;
+ rte_memzone_walk(memzone_walk_clb, NULL);
+ memzone_cnt_after = memzone_walk_cnt;
+ if (memzone_cnt_after != memzone_cnt_before)
+ return -1;
+
+ return 0;
+}
+
+static int
+test_memzone(void)
+{
+ /* take note of how many memzones were allocated before running */
+ int memzone_cnt;
+
+ memzone_walk_cnt = 0;
+ test_memzones_left = 0;
+ rte_memzone_walk(memzone_walk_clb, NULL);
+ memzone_cnt = memzone_walk_cnt;
+
+ printf("test basic memzone API\n");
+ if (test_memzone_basic() < 0)
+ return -1;
+
+ printf("test free memzone\n");
+ if (test_memzone_free() < 0)
+ return -1;
+
+ printf("test reserving memzone with bigger size than the maximum\n");
+ if (test_memzone_reserving_zone_size_bigger_than_the_maximum() < 0)
+ return -1;
+
+ printf("test memzone_reserve flags\n");
+ if (test_memzone_reserve_flags() < 0)
+ return -1;
+
+ printf("test alignment for memzone_reserve\n");
+ if (test_memzone_aligned() < 0)
+ return -1;
+
+ printf("test boundary alignment for memzone_reserve\n");
+ if (test_memzone_bounded() < 0)
+ return -1;
+
+ printf("test invalid alignment for memzone_reserve\n");
+ if (test_memzone_invalid_alignment() < 0)
+ return -1;
+
+ printf("test reserving the largest size memzone possible\n");
+ if (test_memzone_reserve_max() < 0)
+ return -1;
+
+ printf("test reserving the largest size aligned memzone possible\n");
+ if (test_memzone_reserve_max_aligned() < 0)
+ return -1;
+
+ printf("check memzone cleanup\n");
+ memzone_walk_cnt = 0;
+ test_memzones_left = 0;
+ rte_memzone_walk(memzone_walk_clb, NULL);
+ if (memzone_walk_cnt != memzone_cnt || test_memzones_left > 0) {
+ printf("there are some memzones left after test\n");
+ rte_memzone_dump(stdout);
+ return -1;
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(memzone_autotest, test_memzone);
diff --git a/src/spdk/dpdk/app/test/test_meter.c b/src/spdk/dpdk/app/test/test_meter.c
new file mode 100644
index 000000000..f6fe6494a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_meter.c
@@ -0,0 +1,716 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "test.h"
+
+#include <rte_cycles.h>
+#include <rte_meter.h>
+
+#define mlog(format, ...) do{\
+ printf("Line %d:",__LINE__);\
+ printf(format, ##__VA_ARGS__);\
+ printf("\n");\
+ }while(0);
+
+#define melog(format, ...) do{\
+ printf("Line %d:",__LINE__);\
+ printf(format, ##__VA_ARGS__);\
+ printf(" failed!\n");\
+ return -1;\
+ }while(0);
+
+#define TM_TEST_SRTCM_CIR_DF 46000000
+#define TM_TEST_SRTCM_CBS_DF 2048
+#define TM_TEST_SRTCM_EBS_DF 4096
+
+#define TM_TEST_TRTCM_CIR_DF 46000000
+#define TM_TEST_TRTCM_PIR_DF 69000000
+#define TM_TEST_TRTCM_EIR_DF 69000000
+#define TM_TEST_TRTCM_CBS_DF 2048
+#define TM_TEST_TRTCM_PBS_DF 4096
+#define TM_TEST_TRTCM_EBS_DF 4096
+
+static struct rte_meter_srtcm_params sparams =
+ {.cir = TM_TEST_SRTCM_CIR_DF,
+ .cbs = TM_TEST_SRTCM_CBS_DF,
+ .ebs = TM_TEST_SRTCM_EBS_DF,};
+
+static struct rte_meter_trtcm_params tparams=
+ {.cir = TM_TEST_TRTCM_CIR_DF,
+ .pir = TM_TEST_TRTCM_PIR_DF,
+ .cbs = TM_TEST_TRTCM_CBS_DF,
+ .pbs = TM_TEST_TRTCM_PBS_DF,};
+
+static struct rte_meter_trtcm_rfc4115_params rfc4115params =
+ {.cir = TM_TEST_TRTCM_CIR_DF,
+ .eir = TM_TEST_TRTCM_EIR_DF,
+ .cbs = TM_TEST_TRTCM_CBS_DF,
+ .ebs = TM_TEST_TRTCM_EBS_DF,};
+
+/**
+ * functional test for rte_meter_srtcm_config
+ */
+static inline int
+tm_test_srtcm_config(void)
+{
+#define SRTCM_CFG_MSG "srtcm_config"
+ struct rte_meter_srtcm_profile sp;
+ struct rte_meter_srtcm_params sparams1;
+
+ /* invalid parameter test */
+ if (rte_meter_srtcm_profile_config(NULL, NULL) == 0)
+ melog(SRTCM_CFG_MSG);
+ if (rte_meter_srtcm_profile_config(&sp, NULL) == 0)
+ melog(SRTCM_CFG_MSG);
+ if (rte_meter_srtcm_profile_config(NULL, &sparams) == 0)
+ melog(SRTCM_CFG_MSG);
+
+ /* cbs and ebs can't both be zero */
+ sparams1 = sparams;
+ sparams1.cbs = 0;
+ sparams1.ebs = 0;
+ if (rte_meter_srtcm_profile_config(&sp, &sparams1) == 0)
+ melog(SRTCM_CFG_MSG);
+
+ /* cir should never be 0 */
+ sparams1 = sparams;
+ sparams1.cir = 0;
+ if (rte_meter_srtcm_profile_config(&sp, &sparams1) == 0)
+ melog(SRTCM_CFG_MSG);
+
+ /* one of ebs and cbs can be zero, should be successful */
+ sparams1 = sparams;
+ sparams1.ebs = 0;
+ if (rte_meter_srtcm_profile_config(&sp, &sparams1) != 0)
+ melog(SRTCM_CFG_MSG);
+
+ sparams1 = sparams;
+ sparams1.cbs = 0;
+ if (rte_meter_srtcm_profile_config(&sp, &sparams1) != 0)
+ melog(SRTCM_CFG_MSG);
+
+ /* usual parameter, should be successful */
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_CFG_MSG);
+
+ return 0;
+
+}
+
+/**
+ * functional test for rte_meter_trtcm_config
+ */
+static inline int
+tm_test_trtcm_config(void)
+{
+ struct rte_meter_trtcm_profile tp;
+ struct rte_meter_trtcm_params tparams1;
+#define TRTCM_CFG_MSG "trtcm_config"
+
+ /* invalid parameter test */
+ if (rte_meter_trtcm_profile_config(NULL, NULL) == 0)
+ melog(TRTCM_CFG_MSG);
+ if (rte_meter_trtcm_profile_config(&tp, NULL) == 0)
+ melog(TRTCM_CFG_MSG);
+ if (rte_meter_trtcm_profile_config(NULL, &tparams) == 0)
+ melog(TRTCM_CFG_MSG);
+
+ /* cir, cbs, pir and pbs never be zero */
+ tparams1 = tparams;
+ tparams1.cir = 0;
+ if (rte_meter_trtcm_profile_config(&tp, &tparams1) == 0)
+ melog(TRTCM_CFG_MSG);
+
+ tparams1 = tparams;
+ tparams1.cbs = 0;
+ if (rte_meter_trtcm_profile_config(&tp, &tparams1) == 0)
+ melog(TRTCM_CFG_MSG);
+
+ tparams1 = tparams;
+ tparams1.pbs = 0;
+ if (rte_meter_trtcm_profile_config(&tp, &tparams1) == 0)
+ melog(TRTCM_CFG_MSG);
+
+ tparams1 = tparams;
+ tparams1.pir = 0;
+ if (rte_meter_trtcm_profile_config(&tp, &tparams1) == 0)
+ melog(TRTCM_CFG_MSG);
+
+ /* pir should be greater or equal to cir */
+ tparams1 = tparams;
+ tparams1.pir = tparams1.cir - 1;
+ if (rte_meter_trtcm_profile_config(&tp, &tparams1) == 0)
+ melog(TRTCM_CFG_MSG" pir < cir test");
+
+ /* usual parameter, should be successful */
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_CFG_MSG);
+
+ return 0;
+}
+
+/**
+ * functional test for rte_meter_trtcm_rfc4115_config
+ */
+static inline int
+tm_test_trtcm_rfc4115_config(void)
+{
+ struct rte_meter_trtcm_rfc4115_profile tp;
+ struct rte_meter_trtcm_rfc4115_params rfc4115params1;
+#define TRTCM_RFC4115_CFG_MSG "trtcm_rfc4115_config"
+
+ /* invalid parameter test */
+ if (rte_meter_trtcm_rfc4115_profile_config(NULL, NULL) == 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, NULL) == 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+ if (rte_meter_trtcm_rfc4115_profile_config(NULL, &rfc4115params) == 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+
+ /*
+ * cbs and pbs should be none-zero if cir and eir are none-zero
+ * respectively
+ */
+ rfc4115params1 = rfc4115params;
+ rfc4115params1.cbs = 0;
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params1) == 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+
+ rfc4115params1 = rfc4115params;
+ rfc4115params1.ebs = 0;
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params1) == 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+
+ /* usual parameter, should be successful */
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_CFG_MSG);
+
+ return 0;
+}
+
+/**
+ * functional test for rte_meter_srtcm_color_blind_check
+ */
+static inline int
+tm_test_srtcm_color_blind_check(void)
+{
+#define SRTCM_BLIND_CHECK_MSG "srtcm_blind_check"
+ struct rte_meter_srtcm_profile sp;
+ struct rte_meter_srtcm sm;
+ uint64_t time;
+ uint64_t hz = rte_get_tsc_hz();
+
+ /* Test green */
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_blind_check(
+ &sm, &sp, time, TM_TEST_SRTCM_CBS_DF - 1)
+ != RTE_COLOR_GREEN)
+ melog(SRTCM_BLIND_CHECK_MSG" GREEN");
+
+ /* Test yellow */
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_blind_check(
+ &sm, &sp, time, TM_TEST_SRTCM_CBS_DF + 1)
+ != RTE_COLOR_YELLOW)
+ melog(SRTCM_BLIND_CHECK_MSG" YELLOW");
+
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_blind_check(
+ &sm, &sp, time, (uint32_t)sp.ebs - 1) != RTE_COLOR_YELLOW)
+ melog(SRTCM_BLIND_CHECK_MSG" YELLOW");
+
+ /* Test red */
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_blind_check(
+ &sm, &sp, time, TM_TEST_SRTCM_EBS_DF + 1)
+ != RTE_COLOR_RED)
+ melog(SRTCM_BLIND_CHECK_MSG" RED");
+
+ return 0;
+
+}
+
+/**
+ * functional test for rte_meter_trtcm_color_blind_check
+ */
+static inline int
+tm_test_trtcm_color_blind_check(void)
+{
+#define TRTCM_BLIND_CHECK_MSG "trtcm_blind_check"
+
+ uint64_t time;
+ struct rte_meter_trtcm_profile tp;
+ struct rte_meter_trtcm tm;
+ uint64_t hz = rte_get_tsc_hz();
+
+ /* Test green */
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF - 1)
+ != RTE_COLOR_GREEN)
+ melog(TRTCM_BLIND_CHECK_MSG" GREEN");
+
+ /* Test yellow */
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF + 1)
+ != RTE_COLOR_YELLOW)
+ melog(TRTCM_BLIND_CHECK_MSG" YELLOW");
+
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_PBS_DF - 1)
+ != RTE_COLOR_YELLOW)
+ melog(TRTCM_BLIND_CHECK_MSG" YELLOW");
+
+ /* Test red */
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_PBS_DF + 1)
+ != RTE_COLOR_RED)
+ melog(TRTCM_BLIND_CHECK_MSG" RED");
+
+ return 0;
+}
+
+/**
+ * functional test for rte_meter_trtcm_rfc4115_color_blind_check
+ */
+static inline int
+tm_test_trtcm_rfc4115_color_blind_check(void)
+{
+#define TRTCM_RFC4115_BLIND_CHECK_MSG "trtcm_rfc4115_blind_check"
+
+ uint64_t time;
+ struct rte_meter_trtcm_rfc4115_profile tp;
+ struct rte_meter_trtcm_rfc4115 tm;
+ uint64_t hz = rte_get_tsc_hz();
+
+ /* Test green */
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF - 1)
+ != RTE_COLOR_GREEN)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG" GREEN");
+
+ /* Test yellow */
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF + 1)
+ != RTE_COLOR_YELLOW)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG" YELLOW");
+
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_EBS_DF - 1)
+ != RTE_COLOR_YELLOW)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG" YELLOW");
+
+ /* Test red */
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_blind_check(
+ &tm, &tp, time, TM_TEST_TRTCM_EBS_DF + 1)
+ != RTE_COLOR_RED)
+ melog(TRTCM_RFC4115_BLIND_CHECK_MSG" RED");
+
+ return 0;
+}
+
+
+/**
+ * @in[4] : the flags packets carries.
+ * @in[4] : the flags function expect to return.
+ * It will do blind check at the time of 1 second from beginning.
+ * At the time, it will use packets length of cbs -1, cbs + 1,
+ * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do
+ * aware check, expect flag out[0], out[1], out[2] and out[3]
+ */
+
+static inline int
+tm_test_srtcm_aware_check
+(enum rte_color in[4], enum rte_color out[4])
+{
+#define SRTCM_AWARE_CHECK_MSG "srtcm_aware_check"
+ struct rte_meter_srtcm_profile sp;
+ struct rte_meter_srtcm sm;
+ uint64_t time;
+ uint64_t hz = rte_get_tsc_hz();
+
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_aware_check(
+ &sm, &sp, time, TM_TEST_SRTCM_CBS_DF - 1, in[0]) != out[0])
+ melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]);
+
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_aware_check(
+ &sm, &sp, time, TM_TEST_SRTCM_CBS_DF + 1, in[1]) != out[1])
+ melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]);
+
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_aware_check(
+ &sm, &sp, time, TM_TEST_SRTCM_EBS_DF - 1, in[2]) != out[2])
+ melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]);
+
+ if (rte_meter_srtcm_profile_config(&sp, &sparams) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_srtcm_config(&sm, &sp) != 0)
+ melog(SRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_srtcm_color_aware_check(
+ &sm, &sp, time, TM_TEST_SRTCM_EBS_DF + 1, in[3]) != out[3])
+ melog(SRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]);
+
+ return 0;
+}
+
+
+/**
+ * functional test for rte_meter_srtcm_color_aware_check
+ */
+static inline int
+tm_test_srtcm_color_aware_check(void)
+{
+ enum rte_color in[4], out[4];
+
+ /**
+ * test 4 points that will produce green, yellow, yellow, red flag
+ * if using blind check
+ */
+
+ /* previouly have a green, test points should keep unchanged */
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_GREEN;
+ out[0] = RTE_COLOR_GREEN;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_srtcm_aware_check(in, out) != 0)
+ return -1;
+
+ /**
+ * previously have a yellow, green & yellow = yellow
+ * yellow & red = red
+ */
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_YELLOW;
+ out[0] = RTE_COLOR_YELLOW;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_srtcm_aware_check(in, out) != 0)
+ return -1;
+
+ /**
+ * previously have a red, red & green = red
+ * red & yellow = red
+ */
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_RED;
+ out[0] = RTE_COLOR_RED;
+ out[1] = RTE_COLOR_RED;
+ out[2] = RTE_COLOR_RED;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_srtcm_aware_check(in, out) != 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * @in[4] : the flags packets carries.
+ * @in[4] : the flags function expect to return.
+ * It will do blind check at the time of 1 second from beginning.
+ * At the time, it will use packets length of cbs -1, cbs + 1,
+ * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do
+ * aware check, expect flag out[0], out[1], out[2] and out[3]
+ */
+static inline int
+tm_test_trtcm_aware_check
+(enum rte_color in[4], enum rte_color out[4])
+{
+#define TRTCM_AWARE_CHECK_MSG "trtcm_aware_check"
+ struct rte_meter_trtcm_profile tp;
+ struct rte_meter_trtcm tm;
+ uint64_t time;
+ uint64_t hz = rte_get_tsc_hz();
+
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF - 1, in[0]) != out[0])
+ melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[0], out[0]);
+
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF + 1, in[1]) != out[1])
+ melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[1], out[1]);
+
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_PBS_DF - 1, in[2]) != out[2])
+ melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[2], out[2]);
+
+ if (rte_meter_trtcm_profile_config(&tp, &tparams) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_config(&tm, &tp) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_PBS_DF + 1, in[3]) != out[3])
+ melog(TRTCM_AWARE_CHECK_MSG" %u:%u", in[3], out[3]);
+
+ return 0;
+}
+
+
+/**
+ * functional test for rte_meter_trtcm_color_aware_check
+ */
+
+static inline int
+tm_test_trtcm_color_aware_check(void)
+{
+ enum rte_color in[4], out[4];
+ /**
+ * test 4 points that will produce green, yellow, yellow, red flag
+ * if using blind check
+ */
+
+ /* previouly have a green, test points should keep unchanged */
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_GREEN;
+ out[0] = RTE_COLOR_GREEN;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_aware_check(in, out) != 0)
+ return -1;
+
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_YELLOW;
+ out[0] = RTE_COLOR_YELLOW;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_aware_check(in, out) != 0)
+ return -1;
+
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_RED;
+ out[0] = RTE_COLOR_RED;
+ out[1] = RTE_COLOR_RED;
+ out[2] = RTE_COLOR_RED;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_aware_check(in, out) != 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * @in[4] : the flags packets carries.
+ * @in[4] : the flags function expect to return.
+ * It will do blind check at the time of 1 second from beginning.
+ * At the time, it will use packets length of cbs -1, cbs + 1,
+ * ebs -1 and ebs +1 with flag in[0], in[1], in[2] and in[3] to do
+ * aware check, expect flag out[0], out[1], out[2] and out[3]
+ */
+static inline int
+tm_test_trtcm_rfc4115_aware_check
+(enum rte_color in[4], enum rte_color out[4])
+{
+#define TRTCM_RFC4115_AWARE_CHECK_MSG "trtcm_rfc4115_aware_check"
+ struct rte_meter_trtcm_rfc4115_profile tp;
+ struct rte_meter_trtcm_rfc4115 tm;
+ uint64_t time;
+ uint64_t hz = rte_get_tsc_hz();
+
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF - 1, in[0]) != out[0])
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG" %u:%u", in[0], out[0]);
+
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_CBS_DF + 1, in[1]) != out[1])
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG" %u:%u", in[1], out[1]);
+
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_EBS_DF - 1, in[2]) != out[2])
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG" %u:%u", in[2], out[2]);
+
+ if (rte_meter_trtcm_rfc4115_profile_config(&tp, &rfc4115params) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ if (rte_meter_trtcm_rfc4115_config(&tm, &tp) != 0)
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG);
+ time = rte_get_tsc_cycles() + hz;
+ if (rte_meter_trtcm_rfc4115_color_aware_check(
+ &tm, &tp, time, TM_TEST_TRTCM_EBS_DF + 1, in[3]) != out[3])
+ melog(TRTCM_RFC4115_AWARE_CHECK_MSG" %u:%u", in[3], out[3]);
+
+ return 0;
+}
+
+/**
+ * functional test for rte_meter_trtcm_rfc4115_color_aware_check
+ */
+static inline int
+tm_test_trtcm_rfc4115_color_aware_check(void)
+{
+ enum rte_color in[4], out[4];
+ /**
+ * test 4 points that will produce green, yellow, yellow, red flag
+ * if using blind check
+ */
+
+ /* previouly have a green, test points should keep unchanged */
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_GREEN;
+ out[0] = RTE_COLOR_GREEN;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_rfc4115_aware_check(in, out) != 0)
+ return -1;
+
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_YELLOW;
+ out[0] = RTE_COLOR_YELLOW;
+ out[1] = RTE_COLOR_YELLOW;
+ out[2] = RTE_COLOR_YELLOW;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_rfc4115_aware_check(in, out) != 0)
+ return -1;
+
+ in[0] = in[1] = in[2] = in[3] = RTE_COLOR_RED;
+ out[0] = RTE_COLOR_RED;
+ out[1] = RTE_COLOR_RED;
+ out[2] = RTE_COLOR_RED;
+ out[3] = RTE_COLOR_RED;
+ if (tm_test_trtcm_rfc4115_aware_check(in, out) != 0)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * test main entrance for library meter
+ */
+static int
+test_meter(void)
+{
+ if (tm_test_srtcm_config() != 0)
+ return -1;
+
+ if (tm_test_trtcm_config() != 0)
+ return -1;
+
+ if (tm_test_trtcm_rfc4115_config() != 0)
+ return -1;
+
+ if (tm_test_srtcm_color_blind_check() != 0)
+ return -1;
+
+ if (tm_test_trtcm_color_blind_check() != 0)
+ return -1;
+
+ if (tm_test_trtcm_rfc4115_color_blind_check() != 0)
+ return -1;
+
+ if (tm_test_srtcm_color_aware_check() != 0)
+ return -1;
+
+ if (tm_test_trtcm_color_aware_check() != 0)
+ return -1;
+
+ if (tm_test_trtcm_rfc4115_color_aware_check() != 0)
+ return -1;
+
+ return 0;
+
+}
+
+REGISTER_TEST_COMMAND(meter_autotest, test_meter);
diff --git a/src/spdk/dpdk/app/test/test_metrics.c b/src/spdk/dpdk/app/test/test_metrics.c
new file mode 100644
index 000000000..e736019ae
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_metrics.c
@@ -0,0 +1,329 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <rte_lcore.h>
+#include <rte_metrics.h>
+
+#include "test.h"
+
+#define REG_METRIC_COUNT 6
+#define METRIC_LESSER_COUNT 3
+#define KEY 1
+#define VALUE 1
+
+/* Initializes metric module. This function must be called
+ * from a primary process before metrics are used
+ */
+static int
+test_metrics_init(void)
+{
+ rte_metrics_init(rte_socket_id());
+ return TEST_SUCCESS;
+}
+
+/* Deinitialize metric module. This function must be called
+ * from a primary process after metrics usage is over
+ */
+static int
+test_metrics_deinitialize(void)
+{
+ int err = 0;
+ err = rte_metrics_deinit();
+ TEST_ASSERT(err == 0, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+ /* Test Case to check failures when memzone init is not done */
+static int
+test_metrics_without_init(void)
+{
+ int err = 0;
+ const uint64_t value[REG_METRIC_COUNT] = {0};
+ const char * const mnames[] = {
+ "mean_bits_in", "mean_bits_out",
+ "peak_bits_in", "peak_bits_out",
+ };
+
+ /* Failure Test: Checking for memzone initialization */
+ err = rte_metrics_reg_name("peak_bits_in");
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ err = rte_metrics_reg_names(&mnames[0], 1);
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ err = rte_metrics_update_value(RTE_METRICS_GLOBAL, KEY, VALUE);
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL, KEY, &value[0], 4);
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ err = rte_metrics_get_names(NULL, 0);
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ err = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL, 0);
+ TEST_ASSERT(err == -EIO, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test Case to validate registering a single metric */
+static int
+test_metrics_reg_name_with_validname(void)
+{
+ int err = 0;
+
+ /* Test to register the new metric name */
+ err = rte_metrics_reg_name("peak_bits_out");
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Test to register the same metric name */
+ err = rte_metrics_reg_name("peak_bits_out");
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Test case to validate registering a invalid metric */
+ err = rte_metrics_reg_name(NULL);
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to validate registering a list of valid metric names */
+static int
+test_metrics_reg_names(void)
+{
+ int err = 0;
+ const char * const mnames[] = {
+ "mean_bits_in", "mean_bits_out",
+ "peak_bits_in", "peak_bits_out",
+ };
+
+ /* Success Test: valid array and count size */
+ err = rte_metrics_reg_names(&mnames[0], RTE_DIM(mnames));
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to validate update a metric */
+static int
+test_metrics_update_value(void)
+{
+ int err = 0;
+
+ /* Successful Test: Valid port_id, key and value */
+ err = rte_metrics_update_value(RTE_METRICS_GLOBAL, KEY, VALUE);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: Valid port_id otherthan RTE_METRICS_GLOBAL, key
+ * and value
+ */
+ err = rte_metrics_update_value(9, KEY, VALUE);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid port_id with lower value */
+ err = rte_metrics_update_value(-2, KEY, VALUE);
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid port_id with higher value */
+ err = rte_metrics_update_value(39, KEY, VALUE);
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: valid port id, value with invalid key */
+ err = rte_metrics_update_value(RTE_METRICS_GLOBAL, KEY+12, VALUE);
+ TEST_ASSERT(err < 0, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test case to validate update a list of metrics */
+static int
+test_metrics_update_values(void)
+{
+ int err = 0;
+ const uint64_t value[REG_METRIC_COUNT] = {1, 2, 3, 4, 5, 6};
+
+ /* Successful Test: update metrics with first set */
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL, 0,
+ &value[0], 1);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: update metrics with second set */
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL, 1,
+ &value[1], 1);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: update metrics with third set */
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL, 2,
+ &value[2], 4);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid count size */
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+ KEY, &value[0], RTE_DIM(value));
+ TEST_ASSERT(err < 0, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid port_id(lower value) and valid data */
+ err = rte_metrics_update_values(-2, KEY, &value[0], RTE_DIM(value));
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid port_id(higher value) and valid data */
+ err = rte_metrics_update_values(39, 1, &value[0], RTE_DIM(value));
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Failed Test: Invalid array */
+ err = rte_metrics_update_values(RTE_METRICS_GLOBAL,
+ KEY, NULL, RTE_DIM(value));
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test to validate get metric name-key lookup table */
+static int
+test_metrics_get_names(void)
+{
+ int err = 0;
+ struct rte_metric_name metrics[METRIC_LESSER_COUNT];
+ struct rte_metric_name success_metrics[REG_METRIC_COUNT];
+
+ /* Successful Test: Invalid array list */
+ err = rte_metrics_get_names(NULL, 0);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: Valid array list, Correct Count Stats same
+ * as memzone stats
+ */
+ err = rte_metrics_get_names(success_metrics, REG_METRIC_COUNT);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: Valid array list, Increase Count Stats than
+ * memzone stats
+ */
+ err = rte_metrics_get_names(success_metrics, REG_METRIC_COUNT+5);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test, Not update results:
+ * Invalid array list, Lesser Count Stats than allocated stats
+ */
+ err = rte_metrics_get_names(metrics, METRIC_LESSER_COUNT);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+/* Test to validate get list of metric values */
+static int
+test_metrics_get_values(void)
+{
+ int i = 0;
+ int err = 0;
+ struct rte_metric_value getvalues[REG_METRIC_COUNT];
+
+ size_t m_size = sizeof(struct rte_metric_value);
+ for (i = 0; i < REG_METRIC_COUNT; i++)
+ memset(&getvalues[i], 0, m_size);
+
+ /* Successful Test, Not update results: valid arguments
+ * count lessthan the memzone stats
+ */
+ err = rte_metrics_get_values(RTE_METRICS_GLOBAL, getvalues,
+ METRIC_LESSER_COUNT);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test, update results: valid arguments */
+ err = rte_metrics_get_values(RTE_METRICS_GLOBAL, getvalues,
+ REG_METRIC_COUNT);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test : valid arguments count greaterthan the
+ * memzone stats
+ */
+ err = rte_metrics_get_values(RTE_METRICS_GLOBAL, getvalues,
+ REG_METRIC_COUNT+2);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ /* Failure Test: Invalid port_id(lower value) with correct values
+ * and Capacity
+ */
+ err = rte_metrics_get_values(-2, getvalues, REG_METRIC_COUNT);
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Failure Test: Invalid port_id(higher value) with correct values
+ * and Capacity
+ */
+ err = rte_metrics_get_values(33, getvalues, REG_METRIC_COUNT);
+ TEST_ASSERT(err == -EINVAL, "%s, %d", __func__, __LINE__);
+
+ /* Successful Test: valid port_id with incorrect values and valid
+ * capacity
+ */
+ err = rte_metrics_get_values(RTE_METRICS_GLOBAL, NULL,
+ REG_METRIC_COUNT);
+ TEST_ASSERT(err >= 0, "%s, %d", __func__, __LINE__);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite metrics_testsuite = {
+ .suite_name = "Metrics Unit Test Suite",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ /* Test Case 1: Test to check all metric APIs without
+ * metrics init
+ */
+ TEST_CASE(test_metrics_without_init),
+
+ /* TEST CASE 2: Test to register valid metrics*/
+ TEST_CASE_ST(test_metrics_init, NULL,
+ test_metrics_reg_name_with_validname),
+
+ /* TEST CASE 3: Test to register list of metrics with valid
+ * names and valid count size, invalid names and invalid
+ * count size
+ */
+ TEST_CASE(test_metrics_reg_names),
+
+ /* TEST CASE 4: Test to register a update value with valid port
+ * id and invalid port id
+ */
+ TEST_CASE(test_metrics_update_value),
+
+ /* TEST CASE 5: Test to register update list of values with
+ * valid port id, key, value, count size and invalid port id,
+ * key, value, count size
+ */
+ TEST_CASE(test_metrics_update_values),
+
+ /* TEST CASE 6: Test to get metric names-key with valid
+ * array list, count size and invalid array list, count size
+ */
+ TEST_CASE(test_metrics_get_names),
+
+ /* TEST CASE 7: Test to get list of metric values with valid
+ * port id, array list, count size and invalid port id,
+ * arraylist, count size
+ */
+ TEST_CASE(test_metrics_get_values),
+
+ /* TEST CASE 8: Test to unregister metrics*/
+ TEST_CASE(test_metrics_deinitialize),
+
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_metrics(void)
+{
+ return unit_test_suite_runner(&metrics_testsuite);
+}
+
+REGISTER_TEST_COMMAND(metrics_autotest, test_metrics);
diff --git a/src/spdk/dpdk/app/test/test_mp_secondary.c b/src/spdk/dpdk/app/test/test_mp_secondary.c
new file mode 100644
index 000000000..ac15ddbf2
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_mp_secondary.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+
+#include "test.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <libgen.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_errno.h>
+#include <rte_branch_prediction.h>
+#include <rte_atomic.h>
+#include <rte_ring.h>
+#include <rte_debug.h>
+#include <rte_log.h>
+#include <rte_mempool.h>
+
+#ifdef RTE_LIBRTE_HASH
+#include <rte_hash.h>
+#include <rte_fbk_hash.h>
+#endif /* RTE_LIBRTE_HASH */
+
+#ifdef RTE_LIBRTE_LPM
+#include <rte_lpm.h>
+#endif /* RTE_LIBRTE_LPM */
+
+#include <rte_string_fns.h>
+
+#include "process.h"
+
+#define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
+
+/*
+ * This function is called in the primary i.e. main test, to spawn off secondary
+ * processes to run actual mp tests. Uses fork() and exec pair
+ */
+static int
+run_secondary_instances(void)
+{
+ int ret = 0;
+ char coremask[10];
+
+#ifdef RTE_EXEC_ENV_LINUX
+ char tmp[PATH_MAX] = {0};
+ char prefix[PATH_MAX] = {0};
+
+ get_current_prefix(tmp, sizeof(tmp));
+
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#else
+ const char *prefix = "";
+#endif
+
+ /* good case, using secondary */
+ const char *argv1[] = {
+ prgname, "-c", coremask, "--proc-type=secondary",
+ prefix
+ };
+ /* good case, using auto */
+ const char *argv2[] = {
+ prgname, "-c", coremask, "--proc-type=auto",
+ prefix
+ };
+ /* bad case, using invalid type */
+ const char *argv3[] = {
+ prgname, "-c", coremask, "--proc-type=ERROR",
+ prefix
+ };
+#ifdef RTE_EXEC_ENV_LINUX
+ /* bad case, using invalid file prefix */
+ const char *argv4[] = {
+ prgname, "-c", coremask, "--proc-type=secondary",
+ "--file-prefix=ERROR"
+ };
+#endif
+
+ snprintf(coremask, sizeof(coremask), "%x", \
+ (1 << rte_get_master_lcore()));
+
+ ret |= launch_proc(argv1);
+ ret |= launch_proc(argv2);
+
+ ret |= !(launch_proc(argv3));
+#ifdef RTE_EXEC_ENV_LINUX
+ ret |= !(launch_proc(argv4));
+#endif
+
+ return ret;
+}
+
+/*
+ * This function is run in the secondary instance to test that creation of
+ * objects fails in a secondary
+ */
+static int
+run_object_creation_tests(void)
+{
+ const unsigned flags = 0;
+ const unsigned size = 1024;
+ const unsigned elt_size = 64;
+ const unsigned cache_size = 64;
+ const unsigned priv_data_size = 32;
+
+ printf("### Testing object creation - expect lots of mz reserve errors!\n");
+
+ rte_errno = 0;
+ if ((rte_memzone_reserve("test_mz", size, rte_socket_id(),
+ flags) == NULL) &&
+ (rte_memzone_lookup("test_mz") == NULL)) {
+ printf("Error: unexpected return value from rte_memzone_reserve\n");
+ return -1;
+ }
+ printf("# Checked rte_memzone_reserve() OK\n");
+
+ rte_errno = 0;
+ if ((rte_ring_create(
+ "test_ring", size, rte_socket_id(), flags) == NULL) &&
+ (rte_ring_lookup("test_ring") == NULL)){
+ printf("Error: unexpected return value from rte_ring_create()\n");
+ return -1;
+ }
+ printf("# Checked rte_ring_create() OK\n");
+
+ rte_errno = 0;
+ if ((rte_mempool_create("test_mp", size, elt_size, cache_size,
+ priv_data_size, NULL, NULL, NULL, NULL,
+ rte_socket_id(), flags) == NULL) &&
+ (rte_mempool_lookup("test_mp") == NULL)){
+ printf("Error: unexpected return value from rte_mempool_create()\n");
+ return -1;
+ }
+ printf("# Checked rte_mempool_create() OK\n");
+
+#ifdef RTE_LIBRTE_HASH
+ const struct rte_hash_parameters hash_params = { .name = "test_mp_hash" };
+ rte_errno=0;
+ if ((rte_hash_create(&hash_params) != NULL) &&
+ (rte_hash_find_existing(hash_params.name) == NULL)){
+ printf("Error: unexpected return value from rte_hash_create()\n");
+ return -1;
+ }
+ printf("# Checked rte_hash_create() OK\n");
+
+ const struct rte_fbk_hash_params fbk_params = { .name = "test_fbk_mp_hash" };
+ rte_errno=0;
+ if ((rte_fbk_hash_create(&fbk_params) != NULL) &&
+ (rte_fbk_hash_find_existing(fbk_params.name) == NULL)){
+ printf("Error: unexpected return value from rte_fbk_hash_create()\n");
+ return -1;
+ }
+ printf("# Checked rte_fbk_hash_create() OK\n");
+#endif
+
+#ifdef RTE_LIBRTE_LPM
+ rte_errno=0;
+ struct rte_lpm_config config;
+
+ config.max_rules = rte_socket_id();
+ config.number_tbl8s = 256;
+ config.flags = 0;
+ if ((rte_lpm_create("test_lpm", size, &config) != NULL) &&
+ (rte_lpm_find_existing("test_lpm") == NULL)){
+ printf("Error: unexpected return value from rte_lpm_create()\n");
+ return -1;
+ }
+ printf("# Checked rte_lpm_create() OK\n");
+#endif
+
+ return 0;
+}
+
+/* if called in a primary process, just spawns off a secondary process to
+ * run validation tests - which brings us right back here again...
+ * if called in a secondary process, this runs a series of API tests to check
+ * how things run in a secondary instance.
+ */
+int
+test_mp_secondary(void)
+{
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ return run_secondary_instances();
+ }
+
+ printf("IN SECONDARY PROCESS\n");
+
+ return run_object_creation_tests();
+}
+
+REGISTER_TEST_COMMAND(multiprocess_autotest, test_mp_secondary);
diff --git a/src/spdk/dpdk/app/test/test_pdump.c b/src/spdk/dpdk/app/test/test_pdump.c
new file mode 100644
index 000000000..6a1180bcb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_pdump.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <limits.h>
+
+#include <rte_ethdev_driver.h>
+#include <rte_pdump.h>
+#include "rte_eal.h"
+#include "rte_lcore.h"
+#include "rte_mempool.h"
+#include "rte_ring.h"
+
+#include "sample_packet_forward.h"
+#include "test.h"
+#include "process.h"
+#include "test_pdump.h"
+
+#define launch_p(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
+
+struct rte_ring *ring_server;
+uint16_t portid;
+uint16_t flag_for_send_pkts = 1;
+
+int
+test_pdump_init(void)
+{
+ int ret = 0;
+
+ ret = rte_pdump_init();
+ if (ret < 0) {
+ printf("rte_pdump_init failed\n");
+ return -1;
+ }
+ ret = test_ring_setup(&ring_server, &portid);
+ if (ret < 0) {
+ printf("test_ring_setup failed\n");
+ return -1;
+ }
+ printf("pdump_init success\n");
+ return ret;
+}
+
+int
+run_pdump_client_tests(void)
+{
+ int flags = RTE_PDUMP_FLAG_TX, ret = 0, itr;
+ char deviceid[] = "net_ring_net_ringa";
+ struct rte_ring *ring_client;
+ struct rte_mempool *mp = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+ char poolname[] = "mbuf_pool_client";
+
+ ret = test_get_mempool(&mp, poolname);
+ if (ret < 0)
+ return -1;
+ mp->flags = 0x0000;
+ ring_client = rte_ring_create("SR0", RING_SIZE, rte_socket_id(), 0);
+ if (ring_client == NULL) {
+ printf("rte_ring_create SR0 failed");
+ return -1;
+ }
+
+ eth_dev = rte_eth_dev_attach_secondary(deviceid);
+ if (!eth_dev) {
+ printf("Failed to probe %s", deviceid);
+ return -1;
+ }
+ rte_eth_dev_probing_finish(eth_dev);
+
+ printf("\n***** flags = RTE_PDUMP_FLAG_TX *****\n");
+
+ for (itr = 0; itr < NUM_ITR; itr++) {
+ ret = rte_pdump_enable(portid, QUEUE_ID, flags, ring_client,
+ mp, NULL);
+ if (ret < 0) {
+ printf("rte_pdump_enable failed\n");
+ return -1;
+ }
+ printf("pdump_enable success\n");
+
+ ret = rte_pdump_disable(portid, QUEUE_ID, flags);
+ if (ret < 0) {
+ printf("rte_pdump_disable failed\n");
+ return -1;
+ }
+ printf("pdump_disable success\n");
+
+ ret = rte_pdump_enable_by_deviceid(deviceid, QUEUE_ID, flags,
+ ring_client, mp, NULL);
+ if (ret < 0) {
+ printf("rte_pdump_enable_by_deviceid failed\n");
+ return -1;
+ }
+ printf("pdump_enable_by_deviceid success\n");
+
+ ret = rte_pdump_disable_by_deviceid(deviceid, QUEUE_ID, flags);
+ if (ret < 0) {
+ printf("rte_pdump_disable_by_deviceid failed\n");
+ return -1;
+ }
+ printf("pdump_disable_by_deviceid success\n");
+
+ if (itr == 0) {
+ flags = RTE_PDUMP_FLAG_RX;
+ printf("\n***** flags = RTE_PDUMP_FLAG_RX *****\n");
+ } else if (itr == 1) {
+ flags = RTE_PDUMP_FLAG_RXTX;
+ printf("\n***** flags = RTE_PDUMP_FLAG_RXTX *****\n");
+ }
+ }
+ if (ring_client != NULL)
+ test_ring_free(ring_client);
+ if (mp != NULL)
+ test_mp_free(mp);
+
+ return ret;
+}
+
+int
+test_pdump_uninit(void)
+{
+ int ret = 0;
+
+ ret = rte_pdump_uninit();
+ if (ret < 0) {
+ printf("rte_pdump_uninit failed\n");
+ return -1;
+ }
+ if (ring_server != NULL)
+ test_ring_free(ring_server);
+ printf("pdump_uninit success\n");
+ test_vdev_uninit("net_ring_net_ringa");
+ return ret;
+}
+
+void *
+send_pkts(void *empty)
+{
+ int ret = 0;
+ struct rte_mbuf *pbuf[NUM_PACKETS] = { };
+ struct rte_mempool *mp;
+ char poolname[] = "mbuf_pool_server";
+
+ ret = test_get_mbuf_from_pool(&mp, pbuf, poolname);
+ if (ret < 0)
+ printf("get_mbuf_from_pool failed\n");
+ do {
+ ret = test_packet_forward(pbuf, portid, QUEUE_ID);
+ if (ret < 0)
+ printf("send pkts Failed\n");
+ } while (flag_for_send_pkts);
+ test_put_mbuf_to_pool(mp, pbuf);
+ return empty;
+}
+
+/*
+ * This function is called in the primary i.e. main test, to spawn off secondary
+ * processes to run actual mp tests. Uses fork() and exec pair
+ */
+
+int
+run_pdump_server_tests(void)
+{
+ int ret = 0;
+ char coremask[10];
+
+#ifdef RTE_EXEC_ENV_LINUX
+ char tmp[PATH_MAX] = { 0 };
+ char prefix[PATH_MAX] = { 0 };
+
+ get_current_prefix(tmp, sizeof(tmp));
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#else
+ const char *prefix = "";
+#endif
+
+ /* good case, using secondary */
+ const char *const argv1[] = {
+ prgname, "-c", coremask, "--proc-type=secondary",
+ prefix
+ };
+
+ snprintf(coremask, sizeof(coremask), "%x",
+ (1 << rte_get_master_lcore()));
+
+ ret = test_pdump_init();
+ ret |= launch_p(argv1);
+ ret |= test_pdump_uninit();
+ return ret;
+}
+
+int
+test_pdump(void)
+{
+ int ret = 0;
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ printf("IN PRIMARY PROCESS\n");
+ ret = run_pdump_server_tests();
+ if (ret < 0)
+ return TEST_FAILED;
+ } else if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+ printf("IN SECONDARY PROCESS\n");
+ sleep(5);
+ ret = run_pdump_client_tests();
+ if (ret < 0)
+ return TEST_FAILED;
+ }
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(pdump_autotest, test_pdump);
diff --git a/src/spdk/dpdk/app/test/test_pdump.h b/src/spdk/dpdk/app/test/test_pdump.h
new file mode 100644
index 000000000..abef9a85e
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_pdump.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef _TEST_PDUMP_H_
+#define _TEST_PDUMP_H_
+
+#define QUEUE_ID 0
+#define NUM_ITR 3
+
+/* sample test to send packets to the pdump client recursively */
+void *send_pkts(void *port);
+
+/* Sample test to create setup for the pdump server tests */
+int test_pdump_init(void);
+
+/* Sample test to teardown the pdump server setup */
+int test_pdump_uninit(void);
+
+/* Sample test to run the pdump client tests */
+int run_pdump_client_tests(void);
+
+/* Sample test to run the pdump server tests */
+int run_pdump_server_tests(void);
+
+/* Sample test to run the pdump client and server tests based on
+ * the process type
+ */
+int test_pdump(void);
+
+#endif /* _TEST_PDUMP_H_ */
diff --git a/src/spdk/dpdk/app/test/test_per_lcore.c b/src/spdk/dpdk/app/test/test_per_lcore.c
new file mode 100644
index 000000000..fcd00212f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_per_lcore.c
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+
+#include "test.h"
+
+/*
+ * Per-lcore variables and lcore launch
+ * ====================================
+ *
+ * - Use ``rte_eal_mp_remote_launch()`` to call ``assign_vars()`` on
+ * every available lcore. In this function, a per-lcore variable is
+ * assigned to the lcore_id.
+ *
+ * - Use ``rte_eal_mp_remote_launch()`` to call ``display_vars()`` on
+ * every available lcore. The function checks that the variable is
+ * correctly set, or returns -1.
+ *
+ * - If at least one per-core variable was not correct, the test function
+ * returns -1.
+ */
+
+static RTE_DEFINE_PER_LCORE(unsigned, test) = 0x12345678;
+
+static int
+assign_vars(__rte_unused void *arg)
+{
+ if (RTE_PER_LCORE(test) != 0x12345678)
+ return -1;
+ RTE_PER_LCORE(test) = rte_lcore_id();
+ return 0;
+}
+
+static int
+display_vars(__rte_unused void *arg)
+{
+ unsigned lcore_id = rte_lcore_id();
+ unsigned var = RTE_PER_LCORE(test);
+ unsigned socket_id = rte_lcore_to_socket_id(lcore_id);
+
+ printf("on socket %u, on core %u, variable is %u\n", socket_id, lcore_id, var);
+ if (lcore_id != var)
+ return -1;
+
+ RTE_PER_LCORE(test) = 0x12345678;
+ return 0;
+}
+
+static int
+test_per_lcore_delay(__rte_unused void *arg)
+{
+ rte_delay_ms(100);
+ printf("wait 100ms on lcore %u\n", rte_lcore_id());
+
+ return 0;
+}
+
+static int
+test_per_lcore(void)
+{
+ unsigned lcore_id;
+ int ret;
+
+ rte_eal_mp_remote_launch(assign_vars, NULL, SKIP_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ return -1;
+ }
+
+ rte_eal_mp_remote_launch(display_vars, NULL, SKIP_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ return -1;
+ }
+
+ /* test if it could do remote launch twice at the same time or not */
+ ret = rte_eal_mp_remote_launch(test_per_lcore_delay, NULL, SKIP_MASTER);
+ if (ret < 0) {
+ printf("It fails to do remote launch but it should able to do\n");
+ return -1;
+ }
+ /* it should not be able to launch a lcore which is running */
+ ret = rte_eal_mp_remote_launch(test_per_lcore_delay, NULL, SKIP_MASTER);
+ if (ret == 0) {
+ printf("It does remote launch successfully but it should not at this time\n");
+ return -1;
+ }
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (rte_eal_wait_lcore(lcore_id) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(per_lcore_autotest, test_per_lcore);
diff --git a/src/spdk/dpdk/app/test/test_pmd_perf.c b/src/spdk/dpdk/app/test/test_pmd_perf.c
new file mode 100644
index 000000000..352cd4715
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_pmd_perf.c
@@ -0,0 +1,888 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <unistd.h>
+#include <rte_cycles.h>
+#include <rte_ethdev.h>
+#include <rte_byteorder.h>
+#include <rte_atomic.h>
+#include <rte_malloc.h>
+#include "packet_burst_generator.h"
+#include "test.h"
+
+#define NB_ETHPORTS_USED (1)
+#define NB_SOCKETS (2)
+#define MEMPOOL_CACHE_SIZE 250
+#define MAX_PKT_BURST (32)
+#define RTE_TEST_RX_DESC_DEFAULT (1024)
+#define RTE_TEST_TX_DESC_DEFAULT (1024)
+#define RTE_PORT_ALL (~(uint16_t)0x0)
+
+/* how long test would take at full line rate */
+#define RTE_TEST_DURATION (2)
+
+/*
+ * RX and TX Prefetch, Host, and Write-back threshold values should be
+ * carefully set for optimal performance. Consult the network
+ * controller's datasheet and supporting DPDK documentation for guidance
+ * on how these parameters should be set.
+ */
+#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
+#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
+#define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */
+
+/*
+ * These default values are optimized for use with the Intel(R) 82599 10 GbE
+ * Controller and the DPDK ixgbe PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+#define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */
+#define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */
+#define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */
+
+#define MAX_TRAFFIC_BURST 2048
+
+#define NB_MBUF RTE_MAX( \
+ (unsigned)(nb_ports*nb_rx_queue*nb_rxd + \
+ nb_ports*nb_lcores*MAX_PKT_BURST + \
+ nb_ports*nb_tx_queue*nb_txd + \
+ nb_lcores*MEMPOOL_CACHE_SIZE + \
+ nb_ports*MAX_TRAFFIC_BURST), \
+ (unsigned)8192)
+
+
+static struct rte_mempool *mbufpool[NB_SOCKETS];
+/* ethernet addresses of ports */
+static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
+
+static struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .max_rx_pkt_len = RTE_ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+ .lpbk_mode = 1, /* enable loopback */
+};
+
+static struct rte_eth_rxconf rx_conf = {
+ .rx_thresh = {
+ .pthresh = RX_PTHRESH,
+ .hthresh = RX_HTHRESH,
+ .wthresh = RX_WTHRESH,
+ },
+ .rx_free_thresh = 32,
+};
+
+static struct rte_eth_txconf tx_conf = {
+ .tx_thresh = {
+ .pthresh = TX_PTHRESH,
+ .hthresh = TX_HTHRESH,
+ .wthresh = TX_WTHRESH,
+ },
+ .tx_free_thresh = 32, /* Use PMD default values */
+ .tx_rs_thresh = 32, /* Use PMD default values */
+};
+
+enum {
+ LCORE_INVALID = 0,
+ LCORE_AVAIL,
+ LCORE_USED,
+};
+
+struct lcore_conf {
+ uint8_t status;
+ uint8_t socketid;
+ uint16_t nb_ports;
+ uint16_t portlist[RTE_MAX_ETHPORTS];
+} __rte_cache_aligned;
+
+struct lcore_conf lcore_conf[RTE_MAX_LCORE];
+
+static uint64_t link_mbps;
+
+enum {
+ SC_CONTINUOUS = 0,
+ SC_BURST_POLL_FIRST,
+ SC_BURST_XMIT_FIRST,
+};
+
+static uint32_t sc_flag;
+
+/* Check the link status of all ports in up to 3s, and print them finally */
+static void
+check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */
+ uint16_t portid;
+ uint8_t count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+ int ret;
+
+ printf("Checking link statuses...\n");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ all_ports_up = 1;
+ for (portid = 0; portid < port_num; portid++) {
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ memset(&link, 0, sizeof(link));
+ ret = rte_eth_link_get_nowait(portid, &link);
+ if (ret < 0) {
+ all_ports_up = 0;
+ if (print_flag == 1)
+ printf("Port %u link get failed: %s\n",
+ portid, rte_strerror(-ret));
+ continue;
+ }
+
+ /* print link status if flag set */
+ if (print_flag == 1) {
+ if (link.link_status) {
+ printf(
+ "Port%d Link Up. Speed %u Mbps - %s\n",
+ portid, link.link_speed,
+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex"));
+ if (link_mbps == 0)
+ link_mbps = link.link_speed;
+ } else
+ printf("Port %d Link Down\n", portid);
+ continue;
+ }
+ /* clear all_ports_up flag if any link down */
+ if (link.link_status == ETH_LINK_DOWN) {
+ all_ports_up = 0;
+ break;
+ }
+ }
+ /* after finally printing all link status, get out */
+ if (print_flag == 1)
+ break;
+
+ if (all_ports_up == 0) {
+ fflush(stdout);
+ rte_delay_ms(CHECK_INTERVAL);
+ }
+
+ /* set the print_flag if all ports up or timeout */
+ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1))
+ print_flag = 1;
+ }
+}
+
+static void
+print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr)
+{
+ char buf[RTE_ETHER_ADDR_FMT_SIZE];
+ rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
+ printf("%s%s", name, buf);
+}
+
+static int
+init_traffic(struct rte_mempool *mp,
+ struct rte_mbuf **pkts_burst, uint32_t burst_size)
+{
+ struct rte_ether_hdr pkt_eth_hdr;
+ struct rte_ipv4_hdr pkt_ipv4_hdr;
+ struct rte_udp_hdr pkt_udp_hdr;
+ uint32_t pktlen;
+ static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
+ static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
+
+
+ initialize_eth_header(&pkt_eth_hdr,
+ (struct rte_ether_addr *)src_mac,
+ (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
+
+ pktlen = initialize_ipv4_header(&pkt_ipv4_hdr,
+ IPV4_ADDR(10, 0, 0, 1),
+ IPV4_ADDR(10, 0, 0, 2), 26);
+ printf("IPv4 pktlen %u\n", pktlen);
+
+ pktlen = initialize_udp_header(&pkt_udp_hdr, 0, 0, 18);
+
+ printf("UDP pktlen %u\n", pktlen);
+
+ return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr,
+ 0, &pkt_ipv4_hdr, 1,
+ &pkt_udp_hdr, burst_size,
+ PACKET_BURST_GEN_PKT_LEN, 1);
+}
+
+static int
+init_lcores(void)
+{
+ unsigned lcore_id;
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ lcore_conf[lcore_id].socketid =
+ rte_lcore_to_socket_id(lcore_id);
+ if (rte_lcore_is_enabled(lcore_id) == 0) {
+ lcore_conf[lcore_id].status = LCORE_INVALID;
+ continue;
+ } else
+ lcore_conf[lcore_id].status = LCORE_AVAIL;
+ }
+ return 0;
+}
+
+static int
+init_mbufpool(unsigned nb_mbuf)
+{
+ int socketid;
+ unsigned lcore_id;
+ char s[64];
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (rte_lcore_is_enabled(lcore_id) == 0)
+ continue;
+
+ socketid = rte_lcore_to_socket_id(lcore_id);
+ if (socketid >= NB_SOCKETS) {
+ rte_exit(EXIT_FAILURE,
+ "Socket %d of lcore %u is out of range %d\n",
+ socketid, lcore_id, NB_SOCKETS);
+ }
+ if (mbufpool[socketid] == NULL) {
+ snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
+ mbufpool[socketid] =
+ rte_pktmbuf_pool_create(s, nb_mbuf,
+ MEMPOOL_CACHE_SIZE, 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
+ if (mbufpool[socketid] == NULL)
+ rte_exit(EXIT_FAILURE,
+ "Cannot init mbuf pool on socket %d\n",
+ socketid);
+ else
+ printf("Allocated mbuf pool on socket %d\n",
+ socketid);
+ }
+ }
+ return 0;
+}
+
+static uint16_t
+alloc_lcore(uint16_t socketid)
+{
+ unsigned lcore_id;
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (LCORE_AVAIL != lcore_conf[lcore_id].status ||
+ lcore_conf[lcore_id].socketid != socketid ||
+ lcore_id == rte_get_master_lcore())
+ continue;
+ lcore_conf[lcore_id].status = LCORE_USED;
+ lcore_conf[lcore_id].nb_ports = 0;
+ return lcore_id;
+ }
+
+ return (uint16_t)-1;
+}
+
+static volatile uint64_t stop;
+static uint64_t count;
+static uint64_t drop;
+static uint64_t idle;
+
+static void
+reset_count(void)
+{
+ count = 0;
+ drop = 0;
+ idle = 0;
+}
+
+static void
+stats_display(uint16_t port_id)
+{
+ struct rte_eth_stats stats;
+ rte_eth_stats_get(port_id, &stats);
+
+ printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: "
+ "%-"PRIu64"\n",
+ stats.ipackets, stats.imissed, stats.ibytes);
+ printf(" RX-errors: %-10"PRIu64" RX-nombuf: %-10"PRIu64"\n",
+ stats.ierrors, stats.rx_nombuf);
+ printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: "
+ "%-"PRIu64"\n",
+ stats.opackets, stats.oerrors, stats.obytes);
+}
+
+static void
+signal_handler(int signum)
+{
+ /* USR1 signal, stop testing */
+ if (signum == SIGUSR1) {
+ printf("Force Stop!\n");
+ stop = 1;
+ }
+
+ /* USR2 signal, print stats */
+ if (signum == SIGUSR2)
+ stats_display(0);
+}
+
+struct rte_mbuf **tx_burst;
+
+uint64_t (*do_measure)(struct lcore_conf *conf,
+ struct rte_mbuf *pkts_burst[],
+ uint64_t total_pkts);
+
+static uint64_t
+measure_rxtx(struct lcore_conf *conf,
+ struct rte_mbuf *pkts_burst[],
+ uint64_t total_pkts)
+{
+ unsigned i, portid, nb_rx, nb_tx;
+ uint64_t prev_tsc, cur_tsc;
+
+ prev_tsc = rte_rdtsc();
+
+ while (likely(!stop)) {
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ pkts_burst, MAX_PKT_BURST);
+ if (unlikely(nb_rx == 0)) {
+ idle++;
+ continue;
+ }
+
+ count += nb_rx;
+ nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
+ if (unlikely(nb_tx < nb_rx)) {
+ drop += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+ }
+ if (unlikely(count >= total_pkts))
+ break;
+ }
+
+ cur_tsc = rte_rdtsc();
+
+ return cur_tsc - prev_tsc;
+}
+
+static uint64_t
+measure_rxonly(struct lcore_conf *conf,
+ struct rte_mbuf *pkts_burst[],
+ uint64_t total_pkts)
+{
+ unsigned i, portid, nb_rx, nb_tx;
+ uint64_t diff_tsc, cur_tsc;
+
+ diff_tsc = 0;
+ while (likely(!stop)) {
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+
+ cur_tsc = rte_rdtsc();
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ pkts_burst, MAX_PKT_BURST);
+ if (unlikely(nb_rx == 0)) {
+ idle++;
+ continue;
+ }
+ diff_tsc += rte_rdtsc() - cur_tsc;
+
+ count += nb_rx;
+ nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
+ if (unlikely(nb_tx < nb_rx)) {
+ drop += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+ }
+ if (unlikely(count >= total_pkts))
+ break;
+ }
+
+ return diff_tsc;
+}
+
+static uint64_t
+measure_txonly(struct lcore_conf *conf,
+ struct rte_mbuf *pkts_burst[],
+ uint64_t total_pkts)
+{
+ unsigned i, portid, nb_rx, nb_tx;
+ uint64_t diff_tsc, cur_tsc;
+
+ printf("do tx measure\n");
+ diff_tsc = 0;
+ while (likely(!stop)) {
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ pkts_burst, MAX_PKT_BURST);
+ if (unlikely(nb_rx == 0)) {
+ idle++;
+ continue;
+ }
+
+ count += nb_rx;
+
+ cur_tsc = rte_rdtsc();
+ nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx);
+ if (unlikely(nb_tx < nb_rx)) {
+ drop += (nb_rx - nb_tx);
+ do {
+ rte_pktmbuf_free(pkts_burst[nb_tx]);
+ } while (++nb_tx < nb_rx);
+ }
+ diff_tsc += rte_rdtsc() - cur_tsc;
+ }
+ if (unlikely(count >= total_pkts))
+ break;
+ }
+
+ return diff_tsc;
+}
+
+/* main processing loop */
+static int
+main_loop(__rte_unused void *args)
+{
+#define PACKET_SIZE 64
+#define FRAME_GAP 12
+#define MAC_PREAMBLE 8
+ struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+ unsigned lcore_id;
+ unsigned i, portid, nb_rx = 0, nb_tx = 0;
+ struct lcore_conf *conf;
+ int pkt_per_port;
+ uint64_t diff_tsc;
+ uint64_t packets_per_second, total_packets;
+
+ lcore_id = rte_lcore_id();
+ conf = &lcore_conf[lcore_id];
+ if (conf->status != LCORE_USED)
+ return 0;
+
+ pkt_per_port = MAX_TRAFFIC_BURST;
+
+ int idx = 0;
+ for (i = 0; i < conf->nb_ports; i++) {
+ int num = pkt_per_port;
+ portid = conf->portlist[i];
+ printf("inject %d packet to port %d\n", num, portid);
+ while (num) {
+ nb_tx = RTE_MIN(MAX_PKT_BURST, num);
+ nb_tx = rte_eth_tx_burst(portid, 0,
+ &tx_burst[idx], nb_tx);
+ num -= nb_tx;
+ idx += nb_tx;
+ }
+ }
+ printf("Total packets inject to prime ports = %u\n", idx);
+
+ packets_per_second = (link_mbps * 1000 * 1000) /
+ ((PACKET_SIZE + FRAME_GAP + MAC_PREAMBLE) * CHAR_BIT);
+ printf("Each port will do %"PRIu64" packets per second\n",
+ packets_per_second);
+
+ total_packets = RTE_TEST_DURATION * conf->nb_ports * packets_per_second;
+ printf("Test will stop after at least %"PRIu64" packets received\n",
+ + total_packets);
+
+ diff_tsc = do_measure(conf, pkts_burst, total_packets);
+
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ int nb_free = 0;
+ uint64_t timeout = 10000;
+ do { /* dry out */
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ pkts_burst, MAX_PKT_BURST);
+ nb_tx = 0;
+ while (nb_tx < nb_rx)
+ rte_pktmbuf_free(pkts_burst[nb_tx++]);
+ nb_free += nb_rx;
+
+ if (unlikely(nb_rx == 0))
+ timeout--;
+ } while (nb_free != pkt_per_port && timeout != 0);
+ printf("free %d (expected %d) mbuf left in port %u\n", nb_free,
+ pkt_per_port, portid);
+ }
+
+ if (count == 0)
+ return -1;
+
+ printf("%"PRIu64" packet, %"PRIu64" drop, %"PRIu64" idle\n",
+ count, drop, idle);
+ printf("Result: %"PRIu64" cycles per packet\n", diff_tsc / count);
+
+ return 0;
+}
+
+static rte_atomic64_t start;
+
+static inline int
+poll_burst(void *args)
+{
+#define MAX_IDLE (10000)
+ unsigned lcore_id;
+ struct rte_mbuf **pkts_burst;
+ uint64_t diff_tsc, cur_tsc;
+ uint16_t next[RTE_MAX_ETHPORTS];
+ struct lcore_conf *conf;
+ uint32_t pkt_per_port = *((uint32_t *)args);
+ unsigned i, portid, nb_rx = 0;
+ uint64_t total;
+ uint64_t timeout = MAX_IDLE;
+ int num[RTE_MAX_ETHPORTS];
+
+ lcore_id = rte_lcore_id();
+ conf = &lcore_conf[lcore_id];
+ if (conf->status != LCORE_USED)
+ return 0;
+
+ total = pkt_per_port * conf->nb_ports;
+ printf("start to receive total expect %"PRIu64"\n", total);
+
+ pkts_burst = (struct rte_mbuf **)
+ rte_calloc_socket("poll_burst",
+ total, sizeof(void *),
+ RTE_CACHE_LINE_SIZE, conf->socketid);
+ if (!pkts_burst)
+ return -1;
+
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ next[portid] = i * pkt_per_port;
+ num[portid] = pkt_per_port;
+ }
+
+ while (!rte_atomic64_read(&start))
+ ;
+
+ cur_tsc = rte_rdtsc();
+ while (total) {
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ nb_rx = rte_eth_rx_burst(portid, 0,
+ &pkts_burst[next[portid]],
+ RTE_MIN(MAX_PKT_BURST, num[portid]));
+ if (unlikely(nb_rx == 0)) {
+ timeout--;
+ if (unlikely(timeout == 0))
+ goto timeout;
+ continue;
+ }
+ next[portid] += nb_rx;
+ num[portid] -= nb_rx;
+ total -= nb_rx;
+ }
+ }
+timeout:
+ diff_tsc = rte_rdtsc() - cur_tsc;
+
+ printf("%"PRIu64" packets lost, IDLE %"PRIu64" times\n",
+ total, MAX_IDLE - timeout);
+ /* clean up */
+ total = pkt_per_port * conf->nb_ports - total;
+ for (i = 0; i < total; i++)
+ rte_pktmbuf_free(pkts_burst[i]);
+
+ rte_free(pkts_burst);
+
+ if (total > 0)
+ return diff_tsc / total;
+ else
+ return -1;
+}
+
+static int
+exec_burst(uint32_t flags, int lcore)
+{
+ unsigned i, portid, nb_tx = 0;
+ struct lcore_conf *conf;
+ uint32_t pkt_per_port;
+ int num, idx = 0;
+ int diff_tsc;
+
+ conf = &lcore_conf[lcore];
+
+ pkt_per_port = MAX_TRAFFIC_BURST;
+ num = pkt_per_port * conf->nb_ports;
+
+ rte_atomic64_init(&start);
+
+ /* start polling thread, but not actually poll yet */
+ rte_eal_remote_launch(poll_burst,
+ (void *)&pkt_per_port, lcore);
+
+ /* Only when polling first */
+ if (flags == SC_BURST_POLL_FIRST)
+ rte_atomic64_set(&start, 1);
+
+ /* start xmit */
+ while (num) {
+ nb_tx = RTE_MIN(MAX_PKT_BURST, num);
+ for (i = 0; i < conf->nb_ports; i++) {
+ portid = conf->portlist[i];
+ nb_tx = rte_eth_tx_burst(portid, 0,
+ &tx_burst[idx], nb_tx);
+ idx += nb_tx;
+ num -= nb_tx;
+ }
+
+ }
+
+ sleep(5);
+
+ /* only when polling second */
+ if (flags == SC_BURST_XMIT_FIRST)
+ rte_atomic64_set(&start, 1);
+
+ /* wait for polling finished */
+ diff_tsc = rte_eal_wait_lcore(lcore);
+ if (diff_tsc < 0) {
+ printf("exec_burst: Failed to measure cycles per packet\n");
+ return -1;
+ }
+
+ printf("Result: %d cycles per packet\n", diff_tsc);
+
+ return 0;
+}
+
+static int
+test_pmd_perf(void)
+{
+ uint16_t nb_ports, num, nb_lcores, slave_id = (uint16_t)-1;
+ uint16_t nb_rxd = MAX_TRAFFIC_BURST;
+ uint16_t nb_txd = MAX_TRAFFIC_BURST;
+ uint16_t portid;
+ uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
+ int socketid = -1;
+ int ret;
+
+ printf("Start PMD RXTX cycles cost test.\n");
+
+ signal(SIGUSR1, signal_handler);
+ signal(SIGUSR2, signal_handler);
+
+ nb_ports = rte_eth_dev_count_avail();
+ if (nb_ports < NB_ETHPORTS_USED) {
+ printf("At least %u port(s) used for perf. test\n",
+ NB_ETHPORTS_USED);
+ return -1;
+ }
+
+ nb_lcores = rte_lcore_count();
+
+ memset(lcore_conf, 0, sizeof(lcore_conf));
+ init_lcores();
+
+ init_mbufpool(NB_MBUF);
+
+ if (sc_flag == SC_CONTINUOUS) {
+ nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
+ nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+ }
+ printf("CONFIG RXD=%d TXD=%d\n", nb_rxd, nb_txd);
+
+ reset_count();
+ num = 0;
+ RTE_ETH_FOREACH_DEV(portid) {
+ if (socketid == -1) {
+ socketid = rte_eth_dev_socket_id(portid);
+ slave_id = alloc_lcore(socketid);
+ if (slave_id == (uint16_t)-1) {
+ printf("No avail lcore to run test\n");
+ return -1;
+ }
+ printf("Performance test runs on lcore %u socket %u\n",
+ slave_id, socketid);
+ }
+
+ if (socketid != rte_eth_dev_socket_id(portid)) {
+ printf("Skip port %d\n", portid);
+ continue;
+ }
+
+ /* port configure */
+ ret = rte_eth_dev_configure(portid, nb_rx_queue,
+ nb_tx_queue, &port_conf);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot configure device: err=%d, port=%d\n",
+ ret, portid);
+
+ ret = rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "Cannot get mac address: err=%d, port=%d\n",
+ ret, portid);
+
+ printf("Port %u ", portid);
+ print_ethaddr("Address:", &ports_eth_addr[portid]);
+ printf("\n");
+
+ /* tx queue setup */
+ ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
+ socketid, &tx_conf);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_tx_queue_setup: err=%d, "
+ "port=%d\n", ret, portid);
+
+ /* rx queue steup */
+ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
+ socketid, &rx_conf,
+ mbufpool[socketid]);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d,"
+ "port=%d\n", ret, portid);
+
+ /* Start device */
+ stop = 0;
+ ret = rte_eth_dev_start(portid);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_dev_start: err=%d, port=%d\n",
+ ret, portid);
+
+ /* always eanble promiscuous */
+ ret = rte_eth_promiscuous_enable(portid);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE,
+ "rte_eth_promiscuous_enable: err=%s, port=%d\n",
+ rte_strerror(-ret), portid);
+
+ lcore_conf[slave_id].portlist[num++] = portid;
+ lcore_conf[slave_id].nb_ports++;
+ }
+ check_all_ports_link_status(nb_ports, RTE_PORT_ALL);
+
+ if (tx_burst == NULL) {
+ tx_burst = (struct rte_mbuf **)
+ rte_calloc_socket("tx_buff",
+ MAX_TRAFFIC_BURST * nb_ports,
+ sizeof(void *),
+ RTE_CACHE_LINE_SIZE, socketid);
+ if (!tx_burst)
+ return -1;
+ }
+
+ init_traffic(mbufpool[socketid],
+ tx_burst, MAX_TRAFFIC_BURST * nb_ports);
+
+ printf("Generate %d packets @socket %d\n",
+ MAX_TRAFFIC_BURST * nb_ports, socketid);
+
+ if (sc_flag == SC_CONTINUOUS) {
+ /* do both rxtx by default */
+ if (NULL == do_measure)
+ do_measure = measure_rxtx;
+
+ rte_eal_remote_launch(main_loop, NULL, slave_id);
+
+ if (rte_eal_wait_lcore(slave_id) < 0)
+ return -1;
+ } else if (sc_flag == SC_BURST_POLL_FIRST ||
+ sc_flag == SC_BURST_XMIT_FIRST)
+ if (exec_burst(sc_flag, slave_id) < 0)
+ return -1;
+
+ /* port tear down */
+ RTE_ETH_FOREACH_DEV(portid) {
+ if (socketid != rte_eth_dev_socket_id(portid))
+ continue;
+
+ rte_eth_dev_stop(portid);
+ }
+
+ return 0;
+}
+
+int
+test_set_rxtx_conf(cmdline_fixed_string_t mode)
+{
+ printf("mode switch to %s\n", mode);
+
+ if (!strcmp(mode, "vector")) {
+ /* vector rx, tx */
+ tx_conf.tx_rs_thresh = 32;
+ tx_conf.tx_free_thresh = 32;
+ return 0;
+ } else if (!strcmp(mode, "scalar")) {
+ /* bulk alloc rx, full-featured tx */
+ tx_conf.tx_rs_thresh = 32;
+ tx_conf.tx_free_thresh = 32;
+ port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
+ return 0;
+ } else if (!strcmp(mode, "hybrid")) {
+ /* bulk alloc rx, vector tx
+ * when vec macro not define,
+ * using the same rx/tx as scalar
+ */
+ tx_conf.tx_rs_thresh = 32;
+ tx_conf.tx_free_thresh = 32;
+ port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM;
+ return 0;
+ } else if (!strcmp(mode, "full")) {
+ /* full feature rx,tx pair */
+ tx_conf.tx_rs_thresh = 32;
+ tx_conf.tx_free_thresh = 32;
+ port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+test_set_rxtx_anchor(cmdline_fixed_string_t type)
+{
+ printf("type switch to %s\n", type);
+
+ if (!strcmp(type, "rxtx")) {
+ do_measure = measure_rxtx;
+ return 0;
+ } else if (!strcmp(type, "rxonly")) {
+ do_measure = measure_rxonly;
+ return 0;
+ } else if (!strcmp(type, "txonly")) {
+ do_measure = measure_txonly;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+test_set_rxtx_sc(cmdline_fixed_string_t type)
+{
+ printf("stream control switch to %s\n", type);
+
+ if (!strcmp(type, "continuous")) {
+ sc_flag = SC_CONTINUOUS;
+ return 0;
+ } else if (!strcmp(type, "poll_before_xmit")) {
+ sc_flag = SC_BURST_POLL_FIRST;
+ return 0;
+ } else if (!strcmp(type, "poll_after_xmit")) {
+ sc_flag = SC_BURST_XMIT_FIRST;
+ return 0;
+ }
+
+ return -1;
+}
+
+REGISTER_TEST_COMMAND(pmd_perf_autotest, test_pmd_perf);
diff --git a/src/spdk/dpdk/app/test/test_pmd_ring.c b/src/spdk/dpdk/app/test/test_pmd_ring.c
new file mode 100644
index 000000000..02873f26a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_pmd_ring.c
@@ -0,0 +1,579 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2015 Intel Corporation
+ */
+#include "test.h"
+#include <string.h>
+
+#include <stdio.h>
+
+#include <rte_eth_ring.h>
+#include <rte_ethdev.h>
+#include <rte_bus_vdev.h>
+
+#define SOCKET0 0
+#define RING_SIZE 256
+#define NUM_RINGS 2
+#define NB_MBUF 512
+
+static struct rte_mempool *mp;
+struct rte_ring *rxtx[NUM_RINGS];
+static int tx_porta, rx_portb, rxtx_portc, rxtx_portd, rxtx_porte;
+
+static int
+test_ethdev_configure_port(int port)
+{
+ struct rte_eth_conf null_conf;
+ struct rte_eth_link link;
+ int ret;
+
+ memset(&null_conf, 0, sizeof(struct rte_eth_conf));
+
+ if (rte_eth_dev_configure(port, 1, 2, &null_conf) < 0) {
+ printf("Configure failed for port %d\n", port);
+ return -1;
+ }
+
+ /* Test queue release */
+ if (rte_eth_dev_configure(port, 1, 1, &null_conf) < 0) {
+ printf("Configure failed for port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_tx_queue_setup(port, 0, RING_SIZE, SOCKET0, NULL) < 0) {
+ printf("TX queue setup failed port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_rx_queue_setup(port, 0, RING_SIZE, SOCKET0,
+ NULL, mp) < 0) {
+ printf("RX queue setup failed port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_dev_start(port) < 0) {
+ printf("Error starting port %d\n", port);
+ return -1;
+ }
+
+ ret = rte_eth_link_get(port, &link);
+ if (ret < 0) {
+ printf("Link get failed for port %u: %s",
+ port, rte_strerror(-ret));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_send_basic_packets(void)
+{
+ struct rte_mbuf bufs[RING_SIZE];
+ struct rte_mbuf *pbufs[RING_SIZE];
+ int i;
+
+ printf("Testing send and receive RING_SIZE/2 packets (tx_porta -> rx_portb)\n");
+
+ for (i = 0; i < RING_SIZE/2; i++)
+ pbufs[i] = &bufs[i];
+
+ if (rte_eth_tx_burst(tx_porta, 0, pbufs, RING_SIZE/2) < RING_SIZE/2) {
+ printf("Failed to transmit packet burst port %d\n", tx_porta);
+ return TEST_FAILED;
+ }
+
+ if (rte_eth_rx_burst(rx_portb, 0, pbufs, RING_SIZE) != RING_SIZE/2) {
+ printf("Failed to receive packet burst on port %d\n", rx_portb);
+ return TEST_FAILED;
+ }
+
+ for (i = 0; i < RING_SIZE/2; i++)
+ if (pbufs[i] != &bufs[i]) {
+ printf("Error: received data does not match that transmitted\n");
+ return TEST_FAILED;
+ }
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_send_basic_packets_port(int port)
+{
+ struct rte_mbuf bufs[RING_SIZE];
+ struct rte_mbuf *pbufs[RING_SIZE];
+ int i;
+
+ printf("Testing send and receive RING_SIZE/2 packets (cmdl_port0 -> cmdl_port0)\n");
+
+ for (i = 0; i < RING_SIZE/2; i++)
+ pbufs[i] = &bufs[i];
+
+ if (rte_eth_tx_burst(port, 0, pbufs, RING_SIZE/2) < RING_SIZE/2) {
+ printf("Failed to transmit packet burst port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_rx_burst(port, 0, pbufs, RING_SIZE) != RING_SIZE/2) {
+ printf("Failed to receive packet burst on port %d\n", port);
+ return -1;
+ }
+
+ for (i = 0; i < RING_SIZE/2; i++)
+ if (pbufs[i] != &bufs[i]) {
+ printf("Error: received data does not match that transmitted\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int
+test_get_stats(int port)
+{
+ struct rte_eth_stats stats;
+ struct rte_mbuf buf, *pbuf = &buf;
+
+ printf("Testing ring PMD stats_get port %d\n", port);
+
+ /* check stats of RXTX port, should all be zero */
+
+ rte_eth_stats_get(port, &stats);
+ if (stats.ipackets != 0 || stats.opackets != 0 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not zero\n", port);
+ return -1;
+ }
+
+ /* send and receive 1 packet and check for stats update */
+ if (rte_eth_tx_burst(port, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_rx_burst(port, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", port);
+ return -1;
+ }
+
+ rte_eth_stats_get(port, &stats);
+ if (stats.ipackets != 1 || stats.opackets != 1 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n", port);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_stats_reset(int port)
+{
+ struct rte_eth_stats stats;
+ struct rte_mbuf buf, *pbuf = &buf;
+
+ printf("Testing ring PMD stats_reset port %d\n", port);
+
+ rte_eth_stats_reset(port);
+
+ /* check stats of RXTX port, should all be zero */
+ rte_eth_stats_get(port, &stats);
+ if (stats.ipackets != 0 || stats.opackets != 0 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not zero\n", port);
+ return -1;
+ }
+
+ /* send and receive 1 packet and check for stats update */
+ if (rte_eth_tx_burst(port, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", port);
+ return -1;
+ }
+
+ if (rte_eth_rx_burst(port, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", port);
+ return -1;
+ }
+
+ rte_eth_stats_get(port, &stats);
+ if (stats.ipackets != 1 || stats.opackets != 1 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n", port);
+ return -1;
+ }
+
+ rte_eth_stats_reset(port);
+
+ /* check stats of RXTX port, should all be zero */
+ rte_eth_stats_get(port, &stats);
+ if (stats.ipackets != 0 || stats.opackets != 0 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not zero\n", port);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_pmd_ring_pair_create_attach(void)
+{
+ struct rte_eth_stats stats, stats2;
+ struct rte_mbuf buf, *pbuf = &buf;
+ struct rte_eth_conf null_conf;
+
+ memset(&null_conf, 0, sizeof(struct rte_eth_conf));
+
+ if ((rte_eth_dev_configure(rxtx_portd, 1, 1, &null_conf) < 0)
+ || (rte_eth_dev_configure(rxtx_porte, 1, 1,
+ &null_conf) < 0)) {
+ printf("Configure failed for port\n");
+ return TEST_FAILED;
+ }
+
+ if ((rte_eth_tx_queue_setup(rxtx_portd, 0, RING_SIZE,
+ SOCKET0, NULL) < 0)
+ || (rte_eth_tx_queue_setup(rxtx_porte, 0, RING_SIZE,
+ SOCKET0, NULL) < 0)) {
+ printf("TX queue setup failed\n");
+ return TEST_FAILED;
+ }
+
+ if ((rte_eth_rx_queue_setup(rxtx_portd, 0, RING_SIZE,
+ SOCKET0, NULL, mp) < 0)
+ || (rte_eth_rx_queue_setup(rxtx_porte, 0, RING_SIZE,
+ SOCKET0, NULL, mp) < 0)) {
+ printf("RX queue setup failed\n");
+ return TEST_FAILED;
+ }
+
+ if ((rte_eth_dev_start(rxtx_portd) < 0)
+ || (rte_eth_dev_start(rxtx_porte) < 0)) {
+ printf("Error starting port\n");
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_reset(rxtx_portd);
+ /* check stats of port, should all be zero */
+ rte_eth_stats_get(rxtx_portd, &stats);
+ if (stats.ipackets != 0 || stats.opackets != 0 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not zero\n", rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_reset(rxtx_porte);
+ /* check stats of port, should all be zero */
+ rte_eth_stats_get(rxtx_porte, &stats2);
+ if (stats2.ipackets != 0 || stats2.opackets != 0 ||
+ stats2.ibytes != 0 || stats2.obytes != 0 ||
+ stats2.ierrors != 0 || stats2.oerrors != 0) {
+ printf("Error: port %d stats are not zero\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ /*
+ * send and receive 1 packet (rxtx_portd -> rxtx_porte)
+ * and check for stats update
+ */
+ printf("Testing send and receive 1 packet (rxtx_portd -> rxtx_porte)\n");
+ if (rte_eth_tx_burst(rxtx_portd, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (rte_eth_rx_burst(rxtx_porte, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_get(rxtx_portd, &stats);
+ rte_eth_stats_get(rxtx_porte, &stats2);
+ if (stats.ipackets != 0 || stats.opackets != 1 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (stats2.ipackets != 1 || stats2.opackets != 0 ||
+ stats2.ibytes != 0 || stats2.obytes != 0 ||
+ stats2.ierrors != 0 || stats2.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ /*
+ * send and receive 1 packet (rxtx_porte -> rxtx_portd)
+ * and check for stats update
+ */
+ printf("Testing send and receive 1 packet "
+ "(rxtx_porte -> rxtx_portd)\n");
+ if (rte_eth_tx_burst(rxtx_porte, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ if (rte_eth_rx_burst(rxtx_portd, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_get(rxtx_portd, &stats);
+ rte_eth_stats_get(rxtx_porte, &stats2);
+ if (stats.ipackets != 1 || stats.opackets != 1 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (stats2.ipackets != 1 || stats2.opackets != 1 ||
+ stats2.ibytes != 0 || stats2.obytes != 0 ||
+ stats2.ierrors != 0 || stats2.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ /*
+ * send and receive 1 packet (rxtx_portd -> rxtx_portd)
+ * and check for stats update
+ */
+ printf("Testing send and receive 1 packet "
+ "(rxtx_portd -> rxtx_portd)\n");
+ if (rte_eth_tx_burst(rxtx_portd, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (rte_eth_rx_burst(rxtx_portd, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_get(rxtx_portd, &stats);
+ rte_eth_stats_get(rxtx_porte, &stats2);
+ if (stats.ipackets != 2 || stats.opackets != 2 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (stats2.ipackets != 1 || stats2.opackets != 1 ||
+ stats2.ibytes != 0 || stats2.obytes != 0 ||
+ stats2.ierrors != 0 || stats2.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ /*
+ * send and receive 1 packet (rxtx_porte -> rxtx_porte)
+ * and check for stats update
+ */
+ printf("Testing send and receive 1 packet "
+ "(rxtx_porte -> rxtx_porte)\n");
+ if (rte_eth_tx_burst(rxtx_porte, 0, &pbuf, 1) != 1) {
+ printf("Error sending packet to port %d\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ if (rte_eth_rx_burst(rxtx_porte, 0, &pbuf, 1) != 1) {
+ printf("Error receiving packet from port %d\n", rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ rte_eth_stats_get(rxtx_portd, &stats);
+ rte_eth_stats_get(rxtx_porte, &stats2);
+ if (stats.ipackets != 2 || stats.opackets != 2 ||
+ stats.ibytes != 0 || stats.obytes != 0 ||
+ stats.ierrors != 0 || stats.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_portd);
+ return TEST_FAILED;
+ }
+
+ if (stats2.ipackets != 2 || stats2.opackets != 2 ||
+ stats2.ibytes != 0 || stats2.obytes != 0 ||
+ stats2.ierrors != 0 || stats2.oerrors != 0) {
+ printf("Error: port %d stats are not as expected\n",
+ rxtx_porte);
+ return TEST_FAILED;
+ }
+
+ rte_eth_dev_stop(rxtx_portd);
+ rte_eth_dev_stop(rxtx_porte);
+
+ return TEST_SUCCESS;
+}
+
+static void
+test_cleanup_resources(void)
+{
+ int itr;
+ for (itr = 0; itr < NUM_RINGS; itr++)
+ rte_ring_free(rxtx[itr]);
+
+ rte_eth_dev_stop(tx_porta);
+ rte_eth_dev_stop(rx_portb);
+ rte_eth_dev_stop(rxtx_portc);
+
+ rte_mempool_free(mp);
+ rte_vdev_uninit("net_ring_net_ringa");
+ rte_vdev_uninit("net_ring_net_ringb");
+ rte_vdev_uninit("net_ring_net_ringc");
+ rte_vdev_uninit("net_ring_net_ringd");
+ rte_vdev_uninit("net_ring_net_ringe");
+}
+
+static int
+test_pmd_ringcreate_setup(void)
+{
+ uint8_t nb_ports;
+
+ nb_ports = rte_eth_dev_count_avail();
+ printf("nb_ports=%d\n", (int)nb_ports);
+
+ /* create the rings and eth_rings in the test code.
+ * This does not test the rte_pmd_ring_devinit function.
+ *
+ * Test with the command line option --vdev=net_ring0 to test rte_pmd_ring_devinit.
+ */
+ rxtx[0] = rte_ring_create("R0", RING_SIZE, SOCKET0, RING_F_SP_ENQ|RING_F_SC_DEQ);
+ if (rxtx[0] == NULL) {
+ printf("rte_ring_create R0 failed");
+ return -1;
+ }
+
+ rxtx[1] = rte_ring_create("R1", RING_SIZE, SOCKET0, RING_F_SP_ENQ|RING_F_SC_DEQ);
+ if (rxtx[1] == NULL) {
+ printf("rte_ring_create R1 failed");
+ return -1;
+ }
+
+ tx_porta = rte_eth_from_rings("net_ringa", rxtx, NUM_RINGS, rxtx, NUM_RINGS, SOCKET0);
+ rx_portb = rte_eth_from_rings("net_ringb", rxtx, NUM_RINGS, rxtx, NUM_RINGS, SOCKET0);
+ rxtx_portc = rte_eth_from_rings("net_ringc", rxtx, NUM_RINGS, rxtx, NUM_RINGS, SOCKET0);
+ rxtx_portd = rte_eth_from_rings("net_ringd", rxtx, NUM_RINGS, rxtx, NUM_RINGS, SOCKET0);
+ rxtx_porte = rte_eth_from_rings("net_ringe", rxtx, NUM_RINGS, rxtx, NUM_RINGS, SOCKET0);
+
+ printf("tx_porta=%d rx_portb=%d rxtx_portc=%d rxtx_portd=%d rxtx_porte=%d\n",
+ tx_porta, rx_portb, rxtx_portc, rxtx_portd, rxtx_porte);
+
+ if ((tx_porta == -1) || (rx_portb == -1) || (rxtx_portc == -1)
+ || (rxtx_portd == -1) || (rxtx_porte == -1)) {
+ printf("rte_eth_from rings failed\n");
+ return -1;
+ }
+
+ mp = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+ if (mp == NULL)
+ return -1;
+
+ if ((tx_porta >= RTE_MAX_ETHPORTS) || (rx_portb >= RTE_MAX_ETHPORTS)
+ || (rxtx_portc >= RTE_MAX_ETHPORTS)
+ || (rxtx_portd >= RTE_MAX_ETHPORTS)
+ || (rxtx_porte >= RTE_MAX_ETHPORTS)) {
+ printf(" port exceed max eth ports\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_command_line_ring_port(void)
+{
+ int port, cmdl_port0 = -1;
+ int ret;
+
+ /* find a port created with the --vdev=net_ring0 command line option */
+ RTE_ETH_FOREACH_DEV(port) {
+ struct rte_eth_dev_info dev_info;
+
+ ret = rte_eth_dev_info_get(port, &dev_info);
+ TEST_ASSERT((ret == 0),
+ "Error during getting device (port %d) info: %s\n",
+ port, strerror(-ret));
+
+ if (!strcmp(dev_info.driver_name, "Rings PMD")) {
+ printf("found a command line ring port=%d\n", port);
+ cmdl_port0 = port;
+ break;
+ }
+ }
+ if (cmdl_port0 != -1) {
+ TEST_ASSERT((test_ethdev_configure_port(cmdl_port0) < 0),
+ "test ethdev configure port cmdl_port0 is failed");
+ TEST_ASSERT((test_send_basic_packets_port(cmdl_port0) < 0),
+ "test send basic packets port cmdl_port0 is failed");
+ TEST_ASSERT((test_stats_reset(cmdl_port0) < 0),
+ "test stats reset cmdl_port0 is failed");
+ TEST_ASSERT((test_get_stats(cmdl_port0) < 0),
+ "test get stats cmdl_port0 is failed");
+ rte_eth_dev_stop(cmdl_port0);
+ }
+ return TEST_SUCCESS;
+}
+
+static int
+test_ethdev_configure_ports(void)
+{
+ TEST_ASSERT((test_ethdev_configure_port(tx_porta) == 0),
+ "test ethdev configure ports tx_porta is failed");
+ TEST_ASSERT((test_ethdev_configure_port(rx_portb) == 0),
+ "test ethdev configure ports rx_portb is failed");
+ TEST_ASSERT((test_ethdev_configure_port(rxtx_portc) == 0),
+ "test ethdev configure ports rxtx_portc is failed");
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_get_stats_for_port(void)
+{
+ TEST_ASSERT(test_get_stats(rxtx_portc) == 0, "test get stats failed");
+ return TEST_SUCCESS;
+}
+
+static int
+test_stats_reset_for_port(void)
+{
+ TEST_ASSERT(test_stats_reset(rxtx_portc) == 0, "test stats reset failed");
+ return TEST_SUCCESS;
+}
+
+static struct
+unit_test_suite test_pmd_ring_suite = {
+ .setup = test_pmd_ringcreate_setup,
+ .teardown = test_cleanup_resources,
+ .suite_name = "Test Pmd Ring Unit Test Suite",
+ .unit_test_cases = {
+ TEST_CASE(test_ethdev_configure_ports),
+ TEST_CASE(test_send_basic_packets),
+ TEST_CASE(test_get_stats_for_port),
+ TEST_CASE(test_stats_reset_for_port),
+ TEST_CASE(test_pmd_ring_pair_create_attach),
+ TEST_CASE(test_command_line_ring_port),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_pmd_ring(void)
+{
+ return unit_test_suite_runner(&test_pmd_ring_suite);
+}
+
+REGISTER_TEST_COMMAND(ring_pmd_autotest, test_pmd_ring);
diff --git a/src/spdk/dpdk/app/test/test_pmd_ring_perf.c b/src/spdk/dpdk/app/test/test_pmd_ring_perf.c
new file mode 100644
index 000000000..3b2ff9cb4
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_pmd_ring_perf.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Intel Corporation
+ */
+
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <rte_ring.h>
+#include <rte_cycles.h>
+#include <rte_launch.h>
+#include <rte_ethdev.h>
+#include <rte_eth_ring.h>
+#include <rte_bus_vdev.h>
+
+#include "test.h"
+
+#define RING_NAME "RING_PERF"
+#define RING_SIZE 4096
+#define MAX_BURST 32
+
+/*
+ * the sizes to enqueue and dequeue in testing
+ * (marked volatile so they won't be seen as compile-time constants)
+ */
+static const volatile unsigned bulk_sizes[] = { 1, 8, 32 };
+
+/* The ring structure used for tests */
+static struct rte_ring *r;
+static uint16_t ring_ethdev_port;
+
+/* Get cycle counts for dequeuing from an empty ring. Should be 2 or 3 cycles */
+static void
+test_empty_dequeue(void)
+{
+ const unsigned iter_shift = 26;
+ const unsigned iterations = 1 << iter_shift;
+ unsigned i = 0;
+ void *burst[MAX_BURST];
+
+ const uint64_t sc_start = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_ring_sc_dequeue_bulk(r, burst, bulk_sizes[0], NULL);
+ const uint64_t sc_end = rte_rdtsc();
+
+ const uint64_t eth_start = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_eth_rx_burst(ring_ethdev_port, 0, (void *)burst,
+ bulk_sizes[0]);
+ const uint64_t eth_end = rte_rdtsc();
+
+ printf("Ring empty dequeue : %.1F\n",
+ (double)(sc_end - sc_start) / iterations);
+ printf("Ethdev empty dequeue: %.1F\n",
+ (double)(eth_end - eth_start) / iterations);
+}
+
+/*
+ * Test function that determines how long an enqueue + dequeue of a single item
+ * takes on a single lcore. Result is for comparison with the bulk enq+deq.
+ */
+static void
+test_single_enqueue_dequeue(void)
+{
+ const unsigned iter_shift = 24;
+ const unsigned iterations = 1 << iter_shift;
+ unsigned i = 0;
+ void *burst = NULL;
+ struct rte_mbuf *mburst[1] = { NULL };
+
+ const uint64_t sc_start = rte_rdtsc_precise();
+ rte_compiler_barrier();
+ for (i = 0; i < iterations; i++) {
+ rte_ring_enqueue_bulk(r, &burst, 1, NULL);
+ rte_ring_dequeue_bulk(r, &burst, 1, NULL);
+ }
+ const uint64_t sc_end = rte_rdtsc_precise();
+ rte_compiler_barrier();
+
+ const uint64_t eth_start = rte_rdtsc_precise();
+ rte_compiler_barrier();
+ for (i = 0; i < iterations; i++) {
+ rte_eth_tx_burst(ring_ethdev_port, 0, mburst, 1);
+ rte_eth_rx_burst(ring_ethdev_port, 0, mburst, 1);
+ }
+ const uint64_t eth_end = rte_rdtsc_precise();
+ rte_compiler_barrier();
+
+ printf("Ring single enq/dequeue : %"PRIu64"\n",
+ (sc_end-sc_start) >> iter_shift);
+ printf("Ethdev single enq/dequeue: %"PRIu64"\n",
+ (eth_end-eth_start) >> iter_shift);
+}
+
+/* Times enqueue and dequeue on a single lcore */
+static void
+test_bulk_enqueue_dequeue(void)
+{
+ const unsigned iter_shift = 23;
+ const unsigned iterations = 1 << iter_shift;
+ unsigned sz, i = 0;
+ struct rte_mbuf *burst[MAX_BURST] = {0};
+
+ for (sz = 0; sz < RTE_DIM(bulk_sizes); sz++) {
+ const uint64_t sc_start = rte_rdtsc();
+ for (i = 0; i < iterations; i++) {
+ rte_ring_sp_enqueue_bulk(r, (void *)burst,
+ bulk_sizes[sz], NULL);
+ rte_ring_sc_dequeue_bulk(r, (void *)burst,
+ bulk_sizes[sz], NULL);
+ }
+ const uint64_t sc_end = rte_rdtsc();
+
+ const uint64_t eth_start = rte_rdtsc_precise();
+ rte_compiler_barrier();
+ for (i = 0; i < iterations; i++) {
+ rte_eth_tx_burst(ring_ethdev_port, 0, burst, bulk_sizes[sz]);
+ rte_eth_rx_burst(ring_ethdev_port, 0, burst, bulk_sizes[sz]);
+ }
+ const uint64_t eth_end = rte_rdtsc_precise();
+ rte_compiler_barrier();
+
+ double sc_avg = ((double)(sc_end-sc_start) /
+ (iterations * bulk_sizes[sz]));
+ double eth_avg = ((double)(eth_end-eth_start) /
+ (iterations * bulk_sizes[sz]));
+
+ printf("ring bulk enq/deq (size: %u) : %.1F\n", bulk_sizes[sz],
+ sc_avg);
+ printf("ethdev bulk enq/deq (size:%u): %.1F\n", bulk_sizes[sz],
+ eth_avg);
+
+ printf("\n");
+ }
+}
+
+static int
+test_ring_pmd_perf(void)
+{
+ char name[RTE_ETH_NAME_MAX_LEN];
+
+ r = rte_ring_create(RING_NAME, RING_SIZE, rte_socket_id(),
+ RING_F_SP_ENQ|RING_F_SC_DEQ);
+ if (r == NULL && (r = rte_ring_lookup(RING_NAME)) == NULL)
+ return -1;
+
+ ring_ethdev_port = rte_eth_from_ring(r);
+
+ printf("\n### Testing const single element enq/deq ###\n");
+ test_single_enqueue_dequeue();
+
+ printf("\n### Testing empty dequeue ###\n");
+ test_empty_dequeue();
+
+ printf("\n### Testing using a single lcore ###\n");
+ test_bulk_enqueue_dequeue();
+
+ /* release port and ring resources */
+ rte_eth_dev_stop(ring_ethdev_port);
+ rte_eth_dev_get_name_by_port(ring_ethdev_port, name);
+ rte_vdev_uninit(name);
+ rte_ring_free(r);
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(ring_pmd_perf_autotest, test_ring_pmd_perf);
diff --git a/src/spdk/dpdk/app/test/test_power.c b/src/spdk/dpdk/app/test/test_power.c
new file mode 100644
index 000000000..0c597c33f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_power.c
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "test.h"
+
+#ifndef RTE_LIBRTE_POWER
+
+static int
+test_power(void)
+{
+ printf("Power management library not supported, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+#else
+
+#include <rte_power.h>
+
+static int
+check_function_ptrs(void)
+{
+ enum power_management_env env = rte_power_get_env();
+
+ const bool not_null_expected = !(env == PM_ENV_NOT_SET);
+
+ const char *inject_not_string1 = not_null_expected ? " not" : "";
+ const char *inject_not_string2 = not_null_expected ? "" : " not";
+
+ if ((rte_power_freqs == NULL) == not_null_expected) {
+ printf("rte_power_freqs should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_get_freq == NULL) == not_null_expected) {
+ printf("rte_power_get_freq should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_set_freq == NULL) == not_null_expected) {
+ printf("rte_power_set_freq should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_up == NULL) == not_null_expected) {
+ printf("rte_power_freq_up should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_down == NULL) == not_null_expected) {
+ printf("rte_power_freq_down should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_max == NULL) == not_null_expected) {
+ printf("rte_power_freq_max should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_min == NULL) == not_null_expected) {
+ printf("rte_power_freq_min should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_turbo_status == NULL) == not_null_expected) {
+ printf("rte_power_turbo_status should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_enable_turbo == NULL) == not_null_expected) {
+ printf("rte_power_freq_enable_turbo should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_freq_disable_turbo == NULL) == not_null_expected) {
+ printf("rte_power_freq_disable_turbo should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+ if ((rte_power_get_capabilities == NULL) == not_null_expected) {
+ printf("rte_power_get_capabilities should%s be NULL, environment has%s been "
+ "initialised\n", inject_not_string1,
+ inject_not_string2);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_power(void)
+{
+ int ret = -1;
+ enum power_management_env env;
+
+ /* Test setting an invalid environment */
+ ret = rte_power_set_env(PM_ENV_NOT_SET);
+ if (ret == 0) {
+ printf("Unexpectedly succeeded on setting an invalid environment\n");
+ return -1;
+ }
+
+ /* Test that the environment has not been set */
+ env = rte_power_get_env();
+ if (env != PM_ENV_NOT_SET) {
+ printf("Unexpectedly got a valid environment configuration\n");
+ return -1;
+ }
+
+ /* Verify that function pointers are NULL */
+ if (check_function_ptrs() < 0)
+ goto fail_all;
+
+ rte_power_unset_env();
+
+ /* Perform tests for valid environments.*/
+ const enum power_management_env envs[] = {PM_ENV_ACPI_CPUFREQ,
+ PM_ENV_KVM_VM,
+ PM_ENV_PSTATE_CPUFREQ};
+
+ unsigned int i;
+ for (i = 0; i < RTE_DIM(envs); ++i) {
+
+ /* Test setting a valid environment */
+ ret = rte_power_set_env(envs[i]);
+ if (ret != 0) {
+ printf("Unexpectedly unsucceeded on setting a valid environment\n");
+ return -1;
+ }
+
+ /* Test that the environment has been set */
+ env = rte_power_get_env();
+ if (env != envs[i]) {
+ printf("Not expected environment configuration\n");
+ return -1;
+ }
+
+ /* Verify that function pointers are NOT NULL */
+ if (check_function_ptrs() < 0)
+ goto fail_all;
+
+ rte_power_unset_env();
+
+ /* Verify that function pointers are NULL */
+ if (check_function_ptrs() < 0)
+ goto fail_all;
+
+ }
+
+ return 0;
+fail_all:
+ rte_power_unset_env();
+ return -1;
+}
+#endif
+
+REGISTER_TEST_COMMAND(power_autotest, test_power);
diff --git a/src/spdk/dpdk/app/test/test_power_cpufreq.c b/src/spdk/dpdk/app/test/test_power_cpufreq.c
new file mode 100644
index 000000000..d203810da
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_power_cpufreq.c
@@ -0,0 +1,644 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "test.h"
+
+#ifndef RTE_LIBRTE_POWER
+
+static int
+test_power_cpufreq(void)
+{
+ printf("Power management library not supported, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+static int
+test_power_caps(void)
+{
+ printf("Power management library not supported, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+#else
+#include <rte_power.h>
+
+#define TEST_POWER_LCORE_ID 2U
+#define TEST_POWER_LCORE_INVALID ((unsigned)RTE_MAX_LCORE)
+#define TEST_POWER_FREQS_NUM_MAX ((unsigned)RTE_MAX_LCORE_FREQS)
+
+#define TEST_POWER_SYSFILE_CUR_FREQ \
+ "/sys/devices/system/cpu/cpu%u/cpufreq/cpuinfo_cur_freq"
+
+static uint32_t total_freq_num;
+static uint32_t freqs[TEST_POWER_FREQS_NUM_MAX];
+
+static int
+check_cur_freq(unsigned lcore_id, uint32_t idx)
+{
+#define TEST_POWER_CONVERT_TO_DECIMAL 10
+ FILE *f;
+ char fullpath[PATH_MAX];
+ char buf[BUFSIZ];
+ uint32_t cur_freq;
+ int ret = -1;
+
+ if (snprintf(fullpath, sizeof(fullpath),
+ TEST_POWER_SYSFILE_CUR_FREQ, lcore_id) < 0) {
+ return 0;
+ }
+ f = fopen(fullpath, "r");
+ if (f == NULL) {
+ return 0;
+ }
+ if (fgets(buf, sizeof(buf), f) == NULL) {
+ goto fail_get_cur_freq;
+ }
+ cur_freq = strtoul(buf, NULL, TEST_POWER_CONVERT_TO_DECIMAL);
+ ret = (freqs[idx] == cur_freq ? 0 : -1);
+
+fail_get_cur_freq:
+ fclose(f);
+
+ return ret;
+}
+
+/* Check rte_power_freqs() */
+static int
+check_power_freqs(void)
+{
+ uint32_t ret;
+
+ total_freq_num = 0;
+ memset(freqs, 0, sizeof(freqs));
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freqs(TEST_POWER_LCORE_INVALID, freqs,
+ TEST_POWER_FREQS_NUM_MAX);
+ if (ret > 0) {
+ printf("Unexpectedly get available freqs successfully on "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+
+ /* test with NULL buffer to save available freqs */
+ ret = rte_power_freqs(TEST_POWER_LCORE_ID, NULL,
+ TEST_POWER_FREQS_NUM_MAX);
+ if (ret > 0) {
+ printf("Unexpectedly get available freqs successfully with "
+ "NULL buffer on lcore %u\n", TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* test of getting zero number of freqs */
+ ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs, 0);
+ if (ret > 0) {
+ printf("Unexpectedly get available freqs successfully with "
+ "zero buffer size on lcore %u\n", TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* test with all valid input parameters */
+ ret = rte_power_freqs(TEST_POWER_LCORE_ID, freqs,
+ TEST_POWER_FREQS_NUM_MAX);
+ if (ret == 0 || ret > TEST_POWER_FREQS_NUM_MAX) {
+ printf("Fail to get available freqs on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Save the total number of available freqs */
+ total_freq_num = ret;
+
+ return 0;
+}
+
+/* Check rte_power_get_freq() */
+static int
+check_power_get_freq(void)
+{
+ int ret;
+ uint32_t count;
+
+ /* test with an invalid lcore id */
+ count = rte_power_get_freq(TEST_POWER_LCORE_INVALID);
+ if (count < TEST_POWER_FREQS_NUM_MAX) {
+ printf("Unexpectedly get freq index successfully on "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+
+ count = rte_power_get_freq(TEST_POWER_LCORE_ID);
+ if (count >= TEST_POWER_FREQS_NUM_MAX) {
+ printf("Fail to get the freq index on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, count);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_set_freq() */
+static int
+check_power_set_freq(void)
+{
+ int ret;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_set_freq(TEST_POWER_LCORE_INVALID, 0);
+ if (ret >= 0) {
+ printf("Unexpectedly set freq index successfully on "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+
+ /* test with an invalid freq index */
+ ret = rte_power_set_freq(TEST_POWER_LCORE_ID,
+ TEST_POWER_FREQS_NUM_MAX);
+ if (ret >= 0) {
+ printf("Unexpectedly set an invalid freq index (%u)"
+ "successfully on lcore %u\n", TEST_POWER_FREQS_NUM_MAX,
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /**
+ * test with an invalid freq index which is right one bigger than
+ * total number of freqs
+ */
+ ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num);
+ if (ret >= 0) {
+ printf("Unexpectedly set an invalid freq index (%u)"
+ "successfully on lcore %u\n", total_freq_num,
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+ ret = rte_power_set_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
+ if (ret < 0) {
+ printf("Fail to set freq index on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_freq_down() */
+static int
+check_power_freq_down(void)
+{
+ int ret;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_down(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly scale down successfully the freq on "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+
+ /* Scale down to min and then scale down one step */
+ ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale down the freq to min on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+ ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale down the freq on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
+ if (ret < 0)
+ return -1;
+
+ /* Scale up to max and then scale down one step */
+ ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale up the freq to max on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+ ret = rte_power_freq_down(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale down the freq on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_freq_up() */
+static int
+check_power_freq_up(void)
+{
+ int ret;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_up(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly scale up successfully the freq on %u\n",
+ TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+
+ /* Scale down to min and then scale up one step */
+ ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale down the freq to min on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+ ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale up the freq on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 2);
+ if (ret < 0)
+ return -1;
+
+ /* Scale up to max and then scale up one step */
+ ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale up the freq to max on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+ ret = rte_power_freq_up(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale up the freq on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_freq_max() */
+static int
+check_power_freq_max(void)
+{
+ int ret;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_max(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly scale up successfully the freq to max on "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+ ret = rte_power_freq_max(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale up the freq to max on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_freq_min() */
+static int
+check_power_freq_min(void)
+{
+ int ret;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_min(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly scale down successfully the freq to min "
+ "on lcore %u\n", TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+ ret = rte_power_freq_min(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to scale down the freq to min on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, total_freq_num - 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check rte_power_turbo() */
+static int
+check_power_turbo(void)
+{
+ int ret;
+
+ if (rte_power_turbo_status(TEST_POWER_LCORE_ID) == 0) {
+ printf("Turbo not available on lcore %u, skipping test\n",
+ TEST_POWER_LCORE_ID);
+ return 0;
+ }
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly enable turbo successfully on lcore %u\n",
+ TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+ ret = rte_power_freq_enable_turbo(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to enable turbo on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, 0);
+ if (ret < 0)
+ return -1;
+
+ /* test with an invalid lcore id */
+ ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_INVALID);
+ if (ret >= 0) {
+ printf("Unexpectedly disable turbo successfully on lcore %u\n",
+ TEST_POWER_LCORE_INVALID);
+ return -1;
+ }
+ ret = rte_power_freq_disable_turbo(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Fail to disable turbo on lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ return -1;
+ }
+
+ /* Check the current frequency */
+ ret = check_cur_freq(TEST_POWER_LCORE_ID, 1);
+ if (ret < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+test_power_cpufreq(void)
+{
+ int ret = -1;
+ enum power_management_env env;
+
+ /* Test initialisation of a valid lcore */
+ ret = rte_power_init(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot initialise power management for lcore %u, this "
+ "may occur if environment is not configured "
+ "correctly(APCI cpufreq) or operating in another valid "
+ "Power management environment\n",
+ TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return TEST_SKIPPED;
+ }
+
+ /* Test environment configuration */
+ env = rte_power_get_env();
+ if ((env != PM_ENV_ACPI_CPUFREQ) && (env != PM_ENV_PSTATE_CPUFREQ)) {
+ printf("Unexpectedly got an environment other than ACPI/PSTATE\n");
+ goto fail_all;
+ }
+
+ /* verify that function pointers are not NULL */
+ if (rte_power_freqs == NULL) {
+ printf("rte_power_freqs should not be NULL, environment has not been "
+ "initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_get_freq == NULL) {
+ printf("rte_power_get_freq should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_set_freq == NULL) {
+ printf("rte_power_set_freq should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_up == NULL) {
+ printf("rte_power_freq_up should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_down == NULL) {
+ printf("rte_power_freq_down should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_max == NULL) {
+ printf("rte_power_freq_max should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_min == NULL) {
+ printf("rte_power_freq_min should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_turbo_status == NULL) {
+ printf("rte_power_turbo_status should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_enable_turbo == NULL) {
+ printf("rte_power_freq_enable_turbo should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+ if (rte_power_freq_disable_turbo == NULL) {
+ printf("rte_power_freq_disable_turbo should not be NULL, environment has not "
+ "been initialised\n");
+ goto fail_all;
+ }
+
+ ret = rte_power_exit(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot exit power management for lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /* test of init power management for an invalid lcore */
+ ret = rte_power_init(TEST_POWER_LCORE_INVALID);
+ if (ret == 0) {
+ printf("Unexpectedly initialise power management successfully "
+ "for lcore %u\n", TEST_POWER_LCORE_INVALID);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /* Test initialisation of a valid lcore */
+ ret = rte_power_init(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot initialise power management for lcore %u, this "
+ "may occur if environment is not configured "
+ "correctly(APCI cpufreq) or operating in another valid "
+ "Power management environment\n", TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return TEST_SKIPPED;
+ }
+
+ /**
+ * test of initialising power management for the lcore which has
+ * been initialised
+ */
+ ret = rte_power_init(TEST_POWER_LCORE_ID);
+ if (ret == 0) {
+ printf("Unexpectedly init successfully power twice on "
+ "lcore %u\n", TEST_POWER_LCORE_ID);
+ goto fail_all;
+ }
+
+ ret = check_power_freqs();
+ if (ret < 0)
+ goto fail_all;
+
+ if (total_freq_num < 2) {
+ rte_power_exit(TEST_POWER_LCORE_ID);
+ printf("Frequency can not be changed due to CPU itself\n");
+ rte_power_unset_env();
+ return 0;
+ }
+
+ ret = check_power_get_freq();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_set_freq();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_freq_down();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_freq_up();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_freq_max();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_freq_min();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = check_power_turbo();
+ if (ret < 0)
+ goto fail_all;
+
+ ret = rte_power_exit(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot exit power management for lcore %u\n",
+ TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /**
+ * test of exiting power management for the lcore which has been exited
+ */
+ ret = rte_power_exit(TEST_POWER_LCORE_ID);
+ if (ret == 0) {
+ printf("Unexpectedly exit successfully power management twice "
+ "on lcore %u\n", TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /* test of exit power management for an invalid lcore */
+ ret = rte_power_exit(TEST_POWER_LCORE_INVALID);
+ if (ret == 0) {
+ printf("Unpectedly exit power management successfully for "
+ "lcore %u\n", TEST_POWER_LCORE_INVALID);
+ rte_power_unset_env();
+ return -1;
+ }
+ rte_power_unset_env();
+ return 0;
+
+fail_all:
+ rte_power_exit(TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+}
+
+static int
+test_power_caps(void)
+{
+ struct rte_power_core_capabilities caps;
+ int ret;
+
+ ret = rte_power_init(TEST_POWER_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot initialise power management for lcore %u, this "
+ "may occur if environment is not configured "
+ "correctly(APCI cpufreq) or operating in another valid "
+ "Power management environment\n", TEST_POWER_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ ret = rte_power_get_capabilities(TEST_POWER_LCORE_ID, &caps);
+ if (ret) {
+ printf("POWER: Error getting capabilities\n");
+ return -1;
+ }
+
+ printf("POWER: Capabilities %"PRIx64"\n", caps.capabilities);
+
+ rte_power_unset_env();
+ return 0;
+}
+
+#endif
+
+REGISTER_TEST_COMMAND(power_cpufreq_autotest, test_power_cpufreq);
+REGISTER_TEST_COMMAND(power_caps_autotest, test_power_caps);
diff --git a/src/spdk/dpdk/app/test/test_power_kvm_vm.c b/src/spdk/dpdk/app/test/test_power_kvm_vm.c
new file mode 100644
index 000000000..785cd048d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_power_kvm_vm.c
@@ -0,0 +1,302 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+
+#include "test.h"
+
+#ifndef RTE_LIBRTE_POWER
+
+static int
+test_power_kvm_vm(void)
+{
+ printf("Power management library not supported, skipping test\n");
+ return TEST_SKIPPED;
+}
+
+#else
+#include <rte_power.h>
+
+#define TEST_POWER_VM_LCORE_ID 0U
+#define TEST_POWER_VM_LCORE_OUT_OF_BOUNDS (RTE_MAX_LCORE+1)
+#define TEST_POWER_VM_LCORE_INVALID 1U
+
+static int
+test_power_kvm_vm(void)
+{
+ int ret;
+ enum power_management_env env;
+
+ ret = rte_power_set_env(PM_ENV_KVM_VM);
+ if (ret != 0) {
+ printf("Failed on setting environment to PM_ENV_KVM_VM\n");
+ return -1;
+ }
+
+ /* Test environment configuration */
+ env = rte_power_get_env();
+ if (env != PM_ENV_KVM_VM) {
+ printf("Unexpectedly got a Power Management environment other than "
+ "KVM VM\n");
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /* verify that function pointers are not NULL */
+ if (rte_power_freqs == NULL) {
+ printf("rte_power_freqs should not be NULL, environment has not been "
+ "initialised\n");
+ return -1;
+ }
+ if (rte_power_get_freq == NULL) {
+ printf("rte_power_get_freq should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ if (rte_power_set_freq == NULL) {
+ printf("rte_power_set_freq should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ if (rte_power_freq_up == NULL) {
+ printf("rte_power_freq_up should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ if (rte_power_freq_down == NULL) {
+ printf("rte_power_freq_down should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ if (rte_power_freq_max == NULL) {
+ printf("rte_power_freq_max should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ if (rte_power_freq_min == NULL) {
+ printf("rte_power_freq_min should not be NULL, environment has not "
+ "been initialised\n");
+ return -1;
+ }
+ /* Test initialisation of an out of bounds lcore */
+ ret = rte_power_init(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ if (ret != -1) {
+ printf("rte_power_init unexpectedly succeeded on an invalid lcore %u\n",
+ TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ rte_power_unset_env();
+ return -1;
+ }
+
+ /* Test initialisation of a valid lcore */
+ ret = rte_power_init(TEST_POWER_VM_LCORE_ID);
+ if (ret < 0) {
+ printf("Cannot initialise power management for lcore %u, this "
+ "may occur if environment is not configured "
+ "correctly(KVM VM) or operating in another valid "
+ "Power management environment\n",
+ TEST_POWER_VM_LCORE_ID);
+ rte_power_unset_env();
+ return TEST_SKIPPED;
+ }
+
+ /* Test initialisation of previously initialised lcore */
+ ret = rte_power_init(TEST_POWER_VM_LCORE_ID);
+ if (ret == 0) {
+ printf("rte_power_init unexpectedly succeeded on calling init twice on"
+ " lcore %u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency up of invalid lcore */
+ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ if (ret == 1) {
+ printf("rte_power_freq_up unexpectedly succeeded on invalid lcore %u\n",
+ TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ goto fail_all;
+ }
+
+ /* Test frequency down of invalid lcore */
+ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ if (ret == 1) {
+ printf("rte_power_freq_down unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ goto fail_all;
+ }
+
+ /* Test frequency min of invalid lcore */
+ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ if (ret == 1) {
+ printf("rte_power_freq_min unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ goto fail_all;
+ }
+
+ /* Test frequency max of invalid lcore */
+ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ if (ret == 1) {
+ printf("rte_power_freq_max unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_OUT_OF_BOUNDS);
+ goto fail_all;
+ }
+
+ /* Test frequency up of valid but uninitialised lcore */
+ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_INVALID);
+ if (ret == 1) {
+ printf("rte_power_freq_up unexpectedly succeeded on invalid lcore %u\n",
+ TEST_POWER_VM_LCORE_INVALID);
+ goto fail_all;
+ }
+
+ /* Test frequency down of valid but uninitialised lcore */
+ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_INVALID);
+ if (ret == 1) {
+ printf("rte_power_freq_down unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_INVALID);
+ goto fail_all;
+ }
+
+ /* Test frequency min of valid but uninitialised lcore */
+ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_INVALID);
+ if (ret == 1) {
+ printf("rte_power_freq_min unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_INVALID);
+ goto fail_all;
+ }
+
+ /* Test frequency max of valid but uninitialised lcore */
+ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_INVALID);
+ if (ret == 1) {
+ printf("rte_power_freq_max unexpectedly succeeded on invalid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_INVALID);
+ goto fail_all;
+ }
+
+ /* Test KVM_VM Enable Turbo of valid core */
+ ret = rte_power_freq_enable_turbo(TEST_POWER_VM_LCORE_ID);
+ if (ret == -1) {
+ printf("rte_power_freq_enable_turbo failed on valid lcore"
+ "%u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test KVM_VM Disable Turbo of valid core */
+ ret = rte_power_freq_disable_turbo(TEST_POWER_VM_LCORE_ID);
+ if (ret == -1) {
+ printf("rte_power_freq_disable_turbo failed on valid lcore"
+ "%u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency up of valid lcore */
+ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_ID);
+ if (ret != 1) {
+ printf("rte_power_freq_up unexpectedly failed on valid lcore %u\n",
+ TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency down of valid lcore */
+ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_ID);
+ if (ret != 1) {
+ printf("rte_power_freq_down unexpectedly failed on valid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency min of valid lcore */
+ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_ID);
+ if (ret != 1) {
+ printf("rte_power_freq_min unexpectedly failed on valid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency max of valid lcore */
+ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_ID);
+ if (ret != 1) {
+ printf("rte_power_freq_max unexpectedly failed on valid lcore "
+ "%u\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test unsupported rte_power_freqs */
+ ret = rte_power_freqs(TEST_POWER_VM_LCORE_ID, NULL, 0);
+ if (ret != -ENOTSUP) {
+ printf("rte_power_freqs did not return the expected -ENOTSUP(%d) but "
+ "returned %d\n", -ENOTSUP, ret);
+ goto fail_all;
+ }
+
+ /* Test unsupported rte_power_get_freq */
+ ret = rte_power_get_freq(TEST_POWER_VM_LCORE_ID);
+ if (ret != -ENOTSUP) {
+ printf("rte_power_get_freq did not return the expected -ENOTSUP(%d) but"
+ " returned %d for lcore %u\n",
+ -ENOTSUP, ret, TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test unsupported rte_power_set_freq */
+ ret = rte_power_set_freq(TEST_POWER_VM_LCORE_ID, 0);
+ if (ret != -ENOTSUP) {
+ printf("rte_power_set_freq did not return the expected -ENOTSUP(%d) but"
+ " returned %d for lcore %u\n",
+ -ENOTSUP, ret, TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test removing of an lcore */
+ ret = rte_power_exit(TEST_POWER_VM_LCORE_ID);
+ if (ret != 0) {
+ printf("rte_power_exit unexpectedly failed on valid lcore %u,"
+ "please ensure that the environment has been configured "
+ "correctly\n", TEST_POWER_VM_LCORE_ID);
+ goto fail_all;
+ }
+
+ /* Test frequency up of previously removed lcore */
+ ret = rte_power_freq_up(TEST_POWER_VM_LCORE_ID);
+ if (ret == 0) {
+ printf("rte_power_freq_up unexpectedly succeeded on a removed "
+ "lcore %u\n", TEST_POWER_VM_LCORE_ID);
+ return -1;
+ }
+
+ /* Test frequency down of previously removed lcore */
+ ret = rte_power_freq_down(TEST_POWER_VM_LCORE_ID);
+ if (ret == 0) {
+ printf("rte_power_freq_down unexpectedly succeeded on a removed "
+ "lcore %u\n", TEST_POWER_VM_LCORE_ID);
+ return -1;
+ }
+
+ /* Test frequency min of previously removed lcore */
+ ret = rte_power_freq_min(TEST_POWER_VM_LCORE_ID);
+ if (ret == 0) {
+ printf("rte_power_freq_min unexpectedly succeeded on a removed "
+ "lcore %u\n", TEST_POWER_VM_LCORE_ID);
+ return -1;
+ }
+
+ /* Test frequency max of previously removed lcore */
+ ret = rte_power_freq_max(TEST_POWER_VM_LCORE_ID);
+ if (ret == 0) {
+ printf("rte_power_freq_max unexpectedly succeeded on a removed "
+ "lcore %u\n", TEST_POWER_VM_LCORE_ID);
+ return -1;
+ }
+ rte_power_unset_env();
+ return 0;
+fail_all:
+ rte_power_exit(TEST_POWER_VM_LCORE_ID);
+ rte_power_unset_env();
+ return -1;
+}
+#endif
+
+REGISTER_TEST_COMMAND(power_kvm_vm_autotest, test_power_kvm_vm);
diff --git a/src/spdk/dpdk/app/test/test_prefetch.c b/src/spdk/dpdk/app/test/test_prefetch.c
new file mode 100644
index 000000000..41f219af7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_prefetch.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include <rte_prefetch.h>
+
+#include "test.h"
+
+/*
+ * Prefetch test
+ * =============
+ *
+ * - Just test that the macro can be called and validate the compilation.
+ * The test always return success.
+ */
+
+static int
+test_prefetch(void)
+{
+ int a;
+
+ rte_prefetch0(&a);
+ rte_prefetch1(&a);
+ rte_prefetch2(&a);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(prefetch_autotest, test_prefetch);
diff --git a/src/spdk/dpdk/app/test/test_rand_perf.c b/src/spdk/dpdk/app/test/test_rand_perf.c
new file mode 100644
index 000000000..fe797ebfa
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rand_perf.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Ericsson AB
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+
+#include "test.h"
+
+static volatile uint64_t vsum;
+
+#define ITERATIONS (100000000)
+
+#define BEST_CASE_BOUND (1<<16)
+#define WORST_CASE_BOUND (BEST_CASE_BOUND + 1)
+
+enum rand_type {
+ rand_type_64,
+ rand_type_bounded_best_case,
+ rand_type_bounded_worst_case
+};
+
+static const char *
+rand_type_desc(enum rand_type rand_type)
+{
+ switch (rand_type) {
+ case rand_type_64:
+ return "Full 64-bit [rte_rand()]";
+ case rand_type_bounded_best_case:
+ return "Bounded average best-case [rte_rand_max()]";
+ case rand_type_bounded_worst_case:
+ return "Bounded average worst-case [rte_rand_max()]";
+ default:
+ return NULL;
+ }
+}
+
+static __rte_always_inline void
+test_rand_perf_type(enum rand_type rand_type)
+{
+ uint64_t start;
+ uint32_t i;
+ uint64_t end;
+ uint64_t sum = 0;
+ uint64_t op_latency;
+
+ start = rte_rdtsc();
+
+ for (i = 0; i < ITERATIONS; i++) {
+ switch (rand_type) {
+ case rand_type_64:
+ sum += rte_rand();
+ break;
+ case rand_type_bounded_best_case:
+ sum += rte_rand_max(BEST_CASE_BOUND);
+ break;
+ case rand_type_bounded_worst_case:
+ sum += rte_rand_max(WORST_CASE_BOUND);
+ break;
+ }
+ }
+
+ end = rte_rdtsc();
+
+ /* to avoid an optimizing compiler removing the whole loop */
+ vsum = sum;
+
+ op_latency = (end - start) / ITERATIONS;
+
+ printf("%s: %"PRId64" TSC cycles/op\n", rand_type_desc(rand_type),
+ op_latency);
+}
+
+static int
+test_rand_perf(void)
+{
+ rte_srand(42);
+
+ printf("Pseudo-random number generation latencies:\n");
+
+ test_rand_perf_type(rand_type_64);
+ test_rand_perf_type(rand_type_bounded_best_case);
+ test_rand_perf_type(rand_type_bounded_worst_case);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(rand_perf_autotest, test_rand_perf);
diff --git a/src/spdk/dpdk/app/test/test_rawdev.c b/src/spdk/dpdk/app/test/test_rawdev.c
new file mode 100644
index 000000000..524a9d5f3
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rawdev.c
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 NXP
+ */
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_dev.h>
+#include <rte_rawdev.h>
+#include <rte_bus_vdev.h>
+
+#include "test.h"
+
+static int
+test_rawdev_selftest_impl(const char *pmd, const char *opts)
+{
+ rte_vdev_init(pmd, opts);
+ return rte_rawdev_selftest(rte_rawdev_get_dev_id(pmd));
+}
+
+static int
+test_rawdev_selftest_skeleton(void)
+{
+ return test_rawdev_selftest_impl("rawdev_skeleton", "");
+}
+
+REGISTER_TEST_COMMAND(rawdev_autotest, test_rawdev_selftest_skeleton);
+
+static int
+test_rawdev_selftest_ioat(void)
+{
+ const int count = rte_rawdev_count();
+ int i;
+
+ for (i = 0; i < count; i++) {
+ struct rte_rawdev_info info = { .dev_private = NULL };
+ if (rte_rawdev_info_get(i, &info) == 0 &&
+ strstr(info.driver_name, "ioat") != NULL)
+ return rte_rawdev_selftest(i) == 0 ?
+ TEST_SUCCESS : TEST_FAILED;
+ }
+
+ printf("No IOAT rawdev found, skipping tests\n");
+ return TEST_SKIPPED;
+}
+
+REGISTER_TEST_COMMAND(ioat_rawdev_autotest, test_rawdev_selftest_ioat);
diff --git a/src/spdk/dpdk/app/test/test_rcu_qsbr.c b/src/spdk/dpdk/app/test/test_rcu_qsbr.c
new file mode 100644
index 000000000..0a9e5ecd1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rcu_qsbr.c
@@ -0,0 +1,1411 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2019-2020 Arm Limited
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <rte_pause.h>
+#include <rte_rcu_qsbr.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <unistd.h>
+
+#include "test.h"
+
+/* Check condition and return an error if true. */
+#define TEST_RCU_QSBR_RETURN_IF_ERROR(cond, str, ...) \
+do { \
+ if (cond) { \
+ printf("ERROR file %s, line %d: " str "\n", __FILE__, \
+ __LINE__, ##__VA_ARGS__); \
+ return -1; \
+ } \
+} while (0)
+
+/* Check condition and go to label if true. */
+#define TEST_RCU_QSBR_GOTO_IF_ERROR(label, cond, str, ...) \
+do { \
+ if (cond) { \
+ printf("ERROR file %s, line %d: " str "\n", __FILE__, \
+ __LINE__, ##__VA_ARGS__); \
+ goto label; \
+ } \
+} while (0)
+
+/* Make sure that this has the same value as __RTE_QSBR_CNT_INIT */
+#define TEST_RCU_QSBR_CNT_INIT 1
+
+static uint16_t enabled_core_ids[RTE_MAX_LCORE];
+static unsigned int num_cores;
+
+static uint32_t *keys;
+#define TOTAL_ENTRY (1024 * 8)
+#define COUNTER_VALUE 4096
+static uint32_t *hash_data[RTE_MAX_LCORE][TOTAL_ENTRY];
+static uint8_t writer_done;
+static uint8_t cb_failed;
+
+static struct rte_rcu_qsbr *t[RTE_MAX_LCORE];
+static struct rte_hash *h[RTE_MAX_LCORE];
+static char hash_name[RTE_MAX_LCORE][8];
+
+struct test_rcu_thread_info {
+ /* Index in RCU array */
+ int ir;
+ /* Index in hash array */
+ int ih;
+ /* lcore IDs registered on the RCU variable */
+ uint16_t r_core_ids[2];
+};
+static struct test_rcu_thread_info thread_info[RTE_MAX_LCORE/4];
+
+static int
+alloc_rcu(void)
+{
+ int i;
+ size_t sz;
+
+ sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ t[i] = (struct rte_rcu_qsbr *)rte_zmalloc(NULL, sz,
+ RTE_CACHE_LINE_SIZE);
+
+ return 0;
+}
+
+static int
+free_rcu(void)
+{
+ int i;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_free(t[i]);
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_thread_register: Add a reader thread, to the list of threads
+ * reporting their quiescent state on a QS variable.
+ */
+static int
+test_rcu_qsbr_get_memsize(void)
+{
+ size_t sz;
+
+ printf("\nTest rte_rcu_qsbr_thread_register()\n");
+
+ sz = rte_rcu_qsbr_get_memsize(0);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((sz != 1), "Get Memsize for 0 threads");
+
+ sz = rte_rcu_qsbr_get_memsize(128);
+ /* For 128 threads,
+ * for machines with cache line size of 64B - 8384
+ * for machines with cache line size of 128 - 16768
+ */
+ if (RTE_CACHE_LINE_SIZE == 64)
+ TEST_RCU_QSBR_RETURN_IF_ERROR((sz != 8384),
+ "Get Memsize for 128 threads");
+ else if (RTE_CACHE_LINE_SIZE == 128)
+ TEST_RCU_QSBR_RETURN_IF_ERROR((sz != 16768),
+ "Get Memsize for 128 threads");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_init: Initialize a QSBR variable.
+ */
+static int
+test_rcu_qsbr_init(void)
+{
+ int r;
+
+ printf("\nTest rte_rcu_qsbr_init()\n");
+
+ r = rte_rcu_qsbr_init(NULL, RTE_MAX_LCORE);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((r != 1), "NULL variable");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_thread_register: Add a reader thread, to the list of threads
+ * reporting their quiescent state on a QS variable.
+ */
+static int
+test_rcu_qsbr_thread_register(void)
+{
+ int ret;
+
+ printf("\nTest rte_rcu_qsbr_thread_register()\n");
+
+ ret = rte_rcu_qsbr_thread_register(NULL, enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "NULL variable check");
+
+ ret = rte_rcu_qsbr_thread_register(NULL, 100000);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "NULL variable, invalid thread id");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Register valid thread id */
+ ret = rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1), "Valid thread id");
+
+ /* Re-registering should not return error */
+ ret = rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1),
+ "Already registered thread id");
+
+ /* Register valid thread id - max allowed thread id */
+ ret = rte_rcu_qsbr_thread_register(t[0], RTE_MAX_LCORE - 1);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1), "Max thread id");
+
+ ret = rte_rcu_qsbr_thread_register(t[0], 100000);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "NULL variable, invalid thread id");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_thread_unregister: Remove a reader thread, from the list of
+ * threads reporting their quiescent state on a QS variable.
+ */
+static int
+test_rcu_qsbr_thread_unregister(void)
+{
+ unsigned int num_threads[3] = {1, RTE_MAX_LCORE, 1};
+ unsigned int i, j;
+ unsigned int skip_thread_id;
+ uint64_t token;
+ int ret;
+
+ printf("\nTest rte_rcu_qsbr_thread_unregister()\n");
+
+ ret = rte_rcu_qsbr_thread_unregister(NULL, enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "NULL variable check");
+
+ ret = rte_rcu_qsbr_thread_unregister(NULL, 100000);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "NULL variable, invalid thread id");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+
+ ret = rte_rcu_qsbr_thread_unregister(t[0], 100000);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "NULL variable, invalid thread id");
+
+ /* Find first disabled core */
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ if (enabled_core_ids[i] == 0)
+ break;
+ }
+ /* Test with disabled lcore */
+ ret = rte_rcu_qsbr_thread_unregister(t[0], i);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1),
+ "disabled thread id");
+ /* Unregister already unregistered core */
+ ret = rte_rcu_qsbr_thread_unregister(t[0], i);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1),
+ "Already unregistered core");
+
+ /* Test with enabled lcore */
+ ret = rte_rcu_qsbr_thread_unregister(t[0], enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1),
+ "enabled thread id");
+ /* Unregister already unregistered core */
+ ret = rte_rcu_qsbr_thread_unregister(t[0], enabled_core_ids[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1),
+ "Already unregistered core");
+
+ /*
+ * Test with different thread_ids:
+ * 1 - thread_id = 0
+ * 2 - All possible thread_ids, from 0 to RTE_MAX_LCORE
+ * 3 - thread_id = RTE_MAX_LCORE - 1
+ */
+ for (j = 0; j < 3; j++) {
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ for (i = 0; i < num_threads[j]; i++)
+ rte_rcu_qsbr_thread_register(t[0],
+ (j == 2) ? (RTE_MAX_LCORE - 1) : i);
+
+ token = rte_rcu_qsbr_start(t[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR(
+ (token != (TEST_RCU_QSBR_CNT_INIT + 1)), "QSBR Start");
+ skip_thread_id = rte_rand() % RTE_MAX_LCORE;
+ /* Update quiescent state counter */
+ for (i = 0; i < num_threads[j]; i++) {
+ /* Skip one update */
+ if ((j == 1) && (i == skip_thread_id))
+ continue;
+ rte_rcu_qsbr_quiescent(t[0],
+ (j == 2) ? (RTE_MAX_LCORE - 1) : i);
+ }
+
+ if (j == 1) {
+ /* Validate the updates */
+ ret = rte_rcu_qsbr_check(t[0], token, false);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "Non-blocking QSBR check");
+ /* Update the previously skipped thread */
+ rte_rcu_qsbr_quiescent(t[0], skip_thread_id);
+ }
+
+ /* Validate the updates */
+ ret = rte_rcu_qsbr_check(t[0], token, false);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "Non-blocking QSBR check");
+
+ for (i = 0; i < num_threads[j]; i++)
+ rte_rcu_qsbr_thread_unregister(t[0],
+ (j == 2) ? (RTE_MAX_LCORE - 1) : i);
+
+ /* Check with no thread registered */
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0),
+ "Blocking QSBR check");
+ }
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_start: Ask the worker threads to report the quiescent state
+ * status.
+ */
+static int
+test_rcu_qsbr_start(void)
+{
+ uint64_t token;
+ int i;
+
+ printf("\nTest rte_rcu_qsbr_start()\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ for (i = 0; i < 3; i++)
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
+
+ token = rte_rcu_qsbr_start(t[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR(
+ (token != (TEST_RCU_QSBR_CNT_INIT + 1)), "QSBR Start");
+ return 0;
+}
+
+static int
+test_rcu_qsbr_check_reader(void *arg)
+{
+ struct rte_rcu_qsbr *temp;
+ uint8_t read_type = (uint8_t)((uintptr_t)arg);
+
+ temp = t[read_type];
+
+ /* Update quiescent state counter */
+ rte_rcu_qsbr_quiescent(temp, enabled_core_ids[0]);
+ rte_rcu_qsbr_quiescent(temp, enabled_core_ids[1]);
+ rte_rcu_qsbr_thread_unregister(temp, enabled_core_ids[2]);
+ rte_rcu_qsbr_quiescent(temp, enabled_core_ids[3]);
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_check: Checks if all the worker threads have entered the queis-
+ * cent state 'n' number of times. 'n' is provided in rte_rcu_qsbr_start API.
+ */
+static int
+test_rcu_qsbr_check(void)
+{
+ int i, ret;
+ uint64_t token;
+
+ printf("\nTest rte_rcu_qsbr_check()\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ token = rte_rcu_qsbr_start(t[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR(
+ (token != (TEST_RCU_QSBR_CNT_INIT + 1)), "QSBR Start");
+
+
+ ret = rte_rcu_qsbr_check(t[0], 0, false);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Token = 0");
+
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Blocking QSBR check");
+
+ for (i = 0; i < 3; i++)
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
+
+ ret = rte_rcu_qsbr_check(t[0], token, false);
+ /* Threads are offline, hence this should pass */
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Non-blocking QSBR check");
+
+ token = rte_rcu_qsbr_start(t[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR(
+ (token != (TEST_RCU_QSBR_CNT_INIT + 2)), "QSBR Start");
+
+ ret = rte_rcu_qsbr_check(t[0], token, false);
+ /* Threads are offline, hence this should pass */
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Non-blocking QSBR check");
+
+ for (i = 0; i < 3; i++)
+ rte_rcu_qsbr_thread_unregister(t[0], enabled_core_ids[i]);
+
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Blocking QSBR check");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ for (i = 0; i < 4; i++)
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
+
+ token = rte_rcu_qsbr_start(t[0]);
+ TEST_RCU_QSBR_RETURN_IF_ERROR(
+ (token != (TEST_RCU_QSBR_CNT_INIT + 1)), "QSBR Start");
+
+ rte_eal_remote_launch(test_rcu_qsbr_check_reader, NULL,
+ enabled_core_ids[0]);
+
+ rte_eal_mp_wait_lcore();
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 1), "Blocking QSBR check");
+
+ return 0;
+}
+
+static int
+test_rcu_qsbr_synchronize_reader(void *arg)
+{
+ uint32_t lcore_id = rte_lcore_id();
+ (void)arg;
+
+ /* Register and become online */
+ rte_rcu_qsbr_thread_register(t[0], lcore_id);
+ rte_rcu_qsbr_thread_online(t[0], lcore_id);
+
+ while (!writer_done)
+ rte_rcu_qsbr_quiescent(t[0], lcore_id);
+
+ rte_rcu_qsbr_thread_offline(t[0], lcore_id);
+ rte_rcu_qsbr_thread_unregister(t[0], lcore_id);
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_synchronize: Wait till all the reader threads have entered
+ * the queiscent state.
+ */
+static int
+test_rcu_qsbr_synchronize(void)
+{
+ unsigned int i;
+
+ printf("\nTest rte_rcu_qsbr_synchronize()\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Test if the API returns when there are no threads reporting
+ * QS on the variable.
+ */
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+
+ /* Test if the API returns when there are threads registered
+ * but not online.
+ */
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_thread_register(t[0], i);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+
+ /* Test if the API returns when the caller is also
+ * reporting the QS status.
+ */
+ rte_rcu_qsbr_thread_online(t[0], 0);
+ rte_rcu_qsbr_synchronize(t[0], 0);
+ rte_rcu_qsbr_thread_offline(t[0], 0);
+
+ /* Check the other boundary */
+ rte_rcu_qsbr_thread_online(t[0], RTE_MAX_LCORE - 1);
+ rte_rcu_qsbr_synchronize(t[0], RTE_MAX_LCORE - 1);
+ rte_rcu_qsbr_thread_offline(t[0], RTE_MAX_LCORE - 1);
+
+ /* Test if the API returns after unregisterng all the threads */
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_thread_unregister(t[0], i);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+
+ /* Test if the API returns with the live threads */
+ writer_done = 0;
+ for (i = 0; i < num_cores; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_synchronize_reader,
+ NULL, enabled_core_ids[i]);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+ rte_rcu_qsbr_synchronize(t[0], RTE_QSBR_THRID_INVALID);
+
+ writer_done = 1;
+ rte_eal_mp_wait_lcore();
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_thread_online: Add a registered reader thread, to
+ * the list of threads reporting their quiescent state on a QS variable.
+ */
+static int
+test_rcu_qsbr_thread_online(void)
+{
+ int i, ret;
+ uint64_t token;
+
+ printf("Test rte_rcu_qsbr_thread_online()\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Register 2 threads to validate that only the
+ * online thread is waited upon.
+ */
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[1]);
+
+ /* Use qsbr_start to verify that the thread_online API
+ * succeeded.
+ */
+ token = rte_rcu_qsbr_start(t[0]);
+
+ /* Make the thread online */
+ rte_rcu_qsbr_thread_online(t[0], enabled_core_ids[0]);
+
+ /* Check if the thread is online */
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread online");
+
+ /* Check if the online thread, can report QS */
+ token = rte_rcu_qsbr_start(t[0]);
+ rte_rcu_qsbr_quiescent(t[0], enabled_core_ids[0]);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread update");
+
+ /* Make all the threads online */
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ token = rte_rcu_qsbr_start(t[0]);
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ rte_rcu_qsbr_thread_register(t[0], i);
+ rte_rcu_qsbr_thread_online(t[0], i);
+ }
+ /* Check if all the threads are online */
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread online");
+ /* Check if all the online threads can report QS */
+ token = rte_rcu_qsbr_start(t[0]);
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_quiescent(t[0], i);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread update");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_thread_offline: Remove a registered reader thread, from
+ * the list of threads reporting their quiescent state on a QS variable.
+ */
+static int
+test_rcu_qsbr_thread_offline(void)
+{
+ int i, ret;
+ uint64_t token;
+
+ printf("\nTest rte_rcu_qsbr_thread_offline()\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+
+ /* Make the thread offline */
+ rte_rcu_qsbr_thread_offline(t[0], enabled_core_ids[0]);
+
+ /* Use qsbr_start to verify that the thread_offline API
+ * succeeded.
+ */
+ token = rte_rcu_qsbr_start(t[0]);
+ /* Check if the thread is offline */
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread offline");
+
+ /* Bring an offline thread online and check if it can
+ * report QS.
+ */
+ rte_rcu_qsbr_thread_online(t[0], enabled_core_ids[0]);
+ /* Check if the online thread, can report QS */
+ token = rte_rcu_qsbr_start(t[0]);
+ rte_rcu_qsbr_quiescent(t[0], enabled_core_ids[0]);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "offline to online");
+
+ /*
+ * Check a sequence of online/status/offline/status/online/status
+ */
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ token = rte_rcu_qsbr_start(t[0]);
+ /* Make the threads online */
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ rte_rcu_qsbr_thread_register(t[0], i);
+ rte_rcu_qsbr_thread_online(t[0], i);
+ }
+
+ /* Check if all the threads are online */
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "thread online");
+
+ /* Check if all the online threads can report QS */
+ token = rte_rcu_qsbr_start(t[0]);
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_quiescent(t[0], i);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "report QS");
+
+ /* Make all the threads offline */
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_thread_offline(t[0], i);
+ /* Make sure these threads are not being waited on */
+ token = rte_rcu_qsbr_start(t[0]);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "offline QS");
+
+ /* Make the threads online */
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_thread_online(t[0], i);
+ /* Check if all the online threads can report QS */
+ token = rte_rcu_qsbr_start(t[0]);
+ for (i = 0; i < RTE_MAX_LCORE; i++)
+ rte_rcu_qsbr_quiescent(t[0], i);
+ ret = rte_rcu_qsbr_check(t[0], token, true);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "online again");
+
+ return 0;
+}
+
+static void
+test_rcu_qsbr_free_resource1(void *p, void *e, unsigned int n)
+{
+ if (p != NULL || e != NULL || n != 1) {
+ printf("%s: Test failed\n", __func__);
+ cb_failed = 1;
+ }
+}
+
+static void
+test_rcu_qsbr_free_resource2(void *p, void *e, unsigned int n)
+{
+ if (p != NULL || e == NULL || n != 1) {
+ printf("%s: Test failed\n", __func__);
+ cb_failed = 1;
+ }
+}
+
+/*
+ * rte_rcu_qsbr_dq_create: create a queue used to store the data structure
+ * elements that can be freed later. This queue is referred to as 'defer queue'.
+ */
+static int
+test_rcu_qsbr_dq_create(void)
+{
+ char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
+ struct rte_rcu_qsbr_dq_parameters params;
+ struct rte_rcu_qsbr_dq *dq;
+
+ printf("\nTest rte_rcu_qsbr_dq_create()\n");
+
+ /* Pass invalid parameters */
+ dq = rte_rcu_qsbr_dq_create(NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ memset(&params, 0, sizeof(struct rte_rcu_qsbr_dq_parameters));
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ snprintf(rcu_dq_name, sizeof(rcu_dq_name), "TEST_RCU");
+ params.name = rcu_dq_name;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ params.free_fn = test_rcu_qsbr_free_resource1;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ params.v = t[0];
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ params.size = 1;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ params.esize = 3;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ params.trigger_reclaim_limit = 0;
+ params.max_reclaim_size = 0;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq != NULL), "dq create invalid params");
+
+ /* Pass all valid parameters */
+ params.esize = 16;
+ params.trigger_reclaim_limit = 0;
+ params.max_reclaim_size = params.size;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq == NULL), "dq create valid params");
+ rte_rcu_qsbr_dq_delete(dq);
+
+ params.esize = 16;
+ params.flags = RTE_RCU_QSBR_DQ_MT_UNSAFE;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq == NULL), "dq create valid params");
+ rte_rcu_qsbr_dq_delete(dq);
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_dq_enqueue: enqueue one resource to the defer queue,
+ * to be freed later after at least one grace period is over.
+ */
+static int
+test_rcu_qsbr_dq_enqueue(void)
+{
+ int ret;
+ uint64_t r;
+ char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
+ struct rte_rcu_qsbr_dq_parameters params;
+ struct rte_rcu_qsbr_dq *dq;
+
+ printf("\nTest rte_rcu_qsbr_dq_enqueue()\n");
+
+ /* Create a queue with simple parameters */
+ memset(&params, 0, sizeof(struct rte_rcu_qsbr_dq_parameters));
+ snprintf(rcu_dq_name, sizeof(rcu_dq_name), "TEST_RCU");
+ params.name = rcu_dq_name;
+ params.free_fn = test_rcu_qsbr_free_resource1;
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ params.v = t[0];
+ params.size = 1;
+ params.esize = 16;
+ params.trigger_reclaim_limit = 0;
+ params.max_reclaim_size = params.size;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq == NULL), "dq create valid params");
+
+ /* Pass invalid parameters */
+ ret = rte_rcu_qsbr_dq_enqueue(NULL, NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "dq enqueue invalid params");
+
+ ret = rte_rcu_qsbr_dq_enqueue(dq, NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "dq enqueue invalid params");
+
+ ret = rte_rcu_qsbr_dq_enqueue(NULL, &r);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "dq enqueue invalid params");
+
+ ret = rte_rcu_qsbr_dq_delete(dq);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 1), "dq delete valid params");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_dq_reclaim: Reclaim resources from the defer queue.
+ */
+static int
+test_rcu_qsbr_dq_reclaim(void)
+{
+ int ret;
+ char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
+ struct rte_rcu_qsbr_dq_parameters params;
+ struct rte_rcu_qsbr_dq *dq;
+
+ printf("\nTest rte_rcu_qsbr_dq_reclaim()\n");
+
+ /* Pass invalid parameters */
+ ret = rte_rcu_qsbr_dq_reclaim(NULL, 10, NULL, NULL, NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 1), "dq reclaim invalid params");
+
+ /* Pass invalid parameters */
+ memset(&params, 0, sizeof(struct rte_rcu_qsbr_dq_parameters));
+ snprintf(rcu_dq_name, sizeof(rcu_dq_name), "TEST_RCU");
+ params.name = rcu_dq_name;
+ params.free_fn = test_rcu_qsbr_free_resource1;
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ params.v = t[0];
+ params.size = 1;
+ params.esize = 3;
+ params.trigger_reclaim_limit = 0;
+ params.max_reclaim_size = params.size;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ ret = rte_rcu_qsbr_dq_reclaim(dq, 0, NULL, NULL, NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 1), "dq reclaim invalid params");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_dq_delete: Delete a defer queue.
+ */
+static int
+test_rcu_qsbr_dq_delete(void)
+{
+ int ret;
+ char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
+ struct rte_rcu_qsbr_dq_parameters params;
+ struct rte_rcu_qsbr_dq *dq;
+
+ printf("\nTest rte_rcu_qsbr_dq_delete()\n");
+
+ /* Pass invalid parameters */
+ ret = rte_rcu_qsbr_dq_delete(NULL);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 0), "dq delete invalid params");
+
+ memset(&params, 0, sizeof(struct rte_rcu_qsbr_dq_parameters));
+ snprintf(rcu_dq_name, sizeof(rcu_dq_name), "TEST_RCU");
+ params.name = rcu_dq_name;
+ params.free_fn = test_rcu_qsbr_free_resource1;
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ params.v = t[0];
+ params.size = 1;
+ params.esize = 16;
+ params.trigger_reclaim_limit = 0;
+ params.max_reclaim_size = params.size;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq == NULL), "dq create valid params");
+ ret = rte_rcu_qsbr_dq_delete(dq);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 0), "dq delete valid params");
+
+ return 0;
+}
+
+/*
+ * rte_rcu_qsbr_dq_enqueue: enqueue one resource to the defer queue,
+ * to be freed later after at least one grace period is over.
+ */
+static int
+test_rcu_qsbr_dq_functional(int32_t size, int32_t esize, uint32_t flags)
+{
+ int i, j, ret;
+ char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
+ struct rte_rcu_qsbr_dq_parameters params;
+ struct rte_rcu_qsbr_dq *dq;
+ uint64_t *e;
+ uint64_t sc = 200;
+ int max_entries;
+
+ printf("\nTest rte_rcu_qsbr_dq_xxx functional tests()\n");
+ printf("Size = %d, esize = %d, flags = 0x%x\n", size, esize, flags);
+
+ e = (uint64_t *)rte_zmalloc(NULL, esize, RTE_CACHE_LINE_SIZE);
+ if (e == NULL)
+ return 0;
+ cb_failed = 0;
+
+ /* Initialize the RCU variable. No threads are registered */
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Create a queue with simple parameters */
+ memset(&params, 0, sizeof(struct rte_rcu_qsbr_dq_parameters));
+ snprintf(rcu_dq_name, sizeof(rcu_dq_name), "TEST_RCU");
+ params.name = rcu_dq_name;
+ params.flags = flags;
+ params.free_fn = test_rcu_qsbr_free_resource2;
+ params.v = t[0];
+ params.size = size;
+ params.esize = esize;
+ params.trigger_reclaim_limit = size >> 3;
+ params.max_reclaim_size = (size >> 4)?(size >> 4):1;
+ dq = rte_rcu_qsbr_dq_create(&params);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((dq == NULL), "dq create valid params");
+
+ /* Given the size calculate the maximum number of entries
+ * that can be stored on the defer queue (look at the logic used
+ * in capacity calculation of rte_ring).
+ */
+ max_entries = rte_align32pow2(size + 1) - 1;
+ printf("max_entries = %d\n", max_entries);
+
+ /* Enqueue few counters starting with the value 'sc' */
+ /* The queue size will be rounded up to 2. The enqueue API also
+ * reclaims if the queue size is above certain limit. Since, there
+ * are no threads registered, reclamation succeeds. Hence, it should
+ * be possible to enqueue more than the provided queue size.
+ */
+ for (i = 0; i < 10; i++) {
+ ret = rte_rcu_qsbr_dq_enqueue(dq, e);
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (ret != 0),
+ "dq enqueue functional, i = %d", i);
+ for (j = 0; j < esize/8; j++)
+ e[j] = sc++;
+ }
+
+ /* Validate that call back function did not return any error */
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (cb_failed == 1), "CB failed");
+
+ /* Register a thread on the RCU QSBR variable. Reclamation will not
+ * succeed. It should not be possible to enqueue more than the size
+ * number of resources.
+ */
+ rte_rcu_qsbr_thread_register(t[0], 1);
+ rte_rcu_qsbr_thread_online(t[0], 1);
+
+ for (i = 0; i < max_entries; i++) {
+ ret = rte_rcu_qsbr_dq_enqueue(dq, e);
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (ret != 0),
+ "dq enqueue functional, max_entries = %d, i = %d",
+ max_entries, i);
+ for (j = 0; j < esize/8; j++)
+ e[j] = sc++;
+ }
+
+ /* Enqueue fails as queue is full */
+ ret = rte_rcu_qsbr_dq_enqueue(dq, e);
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (ret == 0), "defer queue is not full");
+
+ /* Delete should fail as there are elements in defer queue which
+ * cannot be reclaimed.
+ */
+ ret = rte_rcu_qsbr_dq_delete(dq);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "dq delete valid params");
+
+ /* Report quiescent state, enqueue should succeed */
+ rte_rcu_qsbr_quiescent(t[0], 1);
+ for (i = 0; i < max_entries; i++) {
+ ret = rte_rcu_qsbr_dq_enqueue(dq, e);
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (ret != 0),
+ "dq enqueue functional");
+ for (j = 0; j < esize/8; j++)
+ e[j] = sc++;
+ }
+
+ /* Validate that call back function did not return any error */
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (cb_failed == 1), "CB failed");
+
+ /* Queue is full */
+ ret = rte_rcu_qsbr_dq_enqueue(dq, e);
+ TEST_RCU_QSBR_GOTO_IF_ERROR(end, (ret == 0), "defer queue is not full");
+
+ /* Report quiescent state, delete should succeed */
+ rte_rcu_qsbr_quiescent(t[0], 1);
+ ret = rte_rcu_qsbr_dq_delete(dq);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 0), "dq delete valid params");
+
+ rte_free(e);
+
+ /* Validate that call back function did not return any error */
+ TEST_RCU_QSBR_RETURN_IF_ERROR((cb_failed == 1), "CB failed");
+
+ return 0;
+
+end:
+ rte_free(e);
+ ret = rte_rcu_qsbr_dq_delete(dq);
+ TEST_RCU_QSBR_RETURN_IF_ERROR((ret != 0), "dq delete valid params");
+ return -1;
+}
+
+/*
+ * rte_rcu_qsbr_dump: Dump status of a single QS variable to a file
+ */
+static int
+test_rcu_qsbr_dump(void)
+{
+ int i;
+
+ printf("\nTest rte_rcu_qsbr_dump()\n");
+
+ /* Negative tests */
+ rte_rcu_qsbr_dump(NULL, t[0]);
+ rte_rcu_qsbr_dump(stdout, NULL);
+ rte_rcu_qsbr_dump(NULL, NULL);
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+ rte_rcu_qsbr_init(t[1], RTE_MAX_LCORE);
+
+ /* QS variable with 0 core mask */
+ rte_rcu_qsbr_dump(stdout, t[0]);
+
+ rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
+
+ for (i = 1; i < 3; i++)
+ rte_rcu_qsbr_thread_register(t[1], enabled_core_ids[i]);
+
+ rte_rcu_qsbr_dump(stdout, t[0]);
+ rte_rcu_qsbr_dump(stdout, t[1]);
+ printf("\n");
+ return 0;
+}
+
+static int
+test_rcu_qsbr_reader(void *arg)
+{
+ struct rte_rcu_qsbr *temp;
+ struct rte_hash *hash = NULL;
+ int i;
+ uint32_t lcore_id = rte_lcore_id();
+ struct test_rcu_thread_info *ti;
+ uint32_t *pdata;
+
+ ti = (struct test_rcu_thread_info *)arg;
+ temp = t[ti->ir];
+ hash = h[ti->ih];
+
+ do {
+ rte_rcu_qsbr_thread_register(temp, lcore_id);
+ rte_rcu_qsbr_thread_online(temp, lcore_id);
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ rte_rcu_qsbr_lock(temp, lcore_id);
+ if (rte_hash_lookup_data(hash, keys+i,
+ (void **)&pdata) != -ENOENT) {
+ pdata[lcore_id] = 0;
+ while (pdata[lcore_id] < COUNTER_VALUE)
+ pdata[lcore_id]++;
+ }
+ rte_rcu_qsbr_unlock(temp, lcore_id);
+ }
+ /* Update quiescent state counter */
+ rte_rcu_qsbr_quiescent(temp, lcore_id);
+ rte_rcu_qsbr_thread_offline(temp, lcore_id);
+ rte_rcu_qsbr_thread_unregister(temp, lcore_id);
+ } while (!writer_done);
+
+ return 0;
+}
+
+static int
+test_rcu_qsbr_writer(void *arg)
+{
+ uint64_t token;
+ int32_t i, pos, del;
+ uint32_t c;
+ struct rte_rcu_qsbr *temp;
+ struct rte_hash *hash = NULL;
+ struct test_rcu_thread_info *ti;
+
+ ti = (struct test_rcu_thread_info *)arg;
+ temp = t[ti->ir];
+ hash = h[ti->ih];
+
+ /* Delete element from the shared data structure */
+ del = rte_lcore_id() % TOTAL_ENTRY;
+ pos = rte_hash_del_key(hash, keys + del);
+ if (pos < 0) {
+ printf("Delete key failed #%d\n", keys[del]);
+ return -1;
+ }
+ /* Start the quiescent state query process */
+ token = rte_rcu_qsbr_start(temp);
+ /* Check the quiescent state status */
+ rte_rcu_qsbr_check(temp, token, true);
+ for (i = 0; i < 2; i++) {
+ c = hash_data[ti->ih][del][ti->r_core_ids[i]];
+ if (c != COUNTER_VALUE && c != 0) {
+ printf("Reader lcore id %u did not complete = %u\t",
+ rte_lcore_id(), c);
+ return -1;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(hash, pos) < 0) {
+ printf("Failed to free the key #%d\n", keys[del]);
+ return -1;
+ }
+ rte_free(hash_data[ti->ih][del]);
+ hash_data[ti->ih][del] = NULL;
+
+ return 0;
+}
+
+static struct rte_hash *
+init_hash(int hash_id)
+{
+ int i;
+ struct rte_hash *h = NULL;
+
+ sprintf(hash_name[hash_id], "hash%d", hash_id);
+ struct rte_hash_parameters hash_params = {
+ .entries = TOTAL_ENTRY,
+ .key_len = sizeof(uint32_t),
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ .hash_func = rte_hash_crc,
+ .extra_flag =
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF,
+ .name = hash_name[hash_id],
+ };
+
+ h = rte_hash_create(&hash_params);
+ if (h == NULL) {
+ printf("Hash create Failed\n");
+ return NULL;
+ }
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ hash_data[hash_id][i] =
+ rte_zmalloc(NULL, sizeof(uint32_t) * RTE_MAX_LCORE, 0);
+ if (hash_data[hash_id][i] == NULL) {
+ printf("No memory\n");
+ return NULL;
+ }
+ }
+ keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
+ if (keys == NULL) {
+ printf("No memory\n");
+ return NULL;
+ }
+
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ keys[i] = i;
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ if (rte_hash_add_key_data(h, keys + i,
+ (void *)((uintptr_t)hash_data[hash_id][i]))
+ < 0) {
+ printf("Hash key add Failed #%d\n", i);
+ return NULL;
+ }
+ }
+ return h;
+}
+
+/*
+ * Functional test:
+ * Single writer, Single QS variable, simultaneous QSBR Queries
+ */
+static int
+test_rcu_qsbr_sw_sv_3qs(void)
+{
+ uint64_t token[3];
+ uint32_t c;
+ int i;
+ int32_t pos[3];
+
+ writer_done = 0;
+
+ printf("Test: 1 writer, 1 QSBR variable, simultaneous QSBR queries\n");
+
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Shared data structure created */
+ h[0] = init_hash(0);
+ if (h[0] == NULL) {
+ printf("Hash init failed\n");
+ goto error;
+ }
+
+ /* No need to fill the registered core IDs as the writer
+ * thread is not launched.
+ */
+ thread_info[0].ir = 0;
+ thread_info[0].ih = 0;
+
+ /* Reader threads are launched */
+ for (i = 0; i < 4; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_reader, &thread_info[0],
+ enabled_core_ids[i]);
+
+ /* Delete element from the shared data structure */
+ pos[0] = rte_hash_del_key(h[0], keys + 0);
+ if (pos[0] < 0) {
+ printf("Delete key failed #%d\n", keys[0]);
+ goto error;
+ }
+ /* Start the quiescent state query process */
+ token[0] = rte_rcu_qsbr_start(t[0]);
+
+ /* Delete element from the shared data structure */
+ pos[1] = rte_hash_del_key(h[0], keys + 3);
+ if (pos[1] < 0) {
+ printf("Delete key failed #%d\n", keys[3]);
+ goto error;
+ }
+ /* Start the quiescent state query process */
+ token[1] = rte_rcu_qsbr_start(t[0]);
+
+ /* Delete element from the shared data structure */
+ pos[2] = rte_hash_del_key(h[0], keys + 6);
+ if (pos[2] < 0) {
+ printf("Delete key failed #%d\n", keys[6]);
+ goto error;
+ }
+ /* Start the quiescent state query process */
+ token[2] = rte_rcu_qsbr_start(t[0]);
+
+ /* Check the quiescent state status */
+ rte_rcu_qsbr_check(t[0], token[0], true);
+ for (i = 0; i < 4; i++) {
+ c = hash_data[0][0][enabled_core_ids[i]];
+ if (c != COUNTER_VALUE && c != 0) {
+ printf("Reader lcore %d did not complete #0 = %d\n",
+ enabled_core_ids[i], c);
+ goto error;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(h[0], pos[0]) < 0) {
+ printf("Failed to free the key #%d\n", keys[0]);
+ goto error;
+ }
+ rte_free(hash_data[0][0]);
+ hash_data[0][0] = NULL;
+
+ /* Check the quiescent state status */
+ rte_rcu_qsbr_check(t[0], token[1], true);
+ for (i = 0; i < 4; i++) {
+ c = hash_data[0][3][enabled_core_ids[i]];
+ if (c != COUNTER_VALUE && c != 0) {
+ printf("Reader lcore %d did not complete #3 = %d\n",
+ enabled_core_ids[i], c);
+ goto error;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(h[0], pos[1]) < 0) {
+ printf("Failed to free the key #%d\n", keys[3]);
+ goto error;
+ }
+ rte_free(hash_data[0][3]);
+ hash_data[0][3] = NULL;
+
+ /* Check the quiescent state status */
+ rte_rcu_qsbr_check(t[0], token[2], true);
+ for (i = 0; i < 4; i++) {
+ c = hash_data[0][6][enabled_core_ids[i]];
+ if (c != COUNTER_VALUE && c != 0) {
+ printf("Reader lcore %d did not complete #6 = %d\n",
+ enabled_core_ids[i], c);
+ goto error;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(h[0], pos[2]) < 0) {
+ printf("Failed to free the key #%d\n", keys[6]);
+ goto error;
+ }
+ rte_free(hash_data[0][6]);
+ hash_data[0][6] = NULL;
+
+ writer_done = 1;
+
+ /* Wait and check return value from reader threads */
+ for (i = 0; i < 4; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto error;
+ rte_hash_free(h[0]);
+ rte_free(keys);
+
+ return 0;
+
+error:
+ writer_done = 1;
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ rte_hash_free(h[0]);
+ rte_free(keys);
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ rte_free(hash_data[0][i]);
+
+ return -1;
+}
+
+/*
+ * Multi writer, Multiple QS variable, simultaneous QSBR queries
+ */
+static int
+test_rcu_qsbr_mw_mv_mqs(void)
+{
+ unsigned int i, j;
+ unsigned int test_cores;
+
+ writer_done = 0;
+ test_cores = num_cores / 4;
+ test_cores = test_cores * 4;
+
+ printf("Test: %d writers, %d QSBR variable, simultaneous QSBR queries\n",
+ test_cores / 2, test_cores / 4);
+
+ for (i = 0; i < test_cores / 4; i++) {
+ j = i * 4;
+ rte_rcu_qsbr_init(t[i], RTE_MAX_LCORE);
+ h[i] = init_hash(i);
+ if (h[i] == NULL) {
+ printf("Hash init failed\n");
+ goto error;
+ }
+ thread_info[i].ir = i;
+ thread_info[i].ih = i;
+ thread_info[i].r_core_ids[0] = enabled_core_ids[j];
+ thread_info[i].r_core_ids[1] = enabled_core_ids[j + 1];
+
+ /* Reader threads are launched */
+ rte_eal_remote_launch(test_rcu_qsbr_reader,
+ (void *)&thread_info[i],
+ enabled_core_ids[j]);
+ rte_eal_remote_launch(test_rcu_qsbr_reader,
+ (void *)&thread_info[i],
+ enabled_core_ids[j + 1]);
+
+ /* Writer threads are launched */
+ rte_eal_remote_launch(test_rcu_qsbr_writer,
+ (void *)&thread_info[i],
+ enabled_core_ids[j + 2]);
+ rte_eal_remote_launch(test_rcu_qsbr_writer,
+ (void *)&thread_info[i],
+ enabled_core_ids[j + 3]);
+ }
+
+ /* Wait and check return value from writer threads */
+ for (i = 0; i < test_cores / 4; i++) {
+ j = i * 4;
+ if (rte_eal_wait_lcore(enabled_core_ids[j + 2]) < 0)
+ goto error;
+
+ if (rte_eal_wait_lcore(enabled_core_ids[j + 3]) < 0)
+ goto error;
+ }
+ writer_done = 1;
+
+ /* Wait and check return value from reader threads */
+ for (i = 0; i < test_cores / 4; i++) {
+ j = i * 4;
+ if (rte_eal_wait_lcore(enabled_core_ids[j]) < 0)
+ goto error;
+
+ if (rte_eal_wait_lcore(enabled_core_ids[j + 1]) < 0)
+ goto error;
+ }
+
+ for (i = 0; i < test_cores / 4; i++)
+ rte_hash_free(h[i]);
+
+ rte_free(keys);
+
+ return 0;
+
+error:
+ writer_done = 1;
+ /* Wait until all readers and writers have exited */
+ rte_eal_mp_wait_lcore();
+
+ for (i = 0; i < test_cores / 4; i++)
+ rte_hash_free(h[i]);
+ rte_free(keys);
+ for (j = 0; j < test_cores / 4; j++)
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ rte_free(hash_data[j][i]);
+
+ return -1;
+}
+
+static int
+test_rcu_qsbr_main(void)
+{
+ uint16_t core_id;
+
+ if (rte_lcore_count() < 5) {
+ printf("Not enough cores for rcu_qsbr_autotest, expecting at least 5\n");
+ return TEST_SKIPPED;
+ }
+
+ num_cores = 0;
+ RTE_LCORE_FOREACH_SLAVE(core_id) {
+ enabled_core_ids[num_cores] = core_id;
+ num_cores++;
+ }
+
+ /* Error-checking test cases */
+ if (test_rcu_qsbr_get_memsize() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_init() < 0)
+ goto test_fail;
+
+ alloc_rcu();
+
+ if (test_rcu_qsbr_thread_register() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_thread_unregister() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_start() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_check() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_synchronize() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dump() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_thread_online() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_thread_offline() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_create() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_reclaim() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_delete() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_enqueue() < 0)
+ goto test_fail;
+
+ printf("\nFunctional tests\n");
+
+ if (test_rcu_qsbr_sw_sv_3qs() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_mw_mv_mqs() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_functional(1, 8, 0) < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_functional(2, 8, RTE_RCU_QSBR_DQ_MT_UNSAFE) < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_functional(303, 16, 0) < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_dq_functional(7, 128, RTE_RCU_QSBR_DQ_MT_UNSAFE) < 0)
+ goto test_fail;
+
+ free_rcu();
+
+ printf("\n");
+ return 0;
+
+test_fail:
+ free_rcu();
+
+ return -1;
+}
+
+REGISTER_TEST_COMMAND(rcu_qsbr_autotest, test_rcu_qsbr_main);
diff --git a/src/spdk/dpdk/app/test/test_rcu_qsbr_perf.c b/src/spdk/dpdk/app/test/test_rcu_qsbr_perf.c
new file mode 100644
index 000000000..d35a6d089
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rcu_qsbr_perf.c
@@ -0,0 +1,690 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2018 Arm Limited
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <rte_pause.h>
+#include <rte_rcu_qsbr.h>
+#include <rte_hash.h>
+#include <rte_hash_crc.h>
+#include <rte_malloc.h>
+#include <rte_cycles.h>
+#include <unistd.h>
+
+#include "test.h"
+
+/* Check condition and return an error if true. */
+static uint16_t enabled_core_ids[RTE_MAX_LCORE];
+static unsigned int num_cores;
+
+static uint32_t *keys;
+#define TOTAL_ENTRY (1024 * 8)
+#define COUNTER_VALUE 4096
+static uint32_t *hash_data[TOTAL_ENTRY];
+static volatile uint8_t writer_done;
+static volatile uint8_t all_registered;
+static volatile uint32_t thr_id;
+
+static struct rte_rcu_qsbr *t[RTE_MAX_LCORE];
+static struct rte_hash *h;
+static char hash_name[8];
+static rte_atomic64_t updates, checks;
+static rte_atomic64_t update_cycles, check_cycles;
+
+/* Scale down results to 1000 operations to support lower
+ * granularity clocks.
+ */
+#define RCU_SCALE_DOWN 1000
+
+/* Simple way to allocate thread ids in 0 to RTE_MAX_LCORE space */
+static inline uint32_t
+alloc_thread_id(void)
+{
+ uint32_t tmp_thr_id;
+
+ tmp_thr_id = __atomic_fetch_add(&thr_id, 1, __ATOMIC_RELAXED);
+ if (tmp_thr_id >= RTE_MAX_LCORE)
+ printf("Invalid thread id %u\n", tmp_thr_id);
+
+ return tmp_thr_id;
+}
+
+static int
+test_rcu_qsbr_reader_perf(void *arg)
+{
+ bool writer_present = (bool)arg;
+ uint32_t thread_id = alloc_thread_id();
+ uint64_t loop_cnt = 0;
+ uint64_t begin, cycles;
+
+ /* Register for report QS */
+ rte_rcu_qsbr_thread_register(t[0], thread_id);
+ /* Make the thread online */
+ rte_rcu_qsbr_thread_online(t[0], thread_id);
+
+ begin = rte_rdtsc_precise();
+
+ if (writer_present) {
+ while (!writer_done) {
+ /* Update quiescent state counter */
+ rte_rcu_qsbr_quiescent(t[0], thread_id);
+ loop_cnt++;
+ }
+ } else {
+ while (loop_cnt < 100000000) {
+ /* Update quiescent state counter */
+ rte_rcu_qsbr_quiescent(t[0], thread_id);
+ loop_cnt++;
+ }
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&update_cycles, cycles);
+ rte_atomic64_add(&updates, loop_cnt);
+
+ /* Make the thread offline */
+ rte_rcu_qsbr_thread_offline(t[0], thread_id);
+ /* Unregister before exiting to avoid writer from waiting */
+ rte_rcu_qsbr_thread_unregister(t[0], thread_id);
+
+ return 0;
+}
+
+static int
+test_rcu_qsbr_writer_perf(void *arg)
+{
+ bool wait = (bool)arg;
+ uint64_t token = 0;
+ uint64_t loop_cnt = 0;
+ uint64_t begin, cycles;
+
+ begin = rte_rdtsc_precise();
+
+ do {
+ /* Start the quiescent state query process */
+ if (wait)
+ token = rte_rcu_qsbr_start(t[0]);
+
+ /* Check quiescent state status */
+ rte_rcu_qsbr_check(t[0], token, wait);
+ loop_cnt++;
+ } while (loop_cnt < 20000000);
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&check_cycles, cycles);
+ rte_atomic64_add(&checks, loop_cnt);
+ return 0;
+}
+
+/*
+ * Perf test: Reader/writer
+ * Single writer, Multiple Readers, Single QS var, Non-Blocking rcu_qsbr_check
+ */
+static int
+test_rcu_qsbr_perf(void)
+{
+ size_t sz;
+ unsigned int i, tmp_num_cores;
+
+ writer_done = 0;
+
+ rte_atomic64_clear(&updates);
+ rte_atomic64_clear(&update_cycles);
+ rte_atomic64_clear(&checks);
+ rte_atomic64_clear(&check_cycles);
+
+ printf("\nPerf Test: %d Readers/1 Writer('wait' in qsbr_check == true)\n",
+ num_cores - 1);
+
+ __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST);
+
+ if (all_registered == 1)
+ tmp_num_cores = num_cores - 1;
+ else
+ tmp_num_cores = RTE_MAX_LCORE;
+
+ sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
+ t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
+ RTE_CACHE_LINE_SIZE);
+ /* QS variable is initialized */
+ rte_rcu_qsbr_init(t[0], tmp_num_cores);
+
+ /* Reader threads are launched */
+ for (i = 0; i < num_cores - 1; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_reader_perf, (void *)1,
+ enabled_core_ids[i]);
+
+ /* Writer thread is launched */
+ rte_eal_remote_launch(test_rcu_qsbr_writer_perf,
+ (void *)1, enabled_core_ids[i]);
+
+ /* Wait for the writer thread */
+ rte_eal_wait_lcore(enabled_core_ids[i]);
+ writer_done = 1;
+
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ printf("Total quiescent state updates = %"PRIi64"\n",
+ rte_atomic64_read(&updates));
+ printf("Cycles per %d quiescent state updates: %"PRIi64"\n",
+ RCU_SCALE_DOWN,
+ rte_atomic64_read(&update_cycles) /
+ (rte_atomic64_read(&updates) / RCU_SCALE_DOWN));
+ printf("Total RCU checks = %"PRIi64"\n", rte_atomic64_read(&checks));
+ printf("Cycles per %d checks: %"PRIi64"\n", RCU_SCALE_DOWN,
+ rte_atomic64_read(&check_cycles) /
+ (rte_atomic64_read(&checks) / RCU_SCALE_DOWN));
+
+ rte_free(t[0]);
+
+ return 0;
+}
+
+/*
+ * Perf test: Readers
+ * Single writer, Multiple readers, Single QS variable
+ */
+static int
+test_rcu_qsbr_rperf(void)
+{
+ size_t sz;
+ unsigned int i, tmp_num_cores;
+
+ rte_atomic64_clear(&updates);
+ rte_atomic64_clear(&update_cycles);
+
+ __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST);
+
+ printf("\nPerf Test: %d Readers\n", num_cores);
+
+ if (all_registered == 1)
+ tmp_num_cores = num_cores;
+ else
+ tmp_num_cores = RTE_MAX_LCORE;
+
+ sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
+ t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
+ RTE_CACHE_LINE_SIZE);
+ /* QS variable is initialized */
+ rte_rcu_qsbr_init(t[0], tmp_num_cores);
+
+ /* Reader threads are launched */
+ for (i = 0; i < num_cores; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_reader_perf, NULL,
+ enabled_core_ids[i]);
+
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ printf("Total quiescent state updates = %"PRIi64"\n",
+ rte_atomic64_read(&updates));
+ printf("Cycles per %d quiescent state updates: %"PRIi64"\n",
+ RCU_SCALE_DOWN,
+ rte_atomic64_read(&update_cycles) /
+ (rte_atomic64_read(&updates) / RCU_SCALE_DOWN));
+
+ rte_free(t[0]);
+
+ return 0;
+}
+
+/*
+ * Perf test:
+ * Multiple writer, Single QS variable, Non-blocking rcu_qsbr_check
+ */
+static int
+test_rcu_qsbr_wperf(void)
+{
+ size_t sz;
+ unsigned int i;
+
+ rte_atomic64_clear(&checks);
+ rte_atomic64_clear(&check_cycles);
+
+ __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST);
+
+ printf("\nPerf test: %d Writers ('wait' in qsbr_check == false)\n",
+ num_cores);
+
+ /* Number of readers does not matter for QS variable in this test
+ * case as no reader will be registered.
+ */
+ sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
+ t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
+ RTE_CACHE_LINE_SIZE);
+ /* QS variable is initialized */
+ rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
+
+ /* Writer threads are launched */
+ for (i = 0; i < num_cores; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_writer_perf,
+ (void *)0, enabled_core_ids[i]);
+
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ printf("Total RCU checks = %"PRIi64"\n", rte_atomic64_read(&checks));
+ printf("Cycles per %d checks: %"PRIi64"\n", RCU_SCALE_DOWN,
+ rte_atomic64_read(&check_cycles) /
+ (rte_atomic64_read(&checks) / RCU_SCALE_DOWN));
+
+ rte_free(t[0]);
+
+ return 0;
+}
+
+/*
+ * RCU test cases using rte_hash data structure.
+ */
+static int
+test_rcu_qsbr_hash_reader(void *arg)
+{
+ struct rte_rcu_qsbr *temp;
+ struct rte_hash *hash = NULL;
+ int i;
+ uint64_t loop_cnt = 0;
+ uint64_t begin, cycles;
+ uint32_t thread_id = alloc_thread_id();
+ uint8_t read_type = (uint8_t)((uintptr_t)arg);
+ uint32_t *pdata;
+
+ temp = t[read_type];
+ hash = h;
+
+ rte_rcu_qsbr_thread_register(temp, thread_id);
+
+ begin = rte_rdtsc_precise();
+
+ do {
+ rte_rcu_qsbr_thread_online(temp, thread_id);
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ rte_rcu_qsbr_lock(temp, thread_id);
+ if (rte_hash_lookup_data(hash, keys + i,
+ (void **)&pdata) != -ENOENT) {
+ pdata[thread_id] = 0;
+ while (pdata[thread_id] < COUNTER_VALUE)
+ pdata[thread_id]++;
+ }
+ rte_rcu_qsbr_unlock(temp, thread_id);
+ }
+ /* Update quiescent state counter */
+ rte_rcu_qsbr_quiescent(temp, thread_id);
+ rte_rcu_qsbr_thread_offline(temp, thread_id);
+ loop_cnt++;
+ } while (!writer_done);
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&update_cycles, cycles);
+ rte_atomic64_add(&updates, loop_cnt);
+
+ rte_rcu_qsbr_thread_unregister(temp, thread_id);
+
+ return 0;
+}
+
+static struct rte_hash *init_hash(void)
+{
+ int i;
+ struct rte_hash *hash = NULL;
+
+ snprintf(hash_name, 8, "hash");
+ struct rte_hash_parameters hash_params = {
+ .entries = TOTAL_ENTRY,
+ .key_len = sizeof(uint32_t),
+ .hash_func_init_val = 0,
+ .socket_id = rte_socket_id(),
+ .hash_func = rte_hash_crc,
+ .extra_flag =
+ RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF,
+ .name = hash_name,
+ };
+
+ hash = rte_hash_create(&hash_params);
+ if (hash == NULL) {
+ printf("Hash create Failed\n");
+ return NULL;
+ }
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ hash_data[i] = rte_zmalloc(NULL,
+ sizeof(uint32_t) * RTE_MAX_LCORE, 0);
+ if (hash_data[i] == NULL) {
+ printf("No memory\n");
+ return NULL;
+ }
+ }
+ keys = rte_malloc(NULL, sizeof(uint32_t) * TOTAL_ENTRY, 0);
+ if (keys == NULL) {
+ printf("No memory\n");
+ return NULL;
+ }
+
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ keys[i] = i;
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ if (rte_hash_add_key_data(hash, keys + i,
+ (void *)((uintptr_t)hash_data[i])) < 0) {
+ printf("Hash key add Failed #%d\n", i);
+ return NULL;
+ }
+ }
+ return hash;
+}
+
+/*
+ * Functional test:
+ * Single writer, Single QS variable Single QSBR query, Blocking rcu_qsbr_check
+ */
+static int
+test_rcu_qsbr_sw_sv_1qs(void)
+{
+ uint64_t token, begin, cycles;
+ size_t sz;
+ unsigned int i, j, tmp_num_cores;
+ int32_t pos;
+
+ writer_done = 0;
+
+ rte_atomic64_clear(&updates);
+ rte_atomic64_clear(&update_cycles);
+ rte_atomic64_clear(&checks);
+ rte_atomic64_clear(&check_cycles);
+
+ __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST);
+
+ printf("\nPerf test: 1 writer, %d readers, 1 QSBR variable, 1 QSBR Query, Blocking QSBR Check\n", num_cores);
+
+ if (all_registered == 1)
+ tmp_num_cores = num_cores;
+ else
+ tmp_num_cores = RTE_MAX_LCORE;
+
+ sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
+ t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
+ RTE_CACHE_LINE_SIZE);
+ /* QS variable is initialized */
+ rte_rcu_qsbr_init(t[0], tmp_num_cores);
+
+ /* Shared data structure created */
+ h = init_hash();
+ if (h == NULL) {
+ printf("Hash init failed\n");
+ goto error;
+ }
+
+ /* Reader threads are launched */
+ for (i = 0; i < num_cores; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_hash_reader, NULL,
+ enabled_core_ids[i]);
+
+ begin = rte_rdtsc_precise();
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ /* Delete elements from the shared data structure */
+ pos = rte_hash_del_key(h, keys + i);
+ if (pos < 0) {
+ printf("Delete key failed #%d\n", keys[i]);
+ goto error;
+ }
+ /* Start the quiescent state query process */
+ token = rte_rcu_qsbr_start(t[0]);
+
+ /* Check the quiescent state status */
+ rte_rcu_qsbr_check(t[0], token, true);
+ for (j = 0; j < tmp_num_cores; j++) {
+ if (hash_data[i][j] != COUNTER_VALUE &&
+ hash_data[i][j] != 0) {
+ printf("Reader thread ID %u did not complete #%d = %d\n",
+ j, i, hash_data[i][j]);
+ goto error;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(h, pos) < 0) {
+ printf("Failed to free the key #%d\n", keys[i]);
+ goto error;
+ }
+ rte_free(hash_data[i]);
+ hash_data[i] = NULL;
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&check_cycles, cycles);
+ rte_atomic64_add(&checks, i);
+
+ writer_done = 1;
+
+ /* Wait and check return value from reader threads */
+ for (i = 0; i < num_cores; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto error;
+ rte_hash_free(h);
+ rte_free(keys);
+
+ printf("Following numbers include calls to rte_hash functions\n");
+ printf("Cycles per 1 quiescent state update(online/update/offline): %"PRIi64"\n",
+ rte_atomic64_read(&update_cycles) /
+ rte_atomic64_read(&updates));
+
+ printf("Cycles per 1 check(start, check): %"PRIi64"\n\n",
+ rte_atomic64_read(&check_cycles) /
+ rte_atomic64_read(&checks));
+
+ rte_free(t[0]);
+
+ return 0;
+
+error:
+ writer_done = 1;
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ rte_hash_free(h);
+ rte_free(keys);
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ rte_free(hash_data[i]);
+
+ rte_free(t[0]);
+
+ return -1;
+}
+
+/*
+ * Functional test:
+ * Single writer, Single QS variable, Single QSBR query,
+ * Non-blocking rcu_qsbr_check
+ */
+static int
+test_rcu_qsbr_sw_sv_1qs_non_blocking(void)
+{
+ uint64_t token, begin, cycles;
+ int ret;
+ size_t sz;
+ unsigned int i, j, tmp_num_cores;
+ int32_t pos;
+
+ writer_done = 0;
+
+ printf("Perf test: 1 writer, %d readers, 1 QSBR variable, 1 QSBR Query, Non-Blocking QSBR check\n", num_cores);
+
+ __atomic_store_n(&thr_id, 0, __ATOMIC_SEQ_CST);
+
+ if (all_registered == 1)
+ tmp_num_cores = num_cores;
+ else
+ tmp_num_cores = RTE_MAX_LCORE;
+
+ sz = rte_rcu_qsbr_get_memsize(tmp_num_cores);
+ t[0] = (struct rte_rcu_qsbr *)rte_zmalloc("rcu0", sz,
+ RTE_CACHE_LINE_SIZE);
+ /* QS variable is initialized */
+ rte_rcu_qsbr_init(t[0], tmp_num_cores);
+
+ /* Shared data structure created */
+ h = init_hash();
+ if (h == NULL) {
+ printf("Hash init failed\n");
+ goto error;
+ }
+
+ /* Reader threads are launched */
+ for (i = 0; i < num_cores; i++)
+ rte_eal_remote_launch(test_rcu_qsbr_hash_reader, NULL,
+ enabled_core_ids[i]);
+
+ begin = rte_rdtsc_precise();
+
+ for (i = 0; i < TOTAL_ENTRY; i++) {
+ /* Delete elements from the shared data structure */
+ pos = rte_hash_del_key(h, keys + i);
+ if (pos < 0) {
+ printf("Delete key failed #%d\n", keys[i]);
+ goto error;
+ }
+ /* Start the quiescent state query process */
+ token = rte_rcu_qsbr_start(t[0]);
+
+ /* Check the quiescent state status */
+ do {
+ ret = rte_rcu_qsbr_check(t[0], token, false);
+ } while (ret == 0);
+ for (j = 0; j < tmp_num_cores; j++) {
+ if (hash_data[i][j] != COUNTER_VALUE &&
+ hash_data[i][j] != 0) {
+ printf("Reader thread ID %u did not complete #%d = %d\n",
+ j, i, hash_data[i][j]);
+ goto error;
+ }
+ }
+
+ if (rte_hash_free_key_with_position(h, pos) < 0) {
+ printf("Failed to free the key #%d\n", keys[i]);
+ goto error;
+ }
+ rte_free(hash_data[i]);
+ hash_data[i] = NULL;
+ }
+
+ cycles = rte_rdtsc_precise() - begin;
+ rte_atomic64_add(&check_cycles, cycles);
+ rte_atomic64_add(&checks, i);
+
+ writer_done = 1;
+ /* Wait and check return value from reader threads */
+ for (i = 0; i < num_cores; i++)
+ if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
+ goto error;
+ rte_hash_free(h);
+ rte_free(keys);
+
+ printf("Following numbers include calls to rte_hash functions\n");
+ printf("Cycles per 1 quiescent state update(online/update/offline): %"PRIi64"\n",
+ rte_atomic64_read(&update_cycles) /
+ rte_atomic64_read(&updates));
+
+ printf("Cycles per 1 check(start, check): %"PRIi64"\n\n",
+ rte_atomic64_read(&check_cycles) /
+ rte_atomic64_read(&checks));
+
+ rte_free(t[0]);
+
+ return 0;
+
+error:
+ writer_done = 1;
+ /* Wait until all readers have exited */
+ rte_eal_mp_wait_lcore();
+
+ rte_hash_free(h);
+ rte_free(keys);
+ for (i = 0; i < TOTAL_ENTRY; i++)
+ rte_free(hash_data[i]);
+
+ rte_free(t[0]);
+
+ return -1;
+}
+
+static int
+test_rcu_qsbr_main(void)
+{
+ uint16_t core_id;
+
+ if (rte_lcore_count() < 3) {
+ printf("Not enough cores for rcu_qsbr_perf_autotest, expecting at least 3\n");
+ return TEST_SKIPPED;
+ }
+
+ rte_atomic64_init(&updates);
+ rte_atomic64_init(&update_cycles);
+ rte_atomic64_init(&checks);
+ rte_atomic64_init(&check_cycles);
+
+ num_cores = 0;
+ RTE_LCORE_FOREACH_SLAVE(core_id) {
+ enabled_core_ids[num_cores] = core_id;
+ num_cores++;
+ }
+
+ printf("Number of cores provided = %d\n", num_cores);
+ printf("Perf test with all reader threads registered\n");
+ printf("--------------------------------------------\n");
+ all_registered = 1;
+
+ if (test_rcu_qsbr_perf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_rperf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_wperf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_sw_sv_1qs() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_sw_sv_1qs_non_blocking() < 0)
+ goto test_fail;
+
+ /* Make sure the actual number of cores provided is less than
+ * RTE_MAX_LCORE. This will allow for some threads not
+ * to be registered on the QS variable.
+ */
+ if (num_cores >= RTE_MAX_LCORE) {
+ printf("Test failed! number of cores provided should be less than %d\n",
+ RTE_MAX_LCORE);
+ goto test_fail;
+ }
+
+ printf("Perf test with some of reader threads registered\n");
+ printf("------------------------------------------------\n");
+ all_registered = 0;
+
+ if (test_rcu_qsbr_perf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_rperf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_wperf() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_sw_sv_1qs() < 0)
+ goto test_fail;
+
+ if (test_rcu_qsbr_sw_sv_1qs_non_blocking() < 0)
+ goto test_fail;
+
+ printf("\n");
+
+ return 0;
+
+test_fail:
+ return -1;
+}
+
+REGISTER_TEST_COMMAND(rcu_qsbr_perf_autotest, test_rcu_qsbr_main);
diff --git a/src/spdk/dpdk/app/test/test_reciprocal_division.c b/src/spdk/dpdk/app/test/test_reciprocal_division.c
new file mode 100644
index 000000000..8ea9b1d24
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_reciprocal_division.c
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_reciprocal.h>
+
+#define MAX_ITERATIONS (1ULL << 32)
+#define DIVIDE_ITER (100)
+
+static int
+test_reciprocal(void)
+{
+ int result = 0;
+ uint32_t divisor_u32 = 0;
+ uint32_t dividend_u32;
+ uint32_t nresult_u32;
+ uint32_t rresult_u32;
+ uint64_t i, j;
+ uint64_t divisor_u64 = 0;
+ uint64_t dividend_u64;
+ uint64_t nresult_u64;
+ uint64_t rresult_u64;
+ struct rte_reciprocal reci_u32 = {0};
+ struct rte_reciprocal_u64 reci_u64 = {0};
+
+ rte_srand(rte_rdtsc());
+ printf("Validating unsigned 32bit division.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u32 = rte_rand();
+ reci_u32 = rte_reciprocal_value(divisor_u32);
+ }
+
+ dividend_u32 = rte_rand();
+ nresult_u32 = dividend_u32 / divisor_u32;
+ rresult_u32 = rte_reciprocal_divide(dividend_u32,
+ reci_u32);
+ if (nresult_u32 != rresult_u32) {
+ printf("Division failed, %"PRIu32"/%"PRIu32" = "
+ "expected %"PRIu32" result %"PRIu32"\n",
+ dividend_u32, divisor_u32,
+ nresult_u32, rresult_u32);
+ result = 1;
+ break;
+ }
+ }
+
+ printf("Validating unsigned 64bit division.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u64 = rte_rand();
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ }
+
+ dividend_u64 = rte_rand();
+ nresult_u64 = dividend_u64 / divisor_u64;
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+ if (nresult_u64 != rresult_u64) {
+ printf("Division failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+
+ printf("Validating unsigned 64bit division with 32bit divisor.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u64 = rte_rand() >> 32;
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ }
+
+ dividend_u64 = rte_rand();
+
+ nresult_u64 = dividend_u64 / divisor_u64;
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+
+ if (nresult_u64 != rresult_u64) {
+ printf("Division failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+
+ printf("Validating division by power of 2.\n");
+ for (i = 0; i < 32; i++) {
+ divisor_u64 = 1ull << i;
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
+
+ for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ dividend_u64 = rte_rand();
+
+ nresult_u64 = dividend_u64 / divisor_u64;
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+
+ if (nresult_u64 != rresult_u64) {
+ printf(
+ "Division 64 failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ }
+
+ nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
+ rresult_u32 = rte_reciprocal_divide(
+ (dividend_u64 >> 32), reci_u32);
+
+ if (nresult_u32 != rresult_u32) {
+ printf(
+ "Division 32 failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64 >> 32, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ for (; i < 64; i++) {
+ divisor_u64 = 1ull << i;
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+
+ for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
+ dividend_u64 = rte_rand();
+
+ nresult_u64 = dividend_u64 / divisor_u64;
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+
+ if (nresult_u64 != rresult_u64) {
+ printf("Division failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+REGISTER_TEST_COMMAND(reciprocal_division, test_reciprocal);
diff --git a/src/spdk/dpdk/app/test/test_reciprocal_division_perf.c b/src/spdk/dpdk/app/test/test_reciprocal_division_perf.c
new file mode 100644
index 000000000..a7be8aa71
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_reciprocal_division_perf.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#include "test.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_random.h>
+#include <rte_reciprocal.h>
+
+#define MAX_ITERATIONS (1ULL << 32)
+#define DIVIDE_ITER (1ULL << 28)
+
+static int
+test_reciprocal_division_perf(void)
+{
+ int result = 0;
+ uint32_t divisor_u32 = 0;
+ uint32_t dividend_u32;
+ uint64_t divisor_u64 = 0;
+ uint64_t dividend_u64;
+ volatile uint32_t nresult_u32;
+ volatile uint32_t rresult_u32;
+ volatile uint64_t nresult_u64;
+ volatile uint64_t rresult_u64;
+ uint64_t start_cyc;
+ uint64_t split_cyc;
+ uint64_t end_cyc;
+ uint64_t tot_cyc_n = 0;
+ uint64_t tot_cyc_r = 0;
+ uint64_t i;
+ struct rte_reciprocal reci_u32 = {0};
+ struct rte_reciprocal_u64 reci_u64 = {0};
+
+ rte_srand(rte_rdtsc());
+
+ printf("Validating unsigned 32bit division.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u32 = rte_rand();
+ reci_u32 = rte_reciprocal_value(divisor_u32);
+ }
+
+ dividend_u32 = rte_rand();
+
+ start_cyc = rte_rdtsc();
+ nresult_u32 = dividend_u32 / divisor_u32;
+ split_cyc = rte_rdtsc();
+ rresult_u32 = rte_reciprocal_divide(dividend_u32,
+ reci_u32);
+ end_cyc = rte_rdtsc();
+
+ tot_cyc_n += split_cyc - start_cyc;
+ tot_cyc_r += end_cyc - split_cyc;
+ if (nresult_u32 != rresult_u32) {
+ printf("Division failed, expected %"PRIu32" "
+ "result %"PRIu32"",
+ nresult_u32, rresult_u32);
+ result = 1;
+ break;
+ }
+ }
+ printf("32bit Division results:\n");
+ printf("Total number of cycles normal division : %"PRIu64"\n",
+ tot_cyc_n);
+ printf("Total number of cycles reciprocal division : %"PRIu64"\n",
+ tot_cyc_r);
+ printf("Cycles per division(normal) : %3.2f\n",
+ ((double)tot_cyc_n)/i);
+ printf("Cycles per division(reciprocal) : %3.2f\n\n",
+ ((double)tot_cyc_r)/i);
+
+ tot_cyc_n = 0;
+ tot_cyc_r = 0;
+
+ printf("Validating unsigned 64bit division.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u64 = rte_rand();
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ }
+
+ dividend_u64 = rte_rand();
+
+ start_cyc = rte_rdtsc();
+ nresult_u64 = dividend_u64 / divisor_u64;
+ split_cyc = rte_rdtsc();
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+ end_cyc = rte_rdtsc();
+
+ tot_cyc_n += split_cyc - start_cyc;
+ tot_cyc_r += end_cyc - split_cyc;
+ if (nresult_u64 != rresult_u64) {
+ printf("Division failed, expected %"PRIu64" "
+ "result %"PRIu64"",
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+ printf("64bit Division results:\n");
+ printf("Total number of cycles normal division : %"PRIu64"\n",
+ tot_cyc_n);
+ printf("Total number of cycles reciprocal division : %"PRIu64"\n",
+ tot_cyc_r);
+ printf("Cycles per division(normal) : %3.2f\n",
+ ((double)tot_cyc_n)/i);
+ printf("Cycles per division(reciprocal) : %3.2f\n\n",
+ ((double)tot_cyc_r)/i);
+
+ tot_cyc_n = 0;
+ tot_cyc_r = 0;
+
+ printf("Validating unsigned 64bit division with 32bit divisor.\n");
+ for (i = 0; i < MAX_ITERATIONS; i++) {
+ /* Change divisor every DIVIDE_ITER iterations. */
+ if (i % DIVIDE_ITER == 0) {
+ divisor_u64 = rte_rand() >> 32;
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+ }
+
+ dividend_u64 = rte_rand();
+
+ start_cyc = rte_rdtsc();
+ nresult_u64 = dividend_u64 / divisor_u64;
+ split_cyc = rte_rdtsc();
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+ end_cyc = rte_rdtsc();
+
+ tot_cyc_n += split_cyc - start_cyc;
+ tot_cyc_r += end_cyc - split_cyc;
+ if (nresult_u64 != rresult_u64) {
+ printf("Division failed, expected %"PRIu64" "
+ "result %"PRIu64"",
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+
+ printf("64bit Division results:\n");
+ printf("Total number of cycles normal division : %"PRIu64"\n",
+ tot_cyc_n);
+ printf("Total number of cycles reciprocal division : %"PRIu64"\n",
+ tot_cyc_r);
+ printf("Cycles per division(normal) : %3.2f\n",
+ ((double)tot_cyc_n)/i);
+ printf("Cycles per division(reciprocal) : %3.2f\n\n",
+ ((double)tot_cyc_r)/i);
+
+ tot_cyc_n = 0;
+ tot_cyc_r = 0;
+
+ printf("Validating division by power of 2.\n");
+ for (i = 0; i < 64; i++) {
+ divisor_u64 = 1ull << i;
+ reci_u64 = rte_reciprocal_value_u64(divisor_u64);
+
+ dividend_u64 = rte_rand();
+
+ start_cyc = rte_rdtsc();
+ nresult_u64 = dividend_u64 / divisor_u64;
+ split_cyc = rte_rdtsc();
+ rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
+ &reci_u64);
+ end_cyc = rte_rdtsc();
+
+ tot_cyc_n += split_cyc - start_cyc;
+ tot_cyc_r += end_cyc - split_cyc;
+ if (nresult_u64 != rresult_u64) {
+ printf("Division 64 failed, %"PRIu64"/%"PRIu64" = "
+ "expected %"PRIu64" result %"PRIu64"\n",
+ dividend_u64, divisor_u64,
+ nresult_u64, rresult_u64);
+ result = 1;
+ break;
+ }
+ }
+ printf("64bit Division results:\n");
+ printf("Total number of cycles normal division : %"PRIu64"\n",
+ tot_cyc_n);
+ printf("Total number of cycles reciprocal division : %"PRIu64"\n",
+ tot_cyc_r);
+ printf("Cycles per division(normal) : %3.2f\n",
+ ((double)tot_cyc_n)/i);
+ printf("Cycles per division(reciprocal) : %3.2f\n",
+ ((double)tot_cyc_r)/i);
+
+ return result;
+}
+
+REGISTER_TEST_COMMAND(reciprocal_division_perf, test_reciprocal_division_perf);
diff --git a/src/spdk/dpdk/app/test/test_red.c b/src/spdk/dpdk/app/test/test_red.c
new file mode 100644
index 000000000..e973f3131
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_red.c
@@ -0,0 +1,1856 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+
+#include "test.h"
+
+#include <rte_red.h>
+
+#ifdef __INTEL_COMPILER
+#pragma warning(disable:2259) /* conversion may lose significant bits */
+#pragma warning(disable:181) /* Arg incompatible with format string */
+#endif
+
+#define TEST_HZ_PER_KHZ 1000
+#define TEST_NSEC_MARGIN 500 /**< nanosecond margin when calculating clk freq */
+
+#define MAX_QEMPTY_TIME_MSEC 50000
+#define MSEC_PER_SEC 1000 /**< Milli-seconds per second */
+#define USEC_PER_MSEC 1000 /**< Micro-seconds per milli-second */
+#define USEC_PER_SEC 1000000 /**< Micro-seconds per second */
+#define NSEC_PER_SEC (USEC_PER_SEC * 1000) /**< Nano-seconds per second */
+
+/**< structures for testing rte_red performance and function */
+struct test_rte_red_config { /**< Test structure for RTE_RED config */
+ struct rte_red_config *rconfig; /**< RTE_RED configuration parameters */
+ uint8_t num_cfg; /**< Number of RTE_RED configs to test */
+ uint8_t *wq_log2; /**< Test wq_log2 value to use */
+ uint32_t min_th; /**< Queue minimum threshold */
+ uint32_t max_th; /**< Queue maximum threshold */
+ uint8_t *maxp_inv; /**< Inverse mark probability */
+};
+
+struct test_queue { /**< Test structure for RTE_RED Queues */
+ struct rte_red *rdata; /**< RTE_RED runtime data */
+ uint32_t num_queues; /**< Number of RTE_RED queues to test */
+ uint32_t *qconfig; /**< Configuration of RTE_RED queues for test */
+ uint32_t *q; /**< Queue size */
+ uint32_t q_ramp_up; /**< Num of enqueues to ramp up the queue */
+ uint32_t avg_ramp_up; /**< Average num of enqueues to ramp up the queue */
+ uint32_t avg_tolerance; /**< Tolerance in queue average */
+ double drop_tolerance; /**< Drop tolerance of packets not enqueued */
+};
+
+struct test_var { /**< Test variables used for testing RTE_RED */
+ uint32_t wait_usec; /**< Micro second wait interval */
+ uint32_t num_iterations; /**< Number of test iterations */
+ uint32_t num_ops; /**< Number of test operations */
+ uint64_t clk_freq; /**< CPU clock frequency */
+ uint32_t sleep_sec; /**< Seconds to sleep */
+ uint32_t *dropped; /**< Test operations dropped */
+ uint32_t *enqueued; /**< Test operations enqueued */
+};
+
+struct test_config { /**< Master test structure for RTE_RED */
+ const char *ifname; /**< Interface name */
+ const char *msg; /**< Test message for display */
+ const char *htxt; /**< Header txt display for result output */
+ struct test_rte_red_config *tconfig; /**< Test structure for RTE_RED config */
+ struct test_queue *tqueue; /**< Test structure for RTE_RED Queues */
+ struct test_var *tvar; /**< Test variables used for testing RTE_RED */
+ uint32_t *tlevel; /**< Queue levels */
+};
+
+enum test_result {
+ FAIL = 0,
+ PASS
+};
+
+/**< Test structure to define tests to run */
+struct tests {
+ struct test_config *testcfg;
+ enum test_result (*testfn)(struct test_config *);
+};
+
+struct rdtsc_prof {
+ uint64_t clk_start;
+ uint64_t clk_min; /**< min clocks */
+ uint64_t clk_max; /**< max clocks */
+ uint64_t clk_avgc; /**< count to calc average */
+ double clk_avg; /**< cumulative sum to calc average */
+ const char *name;
+};
+
+static const uint64_t port_speed_bytes = (10ULL*1000ULL*1000ULL*1000ULL)/8ULL;
+static double inv_cycles_per_byte = 0;
+static double pkt_time_usec = 0;
+
+static void init_port_ts(uint64_t cpu_clock)
+{
+ double cycles_per_byte = (double)(cpu_clock) / (double)(port_speed_bytes);
+ inv_cycles_per_byte = 1.0 / cycles_per_byte;
+ pkt_time_usec = 1000000.0 / ((double)port_speed_bytes / (double)RTE_RED_S);
+}
+
+static uint64_t get_port_ts(void)
+{
+ return (uint64_t)((double)rte_rdtsc() * inv_cycles_per_byte);
+}
+
+static void rdtsc_prof_init(struct rdtsc_prof *p, const char *name)
+{
+ p->clk_min = (uint64_t)(-1LL);
+ p->clk_max = 0;
+ p->clk_avg = 0;
+ p->clk_avgc = 0;
+ p->name = name;
+}
+
+static inline void rdtsc_prof_start(struct rdtsc_prof *p)
+{
+ p->clk_start = rte_rdtsc_precise();
+}
+
+static inline void rdtsc_prof_end(struct rdtsc_prof *p)
+{
+ uint64_t clk_start = rte_rdtsc() - p->clk_start;
+
+ p->clk_avgc++;
+ p->clk_avg += (double) clk_start;
+
+ if (clk_start > p->clk_max)
+ p->clk_max = clk_start;
+ if (clk_start < p->clk_min)
+ p->clk_min = clk_start;
+}
+
+static void rdtsc_prof_print(struct rdtsc_prof *p)
+{
+ if (p->clk_avgc>0) {
+ printf("RDTSC stats for %s: n=%" PRIu64 ", min=%" PRIu64 ", max=%" PRIu64 ", avg=%.1f\n",
+ p->name,
+ p->clk_avgc,
+ p->clk_min,
+ p->clk_max,
+ (p->clk_avg / ((double) p->clk_avgc)));
+ }
+}
+
+static uint32_t rte_red_get_avg_int(const struct rte_red_config *red_cfg,
+ struct rte_red *red)
+{
+ /**
+ * scale by 1/n and convert from fixed-point to integer
+ */
+ return red->avg >> (RTE_RED_SCALING + red_cfg->wq_log2);
+}
+
+static double rte_red_get_avg_float(const struct rte_red_config *red_cfg,
+ struct rte_red *red)
+{
+ /**
+ * scale by 1/n and convert from fixed-point to floating-point
+ */
+ return ldexp((double)red->avg, -(RTE_RED_SCALING + red_cfg->wq_log2));
+}
+
+static void rte_red_set_avg_int(const struct rte_red_config *red_cfg,
+ struct rte_red *red,
+ uint32_t avg)
+{
+ /**
+ * scale by n and convert from integer to fixed-point
+ */
+ red->avg = avg << (RTE_RED_SCALING + red_cfg->wq_log2);
+}
+
+static double calc_exp_avg_on_empty(double avg, uint32_t n, uint32_t time_diff)
+{
+ return avg * pow((1.0 - 1.0 / (double)n), (double)time_diff / pkt_time_usec);
+}
+
+static double calc_drop_rate(uint32_t enqueued, uint32_t dropped)
+{
+ return (double)dropped / ((double)enqueued + (double)dropped);
+}
+
+/**
+ * calculate the drop probability
+ */
+static double calc_drop_prob(uint32_t min_th, uint32_t max_th,
+ uint32_t maxp_inv, uint32_t avg)
+{
+ double drop_prob = 0.0;
+
+ if (avg < min_th) {
+ drop_prob = 0.0;
+ } else if (avg < max_th) {
+ drop_prob = (1.0 / (double)maxp_inv)
+ * ((double)(avg - min_th)
+ / (double)(max_th - min_th));
+ } else {
+ drop_prob = 1.0;
+ }
+ return drop_prob;
+}
+
+/**
+ * check if drop rate matches drop probability within tolerance
+ */
+static int check_drop_rate(double *diff, double drop_rate, double drop_prob, double tolerance)
+{
+ double abs_diff = 0.0;
+ int ret = 1;
+
+ abs_diff = fabs(drop_rate - drop_prob);
+ if ((int)abs_diff == 0) {
+ *diff = 0.0;
+ } else {
+ *diff = (abs_diff / drop_prob) * 100.0;
+ if (*diff > tolerance) {
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+/**
+ * check if average queue size is within tolerance
+ */
+static int check_avg(double *diff, double avg, double exp_avg, double tolerance)
+{
+ double abs_diff = 0.0;
+ int ret = 1;
+
+ abs_diff = fabs(avg - exp_avg);
+ if ((int)abs_diff == 0) {
+ *diff = 0.0;
+ } else {
+ *diff = (abs_diff / exp_avg) * 100.0;
+ if (*diff > tolerance) {
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+/**
+ * initialize the test rte_red config
+ */
+static enum test_result
+test_rte_red_init(struct test_config *tcfg)
+{
+ unsigned i = 0;
+
+ tcfg->tvar->clk_freq = rte_get_timer_hz();
+ init_port_ts( tcfg->tvar->clk_freq );
+
+ for (i = 0; i < tcfg->tconfig->num_cfg; i++) {
+ if (rte_red_config_init(&tcfg->tconfig->rconfig[i],
+ (uint16_t)tcfg->tconfig->wq_log2[i],
+ (uint16_t)tcfg->tconfig->min_th,
+ (uint16_t)tcfg->tconfig->max_th,
+ (uint16_t)tcfg->tconfig->maxp_inv[i]) != 0) {
+ return FAIL;
+ }
+ }
+
+ *tcfg->tqueue->q = 0;
+ *tcfg->tvar->dropped = 0;
+ *tcfg->tvar->enqueued = 0;
+ return PASS;
+}
+
+/**
+ * enqueue until actual queue size reaches target level
+ */
+static int
+increase_actual_qsize(struct rte_red_config *red_cfg,
+ struct rte_red *red,
+ uint32_t *q,
+ uint32_t level,
+ uint32_t attempts)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < attempts; i++) {
+ int ret = 0;
+
+ /**
+ * enqueue
+ */
+ ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts() );
+ if (ret == 0) {
+ if (++(*q) >= level)
+ break;
+ }
+ }
+ /**
+ * check if target actual queue size has been reached
+ */
+ if (*q != level)
+ return -1;
+ /**
+ * success
+ */
+ return 0;
+}
+
+/**
+ * enqueue until average queue size reaches target level
+ */
+static int
+increase_average_qsize(struct rte_red_config *red_cfg,
+ struct rte_red *red,
+ uint32_t *q,
+ uint32_t level,
+ uint32_t num_ops)
+{
+ uint32_t avg = 0;
+ uint32_t i = 0;
+
+ for (i = 0; i < num_ops; i++) {
+ /**
+ * enqueue
+ */
+ rte_red_enqueue(red_cfg, red, *q, get_port_ts());
+ }
+ /**
+ * check if target average queue size has been reached
+ */
+ avg = rte_red_get_avg_int(red_cfg, red);
+ if (avg != level)
+ return -1;
+ /**
+ * success
+ */
+ return 0;
+}
+
+/**
+ * setup default values for the functional test structures
+ */
+static struct rte_red_config ft_wrconfig[1];
+static struct rte_red ft_rtdata[1];
+static uint8_t ft_wq_log2[] = {9};
+static uint8_t ft_maxp_inv[] = {10};
+static uint32_t ft_qconfig[] = {0, 0, 1, 1};
+static uint32_t ft_q[] ={0};
+static uint32_t ft_dropped[] ={0};
+static uint32_t ft_enqueued[] ={0};
+
+static struct test_rte_red_config ft_tconfig = {
+ .rconfig = ft_wrconfig,
+ .num_cfg = RTE_DIM(ft_wrconfig),
+ .wq_log2 = ft_wq_log2,
+ .min_th = 32,
+ .max_th = 128,
+ .maxp_inv = ft_maxp_inv,
+};
+
+static struct test_queue ft_tqueue = {
+ .rdata = ft_rtdata,
+ .num_queues = RTE_DIM(ft_rtdata),
+ .qconfig = ft_qconfig,
+ .q = ft_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 5, /* 5 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+static struct test_var ft_tvar = {
+ .wait_usec = 10000,
+ .num_iterations = 5,
+ .num_ops = 10000,
+ .clk_freq = 0,
+ .dropped = ft_dropped,
+ .enqueued = ft_enqueued,
+ .sleep_sec = (MAX_QEMPTY_TIME_MSEC / MSEC_PER_SEC) + 2,
+};
+
+/**
+ * functional test enqueue/dequeue packets
+ */
+static void enqueue_dequeue_func(struct rte_red_config *red_cfg,
+ struct rte_red *red,
+ uint32_t *q,
+ uint32_t num_ops,
+ uint32_t *enqueued,
+ uint32_t *dropped)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < num_ops; i++) {
+ int ret = 0;
+
+ /**
+ * enqueue
+ */
+ ret = rte_red_enqueue(red_cfg, red, *q, get_port_ts());
+ if (ret == 0)
+ (*enqueued)++;
+ else
+ (*dropped)++;
+ }
+}
+
+/**
+ * Test F1: functional test 1
+ */
+static uint32_t ft1_tlevels[] = {6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144};
+
+static struct test_config func_test1_config = {
+ .ifname = "functional test 1 interface",
+ .msg = "functional test 1 : use one rte_red configuration,\n"
+ " increase average queue size to various levels,\n"
+ " compare drop rate to drop probability\n\n",
+ .htxt = " "
+ "avg queue size "
+ "enqueued "
+ "dropped "
+ "drop prob % "
+ "drop rate % "
+ "diff % "
+ "tolerance % "
+ "\n",
+ .tconfig = &ft_tconfig,
+ .tqueue = &ft_tqueue,
+ .tvar = &ft_tvar,
+ .tlevel = ft1_tlevels,
+};
+
+static enum test_result func_test1(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint32_t i = 0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ printf("%s", tcfg->htxt);
+
+ for (i = 0; i < RTE_DIM(ft1_tlevels); i++) {
+ const char *label = NULL;
+ uint32_t avg = 0;
+ double drop_rate = 0.0;
+ double drop_prob = 0.0;
+ double diff = 0.0;
+
+ /**
+ * reset rte_red run-time data
+ */
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+ *tcfg->tvar->enqueued = 0;
+ *tcfg->tvar->dropped = 0;
+
+ if (increase_actual_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ tcfg->tlevel[i],
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ if (increase_average_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ tcfg->tlevel[i],
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ enqueue_dequeue_func(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ tcfg->tvar->num_ops,
+ tcfg->tvar->enqueued,
+ tcfg->tvar->dropped);
+
+ avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ if (avg != tcfg->tlevel[i]) {
+ fprintf(stderr, "Fail: avg != level\n");
+ result = FAIL;
+ }
+
+ drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped);
+ drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th,
+ *tcfg->tconfig->maxp_inv, tcfg->tlevel[i]);
+ if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance))
+ result = FAIL;
+
+ if (tcfg->tlevel[i] == tcfg->tconfig->min_th)
+ label = "min thresh: ";
+ else if (tcfg->tlevel[i] == tcfg->tconfig->max_th)
+ label = "max thresh: ";
+ else
+ label = " ";
+ printf("%s%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n",
+ label, avg, *tcfg->tvar->enqueued, *tcfg->tvar->dropped,
+ drop_prob * 100.0, drop_rate * 100.0, diff,
+ (double)tcfg->tqueue->drop_tolerance);
+ }
+out:
+ return result;
+}
+
+/**
+ * Test F2: functional test 2
+ */
+static uint32_t ft2_tlevel[] = {127};
+static uint8_t ft2_wq_log2[] = {9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
+static uint8_t ft2_maxp_inv[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
+static struct rte_red_config ft2_rconfig[10];
+
+static struct test_rte_red_config ft2_tconfig = {
+ .rconfig = ft2_rconfig,
+ .num_cfg = RTE_DIM(ft2_rconfig),
+ .wq_log2 = ft2_wq_log2,
+ .min_th = 32,
+ .max_th = 128,
+ .maxp_inv = ft2_maxp_inv,
+};
+
+static struct test_config func_test2_config = {
+ .ifname = "functional test 2 interface",
+ .msg = "functional test 2 : use several RED configurations,\n"
+ " increase average queue size to just below maximum threshold,\n"
+ " compare drop rate to drop probability\n\n",
+ .htxt = "RED config "
+ "avg queue size "
+ "min threshold "
+ "max threshold "
+ "drop prob % "
+ "drop rate % "
+ "diff % "
+ "tolerance % "
+ "\n",
+ .tconfig = &ft2_tconfig,
+ .tqueue = &ft_tqueue,
+ .tvar = &ft_tvar,
+ .tlevel = ft2_tlevel,
+};
+
+static enum test_result func_test2(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ double prev_drop_rate = 1.0;
+ uint32_t i = 0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+
+ if (increase_actual_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ if (increase_average_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+ printf("%s", tcfg->htxt);
+
+ for (i = 0; i < tcfg->tconfig->num_cfg; i++) {
+ uint32_t avg = 0;
+ double drop_rate = 0.0;
+ double drop_prob = 0.0;
+ double diff = 0.0;
+
+ *tcfg->tvar->dropped = 0;
+ *tcfg->tvar->enqueued = 0;
+
+ enqueue_dequeue_func(&tcfg->tconfig->rconfig[i],
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ tcfg->tvar->num_ops,
+ tcfg->tvar->enqueued,
+ tcfg->tvar->dropped);
+
+ avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[i], tcfg->tqueue->rdata);
+ if (avg != *tcfg->tlevel)
+ result = FAIL;
+
+ drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped);
+ drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th,
+ tcfg->tconfig->maxp_inv[i], *tcfg->tlevel);
+ if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance))
+ result = FAIL;
+ /**
+ * drop rate should decrease as maxp_inv increases
+ */
+ if (drop_rate > prev_drop_rate)
+ result = FAIL;
+ prev_drop_rate = drop_rate;
+
+ printf("%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n",
+ i, avg, tcfg->tconfig->min_th, tcfg->tconfig->max_th,
+ drop_prob * 100.0, drop_rate * 100.0, diff,
+ (double)tcfg->tqueue->drop_tolerance);
+ }
+out:
+ return result;
+}
+
+/**
+ * Test F3: functional test 3
+ */
+static uint32_t ft3_tlevel[] = {1022};
+
+static struct test_rte_red_config ft3_tconfig = {
+ .rconfig = ft_wrconfig,
+ .num_cfg = RTE_DIM(ft_wrconfig),
+ .wq_log2 = ft_wq_log2,
+ .min_th = 32,
+ .max_th = 1023,
+ .maxp_inv = ft_maxp_inv,
+};
+
+static struct test_config func_test3_config = {
+ .ifname = "functional test 3 interface",
+ .msg = "functional test 3 : use one RED configuration,\n"
+ " increase average queue size to target level,\n"
+ " dequeue all packets until queue is empty,\n"
+ " confirm that average queue size is computed correctly while queue is empty\n\n",
+ .htxt = "q avg before "
+ "q avg after "
+ "expected "
+ "difference % "
+ "tolerance % "
+ "result "
+ "\n",
+ .tconfig = &ft3_tconfig,
+ .tqueue = &ft_tqueue,
+ .tvar = &ft_tvar,
+ .tlevel = ft3_tlevel,
+};
+
+static enum test_result func_test3(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint32_t i = 0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+
+ if (increase_actual_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ if (increase_average_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ printf("%s", tcfg->htxt);
+
+ for (i = 0; i < tcfg->tvar->num_iterations; i++) {
+ double avg_before = 0;
+ double avg_after = 0;
+ double exp_avg = 0;
+ double diff = 0.0;
+
+ avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+
+ /**
+ * empty the queue
+ */
+ *tcfg->tqueue->q = 0;
+ rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts());
+
+ rte_delay_us(tcfg->tvar->wait_usec);
+
+ /**
+ * enqueue one packet to recalculate average queue size
+ */
+ if (rte_red_enqueue(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ *tcfg->tqueue->q,
+ get_port_ts()) == 0) {
+ (*tcfg->tqueue->q)++;
+ } else {
+ printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__);
+ result = FAIL;
+ }
+
+ exp_avg = calc_exp_avg_on_empty(avg_before,
+ (1 << *tcfg->tconfig->wq_log2),
+ tcfg->tvar->wait_usec);
+ avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata);
+ if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
+ result = FAIL;
+
+ printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n",
+ avg_before, avg_after, exp_avg, diff,
+ (double)tcfg->tqueue->avg_tolerance,
+ diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail");
+ }
+out:
+ return result;
+}
+
+/**
+ * Test F4: functional test 4
+ */
+static uint32_t ft4_tlevel[] = {1022};
+static uint8_t ft4_wq_log2[] = {11};
+
+static struct test_rte_red_config ft4_tconfig = {
+ .rconfig = ft_wrconfig,
+ .num_cfg = RTE_DIM(ft_wrconfig),
+ .min_th = 32,
+ .max_th = 1023,
+ .wq_log2 = ft4_wq_log2,
+ .maxp_inv = ft_maxp_inv,
+};
+
+static struct test_queue ft4_tqueue = {
+ .rdata = ft_rtdata,
+ .num_queues = RTE_DIM(ft_rtdata),
+ .qconfig = ft_qconfig,
+ .q = ft_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 0, /* 0 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+static struct test_config func_test4_config = {
+ .ifname = "functional test 4 interface",
+ .msg = "functional test 4 : use one RED configuration,\n"
+ " increase average queue size to target level,\n"
+ " dequeue all packets until queue is empty,\n"
+ " confirm that average queue size is computed correctly while\n"
+ " queue is empty for more than 50 sec,\n"
+ " (this test takes 52 sec to run)\n\n",
+ .htxt = "q avg before "
+ "q avg after "
+ "expected "
+ "difference % "
+ "tolerance % "
+ "result "
+ "\n",
+ .tconfig = &ft4_tconfig,
+ .tqueue = &ft4_tqueue,
+ .tvar = &ft_tvar,
+ .tlevel = ft4_tlevel,
+};
+
+static enum test_result func_test4(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint64_t time_diff = 0;
+ uint64_t start = 0;
+ double avg_before = 0.0;
+ double avg_after = 0.0;
+ double exp_avg = 0.0;
+ double diff = 0.0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+
+ if (increase_actual_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ if (increase_average_qsize(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ *tcfg->tlevel,
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ printf("%s", tcfg->htxt);
+
+ avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+
+ /**
+ * empty the queue
+ */
+ *tcfg->tqueue->q = 0;
+ rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts());
+
+ /**
+ * record empty time locally
+ */
+ start = rte_rdtsc();
+
+ sleep(tcfg->tvar->sleep_sec);
+
+ /**
+ * enqueue one packet to recalculate average queue size
+ */
+ if (rte_red_enqueue(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ *tcfg->tqueue->q,
+ get_port_ts()) != 0) {
+ result = FAIL;
+ goto out;
+ }
+ (*tcfg->tqueue->q)++;
+
+ /**
+ * calculate how long queue has been empty
+ */
+ time_diff = ((rte_rdtsc() - start) / tcfg->tvar->clk_freq)
+ * MSEC_PER_SEC;
+ if (time_diff < MAX_QEMPTY_TIME_MSEC) {
+ /**
+ * this could happen if sleep was interrupted for some reason
+ */
+ result = FAIL;
+ goto out;
+ }
+
+ /**
+ * confirm that average queue size is now at expected level
+ */
+ exp_avg = 0.0;
+ avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
+ result = FAIL;
+
+ printf("%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n",
+ avg_before, avg_after, exp_avg,
+ diff, (double)tcfg->tqueue->avg_tolerance,
+ diff <= (double)tcfg->tqueue->avg_tolerance ? "pass" : "fail");
+out:
+ return result;
+}
+
+/**
+ * Test F5: functional test 5
+ */
+static uint32_t ft5_tlevel[] = {127};
+static uint8_t ft5_wq_log2[] = {9, 8};
+static uint8_t ft5_maxp_inv[] = {10, 20};
+static struct rte_red_config ft5_config[2];
+static struct rte_red ft5_data[4];
+static uint32_t ft5_q[4];
+static uint32_t ft5_dropped[] = {0, 0, 0, 0};
+static uint32_t ft5_enqueued[] = {0, 0, 0, 0};
+
+static struct test_rte_red_config ft5_tconfig = {
+ .rconfig = ft5_config,
+ .num_cfg = RTE_DIM(ft5_config),
+ .min_th = 32,
+ .max_th = 128,
+ .wq_log2 = ft5_wq_log2,
+ .maxp_inv = ft5_maxp_inv,
+};
+
+static struct test_queue ft5_tqueue = {
+ .rdata = ft5_data,
+ .num_queues = RTE_DIM(ft5_data),
+ .qconfig = ft_qconfig,
+ .q = ft5_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 5, /* 10 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+struct test_var ft5_tvar = {
+ .wait_usec = 0,
+ .num_iterations = 15,
+ .num_ops = 10000,
+ .clk_freq = 0,
+ .dropped = ft5_dropped,
+ .enqueued = ft5_enqueued,
+ .sleep_sec = 0,
+};
+
+static struct test_config func_test5_config = {
+ .ifname = "functional test 5 interface",
+ .msg = "functional test 5 : use several queues (each with its own run-time data),\n"
+ " use several RED configurations (such that each configuration is shared by multiple queues),\n"
+ " increase average queue size to just below maximum threshold,\n"
+ " compare drop rate to drop probability,\n"
+ " (this is a larger scale version of functional test 2)\n\n",
+ .htxt = "queue "
+ "config "
+ "avg queue size "
+ "min threshold "
+ "max threshold "
+ "drop prob % "
+ "drop rate % "
+ "diff % "
+ "tolerance % "
+ "\n",
+ .tconfig = &ft5_tconfig,
+ .tqueue = &ft5_tqueue,
+ .tvar = &ft5_tvar,
+ .tlevel = ft5_tlevel,
+};
+
+static enum test_result func_test5(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint32_t j = 0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ printf("%s", tcfg->htxt);
+
+ for (j = 0; j < tcfg->tqueue->num_queues; j++) {
+ rte_red_rt_data_init(&tcfg->tqueue->rdata[j]);
+ tcfg->tqueue->q[j] = 0;
+
+ if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ &tcfg->tqueue->q[j],
+ *tcfg->tlevel,
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+
+ if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ &tcfg->tqueue->q[j],
+ *tcfg->tlevel,
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+ }
+
+ for (j = 0; j < tcfg->tqueue->num_queues; j++) {
+ uint32_t avg = 0;
+ double drop_rate = 0.0;
+ double drop_prob = 0.0;
+ double diff = 0.0;
+
+ tcfg->tvar->dropped[j] = 0;
+ tcfg->tvar->enqueued[j] = 0;
+
+ enqueue_dequeue_func(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ &tcfg->tqueue->q[j],
+ tcfg->tvar->num_ops,
+ &tcfg->tvar->enqueued[j],
+ &tcfg->tvar->dropped[j]);
+
+ avg = rte_red_get_avg_int(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j]);
+ if (avg != *tcfg->tlevel)
+ result = FAIL;
+
+ drop_rate = calc_drop_rate(tcfg->tvar->enqueued[j],tcfg->tvar->dropped[j]);
+ drop_prob = calc_drop_prob(tcfg->tconfig->min_th, tcfg->tconfig->max_th,
+ tcfg->tconfig->maxp_inv[tcfg->tqueue->qconfig[j]],
+ *tcfg->tlevel);
+ if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance))
+ result = FAIL;
+
+ printf("%-15u%-15u%-15u%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf\n",
+ j, tcfg->tqueue->qconfig[j], avg,
+ tcfg->tconfig->min_th, tcfg->tconfig->max_th,
+ drop_prob * 100.0, drop_rate * 100.0,
+ diff, (double)tcfg->tqueue->drop_tolerance);
+ }
+out:
+ return result;
+}
+
+/**
+ * Test F6: functional test 6
+ */
+static uint32_t ft6_tlevel[] = {1022};
+static uint8_t ft6_wq_log2[] = {9, 8};
+static uint8_t ft6_maxp_inv[] = {10, 20};
+static struct rte_red_config ft6_config[2];
+static struct rte_red ft6_data[4];
+static uint32_t ft6_q[4];
+
+static struct test_rte_red_config ft6_tconfig = {
+ .rconfig = ft6_config,
+ .num_cfg = RTE_DIM(ft6_config),
+ .min_th = 32,
+ .max_th = 1023,
+ .wq_log2 = ft6_wq_log2,
+ .maxp_inv = ft6_maxp_inv,
+};
+
+static struct test_queue ft6_tqueue = {
+ .rdata = ft6_data,
+ .num_queues = RTE_DIM(ft6_data),
+ .qconfig = ft_qconfig,
+ .q = ft6_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 5, /* 10 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+static struct test_config func_test6_config = {
+ .ifname = "functional test 6 interface",
+ .msg = "functional test 6 : use several queues (each with its own run-time data),\n"
+ " use several RED configurations (such that each configuration is sharte_red by multiple queues),\n"
+ " increase average queue size to target level,\n"
+ " dequeue all packets until queue is empty,\n"
+ " confirm that average queue size is computed correctly while queue is empty\n"
+ " (this is a larger scale version of functional test 3)\n\n",
+ .htxt = "queue "
+ "config "
+ "q avg before "
+ "q avg after "
+ "expected "
+ "difference % "
+ "tolerance % "
+ "result ""\n",
+ .tconfig = &ft6_tconfig,
+ .tqueue = &ft6_tqueue,
+ .tvar = &ft_tvar,
+ .tlevel = ft6_tlevel,
+};
+
+static enum test_result func_test6(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint32_t j = 0;
+
+ printf("%s", tcfg->msg);
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+ printf("%s", tcfg->htxt);
+
+ for (j = 0; j < tcfg->tqueue->num_queues; j++) {
+ rte_red_rt_data_init(&tcfg->tqueue->rdata[j]);
+ tcfg->tqueue->q[j] = 0;
+
+ if (increase_actual_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ &tcfg->tqueue->q[j],
+ *tcfg->tlevel,
+ tcfg->tqueue->q_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+ if (increase_average_qsize(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ &tcfg->tqueue->q[j],
+ *tcfg->tlevel,
+ tcfg->tqueue->avg_ramp_up) != 0) {
+ result = FAIL;
+ goto out;
+ }
+ }
+ for (j = 0; j < tcfg->tqueue->num_queues; j++) {
+ double avg_before = 0;
+ double avg_after = 0;
+ double exp_avg = 0;
+ double diff = 0.0;
+
+ avg_before = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j]);
+
+ /**
+ * empty the queue
+ */
+ tcfg->tqueue->q[j] = 0;
+ rte_red_mark_queue_empty(&tcfg->tqueue->rdata[j], get_port_ts());
+ rte_delay_us(tcfg->tvar->wait_usec);
+
+ /**
+ * enqueue one packet to recalculate average queue size
+ */
+ if (rte_red_enqueue(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j],
+ tcfg->tqueue->q[j],
+ get_port_ts()) == 0) {
+ tcfg->tqueue->q[j]++;
+ } else {
+ printf("%s:%d: packet enqueued on empty queue was dropped\n", __func__, __LINE__);
+ result = FAIL;
+ }
+
+ exp_avg = calc_exp_avg_on_empty(avg_before,
+ (1 << tcfg->tconfig->wq_log2[tcfg->tqueue->qconfig[j]]),
+ tcfg->tvar->wait_usec);
+ avg_after = rte_red_get_avg_float(&tcfg->tconfig->rconfig[tcfg->tqueue->qconfig[j]],
+ &tcfg->tqueue->rdata[j]);
+ if (!check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
+ result = FAIL;
+
+ printf("%-15u%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n",
+ j, tcfg->tqueue->qconfig[j], avg_before, avg_after,
+ exp_avg, diff, (double)tcfg->tqueue->avg_tolerance,
+ diff <= tcfg->tqueue->avg_tolerance ? "pass" : "fail");
+ }
+out:
+ return result;
+}
+
+/**
+ * setup default values for the performance test structures
+ */
+static struct rte_red_config pt_wrconfig[1];
+static struct rte_red pt_rtdata[1];
+static uint8_t pt_wq_log2[] = {9};
+static uint8_t pt_maxp_inv[] = {10};
+static uint32_t pt_qconfig[] = {0};
+static uint32_t pt_q[] = {0};
+static uint32_t pt_dropped[] = {0};
+static uint32_t pt_enqueued[] = {0};
+
+static struct test_rte_red_config pt_tconfig = {
+ .rconfig = pt_wrconfig,
+ .num_cfg = RTE_DIM(pt_wrconfig),
+ .wq_log2 = pt_wq_log2,
+ .min_th = 32,
+ .max_th = 128,
+ .maxp_inv = pt_maxp_inv,
+};
+
+static struct test_queue pt_tqueue = {
+ .rdata = pt_rtdata,
+ .num_queues = RTE_DIM(pt_rtdata),
+ .qconfig = pt_qconfig,
+ .q = pt_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 5, /* 10 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+/**
+ * enqueue/dequeue packets
+ */
+static void enqueue_dequeue_perf(struct rte_red_config *red_cfg,
+ struct rte_red *red,
+ uint32_t *q,
+ uint32_t num_ops,
+ uint32_t *enqueued,
+ uint32_t *dropped,
+ struct rdtsc_prof *prof)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < num_ops; i++) {
+ uint64_t ts = 0;
+ int ret = 0;
+ /**
+ * enqueue
+ */
+ ts = get_port_ts();
+ rdtsc_prof_start(prof);
+ ret = rte_red_enqueue(red_cfg, red, *q, ts );
+ rdtsc_prof_end(prof);
+ if (ret == 0)
+ (*enqueued)++;
+ else
+ (*dropped)++;
+ }
+}
+
+/**
+ * Setup test structures for tests P1, P2, P3
+ * performance tests 1, 2 and 3
+ */
+static uint32_t pt1_tlevel[] = {16};
+static uint32_t pt2_tlevel[] = {80};
+static uint32_t pt3_tlevel[] = {144};
+
+static struct test_var perf1_tvar = {
+ .wait_usec = 0,
+ .num_iterations = 15,
+ .num_ops = 50000000,
+ .clk_freq = 0,
+ .dropped = pt_dropped,
+ .enqueued = pt_enqueued,
+ .sleep_sec = 0
+};
+
+static struct test_config perf1_test1_config = {
+ .ifname = "performance test 1 interface",
+ .msg = "performance test 1 : use one RED configuration,\n"
+ " set actual and average queue sizes to level below min threshold,\n"
+ " measure enqueue performance\n\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf1_tvar,
+ .tlevel = pt1_tlevel,
+};
+
+static struct test_config perf1_test2_config = {
+ .ifname = "performance test 2 interface",
+ .msg = "performance test 2 : use one RED configuration,\n"
+ " set actual and average queue sizes to level in between min and max thresholds,\n"
+ " measure enqueue performance\n\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf1_tvar,
+ .tlevel = pt2_tlevel,
+};
+
+static struct test_config perf1_test3_config = {
+ .ifname = "performance test 3 interface",
+ .msg = "performance test 3 : use one RED configuration,\n"
+ " set actual and average queue sizes to level above max threshold,\n"
+ " measure enqueue performance\n\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf1_tvar,
+ .tlevel = pt3_tlevel,
+};
+
+/**
+ * Performance test function to measure enqueue performance.
+ * This runs performance tests 1, 2 and 3
+ */
+static enum test_result perf1_test(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL};
+ uint32_t total = 0;
+
+ printf("%s", tcfg->msg);
+
+ rdtsc_prof_init(&prof, "enqueue");
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ /**
+ * set average queue size to target level
+ */
+ *tcfg->tqueue->q = *tcfg->tlevel;
+
+ /**
+ * initialize the rte_red run time data structure
+ */
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+
+ /**
+ * set the queue average
+ */
+ rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel);
+ if (rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata)
+ != *tcfg->tlevel) {
+ result = FAIL;
+ goto out;
+ }
+
+ enqueue_dequeue_perf(tcfg->tconfig->rconfig,
+ tcfg->tqueue->rdata,
+ tcfg->tqueue->q,
+ tcfg->tvar->num_ops,
+ tcfg->tvar->enqueued,
+ tcfg->tvar->dropped,
+ &prof);
+
+ total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped;
+
+ printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total,
+ *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0,
+ *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0);
+
+ rdtsc_prof_print(&prof);
+out:
+ return result;
+}
+
+/**
+ * Setup test structures for tests P4, P5, P6
+ * performance tests 4, 5 and 6
+ */
+static uint32_t pt4_tlevel[] = {16};
+static uint32_t pt5_tlevel[] = {80};
+static uint32_t pt6_tlevel[] = {144};
+
+static struct test_var perf2_tvar = {
+ .wait_usec = 500,
+ .num_iterations = 10000,
+ .num_ops = 10000,
+ .dropped = pt_dropped,
+ .enqueued = pt_enqueued,
+ .sleep_sec = 0
+};
+
+static struct test_config perf2_test4_config = {
+ .ifname = "performance test 4 interface",
+ .msg = "performance test 4 : use one RED configuration,\n"
+ " set actual and average queue sizes to level below min threshold,\n"
+ " dequeue all packets until queue is empty,\n"
+ " measure enqueue performance when queue is empty\n\n",
+ .htxt = "iteration "
+ "q avg before "
+ "q avg after "
+ "expected "
+ "difference % "
+ "tolerance % "
+ "result ""\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf2_tvar,
+ .tlevel = pt4_tlevel,
+};
+
+static struct test_config perf2_test5_config = {
+ .ifname = "performance test 5 interface",
+ .msg = "performance test 5 : use one RED configuration,\n"
+ " set actual and average queue sizes to level in between min and max thresholds,\n"
+ " dequeue all packets until queue is empty,\n"
+ " measure enqueue performance when queue is empty\n\n",
+ .htxt = "iteration "
+ "q avg before "
+ "q avg after "
+ "expected "
+ "difference "
+ "tolerance "
+ "result ""\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf2_tvar,
+ .tlevel = pt5_tlevel,
+};
+
+static struct test_config perf2_test6_config = {
+ .ifname = "performance test 6 interface",
+ .msg = "performance test 6 : use one RED configuration,\n"
+ " set actual and average queue sizes to level above max threshold,\n"
+ " dequeue all packets until queue is empty,\n"
+ " measure enqueue performance when queue is empty\n\n",
+ .htxt = "iteration "
+ "q avg before "
+ "q avg after "
+ "expected "
+ "difference % "
+ "tolerance % "
+ "result ""\n",
+ .tconfig = &pt_tconfig,
+ .tqueue = &pt_tqueue,
+ .tvar = &perf2_tvar,
+ .tlevel = pt6_tlevel,
+};
+
+/**
+ * Performance test function to measure enqueue performance when the
+ * queue is empty. This runs performance tests 4, 5 and 6
+ */
+static enum test_result perf2_test(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ struct rdtsc_prof prof = {0, 0, 0, 0, 0.0, NULL};
+ uint32_t total = 0;
+ uint32_t i = 0;
+
+ printf("%s", tcfg->msg);
+
+ rdtsc_prof_init(&prof, "enqueue");
+
+ if (test_rte_red_init(tcfg) != PASS) {
+ result = FAIL;
+ goto out;
+ }
+
+ printf("%s", tcfg->htxt);
+
+ for (i = 0; i < tcfg->tvar->num_iterations; i++) {
+ uint32_t count = 0;
+ uint64_t ts = 0;
+ double avg_before = 0;
+ int ret = 0;
+
+ /**
+ * set average queue size to target level
+ */
+ *tcfg->tqueue->q = *tcfg->tlevel;
+ count = (*tcfg->tqueue->rdata).count;
+
+ /**
+ * initialize the rte_red run time data structure
+ */
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+ (*tcfg->tqueue->rdata).count = count;
+
+ /**
+ * set the queue average
+ */
+ rte_red_set_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata, *tcfg->tlevel);
+ avg_before = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ if ((avg_before < *tcfg->tlevel) || (avg_before > *tcfg->tlevel)) {
+ result = FAIL;
+ goto out;
+ }
+
+ /**
+ * empty the queue
+ */
+ *tcfg->tqueue->q = 0;
+ rte_red_mark_queue_empty(tcfg->tqueue->rdata, get_port_ts());
+
+ /**
+ * wait for specified period of time
+ */
+ rte_delay_us(tcfg->tvar->wait_usec);
+
+ /**
+ * measure performance of enqueue operation while queue is empty
+ */
+ ts = get_port_ts();
+ rdtsc_prof_start(&prof);
+ ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata,
+ *tcfg->tqueue->q, ts );
+ rdtsc_prof_end(&prof);
+
+ /**
+ * gather enqueued/dropped statistics
+ */
+ if (ret == 0)
+ (*tcfg->tvar->enqueued)++;
+ else
+ (*tcfg->tvar->dropped)++;
+
+ /**
+ * on first and last iteration, confirm that
+ * average queue size was computed correctly
+ */
+ if ((i == 0) || (i == tcfg->tvar->num_iterations - 1)) {
+ double avg_after = 0;
+ double exp_avg = 0;
+ double diff = 0.0;
+ int ok = 0;
+
+ avg_after = rte_red_get_avg_float(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ exp_avg = calc_exp_avg_on_empty(avg_before,
+ (1 << *tcfg->tconfig->wq_log2),
+ tcfg->tvar->wait_usec);
+ if (check_avg(&diff, avg_after, exp_avg, (double)tcfg->tqueue->avg_tolerance))
+ ok = 1;
+ printf("%-15u%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15.4lf%-15s\n",
+ i, avg_before, avg_after, exp_avg, diff,
+ (double)tcfg->tqueue->avg_tolerance, ok ? "pass" : "fail");
+ if (!ok) {
+ result = FAIL;
+ goto out;
+ }
+ }
+ }
+ total = *tcfg->tvar->enqueued + *tcfg->tvar->dropped;
+ printf("\ntotal: %u, enqueued: %u (%.2lf%%), dropped: %u (%.2lf%%)\n", total,
+ *tcfg->tvar->enqueued, ((double)(*tcfg->tvar->enqueued) / (double)total) * 100.0,
+ *tcfg->tvar->dropped, ((double)(*tcfg->tvar->dropped) / (double)total) * 100.0);
+
+ rdtsc_prof_print(&prof);
+out:
+ return result;
+}
+
+/**
+ * setup default values for overflow test structures
+ */
+static uint32_t avg_max = 0;
+static uint32_t avg_max_bits = 0;
+
+static struct rte_red_config ovfl_wrconfig[1];
+static struct rte_red ovfl_rtdata[1];
+static uint8_t ovfl_maxp_inv[] = {10};
+static uint32_t ovfl_qconfig[] = {0, 0, 1, 1};
+static uint32_t ovfl_q[] ={0};
+static uint32_t ovfl_dropped[] ={0};
+static uint32_t ovfl_enqueued[] ={0};
+static uint32_t ovfl_tlevel[] = {1023};
+static uint8_t ovfl_wq_log2[] = {12};
+
+static struct test_rte_red_config ovfl_tconfig = {
+ .rconfig = ovfl_wrconfig,
+ .num_cfg = RTE_DIM(ovfl_wrconfig),
+ .wq_log2 = ovfl_wq_log2,
+ .min_th = 32,
+ .max_th = 1023,
+ .maxp_inv = ovfl_maxp_inv,
+};
+
+static struct test_queue ovfl_tqueue = {
+ .rdata = ovfl_rtdata,
+ .num_queues = RTE_DIM(ovfl_rtdata),
+ .qconfig = ovfl_qconfig,
+ .q = ovfl_q,
+ .q_ramp_up = 1000000,
+ .avg_ramp_up = 1000000,
+ .avg_tolerance = 5, /* 10 percent */
+ .drop_tolerance = 50, /* 50 percent */
+};
+
+static struct test_var ovfl_tvar = {
+ .wait_usec = 10000,
+ .num_iterations = 1,
+ .num_ops = 10000,
+ .clk_freq = 0,
+ .dropped = ovfl_dropped,
+ .enqueued = ovfl_enqueued,
+ .sleep_sec = 0
+};
+
+static void ovfl_check_avg(uint32_t avg)
+{
+ if (avg > avg_max) {
+ double avg_log = 0;
+ uint32_t bits = 0;
+ avg_max = avg;
+ avg_log = log(((double)avg_max));
+ avg_log = avg_log / log(2.0);
+ bits = (uint32_t)ceil(avg_log);
+ if (bits > avg_max_bits)
+ avg_max_bits = bits;
+ }
+}
+
+static struct test_config ovfl_test1_config = {
+ .ifname = "queue avergage overflow test interface",
+ .msg = "overflow test 1 : use one RED configuration,\n"
+ " increase average queue size to target level,\n"
+ " check maximum number of bits requirte_red to represent avg_s\n\n",
+ .htxt = "avg queue size "
+ "wq_log2 "
+ "fraction bits "
+ "max queue avg "
+ "num bits "
+ "enqueued "
+ "dropped "
+ "drop prob % "
+ "drop rate % "
+ "\n",
+ .tconfig = &ovfl_tconfig,
+ .tqueue = &ovfl_tqueue,
+ .tvar = &ovfl_tvar,
+ .tlevel = ovfl_tlevel,
+};
+
+static enum test_result ovfl_test1(struct test_config *tcfg)
+{
+ enum test_result result = PASS;
+ uint32_t avg = 0;
+ uint32_t i = 0;
+ double drop_rate = 0.0;
+ double drop_prob = 0.0;
+ double diff = 0.0;
+ int ret = 0;
+
+ printf("%s", tcfg->msg);
+
+ if (test_rte_red_init(tcfg) != PASS) {
+
+ result = FAIL;
+ goto out;
+ }
+
+ /**
+ * reset rte_red run-time data
+ */
+ rte_red_rt_data_init(tcfg->tqueue->rdata);
+
+ /**
+ * increase actual queue size
+ */
+ for (i = 0; i < tcfg->tqueue->q_ramp_up; i++) {
+ ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata,
+ *tcfg->tqueue->q, get_port_ts());
+
+ if (ret == 0) {
+ if (++(*tcfg->tqueue->q) >= *tcfg->tlevel)
+ break;
+ }
+ }
+
+ /**
+ * enqueue
+ */
+ for (i = 0; i < tcfg->tqueue->avg_ramp_up; i++) {
+ ret = rte_red_enqueue(tcfg->tconfig->rconfig, tcfg->tqueue->rdata,
+ *tcfg->tqueue->q, get_port_ts());
+ ovfl_check_avg((*tcfg->tqueue->rdata).avg);
+ avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ if (avg == *tcfg->tlevel) {
+ if (ret == 0)
+ (*tcfg->tvar->enqueued)++;
+ else
+ (*tcfg->tvar->dropped)++;
+ }
+ }
+
+ /**
+ * check if target average queue size has been reached
+ */
+ avg = rte_red_get_avg_int(tcfg->tconfig->rconfig, tcfg->tqueue->rdata);
+ if (avg != *tcfg->tlevel) {
+ result = FAIL;
+ goto out;
+ }
+
+ /**
+ * check drop rate against drop probability
+ */
+ drop_rate = calc_drop_rate(*tcfg->tvar->enqueued, *tcfg->tvar->dropped);
+ drop_prob = calc_drop_prob(tcfg->tconfig->min_th,
+ tcfg->tconfig->max_th,
+ *tcfg->tconfig->maxp_inv,
+ *tcfg->tlevel);
+ if (!check_drop_rate(&diff, drop_rate, drop_prob, (double)tcfg->tqueue->drop_tolerance))
+ result = FAIL;
+
+ printf("%s", tcfg->htxt);
+
+ printf("%-16u%-9u%-15u0x%08x %-10u%-10u%-10u%-13.2lf%-13.2lf\n",
+ avg, *tcfg->tconfig->wq_log2, RTE_RED_SCALING,
+ avg_max, avg_max_bits,
+ *tcfg->tvar->enqueued, *tcfg->tvar->dropped,
+ drop_prob * 100.0, drop_rate * 100.0);
+out:
+ return result;
+}
+
+/**
+ * define the functional and performance tests to be executed
+ */
+struct tests func_tests[] = {
+ { &func_test1_config, func_test1 },
+ { &func_test2_config, func_test2 },
+ { &func_test3_config, func_test3 },
+ { &func_test4_config, func_test4 },
+ { &func_test5_config, func_test5 },
+ { &func_test6_config, func_test6 },
+ { &ovfl_test1_config, ovfl_test1 },
+};
+
+struct tests func_tests_quick[] = {
+ { &func_test1_config, func_test1 },
+ { &func_test2_config, func_test2 },
+ { &func_test3_config, func_test3 },
+ /* no test 4 as it takes a lot of time */
+ { &func_test5_config, func_test5 },
+ { &func_test6_config, func_test6 },
+ { &ovfl_test1_config, ovfl_test1 },
+};
+
+struct tests perf_tests[] = {
+ { &perf1_test1_config, perf1_test },
+ { &perf1_test2_config, perf1_test },
+ { &perf1_test3_config, perf1_test },
+ { &perf2_test4_config, perf2_test },
+ { &perf2_test5_config, perf2_test },
+ { &perf2_test6_config, perf2_test },
+};
+
+/**
+ * function to execute the required_red tests
+ */
+static void run_tests(struct tests *test_type, uint32_t test_count, uint32_t *num_tests, uint32_t *num_pass)
+{
+ enum test_result result = PASS;
+ uint32_t i = 0;
+
+ for (i = 0; i < test_count; i++) {
+ printf("\n--------------------------------------------------------------------------------\n");
+ result = test_type[i].testfn(test_type[i].testcfg);
+ (*num_tests)++;
+ if (result == PASS) {
+ (*num_pass)++;
+ printf("-------------------------------------<pass>-------------------------------------\n");
+ } else {
+ printf("-------------------------------------<fail>-------------------------------------\n");
+ }
+ }
+ return;
+}
+
+/**
+ * check if functions accept invalid parameters
+ *
+ * First, all functions will be called without initialized RED
+ * Then, all of them will be called with NULL/invalid parameters
+ *
+ * Some functions are not tested as they are performance-critical and thus
+ * don't do any parameter checking.
+ */
+static int
+test_invalid_parameters(void)
+{
+ struct rte_red_config config;
+
+ if (rte_red_rt_data_init(NULL) == 0) {
+ printf("rte_red_rt_data_init should have failed!\n");
+ return -1;
+ }
+
+ if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) {
+ printf("rte_red_config_init should have failed!\n");
+ return -1;
+ }
+
+ if (rte_red_rt_data_init(NULL) == 0) {
+ printf("rte_red_rt_data_init should have failed!\n");
+ return -1;
+ }
+
+ /* NULL config */
+ if (rte_red_config_init(NULL, 0, 0, 0, 0) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* min_treshold == max_treshold */
+ if (rte_red_config_init(&config, 0, 1, 1, 0) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* min_treshold > max_treshold */
+ if (rte_red_config_init(&config, 0, 2, 1, 0) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* wq_log2 > RTE_RED_WQ_LOG2_MAX */
+ if (rte_red_config_init(&config,
+ RTE_RED_WQ_LOG2_MAX + 1, 1, 2, 0) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* wq_log2 < RTE_RED_WQ_LOG2_MIN */
+ if (rte_red_config_init(&config,
+ RTE_RED_WQ_LOG2_MIN - 1, 1, 2, 0) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* maxp_inv > RTE_RED_MAXP_INV_MAX */
+ if (rte_red_config_init(&config,
+ RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MAX + 1) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+ /* maxp_inv < RTE_RED_MAXP_INV_MIN */
+ if (rte_red_config_init(&config,
+ RTE_RED_WQ_LOG2_MIN, 1, 2, RTE_RED_MAXP_INV_MIN - 1) == 0) {
+ printf("%i: rte_red_config_init should have failed!\n", __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+show_stats(const uint32_t num_tests, const uint32_t num_pass)
+{
+ if (num_pass == num_tests)
+ printf("[total: %u, pass: %u]\n", num_tests, num_pass);
+ else
+ printf("[total: %u, pass: %u, fail: %u]\n", num_tests, num_pass,
+ num_tests - num_pass);
+}
+
+static int
+tell_the_result(const uint32_t num_tests, const uint32_t num_pass)
+{
+ return (num_pass == num_tests) ? 0 : 1;
+}
+
+static int
+test_red(void)
+{
+ uint32_t num_tests = 0;
+ uint32_t num_pass = 0;
+
+ if (test_invalid_parameters() < 0)
+ return -1;
+ run_tests(func_tests_quick, RTE_DIM(func_tests_quick),
+ &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
+}
+
+static int
+test_red_perf(void)
+{
+ uint32_t num_tests = 0;
+ uint32_t num_pass = 0;
+
+ run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
+}
+
+static int
+test_red_all(void)
+{
+ uint32_t num_tests = 0;
+ uint32_t num_pass = 0;
+
+ if (test_invalid_parameters() < 0)
+ return -1;
+
+ run_tests(func_tests, RTE_DIM(func_tests), &num_tests, &num_pass);
+ run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass);
+ show_stats(num_tests, num_pass);
+ return tell_the_result(num_tests, num_pass);
+}
+
+REGISTER_TEST_COMMAND(red_autotest, test_red);
+REGISTER_TEST_COMMAND(red_perf, test_red_perf);
+REGISTER_TEST_COMMAND(red_all, test_red_all);
diff --git a/src/spdk/dpdk/app/test/test_reorder.c b/src/spdk/dpdk/app/test/test_reorder.c
new file mode 100644
index 000000000..58fa9c71b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_reorder.c
@@ -0,0 +1,393 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rte_cycles.h>
+#include <rte_errno.h>
+#include <rte_mbuf.h>
+#include <rte_reorder.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+
+#include "test.h"
+
+#define BURST 32
+#define REORDER_BUFFER_SIZE 16384
+#define NUM_MBUFS (2*REORDER_BUFFER_SIZE)
+#define REORDER_BUFFER_SIZE_INVALID 2049
+
+struct reorder_unittest_params {
+ struct rte_mempool *p;
+ struct rte_reorder_buffer *b;
+};
+
+static struct reorder_unittest_params default_params = {
+ .p = NULL,
+ .b = NULL
+};
+
+static struct reorder_unittest_params *test_params = &default_params;
+
+static int
+test_reorder_create(void)
+{
+ struct rte_reorder_buffer *b = NULL;
+
+ b = rte_reorder_create(NULL, rte_socket_id(), REORDER_BUFFER_SIZE);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on create() with NULL name");
+
+ b = rte_reorder_create("PKT", rte_socket_id(), REORDER_BUFFER_SIZE_INVALID);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on create() with invalid buffer size param.");
+
+ b = rte_reorder_create("PKT_RO1", rte_socket_id(), REORDER_BUFFER_SIZE);
+ TEST_ASSERT_EQUAL(b, test_params->b,
+ "New reorder instance created with already existing name");
+
+ return 0;
+}
+
+static int
+test_reorder_init(void)
+{
+ struct rte_reorder_buffer *b = NULL;
+ unsigned int size;
+ /*
+ * The minimum memory area size that should be passed to library is,
+ * sizeof(struct rte_reorder_buffer) + (2 * size * sizeof(struct rte_mbuf *));
+ * Otherwise error will be thrown
+ */
+
+ size = 100;
+ b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on init with NULL buffer.");
+
+ b = rte_malloc(NULL, size, 0);
+ b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on init with invalid mem zone size.");
+ rte_free(b);
+
+ size = 262336;
+ b = rte_malloc(NULL, size, 0);
+ b = rte_reorder_init(b, size, "PKT1", REORDER_BUFFER_SIZE_INVALID);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on init with invalid buffer size param.");
+
+ b = rte_reorder_init(b, size, NULL, REORDER_BUFFER_SIZE);
+ TEST_ASSERT((b == NULL) && (rte_errno == EINVAL),
+ "No error on init with invalid name.");
+ rte_free(b);
+
+ return 0;
+}
+
+static int
+test_reorder_find_existing(void)
+{
+ struct rte_reorder_buffer *b = NULL;
+
+ /* Try to find existing reorder buffer instance */
+ b = rte_reorder_find_existing("PKT_RO1");
+ TEST_ASSERT_EQUAL(b, test_params->b,
+ "existing reorder buffer instance not found");
+
+ /* Try to find non existing reorder buffer instance */
+ b = rte_reorder_find_existing("ro_find_non_existing");
+ TEST_ASSERT((b == NULL) && (rte_errno == ENOENT),
+ "non existing reorder buffer instance found");
+
+ return 0;
+}
+
+static int
+test_reorder_free(void)
+{
+ struct rte_reorder_buffer *b1 = NULL, *b2 = NULL;
+ const char *name = "test_free";
+
+ b1 = rte_reorder_create(name, rte_socket_id(), 8);
+ TEST_ASSERT_NOT_NULL(b1, "Failed to create reorder buffer.");
+
+ b2 = rte_reorder_find_existing(name);
+ TEST_ASSERT_EQUAL(b1, b2, "Failed to find existing reorder buffer");
+
+ rte_reorder_free(b1);
+
+ b2 = rte_reorder_find_existing(name);
+ TEST_ASSERT((b2 == NULL) && (rte_errno == ENOENT),
+ "Found previously freed reorder buffer");
+
+ return 0;
+}
+
+static int
+test_reorder_insert(void)
+{
+ struct rte_reorder_buffer *b = NULL;
+ struct rte_mempool *p = test_params->p;
+ const unsigned int size = 4;
+ const unsigned int num_bufs = 7;
+ struct rte_mbuf *bufs[num_bufs];
+ int ret = 0;
+ unsigned i;
+
+ /* This would create a reorder buffer instance consisting of:
+ * reorder_seq = 0
+ * ready_buf: RB[size] = {NULL, NULL, NULL, NULL}
+ * order_buf: OB[size] = {NULL, NULL, NULL, NULL}
+ */
+ b = rte_reorder_create("test_insert", rte_socket_id(), size);
+ TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer");
+
+ for (i = 0; i < num_bufs; i++) {
+ bufs[i] = rte_pktmbuf_alloc(p);
+ TEST_ASSERT_NOT_NULL(bufs[i], "Packet allocation failed\n");
+ bufs[i]->seqn = i;
+ }
+
+ /* This should fill up order buffer:
+ * reorder_seq = 0
+ * RB[] = {NULL, NULL, NULL, NULL}
+ * OB[] = {0, 1, 2, 3}
+ */
+ for (i = 0; i < size; i++) {
+ ret = rte_reorder_insert(b, bufs[i]);
+ if (ret != 0) {
+ printf("%s:%d: Error inserting packet with seqn less than size\n",
+ __func__, __LINE__);
+ ret = -1;
+ goto exit;
+ }
+ bufs[i] = NULL;
+ }
+
+ /* early packet - should move mbufs to ready buf and move sequence window
+ * reorder_seq = 4
+ * RB[] = {0, 1, 2, 3}
+ * OB[] = {4, NULL, NULL, NULL}
+ */
+ ret = rte_reorder_insert(b, bufs[4]);
+ if (ret != 0) {
+ printf("%s:%d: Error inserting early packet with seqn: size\n",
+ __func__, __LINE__);
+ ret = -1;
+ goto exit;
+ }
+ bufs[4] = NULL;
+
+ /* early packet from current sequence window - full ready buffer */
+ bufs[5]->seqn = 2 * size;
+ ret = rte_reorder_insert(b, bufs[5]);
+ if (!((ret == -1) && (rte_errno == ENOSPC))) {
+ printf("%s:%d: No error inserting early packet with full ready buffer\n",
+ __func__, __LINE__);
+ ret = -1;
+ goto exit;
+ }
+ bufs[5] = NULL;
+
+ /* late packet */
+ bufs[6]->seqn = 3 * size;
+ ret = rte_reorder_insert(b, bufs[6]);
+ if (!((ret == -1) && (rte_errno == ERANGE))) {
+ printf("%s:%d: No error inserting late packet with seqn:"
+ " 3 * size\n", __func__, __LINE__);
+ ret = -1;
+ goto exit;
+ }
+ bufs[6] = NULL;
+
+ ret = 0;
+exit:
+ rte_reorder_free(b);
+ for (i = 0; i < num_bufs; i++) {
+ if (bufs[i] != NULL)
+ rte_pktmbuf_free(bufs[i]);
+ }
+ return ret;
+}
+
+static int
+test_reorder_drain(void)
+{
+ struct rte_reorder_buffer *b = NULL;
+ struct rte_mempool *p = test_params->p;
+ const unsigned int size = 4;
+ const unsigned int num_bufs = 8;
+ struct rte_mbuf *bufs[num_bufs];
+ struct rte_mbuf *robufs[num_bufs];
+ int ret = 0;
+ unsigned i, cnt;
+
+ /* initialize all robufs to NULL */
+ for (i = 0; i < num_bufs; i++)
+ robufs[i] = NULL;
+
+ /* This would create a reorder buffer instance consisting of:
+ * reorder_seq = 0
+ * ready_buf: RB[size] = {NULL, NULL, NULL, NULL}
+ * order_buf: OB[size] = {NULL, NULL, NULL, NULL}
+ */
+ b = rte_reorder_create("test_drain", rte_socket_id(), size);
+ TEST_ASSERT_NOT_NULL(b, "Failed to create reorder buffer");
+
+ /* Check no drained packets if reorder is empty */
+ cnt = rte_reorder_drain(b, robufs, 1);
+ if (cnt != 0) {
+ printf("%s:%d: drained packets from empty reorder buffer\n",
+ __func__, __LINE__);
+ ret = -1;
+ goto exit;
+ }
+
+ for (i = 0; i < num_bufs; i++) {
+ bufs[i] = rte_pktmbuf_alloc(p);
+ TEST_ASSERT_NOT_NULL(bufs[i], "Packet allocation failed\n");
+ bufs[i]->seqn = i;
+ }
+
+ /* Insert packet with seqn 1:
+ * reorder_seq = 0
+ * RB[] = {NULL, NULL, NULL, NULL}
+ * OB[] = {1, NULL, NULL, NULL}
+ */
+ rte_reorder_insert(b, bufs[1]);
+ bufs[1] = NULL;
+
+ cnt = rte_reorder_drain(b, robufs, 1);
+ if (cnt != 1) {
+ printf("%s:%d:%d: number of expected packets not drained\n",
+ __func__, __LINE__, cnt);
+ ret = -1;
+ goto exit;
+ }
+ if (robufs[0] != NULL)
+ rte_pktmbuf_free(robufs[0]);
+
+ /* Insert more packets
+ * RB[] = {NULL, NULL, NULL, NULL}
+ * OB[] = {NULL, 2, 3, NULL}
+ */
+ rte_reorder_insert(b, bufs[2]);
+ rte_reorder_insert(b, bufs[3]);
+ bufs[2] = NULL;
+ bufs[3] = NULL;
+
+ /* Insert more packets
+ * RB[] = {NULL, NULL, NULL, NULL}
+ * OB[] = {NULL, 2, 3, 4}
+ */
+ rte_reorder_insert(b, bufs[4]);
+ bufs[4] = NULL;
+
+ /* Insert more packets
+ * RB[] = {2, 3, 4, NULL}
+ * OB[] = {NULL, NULL, 7, NULL}
+ */
+ rte_reorder_insert(b, bufs[7]);
+ bufs[7] = NULL;
+
+ /* drained expected packets */
+ cnt = rte_reorder_drain(b, robufs, 4);
+ if (cnt != 3) {
+ printf("%s:%d:%d: number of expected packets not drained\n",
+ __func__, __LINE__, cnt);
+ ret = -1;
+ goto exit;
+ }
+ for (i = 0; i < 3; i++) {
+ if (robufs[i] != NULL)
+ rte_pktmbuf_free(robufs[i]);
+ }
+
+ /*
+ * RB[] = {NULL, NULL, NULL, NULL}
+ * OB[] = {NULL, NULL, 7, NULL}
+ */
+ cnt = rte_reorder_drain(b, robufs, 1);
+ if (cnt != 0) {
+ printf("%s:%d:%d: number of expected packets not drained\n",
+ __func__, __LINE__, cnt);
+ ret = -1;
+ goto exit;
+ }
+ ret = 0;
+exit:
+ rte_reorder_free(b);
+ for (i = 0; i < num_bufs; i++) {
+ if (bufs[i] != NULL)
+ rte_pktmbuf_free(bufs[i]);
+ if (robufs[i] != NULL)
+ rte_pktmbuf_free(robufs[i]);
+ }
+ return ret;
+}
+
+static int
+test_setup(void)
+{
+ /* reorder buffer instance creation */
+ if (test_params->b == NULL) {
+ test_params->b = rte_reorder_create("PKT_RO1", rte_socket_id(),
+ REORDER_BUFFER_SIZE);
+ if (test_params->b == NULL) {
+ printf("%s: Error creating reorder buffer instance b\n",
+ __func__);
+ return -1;
+ }
+ } else
+ rte_reorder_reset(test_params->b);
+
+ /* mempool creation */
+ if (test_params->p == NULL) {
+ test_params->p = rte_pktmbuf_pool_create("RO_MBUF_POOL",
+ NUM_MBUFS, BURST, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+ if (test_params->p == NULL) {
+ printf("%s: Error creating mempool\n", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void
+test_teardown(void)
+{
+ rte_reorder_free(test_params->b);
+ test_params->b = NULL;
+ rte_mempool_free(test_params->p);
+ test_params->p = NULL;
+}
+
+
+static struct unit_test_suite reorder_test_suite = {
+
+ .setup = test_setup,
+ .teardown = test_teardown,
+ .suite_name = "Reorder Unit Test Suite",
+ .unit_test_cases = {
+ TEST_CASE(test_reorder_create),
+ TEST_CASE(test_reorder_init),
+ TEST_CASE(test_reorder_find_existing),
+ TEST_CASE(test_reorder_free),
+ TEST_CASE(test_reorder_insert),
+ TEST_CASE(test_reorder_drain),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_reorder(void)
+{
+ return unit_test_suite_runner(&reorder_test_suite);
+}
+
+REGISTER_TEST_COMMAND(reorder_autotest, test_reorder);
diff --git a/src/spdk/dpdk/app/test/test_resource.c b/src/spdk/dpdk/app/test/test_resource.c
new file mode 100644
index 000000000..8f41e3bab
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_resource.c
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2016 RehiveTech. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "test.h"
+#include "resource.h"
+
+const char test_resource_dpdk_blob[] = {
+ '\x44', '\x50', '\x44', '\x4b', '\x00'
+};
+
+REGISTER_RESOURCE(test_resource_dpdk,
+ test_resource_dpdk_blob, test_resource_dpdk_blob + 4);
+
+static int test_resource_dpdk(void)
+{
+ const struct resource *r;
+
+ r = resource_find("test_resource_dpdk");
+ TEST_ASSERT_NOT_NULL(r, "Could not find test_resource_dpdk");
+ TEST_ASSERT(!strcmp(r->name, "test_resource_dpdk"),
+ "Found resource %s, expected test_resource_dpdk",
+ r->name);
+
+ TEST_ASSERT(!strncmp("DPDK", r->begin, 4),
+ "Unexpected payload: %.4s...", r->begin);
+
+ return 0;
+}
+
+REGISTER_LINKED_RESOURCE(test_resource_c);
+
+static int test_resource_c(void)
+{
+ const struct resource *r;
+ FILE *f;
+
+ r = resource_find("test_resource_c");
+ TEST_ASSERT_NOT_NULL(r, "No test_resource_c found");
+ TEST_ASSERT(!strcmp(r->name, "test_resource_c"),
+ "Found resource %s, expected test_resource_c",
+ r->name);
+
+ TEST_ASSERT_SUCCESS(resource_fwrite_file(r, "test_resource.c"),
+ "Failed to to write file %s", r->name);
+
+ f = fopen("test_resource.c", "r");
+ TEST_ASSERT_NOT_NULL(f,
+ "Missing extracted file resource.c");
+ fclose(f);
+ remove("test_resource.c");
+
+ return 0;
+}
+
+#ifdef RTE_APP_TEST_RESOURCE_TAR
+REGISTER_LINKED_RESOURCE(test_resource_tar);
+
+static int test_resource_tar(void)
+{
+ const struct resource *r;
+ FILE *f;
+
+ r = resource_find("test_resource_tar");
+ TEST_ASSERT_NOT_NULL(r, "No test_resource_tar found");
+ TEST_ASSERT(!strcmp(r->name, "test_resource_tar"),
+ "Found resource %s, expected test_resource_tar",
+ r->name);
+
+ TEST_ASSERT_SUCCESS(resource_untar(r),
+ "Failed to to untar %s", r->name);
+
+ f = fopen("test_resource.c", "r");
+ TEST_ASSERT_NOT_NULL(f,
+ "Missing extracted file test_resource.c");
+ fclose(f);
+
+ TEST_ASSERT_SUCCESS(resource_rm_by_tar(r),
+ "Failed to remove extracted contents of %s", r->name);
+ return 0;
+}
+
+#endif /* RTE_APP_TEST_RESOURCE_TAR */
+
+static int test_resource(void)
+{
+ if (test_resource_dpdk())
+ return -1;
+
+ if (test_resource_c())
+ return -1;
+
+#ifdef RTE_APP_TEST_RESOURCE_TAR
+ if (test_resource_tar())
+ return -1;
+#endif /* RTE_APP_TEST_RESOURCE_TAR */
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(resource_autotest, test_resource);
diff --git a/src/spdk/dpdk/app/test/test_rib.c b/src/spdk/dpdk/app/test/test_rib.c
new file mode 100644
index 000000000..3dc48fe1f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rib.c
@@ -0,0 +1,367 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_rib.h>
+
+#include "test.h"
+
+typedef int32_t (*rte_rib_test)(void);
+
+static int32_t test_create_invalid(void);
+static int32_t test_multiple_create(void);
+static int32_t test_free_null(void);
+static int32_t test_insert_invalid(void);
+static int32_t test_get_fn(void);
+static int32_t test_basic(void);
+static int32_t test_tree_traversal(void);
+
+#define MAX_DEPTH 32
+#define MAX_RULES (1 << 22)
+
+/*
+ * Check that rte_rib_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_create_invalid(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_conf config;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ /* rte_rib_create: rib name == NULL */
+ rib = rte_rib_create(NULL, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_rib_create: config == NULL */
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, NULL);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* socket_id < -1 is invalid */
+ rib = rte_rib_create(__func__, -2, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_rib_create: max_nodes = 0 */
+ config.max_nodes = 0;
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.max_nodes = MAX_RULES;
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Create rib table then delete rib table 10 times
+ * Use a slightly different rules size each time
+ */
+int32_t
+test_multiple_create(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_conf config;
+ int32_t i;
+
+ config.ext_sz = 0;
+
+ for (i = 0; i < 100; i++) {
+ config.max_nodes = MAX_RULES - i;
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+ rte_rib_free(rib);
+ }
+ /* Can not test free so return success */
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_rib_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test_free_null(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_conf config;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ rte_rib_free(rib);
+ rte_rib_free(NULL);
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_rib_insert fails gracefully for incorrect user input arguments
+ */
+int32_t
+test_insert_invalid(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_node *node, *node1;
+ struct rte_rib_conf config;
+ uint32_t ip = RTE_IPV4(0, 0, 0, 0);
+ uint8_t depth = 24;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ /* rte_rib_insert: rib == NULL */
+ node = rte_rib_insert(NULL, ip, depth);
+ RTE_TEST_ASSERT(node == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /*Create valid rib to use in rest of test. */
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ /* rte_rib_insert: depth > MAX_DEPTH */
+ node = rte_rib_insert(rib, ip, MAX_DEPTH + 1);
+ RTE_TEST_ASSERT(node == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* insert the same ip/depth twice*/
+ node = rte_rib_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+ node1 = rte_rib_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node1 == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ rte_rib_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_rib_node access functions with incorrect input.
+ * After call rte_rib_node access functions with correct args
+ * and check the return values for correctness
+ */
+int32_t
+test_get_fn(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_node *node;
+ struct rte_rib_conf config;
+ void *ext;
+ uint32_t ip = RTE_IPV4(192, 0, 2, 0);
+ uint32_t ip_ret;
+ uint64_t nh_set = 10;
+ uint64_t nh_ret;
+ uint8_t depth = 24;
+ uint8_t depth_ret;
+ int ret;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ /* test rte_rib_get_ip() with incorrect args */
+ ret = rte_rib_get_ip(NULL, &ip_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib_get_ip(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib_get_depth() with incorrect args */
+ ret = rte_rib_get_depth(NULL, &depth_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib_get_depth(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib_set_nh() with incorrect args */
+ ret = rte_rib_set_nh(NULL, nh_set);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib_get_nh() with incorrect args */
+ ret = rte_rib_get_nh(NULL, &nh_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib_get_nh(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib_get_ext() with incorrect args */
+ ext = rte_rib_get_ext(NULL);
+ RTE_TEST_ASSERT(ext == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* check the return values */
+ ret = rte_rib_get_ip(node, &ip_ret);
+ RTE_TEST_ASSERT((ret == 0) && (ip_ret == ip),
+ "Failed to get proper node ip\n");
+ ret = rte_rib_get_depth(node, &depth_ret);
+ RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
+ "Failed to get proper node depth\n");
+ ret = rte_rib_set_nh(node, nh_set);
+ RTE_TEST_ASSERT(ret == 0,
+ "Failed to set rte_rib_node nexthop\n");
+ ret = rte_rib_get_nh(node, &nh_ret);
+ RTE_TEST_ASSERT((ret == 0) && (nh_ret == nh_set),
+ "Failed to get proper nexthop\n");
+
+ rte_rib_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call insert, lookup/lookup_exact and delete for a single rule
+ */
+int32_t
+test_basic(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_node *node;
+ struct rte_rib_conf config;
+
+ uint32_t ip = RTE_IPV4(192, 0, 2, 0);
+ uint64_t next_hop_add = 10;
+ uint64_t next_hop_return;
+ uint8_t depth = 24;
+ int ret;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ ret = rte_rib_set_nh(node, next_hop_add);
+ RTE_TEST_ASSERT(ret == 0,
+ "Failed to set rte_rib_node field\n");
+
+ node = rte_rib_lookup(rib, ip);
+ RTE_TEST_ASSERT(node != NULL, "Failed to lookup\n");
+
+ ret = rte_rib_get_nh(node, &next_hop_return);
+ RTE_TEST_ASSERT((ret == 0) && (next_hop_add == next_hop_return),
+ "Failed to get proper nexthop\n");
+
+ node = rte_rib_lookup_exact(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL,
+ "Failed to lookup\n");
+
+ ret = rte_rib_get_nh(node, &next_hop_return);
+ RTE_TEST_ASSERT((ret == 0) && (next_hop_add == next_hop_return),
+ "Failed to get proper nexthop\n");
+
+ rte_rib_remove(rib, ip, depth);
+
+ node = rte_rib_lookup(rib, ip);
+ RTE_TEST_ASSERT(node == NULL,
+ "Lookup returns non existent rule\n");
+ node = rte_rib_lookup_exact(rib, ip, depth);
+ RTE_TEST_ASSERT(node == NULL,
+ "Lookup returns non existent rule\n");
+
+ rte_rib_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+int32_t
+test_tree_traversal(void)
+{
+ struct rte_rib *rib = NULL;
+ struct rte_rib_node *node;
+ struct rte_rib_conf config;
+
+ uint32_t ip1 = RTE_IPV4(10, 10, 10, 0);
+ uint32_t ip2 = RTE_IPV4(10, 10, 130, 80);
+ uint8_t depth = 30;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib_insert(rib, ip1, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ node = rte_rib_insert(rib, ip2, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ node = NULL;
+ node = rte_rib_get_nxt(rib, RTE_IPV4(10, 10, 130, 0), 24, node,
+ RTE_RIB_GET_NXT_ALL);
+ RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
+
+ rte_rib_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite rib_tests = {
+ .suite_name = "rib autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_create_invalid),
+ TEST_CASE(test_free_null),
+ TEST_CASE(test_insert_invalid),
+ TEST_CASE(test_get_fn),
+ TEST_CASE(test_basic),
+ TEST_CASE(test_tree_traversal),
+ TEST_CASES_END()
+ }
+};
+
+static struct unit_test_suite rib_slow_tests = {
+ .suite_name = "rib slow autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_multiple_create),
+ TEST_CASES_END()
+ }
+};
+
+/*
+ * Do all unit tests.
+ */
+static int
+test_rib(void)
+{
+ return unit_test_suite_runner(&rib_tests);
+}
+
+static int
+test_slow_rib(void)
+{
+ return unit_test_suite_runner(&rib_slow_tests);
+}
+
+REGISTER_TEST_COMMAND(rib_autotest, test_rib);
+REGISTER_TEST_COMMAND(rib_slow_autotest, test_slow_rib);
diff --git a/src/spdk/dpdk/app/test/test_rib6.c b/src/spdk/dpdk/app/test/test_rib6.c
new file mode 100644
index 000000000..c77df1129
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rib6.c
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <rte_ip.h>
+#include <rte_rib6.h>
+
+#include "test.h"
+
+typedef int32_t (*rte_rib6_test)(void);
+
+static int32_t test_create_invalid(void);
+static int32_t test_multiple_create(void);
+static int32_t test_free_null(void);
+static int32_t test_insert_invalid(void);
+static int32_t test_get_fn(void);
+static int32_t test_basic(void);
+static int32_t test_tree_traversal(void);
+
+#define MAX_DEPTH 128
+#define MAX_RULES (1 << 22)
+
+/*
+ * Check that rte_rib6_create fails gracefully for incorrect user input
+ * arguments
+ */
+int32_t
+test_create_invalid(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_conf config;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ /* rte_rib6_create: rib name == NULL */
+ rib = rte_rib6_create(NULL, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_rib6_create: config == NULL */
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, NULL);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* socket_id < -1 is invalid */
+ rib = rte_rib6_create(__func__, -2, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* rte_rib6_create: max_nodes = 0 */
+ config.max_nodes = 0;
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib == NULL,
+ "Call succeeded with invalid parameters\n");
+ config.max_nodes = MAX_RULES;
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Create rib table then delete rib table 10 times
+ * Use a slightly different rules size each time
+ */
+int32_t
+test_multiple_create(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_conf config;
+ int32_t i;
+
+ config.ext_sz = 0;
+
+ for (i = 0; i < 100; i++) {
+ config.max_nodes = MAX_RULES - i;
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+ rte_rib6_free(rib);
+ }
+ /* Can not test free so return success */
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_rib6_free for NULL pointer user input. Note: free has no return and
+ * therefore it is impossible to check for failure but this test is added to
+ * increase function coverage metrics and to validate that freeing null does
+ * not crash.
+ */
+int32_t
+test_free_null(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_conf config;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ rte_rib6_free(rib);
+ rte_rib6_free(NULL);
+ return TEST_SUCCESS;
+}
+
+/*
+ * Check that rte_rib6_insert fails gracefully
+ * for incorrect user input arguments
+ */
+int32_t
+test_insert_invalid(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_node *node, *node1;
+ struct rte_rib6_conf config;
+ uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {0};
+ uint8_t depth = 24;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ /* rte_rib6_insert: rib == NULL */
+ node = rte_rib6_insert(NULL, ip, depth);
+ RTE_TEST_ASSERT(node == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /*Create valid rib to use in rest of test. */
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ /* rte_rib6_insert: depth > MAX_DEPTH */
+ node = rte_rib6_insert(rib, ip, MAX_DEPTH + 1);
+ RTE_TEST_ASSERT(node == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* insert the same ip/depth twice*/
+ node = rte_rib6_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+ node1 = rte_rib6_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node1 == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ rte_rib6_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call rte_rib6_node access functions with incorrect input.
+ * After call rte_rib6_node access functions with correct args
+ * and check the return values for correctness
+ */
+int32_t
+test_get_fn(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_node *node;
+ struct rte_rib6_conf config;
+ void *ext;
+ uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t ip_ret[RTE_RIB6_IPV6_ADDR_SIZE];
+ uint64_t nh_set = 10;
+ uint64_t nh_ret;
+ uint8_t depth = 24;
+ uint8_t depth_ret;
+ int ret;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib6_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ /* test rte_rib6_get_ip() with incorrect args */
+ ret = rte_rib6_get_ip(NULL, ip_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib6_get_ip(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib6_get_depth() with incorrect args */
+ ret = rte_rib6_get_depth(NULL, &depth_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib6_get_depth(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib6_set_nh() with incorrect args */
+ ret = rte_rib6_set_nh(NULL, nh_set);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib6_get_nh() with incorrect args */
+ ret = rte_rib6_get_nh(NULL, &nh_ret);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+ ret = rte_rib6_get_nh(node, NULL);
+ RTE_TEST_ASSERT(ret < 0,
+ "Call succeeded with invalid parameters\n");
+
+ /* test rte_rib6_get_ext() with incorrect args */
+ ext = rte_rib6_get_ext(NULL);
+ RTE_TEST_ASSERT(ext == NULL,
+ "Call succeeded with invalid parameters\n");
+
+ /* check the return values */
+ ret = rte_rib6_get_ip(node, ip_ret);
+ RTE_TEST_ASSERT((ret == 0) && (rte_rib6_is_equal(ip_ret, ip)),
+ "Failed to get proper node ip\n");
+ ret = rte_rib6_get_depth(node, &depth_ret);
+ RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
+ "Failed to get proper node depth\n");
+ ret = rte_rib6_set_nh(node, nh_set);
+ RTE_TEST_ASSERT(ret == 0,
+ "Failed to set rte_rib_node nexthop\n");
+ ret = rte_rib6_get_nh(node, &nh_ret);
+ RTE_TEST_ASSERT((ret == 0) && (nh_ret == nh_set),
+ "Failed to get proper nexthop\n");
+
+ rte_rib6_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+/*
+ * Call insert, lookup/lookup_exact and delete for a single rule
+ */
+int32_t
+test_basic(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_node *node;
+ struct rte_rib6_conf config;
+
+ uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ uint64_t next_hop_add = 10;
+ uint64_t next_hop_return;
+ uint8_t depth = 24;
+ uint32_t status = 0;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib6_insert(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ status = rte_rib6_set_nh(node, next_hop_add);
+ RTE_TEST_ASSERT(status == 0,
+ "Failed to set rte_rib_node field\n");
+
+ node = rte_rib6_lookup(rib, ip);
+ RTE_TEST_ASSERT(node != NULL, "Failed to lookup\n");
+
+ status = rte_rib6_get_nh(node, &next_hop_return);
+ RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
+ "Failed to get proper nexthop\n");
+
+ node = rte_rib6_lookup_exact(rib, ip, depth);
+ RTE_TEST_ASSERT(node != NULL,
+ "Failed to lookup\n");
+
+ status = rte_rib6_get_nh(node, &next_hop_return);
+ RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
+ "Failed to get proper nexthop\n");
+
+ rte_rib6_remove(rib, ip, depth);
+
+ node = rte_rib6_lookup(rib, ip);
+ RTE_TEST_ASSERT(node == NULL,
+ "Lookup returns non existent rule\n");
+ node = rte_rib6_lookup_exact(rib, ip, depth);
+ RTE_TEST_ASSERT(node == NULL,
+ "Lookup returns non existent rule\n");
+
+ rte_rib6_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+int32_t
+test_tree_traversal(void)
+{
+ struct rte_rib6 *rib = NULL;
+ struct rte_rib6_node *node;
+ struct rte_rib6_conf config;
+
+ uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t ip1[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t ip2[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 80};
+ uint8_t depth = 126;
+
+ config.max_nodes = MAX_RULES;
+ config.ext_sz = 0;
+
+ rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
+ RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
+
+ node = rte_rib6_insert(rib, ip1, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+ node = rte_rib6_insert(rib, ip2, depth);
+ RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
+
+ node = NULL;
+ node = rte_rib6_get_nxt(rib, ip, 32, node, RTE_RIB6_GET_NXT_ALL);
+ RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
+
+ rte_rib6_free(rib);
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite rib6_tests = {
+ .suite_name = "rib6 autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_create_invalid),
+ TEST_CASE(test_free_null),
+ TEST_CASE(test_insert_invalid),
+ TEST_CASE(test_get_fn),
+ TEST_CASE(test_basic),
+ TEST_CASE(test_tree_traversal),
+ TEST_CASES_END()
+ }
+};
+
+static struct unit_test_suite rib6_slow_tests = {
+ .suite_name = "rib6 slow autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_multiple_create),
+ TEST_CASES_END()
+ }
+};
+
+/*
+ * Do all unit tests.
+ */
+static int
+test_rib6(void)
+{
+ return unit_test_suite_runner(&rib6_tests);
+}
+
+static int
+test_slow_rib6(void)
+{
+ return unit_test_suite_runner(&rib6_slow_tests);
+}
+
+REGISTER_TEST_COMMAND(rib6_autotest, test_rib6);
+REGISTER_TEST_COMMAND(rib6_slow_autotest, test_slow_rib6);
diff --git a/src/spdk/dpdk/app/test/test_ring.c b/src/spdk/dpdk/app/test/test_ring.c
new file mode 100644
index 000000000..e21557cd9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring.c
@@ -0,0 +1,922 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_malloc.h>
+#include <rte_ring.h>
+#include <rte_ring_elem.h>
+#include <rte_random.h>
+#include <rte_errno.h>
+#include <rte_hexdump.h>
+
+#include "test.h"
+#include "test_ring.h"
+
+/*
+ * Ring
+ * ====
+ *
+ * #. Functional tests. Tests single/bulk/burst, default/SPSC/MPMC,
+ * legacy/custom element size (4B, 8B, 16B, 20B) APIs.
+ * Some tests incorporate unaligned addresses for objects.
+ * The enqueued/dequeued data is validated for correctness.
+ *
+ * #. Performance tests are in test_ring_perf.c
+ */
+
+#define RING_SIZE 4096
+#define MAX_BULK 32
+
+#define TEST_RING_VERIFY(exp) \
+ if (!(exp)) { \
+ printf("error at %s:%d\tcondition " #exp " failed\n", \
+ __func__, __LINE__); \
+ rte_ring_dump(stdout, r); \
+ return -1; \
+ }
+
+#define TEST_RING_FULL_EMTPY_ITER 8
+
+static const int esize[] = {-1, 4, 8, 16, 20};
+
+static void**
+test_ring_inc_ptr(void **obj, int esize, unsigned int n)
+{
+ /* Legacy queue APIs? */
+ if ((esize) == -1)
+ return ((void **)obj) + n;
+ else
+ return (void **)(((uint32_t *)obj) +
+ (n * esize / sizeof(uint32_t)));
+}
+
+static void
+test_ring_mem_init(void *obj, unsigned int count, int esize)
+{
+ unsigned int i;
+
+ /* Legacy queue APIs? */
+ if (esize == -1)
+ for (i = 0; i < count; i++)
+ ((void **)obj)[i] = (void *)(unsigned long)i;
+ else
+ for (i = 0; i < (count * esize / sizeof(uint32_t)); i++)
+ ((uint32_t *)obj)[i] = i;
+}
+
+static void
+test_ring_print_test_string(const char *istr, unsigned int api_type, int esize)
+{
+ printf("\n%s: ", istr);
+
+ if (esize == -1)
+ printf("legacy APIs: ");
+ else
+ printf("elem APIs: element size %dB ", esize);
+
+ if (api_type == TEST_RING_IGNORE_API_TYPE)
+ return;
+
+ if (api_type & TEST_RING_THREAD_DEF)
+ printf(": default enqueue/dequeue: ");
+ else if (api_type & TEST_RING_THREAD_SPSC)
+ printf(": SP/SC: ");
+ else if (api_type & TEST_RING_THREAD_MPMC)
+ printf(": MP/MC: ");
+
+ if (api_type & TEST_RING_ELEM_SINGLE)
+ printf("single\n");
+ else if (api_type & TEST_RING_ELEM_BULK)
+ printf("bulk\n");
+ else if (api_type & TEST_RING_ELEM_BURST)
+ printf("burst\n");
+}
+
+/*
+ * Various negative test cases.
+ */
+static int
+test_ring_negative_tests(void)
+{
+ struct rte_ring *rp = NULL;
+ struct rte_ring *rt = NULL;
+ unsigned int i;
+
+ /* Test with esize not a multiple of 4 */
+ rp = test_ring_create("test_bad_element_size", 23,
+ RING_SIZE + 1, SOCKET_ID_ANY, 0);
+ if (rp != NULL) {
+ printf("Test failed to detect invalid element size\n");
+ goto test_fail;
+ }
+
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ /* Test if ring size is not power of 2 */
+ rp = test_ring_create("test_bad_ring_size", esize[i],
+ RING_SIZE + 1, SOCKET_ID_ANY, 0);
+ if (rp != NULL) {
+ printf("Test failed to detect odd count\n");
+ goto test_fail;
+ }
+
+ /* Test if ring size is exceeding the limit */
+ rp = test_ring_create("test_bad_ring_size", esize[i],
+ RTE_RING_SZ_MASK + 1, SOCKET_ID_ANY, 0);
+ if (rp != NULL) {
+ printf("Test failed to detect limits\n");
+ goto test_fail;
+ }
+
+ /* Tests if lookup returns NULL on non-existing ring */
+ rp = rte_ring_lookup("ring_not_found");
+ if (rp != NULL && rte_errno != ENOENT) {
+ printf("Test failed to detect NULL ring lookup\n");
+ goto test_fail;
+ }
+
+ /* Test to if a non-power of 2 count causes the create
+ * function to fail correctly
+ */
+ rp = test_ring_create("test_ring_count", esize[i], 4097,
+ SOCKET_ID_ANY, 0);
+ if (rp != NULL)
+ goto test_fail;
+
+ rp = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
+ SOCKET_ID_ANY,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (rp == NULL) {
+ printf("test_ring_negative fail to create ring\n");
+ goto test_fail;
+ }
+
+ if (rte_ring_lookup("test_ring_negative") != rp)
+ goto test_fail;
+
+ if (rte_ring_empty(rp) != 1) {
+ printf("test_ring_nagative ring is not empty but it should be\n");
+ goto test_fail;
+ }
+
+ /* Tests if it would always fail to create ring with an used
+ * ring name.
+ */
+ rt = test_ring_create("test_ring_negative", esize[i], RING_SIZE,
+ SOCKET_ID_ANY, 0);
+ if (rt != NULL)
+ goto test_fail;
+
+ rte_ring_free(rp);
+ rp = NULL;
+ }
+
+ return 0;
+
+test_fail:
+
+ rte_ring_free(rp);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
+ * Random number of elements are enqueued and dequeued.
+ */
+static int
+test_ring_burst_bulk_tests1(unsigned int api_type, unsigned int create_flags,
+ const char *tname)
+{
+ struct rte_ring *r;
+ void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
+ int ret;
+ unsigned int i, j;
+ int rand;
+ const unsigned int rsz = RING_SIZE - 1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ test_ring_print_test_string(tname, api_type, esize[i]);
+
+ /* Create the ring */
+ r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
+ RING_SIZE, SOCKET_ID_ANY, create_flags);
+
+ /* alloc dummy object pointers */
+ src = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("Random full/empty test\n");
+
+ for (j = 0; j != TEST_RING_FULL_EMTPY_ITER; j++) {
+ /* random shift in the ring */
+ rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL);
+ printf("%s: iteration %u, random shift: %u;\n",
+ __func__, i, rand);
+ ret = test_ring_enqueue(r, cur_src, esize[i], rand,
+ api_type);
+ TEST_RING_VERIFY(ret != 0);
+
+ ret = test_ring_dequeue(r, cur_dst, esize[i], rand,
+ api_type);
+ TEST_RING_VERIFY(ret == rand);
+
+ /* fill the ring */
+ ret = test_ring_enqueue(r, cur_src, esize[i], rsz,
+ api_type);
+ TEST_RING_VERIFY(ret != 0);
+
+ TEST_RING_VERIFY(rte_ring_free_count(r) == 0);
+ TEST_RING_VERIFY(rsz == rte_ring_count(r));
+ TEST_RING_VERIFY(rte_ring_full(r));
+ TEST_RING_VERIFY(rte_ring_empty(r) == 0);
+
+ /* empty the ring */
+ ret = test_ring_dequeue(r, cur_dst, esize[i], rsz,
+ api_type);
+ TEST_RING_VERIFY(ret == (int)rsz);
+ TEST_RING_VERIFY(rsz == rte_ring_free_count(r));
+ TEST_RING_VERIFY(rte_ring_count(r) == 0);
+ TEST_RING_VERIFY(rte_ring_full(r) == 0);
+ TEST_RING_VERIFY(rte_ring_empty(r));
+
+ /* check data */
+ TEST_RING_VERIFY(memcmp(src, dst, rsz) == 0);
+ }
+
+ /* Free memory before test completed */
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ r = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
+ * Sequence of simple enqueues/dequeues and validate the enqueued and
+ * dequeued data.
+ */
+static int
+test_ring_burst_bulk_tests2(unsigned int api_type, unsigned int create_flags,
+ const char *tname)
+{
+ struct rte_ring *r;
+ void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
+ int ret;
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ test_ring_print_test_string(tname, api_type, esize[i]);
+
+ /* Create the ring */
+ r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
+ RING_SIZE, SOCKET_ID_ANY, create_flags);
+
+ /* alloc dummy object pointers */
+ src = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("enqueue 1 obj\n");
+ ret = test_ring_enqueue(r, cur_src, esize[i], 1, api_type);
+ if (ret != 1)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i], 1);
+
+ printf("enqueue 2 objs\n");
+ ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
+ if (ret != 2)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
+
+ printf("enqueue MAX_BULK objs\n");
+ ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK);
+
+ printf("dequeue 1 obj\n");
+ ret = test_ring_dequeue(r, cur_dst, esize[i], 1, api_type);
+ if (ret != 1)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 1);
+
+ printf("dequeue 2 objs\n");
+ ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
+ if (ret != 2)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
+
+ printf("dequeue MAX_BULK objs\n");
+ ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK);
+
+ /* check data */
+ if (memcmp(src, dst, cur_dst - dst)) {
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
+ printf("data after dequeue is not the same\n");
+ goto fail;
+ }
+
+ /* Free memory before test completed */
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ r = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
+ * Enqueue and dequeue to cover the entire ring length.
+ */
+static int
+test_ring_burst_bulk_tests3(unsigned int api_type, unsigned int create_flags,
+ const char *tname)
+{
+ struct rte_ring *r;
+ void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
+ int ret;
+ unsigned int i, j;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ test_ring_print_test_string(tname, api_type, esize[i]);
+
+ /* Create the ring */
+ r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
+ RING_SIZE, SOCKET_ID_ANY, create_flags);
+
+ /* alloc dummy object pointers */
+ src = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("fill and empty the ring\n");
+ for (j = 0; j < RING_SIZE / MAX_BULK; j++) {
+ ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i],
+ MAX_BULK);
+
+ ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
+ MAX_BULK);
+ }
+
+ /* check data */
+ if (memcmp(src, dst, cur_dst - dst)) {
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
+ printf("data after dequeue is not the same\n");
+ goto fail;
+ }
+
+ /* Free memory before test completed */
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ r = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Burst and bulk operations with sp/sc, mp/mc and default (during creation)
+ * Enqueue till the ring is full and dequeue till the ring becomes empty.
+ */
+static int
+test_ring_burst_bulk_tests4(unsigned int api_type, unsigned int create_flags,
+ const char *tname)
+{
+ struct rte_ring *r;
+ void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL;
+ int ret;
+ unsigned int i, j;
+ unsigned int num_elems;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ test_ring_print_test_string(tname, api_type, esize[i]);
+
+ /* Create the ring */
+ r = test_ring_create("test_ring_burst_bulk_tests", esize[i],
+ RING_SIZE, SOCKET_ID_ANY, create_flags);
+
+ /* alloc dummy object pointers */
+ src = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (src == NULL)
+ goto fail;
+ test_ring_mem_init(src, RING_SIZE * 2, esize[i]);
+ cur_src = src;
+
+ /* alloc some room for copied objects */
+ dst = test_ring_calloc(RING_SIZE * 2, esize[i]);
+ if (dst == NULL)
+ goto fail;
+ cur_dst = dst;
+
+ printf("Test enqueue without enough memory space\n");
+ for (j = 0; j < (RING_SIZE/MAX_BULK - 1); j++) {
+ ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i],
+ MAX_BULK);
+ }
+
+ printf("Enqueue 2 objects, free entries = MAX_BULK - 2\n");
+ ret = test_ring_enqueue(r, cur_src, esize[i], 2, api_type);
+ if (ret != 2)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i], 2);
+
+ printf("Enqueue the remaining entries = MAX_BULK - 3\n");
+ /* Bulk APIs enqueue exact number of elements */
+ if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
+ num_elems = MAX_BULK - 3;
+ else
+ num_elems = MAX_BULK;
+ /* Always one free entry left */
+ ret = test_ring_enqueue(r, cur_src, esize[i], num_elems,
+ api_type);
+ if (ret != MAX_BULK - 3)
+ goto fail;
+ cur_src = test_ring_inc_ptr(cur_src, esize[i], MAX_BULK - 3);
+
+ printf("Test if ring is full\n");
+ if (rte_ring_full(r) != 1)
+ goto fail;
+
+ printf("Test enqueue for a full entry\n");
+ ret = test_ring_enqueue(r, cur_src, esize[i], MAX_BULK,
+ api_type);
+ if (ret != 0)
+ goto fail;
+
+ printf("Test dequeue without enough objects\n");
+ for (j = 0; j < RING_SIZE / MAX_BULK - 1; j++) {
+ ret = test_ring_dequeue(r, cur_dst, esize[i], MAX_BULK,
+ api_type);
+ if (ret != MAX_BULK)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i],
+ MAX_BULK);
+ }
+
+ /* Available memory space for the exact MAX_BULK entries */
+ ret = test_ring_dequeue(r, cur_dst, esize[i], 2, api_type);
+ if (ret != 2)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i], 2);
+
+ /* Bulk APIs enqueue exact number of elements */
+ if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
+ num_elems = MAX_BULK - 3;
+ else
+ num_elems = MAX_BULK;
+ ret = test_ring_dequeue(r, cur_dst, esize[i], num_elems,
+ api_type);
+ if (ret != MAX_BULK - 3)
+ goto fail;
+ cur_dst = test_ring_inc_ptr(cur_dst, esize[i], MAX_BULK - 3);
+
+ printf("Test if ring is empty\n");
+ /* Check if ring is empty */
+ if (rte_ring_empty(r) != 1)
+ goto fail;
+
+ /* check data */
+ if (memcmp(src, dst, cur_dst - dst)) {
+ rte_hexdump(stdout, "src", src, cur_src - src);
+ rte_hexdump(stdout, "dst", dst, cur_dst - dst);
+ printf("data after dequeue is not the same\n");
+ goto fail;
+ }
+
+ /* Free memory before test completed */
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ r = NULL;
+ src = NULL;
+ dst = NULL;
+ }
+
+ return 0;
+fail:
+ rte_ring_free(r);
+ rte_free(src);
+ rte_free(dst);
+ return -1;
+}
+
+/*
+ * Test default, single element, bulk and burst APIs
+ */
+static int
+test_ring_basic_ex(void)
+{
+ int ret = -1;
+ unsigned int i, j;
+ struct rte_ring *rp = NULL;
+ void *obj = NULL;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ obj = test_ring_calloc(RING_SIZE, esize[i]);
+ if (obj == NULL) {
+ printf("%s: failed to alloc memory\n", __func__);
+ goto fail_test;
+ }
+
+ rp = test_ring_create("test_ring_basic_ex", esize[i], RING_SIZE,
+ SOCKET_ID_ANY,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (rp == NULL) {
+ printf("%s: failed to create ring\n", __func__);
+ goto fail_test;
+ }
+
+ if (rte_ring_lookup("test_ring_basic_ex") != rp) {
+ printf("%s: failed to find ring\n", __func__);
+ goto fail_test;
+ }
+
+ if (rte_ring_empty(rp) != 1) {
+ printf("%s: ring is not empty but it should be\n",
+ __func__);
+ goto fail_test;
+ }
+
+ printf("%u ring entries are now free\n",
+ rte_ring_free_count(rp));
+
+ for (j = 0; j < RING_SIZE; j++) {
+ test_ring_enqueue(rp, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ }
+
+ if (rte_ring_full(rp) != 1) {
+ printf("%s: ring is not full but it should be\n",
+ __func__);
+ goto fail_test;
+ }
+
+ for (j = 0; j < RING_SIZE; j++) {
+ test_ring_dequeue(rp, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ }
+
+ if (rte_ring_empty(rp) != 1) {
+ printf("%s: ring is not empty but it should be\n",
+ __func__);
+ goto fail_test;
+ }
+
+ /* Following tests use the configured flags to decide
+ * SP/SC or MP/MC.
+ */
+ /* Covering the ring burst operation */
+ ret = test_ring_enqueue(rp, obj, esize[i], 2,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
+ if (ret != 2) {
+ printf("%s: rte_ring_enqueue_burst fails\n", __func__);
+ goto fail_test;
+ }
+
+ ret = test_ring_dequeue(rp, obj, esize[i], 2,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
+ if (ret != 2) {
+ printf("%s: rte_ring_dequeue_burst fails\n", __func__);
+ goto fail_test;
+ }
+
+ /* Covering the ring bulk operation */
+ ret = test_ring_enqueue(rp, obj, esize[i], 2,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
+ if (ret != 2) {
+ printf("%s: rte_ring_enqueue_bulk fails\n", __func__);
+ goto fail_test;
+ }
+
+ ret = test_ring_dequeue(rp, obj, esize[i], 2,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK);
+ if (ret != 2) {
+ printf("%s: rte_ring_dequeue_bulk fails\n", __func__);
+ goto fail_test;
+ }
+
+ rte_ring_free(rp);
+ rte_free(obj);
+ rp = NULL;
+ obj = NULL;
+ }
+
+ return 0;
+
+fail_test:
+ rte_ring_free(rp);
+ if (obj != NULL)
+ rte_free(obj);
+
+ return -1;
+}
+
+/*
+ * Basic test cases with exact size ring.
+ */
+static int
+test_ring_with_exact_size(void)
+{
+ struct rte_ring *std_r = NULL, *exact_sz_r = NULL;
+ void *obj_orig;
+ void *obj;
+ const unsigned int ring_sz = 16;
+ unsigned int i, j;
+ int ret = -1;
+
+ for (i = 0; i < RTE_DIM(esize); i++) {
+ test_ring_print_test_string("Test exact size ring",
+ TEST_RING_IGNORE_API_TYPE,
+ esize[i]);
+
+ /* alloc object pointers. Allocate one extra object
+ * and create an unaligned address.
+ */
+ obj_orig = test_ring_calloc(17, esize[i]);
+ if (obj_orig == NULL)
+ goto test_fail;
+ obj = ((char *)obj_orig) + 1;
+
+ std_r = test_ring_create("std", esize[i], ring_sz,
+ rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (std_r == NULL) {
+ printf("%s: error, can't create std ring\n", __func__);
+ goto test_fail;
+ }
+ exact_sz_r = test_ring_create("exact sz", esize[i], ring_sz,
+ rte_socket_id(),
+ RING_F_SP_ENQ | RING_F_SC_DEQ |
+ RING_F_EXACT_SZ);
+ if (exact_sz_r == NULL) {
+ printf("%s: error, can't create exact size ring\n",
+ __func__);
+ goto test_fail;
+ }
+
+ /*
+ * Check that the exact size ring is bigger than the
+ * standard ring
+ */
+ if (rte_ring_get_size(std_r) >= rte_ring_get_size(exact_sz_r)) {
+ printf("%s: error, std ring (size: %u) is not smaller than exact size one (size %u)\n",
+ __func__,
+ rte_ring_get_size(std_r),
+ rte_ring_get_size(exact_sz_r));
+ goto test_fail;
+ }
+ /*
+ * check that the exact_sz_ring can hold one more element
+ * than the standard ring. (16 vs 15 elements)
+ */
+ for (j = 0; j < ring_sz - 1; j++) {
+ test_ring_enqueue(std_r, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ }
+ ret = test_ring_enqueue(std_r, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ if (ret != -ENOBUFS) {
+ printf("%s: error, unexpected successful enqueue\n",
+ __func__);
+ goto test_fail;
+ }
+ ret = test_ring_enqueue(exact_sz_r, obj, esize[i], 1,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE);
+ if (ret == -ENOBUFS) {
+ printf("%s: error, enqueue failed\n", __func__);
+ goto test_fail;
+ }
+
+ /* check that dequeue returns the expected number of elements */
+ ret = test_ring_dequeue(exact_sz_r, obj, esize[i], ring_sz,
+ TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST);
+ if (ret != (int)ring_sz) {
+ printf("%s: error, failed to dequeue expected nb of elements\n",
+ __func__);
+ goto test_fail;
+ }
+
+ /* check that the capacity function returns expected value */
+ if (rte_ring_get_capacity(exact_sz_r) != ring_sz) {
+ printf("%s: error, incorrect ring capacity reported\n",
+ __func__);
+ goto test_fail;
+ }
+
+ rte_free(obj_orig);
+ rte_ring_free(std_r);
+ rte_ring_free(exact_sz_r);
+ obj_orig = NULL;
+ std_r = NULL;
+ exact_sz_r = NULL;
+ }
+
+ return 0;
+
+test_fail:
+ rte_free(obj_orig);
+ rte_ring_free(std_r);
+ rte_ring_free(exact_sz_r);
+ return -1;
+}
+
+static int
+test_ring(void)
+{
+ int32_t rc;
+ unsigned int i, j;
+ const char *tname;
+
+ static const struct {
+ uint32_t create_flags;
+ const char *name;
+ } test_sync_modes[] = {
+ {
+ RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ,
+ "Test MT_RTS ring",
+ },
+ {
+ RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ,
+ "Test MT_HTS ring",
+ },
+ };
+
+ /* Negative test cases */
+ if (test_ring_negative_tests() < 0)
+ goto test_fail;
+
+ /* Some basic operations */
+ if (test_ring_basic_ex() < 0)
+ goto test_fail;
+
+ if (test_ring_with_exact_size() < 0)
+ goto test_fail;
+
+ /* Burst and bulk operations with sp/sc, mp/mc and default.
+ * The test cases are split into smaller test cases to
+ * help clang compile faster.
+ */
+ tname = "Test standard ring";
+
+ for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
+ for (i = TEST_RING_THREAD_DEF;
+ i <= TEST_RING_THREAD_MPMC; i <<= 1)
+ if (test_ring_burst_bulk_tests1(i | j, 0, tname) < 0)
+ goto test_fail;
+
+ for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
+ for (i = TEST_RING_THREAD_DEF;
+ i <= TEST_RING_THREAD_MPMC; i <<= 1)
+ if (test_ring_burst_bulk_tests2(i | j, 0, tname) < 0)
+ goto test_fail;
+
+ for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
+ for (i = TEST_RING_THREAD_DEF;
+ i <= TEST_RING_THREAD_MPMC; i <<= 1)
+ if (test_ring_burst_bulk_tests3(i | j, 0, tname) < 0)
+ goto test_fail;
+
+ for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST; j <<= 1)
+ for (i = TEST_RING_THREAD_DEF;
+ i <= TEST_RING_THREAD_MPMC; i <<= 1)
+ if (test_ring_burst_bulk_tests4(i | j, 0, tname) < 0)
+ goto test_fail;
+
+ /* Burst and bulk operations with MT_RTS and MT_HTS sync modes */
+ for (i = 0; i != RTE_DIM(test_sync_modes); i++) {
+ for (j = TEST_RING_ELEM_BULK; j <= TEST_RING_ELEM_BURST;
+ j <<= 1) {
+
+ rc = test_ring_burst_bulk_tests1(
+ TEST_RING_THREAD_DEF | j,
+ test_sync_modes[i].create_flags,
+ test_sync_modes[i].name);
+ if (rc < 0)
+ goto test_fail;
+
+ rc = test_ring_burst_bulk_tests2(
+ TEST_RING_THREAD_DEF | j,
+ test_sync_modes[i].create_flags,
+ test_sync_modes[i].name);
+ if (rc < 0)
+ goto test_fail;
+
+ rc = test_ring_burst_bulk_tests3(
+ TEST_RING_THREAD_DEF | j,
+ test_sync_modes[i].create_flags,
+ test_sync_modes[i].name);
+ if (rc < 0)
+ goto test_fail;
+
+ rc = test_ring_burst_bulk_tests3(
+ TEST_RING_THREAD_DEF | j,
+ test_sync_modes[i].create_flags,
+ test_sync_modes[i].name);
+ if (rc < 0)
+ goto test_fail;
+ }
+ }
+
+ /* dump the ring status */
+ rte_ring_list_dump(stdout);
+
+ return 0;
+
+test_fail:
+
+ return -1;
+}
+
+REGISTER_TEST_COMMAND(ring_autotest, test_ring);
diff --git a/src/spdk/dpdk/app/test/test_ring.h b/src/spdk/dpdk/app/test/test_ring.h
new file mode 100644
index 000000000..aa6ae67ca
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring.h
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Arm Limited
+ */
+
+#include <rte_malloc.h>
+#include <rte_ring.h>
+#include <rte_ring_elem.h>
+
+/* API type to call
+ * rte_ring_<sp/mp or sc/mc>_enqueue_<bulk/burst>
+ * TEST_RING_THREAD_DEF - Uses configured SPSC/MPMC calls
+ * TEST_RING_THREAD_SPSC - Calls SP or SC API
+ * TEST_RING_THREAD_MPMC - Calls MP or MC API
+ */
+#define TEST_RING_THREAD_DEF 1
+#define TEST_RING_THREAD_SPSC 2
+#define TEST_RING_THREAD_MPMC 4
+
+/* API type to call
+ * TEST_RING_ELEM_SINGLE - Calls single element APIs
+ * TEST_RING_ELEM_BULK - Calls bulk APIs
+ * TEST_RING_ELEM_BURST - Calls burst APIs
+ */
+#define TEST_RING_ELEM_SINGLE 8
+#define TEST_RING_ELEM_BULK 16
+#define TEST_RING_ELEM_BURST 32
+
+#define TEST_RING_IGNORE_API_TYPE ~0U
+
+/* This function is placed here as it is required for both
+ * performance and functional tests.
+ */
+static inline struct rte_ring*
+test_ring_create(const char *name, int esize, unsigned int count,
+ int socket_id, unsigned int flags)
+{
+ /* Legacy queue APIs? */
+ if ((esize) == -1)
+ return rte_ring_create((name), (count), (socket_id), (flags));
+ else
+ return rte_ring_create_elem((name), (esize), (count),
+ (socket_id), (flags));
+}
+
+static __rte_always_inline unsigned int
+test_ring_enqueue(struct rte_ring *r, void **obj, int esize, unsigned int n,
+ unsigned int api_type)
+{
+ /* Legacy queue APIs? */
+ if ((esize) == -1)
+ switch (api_type) {
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
+ return rte_ring_enqueue(r, obj);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_sp_enqueue(r, obj);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_mp_enqueue(r, obj);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
+ return rte_ring_enqueue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
+ return rte_ring_sp_enqueue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
+ return rte_ring_mp_enqueue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
+ return rte_ring_enqueue_burst(r, obj, n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
+ return rte_ring_sp_enqueue_burst(r, obj, n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
+ return rte_ring_mp_enqueue_burst(r, obj, n, NULL);
+ default:
+ printf("Invalid API type\n");
+ return 0;
+ }
+ else
+ switch (api_type) {
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
+ return rte_ring_enqueue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_sp_enqueue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_mp_enqueue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
+ return rte_ring_enqueue_bulk_elem(r, obj, esize, n,
+ NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
+ return rte_ring_sp_enqueue_bulk_elem(r, obj, esize, n,
+ NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
+ return rte_ring_mp_enqueue_bulk_elem(r, obj, esize, n,
+ NULL);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
+ return rte_ring_enqueue_burst_elem(r, obj, esize, n,
+ NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
+ return rte_ring_sp_enqueue_burst_elem(r, obj, esize, n,
+ NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
+ return rte_ring_mp_enqueue_burst_elem(r, obj, esize, n,
+ NULL);
+ default:
+ printf("Invalid API type\n");
+ return 0;
+ }
+}
+
+static __rte_always_inline unsigned int
+test_ring_dequeue(struct rte_ring *r, void **obj, int esize, unsigned int n,
+ unsigned int api_type)
+{
+ /* Legacy queue APIs? */
+ if ((esize) == -1)
+ switch (api_type) {
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
+ return rte_ring_dequeue(r, obj);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_sc_dequeue(r, obj);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_mc_dequeue(r, obj);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
+ return rte_ring_dequeue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
+ return rte_ring_sc_dequeue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
+ return rte_ring_mc_dequeue_bulk(r, obj, n, NULL);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
+ return rte_ring_dequeue_burst(r, obj, n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
+ return rte_ring_sc_dequeue_burst(r, obj, n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
+ return rte_ring_mc_dequeue_burst(r, obj, n, NULL);
+ default:
+ printf("Invalid API type\n");
+ return 0;
+ }
+ else
+ switch (api_type) {
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_SINGLE):
+ return rte_ring_dequeue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_sc_dequeue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE):
+ return rte_ring_mc_dequeue_elem(r, obj, esize);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BULK):
+ return rte_ring_dequeue_bulk_elem(r, obj, esize,
+ n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK):
+ return rte_ring_sc_dequeue_bulk_elem(r, obj, esize,
+ n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK):
+ return rte_ring_mc_dequeue_bulk_elem(r, obj, esize,
+ n, NULL);
+ case (TEST_RING_THREAD_DEF | TEST_RING_ELEM_BURST):
+ return rte_ring_dequeue_burst_elem(r, obj, esize,
+ n, NULL);
+ case (TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST):
+ return rte_ring_sc_dequeue_burst_elem(r, obj, esize,
+ n, NULL);
+ case (TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST):
+ return rte_ring_mc_dequeue_burst_elem(r, obj, esize,
+ n, NULL);
+ default:
+ printf("Invalid API type\n");
+ return 0;
+ }
+}
+
+/* This function is placed here as it is required for both
+ * performance and functional tests.
+ */
+static __rte_always_inline void *
+test_ring_calloc(unsigned int rsize, int esize)
+{
+ unsigned int sz;
+ void *p;
+
+ /* Legacy queue APIs? */
+ if (esize == -1)
+ sz = sizeof(void *);
+ else
+ sz = esize;
+
+ p = rte_zmalloc(NULL, rsize * sz, RTE_CACHE_LINE_SIZE);
+ if (p == NULL)
+ printf("Failed to allocate memory\n");
+
+ return p;
+}
diff --git a/src/spdk/dpdk/app/test/test_ring_hts_stress.c b/src/spdk/dpdk/app/test/test_ring_hts_stress.c
new file mode 100644
index 000000000..edc9175cb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_hts_stress.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress_impl.h"
+
+static inline uint32_t
+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,
+ uint32_t *avail)
+{
+ return rte_ring_mc_hts_dequeue_bulk(r, obj, n, avail);
+}
+
+static inline uint32_t
+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,
+ uint32_t *free)
+{
+ return rte_ring_mp_hts_enqueue_bulk(r, obj, n, free);
+}
+
+static int
+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num)
+{
+ return rte_ring_init(r, name, num,
+ RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ);
+}
+
+const struct test test_ring_hts_stress = {
+ .name = "MT_HTS",
+ .nb_case = RTE_DIM(tests),
+ .cases = tests,
+};
diff --git a/src/spdk/dpdk/app/test/test_ring_mpmc_stress.c b/src/spdk/dpdk/app/test/test_ring_mpmc_stress.c
new file mode 100644
index 000000000..1524b0248
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_mpmc_stress.c
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress_impl.h"
+
+static inline uint32_t
+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,
+ uint32_t *avail)
+{
+ return rte_ring_mc_dequeue_bulk(r, obj, n, avail);
+}
+
+static inline uint32_t
+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,
+ uint32_t *free)
+{
+ return rte_ring_mp_enqueue_bulk(r, obj, n, free);
+}
+
+static int
+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num)
+{
+ return rte_ring_init(r, name, num, 0);
+}
+
+const struct test test_ring_mpmc_stress = {
+ .name = "MP/MC",
+ .nb_case = RTE_DIM(tests),
+ .cases = tests,
+};
diff --git a/src/spdk/dpdk/app/test/test_ring_peek_stress.c b/src/spdk/dpdk/app/test/test_ring_peek_stress.c
new file mode 100644
index 000000000..cfc82d728
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_peek_stress.c
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress_impl.h"
+#include <rte_ring_elem.h>
+
+static inline uint32_t
+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,
+ uint32_t *avail)
+{
+ uint32_t m;
+
+ m = rte_ring_dequeue_bulk_start(r, obj, n, avail);
+ n = (m == n) ? n : 0;
+ rte_ring_dequeue_finish(r, n);
+ return n;
+}
+
+static inline uint32_t
+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,
+ uint32_t *free)
+{
+ uint32_t m;
+
+ m = rte_ring_enqueue_bulk_start(r, n, free);
+ n = (m == n) ? n : 0;
+ rte_ring_enqueue_finish(r, obj, n);
+ return n;
+}
+
+static int
+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num)
+{
+ return rte_ring_init(r, name, num,
+ RING_F_MP_HTS_ENQ | RING_F_MC_HTS_DEQ);
+}
+
+const struct test test_ring_peek_stress = {
+ .name = "MT_PEEK",
+ .nb_case = RTE_DIM(tests),
+ .cases = tests,
+};
diff --git a/src/spdk/dpdk/app/test/test_ring_perf.c b/src/spdk/dpdk/app/test/test_ring_perf.c
new file mode 100644
index 000000000..ee21faf71
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_perf.c
@@ -0,0 +1,582 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ * Copyright(c) 2019 Arm Limited
+ */
+
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <rte_ring.h>
+#include <rte_cycles.h>
+#include <rte_launch.h>
+#include <rte_pause.h>
+#include <string.h>
+
+#include "test.h"
+#include "test_ring.h"
+
+/*
+ * Ring performance test cases, measures performance of various operations
+ * using rdtsc for legacy and 16B size ring elements.
+ */
+
+#define RING_NAME "RING_PERF"
+#define RING_SIZE 4096
+#define MAX_BURST 32
+
+/*
+ * the sizes to enqueue and dequeue in testing
+ * (marked volatile so they won't be seen as compile-time constants)
+ */
+static const volatile unsigned bulk_sizes[] = { 8, 32 };
+
+struct lcore_pair {
+ unsigned c1, c2;
+};
+
+static volatile unsigned lcore_count = 0;
+
+static void
+test_ring_print_test_string(unsigned int api_type, int esize,
+ unsigned int bsz, double value)
+{
+ if (esize == -1)
+ printf("legacy APIs");
+ else
+ printf("elem APIs: element size %dB", esize);
+
+ if (api_type == TEST_RING_IGNORE_API_TYPE)
+ return;
+
+ if ((api_type & TEST_RING_THREAD_DEF) == TEST_RING_THREAD_DEF)
+ printf(": default enqueue/dequeue: ");
+ else if ((api_type & TEST_RING_THREAD_SPSC) == TEST_RING_THREAD_SPSC)
+ printf(": SP/SC: ");
+ else if ((api_type & TEST_RING_THREAD_MPMC) == TEST_RING_THREAD_MPMC)
+ printf(": MP/MC: ");
+
+ if ((api_type & TEST_RING_ELEM_SINGLE) == TEST_RING_ELEM_SINGLE)
+ printf("single: ");
+ else if ((api_type & TEST_RING_ELEM_BULK) == TEST_RING_ELEM_BULK)
+ printf("bulk (size: %u): ", bsz);
+ else if ((api_type & TEST_RING_ELEM_BURST) == TEST_RING_ELEM_BURST)
+ printf("burst (size: %u): ", bsz);
+
+ printf("%.2F\n", value);
+}
+
+/**** Functions to analyse our core mask to get cores for different tests ***/
+
+static int
+get_two_hyperthreads(struct lcore_pair *lcp)
+{
+ unsigned id1, id2;
+ unsigned c1, c2, s1, s2;
+ RTE_LCORE_FOREACH(id1) {
+ /* inner loop just re-reads all id's. We could skip the first few
+ * elements, but since number of cores is small there is little point
+ */
+ RTE_LCORE_FOREACH(id2) {
+ if (id1 == id2)
+ continue;
+
+ c1 = rte_lcore_to_cpu_id(id1);
+ c2 = rte_lcore_to_cpu_id(id2);
+ s1 = rte_lcore_to_socket_id(id1);
+ s2 = rte_lcore_to_socket_id(id2);
+ if ((c1 == c2) && (s1 == s2)){
+ lcp->c1 = id1;
+ lcp->c2 = id2;
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static int
+get_two_cores(struct lcore_pair *lcp)
+{
+ unsigned id1, id2;
+ unsigned c1, c2, s1, s2;
+ RTE_LCORE_FOREACH(id1) {
+ RTE_LCORE_FOREACH(id2) {
+ if (id1 == id2)
+ continue;
+
+ c1 = rte_lcore_to_cpu_id(id1);
+ c2 = rte_lcore_to_cpu_id(id2);
+ s1 = rte_lcore_to_socket_id(id1);
+ s2 = rte_lcore_to_socket_id(id2);
+ if ((c1 != c2) && (s1 == s2)){
+ lcp->c1 = id1;
+ lcp->c2 = id2;
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+static int
+get_two_sockets(struct lcore_pair *lcp)
+{
+ unsigned id1, id2;
+ unsigned s1, s2;
+ RTE_LCORE_FOREACH(id1) {
+ RTE_LCORE_FOREACH(id2) {
+ if (id1 == id2)
+ continue;
+ s1 = rte_lcore_to_socket_id(id1);
+ s2 = rte_lcore_to_socket_id(id2);
+ if (s1 != s2){
+ lcp->c1 = id1;
+ lcp->c2 = id2;
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+/* Get cycle counts for dequeuing from an empty ring. Should be 2 or 3 cycles */
+static void
+test_empty_dequeue(struct rte_ring *r, const int esize,
+ const unsigned int api_type)
+{
+ const unsigned int iter_shift = 26;
+ const unsigned int iterations = 1 << iter_shift;
+ unsigned int i = 0;
+ void *burst[MAX_BURST];
+
+ const uint64_t start = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ test_ring_dequeue(r, burst, esize, bulk_sizes[0], api_type);
+ const uint64_t end = rte_rdtsc();
+
+ test_ring_print_test_string(api_type, esize, bulk_sizes[0],
+ ((double)(end - start)) / iterations);
+}
+
+/*
+ * for the separate enqueue and dequeue threads they take in one param
+ * and return two. Input = burst size, output = cycle average for sp/sc & mp/mc
+ */
+struct thread_params {
+ struct rte_ring *r;
+ unsigned size; /* input value, the burst size */
+ double spsc, mpmc; /* output value, the single or multi timings */
+};
+
+/*
+ * Helper function to call bulk SP/MP enqueue functions.
+ * flag == 0 -> enqueue
+ * flag == 1 -> dequeue
+ */
+static __rte_always_inline int
+enqueue_dequeue_bulk_helper(const unsigned int flag, const int esize,
+ struct thread_params *p)
+{
+ int ret;
+ const unsigned int iter_shift = 23;
+ const unsigned int iterations = 1 << iter_shift;
+ struct rte_ring *r = p->r;
+ unsigned int bsize = p->size;
+ unsigned int i;
+ void *burst = NULL;
+
+#ifdef RTE_USE_C11_MEM_MODEL
+ if (__atomic_add_fetch(&lcore_count, 1, __ATOMIC_RELAXED) != 2)
+#else
+ if (__sync_add_and_fetch(&lcore_count, 1) != 2)
+#endif
+ while(lcore_count != 2)
+ rte_pause();
+
+ burst = test_ring_calloc(MAX_BURST, esize);
+ if (burst == NULL)
+ return -1;
+
+ const uint64_t sp_start = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ do {
+ if (flag == 0)
+ ret = test_ring_enqueue(r, burst, esize, bsize,
+ TEST_RING_THREAD_SPSC |
+ TEST_RING_ELEM_BULK);
+ else if (flag == 1)
+ ret = test_ring_dequeue(r, burst, esize, bsize,
+ TEST_RING_THREAD_SPSC |
+ TEST_RING_ELEM_BULK);
+ if (ret == 0)
+ rte_pause();
+ } while (!ret);
+ const uint64_t sp_end = rte_rdtsc();
+
+ const uint64_t mp_start = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ do {
+ if (flag == 0)
+ ret = test_ring_enqueue(r, burst, esize, bsize,
+ TEST_RING_THREAD_MPMC |
+ TEST_RING_ELEM_BULK);
+ else if (flag == 1)
+ ret = test_ring_dequeue(r, burst, esize, bsize,
+ TEST_RING_THREAD_MPMC |
+ TEST_RING_ELEM_BULK);
+ if (ret == 0)
+ rte_pause();
+ } while (!ret);
+ const uint64_t mp_end = rte_rdtsc();
+
+ p->spsc = ((double)(sp_end - sp_start))/(iterations * bsize);
+ p->mpmc = ((double)(mp_end - mp_start))/(iterations * bsize);
+ return 0;
+}
+
+/*
+ * Function that uses rdtsc to measure timing for ring enqueue. Needs pair
+ * thread running dequeue_bulk function
+ */
+static int
+enqueue_bulk(void *p)
+{
+ struct thread_params *params = p;
+
+ return enqueue_dequeue_bulk_helper(0, -1, params);
+}
+
+static int
+enqueue_bulk_16B(void *p)
+{
+ struct thread_params *params = p;
+
+ return enqueue_dequeue_bulk_helper(0, 16, params);
+}
+
+/*
+ * Function that uses rdtsc to measure timing for ring dequeue. Needs pair
+ * thread running enqueue_bulk function
+ */
+static int
+dequeue_bulk(void *p)
+{
+ struct thread_params *params = p;
+
+ return enqueue_dequeue_bulk_helper(1, -1, params);
+}
+
+static int
+dequeue_bulk_16B(void *p)
+{
+ struct thread_params *params = p;
+
+ return enqueue_dequeue_bulk_helper(1, 16, params);
+}
+
+/*
+ * Function that calls the enqueue and dequeue bulk functions on pairs of cores.
+ * used to measure ring perf between hyperthreads, cores and sockets.
+ */
+static int
+run_on_core_pair(struct lcore_pair *cores, struct rte_ring *r, const int esize)
+{
+ lcore_function_t *f1, *f2;
+ struct thread_params param1 = {0}, param2 = {0};
+ unsigned i;
+
+ if (esize == -1) {
+ f1 = enqueue_bulk;
+ f2 = dequeue_bulk;
+ } else {
+ f1 = enqueue_bulk_16B;
+ f2 = dequeue_bulk_16B;
+ }
+
+ for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
+ lcore_count = 0;
+ param1.size = param2.size = bulk_sizes[i];
+ param1.r = param2.r = r;
+ if (cores->c1 == rte_get_master_lcore()) {
+ rte_eal_remote_launch(f2, &param2, cores->c2);
+ f1(&param1);
+ rte_eal_wait_lcore(cores->c2);
+ } else {
+ rte_eal_remote_launch(f1, &param1, cores->c1);
+ rte_eal_remote_launch(f2, &param2, cores->c2);
+ if (rte_eal_wait_lcore(cores->c1) < 0)
+ return -1;
+ if (rte_eal_wait_lcore(cores->c2) < 0)
+ return -1;
+ }
+ test_ring_print_test_string(
+ TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK,
+ esize, bulk_sizes[i], param1.spsc + param2.spsc);
+ test_ring_print_test_string(
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK,
+ esize, bulk_sizes[i], param1.mpmc + param2.mpmc);
+ }
+
+ return 0;
+}
+
+static rte_atomic32_t synchro;
+static uint64_t queue_count[RTE_MAX_LCORE];
+
+#define TIME_MS 100
+
+static int
+load_loop_fn_helper(struct thread_params *p, const int esize)
+{
+ uint64_t time_diff = 0;
+ uint64_t begin = 0;
+ uint64_t hz = rte_get_timer_hz();
+ uint64_t lcount = 0;
+ const unsigned int lcore = rte_lcore_id();
+ struct thread_params *params = p;
+ void *burst = NULL;
+
+ burst = test_ring_calloc(MAX_BURST, esize);
+ if (burst == NULL)
+ return -1;
+
+ /* wait synchro for slaves */
+ if (lcore != rte_get_master_lcore())
+ while (rte_atomic32_read(&synchro) == 0)
+ rte_pause();
+
+ begin = rte_get_timer_cycles();
+ while (time_diff < hz * TIME_MS / 1000) {
+ test_ring_enqueue(params->r, burst, esize, params->size,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
+ test_ring_dequeue(params->r, burst, esize, params->size,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
+ lcount++;
+ time_diff = rte_get_timer_cycles() - begin;
+ }
+ queue_count[lcore] = lcount;
+
+ rte_free(burst);
+
+ return 0;
+}
+
+static int
+load_loop_fn(void *p)
+{
+ struct thread_params *params = p;
+
+ return load_loop_fn_helper(params, -1);
+}
+
+static int
+load_loop_fn_16B(void *p)
+{
+ struct thread_params *params = p;
+
+ return load_loop_fn_helper(params, 16);
+}
+
+static int
+run_on_all_cores(struct rte_ring *r, const int esize)
+{
+ uint64_t total = 0;
+ struct thread_params param;
+ lcore_function_t *lcore_f;
+ unsigned int i, c;
+
+ if (esize == -1)
+ lcore_f = load_loop_fn;
+ else
+ lcore_f = load_loop_fn_16B;
+
+ memset(&param, 0, sizeof(struct thread_params));
+ for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
+ printf("\nBulk enq/dequeue count on size %u\n", bulk_sizes[i]);
+ param.size = bulk_sizes[i];
+ param.r = r;
+
+ /* clear synchro and start slaves */
+ rte_atomic32_set(&synchro, 0);
+ if (rte_eal_mp_remote_launch(lcore_f, &param, SKIP_MASTER) < 0)
+ return -1;
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+ lcore_f(&param);
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_LCORE_FOREACH(c) {
+ printf("Core [%u] count = %"PRIu64"\n",
+ c, queue_count[c]);
+ total += queue_count[c];
+ }
+
+ printf("Total count (size: %u): %"PRIu64"\n",
+ bulk_sizes[i], total);
+ }
+
+ return 0;
+}
+
+/*
+ * Test function that determines how long an enqueue + dequeue of a single item
+ * takes on a single lcore. Result is for comparison with the bulk enq+deq.
+ */
+static int
+test_single_enqueue_dequeue(struct rte_ring *r, const int esize,
+ const unsigned int api_type)
+{
+ const unsigned int iter_shift = 24;
+ const unsigned int iterations = 1 << iter_shift;
+ unsigned int i = 0;
+ void *burst = NULL;
+
+ /* alloc dummy object pointers */
+ burst = test_ring_calloc(1, esize);
+ if (burst == NULL)
+ return -1;
+
+ const uint64_t start = rte_rdtsc();
+ for (i = 0; i < iterations; i++) {
+ test_ring_enqueue(r, burst, esize, 1, api_type);
+ test_ring_dequeue(r, burst, esize, 1, api_type);
+ }
+ const uint64_t end = rte_rdtsc();
+
+ test_ring_print_test_string(api_type, esize, 1,
+ ((double)(end - start)) / iterations);
+
+ rte_free(burst);
+
+ return 0;
+}
+
+/*
+ * Test that does both enqueue and dequeue on a core using the burst/bulk API
+ * calls Results should be the same as for the bulk function called on a
+ * single lcore.
+ */
+static int
+test_burst_bulk_enqueue_dequeue(struct rte_ring *r, const int esize,
+ const unsigned int api_type)
+{
+ const unsigned int iter_shift = 23;
+ const unsigned int iterations = 1 << iter_shift;
+ unsigned int sz, i = 0;
+ void **burst = NULL;
+
+ burst = test_ring_calloc(MAX_BURST, esize);
+ if (burst == NULL)
+ return -1;
+
+ for (sz = 0; sz < RTE_DIM(bulk_sizes); sz++) {
+ const uint64_t start = rte_rdtsc();
+ for (i = 0; i < iterations; i++) {
+ test_ring_enqueue(r, burst, esize, bulk_sizes[sz],
+ api_type);
+ test_ring_dequeue(r, burst, esize, bulk_sizes[sz],
+ api_type);
+ }
+ const uint64_t end = rte_rdtsc();
+
+ test_ring_print_test_string(api_type, esize, bulk_sizes[sz],
+ ((double)(end - start)) / iterations);
+ }
+
+ rte_free(burst);
+
+ return 0;
+}
+
+/* Run all tests for a given element size */
+static __rte_always_inline int
+test_ring_perf_esize(const int esize)
+{
+ struct lcore_pair cores;
+ struct rte_ring *r = NULL;
+
+ /*
+ * Performance test for legacy/_elem APIs
+ * SP-SC/MP-MC, single
+ */
+ r = test_ring_create(RING_NAME, esize, RING_SIZE, rte_socket_id(), 0);
+ if (r == NULL)
+ goto test_fail;
+
+ printf("\n### Testing single element enq/deq ###\n");
+ if (test_single_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_SPSC | TEST_RING_ELEM_SINGLE) < 0)
+ goto test_fail;
+ if (test_single_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_SINGLE) < 0)
+ goto test_fail;
+
+ printf("\n### Testing burst enq/deq ###\n");
+ if (test_burst_bulk_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BURST) < 0)
+ goto test_fail;
+ if (test_burst_bulk_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BURST) < 0)
+ goto test_fail;
+
+ printf("\n### Testing bulk enq/deq ###\n");
+ if (test_burst_bulk_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK) < 0)
+ goto test_fail;
+ if (test_burst_bulk_enqueue_dequeue(r, esize,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK) < 0)
+ goto test_fail;
+
+ printf("\n### Testing empty bulk deq ###\n");
+ test_empty_dequeue(r, esize,
+ TEST_RING_THREAD_SPSC | TEST_RING_ELEM_BULK);
+ test_empty_dequeue(r, esize,
+ TEST_RING_THREAD_MPMC | TEST_RING_ELEM_BULK);
+
+ if (get_two_hyperthreads(&cores) == 0) {
+ printf("\n### Testing using two hyperthreads ###\n");
+ if (run_on_core_pair(&cores, r, esize) < 0)
+ goto test_fail;
+ }
+
+ if (get_two_cores(&cores) == 0) {
+ printf("\n### Testing using two physical cores ###\n");
+ if (run_on_core_pair(&cores, r, esize) < 0)
+ goto test_fail;
+ }
+ if (get_two_sockets(&cores) == 0) {
+ printf("\n### Testing using two NUMA nodes ###\n");
+ if (run_on_core_pair(&cores, r, esize) < 0)
+ goto test_fail;
+ }
+
+ printf("\n### Testing using all slave nodes ###\n");
+ if (run_on_all_cores(r, esize) < 0)
+ goto test_fail;
+
+ rte_ring_free(r);
+
+ return 0;
+
+test_fail:
+ rte_ring_free(r);
+
+ return -1;
+}
+
+static int
+test_ring_perf(void)
+{
+ /* Run all the tests for different element sizes */
+ if (test_ring_perf_esize(-1) == -1)
+ return -1;
+
+ if (test_ring_perf_esize(16) == -1)
+ return -1;
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(ring_perf_autotest, test_ring_perf);
diff --git a/src/spdk/dpdk/app/test/test_ring_rts_stress.c b/src/spdk/dpdk/app/test/test_ring_rts_stress.c
new file mode 100644
index 000000000..f5255f24c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_rts_stress.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress_impl.h"
+
+static inline uint32_t
+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,
+ uint32_t *avail)
+{
+ return rte_ring_mc_rts_dequeue_bulk(r, obj, n, avail);
+}
+
+static inline uint32_t
+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,
+ uint32_t *free)
+{
+ return rte_ring_mp_rts_enqueue_bulk(r, obj, n, free);
+}
+
+static int
+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num)
+{
+ return rte_ring_init(r, name, num,
+ RING_F_MP_RTS_ENQ | RING_F_MC_RTS_DEQ);
+}
+
+const struct test test_ring_rts_stress = {
+ .name = "MT_RTS",
+ .nb_case = RTE_DIM(tests),
+ .cases = tests,
+};
diff --git a/src/spdk/dpdk/app/test/test_ring_stress.c b/src/spdk/dpdk/app/test/test_ring_stress.c
new file mode 100644
index 000000000..853fcc190
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_stress.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress.h"
+
+static int
+run_test(const struct test *test)
+{
+ int32_t rc;
+ uint32_t i, k;
+
+ for (i = 0, k = 0; i != test->nb_case; i++) {
+
+ printf("TEST-CASE %s %s START\n",
+ test->name, test->cases[i].name);
+
+ rc = test->cases[i].func(test->cases[i].wfunc);
+ k += (rc == 0);
+
+ if (rc != 0)
+ printf("TEST-CASE %s %s FAILED\n",
+ test->name, test->cases[i].name);
+ else
+ printf("TEST-CASE %s %s OK\n",
+ test->name, test->cases[i].name);
+ }
+
+ return k;
+}
+
+static int
+test_ring_stress(void)
+{
+ uint32_t n, k;
+
+ n = 0;
+ k = 0;
+
+ n += test_ring_mpmc_stress.nb_case;
+ k += run_test(&test_ring_mpmc_stress);
+
+ n += test_ring_rts_stress.nb_case;
+ k += run_test(&test_ring_rts_stress);
+
+ n += test_ring_hts_stress.nb_case;
+ k += run_test(&test_ring_hts_stress);
+
+ n += test_ring_peek_stress.nb_case;
+ k += run_test(&test_ring_peek_stress);
+
+ printf("Number of tests:\t%u\nSuccess:\t%u\nFailed:\t%u\n",
+ n, k, n - k);
+ return (k != n);
+}
+
+REGISTER_TEST_COMMAND(ring_stress_autotest, test_ring_stress);
diff --git a/src/spdk/dpdk/app/test/test_ring_stress.h b/src/spdk/dpdk/app/test/test_ring_stress.h
new file mode 100644
index 000000000..60953ce47
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_stress.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdalign.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rte_ring.h>
+#include <rte_cycles.h>
+#include <rte_launch.h>
+#include <rte_pause.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+#include <rte_spinlock.h>
+
+#include "test.h"
+
+struct test_case {
+ const char *name;
+ int (*func)(int (*)(void *));
+ int (*wfunc)(void *arg);
+};
+
+struct test {
+ const char *name;
+ uint32_t nb_case;
+ const struct test_case *cases;
+};
+
+extern const struct test test_ring_mpmc_stress;
+extern const struct test test_ring_rts_stress;
+extern const struct test test_ring_hts_stress;
+extern const struct test test_ring_peek_stress;
diff --git a/src/spdk/dpdk/app/test/test_ring_stress_impl.h b/src/spdk/dpdk/app/test/test_ring_stress_impl.h
new file mode 100644
index 000000000..222d62bc4
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ring_stress_impl.h
@@ -0,0 +1,396 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#include "test_ring_stress.h"
+
+/**
+ * Stress test for ring enqueue/dequeue operations.
+ * Performs the following pattern on each slave worker:
+ * dequeue/read-write data from the dequeued objects/enqueue.
+ * Serves as both functional and performance test of ring
+ * enqueue/dequeue operations under high contention
+ * (for both over committed and non-over committed scenarios).
+ */
+
+#define RING_NAME "RING_STRESS"
+#define BULK_NUM 32
+#define RING_SIZE (2 * BULK_NUM * RTE_MAX_LCORE)
+
+enum {
+ WRK_CMD_STOP,
+ WRK_CMD_RUN,
+};
+
+static volatile uint32_t wrk_cmd __rte_cache_aligned;
+
+/* test run-time in seconds */
+static const uint32_t run_time = 60;
+static const uint32_t verbose;
+
+struct lcore_stat {
+ uint64_t nb_cycle;
+ struct {
+ uint64_t nb_call;
+ uint64_t nb_obj;
+ uint64_t nb_cycle;
+ uint64_t max_cycle;
+ uint64_t min_cycle;
+ } op;
+};
+
+struct lcore_arg {
+ struct rte_ring *rng;
+ struct lcore_stat stats;
+} __rte_cache_aligned;
+
+struct ring_elem {
+ uint32_t cnt[RTE_CACHE_LINE_SIZE / sizeof(uint32_t)];
+} __rte_cache_aligned;
+
+/*
+ * redefinable functions
+ */
+static uint32_t
+_st_ring_dequeue_bulk(struct rte_ring *r, void **obj, uint32_t n,
+ uint32_t *avail);
+
+static uint32_t
+_st_ring_enqueue_bulk(struct rte_ring *r, void * const *obj, uint32_t n,
+ uint32_t *free);
+
+static int
+_st_ring_init(struct rte_ring *r, const char *name, uint32_t num);
+
+
+static void
+lcore_stat_update(struct lcore_stat *ls, uint64_t call, uint64_t obj,
+ uint64_t tm, int32_t prcs)
+{
+ ls->op.nb_call += call;
+ ls->op.nb_obj += obj;
+ ls->op.nb_cycle += tm;
+ if (prcs) {
+ ls->op.max_cycle = RTE_MAX(ls->op.max_cycle, tm);
+ ls->op.min_cycle = RTE_MIN(ls->op.min_cycle, tm);
+ }
+}
+
+static void
+lcore_op_stat_aggr(struct lcore_stat *ms, const struct lcore_stat *ls)
+{
+
+ ms->op.nb_call += ls->op.nb_call;
+ ms->op.nb_obj += ls->op.nb_obj;
+ ms->op.nb_cycle += ls->op.nb_cycle;
+ ms->op.max_cycle = RTE_MAX(ms->op.max_cycle, ls->op.max_cycle);
+ ms->op.min_cycle = RTE_MIN(ms->op.min_cycle, ls->op.min_cycle);
+}
+
+static void
+lcore_stat_aggr(struct lcore_stat *ms, const struct lcore_stat *ls)
+{
+ ms->nb_cycle = RTE_MAX(ms->nb_cycle, ls->nb_cycle);
+ lcore_op_stat_aggr(ms, ls);
+}
+
+static void
+lcore_stat_dump(FILE *f, uint32_t lc, const struct lcore_stat *ls)
+{
+ long double st;
+
+ st = (long double)rte_get_timer_hz() / US_PER_S;
+
+ if (lc == UINT32_MAX)
+ fprintf(f, "%s(AGGREGATE)={\n", __func__);
+ else
+ fprintf(f, "%s(lcore=%u)={\n", __func__, lc);
+
+ fprintf(f, "\tnb_cycle=%" PRIu64 "(%.2Lf usec),\n",
+ ls->nb_cycle, (long double)ls->nb_cycle / st);
+
+ fprintf(f, "\tDEQ+ENQ={\n");
+
+ fprintf(f, "\t\tnb_call=%" PRIu64 ",\n", ls->op.nb_call);
+ fprintf(f, "\t\tnb_obj=%" PRIu64 ",\n", ls->op.nb_obj);
+ fprintf(f, "\t\tnb_cycle=%" PRIu64 ",\n", ls->op.nb_cycle);
+ fprintf(f, "\t\tobj/call(avg): %.2Lf\n",
+ (long double)ls->op.nb_obj / ls->op.nb_call);
+ fprintf(f, "\t\tcycles/obj(avg): %.2Lf\n",
+ (long double)ls->op.nb_cycle / ls->op.nb_obj);
+ fprintf(f, "\t\tcycles/call(avg): %.2Lf\n",
+ (long double)ls->op.nb_cycle / ls->op.nb_call);
+
+ /* if min/max cycles per call stats was collected */
+ if (ls->op.min_cycle != UINT64_MAX) {
+ fprintf(f, "\t\tmax cycles/call=%" PRIu64 "(%.2Lf usec),\n",
+ ls->op.max_cycle,
+ (long double)ls->op.max_cycle / st);
+ fprintf(f, "\t\tmin cycles/call=%" PRIu64 "(%.2Lf usec),\n",
+ ls->op.min_cycle,
+ (long double)ls->op.min_cycle / st);
+ }
+
+ fprintf(f, "\t},\n");
+ fprintf(f, "};\n");
+}
+
+static void
+fill_ring_elm(struct ring_elem *elm, uint32_t fill)
+{
+ uint32_t i;
+
+ for (i = 0; i != RTE_DIM(elm->cnt); i++)
+ elm->cnt[i] = fill;
+}
+
+static int32_t
+check_updt_elem(struct ring_elem *elm[], uint32_t num,
+ const struct ring_elem *check, const struct ring_elem *fill)
+{
+ uint32_t i;
+
+ static rte_spinlock_t dump_lock;
+
+ for (i = 0; i != num; i++) {
+ if (memcmp(check, elm[i], sizeof(*check)) != 0) {
+ rte_spinlock_lock(&dump_lock);
+ printf("%s(lc=%u, num=%u) failed at %u-th iter, "
+ "offending object: %p\n",
+ __func__, rte_lcore_id(), num, i, elm[i]);
+ rte_memdump(stdout, "expected", check, sizeof(*check));
+ rte_memdump(stdout, "result", elm[i], sizeof(elm[i]));
+ rte_spinlock_unlock(&dump_lock);
+ return -EINVAL;
+ }
+ memcpy(elm[i], fill, sizeof(*elm[i]));
+ }
+
+ return 0;
+}
+
+static int
+check_ring_op(uint32_t exp, uint32_t res, uint32_t lc,
+ const char *fname, const char *opname)
+{
+ if (exp != res) {
+ printf("%s(lc=%u) failure: %s expected: %u, returned %u\n",
+ fname, lc, opname, exp, res);
+ return -ENOSPC;
+ }
+ return 0;
+}
+
+static int
+test_worker(void *arg, const char *fname, int32_t prcs)
+{
+ int32_t rc;
+ uint32_t lc, n, num;
+ uint64_t cl, tm0, tm1;
+ struct lcore_arg *la;
+ struct ring_elem def_elm, loc_elm;
+ struct ring_elem *obj[2 * BULK_NUM];
+
+ la = arg;
+ lc = rte_lcore_id();
+
+ fill_ring_elm(&def_elm, UINT32_MAX);
+ fill_ring_elm(&loc_elm, lc);
+
+ while (wrk_cmd != WRK_CMD_RUN) {
+ rte_smp_rmb();
+ rte_pause();
+ }
+
+ cl = rte_rdtsc_precise();
+
+ do {
+ /* num in interval [7/8, 11/8] of BULK_NUM */
+ num = 7 * BULK_NUM / 8 + rte_rand() % (BULK_NUM / 2);
+
+ /* reset all pointer values */
+ memset(obj, 0, sizeof(obj));
+
+ /* dequeue num elems */
+ tm0 = (prcs != 0) ? rte_rdtsc_precise() : 0;
+ n = _st_ring_dequeue_bulk(la->rng, (void **)obj, num, NULL);
+ tm0 = (prcs != 0) ? rte_rdtsc_precise() - tm0 : 0;
+
+ /* check return value and objects */
+ rc = check_ring_op(num, n, lc, fname,
+ RTE_STR(_st_ring_dequeue_bulk));
+ if (rc == 0)
+ rc = check_updt_elem(obj, num, &def_elm, &loc_elm);
+ if (rc != 0)
+ break;
+
+ /* enqueue num elems */
+ rte_compiler_barrier();
+ rc = check_updt_elem(obj, num, &loc_elm, &def_elm);
+ if (rc != 0)
+ break;
+
+ tm1 = (prcs != 0) ? rte_rdtsc_precise() : 0;
+ n = _st_ring_enqueue_bulk(la->rng, (void **)obj, num, NULL);
+ tm1 = (prcs != 0) ? rte_rdtsc_precise() - tm1 : 0;
+
+ /* check return value */
+ rc = check_ring_op(num, n, lc, fname,
+ RTE_STR(_st_ring_enqueue_bulk));
+ if (rc != 0)
+ break;
+
+ lcore_stat_update(&la->stats, 1, num, tm0 + tm1, prcs);
+
+ } while (wrk_cmd == WRK_CMD_RUN);
+
+ cl = rte_rdtsc_precise() - cl;
+ if (prcs == 0)
+ lcore_stat_update(&la->stats, 0, 0, cl, 0);
+ la->stats.nb_cycle = cl;
+ return rc;
+}
+static int
+test_worker_prcs(void *arg)
+{
+ return test_worker(arg, __func__, 1);
+}
+
+static int
+test_worker_avg(void *arg)
+{
+ return test_worker(arg, __func__, 0);
+}
+
+static void
+mt1_fini(struct rte_ring *rng, void *data)
+{
+ rte_free(rng);
+ rte_free(data);
+}
+
+static int
+mt1_init(struct rte_ring **rng, void **data, uint32_t num)
+{
+ int32_t rc;
+ size_t sz;
+ uint32_t i, nr;
+ struct rte_ring *r;
+ struct ring_elem *elm;
+ void *p;
+
+ *rng = NULL;
+ *data = NULL;
+
+ sz = num * sizeof(*elm);
+ elm = rte_zmalloc(NULL, sz, __alignof__(*elm));
+ if (elm == NULL) {
+ printf("%s: alloc(%zu) for %u elems data failed",
+ __func__, sz, num);
+ return -ENOMEM;
+ }
+
+ *data = elm;
+
+ /* alloc ring */
+ nr = 2 * num;
+ sz = rte_ring_get_memsize(nr);
+ r = rte_zmalloc(NULL, sz, __alignof__(*r));
+ if (r == NULL) {
+ printf("%s: alloc(%zu) for FIFO with %u elems failed",
+ __func__, sz, nr);
+ return -ENOMEM;
+ }
+
+ *rng = r;
+
+ rc = _st_ring_init(r, RING_NAME, nr);
+ if (rc != 0) {
+ printf("%s: _st_ring_init(%p, %u) failed, error: %d(%s)\n",
+ __func__, r, nr, rc, strerror(-rc));
+ return rc;
+ }
+
+ for (i = 0; i != num; i++) {
+ fill_ring_elm(elm + i, UINT32_MAX);
+ p = elm + i;
+ if (_st_ring_enqueue_bulk(r, &p, 1, NULL) != 1)
+ break;
+ }
+
+ if (i != num) {
+ printf("%s: _st_ring_enqueue(%p, %u) returned %u\n",
+ __func__, r, num, i);
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static int
+test_mt1(int (*test)(void *))
+{
+ int32_t rc;
+ uint32_t lc, mc;
+ struct rte_ring *r;
+ void *data;
+ struct lcore_arg arg[RTE_MAX_LCORE];
+
+ static const struct lcore_stat init_stat = {
+ .op.min_cycle = UINT64_MAX,
+ };
+
+ rc = mt1_init(&r, &data, RING_SIZE);
+ if (rc != 0) {
+ mt1_fini(r, data);
+ return rc;
+ }
+
+ memset(arg, 0, sizeof(arg));
+
+ /* launch on all slaves */
+ RTE_LCORE_FOREACH_SLAVE(lc) {
+ arg[lc].rng = r;
+ arg[lc].stats = init_stat;
+ rte_eal_remote_launch(test, &arg[lc], lc);
+ }
+
+ /* signal worker to start test */
+ wrk_cmd = WRK_CMD_RUN;
+ rte_smp_wmb();
+
+ usleep(run_time * US_PER_S);
+
+ /* signal worker to start test */
+ wrk_cmd = WRK_CMD_STOP;
+ rte_smp_wmb();
+
+ /* wait for slaves and collect stats. */
+ mc = rte_lcore_id();
+ arg[mc].stats = init_stat;
+
+ rc = 0;
+ RTE_LCORE_FOREACH_SLAVE(lc) {
+ rc |= rte_eal_wait_lcore(lc);
+ lcore_stat_aggr(&arg[mc].stats, &arg[lc].stats);
+ if (verbose != 0)
+ lcore_stat_dump(stdout, lc, &arg[lc].stats);
+ }
+
+ lcore_stat_dump(stdout, UINT32_MAX, &arg[mc].stats);
+ mt1_fini(r, data);
+ return rc;
+}
+
+static const struct test_case tests[] = {
+ {
+ .name = "MT-WRK_ENQ_DEQ-MST_NONE-PRCS",
+ .func = test_mt1,
+ .wfunc = test_worker_prcs,
+ },
+ {
+ .name = "MT-WRK_ENQ_DEQ-MST_NONE-AVG",
+ .func = test_mt1,
+ .wfunc = test_worker_avg,
+ },
+};
diff --git a/src/spdk/dpdk/app/test/test_rwlock.c b/src/spdk/dpdk/app/test/test_rwlock.c
new file mode 100644
index 000000000..61bee7d7c
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_rwlock.c
@@ -0,0 +1,555 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <sys/queue.h>
+#include <string.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_rwlock.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+
+#include "test.h"
+
+/*
+ * rwlock test
+ * ===========
+ * Provides UT for rte_rwlock API.
+ * Main concern is on functional testing, but also provides some
+ * performance measurements.
+ * Obviously for proper testing need to be executed with more than one lcore.
+ */
+
+#define ITER_NUM 0x80
+
+#define TEST_SEC 5
+
+static rte_rwlock_t sl;
+static rte_rwlock_t sl_tab[RTE_MAX_LCORE];
+static rte_atomic32_t synchro;
+
+enum {
+ LC_TYPE_RDLOCK,
+ LC_TYPE_WRLOCK,
+};
+
+static struct {
+ rte_rwlock_t lock;
+ uint64_t tick;
+ volatile union {
+ uint8_t u8[RTE_CACHE_LINE_SIZE];
+ uint64_t u64[RTE_CACHE_LINE_SIZE / sizeof(uint64_t)];
+ } data;
+} __rte_cache_aligned try_rwlock_data;
+
+struct try_rwlock_lcore {
+ int32_t rc;
+ int32_t type;
+ struct {
+ uint64_t tick;
+ uint64_t fail;
+ uint64_t success;
+ } stat;
+} __rte_cache_aligned;
+
+static struct try_rwlock_lcore try_lcore_data[RTE_MAX_LCORE];
+
+static int
+test_rwlock_per_core(__rte_unused void *arg)
+{
+ rte_rwlock_write_lock(&sl);
+ printf("Global write lock taken on core %u\n", rte_lcore_id());
+ rte_rwlock_write_unlock(&sl);
+
+ rte_rwlock_write_lock(&sl_tab[rte_lcore_id()]);
+ printf("Hello from core %u !\n", rte_lcore_id());
+ rte_rwlock_write_unlock(&sl_tab[rte_lcore_id()]);
+
+ rte_rwlock_read_lock(&sl);
+ printf("Global read lock taken on core %u\n", rte_lcore_id());
+ rte_delay_ms(100);
+ printf("Release global read lock on core %u\n", rte_lcore_id());
+ rte_rwlock_read_unlock(&sl);
+
+ return 0;
+}
+
+static rte_rwlock_t lk = RTE_RWLOCK_INITIALIZER;
+static volatile uint64_t rwlock_data;
+static uint64_t time_count[RTE_MAX_LCORE] = {0};
+
+#define MAX_LOOP 10000
+#define TEST_RWLOCK_DEBUG 0
+
+static int
+load_loop_fn(__rte_unused void *arg)
+{
+ uint64_t time_diff = 0, begin;
+ uint64_t hz = rte_get_timer_hz();
+ uint64_t lcount = 0;
+ const unsigned int lcore = rte_lcore_id();
+
+ /* wait synchro for slaves */
+ if (lcore != rte_get_master_lcore())
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ begin = rte_rdtsc_precise();
+ while (lcount < MAX_LOOP) {
+ rte_rwlock_write_lock(&lk);
+ ++rwlock_data;
+ rte_rwlock_write_unlock(&lk);
+
+ rte_rwlock_read_lock(&lk);
+ if (TEST_RWLOCK_DEBUG && !(lcount % 100))
+ printf("Core [%u] rwlock_data = %"PRIu64"\n",
+ lcore, rwlock_data);
+ rte_rwlock_read_unlock(&lk);
+
+ lcount++;
+ /* delay to make lock duty cycle slightly realistic */
+ rte_pause();
+ }
+
+ time_diff = rte_rdtsc_precise() - begin;
+ time_count[lcore] = time_diff * 1000000 / hz;
+ return 0;
+}
+
+static int
+test_rwlock_perf(void)
+{
+ unsigned int i;
+ uint64_t total = 0;
+
+ printf("\nRwlock Perf Test on %u cores...\n", rte_lcore_count());
+
+ /* clear synchro and start slaves */
+ rte_atomic32_set(&synchro, 0);
+ if (rte_eal_mp_remote_launch(load_loop_fn, NULL, SKIP_MASTER) < 0)
+ return -1;
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(NULL);
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_LCORE_FOREACH(i) {
+ printf("Core [%u] cost time = %"PRIu64" us\n",
+ i, time_count[i]);
+ total += time_count[i];
+ }
+
+ printf("Total cost time = %"PRIu64" us\n", total);
+ memset(time_count, 0, sizeof(time_count));
+
+ return 0;
+}
+
+/*
+ * - There is a global rwlock and a table of rwlocks (one per lcore).
+ *
+ * - The test function takes all of these locks and launches the
+ * ``test_rwlock_per_core()`` function on each core (except the master).
+ *
+ * - The function takes the global write lock, display something,
+ * then releases the global lock.
+ * - Then, it takes the per-lcore write lock, display something, and
+ * releases the per-core lock.
+ * - Finally, a read lock is taken during 100 ms, then released.
+ *
+ * - The main function unlocks the per-lcore locks sequentially and
+ * waits between each lock. This triggers the display of a message
+ * for each core, in the correct order.
+ *
+ * Then, it tries to take the global write lock and display the last
+ * message. The autotest script checks that the message order is correct.
+ */
+static int
+rwlock_test1(void)
+{
+ int i;
+
+ rte_rwlock_init(&sl);
+ for (i=0; i<RTE_MAX_LCORE; i++)
+ rte_rwlock_init(&sl_tab[i]);
+
+ rte_rwlock_write_lock(&sl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_rwlock_write_lock(&sl_tab[i]);
+ rte_eal_remote_launch(test_rwlock_per_core, NULL, i);
+ }
+
+ rte_rwlock_write_unlock(&sl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_rwlock_write_unlock(&sl_tab[i]);
+ rte_delay_ms(100);
+ }
+
+ rte_rwlock_write_lock(&sl);
+ /* this message should be the last message of test */
+ printf("Global write lock taken on master core %u\n", rte_lcore_id());
+ rte_rwlock_write_unlock(&sl);
+
+ rte_eal_mp_wait_lcore();
+
+ if (test_rwlock_perf() < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+try_read(uint32_t lc)
+{
+ int32_t rc;
+ uint32_t i;
+
+ rc = rte_rwlock_read_trylock(&try_rwlock_data.lock);
+ if (rc != 0)
+ return rc;
+
+ for (i = 0; i != RTE_DIM(try_rwlock_data.data.u64); i++) {
+
+ /* race condition occurred, lock doesn't work properly */
+ if (try_rwlock_data.data.u64[i] != 0) {
+ printf("%s(%u) error: unexpected data pattern\n",
+ __func__, lc);
+ rte_memdump(stdout, NULL,
+ (void *)(uintptr_t)&try_rwlock_data.data,
+ sizeof(try_rwlock_data.data));
+ rc = -EFAULT;
+ break;
+ }
+ }
+
+ rte_rwlock_read_unlock(&try_rwlock_data.lock);
+ return rc;
+}
+
+static int
+try_write(uint32_t lc)
+{
+ int32_t rc;
+ uint32_t i, v;
+
+ v = RTE_MAX(lc % UINT8_MAX, 1U);
+
+ rc = rte_rwlock_write_trylock(&try_rwlock_data.lock);
+ if (rc != 0)
+ return rc;
+
+ /* update by bytes in reverese order */
+ for (i = RTE_DIM(try_rwlock_data.data.u8); i-- != 0; ) {
+
+ /* race condition occurred, lock doesn't work properly */
+ if (try_rwlock_data.data.u8[i] != 0) {
+ printf("%s:%d(%u) error: unexpected data pattern\n",
+ __func__, __LINE__, lc);
+ rte_memdump(stdout, NULL,
+ (void *)(uintptr_t)&try_rwlock_data.data,
+ sizeof(try_rwlock_data.data));
+ rc = -EFAULT;
+ break;
+ }
+
+ try_rwlock_data.data.u8[i] = v;
+ }
+
+ /* restore by bytes in reverese order */
+ for (i = RTE_DIM(try_rwlock_data.data.u8); i-- != 0; ) {
+
+ /* race condition occurred, lock doesn't work properly */
+ if (try_rwlock_data.data.u8[i] != v) {
+ printf("%s:%d(%u) error: unexpected data pattern\n",
+ __func__, __LINE__, lc);
+ rte_memdump(stdout, NULL,
+ (void *)(uintptr_t)&try_rwlock_data.data,
+ sizeof(try_rwlock_data.data));
+ rc = -EFAULT;
+ break;
+ }
+
+ try_rwlock_data.data.u8[i] = 0;
+ }
+
+ rte_rwlock_write_unlock(&try_rwlock_data.lock);
+ return rc;
+}
+
+static int
+try_read_lcore(__rte_unused void *data)
+{
+ int32_t rc;
+ uint32_t i, lc;
+ uint64_t ftm, stm, tm;
+ struct try_rwlock_lcore *lcd;
+
+ lc = rte_lcore_id();
+ lcd = try_lcore_data + lc;
+ lcd->type = LC_TYPE_RDLOCK;
+
+ ftm = try_rwlock_data.tick;
+ stm = rte_get_timer_cycles();
+
+ do {
+ for (i = 0; i != ITER_NUM; i++) {
+ rc = try_read(lc);
+ if (rc == 0)
+ lcd->stat.success++;
+ else if (rc == -EBUSY)
+ lcd->stat.fail++;
+ else
+ break;
+ rc = 0;
+ }
+ tm = rte_get_timer_cycles() - stm;
+ } while (tm < ftm && rc == 0);
+
+ lcd->rc = rc;
+ lcd->stat.tick = tm;
+ return rc;
+}
+
+static int
+try_write_lcore(__rte_unused void *data)
+{
+ int32_t rc;
+ uint32_t i, lc;
+ uint64_t ftm, stm, tm;
+ struct try_rwlock_lcore *lcd;
+
+ lc = rte_lcore_id();
+ lcd = try_lcore_data + lc;
+ lcd->type = LC_TYPE_WRLOCK;
+
+ ftm = try_rwlock_data.tick;
+ stm = rte_get_timer_cycles();
+
+ do {
+ for (i = 0; i != ITER_NUM; i++) {
+ rc = try_write(lc);
+ if (rc == 0)
+ lcd->stat.success++;
+ else if (rc == -EBUSY)
+ lcd->stat.fail++;
+ else
+ break;
+ rc = 0;
+ }
+ tm = rte_get_timer_cycles() - stm;
+ } while (tm < ftm && rc == 0);
+
+ lcd->rc = rc;
+ lcd->stat.tick = tm;
+ return rc;
+}
+
+static void
+print_try_lcore_stats(const struct try_rwlock_lcore *tlc, uint32_t lc)
+{
+ uint64_t f, s;
+
+ f = RTE_MAX(tlc->stat.fail, 1ULL);
+ s = RTE_MAX(tlc->stat.success, 1ULL);
+
+ printf("try_lcore_data[%u]={\n"
+ "\trc=%d,\n"
+ "\ttype=%s,\n"
+ "\tfail=%" PRIu64 ",\n"
+ "\tsuccess=%" PRIu64 ",\n"
+ "\tcycles=%" PRIu64 ",\n"
+ "\tcycles/op=%#Lf,\n"
+ "\tcycles/success=%#Lf,\n"
+ "\tsuccess/fail=%#Lf,\n"
+ "};\n",
+ lc,
+ tlc->rc,
+ tlc->type == LC_TYPE_RDLOCK ? "RDLOCK" : "WRLOCK",
+ tlc->stat.fail,
+ tlc->stat.success,
+ tlc->stat.tick,
+ (long double)tlc->stat.tick /
+ (tlc->stat.fail + tlc->stat.success),
+ (long double)tlc->stat.tick / s,
+ (long double)tlc->stat.success / f);
+}
+
+static void
+collect_try_lcore_stats(struct try_rwlock_lcore *tlc,
+ const struct try_rwlock_lcore *lc)
+{
+ tlc->stat.tick += lc->stat.tick;
+ tlc->stat.fail += lc->stat.fail;
+ tlc->stat.success += lc->stat.success;
+}
+
+/*
+ * Process collected results:
+ * - check status
+ * - collect and print statistics
+ */
+static int
+process_try_lcore_stats(void)
+{
+ int32_t rc;
+ uint32_t lc, rd, wr;
+ struct try_rwlock_lcore rlc, wlc;
+
+ memset(&rlc, 0, sizeof(rlc));
+ memset(&wlc, 0, sizeof(wlc));
+
+ rlc.type = LC_TYPE_RDLOCK;
+ wlc.type = LC_TYPE_WRLOCK;
+ rd = 0;
+ wr = 0;
+
+ rc = 0;
+ RTE_LCORE_FOREACH(lc) {
+ rc |= try_lcore_data[lc].rc;
+ if (try_lcore_data[lc].type == LC_TYPE_RDLOCK) {
+ collect_try_lcore_stats(&rlc, try_lcore_data + lc);
+ rd++;
+ } else {
+ collect_try_lcore_stats(&wlc, try_lcore_data + lc);
+ wr++;
+ }
+ }
+
+ if (rc == 0) {
+ RTE_LCORE_FOREACH(lc)
+ print_try_lcore_stats(try_lcore_data + lc, lc);
+
+ if (rd != 0) {
+ printf("aggregated stats for %u RDLOCK cores:\n", rd);
+ print_try_lcore_stats(&rlc, rd);
+ }
+
+ if (wr != 0) {
+ printf("aggregated stats for %u WRLOCK cores:\n", wr);
+ print_try_lcore_stats(&wlc, wr);
+ }
+ }
+
+ return rc;
+}
+
+static void
+try_test_reset(void)
+{
+ memset(&try_lcore_data, 0, sizeof(try_lcore_data));
+ memset(&try_rwlock_data, 0, sizeof(try_rwlock_data));
+ try_rwlock_data.tick = TEST_SEC * rte_get_tsc_hz();
+}
+
+/* all lcores grab RDLOCK */
+static int
+try_rwlock_test_rda(void)
+{
+ try_test_reset();
+
+ /* start read test on all avaialble lcores */
+ rte_eal_mp_remote_launch(try_read_lcore, NULL, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ return process_try_lcore_stats();
+}
+
+/* all slave lcores grab RDLOCK, master one grabs WRLOCK */
+static int
+try_rwlock_test_rds_wrm(void)
+{
+ try_test_reset();
+
+ rte_eal_mp_remote_launch(try_read_lcore, NULL, SKIP_MASTER);
+ try_write_lcore(NULL);
+ rte_eal_mp_wait_lcore();
+
+ return process_try_lcore_stats();
+}
+
+/* master and even slave lcores grab RDLOCK, odd lcores grab WRLOCK */
+static int
+try_rwlock_test_rde_wro(void)
+{
+ uint32_t lc, mlc;
+
+ try_test_reset();
+
+ mlc = rte_get_master_lcore();
+
+ RTE_LCORE_FOREACH(lc) {
+ if (lc != mlc) {
+ if ((lc & 1) == 0)
+ rte_eal_remote_launch(try_read_lcore,
+ NULL, lc);
+ else
+ rte_eal_remote_launch(try_write_lcore,
+ NULL, lc);
+ }
+ }
+ try_read_lcore(NULL);
+ rte_eal_mp_wait_lcore();
+
+ return process_try_lcore_stats();
+}
+
+static int
+test_rwlock(void)
+{
+ uint32_t i;
+ int32_t rc, ret;
+
+ static const struct {
+ const char *name;
+ int (*ftst)(void);
+ } test[] = {
+ {
+ .name = "rwlock_test1",
+ .ftst = rwlock_test1,
+ },
+ {
+ .name = "try_rwlock_test_rda",
+ .ftst = try_rwlock_test_rda,
+ },
+ {
+ .name = "try_rwlock_test_rds_wrm",
+ .ftst = try_rwlock_test_rds_wrm,
+ },
+ {
+ .name = "try_rwlock_test_rde_wro",
+ .ftst = try_rwlock_test_rde_wro,
+ },
+ };
+
+ ret = 0;
+ for (i = 0; i != RTE_DIM(test); i++) {
+ printf("starting test %s;\n", test[i].name);
+ rc = test[i].ftst();
+ printf("test %s completed with status %d\n", test[i].name, rc);
+ ret |= rc;
+ }
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(rwlock_autotest, test_rwlock);
+
+/* subtests used in meson for CI */
+REGISTER_TEST_COMMAND(rwlock_test1_autotest, rwlock_test1);
+REGISTER_TEST_COMMAND(rwlock_rda_autotest, try_rwlock_test_rda);
+REGISTER_TEST_COMMAND(rwlock_rds_wrm_autotest, try_rwlock_test_rds_wrm);
+REGISTER_TEST_COMMAND(rwlock_rde_wro_autotest, try_rwlock_test_rde_wro);
diff --git a/src/spdk/dpdk/app/test/test_sched.c b/src/spdk/dpdk/app/test/test_sched.c
new file mode 100644
index 000000000..fc31080ef
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_sched.c
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "test.h"
+
+#include <rte_cycles.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_byteorder.h>
+#include <rte_sched.h>
+
+
+#define SUBPORT 0
+#define PIPE 1
+#define TC 2
+#define QUEUE 0
+
+static struct rte_sched_pipe_params pipe_profile[] = {
+ { /* Profile #0 */
+ .tb_rate = 305175,
+ .tb_size = 1000000,
+
+ .tc_rate = {305175, 305175, 305175, 305175, 305175, 305175,
+ 305175, 305175, 305175, 305175, 305175, 305175, 305175},
+ .tc_period = 40,
+ .tc_ov_weight = 1,
+
+ .wrr_weights = {1, 1, 1, 1},
+ },
+};
+
+static struct rte_sched_subport_params subport_param[] = {
+ {
+ .tb_rate = 1250000000,
+ .tb_size = 1000000,
+
+ .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000,
+ 1250000000, 1250000000, 1250000000, 1250000000, 1250000000,
+ 1250000000, 1250000000, 1250000000, 1250000000},
+ .tc_period = 10,
+ .n_pipes_per_subport_enabled = 1024,
+ .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32},
+ .pipe_profiles = pipe_profile,
+ .n_pipe_profiles = 1,
+ .n_max_pipe_profiles = 1,
+ },
+};
+
+static struct rte_sched_port_params port_param = {
+ .socket = 0, /* computed */
+ .rate = 0, /* computed */
+ .mtu = 1522,
+ .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT,
+ .n_subports_per_port = 1,
+ .n_pipes_per_subport = 1024,
+};
+
+#define NB_MBUF 32
+#define MBUF_DATA_SZ (2048 + RTE_PKTMBUF_HEADROOM)
+#define MEMPOOL_CACHE_SZ 0
+#define SOCKET 0
+
+
+static struct rte_mempool *
+create_mempool(void)
+{
+ struct rte_mempool * mp;
+
+ mp = rte_mempool_lookup("test_sched");
+ if (!mp)
+ mp = rte_pktmbuf_pool_create("test_sched", NB_MBUF,
+ MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, SOCKET);
+
+ return mp;
+}
+
+static void
+prepare_pkt(struct rte_sched_port *port, struct rte_mbuf *mbuf)
+{
+ struct rte_ether_hdr *eth_hdr;
+ struct rte_vlan_hdr *vlan1, *vlan2;
+ struct rte_ipv4_hdr *ip_hdr;
+
+ /* Simulate a classifier */
+ eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr *);
+ vlan1 = (struct rte_vlan_hdr *)(&eth_hdr->ether_type);
+ vlan2 = (struct rte_vlan_hdr *)(
+ (uintptr_t)&eth_hdr->ether_type + sizeof(struct rte_vlan_hdr));
+ eth_hdr = (struct rte_ether_hdr *)(
+ (uintptr_t)&eth_hdr->ether_type +
+ 2 * sizeof(struct rte_vlan_hdr));
+ ip_hdr = (struct rte_ipv4_hdr *)(
+ (uintptr_t)eth_hdr + sizeof(eth_hdr->ether_type));
+
+ vlan1->vlan_tci = rte_cpu_to_be_16(SUBPORT);
+ vlan2->vlan_tci = rte_cpu_to_be_16(PIPE);
+ eth_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
+ ip_hdr->dst_addr = RTE_IPV4(0,0,TC,QUEUE);
+
+
+ rte_sched_port_pkt_write(port, mbuf, SUBPORT, PIPE, TC, QUEUE,
+ RTE_COLOR_YELLOW);
+
+ /* 64 byte packet */
+ mbuf->pkt_len = 60;
+ mbuf->data_len = 60;
+}
+
+
+/**
+ * test main entrance for library sched
+ */
+static int
+test_sched(void)
+{
+ struct rte_mempool *mp = NULL;
+ struct rte_sched_port *port = NULL;
+ uint32_t pipe;
+ struct rte_mbuf *in_mbufs[10];
+ struct rte_mbuf *out_mbufs[10];
+ int i;
+
+ int err;
+
+ mp = create_mempool();
+ TEST_ASSERT_NOT_NULL(mp, "Error creating mempool\n");
+
+ port_param.socket = 0;
+ port_param.rate = (uint64_t) 10000 * 1000 * 1000 / 8;
+
+ port = rte_sched_port_config(&port_param);
+ TEST_ASSERT_NOT_NULL(port, "Error config sched port\n");
+
+ err = rte_sched_subport_config(port, SUBPORT, subport_param);
+ TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err);
+
+ for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) {
+ err = rte_sched_pipe_config(port, SUBPORT, pipe, 0);
+ TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err);
+ }
+
+ for (i = 0; i < 10; i++) {
+ in_mbufs[i] = rte_pktmbuf_alloc(mp);
+ TEST_ASSERT_NOT_NULL(in_mbufs[i], "Packet allocation failed\n");
+ prepare_pkt(port, in_mbufs[i]);
+ }
+
+
+ err = rte_sched_port_enqueue(port, in_mbufs, 10);
+ TEST_ASSERT_EQUAL(err, 10, "Wrong enqueue, err=%d\n", err);
+
+ err = rte_sched_port_dequeue(port, out_mbufs, 10);
+ TEST_ASSERT_EQUAL(err, 10, "Wrong dequeue, err=%d\n", err);
+
+ for (i = 0; i < 10; i++) {
+ enum rte_color color;
+ uint32_t subport, traffic_class, queue;
+
+ color = rte_sched_port_pkt_read_color(out_mbufs[i]);
+ TEST_ASSERT_EQUAL(color, RTE_COLOR_YELLOW, "Wrong color\n");
+
+ rte_sched_port_pkt_read_tree_path(port, out_mbufs[i],
+ &subport, &pipe, &traffic_class, &queue);
+
+ TEST_ASSERT_EQUAL(subport, SUBPORT, "Wrong subport\n");
+ TEST_ASSERT_EQUAL(pipe, PIPE, "Wrong pipe\n");
+ TEST_ASSERT_EQUAL(traffic_class, TC, "Wrong traffic_class\n");
+ TEST_ASSERT_EQUAL(queue, QUEUE, "Wrong queue\n");
+
+ }
+
+
+ struct rte_sched_subport_stats subport_stats;
+ uint32_t tc_ov;
+ rte_sched_subport_read_stats(port, SUBPORT, &subport_stats, &tc_ov);
+#if 0
+ TEST_ASSERT_EQUAL(subport_stats.n_pkts_tc[TC-1], 10, "Wrong subport stats\n");
+#endif
+ struct rte_sched_queue_stats queue_stats;
+ uint16_t qlen;
+ rte_sched_queue_read_stats(port, QUEUE, &queue_stats, &qlen);
+#if 0
+ TEST_ASSERT_EQUAL(queue_stats.n_pkts, 10, "Wrong queue stats\n");
+#endif
+
+ rte_sched_port_free(port);
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(sched_autotest, test_sched);
diff --git a/src/spdk/dpdk/app/test/test_security.c b/src/spdk/dpdk/app/test/test_security.c
new file mode 100644
index 000000000..3076a4c5a
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_security.c
@@ -0,0 +1,2427 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ */
+
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_security.h>
+#include <rte_security_driver.h>
+
+/* Before including rte_test.h file you can define
+ * RTE_TEST_TRACE_FAILURE(_file, _line, _func) macro to better trace/debug test
+ * failures. Mostly useful in development phase.
+ */
+#ifndef RTE_TEST_TRACE_FAILURE
+#define RTE_TEST_TRACE_FAILURE(_file, _line, _func) \
+ RTE_LOG(DEBUG, EAL, "in %s:%d %s\n", _file, _line, _func)
+#endif
+
+#include <rte_test.h>
+#include "test.h"
+
+/**
+ * Security
+ * =======
+ *
+ * Basic unit tests of the librte_security API.
+ *
+ * Structure of the file:
+ * - macros for making tests more readable;
+ * - mockup structures and functions for rte_security_ops;
+ * - test suite and test cases setup and teardown functions;
+ * - tests functions;
+ * - declaration of testcases.
+ */
+
+
+/**
+ * Macros
+ *
+ * Set of macros for making tests easier to read.
+ */
+
+/**
+ * Verify condition inside mocked up function.
+ * Mockup function cannot return a test error, so the failure
+ * of assertion increases counter and print logs.
+ * The counter can be verified later to check if test case should fail.
+ *
+ * @param fail_counter fail counter
+ * @param cond condition expected to be true
+ * @param msg printf style formatting string for custom message
+ */
+#define MOCK_TEST_ASSERT(fail_counter, cond, msg, ...) do { \
+ if (!(cond)) { \
+ fail_counter++; \
+ RTE_LOG(DEBUG, EAL, "Test assert %s line %d failed: " \
+ msg "\n", __func__, __LINE__, \
+ ##__VA_ARGS__); \
+ RTE_TEST_TRACE_FAILURE(__FILE__, __LINE__, __func__); \
+ } \
+} while (0)
+
+/**
+ * Verify equality condition inside mocked up function.
+ * Mockup function cannot return a test error, so the failure
+ * of assertion increases counter and print logs.
+ * The counter can be verified later to check if test case should fail.
+ *
+ * @param fail_counter fail counter
+ * @param a first value of comparison
+ * @param b second value of comparison
+ * @param msg printf style formatting string for custom message
+ */
+#define MOCK_TEST_ASSERT_EQUAL(fail_counter, a, b, msg, ...) \
+ MOCK_TEST_ASSERT(fail_counter, (a) == (b), msg, ##__VA_ARGS__)
+
+/**
+ * Verify not null condition inside mocked up function.
+ * Mockup function cannot return a test error, so the failure
+ * of assertion increases counter and print logs.
+ * The counter can be verified later to check if test case should fail.
+ *
+ * @param fail_counter fail counter
+ * @param val value expected not to be NULL
+ * @param msg printf style formatting string for custom message
+ */
+#define MOCK_TEST_ASSERT_NOT_NULL(fail_counter, val, msg, ...) \
+ MOCK_TEST_ASSERT(fail_counter, (val) != NULL, msg, ##__VA_ARGS__)
+
+
+/**
+ * Verify if parameter of the mocked up function matches expected value.
+ * The expected value is stored in data structure in the field matching
+ * parameter name.
+ *
+ * @param data structure with expected values
+ * @param parameter name of the parameter (both field and parameter name)
+ * @param spec printf style spec for parameter
+ */
+#define MOCK_TEST_ASSERT_PARAMETER(data, parameter, spec) \
+ MOCK_TEST_ASSERT_EQUAL(data.failed, data.parameter, parameter, \
+ "Expecting parameter %s to be " spec \
+ " but it's " spec, RTE_STR(parameter), \
+ data.parameter, parameter)
+
+/**
+ * Wrap for MOCK_TEST_ASSERT_PARAMETER macro for pointer type parameters.
+ *
+ * @param data structure with expected values
+ * @param parameter name of the parameter (both field and parameter name)
+ */
+#define MOCK_TEST_ASSERT_POINTER_PARAMETER(data, parameter) \
+ MOCK_TEST_ASSERT_PARAMETER(data, parameter, "%p")
+
+/**
+ * Wrap for MOCK_TEST_ASSERT_PARAMETER macro for uint64_t type parameters.
+ *
+ * @param data structure with expected values
+ * @param parameter name of the parameter (both field and parameter name)
+ */
+#define MOCK_TEST_ASSERT_U64_PARAMETER(data, parameter) \
+ MOCK_TEST_ASSERT_PARAMETER(data, parameter, "%" PRIu64)
+
+/**
+ * Verify number of calls of the mocked up function
+ * and check if there were any fails during execution.
+ * The fails statistics inside mocked up functions are collected
+ * as "failed" field in mockup structures.
+ *
+ * @param mock_data structure with statistics (called, failed)
+ * @param exp_calls expected number of mockup function calls
+ */
+#define TEST_ASSERT_MOCK_CALLS(mock_data, exp_calls) do { \
+ TEST_ASSERT_EQUAL(exp_calls, mock_data.called, \
+ "Expecting sub op to be called %d times, " \
+ "but it's called %d times", \
+ exp_calls, mock_data.called); \
+ TEST_ASSERT_EQUAL(0, mock_data.failed, \
+ "Expecting sub op asserts not to fail, " \
+ "but they're failed %d times", \
+ mock_data.failed); \
+} while (0)
+
+/**
+ * Assert tested function result match expected value
+ *
+ * @param f_name name of tested function
+ * @param f_ret value returned by the function
+ * @param exp_ret expected returned value
+ * @param fmt printf style format for returned value
+ */
+#define TEST_ASSERT_MOCK_FUNCTION_CALL_RET(f_name, f_ret, exp_ret, fmt) \
+ TEST_ASSERT_EQUAL(exp_ret, f_ret, "Expecting " RTE_STR(f_name) \
+ " to return " fmt ", but it returned " fmt \
+ "\n", exp_ret, f_ret)
+
+/**
+ * Assert tested function result is not NULL
+ *
+ * @param f_name name of tested function
+ * @param f_ret value returned by the function
+ */
+#define TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(f_name, f_ret) \
+ TEST_ASSERT_NOT_NULL(f_ret, "Expecting " RTE_STR(f_name) \
+ " to return not NULL\n")
+
+/**
+ * Verify that sess_cnt counter value matches expected
+ *
+ * @param expected_sessions_count expected counter value
+ */
+#define TEST_ASSERT_SESSION_COUNT(expected_sessions_count) do { \
+ struct security_unittest_params *ut_params = &unittest_params; \
+ TEST_ASSERT_EQUAL(expected_sessions_count, \
+ ut_params->ctx.sess_cnt, \
+ "Expecting session counter to be %u," \
+ " but it's %u", expected_sessions_count, \
+ ut_params->ctx.sess_cnt); \
+} while (0)
+
+/**
+ * Verify usage of mempool by checking if number of allocated objects matches
+ * expectations. The mempool is used to manage objects for sessions data.
+ * A single object is acquired from mempool during session_create
+ * and put back in session_destroy.
+ *
+ * @param expected_mempool_usage expected number of used mempool objects
+ */
+#define TEST_ASSERT_MEMPOOL_USAGE(expected_mempool_usage) do { \
+ struct security_testsuite_params *ts_params = &testsuite_params;\
+ unsigned int mempool_usage; \
+ mempool_usage = rte_mempool_in_use_count( \
+ ts_params->session_mpool); \
+ TEST_ASSERT_EQUAL(expected_mempool_usage, mempool_usage, \
+ "Expecting %u mempool allocations, " \
+ "but there are %u allocated objects", \
+ expected_mempool_usage, mempool_usage); \
+} while (0)
+
+
+/**
+ * Mockup structures and functions for rte_security_ops;
+ *
+ * Set of structures for controlling mockup functions calls.
+ * Every mockup function X has its corresponding X_data structure
+ * and an instance of that structure X_exp.
+ * Structure contains parameters that a mockup function is expected
+ * to be called with, a value to return (.ret) and 2 statistics:
+ * .called (number of times the mockup function was called)
+ * and .failed (number of assertion fails during mockup function call).
+ *
+ * Mockup functions verify that the parameters they are called with match
+ * expected values. The expected values should be stored in corresponding
+ * structures prior to mockup functions call. Every failure of such
+ * verification increases .failed counter. Every call of mockup function
+ * increases .called counter. Function returns value stored in .ret field
+ * of the structure.
+ * In case of some parameters in some functions the expected value is unknown
+ * and cannot be detrmined prior to call. Such parameters are stored
+ * in structure and can be compared or analyzed later in test case code.
+ *
+ * Below structures and functions follow the rules just described.
+ * Additional remarks and exceptions are added in comments.
+ */
+
+/**
+ * session_create mockup
+ *
+ * Verified parameters: device, conf, mp.
+ * Saved, not verified parameters: sess.
+ */
+static struct mock_session_create_data {
+ void *device;
+ struct rte_security_session_conf *conf;
+ struct rte_security_session *sess;
+ struct rte_mempool *mp;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_session_create_exp = {NULL, NULL, NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_create(void *device,
+ struct rte_security_session_conf *conf,
+ struct rte_security_session *sess,
+ struct rte_mempool *mp)
+{
+ mock_session_create_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, device);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, conf);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_create_exp, mp);
+
+ mock_session_create_exp.sess = sess;
+
+ return mock_session_create_exp.ret;
+}
+
+/**
+ * session_update mockup
+ *
+ * Verified parameters: device, sess, conf.
+ */
+static struct mock_session_update_data {
+ void *device;
+ struct rte_security_session *sess;
+ struct rte_security_session_conf *conf;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_session_update_exp = {NULL, NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_update(void *device,
+ struct rte_security_session *sess,
+ struct rte_security_session_conf *conf)
+{
+ mock_session_update_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_update_exp, device);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_update_exp, sess);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_update_exp, conf);
+
+ return mock_session_update_exp.ret;
+}
+
+/**
+ * session_get_size mockup
+ *
+ * Verified parameters: device.
+ */
+static struct mock_session_get_size_data {
+ void *device;
+
+ unsigned int ret;
+
+ int called;
+ int failed;
+} mock_session_get_size_exp = {NULL, 0U, 0, 0};
+
+static unsigned int
+mock_session_get_size(void *device)
+{
+ mock_session_get_size_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_get_size_exp, device);
+
+ return mock_session_get_size_exp.ret;
+}
+
+/**
+ * session_stats_get mockup
+ *
+ * Verified parameters: device, sess, stats.
+ */
+static struct mock_session_stats_get_data {
+ void *device;
+ struct rte_security_session *sess;
+ struct rte_security_stats *stats;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_session_stats_get_exp = {NULL, NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_stats_get(void *device,
+ struct rte_security_session *sess,
+ struct rte_security_stats *stats)
+{
+ mock_session_stats_get_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_stats_get_exp, device);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_stats_get_exp, sess);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_stats_get_exp, stats);
+
+ return mock_session_stats_get_exp.ret;
+}
+
+/**
+ * session_destroy mockup
+ *
+ * Verified parameters: device, sess.
+ */
+static struct mock_session_destroy_data {
+ void *device;
+ struct rte_security_session *sess;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_session_destroy_exp = {NULL, NULL, 0, 0, 0};
+
+static int
+mock_session_destroy(void *device, struct rte_security_session *sess)
+{
+ mock_session_destroy_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, device);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_session_destroy_exp, sess);
+
+ return mock_session_destroy_exp.ret;
+}
+
+/**
+ * set_pkt_metadata mockup
+ *
+ * Verified parameters: device, sess, m, params.
+ */
+static struct mock_set_pkt_metadata_data {
+ void *device;
+ struct rte_security_session *sess;
+ struct rte_mbuf *m;
+ void *params;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_set_pkt_metadata_exp = {NULL, NULL, NULL, NULL, 0, 0, 0};
+
+static int
+mock_set_pkt_metadata(void *device,
+ struct rte_security_session *sess,
+ struct rte_mbuf *m,
+ void *params)
+{
+ mock_set_pkt_metadata_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_set_pkt_metadata_exp, device);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_set_pkt_metadata_exp, sess);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_set_pkt_metadata_exp, m);
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_set_pkt_metadata_exp, params);
+
+ return mock_set_pkt_metadata_exp.ret;
+}
+
+/**
+ * get_userdata mockup
+ *
+ * Verified parameters: device, md.
+ * The userdata parameter works as an output parameter, so a passed address
+ * is verified not to be NULL and filled with userdata stored in structure.
+ */
+static struct mock_get_userdata_data {
+ void *device;
+ uint64_t md;
+ void *userdata;
+
+ int ret;
+
+ int called;
+ int failed;
+} mock_get_userdata_exp = {NULL, 0UL, NULL, 0, 0, 0};
+
+static int
+mock_get_userdata(void *device,
+ uint64_t md,
+ void **userdata)
+{
+ mock_get_userdata_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_get_userdata_exp, device);
+ MOCK_TEST_ASSERT_U64_PARAMETER(mock_get_userdata_exp, md);
+
+ MOCK_TEST_ASSERT_NOT_NULL(mock_get_userdata_exp.failed,
+ userdata,
+ "Expecting parameter userdata not to be NULL but it's %p",
+ userdata);
+ *userdata = mock_get_userdata_exp.userdata;
+
+ return mock_get_userdata_exp.ret;
+}
+
+/**
+ * capabilities_get mockup
+ *
+ * Verified parameters: device.
+ */
+static struct mock_capabilities_get_data {
+ void *device;
+
+ struct rte_security_capability *ret;
+
+ int called;
+ int failed;
+} mock_capabilities_get_exp = {NULL, NULL, 0, 0};
+
+static const struct rte_security_capability *
+mock_capabilities_get(void *device)
+{
+ mock_capabilities_get_exp.called++;
+
+ MOCK_TEST_ASSERT_POINTER_PARAMETER(mock_capabilities_get_exp, device);
+
+ return mock_capabilities_get_exp.ret;
+}
+
+/**
+ * empty_ops
+ *
+ * is an empty security operations set (all function pointers set to NULL)
+ */
+struct rte_security_ops empty_ops = { NULL };
+
+/**
+ * mock_ops
+ *
+ * is a security operations set using mockup functions
+ */
+struct rte_security_ops mock_ops = {
+ .session_create = mock_session_create,
+ .session_update = mock_session_update,
+ .session_get_size = mock_session_get_size,
+ .session_stats_get = mock_session_stats_get,
+ .session_destroy = mock_session_destroy,
+ .set_pkt_metadata = mock_set_pkt_metadata,
+ .get_userdata = mock_get_userdata,
+ .capabilities_get = mock_capabilities_get,
+};
+
+
+/**
+ * Test suite and test cases setup and teardown functions.
+ */
+
+/**
+ * struct security_testsuite_params defines parameters initialized once
+ * for whole tests suite.
+ * Currently the only stored parameter is session_mpool a mempool created
+ * once in testsuite_setup and released in testsuite_teardown.
+ * The instance of this structure is stored in testsuite_params variable.
+ */
+static struct security_testsuite_params {
+ struct rte_mempool *session_mpool;
+} testsuite_params = { NULL };
+
+/**
+ * struct security_unittest_params defines parameters initialized
+ * for every test case. The parameters are initialized in ut_setup
+ * or ut_setup_with_session (depending on the testcase)
+ * and released in ut_teardown.
+ * The instance of this structure is stored in unittest_params variable.
+ */
+static struct security_unittest_params {
+ struct rte_security_ctx ctx;
+ struct rte_security_session_conf conf;
+ struct rte_security_session *sess;
+} unittest_params = {
+ .ctx = {
+ .device = NULL,
+ .ops = &mock_ops,
+ .sess_cnt = 0,
+ },
+ .sess = NULL,
+};
+
+#define SECURITY_TEST_MEMPOOL_NAME "SecurityTestsMempoolName"
+#define SECURITY_TEST_MEMPOOL_SIZE 15
+#define SECURITY_TEST_SESSION_OBJECT_SIZE sizeof(struct rte_security_session)
+
+/**
+ * testsuite_setup initializes whole test suite parameters.
+ * It creates a new mempool used in all test cases
+ * and verifies if it properly created.
+ */
+static int
+testsuite_setup(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ ts_params->session_mpool = rte_mempool_create(
+ SECURITY_TEST_MEMPOOL_NAME,
+ SECURITY_TEST_MEMPOOL_SIZE,
+ SECURITY_TEST_SESSION_OBJECT_SIZE,
+ 0, 0, NULL, NULL, NULL, NULL,
+ SOCKET_ID_ANY, 0);
+ TEST_ASSERT_NOT_NULL(ts_params->session_mpool,
+ "Cannot create mempool %s\n", rte_strerror(rte_errno));
+ return TEST_SUCCESS;
+}
+
+/**
+ * testsuite_teardown releases test suite wide parameters.
+ */
+static void
+testsuite_teardown(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ if (ts_params->session_mpool) {
+ rte_mempool_free(ts_params->session_mpool);
+ ts_params->session_mpool = NULL;
+ }
+}
+
+/**
+ * ut_setup initializes test case parameters to default values.
+ * It resets also any .called and .failed statistics of mockup functions
+ * usage.
+ */
+static int
+ut_setup(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.device = NULL;
+ ut_params->ctx.ops = &mock_ops;
+ ut_params->ctx.sess_cnt = 0;
+ ut_params->sess = NULL;
+
+ mock_session_create_exp.called = 0;
+ mock_session_update_exp.called = 0;
+ mock_session_get_size_exp.called = 0;
+ mock_session_stats_get_exp.called = 0;
+ mock_session_destroy_exp.called = 0;
+ mock_set_pkt_metadata_exp.called = 0;
+ mock_get_userdata_exp.called = 0;
+ mock_capabilities_get_exp.called = 0;
+
+ mock_session_create_exp.failed = 0;
+ mock_session_update_exp.failed = 0;
+ mock_session_get_size_exp.failed = 0;
+ mock_session_stats_get_exp.failed = 0;
+ mock_session_destroy_exp.failed = 0;
+ mock_set_pkt_metadata_exp.failed = 0;
+ mock_get_userdata_exp.failed = 0;
+ mock_capabilities_get_exp.failed = 0;
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * destroy_session_with_check is a helper function releasing session
+ * created with rte_security_session_create and stored in test case parameters.
+ * It's used both to release sessions created in test cases' bodies
+ * which are assigned to ut_params->sess
+ * as well as sessions created in ut_setup_with_session.
+ */
+static int
+destroy_session_with_check(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ if (ut_params->sess != NULL) {
+ /* Assure that mockup function for destroy operation is set. */
+ ut_params->ctx.ops = &mock_ops;
+
+ mock_session_destroy_exp.device = NULL;
+ mock_session_destroy_exp.sess = ut_params->sess;
+ mock_session_destroy_exp.ret = 0;
+ mock_session_destroy_exp.called = 0;
+ mock_session_destroy_exp.failed = 0;
+
+ int ret = rte_security_session_destroy(&ut_params->ctx,
+ ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, 0, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 1);
+
+ ut_params->sess = NULL;
+ }
+ return TEST_SUCCESS;
+}
+
+/**
+ * ut_teardown releases test case parameters.
+ */
+static void
+ut_teardown(void)
+{
+ destroy_session_with_check();
+}
+
+/**
+ * ut_setup_with_session initializes test case parameters by
+ * - calling standard ut_setup,
+ * - creating a session that can be used in test case.
+ */
+static int
+ut_setup_with_session(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct rte_security_session *sess;
+
+ int ret = ut_setup();
+ if (ret != TEST_SUCCESS)
+ return ret;
+
+ mock_session_create_exp.device = NULL;
+ mock_session_create_exp.conf = &ut_params->conf;
+ mock_session_create_exp.mp = ts_params->session_mpool;
+ mock_session_create_exp.ret = 0;
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(rte_security_session_create,
+ sess);
+ TEST_ASSERT_EQUAL(sess, mock_session_create_exp.sess,
+ "Expecting session_create to be called with %p sess"
+ " parameter, but it's called %p sess parameter",
+ sess, mock_session_create_exp.sess);
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
+
+ /*
+ * Store created session in test case parameters, so it can be released
+ * after test case in ut_teardown by destroy_session_with_check.
+ */
+ ut_params->sess = sess;
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * Test functions
+ *
+ * Each test function is related to a single test case.
+ * They are arranged by tested rte_security API function
+ * and by rte_security execution paths sequence in code.
+ */
+
+/**
+ * rte_security_session_create tests
+ */
+
+/**
+ * Test execution of rte_security_session_create with NULL instance
+ */
+static int
+test_session_create_inv_context(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ sess = rte_security_session_create(NULL, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_session_create_inv_context_ops(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ ut_params->ctx.ops = NULL;
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with empty
+ * security operations
+ */
+static int
+test_session_create_inv_context_ops_fun(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ ut_params->ctx.ops = &empty_ops;
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with NULL conf parameter
+ */
+static int
+test_session_create_inv_configuration(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ sess = rte_security_session_create(&ut_params->ctx, NULL,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create with NULL mp parameter
+ */
+static int
+test_session_create_inv_mempool(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create in case when mempool
+ * is fully used and no object can be got from it
+ */
+static int
+test_session_create_mempool_empty(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *tmp[SECURITY_TEST_MEMPOOL_SIZE];
+ struct rte_security_session *sess;
+
+ /* Get all available objects from mempool. */
+ int i, ret;
+ for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i) {
+ ret = rte_mempool_get(ts_params->session_mpool,
+ (void **)(&tmp[i]));
+ TEST_ASSERT_EQUAL(0, ret,
+ "Expect getting %d object from mempool"
+ " to succeed", i);
+ }
+ TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(SECURITY_TEST_MEMPOOL_SIZE);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ /* Put objects back to the pool. */
+ for (i = 0; i < SECURITY_TEST_MEMPOOL_SIZE; ++i)
+ rte_mempool_put(ts_params->session_mpool, (void *)(tmp[i]));
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create when session_create
+ * security operation fails
+ */
+static int
+test_session_create_ops_failure(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ mock_session_create_exp.device = NULL;
+ mock_session_create_exp.conf = &ut_params->conf;
+ mock_session_create_exp.mp = ts_params->session_mpool;
+ mock_session_create_exp.ret = -1; /* Return failure status. */
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_create,
+ sess, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_create in successful execution path
+ */
+static int
+test_session_create_success(void)
+{
+ struct security_testsuite_params *ts_params = &testsuite_params;
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_session *sess;
+
+ mock_session_create_exp.device = NULL;
+ mock_session_create_exp.conf = &ut_params->conf;
+ mock_session_create_exp.mp = ts_params->session_mpool;
+ mock_session_create_exp.ret = 0; /* Return success status. */
+
+ sess = rte_security_session_create(&ut_params->ctx, &ut_params->conf,
+ ts_params->session_mpool);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_NOT_NULL(rte_security_session_create,
+ sess);
+ TEST_ASSERT_EQUAL(sess, mock_session_create_exp.sess,
+ "Expecting session_create to be called with %p sess"
+ " parameter, but it's called %p sess parameter",
+ sess, mock_session_create_exp.sess);
+ TEST_ASSERT_MOCK_CALLS(mock_session_create_exp, 1);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ /*
+ * Store created session in test case parameters, so it can be released
+ * after test case in ut_teardown by destroy_session_with_check.
+ */
+ ut_params->sess = sess;
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_session_update tests
+ */
+
+/**
+ * Test execution of rte_security_session_update with NULL instance
+ */
+static int
+test_session_update_inv_context(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ int ret = rte_security_session_update(NULL, ut_params->sess,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_session_update_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = NULL;
+
+ int ret = rte_security_session_update(&ut_params->ctx, ut_params->sess,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update with empty
+ * security operations
+ */
+static int
+test_session_update_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = &empty_ops;
+
+ int ret = rte_security_session_update(&ut_params->ctx, ut_params->sess,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -ENOTSUP, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update with NULL conf parameter
+ */
+static int
+test_session_update_inv_configuration(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ int ret = rte_security_session_update(&ut_params->ctx, ut_params->sess,
+ NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update with NULL sess parameter
+ */
+static int
+test_session_update_inv_session(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ int ret = rte_security_session_update(&ut_params->ctx, NULL,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update when session_update
+ * security operation fails
+ */
+static int
+test_session_update_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_update_exp.device = NULL;
+ mock_session_update_exp.sess = ut_params->sess;
+ mock_session_update_exp.conf = &ut_params->conf;
+ mock_session_update_exp.ret = -1; /* Return failure status. */
+
+ int ret = rte_security_session_update(&ut_params->ctx, ut_params->sess,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, -1, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_update in successful execution path
+ */
+static int
+test_session_update_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_update_exp.device = NULL;
+ mock_session_update_exp.sess = ut_params->sess;
+ mock_session_update_exp.conf = &ut_params->conf;
+ mock_session_update_exp.ret = 0; /* Return success status. */
+
+ int ret = rte_security_session_update(&ut_params->ctx, ut_params->sess,
+ &ut_params->conf);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_update,
+ ret, 0, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_update_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_session_get_size tests
+ */
+
+/**
+ * Test execution of rte_security_session_get_size with NULL instance
+ */
+static int
+test_session_get_size_inv_context(void)
+{
+ unsigned int ret = rte_security_session_get_size(NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_get_size,
+ ret, 0, "%u");
+ TEST_ASSERT_MOCK_CALLS(mock_session_get_size_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_get_size with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_session_get_size_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = NULL;
+
+ unsigned int ret = rte_security_session_get_size(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_get_size,
+ ret, 0, "%u");
+ TEST_ASSERT_MOCK_CALLS(mock_session_get_size_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_get_size with empty
+ * security operations
+ */
+static int
+test_session_get_size_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = &empty_ops;
+
+ unsigned int ret = rte_security_session_get_size(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_get_size,
+ ret, 0, "%u");
+ TEST_ASSERT_MOCK_CALLS(mock_session_get_size_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_get_size when session_get_size
+ * security operation fails
+ */
+static int
+test_session_get_size_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_get_size_exp.device = NULL;
+ mock_session_get_size_exp.ret = 0;
+
+ unsigned int ret = rte_security_session_get_size(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_get_size,
+ ret, 0, "%u");
+ TEST_ASSERT_MOCK_CALLS(mock_session_get_size_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_get_size in successful execution path
+ */
+static int
+test_session_get_size_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_get_size_exp.device = NULL;
+ mock_session_get_size_exp.ret = 1024;
+
+ unsigned int ret = rte_security_session_get_size(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_get_size,
+ ret, 1024U, "%u");
+ TEST_ASSERT_MOCK_CALLS(mock_session_get_size_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_session_stats_get tests
+ */
+
+/**
+ * Test execution of rte_security_session_stats_get with NULL instance
+ */
+static int
+test_session_stats_get_inv_context(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_stats stats;
+
+ int ret = rte_security_session_stats_get(NULL, ut_params->sess, &stats);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_stats_get with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_session_stats_get_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_stats stats;
+ ut_params->ctx.ops = NULL;
+
+ int ret = rte_security_session_stats_get(&ut_params->ctx,
+ ut_params->sess, &stats);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_stats_get with empty
+ * security operations
+ */
+static int
+test_session_stats_get_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_stats stats;
+ ut_params->ctx.ops = &empty_ops;
+
+ int ret = rte_security_session_stats_get(&ut_params->ctx,
+ ut_params->sess, &stats);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, -ENOTSUP, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_stats_get with NULL stats parameter
+ */
+static int
+test_session_stats_get_inv_stats(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ int ret = rte_security_session_stats_get(&ut_params->ctx,
+ ut_params->sess, NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_stats_get when session_stats_get
+ * security operation fails
+ */
+static int
+test_session_stats_get_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_stats stats;
+
+ mock_session_stats_get_exp.device = NULL;
+ mock_session_stats_get_exp.sess = ut_params->sess;
+ mock_session_stats_get_exp.stats = &stats;
+ mock_session_stats_get_exp.ret = -1;
+
+ int ret = rte_security_session_stats_get(&ut_params->ctx,
+ ut_params->sess, &stats);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, -1, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_stats_get in successful execution
+ * path
+ */
+static int
+test_session_stats_get_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_stats stats;
+
+ mock_session_stats_get_exp.device = NULL;
+ mock_session_stats_get_exp.sess = ut_params->sess;
+ mock_session_stats_get_exp.stats = &stats;
+ mock_session_stats_get_exp.ret = 0;
+
+ int ret = rte_security_session_stats_get(&ut_params->ctx,
+ ut_params->sess, &stats);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_stats_get,
+ ret, 0, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_stats_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_session_destroy tests
+ */
+
+/**
+ * Test execution of rte_security_session_destroy with NULL instance
+ */
+static int
+test_session_destroy_inv_context(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(NULL, ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_destroy with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_session_destroy_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = NULL;
+
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(&ut_params->ctx,
+ ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_destroy with empty
+ * security operations
+ */
+static int
+test_session_destroy_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = &empty_ops;
+
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(&ut_params->ctx,
+ ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, -ENOTSUP, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_destroy with NULL sess parameter
+ */
+static int
+test_session_destroy_inv_session(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(&ut_params->ctx, NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 0);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_destroy when session_destroy
+ * security operation fails
+ */
+static int
+test_session_destroy_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_destroy_exp.device = NULL;
+ mock_session_destroy_exp.sess = ut_params->sess;
+ mock_session_destroy_exp.ret = -1;
+
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(&ut_params->ctx,
+ ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, -1, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 1);
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_session_destroy in successful execution path
+ */
+static int
+test_session_destroy_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_session_destroy_exp.device = NULL;
+ mock_session_destroy_exp.sess = ut_params->sess;
+ mock_session_destroy_exp.ret = 0;
+ TEST_ASSERT_MEMPOOL_USAGE(1);
+ TEST_ASSERT_SESSION_COUNT(1);
+
+ int ret = rte_security_session_destroy(&ut_params->ctx,
+ ut_params->sess);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_session_destroy,
+ ret, 0, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_session_destroy_exp, 1);
+ TEST_ASSERT_MEMPOOL_USAGE(0);
+ TEST_ASSERT_SESSION_COUNT(0);
+
+ /*
+ * Remove session from test case parameters, so it won't be destroyed
+ * during test case teardown.
+ */
+ ut_params->sess = NULL;
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_set_pkt_metadata tests
+ */
+
+/**
+ * Test execution of rte_security_set_pkt_metadata with NULL instance
+ */
+static int
+test_set_pkt_metadata_inv_context(void)
+{
+#ifdef RTE_DEBUG
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+
+ int ret = rte_security_set_pkt_metadata(NULL, ut_params->sess, &m,
+ &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 0);
+
+ return TEST_SUCCESS;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/**
+ * Test execution of rte_security_set_pkt_metadata with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_set_pkt_metadata_inv_context_ops(void)
+{
+#ifdef RTE_DEBUG
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+ ut_params->ctx.ops = NULL;
+
+ int ret = rte_security_set_pkt_metadata(&ut_params->ctx,
+ ut_params->sess, &m, &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 0);
+
+ return TEST_SUCCESS;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/**
+ * Test execution of rte_security_set_pkt_metadata with empty
+ * security operations
+ */
+static int
+test_set_pkt_metadata_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+ ut_params->ctx.ops = &empty_ops;
+
+ int ret = rte_security_set_pkt_metadata(&ut_params->ctx,
+ ut_params->sess, &m, &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, -ENOTSUP, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_set_pkt_metadata with NULL sess parameter
+ */
+static int
+test_set_pkt_metadata_inv_session(void)
+{
+#ifdef RTE_DEBUG
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+
+ int ret = rte_security_set_pkt_metadata(&ut_params->ctx, NULL,
+ &m, &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, -EINVAL, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 0);
+
+ return TEST_SUCCESS;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/**
+ * Test execution of rte_security_set_pkt_metadata when set_pkt_metadata
+ * security operation fails
+ */
+static int
+test_set_pkt_metadata_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+
+ mock_set_pkt_metadata_exp.device = NULL;
+ mock_set_pkt_metadata_exp.sess = ut_params->sess;
+ mock_set_pkt_metadata_exp.m = &m;
+ mock_set_pkt_metadata_exp.params = &params;
+ mock_set_pkt_metadata_exp.ret = -1;
+
+ int ret = rte_security_set_pkt_metadata(&ut_params->ctx,
+ ut_params->sess, &m, &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, -1, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_set_pkt_metadata in successful execution path
+ */
+static int
+test_set_pkt_metadata_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_mbuf m;
+ int params;
+
+ mock_set_pkt_metadata_exp.device = NULL;
+ mock_set_pkt_metadata_exp.sess = ut_params->sess;
+ mock_set_pkt_metadata_exp.m = &m;
+ mock_set_pkt_metadata_exp.params = &params;
+ mock_set_pkt_metadata_exp.ret = 0;
+
+ int ret = rte_security_set_pkt_metadata(&ut_params->ctx,
+ ut_params->sess, &m, &params);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_set_pkt_metadata,
+ ret, 0, "%d");
+ TEST_ASSERT_MOCK_CALLS(mock_set_pkt_metadata_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_get_userdata tests
+ */
+
+/**
+ * Test execution of rte_security_get_userdata with NULL instance
+ */
+static int
+test_get_userdata_inv_context(void)
+{
+#ifdef RTE_DEBUG
+ uint64_t md = 0xDEADBEEF;
+
+ void *ret = rte_security_get_userdata(NULL, md);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_get_userdata,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_get_userdata_exp, 0);
+
+ return TEST_SUCCESS;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/**
+ * Test execution of rte_security_get_userdata with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_get_userdata_inv_context_ops(void)
+{
+#ifdef RTE_DEBUG
+ struct security_unittest_params *ut_params = &unittest_params;
+ uint64_t md = 0xDEADBEEF;
+ ut_params->ctx.ops = NULL;
+
+ void *ret = rte_security_get_userdata(&ut_params->ctx, md);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_get_userdata,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_get_userdata_exp, 0);
+
+ return TEST_SUCCESS;
+#else
+ return TEST_SKIPPED;
+#endif
+}
+
+/**
+ * Test execution of rte_security_get_userdata with empty
+ * security operations
+ */
+static int
+test_get_userdata_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ uint64_t md = 0xDEADBEEF;
+ ut_params->ctx.ops = &empty_ops;
+
+ void *ret = rte_security_get_userdata(&ut_params->ctx, md);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_get_userdata,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_get_userdata_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_get_userdata when get_userdata
+ * security operation fails
+ */
+static int
+test_get_userdata_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ uint64_t md = 0xDEADBEEF;
+ void *userdata = (void *)0x7E577E57;
+
+ mock_get_userdata_exp.device = NULL;
+ mock_get_userdata_exp.md = md;
+ mock_get_userdata_exp.userdata = userdata;
+ mock_get_userdata_exp.ret = -1;
+
+ void *ret = rte_security_get_userdata(&ut_params->ctx, md);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_get_userdata,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_get_userdata_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_get_userdata in successful execution path
+ */
+static int
+test_get_userdata_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ uint64_t md = 0xDEADBEEF;
+ void *userdata = (void *)0x7E577E57;
+
+ mock_get_userdata_exp.device = NULL;
+ mock_get_userdata_exp.md = md;
+ mock_get_userdata_exp.userdata = userdata;
+ mock_get_userdata_exp.ret = 0;
+
+ void *ret = rte_security_get_userdata(&ut_params->ctx, md);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_get_userdata,
+ ret, userdata, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_get_userdata_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_capabilities_get tests
+ */
+
+/**
+ * Test execution of rte_security_capabilities_get with NULL instance
+ */
+static int
+test_capabilities_get_inv_context(void)
+{
+ const struct rte_security_capability *ret;
+ ret = rte_security_capabilities_get(NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capabilities_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capabilities_get with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_capabilities_get_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = NULL;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capabilities_get(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capabilities_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capabilities_get with empty
+ * security operations
+ */
+static int
+test_capabilities_get_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ ut_params->ctx.ops = &empty_ops;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capabilities_get(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capabilities_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capabilities_get when capabilities_get
+ * security operation fails
+ */
+static int
+test_capabilities_get_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = NULL;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capabilities_get(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capabilities_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capabilities_get in successful execution path
+ */
+static int
+test_capabilities_get_success(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability capabilities;
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = &capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capabilities_get(&ut_params->ctx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capabilities_get,
+ ret, &capabilities, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+
+/**
+ * rte_security_capability_get tests
+ */
+
+/**
+ * Test execution of rte_security_capability_get with NULL instance
+ */
+static int
+test_capability_get_inv_context(void)
+{
+ struct rte_security_capability_idx idx;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(NULL, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get with invalid
+ * security operations structure (NULL)
+ */
+static int
+test_capability_get_inv_context_ops(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx;
+ ut_params->ctx.ops = NULL;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get with empty
+ * security operations
+ */
+static int
+test_capability_get_inv_context_ops_fun(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx;
+ ut_params->ctx.ops = &empty_ops;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get with NULL idx parameter
+ */
+static int
+test_capability_get_inv_idx(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, NULL);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 0);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities_get
+ * security operation fails
+ */
+static int
+test_capability_get_ops_failure(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx;
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = NULL;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * is empty (contains only RTE_SECURITY_ACTION_TYPE_NONE ending entry)
+ */
+static int
+test_capability_get_empty_table(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx;
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching action
+ */
+static int
+test_capability_get_no_matching_action(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching protocol
+ */
+static int
+test_capability_get_no_matching_protocol(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when macsec protocol
+ * is searched and capabilities table contain proper entry.
+ * However macsec records search is not supported in rte_security.
+ */
+static int
+test_capability_get_no_support_for_macsec(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_MACSEC,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching ipsec proto field
+ */
+static int
+test_capability_get_ipsec_mismatch_proto(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_AH,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching ipsec mode field
+ */
+static int
+test_capability_get_ipsec_mismatch_mode(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching ipsec direction field
+ */
+static int
+test_capability_get_ipsec_mismatch_dir(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * contains matching ipsec entry
+ */
+static int
+test_capability_get_ipsec_match(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+ .ipsec = {
+ .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+ .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+ .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, &capabilities[1], "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching pdcp domain field
+ */
+static int
+test_capability_get_pdcp_mismatch_domain(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ .pdcp = {
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ .pdcp = {
+ .domain = RTE_SECURITY_PDCP_MODE_DATA,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, NULL, "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * contains matching pdcp entry
+ */
+static int
+test_capability_get_pdcp_match(void)
+{
+ struct security_unittest_params *ut_params = &unittest_params;
+ struct rte_security_capability_idx idx = {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ .pdcp = {
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ },
+ };
+ struct rte_security_capability capabilities[] = {
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+ .protocol = RTE_SECURITY_PROTOCOL_PDCP,
+ .pdcp = {
+ .domain = RTE_SECURITY_PDCP_MODE_CONTROL,
+ },
+ },
+ {
+ .action = RTE_SECURITY_ACTION_TYPE_NONE,
+ },
+ };
+
+ mock_capabilities_get_exp.device = NULL;
+ mock_capabilities_get_exp.ret = capabilities;
+
+ const struct rte_security_capability *ret;
+ ret = rte_security_capability_get(&ut_params->ctx, &idx);
+ TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+ ret, &capabilities[1], "%p");
+ TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+ return TEST_SUCCESS;
+}
+
+/**
+ * Declaration of testcases
+ */
+static struct unit_test_suite security_testsuite = {
+ .suite_name = "generic security",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_inv_context),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_inv_context_ops),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_inv_configuration),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_inv_mempool),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_mempool_empty),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_ops_failure),
+ TEST_CASE_ST(ut_setup, ut_teardown,
+ test_session_create_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_inv_configuration),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_inv_session),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_update_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_get_size_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_get_size_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_get_size_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_get_size_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_get_size_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_inv_stats),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_stats_get_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_inv_session),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_session_destroy_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_inv_session),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_set_pkt_metadata_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_get_userdata_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_get_userdata_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_get_userdata_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_get_userdata_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_get_userdata_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capabilities_get_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capabilities_get_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capabilities_get_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capabilities_get_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capabilities_get_success),
+
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_inv_context),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_inv_context_ops),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_inv_context_ops_fun),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_inv_idx),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_ops_failure),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_empty_table),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_no_matching_action),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_no_matching_protocol),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_no_support_for_macsec),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_ipsec_mismatch_proto),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_ipsec_mismatch_mode),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_ipsec_mismatch_dir),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_ipsec_match),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_pdcp_mismatch_domain),
+ TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+ test_capability_get_pdcp_match),
+
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_security(void)
+{
+ rte_log_set_global_level(RTE_LOG_DEBUG);
+ rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
+
+ return unit_test_suite_runner(&security_testsuite);
+}
+
+REGISTER_TEST_COMMAND(security_autotest, test_security);
diff --git a/src/spdk/dpdk/app/test/test_service_cores.c b/src/spdk/dpdk/app/test/test_service_cores.c
new file mode 100644
index 000000000..981e21213
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_service_cores.c
@@ -0,0 +1,944 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <rte_common.h>
+#include <rte_hexdump.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_cycles.h>
+
+#include <rte_service.h>
+#include <rte_service_component.h>
+
+#include "test.h"
+
+/* used as the service core ID */
+static uint32_t slcore_id;
+/* used as timestamp to detect if a service core is running */
+static uint64_t service_tick;
+/* used as a flag to check if a function was run */
+static uint32_t service_remote_launch_flag;
+
+#define SERVICE_DELAY 1
+
+#define DUMMY_SERVICE_NAME "dummy_service"
+#define MT_SAFE_SERVICE_NAME "mt_safe_service"
+
+static int
+testsuite_setup(void)
+{
+ slcore_id = rte_get_next_lcore(/* start core */ -1,
+ /* skip master */ 1,
+ /* wrap */ 0);
+
+ return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+ /* release service cores? */
+}
+
+static int32_t dummy_cb(void *args)
+{
+ RTE_SET_USED(args);
+ service_tick++;
+ rte_delay_ms(SERVICE_DELAY);
+ return 0;
+}
+
+static int32_t dummy_mt_unsafe_cb(void *args)
+{
+ /* before running test, the initialization has set pass_test to 1.
+ * If the cmpset in service-cores is working correctly, the code here
+ * should never fail to take the lock. If the lock *is* taken, fail the
+ * test, because two threads are concurrently in a non-MT safe callback.
+ */
+ uint32_t *test_params = args;
+ uint32_t *atomic_lock = &test_params[0];
+ uint32_t *pass_test = &test_params[1];
+ int lock_taken = rte_atomic32_cmpset(atomic_lock, 0, 1);
+ if (lock_taken) {
+ /* delay with the lock held */
+ rte_delay_ms(250);
+ rte_atomic32_clear((rte_atomic32_t *)atomic_lock);
+ } else {
+ /* 2nd thread will fail to take lock, so set pass flag */
+ *pass_test = 0;
+ }
+
+ return 0;
+}
+
+
+static int32_t dummy_mt_safe_cb(void *args)
+{
+ /* Atomic checks to ensure MT safe services allow > 1 thread to
+ * concurrently run the callback. The concept is as follows;
+ * 1) if lock is available, take the lock then delay
+ * 2) if first lock is taken, and a thread arrives in the CB, we know
+ * that 2 threads are running the callback at the same time: MT safe
+ */
+ uint32_t *test_params = args;
+ uint32_t *atomic_lock = &test_params[0];
+ uint32_t *pass_test = &test_params[1];
+ int lock_taken = rte_atomic32_cmpset(atomic_lock, 0, 1);
+ if (lock_taken) {
+ /* delay with the lock held */
+ rte_delay_ms(250);
+ rte_atomic32_clear((rte_atomic32_t *)atomic_lock);
+ } else {
+ /* 2nd thread will fail to take lock, so set pass flag */
+ *pass_test = 1;
+ }
+
+ return 0;
+}
+
+/* unregister all services */
+static int
+unregister_all(void)
+{
+ uint32_t i;
+
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_component_unregister(1000),
+ "Unregistered invalid service id");
+
+ uint32_t c = rte_service_get_count();
+ for (i = 0; i < c; i++) {
+ TEST_ASSERT_EQUAL(0, rte_service_component_unregister(i),
+ "Error unregistering a valid service");
+ }
+
+ rte_service_lcore_reset_all();
+
+ return TEST_SUCCESS;
+}
+
+/* register a single dummy service */
+static int
+dummy_register(void)
+{
+ /* make sure there are no remains from previous tests */
+ unregister_all();
+
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+
+ TEST_ASSERT_EQUAL(-EINVAL,
+ rte_service_component_register(&service, NULL),
+ "Invalid callback");
+ service.callback = dummy_cb;
+
+ TEST_ASSERT_EQUAL(-EINVAL,
+ rte_service_component_register(&service, NULL),
+ "Invalid name");
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
+ "Failed to register valid service");
+
+ rte_service_component_runstate_set(id, 1);
+
+ return TEST_SUCCESS;
+}
+
+/* verify get_by_name() service lookup */
+static int
+service_get_by_name(void)
+{
+ unregister_all();
+
+ uint32_t sid;
+ TEST_ASSERT_EQUAL(-ENODEV,
+ rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid),
+ "get by name with invalid name should return -ENODEV");
+ TEST_ASSERT_EQUAL(-EINVAL,
+ rte_service_get_by_name(DUMMY_SERVICE_NAME, 0x0),
+ "get by name with NULL ptr should return -ENODEV");
+
+ /* register service */
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ TEST_ASSERT_EQUAL(-EINVAL,
+ rte_service_component_register(&service, NULL),
+ "Invalid callback");
+ service.callback = dummy_cb;
+ TEST_ASSERT_EQUAL(-EINVAL,
+ rte_service_component_register(&service, NULL),
+ "Invalid name");
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL),
+ "Failed to register valid service");
+
+ /* we unregistered all service, now registering 1, should be id 0 */
+ uint32_t service_id_as_expected = 0;
+ TEST_ASSERT_EQUAL(0, rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid),
+ "Service get_by_name should return 0 on valid inputs");
+ TEST_ASSERT_EQUAL(service_id_as_expected, sid,
+ "Service get_by_name should equal expected id");
+
+ unregister_all();
+
+ /* ensure after unregister, get_by_name returns NULL */
+ TEST_ASSERT_EQUAL(-ENODEV,
+ rte_service_get_by_name(DUMMY_SERVICE_NAME, &sid),
+ "get by name should return -ENODEV after unregister");
+
+ return TEST_SUCCESS;
+}
+
+/* verify probe of capabilities */
+static int
+service_probe_capability(void)
+{
+ unregister_all();
+
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ service.callback = dummy_cb;
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+ service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL),
+ "Register of MT SAFE service failed");
+
+ /* verify flag is enabled */
+ const uint32_t sid = 0;
+ int32_t mt = rte_service_probe_capability(sid, RTE_SERVICE_CAP_MT_SAFE);
+ TEST_ASSERT_EQUAL(1, mt, "MT SAFE capability flag not set.");
+
+
+ unregister_all();
+
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ service.callback = dummy_cb;
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, NULL),
+ "Register of non-MT safe service failed");
+
+ /* verify flag is enabled */
+ mt = rte_service_probe_capability(sid, RTE_SERVICE_CAP_MT_SAFE);
+ TEST_ASSERT_EQUAL(0, mt, "MT SAFE cap flag set on non MT SAFE service");
+
+ return unregister_all();
+}
+
+/* verify the service name */
+static int
+service_name(void)
+{
+ const char *name = rte_service_get_name(0);
+ int equal = strcmp(name, DUMMY_SERVICE_NAME);
+ TEST_ASSERT_EQUAL(0, equal, "Error: Service name not correct");
+
+ return unregister_all();
+}
+
+/* verify service attr get */
+static int
+service_attr_get(void)
+{
+ /* ensure all services unregistered so cycle counts are zero */
+ unregister_all();
+
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ service.callback = dummy_cb;
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+ service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
+ "Register of service failed");
+ rte_service_component_runstate_set(id, 1);
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1),
+ "Error: Service start returned non-zero");
+ rte_service_set_stats_enable(id, 1);
+
+ uint32_t attr_id = UINT32_MAX;
+ uint64_t attr_value = 0xdead;
+ /* check error return values */
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(id, attr_id,
+ &attr_value),
+ "Invalid attr_id didn't return -EINVAL");
+
+ attr_id = RTE_SERVICE_ATTR_CYCLES;
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(UINT32_MAX, attr_id,
+ &attr_value),
+ "Invalid service id didn't return -EINVAL");
+
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_attr_get(id, attr_id, NULL),
+ "Invalid attr_value pointer id didn't return -EINVAL");
+
+ /* check correct (zero) return value and correct value (zero) */
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value),
+ "Valid attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(0, attr_value,
+ "attr_get() call didn't set correct cycles (zero)");
+ /* check correct call count */
+ const int attr_calls = RTE_SERVICE_ATTR_CALL_COUNT;
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value),
+ "Valid attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(0, attr_value,
+ "attr_get() call didn't get call count (zero)");
+
+ /* Call service to increment cycle count */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Service core add did not return zero");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1),
+ "Enabling valid service and core failed");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id),
+ "Starting service core failed");
+
+ /* wait for the service lcore to run */
+ rte_delay_ms(200);
+
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value),
+ "Valid attr_get() call didn't return success");
+ int cycles_gt_zero = attr_value > 0;
+ TEST_ASSERT_EQUAL(1, cycles_gt_zero,
+ "attr_get() failed to get cycles (expected > zero)");
+
+ rte_service_lcore_stop(slcore_id);
+
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value),
+ "Valid attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(1, (attr_value > 0),
+ "attr_get() call didn't get call count (zero)");
+
+ TEST_ASSERT_EQUAL(0, rte_service_attr_reset_all(id),
+ "Valid attr_reset_all() return success");
+
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_id, &attr_value),
+ "Valid attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(0, attr_value,
+ "attr_get() call didn't set correct cycles (zero)");
+ /* ensure call count > zero */
+ TEST_ASSERT_EQUAL(0, rte_service_attr_get(id, attr_calls, &attr_value),
+ "Valid attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(0, (attr_value > 0),
+ "attr_get() call didn't get call count (zero)");
+
+ return unregister_all();
+}
+
+/* verify service lcore attr get */
+static int
+service_lcore_attr_get(void)
+{
+ /* ensure all services unregistered so cycle counts are zero */
+ unregister_all();
+
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ service.callback = dummy_cb;
+ snprintf(service.name, sizeof(service.name), DUMMY_SERVICE_NAME);
+ service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
+ "Register of service failed");
+ rte_service_component_runstate_set(id, 1);
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(id, 1),
+ "Error: Service start returned non-zero");
+ rte_service_set_stats_enable(id, 1);
+
+ uint64_t lcore_attr_value = 0xdead;
+ uint32_t lcore_attr_id = UINT32_MAX;
+
+ /* check error return values */
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(UINT32_MAX,
+ lcore_attr_id, &lcore_attr_value),
+ "Invalid lcore_id didn't return -EINVAL");
+ TEST_ASSERT_EQUAL(-ENOTSUP, rte_service_lcore_attr_get(rte_lcore_id(),
+ lcore_attr_id, &lcore_attr_value),
+ "Non-service core didn't return -ENOTSUP");
+
+ /* Start service core to increment loop count */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Service core add did not return zero");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(id, slcore_id, 1),
+ "Enabling valid service and core failed");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id),
+ "Starting service core failed");
+
+ /* wait for the service lcore to run */
+ rte_delay_ms(200);
+
+ lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS;
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id,
+ lcore_attr_id, &lcore_attr_value),
+ "Valid lcore_attr_get() call didn't return success");
+ int loops_gt_zero = lcore_attr_value > 0;
+ TEST_ASSERT_EQUAL(1, loops_gt_zero,
+ "lcore_attr_get() failed to get loops "
+ "(expected > zero)");
+
+ lcore_attr_id++; // invalid lcore attr id
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_attr_get(slcore_id,
+ lcore_attr_id, &lcore_attr_value),
+ "Invalid lcore attr didn't return -EINVAL");
+
+ rte_service_lcore_stop(slcore_id);
+
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_reset_all(slcore_id),
+ "Valid lcore_attr_reset_all() didn't return success");
+
+ lcore_attr_id = RTE_SERVICE_LCORE_ATTR_LOOPS;
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_attr_get(slcore_id,
+ lcore_attr_id, &lcore_attr_value),
+ "Valid lcore_attr_get() call didn't return success");
+ TEST_ASSERT_EQUAL(0, lcore_attr_value,
+ "lcore_attr_get() didn't get correct loop count "
+ "(zero)");
+
+ return unregister_all();
+}
+
+/* verify service dump */
+static int
+service_dump(void)
+{
+ const uint32_t sid = 0;
+ rte_service_set_stats_enable(sid, 1);
+ rte_service_dump(stdout, 0);
+ rte_service_set_stats_enable(sid, 0);
+ rte_service_dump(stdout, 0);
+ return unregister_all();
+}
+
+/* start and stop a service */
+static int
+service_start_stop(void)
+{
+ const uint32_t sid = 0;
+
+ /* runstate_get() returns if service is running and slcore is mapped */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Service core add did not return zero");
+ int ret = rte_service_map_lcore_set(sid, slcore_id, 1);
+ TEST_ASSERT_EQUAL(0, ret,
+ "Enabling service core, expected 0 got %d", ret);
+
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid),
+ "Error: Service should be stopped");
+
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
+ "Error: Service stopped returned non-zero");
+
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_get(sid),
+ "Error: Service is running - should be stopped");
+
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1),
+ "Error: Service start returned non-zero");
+
+ TEST_ASSERT_EQUAL(1, rte_service_runstate_get(sid),
+ "Error: Service is not running");
+
+ return unregister_all();
+}
+
+
+static int
+service_remote_launch_func(void *arg)
+{
+ RTE_SET_USED(arg);
+ service_remote_launch_flag = 1;
+ return 0;
+}
+
+/* enable and disable a lcore for a service */
+static int
+service_lcore_en_dis_able(void)
+{
+ const uint32_t sid = 0;
+
+ /* expected failure cases */
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 1),
+ "Enable on invalid core did not fail");
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, 100000, 0),
+ "Disable on invalid core did not fail");
+
+ /* add service core to allow enabling */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Add service core failed when not in use before");
+
+ /* valid enable */
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1),
+ "Enabling valid service and core failed");
+ TEST_ASSERT_EQUAL(1, rte_service_map_lcore_get(sid, slcore_id),
+ "Enabled core returned not-enabled");
+
+ /* valid disable */
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 0),
+ "Disabling valid service and lcore failed");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_get(sid, slcore_id),
+ "Disabled core returned enabled");
+
+ /* call remote_launch to verify that app can launch ex-service lcore */
+ service_remote_launch_flag = 0;
+ rte_eal_wait_lcore(slcore_id);
+ int ret = rte_eal_remote_launch(service_remote_launch_func, NULL,
+ slcore_id);
+ TEST_ASSERT_EQUAL(0, ret, "Ex-service core remote launch failed.");
+ rte_eal_wait_lcore(slcore_id);
+ TEST_ASSERT_EQUAL(1, service_remote_launch_flag,
+ "Ex-service core function call had no effect.");
+
+ return unregister_all();
+}
+
+static int
+service_lcore_running_check(void)
+{
+ uint64_t tick = service_tick;
+ rte_delay_ms(SERVICE_DELAY * 100);
+ /* if (tick != service_tick) we know the lcore as polled the service */
+ return tick != service_tick;
+}
+
+static int
+service_lcore_add_del(void)
+{
+ if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) ||
+ !rte_lcore_is_enabled(2) || !rte_lcore_is_enabled(3))
+ return TEST_SKIPPED;
+
+ /* check initial count */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_count(),
+ "Service lcore count has value before adding a lcore");
+
+ /* check service lcore add */
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Add service core failed when not in use before");
+ TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_add(slcore_id),
+ "Add service core failed to refuse in-use lcore");
+
+ /* check count */
+ TEST_ASSERT_EQUAL(1, rte_service_lcore_count(),
+ "Service core count not equal to one");
+
+ /* retrieve core list, checking lcore ids */
+ const uint32_t size = 4;
+ uint32_t service_core_ids[size];
+ int32_t n = rte_service_lcore_list(service_core_ids, size);
+ TEST_ASSERT_EQUAL(1, n, "Service core list return should equal 1");
+ TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0],
+ "Service core list lcore must equal slcore_id");
+
+ /* recheck count, add more cores, and check count */
+ TEST_ASSERT_EQUAL(1, rte_service_lcore_count(),
+ "Service core count not equal to one");
+ uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1,
+ /* skip master */ 1,
+ /* wrap */ 0);
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1),
+ "Service core add did not return zero");
+ uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1,
+ /* skip master */ 1,
+ /* wrap */ 0);
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2),
+ "Service core add did not return zero");
+
+ uint32_t count = rte_service_lcore_count();
+ const uint32_t cores_at_this_point = 3;
+ TEST_ASSERT_EQUAL(cores_at_this_point, count,
+ "Service core count %d, expected %d", count,
+ cores_at_this_point);
+
+ /* check longer service core list */
+ n = rte_service_lcore_list(service_core_ids, size);
+ TEST_ASSERT_EQUAL(3, n, "Service core list return should equal 3");
+ TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0],
+ "Service core list[0] lcore must equal 1");
+ TEST_ASSERT_EQUAL(slcore_1, service_core_ids[1],
+ "Service core list[1] lcore must equal 2");
+ TEST_ASSERT_EQUAL(slcore_2, service_core_ids[2],
+ "Service core list[2] lcore must equal 3");
+
+ /* recheck count, remove lcores, check remaining lcore_id is correct */
+ TEST_ASSERT_EQUAL(3, rte_service_lcore_count(),
+ "Service core count not equal to three");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_1),
+ "Service core add did not return zero");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_2),
+ "Service core add did not return zero");
+ TEST_ASSERT_EQUAL(1, rte_service_lcore_count(),
+ "Service core count not equal to one");
+ n = rte_service_lcore_list(service_core_ids, size);
+ TEST_ASSERT_EQUAL(1, n, "Service core list return should equal one");
+ TEST_ASSERT_EQUAL(slcore_id, service_core_ids[0],
+ "Service core list[0] lcore must equal %d",
+ slcore_id);
+
+ return unregister_all();
+}
+
+static int
+service_threaded_test(int mt_safe)
+{
+ unregister_all();
+
+ /* add next 2 cores */
+ uint32_t slcore_1 = rte_get_next_lcore(/* start core */ -1,
+ /* skip master */ 1,
+ /* wrap */ 0);
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_1),
+ "mt safe lcore add fail");
+ uint32_t slcore_2 = rte_get_next_lcore(/* start core */ slcore_1,
+ /* skip master */ 1,
+ /* wrap */ 0);
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_2),
+ "mt safe lcore add fail");
+
+ /* Use atomic locks to verify that two threads are in the same function
+ * at the same time. These are passed to the unit tests through the
+ * callback userdata parameter
+ */
+ uint32_t test_params[2];
+ memset(test_params, 0, sizeof(uint32_t) * 2);
+
+ /* register MT safe service. */
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ service.callback_userdata = test_params;
+ snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME);
+
+ if (mt_safe) {
+ service.callback = dummy_mt_safe_cb;
+ service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
+ } else
+ service.callback = dummy_mt_unsafe_cb;
+
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
+ "Register of MT SAFE service failed");
+
+ const uint32_t sid = 0;
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1),
+ "Starting valid service failed");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_1, 1),
+ "Failed to enable lcore 1 on mt safe service");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_2, 1),
+ "Failed to enable lcore 2 on mt safe service");
+ rte_service_lcore_start(slcore_1);
+ rte_service_lcore_start(slcore_2);
+
+ /* wait for the worker threads to run */
+ rte_delay_ms(500);
+ rte_service_lcore_stop(slcore_1);
+ rte_service_lcore_stop(slcore_2);
+
+ TEST_ASSERT_EQUAL(0, test_params[1],
+ "Service run with component runstate = 0");
+
+ /* enable backend runstate: the service should run after this */
+ rte_service_component_runstate_set(id, 1);
+
+ /* initialize to pass, see callback comment for details */
+ if (!mt_safe)
+ test_params[1] = 1;
+
+ /* wait for lcores before start() */
+ rte_eal_wait_lcore(slcore_1);
+ rte_eal_wait_lcore(slcore_2);
+
+ rte_service_lcore_start(slcore_1);
+ rte_service_lcore_start(slcore_2);
+
+ /* wait for the worker threads to run */
+ rte_delay_ms(500);
+ rte_service_lcore_stop(slcore_1);
+ rte_service_lcore_stop(slcore_2);
+
+ TEST_ASSERT_EQUAL(1, test_params[1],
+ "MT Safe service not run by two cores concurrently");
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
+ "Failed to stop MT Safe service");
+
+ rte_eal_wait_lcore(slcore_1);
+ rte_eal_wait_lcore(slcore_2);
+ unregister_all();
+
+ /* return the value of the callback pass_test variable to caller */
+ return test_params[1];
+}
+
+/* tests an MT SAFE service with two cores. The callback function ensures that
+ * two threads access the callback concurrently.
+ */
+static int
+service_mt_safe_poll(void)
+{
+ int mt_safe = 1;
+
+ if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) ||
+ !rte_lcore_is_enabled(2))
+ return TEST_SKIPPED;
+
+ TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe),
+ "Error: MT Safe service not run by two cores concurrently");
+ return TEST_SUCCESS;
+}
+
+/* tests a NON mt safe service with two cores, the callback is serialized
+ * using the atomic cmpset.
+ */
+static int
+service_mt_unsafe_poll(void)
+{
+ int mt_safe = 0;
+
+ if (!rte_lcore_is_enabled(0) || !rte_lcore_is_enabled(1) ||
+ !rte_lcore_is_enabled(2))
+ return TEST_SKIPPED;
+
+ TEST_ASSERT_EQUAL(1, service_threaded_test(mt_safe),
+ "Error: NON MT Safe service run by two cores concurrently");
+ return TEST_SUCCESS;
+}
+
+static int32_t
+delay_as_a_mt_safe_service(void *args)
+{
+ RTE_SET_USED(args);
+ uint32_t *params = args;
+
+ /* retrieve done flag and atomic lock to inc/dec */
+ uint32_t *done = &params[0];
+ rte_atomic32_t *lock = (rte_atomic32_t *)&params[1];
+
+ while (!*done) {
+ rte_atomic32_inc(lock);
+ rte_delay_us(500);
+ if (rte_atomic32_read(lock) > 1)
+ /* pass: second core has simultaneously incremented */
+ *done = 1;
+ rte_atomic32_dec(lock);
+ }
+
+ return 0;
+}
+
+static int32_t
+delay_as_a_service(void *args)
+{
+ uint32_t *done = (uint32_t *)args;
+ while (!*done)
+ rte_delay_ms(5);
+ return 0;
+}
+
+static int
+service_run_on_app_core_func(void *arg)
+{
+ uint32_t *delay_service_id = (uint32_t *)arg;
+ return rte_service_run_iter_on_app_lcore(*delay_service_id, 1);
+}
+
+static int
+service_app_lcore_poll_impl(const int mt_safe)
+{
+ uint32_t params[2] = {0};
+
+ struct rte_service_spec service;
+ memset(&service, 0, sizeof(struct rte_service_spec));
+ snprintf(service.name, sizeof(service.name), MT_SAFE_SERVICE_NAME);
+ if (mt_safe) {
+ service.callback = delay_as_a_mt_safe_service;
+ service.callback_userdata = params;
+ service.capabilities |= RTE_SERVICE_CAP_MT_SAFE;
+ } else {
+ service.callback = delay_as_a_service;
+ service.callback_userdata = &params;
+ }
+
+ uint32_t id;
+ TEST_ASSERT_EQUAL(0, rte_service_component_register(&service, &id),
+ "Register of app lcore delay service failed");
+
+ rte_service_component_runstate_set(id, 1);
+ rte_service_runstate_set(id, 1);
+
+ uint32_t app_core2 = rte_get_next_lcore(slcore_id, 1, 1);
+ rte_eal_wait_lcore(app_core2);
+ int app_core2_ret = rte_eal_remote_launch(service_run_on_app_core_func,
+ &id, app_core2);
+
+ rte_delay_ms(100);
+
+ int app_core1_ret = service_run_on_app_core_func(&id);
+
+ /* flag done, then wait for the spawned 2nd core to return */
+ params[0] = 1;
+ rte_eal_mp_wait_lcore();
+
+ /* core two gets launched first - and should hold the service lock */
+ TEST_ASSERT_EQUAL(0, app_core2_ret,
+ "App core2 : run service didn't return zero");
+
+ if (mt_safe) {
+ /* mt safe should have both cores return 0 for success */
+ TEST_ASSERT_EQUAL(0, app_core1_ret,
+ "MT Safe: App core1 didn't return 0");
+ } else {
+ /* core one attempts to run later - should be blocked */
+ TEST_ASSERT_EQUAL(-EBUSY, app_core1_ret,
+ "MT Unsafe: App core1 didn't return -EBUSY");
+ }
+
+ /* Performance test: call in a loop, and measure tsc() */
+ const uint32_t perf_iters = (1 << 12);
+ uint64_t start = rte_rdtsc();
+ uint32_t i;
+ for (i = 0; i < perf_iters; i++) {
+ int err = service_run_on_app_core_func(&id);
+ TEST_ASSERT_EQUAL(0, err, "perf test: returned run failure");
+ }
+ uint64_t end = rte_rdtsc();
+ printf("perf test for %s: %0.1f cycles per call\n", mt_safe ?
+ "MT Safe" : "MT Unsafe", (end - start)/(float)perf_iters);
+
+ unregister_all();
+ return TEST_SUCCESS;
+}
+
+static int
+service_app_lcore_mt_safe(void)
+{
+ const int mt_safe = 1;
+ return service_app_lcore_poll_impl(mt_safe);
+}
+
+static int
+service_app_lcore_mt_unsafe(void)
+{
+ const int mt_safe = 0;
+ return service_app_lcore_poll_impl(mt_safe);
+}
+
+/* start and stop a service core - ensuring it goes back to sleep */
+static int
+service_lcore_start_stop(void)
+{
+ /* start service core and service, create mapping so tick() runs */
+ const uint32_t sid = 0;
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1),
+ "Starting valid service failed");
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_map_lcore_set(sid, slcore_id, 1),
+ "Enabling valid service on non-service core must fail");
+
+ /* core start */
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_start(slcore_id),
+ "Service core start without add should return EINVAL");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Service core add did not return zero");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1),
+ "Enabling valid service on valid core failed");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id),
+ "Service core start after add failed");
+ TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_start(slcore_id),
+ "Service core expected as running but was stopped");
+
+ /* ensures core really is running the service function */
+ TEST_ASSERT_EQUAL(1, service_lcore_running_check(),
+ "Service core expected to poll service but it didn't");
+
+ /* core stop */
+ TEST_ASSERT_EQUAL(-EBUSY, rte_service_lcore_stop(slcore_id),
+ "Service core running a service should return -EBUSY");
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
+ "Stopping valid service failed");
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_lcore_stop(100000),
+ "Invalid Service core stop should return -EINVAL");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_stop(slcore_id),
+ "Service core stop expected to return 0");
+ TEST_ASSERT_EQUAL(-EALREADY, rte_service_lcore_stop(slcore_id),
+ "Already stopped service core should return -EALREADY");
+
+ /* ensure service is not longer running */
+ TEST_ASSERT_EQUAL(0, service_lcore_running_check(),
+ "Service core expected to poll service but it didn't");
+
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_del(slcore_id),
+ "Service core del did not return zero");
+
+ return unregister_all();
+}
+
+/* stop a service and wait for it to become inactive */
+static int
+service_may_be_active(void)
+{
+ const uint32_t sid = 0;
+ int i;
+
+ /* expected failure cases */
+ TEST_ASSERT_EQUAL(-EINVAL, rte_service_may_be_active(10000),
+ "Invalid service may be active check did not fail");
+
+ /* start the service */
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 1),
+ "Starting valid service failed");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_add(slcore_id),
+ "Add service core failed when not in use before");
+ TEST_ASSERT_EQUAL(0, rte_service_map_lcore_set(sid, slcore_id, 1),
+ "Enabling valid service on valid core failed");
+ TEST_ASSERT_EQUAL(0, rte_service_lcore_start(slcore_id),
+ "Service core start after add failed");
+
+ /* ensures core really is running the service function */
+ TEST_ASSERT_EQUAL(1, service_lcore_running_check(),
+ "Service core expected to poll service but it didn't");
+
+ /* stop the service */
+ TEST_ASSERT_EQUAL(0, rte_service_runstate_set(sid, 0),
+ "Error: Service stop returned non-zero");
+
+ /* give the service 100ms to stop running */
+ for (i = 0; i < 100; i++) {
+ if (!rte_service_may_be_active(sid))
+ break;
+ rte_delay_ms(SERVICE_DELAY);
+ }
+
+ TEST_ASSERT_EQUAL(0, rte_service_may_be_active(sid),
+ "Error: Service not stopped after 100ms");
+
+ return unregister_all();
+}
+
+static struct unit_test_suite service_tests = {
+ .suite_name = "service core test suite",
+ .setup = testsuite_setup,
+ .teardown = testsuite_teardown,
+ .unit_test_cases = {
+ TEST_CASE_ST(dummy_register, NULL, unregister_all),
+ TEST_CASE_ST(dummy_register, NULL, service_name),
+ TEST_CASE_ST(dummy_register, NULL, service_get_by_name),
+ TEST_CASE_ST(dummy_register, NULL, service_dump),
+ TEST_CASE_ST(dummy_register, NULL, service_attr_get),
+ TEST_CASE_ST(dummy_register, NULL, service_lcore_attr_get),
+ TEST_CASE_ST(dummy_register, NULL, service_probe_capability),
+ TEST_CASE_ST(dummy_register, NULL, service_start_stop),
+ TEST_CASE_ST(dummy_register, NULL, service_lcore_add_del),
+ TEST_CASE_ST(dummy_register, NULL, service_lcore_start_stop),
+ TEST_CASE_ST(dummy_register, NULL, service_lcore_en_dis_able),
+ TEST_CASE_ST(dummy_register, NULL, service_mt_unsafe_poll),
+ TEST_CASE_ST(dummy_register, NULL, service_mt_safe_poll),
+ TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_safe),
+ TEST_CASE_ST(dummy_register, NULL, service_app_lcore_mt_unsafe),
+ TEST_CASE_ST(dummy_register, NULL, service_may_be_active),
+ TEST_CASES_END() /**< NULL terminate unit test array */
+ }
+};
+
+static int
+test_service_common(void)
+{
+ return unit_test_suite_runner(&service_tests);
+}
+
+REGISTER_TEST_COMMAND(service_autotest, test_service_common);
diff --git a/src/spdk/dpdk/app/test/test_spinlock.c b/src/spdk/dpdk/app/test/test_spinlock.c
new file mode 100644
index 000000000..842990ed3
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_spinlock.c
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_cycles.h>
+#include <rte_spinlock.h>
+#include <rte_atomic.h>
+
+#include "test.h"
+
+/*
+ * Spinlock test
+ * =============
+ *
+ * - There is a global spinlock and a table of spinlocks (one per lcore).
+ *
+ * - The test function takes all of these locks and launches the
+ * ``test_spinlock_per_core()`` function on each core (except the master).
+ *
+ * - The function takes the global lock, display something, then releases
+ * the global lock.
+ * - The function takes the per-lcore lock, display something, then releases
+ * the per-core lock.
+ *
+ * - The main function unlocks the per-lcore locks sequentially and
+ * waits between each lock. This triggers the display of a message
+ * for each core, in the correct order. The autotest script checks that
+ * this order is correct.
+ *
+ * - A load test is carried out, with all cores attempting to lock a single lock
+ * multiple times
+ */
+
+static rte_spinlock_t sl, sl_try;
+static rte_spinlock_t sl_tab[RTE_MAX_LCORE];
+static rte_spinlock_recursive_t slr;
+static unsigned count = 0;
+
+static rte_atomic32_t synchro;
+
+static int
+test_spinlock_per_core(__rte_unused void *arg)
+{
+ rte_spinlock_lock(&sl);
+ printf("Global lock taken on core %u\n", rte_lcore_id());
+ rte_spinlock_unlock(&sl);
+
+ rte_spinlock_lock(&sl_tab[rte_lcore_id()]);
+ printf("Hello from core %u !\n", rte_lcore_id());
+ rte_spinlock_unlock(&sl_tab[rte_lcore_id()]);
+
+ return 0;
+}
+
+static int
+test_spinlock_recursive_per_core(__rte_unused void *arg)
+{
+ unsigned id = rte_lcore_id();
+
+ rte_spinlock_recursive_lock(&slr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, slr.count);
+ rte_spinlock_recursive_lock(&slr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, slr.count);
+ rte_spinlock_recursive_lock(&slr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, slr.count);
+
+ printf("Hello from within recursive locks from core %u !\n", id);
+
+ rte_spinlock_recursive_unlock(&slr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, slr.count);
+ rte_spinlock_recursive_unlock(&slr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, slr.count);
+ rte_spinlock_recursive_unlock(&slr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, slr.count);
+
+ return 0;
+}
+
+static rte_spinlock_t lk = RTE_SPINLOCK_INITIALIZER;
+static uint64_t time_count[RTE_MAX_LCORE] = {0};
+
+#define MAX_LOOP 10000
+
+static int
+load_loop_fn(void *func_param)
+{
+ uint64_t time_diff = 0, begin;
+ uint64_t hz = rte_get_timer_hz();
+ volatile uint64_t lcount = 0;
+ const int use_lock = *(int*)func_param;
+ const unsigned lcore = rte_lcore_id();
+
+ /* wait synchro for slaves */
+ if (lcore != rte_get_master_lcore())
+ while (rte_atomic32_read(&synchro) == 0);
+
+ begin = rte_get_timer_cycles();
+ while (lcount < MAX_LOOP) {
+ if (use_lock)
+ rte_spinlock_lock(&lk);
+ lcount++;
+ if (use_lock)
+ rte_spinlock_unlock(&lk);
+ }
+ time_diff = rte_get_timer_cycles() - begin;
+ time_count[lcore] = time_diff * 1000000 / hz;
+ return 0;
+}
+
+static int
+test_spinlock_perf(void)
+{
+ unsigned int i;
+ uint64_t total = 0;
+ int lock = 0;
+ const unsigned lcore = rte_lcore_id();
+
+ printf("\nTest with no lock on single core...\n");
+ load_loop_fn(&lock);
+ printf("Core [%u] Cost Time = %"PRIu64" us\n", lcore,
+ time_count[lcore]);
+ memset(time_count, 0, sizeof(time_count));
+
+ printf("\nTest with lock on single core...\n");
+ lock = 1;
+ load_loop_fn(&lock);
+ printf("Core [%u] Cost Time = %"PRIu64" us\n", lcore,
+ time_count[lcore]);
+ memset(time_count, 0, sizeof(time_count));
+
+ printf("\nTest with lock on %u cores...\n", rte_lcore_count());
+
+ /* Clear synchro and start slaves */
+ rte_atomic32_set(&synchro, 0);
+ rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER);
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(&lock);
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_LCORE_FOREACH(i) {
+ printf("Core [%u] Cost Time = %"PRIu64" us\n", i,
+ time_count[i]);
+ total += time_count[i];
+ }
+
+ printf("Total Cost Time = %"PRIu64" us\n", total);
+
+ return 0;
+}
+
+/*
+ * Use rte_spinlock_trylock() to trylock a spinlock object,
+ * If it could not lock the object successfully, it would
+ * return immediately and the variable of "count" would be
+ * increased by one per times. the value of "count" could be
+ * checked as the result later.
+ */
+static int
+test_spinlock_try(__rte_unused void *arg)
+{
+ if (rte_spinlock_trylock(&sl_try) == 0) {
+ rte_spinlock_lock(&sl);
+ count ++;
+ rte_spinlock_unlock(&sl);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Test rte_eal_get_lcore_state() in addition to spinlocks
+ * as we have "waiting" then "running" lcores.
+ */
+static int
+test_spinlock(void)
+{
+ int ret = 0;
+ int i;
+
+ /* slave cores should be waiting: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+
+ rte_spinlock_init(&sl);
+ rte_spinlock_init(&sl_try);
+ rte_spinlock_recursive_init(&slr);
+ for (i=0; i<RTE_MAX_LCORE; i++)
+ rte_spinlock_init(&sl_tab[i]);
+
+ rte_spinlock_lock(&sl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_spinlock_lock(&sl_tab[i]);
+ rte_eal_remote_launch(test_spinlock_per_core, NULL, i);
+ }
+
+ /* slave cores should be busy: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+ rte_spinlock_unlock(&sl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_spinlock_unlock(&sl_tab[i]);
+ rte_delay_ms(10);
+ }
+
+ rte_eal_mp_wait_lcore();
+
+ rte_spinlock_recursive_lock(&slr);
+
+ /*
+ * Try to acquire a lock that we already own
+ */
+ if(!rte_spinlock_recursive_trylock(&slr)) {
+ printf("rte_spinlock_recursive_trylock failed on a lock that "
+ "we already own\n");
+ ret = -1;
+ } else
+ rte_spinlock_recursive_unlock(&slr);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_spinlock_recursive_per_core, NULL, i);
+ }
+ rte_spinlock_recursive_unlock(&slr);
+ rte_eal_mp_wait_lcore();
+
+ /*
+ * Test if it could return immediately from try-locking a locked object.
+ * Here it will lock the spinlock object first, then launch all the slave
+ * lcores to trylock the same spinlock object.
+ * All the slave lcores should give up try-locking a locked object and
+ * return immediately, and then increase the "count" initialized with zero
+ * by one per times.
+ * We can check if the "count" is finally equal to the number of all slave
+ * lcores to see if the behavior of try-locking a locked spinlock object
+ * is correct.
+ */
+ if (rte_spinlock_trylock(&sl_try) == 0) {
+ return -1;
+ }
+ count = 0;
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_spinlock_try, NULL, i);
+ }
+ rte_eal_mp_wait_lcore();
+ rte_spinlock_unlock(&sl_try);
+ if (rte_spinlock_is_locked(&sl)) {
+ printf("spinlock is locked but it should not be\n");
+ return -1;
+ }
+ rte_spinlock_lock(&sl);
+ if (count != ( rte_lcore_count() - 1)) {
+ ret = -1;
+ }
+ rte_spinlock_unlock(&sl);
+
+ /*
+ * Test if it can trylock recursively.
+ * Use rte_spinlock_recursive_trylock() to check if it can lock a spinlock
+ * object recursively. Here it will try to lock a spinlock object twice.
+ */
+ if (rte_spinlock_recursive_trylock(&slr) == 0) {
+ printf("It failed to do the first spinlock_recursive_trylock but it should able to do\n");
+ return -1;
+ }
+ if (rte_spinlock_recursive_trylock(&slr) == 0) {
+ printf("It failed to do the second spinlock_recursive_trylock but it should able to do\n");
+ return -1;
+ }
+ rte_spinlock_recursive_unlock(&slr);
+ rte_spinlock_recursive_unlock(&slr);
+
+ if (test_spinlock_perf() < 0)
+ return -1;
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(spinlock_autotest, test_spinlock);
diff --git a/src/spdk/dpdk/app/test/test_stack.c b/src/spdk/dpdk/app/test/test_stack.c
new file mode 100644
index 000000000..c8dac1f55
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_stack.c
@@ -0,0 +1,426 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <string.h>
+
+#include <rte_atomic.h>
+#include <rte_lcore.h>
+#include <rte_malloc.h>
+#include <rte_random.h>
+#include <rte_stack.h>
+
+#include "test.h"
+
+#define STACK_SIZE 4096
+#define MAX_BULK 32
+
+static int
+test_stack_push_pop(struct rte_stack *s, void **obj_table, unsigned int bulk_sz)
+{
+ unsigned int i, ret;
+ void **popped_objs;
+
+ popped_objs = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
+ if (popped_objs == NULL) {
+ printf("[%s():%u] failed to calloc %zu bytes\n",
+ __func__, __LINE__, STACK_SIZE * sizeof(void *));
+ return -1;
+ }
+
+ for (i = 0; i < STACK_SIZE; i += bulk_sz) {
+ ret = rte_stack_push(s, &obj_table[i], bulk_sz);
+
+ if (ret != bulk_sz) {
+ printf("[%s():%u] push returned: %d (expected %u)\n",
+ __func__, __LINE__, ret, bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+
+ if (rte_stack_count(s) != i + bulk_sz) {
+ printf("[%s():%u] stack count: %u (expected %u)\n",
+ __func__, __LINE__, rte_stack_count(s),
+ i + bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+
+ if (rte_stack_free_count(s) != STACK_SIZE - i - bulk_sz) {
+ printf("[%s():%u] stack free count: %u (expected %u)\n",
+ __func__, __LINE__, rte_stack_count(s),
+ STACK_SIZE - i - bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < STACK_SIZE; i += bulk_sz) {
+ ret = rte_stack_pop(s, &popped_objs[i], bulk_sz);
+
+ if (ret != bulk_sz) {
+ printf("[%s():%u] pop returned: %d (expected %u)\n",
+ __func__, __LINE__, ret, bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+
+ if (rte_stack_count(s) != STACK_SIZE - i - bulk_sz) {
+ printf("[%s():%u] stack count: %u (expected %u)\n",
+ __func__, __LINE__, rte_stack_count(s),
+ STACK_SIZE - i - bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+
+ if (rte_stack_free_count(s) != i + bulk_sz) {
+ printf("[%s():%u] stack free count: %u (expected %u)\n",
+ __func__, __LINE__, rte_stack_count(s),
+ i + bulk_sz);
+ rte_free(popped_objs);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < STACK_SIZE; i++) {
+ if (obj_table[i] != popped_objs[STACK_SIZE - i - 1]) {
+ printf("[%s():%u] Incorrect value %p at index 0x%x\n",
+ __func__, __LINE__,
+ popped_objs[STACK_SIZE - i - 1], i);
+ rte_free(popped_objs);
+ return -1;
+ }
+ }
+
+ rte_free(popped_objs);
+
+ return 0;
+}
+
+static int
+test_stack_basic(uint32_t flags)
+{
+ struct rte_stack *s = NULL;
+ void **obj_table = NULL;
+ int i, ret = -1;
+
+ obj_table = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
+ if (obj_table == NULL) {
+ printf("[%s():%u] failed to calloc %zu bytes\n",
+ __func__, __LINE__, STACK_SIZE * sizeof(void *));
+ goto fail_test;
+ }
+
+ for (i = 0; i < STACK_SIZE; i++)
+ obj_table[i] = (void *)(uintptr_t)i;
+
+ s = rte_stack_create(__func__, STACK_SIZE, rte_socket_id(), flags);
+ if (s == NULL) {
+ printf("[%s():%u] failed to create a stack\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ if (rte_stack_lookup(__func__) != s) {
+ printf("[%s():%u] failed to lookup a stack\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ if (rte_stack_count(s) != 0) {
+ printf("[%s():%u] stack count: %u (expected 0)\n",
+ __func__, __LINE__, rte_stack_count(s));
+ goto fail_test;
+ }
+
+ if (rte_stack_free_count(s) != STACK_SIZE) {
+ printf("[%s():%u] stack free count: %u (expected %u)\n",
+ __func__, __LINE__, rte_stack_count(s), STACK_SIZE);
+ goto fail_test;
+ }
+
+ ret = test_stack_push_pop(s, obj_table, 1);
+ if (ret) {
+ printf("[%s():%u] Single object push/pop failed\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ ret = test_stack_push_pop(s, obj_table, MAX_BULK);
+ if (ret) {
+ printf("[%s():%u] Bulk object push/pop failed\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ ret = rte_stack_push(s, obj_table, 2 * STACK_SIZE);
+ if (ret != 0) {
+ printf("[%s():%u] Excess objects push succeeded\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ ret = rte_stack_pop(s, obj_table, 1);
+ if (ret != 0) {
+ printf("[%s():%u] Empty stack pop succeeded\n",
+ __func__, __LINE__);
+ goto fail_test;
+ }
+
+ ret = 0;
+
+fail_test:
+ rte_stack_free(s);
+
+ rte_free(obj_table);
+
+ return ret;
+}
+
+static int
+test_stack_name_reuse(uint32_t flags)
+{
+ struct rte_stack *s[2];
+
+ s[0] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
+ if (s[0] == NULL) {
+ printf("[%s():%u] Failed to create a stack\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ s[1] = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
+ if (s[1] != NULL) {
+ printf("[%s():%u] Failed to detect re-used name\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ rte_stack_free(s[0]);
+
+ return 0;
+}
+
+static int
+test_stack_name_length(uint32_t flags)
+{
+ char name[RTE_STACK_NAMESIZE + 1];
+ struct rte_stack *s;
+
+ memset(name, 's', sizeof(name));
+ name[RTE_STACK_NAMESIZE] = '\0';
+
+ s = rte_stack_create(name, STACK_SIZE, rte_socket_id(), flags);
+ if (s != NULL) {
+ printf("[%s():%u] Failed to prevent long name\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_errno != ENAMETOOLONG) {
+ printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_lookup_null(void)
+{
+ struct rte_stack *s = rte_stack_lookup("stack_not_found");
+
+ if (s != NULL) {
+ printf("[%s():%u] rte_stack found a non-existent stack\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_errno != ENOENT) {
+ printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ s = rte_stack_lookup(NULL);
+
+ if (s != NULL) {
+ printf("[%s():%u] rte_stack found a non-existent stack\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ if (rte_errno != EINVAL) {
+ printf("[%s():%u] rte_stack failed to set correct errno on failed lookup\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+test_free_null(void)
+{
+ /* Check whether the library proper handles a NULL pointer */
+ rte_stack_free(NULL);
+
+ return 0;
+}
+
+#define NUM_ITERS_PER_THREAD 100000
+
+struct test_args {
+ struct rte_stack *s;
+ rte_atomic64_t *sz;
+};
+
+static int
+stack_thread_push_pop(void *args)
+{
+ struct test_args *t = args;
+ void **obj_table;
+ int i;
+
+ obj_table = rte_calloc(NULL, STACK_SIZE, sizeof(void *), 0);
+ if (obj_table == NULL) {
+ printf("[%s():%u] failed to calloc %zu bytes\n",
+ __func__, __LINE__, STACK_SIZE * sizeof(void *));
+ return -1;
+ }
+
+ for (i = 0; i < NUM_ITERS_PER_THREAD; i++) {
+ unsigned int success, num;
+
+ /* Reserve up to min(MAX_BULK, available slots) stack entries,
+ * then push and pop those stack entries.
+ */
+ do {
+ uint64_t sz = rte_atomic64_read(t->sz);
+ volatile uint64_t *sz_addr;
+
+ sz_addr = (volatile uint64_t *)t->sz;
+
+ num = RTE_MIN(rte_rand() % MAX_BULK, STACK_SIZE - sz);
+
+ success = rte_atomic64_cmpset(sz_addr, sz, sz + num);
+ } while (success == 0);
+
+ if (rte_stack_push(t->s, obj_table, num) != num) {
+ printf("[%s():%u] Failed to push %u pointers\n",
+ __func__, __LINE__, num);
+ rte_free(obj_table);
+ return -1;
+ }
+
+ if (rte_stack_pop(t->s, obj_table, num) != num) {
+ printf("[%s():%u] Failed to pop %u pointers\n",
+ __func__, __LINE__, num);
+ rte_free(obj_table);
+ return -1;
+ }
+
+ rte_atomic64_sub(t->sz, num);
+ }
+
+ rte_free(obj_table);
+ return 0;
+}
+
+static int
+test_stack_multithreaded(uint32_t flags)
+{
+ struct test_args *args;
+ unsigned int lcore_id;
+ struct rte_stack *s;
+ rte_atomic64_t size;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for test_stack_multithreaded, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ printf("[%s():%u] Running with %u lcores\n",
+ __func__, __LINE__, rte_lcore_count());
+
+ args = rte_malloc(NULL, sizeof(struct test_args) * RTE_MAX_LCORE, 0);
+ if (args == NULL) {
+ printf("[%s():%u] failed to malloc %zu bytes\n",
+ __func__, __LINE__,
+ sizeof(struct test_args) * RTE_MAX_LCORE);
+ return -1;
+ }
+
+ s = rte_stack_create("test", STACK_SIZE, rte_socket_id(), flags);
+ if (s == NULL) {
+ printf("[%s():%u] Failed to create a stack\n",
+ __func__, __LINE__);
+ rte_free(args);
+ return -1;
+ }
+
+ rte_atomic64_init(&size);
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ args[lcore_id].s = s;
+ args[lcore_id].sz = &size;
+
+ if (rte_eal_remote_launch(stack_thread_push_pop,
+ &args[lcore_id], lcore_id))
+ rte_panic("Failed to launch lcore %d\n", lcore_id);
+ }
+
+ lcore_id = rte_lcore_id();
+
+ args[lcore_id].s = s;
+ args[lcore_id].sz = &size;
+
+ stack_thread_push_pop(&args[lcore_id]);
+
+ rte_eal_mp_wait_lcore();
+
+ rte_stack_free(s);
+ rte_free(args);
+
+ return 0;
+}
+
+static int
+__test_stack(uint32_t flags)
+{
+ if (test_stack_basic(flags) < 0)
+ return -1;
+
+ if (test_lookup_null() < 0)
+ return -1;
+
+ if (test_free_null() < 0)
+ return -1;
+
+ if (test_stack_name_reuse(flags) < 0)
+ return -1;
+
+ if (test_stack_name_length(flags) < 0)
+ return -1;
+
+ if (test_stack_multithreaded(flags) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+test_stack(void)
+{
+ return __test_stack(0);
+}
+
+static int
+test_lf_stack(void)
+{
+ return __test_stack(RTE_STACK_F_LF);
+}
+
+REGISTER_TEST_COMMAND(stack_autotest, test_stack);
+REGISTER_TEST_COMMAND(stack_lf_autotest, test_lf_stack);
diff --git a/src/spdk/dpdk/app/test/test_stack_perf.c b/src/spdk/dpdk/app/test/test_stack_perf.c
new file mode 100644
index 000000000..3ab7267b1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_stack_perf.c
@@ -0,0 +1,356 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_launch.h>
+#include <rte_pause.h>
+#include <rte_stack.h>
+
+#include "test.h"
+
+#define STACK_NAME "STACK_PERF"
+#define MAX_BURST 32
+#define STACK_SIZE (RTE_MAX_LCORE * MAX_BURST)
+
+/*
+ * Push/pop bulk sizes, marked volatile so they aren't treated as compile-time
+ * constants.
+ */
+static volatile unsigned int bulk_sizes[] = {8, MAX_BURST};
+
+static rte_atomic32_t lcore_barrier;
+
+struct lcore_pair {
+ unsigned int c1;
+ unsigned int c2;
+};
+
+static int
+get_two_hyperthreads(struct lcore_pair *lcp)
+{
+ unsigned int socket[2];
+ unsigned int core[2];
+ unsigned int id[2];
+
+ RTE_LCORE_FOREACH(id[0]) {
+ RTE_LCORE_FOREACH(id[1]) {
+ if (id[0] == id[1])
+ continue;
+ core[0] = rte_lcore_to_cpu_id(id[0]);
+ core[1] = rte_lcore_to_cpu_id(id[1]);
+ socket[0] = rte_lcore_to_socket_id(id[0]);
+ socket[1] = rte_lcore_to_socket_id(id[1]);
+ if ((core[0] == core[1]) && (socket[0] == socket[1])) {
+ lcp->c1 = id[0];
+ lcp->c2 = id[1];
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+get_two_cores(struct lcore_pair *lcp)
+{
+ unsigned int socket[2];
+ unsigned int core[2];
+ unsigned int id[2];
+
+ RTE_LCORE_FOREACH(id[0]) {
+ RTE_LCORE_FOREACH(id[1]) {
+ if (id[0] == id[1])
+ continue;
+ core[0] = rte_lcore_to_cpu_id(id[0]);
+ core[1] = rte_lcore_to_cpu_id(id[1]);
+ socket[0] = rte_lcore_to_socket_id(id[0]);
+ socket[1] = rte_lcore_to_socket_id(id[1]);
+ if ((core[0] != core[1]) && (socket[0] == socket[1])) {
+ lcp->c1 = id[0];
+ lcp->c2 = id[1];
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+get_two_sockets(struct lcore_pair *lcp)
+{
+ unsigned int socket[2];
+ unsigned int id[2];
+
+ RTE_LCORE_FOREACH(id[0]) {
+ RTE_LCORE_FOREACH(id[1]) {
+ if (id[0] == id[1])
+ continue;
+ socket[0] = rte_lcore_to_socket_id(id[0]);
+ socket[1] = rte_lcore_to_socket_id(id[1]);
+ if (socket[0] != socket[1]) {
+ lcp->c1 = id[0];
+ lcp->c2 = id[1];
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/* Measure the cycle cost of popping an empty stack. */
+static void
+test_empty_pop(struct rte_stack *s)
+{
+ unsigned int iterations = 100000000;
+ void *objs[MAX_BURST];
+ unsigned int i;
+
+ uint64_t start = rte_rdtsc();
+
+ for (i = 0; i < iterations; i++)
+ rte_stack_pop(s, objs, bulk_sizes[0]);
+
+ uint64_t end = rte_rdtsc();
+
+ printf("Stack empty pop: %.2F\n",
+ (double)(end - start) / iterations);
+}
+
+struct thread_args {
+ struct rte_stack *s;
+ unsigned int sz;
+ double avg;
+};
+
+/* Measure the average per-pointer cycle cost of stack push and pop */
+static int
+bulk_push_pop(void *p)
+{
+ unsigned int iterations = 1000000;
+ struct thread_args *args = p;
+ void *objs[MAX_BURST] = {0};
+ unsigned int size, i;
+ struct rte_stack *s;
+
+ s = args->s;
+ size = args->sz;
+
+ rte_atomic32_sub(&lcore_barrier, 1);
+ while (rte_atomic32_read(&lcore_barrier) != 0)
+ rte_pause();
+
+ uint64_t start = rte_rdtsc();
+
+ for (i = 0; i < iterations; i++) {
+ rte_stack_push(s, objs, size);
+ rte_stack_pop(s, objs, size);
+ }
+
+ uint64_t end = rte_rdtsc();
+
+ args->avg = ((double)(end - start))/(iterations * size);
+
+ return 0;
+}
+
+/*
+ * Run bulk_push_pop() simultaneously on pairs of cores, to measure stack
+ * perf when between hyperthread siblings, cores on the same socket, and cores
+ * on different sockets.
+ */
+static void
+run_on_core_pair(struct lcore_pair *cores, struct rte_stack *s,
+ lcore_function_t fn)
+{
+ struct thread_args args[2];
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
+ rte_atomic32_set(&lcore_barrier, 2);
+
+ args[0].sz = args[1].sz = bulk_sizes[i];
+ args[0].s = args[1].s = s;
+
+ if (cores->c1 == rte_get_master_lcore()) {
+ rte_eal_remote_launch(fn, &args[1], cores->c2);
+ fn(&args[0]);
+ rte_eal_wait_lcore(cores->c2);
+ } else {
+ rte_eal_remote_launch(fn, &args[0], cores->c1);
+ rte_eal_remote_launch(fn, &args[1], cores->c2);
+ rte_eal_wait_lcore(cores->c1);
+ rte_eal_wait_lcore(cores->c2);
+ }
+
+ printf("Average cycles per object push/pop (bulk size: %u): %.2F\n",
+ bulk_sizes[i], (args[0].avg + args[1].avg) / 2);
+ }
+}
+
+/* Run bulk_push_pop() simultaneously on 1+ cores. */
+static void
+run_on_n_cores(struct rte_stack *s, lcore_function_t fn, int n)
+{
+ struct thread_args args[RTE_MAX_LCORE];
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
+ unsigned int lcore_id;
+ int cnt = 0;
+ double avg;
+
+ rte_atomic32_set(&lcore_barrier, n);
+
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (++cnt >= n)
+ break;
+
+ args[lcore_id].s = s;
+ args[lcore_id].sz = bulk_sizes[i];
+
+ if (rte_eal_remote_launch(fn, &args[lcore_id],
+ lcore_id))
+ rte_panic("Failed to launch lcore %d\n",
+ lcore_id);
+ }
+
+ lcore_id = rte_lcore_id();
+
+ args[lcore_id].s = s;
+ args[lcore_id].sz = bulk_sizes[i];
+
+ fn(&args[lcore_id]);
+
+ rte_eal_mp_wait_lcore();
+
+ avg = args[rte_lcore_id()].avg;
+
+ cnt = 0;
+ RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+ if (++cnt >= n)
+ break;
+ avg += args[lcore_id].avg;
+ }
+
+ printf("Average cycles per object push/pop (bulk size: %u): %.2F\n",
+ bulk_sizes[i], avg / n);
+ }
+}
+
+/*
+ * Measure the cycle cost of pushing and popping a single pointer on a single
+ * lcore.
+ */
+static void
+test_single_push_pop(struct rte_stack *s)
+{
+ unsigned int iterations = 16000000;
+ void *obj = NULL;
+ unsigned int i;
+
+ uint64_t start = rte_rdtsc();
+
+ for (i = 0; i < iterations; i++) {
+ rte_stack_push(s, &obj, 1);
+ rte_stack_pop(s, &obj, 1);
+ }
+
+ uint64_t end = rte_rdtsc();
+
+ printf("Average cycles per single object push/pop: %.2F\n",
+ ((double)(end - start)) / iterations);
+}
+
+/* Measure the cycle cost of bulk pushing and popping on a single lcore. */
+static void
+test_bulk_push_pop(struct rte_stack *s)
+{
+ unsigned int iterations = 8000000;
+ void *objs[MAX_BURST];
+ unsigned int sz, i;
+
+ for (sz = 0; sz < RTE_DIM(bulk_sizes); sz++) {
+ uint64_t start = rte_rdtsc();
+
+ for (i = 0; i < iterations; i++) {
+ rte_stack_push(s, objs, bulk_sizes[sz]);
+ rte_stack_pop(s, objs, bulk_sizes[sz]);
+ }
+
+ uint64_t end = rte_rdtsc();
+
+ double avg = ((double)(end - start) /
+ (iterations * bulk_sizes[sz]));
+
+ printf("Average cycles per object push/pop (bulk size: %u): %.2F\n",
+ bulk_sizes[sz], avg);
+ }
+}
+
+static int
+__test_stack_perf(uint32_t flags)
+{
+ struct lcore_pair cores;
+ struct rte_stack *s;
+
+ rte_atomic32_init(&lcore_barrier);
+
+ s = rte_stack_create(STACK_NAME, STACK_SIZE, rte_socket_id(), flags);
+ if (s == NULL) {
+ printf("[%s():%u] failed to create a stack\n",
+ __func__, __LINE__);
+ return -1;
+ }
+
+ printf("### Testing single element push/pop ###\n");
+ test_single_push_pop(s);
+
+ printf("\n### Testing empty pop ###\n");
+ test_empty_pop(s);
+
+ printf("\n### Testing using a single lcore ###\n");
+ test_bulk_push_pop(s);
+
+ if (get_two_hyperthreads(&cores) == 0) {
+ printf("\n### Testing using two hyperthreads ###\n");
+ run_on_core_pair(&cores, s, bulk_push_pop);
+ }
+ if (get_two_cores(&cores) == 0) {
+ printf("\n### Testing using two physical cores ###\n");
+ run_on_core_pair(&cores, s, bulk_push_pop);
+ }
+ if (get_two_sockets(&cores) == 0) {
+ printf("\n### Testing using two NUMA nodes ###\n");
+ run_on_core_pair(&cores, s, bulk_push_pop);
+ }
+
+ printf("\n### Testing on all %u lcores ###\n", rte_lcore_count());
+ run_on_n_cores(s, bulk_push_pop, rte_lcore_count());
+
+ rte_stack_free(s);
+ return 0;
+}
+
+static int
+test_stack_perf(void)
+{
+ return __test_stack_perf(0);
+}
+
+static int
+test_lf_stack_perf(void)
+{
+ return __test_stack_perf(RTE_STACK_F_LF);
+}
+
+REGISTER_TEST_COMMAND(stack_perf_autotest, test_stack_perf);
+REGISTER_TEST_COMMAND(stack_lf_perf_autotest, test_lf_stack_perf);
diff --git a/src/spdk/dpdk/app/test/test_string_fns.c b/src/spdk/dpdk/app/test/test_string_fns.c
new file mode 100644
index 000000000..5e105d2bb
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_string_fns.c
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <errno.h>
+#include <string.h>
+
+#include <rte_string_fns.h>
+
+#include "test.h"
+
+#define LOG(...) do {\
+ fprintf(stderr, "%s() ln %d: ", __func__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+} while(0)
+
+#define DATA_BYTE 'a'
+
+static int
+test_rte_strsplit(void)
+{
+ int i;
+ do {
+ /* =======================================================
+ * split a mac address correct number of splits requested
+ * =======================================================*/
+ char test_string[] = "54:65:76:87:98:90";
+ char *splits[6];
+
+ LOG("Source string: '%s', to split on ':'\n", test_string);
+ if (rte_strsplit(test_string, sizeof(test_string),
+ splits, 6, ':') != 6) {
+ LOG("Error splitting mac address\n");
+ return -1;
+ }
+ for (i = 0; i < 6; i++)
+ LOG("Token %d = %s\n", i + 1, splits[i]);
+ } while (0);
+
+
+ do {
+ /* =======================================================
+ * split on spaces smaller number of splits requested
+ * =======================================================*/
+ char test_string[] = "54 65 76 87 98 90";
+ char *splits[6];
+
+ LOG("Source string: '%s', to split on ' '\n", test_string);
+ if (rte_strsplit(test_string, sizeof(test_string),
+ splits, 3, ' ') != 3) {
+ LOG("Error splitting mac address for max 2 splits\n");
+ return -1;
+ }
+ for (i = 0; i < 3; i++)
+ LOG("Token %d = %s\n", i + 1, splits[i]);
+ } while (0);
+
+ do {
+ /* =======================================================
+ * split on commas - more splits than commas requested
+ * =======================================================*/
+ char test_string[] = "a,b,c,d";
+ char *splits[6];
+
+ LOG("Source string: '%s', to split on ','\n", test_string);
+ if (rte_strsplit(test_string, sizeof(test_string),
+ splits, 6, ',') != 4) {
+ LOG("Error splitting %s on ','\n", test_string);
+ return -1;
+ }
+ for (i = 0; i < 4; i++)
+ LOG("Token %d = %s\n", i + 1, splits[i]);
+ } while(0);
+
+ do {
+ /* =======================================================
+ * Try splitting on non-existent character.
+ * =======================================================*/
+ char test_string[] = "a,b,c,d";
+ char *splits[6];
+
+ LOG("Source string: '%s', to split on ' '\n", test_string);
+ if (rte_strsplit(test_string, sizeof(test_string),
+ splits, 6, ' ') != 1) {
+ LOG("Error splitting %s on ' '\n", test_string);
+ return -1;
+ }
+ LOG("String not split\n");
+ } while(0);
+
+ do {
+ /* =======================================================
+ * Invalid / edge case parameter checks
+ * =======================================================*/
+ char test_string[] = "a,b,c,d";
+ char *splits[6];
+
+ if (rte_strsplit(NULL, 0, splits, 6, ',') >= 0
+ || errno != EINVAL){
+ LOG("Error: rte_strsplit accepted NULL string parameter\n");
+ return -1;
+ }
+
+ if (rte_strsplit(test_string, sizeof(test_string), NULL, 0, ',') >= 0
+ || errno != EINVAL){
+ LOG("Error: rte_strsplit accepted NULL array parameter\n");
+ return -1;
+ }
+
+ errno = 0;
+ if (rte_strsplit(test_string, 0, splits, 6, ',') != 0 || errno != 0) {
+ LOG("Error: rte_strsplit did not accept 0 length string\n");
+ return -1;
+ }
+
+ if (rte_strsplit(test_string, sizeof(test_string), splits, 0, ',') != 0
+ || errno != 0) {
+ LOG("Error: rte_strsplit did not accept 0 length array\n");
+ return -1;
+ }
+
+ LOG("Parameter test cases passed\n");
+ } while(0);
+
+ LOG("%s - PASSED\n", __func__);
+ return 0;
+}
+
+static int
+test_rte_strlcat(void)
+{
+ /* only run actual unit tests if we have system-provided strlcat */
+#if defined(__BSD_VISIBLE) || defined(RTE_USE_LIBBSD)
+#define BUF_LEN 32
+ const char dst[BUF_LEN] = "Test string";
+ const char src[] = " appended";
+ char bsd_dst[BUF_LEN];
+ char rte_dst[BUF_LEN];
+ size_t i, bsd_ret, rte_ret;
+
+ LOG("dst = '%s', strlen(dst) = %zu\n", dst, strlen(dst));
+ LOG("src = '%s', strlen(src) = %zu\n", src, strlen(src));
+ LOG("---\n");
+
+ for (i = 0; i < BUF_LEN; i++) {
+ /* initialize destination buffers */
+ memcpy(bsd_dst, dst, BUF_LEN);
+ memcpy(rte_dst, dst, BUF_LEN);
+ /* compare implementations */
+ bsd_ret = strlcat(bsd_dst, src, i);
+ rte_ret = rte_strlcat(rte_dst, src, i);
+ if (bsd_ret != rte_ret) {
+ LOG("Incorrect retval for buf length = %zu\n", i);
+ LOG("BSD: '%zu', rte: '%zu'\n", bsd_ret, rte_ret);
+ return -1;
+ }
+ if (memcmp(bsd_dst, rte_dst, BUF_LEN) != 0) {
+ LOG("Resulting buffers don't match\n");
+ LOG("BSD: '%s', rte: '%s'\n", bsd_dst, rte_dst);
+ return -1;
+ }
+ LOG("buffer size = %zu: dst = '%s', ret = %zu\n",
+ i, rte_dst, rte_ret);
+ }
+ LOG("Checked %zu combinations\n", i);
+#undef BUF_LEN
+#endif /* defined(__BSD_VISIBLE) || defined(RTE_USE_LIBBSD) */
+
+ return 0;
+}
+
+static int
+test_string_fns(void)
+{
+ if (test_rte_strsplit() < 0)
+ return -1;
+ if (test_rte_strlcat() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(string_autotest, test_string_fns);
diff --git a/src/spdk/dpdk/app/test/test_table.c b/src/spdk/dpdk/app/test/test_table.c
new file mode 100644
index 000000000..bc8d8a2e1
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table.c
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_byteorder.h>
+#include <rte_hexdump.h>
+#include <rte_string_fns.h>
+#include <string.h>
+#include "test.h"
+#include "test_table.h"
+#include "test_table_pipeline.h"
+#include "test_table_ports.h"
+#include "test_table_tables.h"
+#include "test_table_combined.h"
+#include "test_table_acl.h"
+
+/* Global variables */
+struct rte_pipeline *p;
+struct rte_ring *rings_rx[N_PORTS];
+struct rte_ring *rings_tx[N_PORTS];
+struct rte_mempool *pool = NULL;
+
+uint32_t port_in_id[N_PORTS];
+uint32_t port_out_id[N_PORTS];
+uint32_t port_out_id_type[3];
+uint32_t table_id[N_PORTS*2];
+uint64_t override_hit_mask = 0xFFFFFFFF;
+uint64_t override_miss_mask = 0xFFFFFFFF;
+uint64_t non_reserved_actions_hit = 0;
+uint64_t non_reserved_actions_miss = 0;
+uint8_t connect_miss_action_to_port_out = 0;
+uint8_t connect_miss_action_to_table = 0;
+uint32_t table_entry_default_action = RTE_PIPELINE_ACTION_DROP;
+uint32_t table_entry_hit_action = RTE_PIPELINE_ACTION_PORT;
+uint32_t table_entry_miss_action = RTE_PIPELINE_ACTION_DROP;
+rte_pipeline_port_in_action_handler port_in_action = NULL;
+rte_pipeline_port_out_action_handler port_out_action = NULL;
+rte_pipeline_table_action_handler_hit action_handler_hit = NULL;
+rte_pipeline_table_action_handler_miss action_handler_miss = NULL;
+
+/* Function prototypes */
+static void app_init_rings(void);
+static void app_init_mbuf_pools(void);
+
+uint64_t pipeline_test_hash(void *key,
+ __rte_unused void *key_mask,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint64_t seed)
+{
+ uint32_t *k32 = key;
+ uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
+ uint64_t signature = ip_dst;
+
+ return signature;
+}
+
+uint32_t pipeline_test_hash_cuckoo(const void *key,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint32_t seed)
+{
+ const uint32_t *k32 = key;
+ uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
+ uint32_t signature = ip_dst;
+
+ return signature;
+}
+
+static void
+app_free_resources(void) {
+ int i;
+ for (i = 0; i < N_PORTS; i++)
+ rte_ring_free(rings_rx[i]);
+ rte_mempool_free(pool);
+}
+
+static void
+app_init_mbuf_pools(void)
+{
+ /* Init the buffer pool */
+ printf("Getting/Creating the mempool ...\n");
+ pool = rte_mempool_lookup("mempool");
+ if (!pool) {
+ pool = rte_pktmbuf_pool_create(
+ "mempool",
+ POOL_SIZE,
+ POOL_CACHE_SIZE, 0, POOL_BUFFER_SIZE,
+ 0);
+ if (pool == NULL)
+ rte_panic("Cannot create mbuf pool\n");
+ }
+}
+
+static void
+app_init_rings(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < N_PORTS; i++) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "app_ring_rx_%u", i);
+ rings_rx[i] = rte_ring_lookup(name);
+ if (rings_rx[i] == NULL) {
+ rings_rx[i] = rte_ring_create(
+ name,
+ RING_RX_SIZE,
+ 0,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ }
+ if (rings_rx[i] == NULL)
+ rte_panic("Cannot create RX ring %u\n", i);
+ }
+
+ for (i = 0; i < N_PORTS; i++) {
+ char name[32];
+
+ snprintf(name, sizeof(name), "app_ring_tx_%u", i);
+ rings_tx[i] = rte_ring_lookup(name);
+ if (rings_tx[i] == NULL) {
+ rings_tx[i] = rte_ring_create(
+ name,
+ RING_TX_SIZE,
+ 0,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ }
+ if (rings_tx[i] == NULL)
+ rte_panic("Cannot create TX ring %u\n", i);
+ }
+
+}
+
+static int
+test_table(void)
+{
+ int status, ret;
+ unsigned i;
+
+ ret = TEST_SUCCESS;
+
+ app_init_rings();
+ app_init_mbuf_pools();
+
+ printf("\n\n\n\n************Pipeline tests************\n");
+
+ if (test_table_pipeline() < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+
+ printf("\n\n\n\n************Port tests************\n");
+ for (i = 0; i < n_port_tests; i++) {
+ status = port_tests[i]();
+ if (status < 0) {
+ printf("\nPort test number %d failed (%d).\n", i,
+ status);
+ ret = TEST_FAILED;
+ goto end;
+ }
+ }
+
+ printf("\n\n\n\n************Table tests************\n");
+ for (i = 0; i < n_table_tests; i++) {
+ status = table_tests[i]();
+ if (status < 0) {
+ printf("\nTable test number %d failed (%d).\n", i,
+ status);
+ ret = TEST_FAILED;
+ goto end;
+ }
+ }
+
+ printf("\n\n\n\n************Table tests************\n");
+ for (i = 0; i < n_table_tests_combined; i++) {
+ status = table_tests_combined[i]();
+ if (status < 0) {
+ printf("\nCombined table test number %d failed with "
+ "reason number %d.\n", i, status);
+ ret = TEST_FAILED;
+ goto end;
+ }
+ }
+
+#ifdef RTE_LIBRTE_ACL
+ printf("\n\n\n\n************ACL tests************\n");
+ if (test_table_acl() < 0) {
+ ret = TEST_FAILED;
+ goto end;
+ }
+#endif
+
+end:
+ app_free_resources();
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(table_autotest, test_table);
diff --git a/src/spdk/dpdk/app/test/test_table.h b/src/spdk/dpdk/app/test/test_table.h
new file mode 100644
index 000000000..43b885587
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_table_stub.h>
+#include <rte_table_lpm.h>
+#include <rte_table_lpm_ipv6.h>
+#include <rte_table_hash.h>
+#include <rte_table_hash_cuckoo.h>
+#include <rte_table_array.h>
+#include <rte_pipeline.h>
+
+#ifdef RTE_LIBRTE_ACL
+#include <rte_table_acl.h>
+#endif
+
+#include <rte_port_ring.h>
+#include <rte_port_ethdev.h>
+#include <rte_port_source_sink.h>
+
+#ifndef TEST_TABLE_H_
+#define TEST_TABLE_H_
+
+#define RING_SIZE 4096
+#define MAX_BULK 32
+#define N 65536
+#define TIME_S 5
+#define TEST_RING_FULL_EMTPY_ITER 8
+#define N_PORTS 2
+#define N_PKTS 2
+#define N_PKTS_EXT 6
+#define RING_RX rings_rx[0]
+#define RING_RX_2 rings_rx[1]
+#define RING_TX rings_tx[0]
+#define RING_TX_2 rings_tx[1]
+#define PORT_RX_RING_SIZE 128
+#define PORT_TX_RING_SIZE 512
+#define RING_RX_SIZE 128
+#define RING_TX_SIZE 128
+#define POOL_BUFFER_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
+#define POOL_SIZE (32 * 1024)
+#define POOL_CACHE_SIZE 256
+#define BURST_SIZE 8
+#define WORKER_TYPE 1
+#define MAX_DUMMY_PORTS 2
+#define MP_NAME "dummy_port_mempool"
+#define MBUF_COUNT (8000 * MAX_DUMMY_PORTS)
+#define MP_CACHE_SZ 256
+#define MP_SOCKET 0
+#define MP_FLAGS 0
+
+/* Macros */
+#define APP_METADATA_OFFSET(offset) (sizeof(struct rte_mbuf) + (offset))
+
+#define RING_ENQUEUE(ring, value) do { \
+ struct rte_mbuf *m; \
+ uint32_t *k32, *signature; \
+ uint8_t *key; \
+ \
+ m = rte_pktmbuf_alloc(pool); \
+ if (m == NULL) \
+ return -1; \
+ signature = RTE_MBUF_METADATA_UINT32_PTR(m, \
+ APP_METADATA_OFFSET(0)); \
+ key = RTE_MBUF_METADATA_UINT8_PTR(m, \
+ APP_METADATA_OFFSET(32)); \
+ k32 = (uint32_t *) key; \
+ k32[0] = (value); \
+ *signature = pipeline_test_hash(key, NULL, 0, 0); \
+ rte_ring_enqueue((ring), m); \
+} while (0)
+
+#define RUN_PIPELINE(pipeline) do { \
+ rte_pipeline_run((pipeline)); \
+ rte_pipeline_flush((pipeline)); \
+} while (0)
+
+#define VERIFY(var, value) do { \
+ if ((var) != -(value)) \
+ return var; \
+} while (0)
+
+#define VERIFY_TRAFFIC(ring, sent, expected) do { \
+ unsigned i, n = 0; \
+ void *mbuf = NULL; \
+ \
+ for (i = 0; i < (sent); i++) { \
+ if (!rte_ring_dequeue((ring), &mbuf)) { \
+ if (mbuf == NULL) \
+ continue; \
+ n++; \
+ rte_pktmbuf_free((struct rte_mbuf *)mbuf); \
+ } \
+ else \
+ break; \
+ } \
+ printf("Expected %d, got %d\n", expected, n); \
+ if (n != (expected)) { \
+ return -21; \
+ } \
+} while (0)
+
+/* Function definitions */
+uint64_t pipeline_test_hash(
+ void *key,
+ __rte_unused void *key_mask,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint64_t seed);
+
+uint32_t pipeline_test_hash_cuckoo(
+ const void *key,
+ __rte_unused uint32_t key_size,
+ __rte_unused uint32_t seed);
+
+/* Extern variables */
+extern struct rte_pipeline *p;
+extern struct rte_ring *rings_rx[N_PORTS];
+extern struct rte_ring *rings_tx[N_PORTS];
+extern struct rte_mempool *pool;
+extern uint32_t port_in_id[N_PORTS];
+extern uint32_t port_out_id[N_PORTS];
+extern uint32_t port_out_id_type[3];
+extern uint32_t table_id[N_PORTS*2];
+extern uint64_t override_hit_mask;
+extern uint64_t override_miss_mask;
+extern uint64_t non_reserved_actions_hit;
+extern uint64_t non_reserved_actions_miss;
+extern uint8_t connect_miss_action_to_port_out;
+extern uint8_t connect_miss_action_to_table;
+extern uint32_t table_entry_default_action;
+extern uint32_t table_entry_hit_action;
+extern uint32_t table_entry_miss_action;
+extern rte_pipeline_port_in_action_handler port_in_action;
+extern rte_pipeline_port_out_action_handler port_out_action;
+extern rte_pipeline_table_action_handler_hit action_handler_hit;
+extern rte_pipeline_table_action_handler_miss action_handler_miss;
+
+/* Global data types */
+struct manage_ops {
+ uint32_t op_id;
+ void *op_data;
+ int expected_result;
+};
+
+/* Internal pipeline structures */
+struct rte_port_in {
+ struct rte_port_in_ops ops;
+ uint32_t burst_size;
+ uint32_t table_id;
+ void *h_port;
+};
+
+struct rte_port_out {
+ struct rte_port_out_ops ops;
+ void *h_port;
+};
+
+struct rte_table {
+ struct rte_table_ops ops;
+ rte_pipeline_table_action_handler_hit f_action;
+ uint32_t table_next_id;
+ uint32_t table_next_id_valid;
+ uint8_t actions_lookup_miss[RTE_CACHE_LINE_SIZE];
+ uint32_t action_data_size;
+ void *h_table;
+};
+
+#define RTE_PIPELINE_MAX_NAME_SZ 124
+
+struct rte_pipeline {
+ char name[RTE_PIPELINE_MAX_NAME_SZ];
+ uint32_t socket_id;
+ struct rte_port_in ports_in[16];
+ struct rte_port_out ports_out[16];
+ struct rte_table tables[64];
+ uint32_t num_ports_in;
+ uint32_t num_ports_out;
+ uint32_t num_tables;
+ struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX];
+ struct rte_table_entry *actions[RTE_PORT_IN_BURST_SIZE_MAX];
+ uint64_t mask_action[64];
+ uint32_t mask_actions;
+};
+#endif
diff --git a/src/spdk/dpdk/app/test/test_table_acl.c b/src/spdk/dpdk/app/test/test_table_acl.c
new file mode 100644
index 000000000..0bdf76ab7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_acl.c
@@ -0,0 +1,730 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_ip.h>
+#include <rte_string_fns.h>
+#include <rte_hexdump.h>
+#include "test_table.h"
+#include "test_table_acl.h"
+
+/*
+ * Rule and trace formats definitions.
+ **/
+
+struct ipv4_5tuple {
+ uint8_t proto;
+ uint32_t ip_src;
+ uint32_t ip_dst;
+ uint16_t port_src;
+ uint16_t port_dst;
+};
+
+enum {
+ PROTO_FIELD_IPV4,
+ SRC_FIELD_IPV4,
+ DST_FIELD_IPV4,
+ SRCP_FIELD_IPV4,
+ DSTP_FIELD_IPV4,
+ NUM_FIELDS_IPV4
+};
+
+struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
+ {
+ .type = RTE_ACL_FIELD_TYPE_BITMASK,
+ .size = sizeof(uint8_t),
+ .field_index = PROTO_FIELD_IPV4,
+ .input_index = PROTO_FIELD_IPV4,
+ .offset = offsetof(struct ipv4_5tuple, proto),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = SRC_FIELD_IPV4,
+ .input_index = SRC_FIELD_IPV4,
+ .offset = offsetof(struct ipv4_5tuple, ip_src),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_MASK,
+ .size = sizeof(uint32_t),
+ .field_index = DST_FIELD_IPV4,
+ .input_index = DST_FIELD_IPV4,
+ .offset = offsetof(struct ipv4_5tuple, ip_dst),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = SRCP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = offsetof(struct ipv4_5tuple, port_src),
+ },
+ {
+ .type = RTE_ACL_FIELD_TYPE_RANGE,
+ .size = sizeof(uint16_t),
+ .field_index = DSTP_FIELD_IPV4,
+ .input_index = SRCP_FIELD_IPV4,
+ .offset = offsetof(struct ipv4_5tuple, port_dst),
+ },
+};
+
+struct rte_table_acl_rule_add_params table_acl_IPv4_rule;
+
+typedef int (*parse_5tuple)(char *text,
+ struct rte_table_acl_rule_add_params *rule);
+
+/*
+* The order of the fields in the rule string after the initial '@'
+*/
+enum {
+ CB_FLD_SRC_ADDR,
+ CB_FLD_DST_ADDR,
+ CB_FLD_SRC_PORT_RANGE,
+ CB_FLD_DST_PORT_RANGE,
+ CB_FLD_PROTO,
+ CB_FLD_NUM,
+};
+
+
+#define GET_CB_FIELD(in, fd, base, lim, dlm) \
+do { \
+ unsigned long val; \
+ char *end; \
+ \
+ errno = 0; \
+ val = strtoul((in), &end, (base)); \
+ if (errno != 0 || end[0] != (dlm) || val > (lim)) \
+ return -EINVAL; \
+ (fd) = (typeof(fd)) val; \
+ (in) = end + 1; \
+} while (0)
+
+
+
+
+static int
+parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
+{
+ uint8_t a, b, c, d, m;
+
+ GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
+ GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
+
+ addr[0] = RTE_IPV4(a, b, c, d);
+ mask_len[0] = m;
+
+ return 0;
+}
+
+static int
+parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high)
+{
+ uint16_t a, b;
+
+ GET_CB_FIELD(in, a, 0, UINT16_MAX, ':');
+ GET_CB_FIELD(in, b, 0, UINT16_MAX, 0);
+
+ port_low[0] = a;
+ port_high[0] = b;
+
+ return 0;
+}
+
+static int
+parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
+{
+ int i, rc;
+ char *s, *sp, *in[CB_FLD_NUM];
+ static const char *dlm = " \t\n";
+
+ /*
+ ** Skip leading '@'
+ */
+ if (strchr(str, '@') != str)
+ return -EINVAL;
+
+ s = str + 1;
+
+ /*
+ * Populate the 'in' array with the location of each
+ * field in the string we're parsing
+ */
+ for (i = 0; i != DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ /* Parse x.x.x.x/x */
+ rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
+ &v->field_value[SRC_FIELD_IPV4].value.u32,
+ &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
+ in[CB_FLD_SRC_ADDR]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
+ v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+
+ /* Parse x.x.x.x/x */
+ rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
+ &v->field_value[DST_FIELD_IPV4].value.u32,
+ &v->field_value[DST_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
+ in[CB_FLD_DST_ADDR]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
+ v->field_value[DST_FIELD_IPV4].mask_range.u32);
+ /* Parse n:n */
+ rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
+ &v->field_value[SRCP_FIELD_IPV4].value.u16,
+ &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
+ in[CB_FLD_SRC_PORT_RANGE]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
+ v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+ /* Parse n:n */
+ rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
+ &v->field_value[DSTP_FIELD_IPV4].value.u16,
+ &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
+ in[CB_FLD_DST_PORT_RANGE]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
+ v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+ /* parse 0/0xnn */
+ GET_CB_FIELD(in[CB_FLD_PROTO],
+ v->field_value[PROTO_FIELD_IPV4].value.u8,
+ 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in[CB_FLD_PROTO],
+ v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
+ 0, UINT8_MAX, 0);
+
+ printf("V=%u, mask=%u\n",
+ (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
+ v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
+ return 0;
+}
+
+static int
+parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v)
+{
+ int i, rc;
+ char *s, *sp, *in[CB_FLD_NUM];
+ static const char *dlm = " \t\n";
+
+ /*
+ ** Skip leading '@'
+ */
+ if (strchr(str, '@') != str)
+ return -EINVAL;
+
+ s = str + 1;
+
+ /*
+ * Populate the 'in' array with the location of each
+ * field in the string we're parsing
+ */
+ for (i = 0; i != DIM(in); i++) {
+ in[i] = strtok_r(s, dlm, &sp);
+ if (in[i] == NULL)
+ return -EINVAL;
+ s = NULL;
+ }
+
+ /* Parse x.x.x.x/x */
+ rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
+ &v->field_value[SRC_FIELD_IPV4].value.u32,
+ &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
+ in[CB_FLD_SRC_ADDR]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
+ v->field_value[SRC_FIELD_IPV4].mask_range.u32);
+
+ /* Parse x.x.x.x/x */
+ rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
+ &v->field_value[DST_FIELD_IPV4].value.u32,
+ &v->field_value[DST_FIELD_IPV4].mask_range.u32);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
+ in[CB_FLD_DST_ADDR]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
+ v->field_value[DST_FIELD_IPV4].mask_range.u32);
+ /* Parse n:n */
+ rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
+ &v->field_value[SRCP_FIELD_IPV4].value.u16,
+ &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
+ in[CB_FLD_SRC_PORT_RANGE]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
+ v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
+ /* Parse n:n */
+ rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
+ &v->field_value[DSTP_FIELD_IPV4].value.u16,
+ &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+ if (rc != 0) {
+ RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
+ in[CB_FLD_DST_PORT_RANGE]);
+ return rc;
+ }
+
+ printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
+ v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
+ /* parse 0/0xnn */
+ GET_CB_FIELD(in[CB_FLD_PROTO],
+ v->field_value[PROTO_FIELD_IPV4].value.u8,
+ 0, UINT8_MAX, '/');
+ GET_CB_FIELD(in[CB_FLD_PROTO],
+ v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
+ 0, UINT8_MAX, 0);
+
+ printf("V=%u, mask=%u\n",
+ (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
+ v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
+ return 0;
+}
+
+/*
+ * The format for these rules DO NOT need the port ranges to be
+ * separated by ' : ', just ':'. It's a lot more readable and
+ * cleaner, IMO.
+ */
+char lines[][128] = {
+ "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
+ "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */
+ "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
+ "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
+ "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
+};
+
+char line[128];
+
+
+static int
+setup_acl_pipeline(void)
+{
+ int ret;
+ int i;
+ struct rte_pipeline_params pipeline_params = {
+ .name = "PIPELINE",
+ .socket_id = 0,
+ };
+ uint32_t n;
+ struct rte_table_acl_rule_add_params rule_params;
+ struct rte_pipeline_table_acl_rule_delete_params *delete_params;
+ parse_5tuple parser;
+ char acl_name[64];
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Input port configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .burst_size = BURST_SIZE,
+ };
+
+ /* Put in action for some ports */
+ if (i)
+ port_params.f_action = port_in_action;
+
+ ret = rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]);
+ if (ret) {
+ rte_panic("Unable to configure input port %d, ret:%d\n",
+ i, ret);
+ goto fail;
+ }
+ }
+
+ /* output Port configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = rings_tx[i],
+ .tx_burst_sz = BURST_SIZE,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i])) {
+ rte_panic("Unable to configure output port %d\n", i);
+ goto fail;
+ }
+ }
+
+ /* Table configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_pipeline_table_params table_params;
+
+ /* Set up defaults for stub */
+ table_params.ops = &rte_table_stub_ops;
+ table_params.arg_create = NULL;
+ table_params.f_action_hit = action_handler_hit;
+ table_params.f_action_miss = NULL;
+ table_params.action_data_size = 0;
+
+ RTE_LOG(INFO, PIPELINE, "miss_action=%x\n",
+ table_entry_miss_action);
+
+ printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
+ RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
+
+ struct rte_table_acl_params acl_params;
+
+ acl_params.n_rules = 1 << 5;
+ acl_params.n_rule_fields = DIM(ipv4_defs);
+ snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
+ acl_params.name = acl_name;
+ memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
+
+ table_params.ops = &rte_table_acl_ops;
+ table_params.arg_create = &acl_params;
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
+ rte_panic("Unable to configure table %u\n", i);
+ goto fail;
+ }
+
+ if (connect_miss_action_to_table) {
+ if (rte_pipeline_table_create(p, &table_params,
+ &table_id[i+2])) {
+ rte_panic("Unable to configure table %u\n", i);
+ goto fail;
+ }
+ }
+ }
+
+ for (i = 0; i < N_PORTS; i++) {
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id[i])) {
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n",
+ port_in_id[i], table_id[i]);
+ goto fail;
+ }
+ }
+
+ /* Add bulk entries to tables */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_table_acl_rule_add_params keys[5];
+ struct rte_pipeline_table_entry entries[5];
+ struct rte_table_acl_rule_add_params *key_array[5];
+ struct rte_pipeline_table_entry *table_entries[5];
+ int key_found[5];
+ struct rte_pipeline_table_entry *table_entries_ptr[5];
+ struct rte_pipeline_table_entry entries_ptr[5];
+
+ parser = parse_cb_ipv4_rule;
+ for (n = 0; n < 5; n++) {
+ memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
+ key_array[n] = &keys[n];
+
+ strlcpy(line, lines[n], sizeof(line));
+ printf("PARSING [%s]\n", line);
+
+ ret = parser(line, &keys[n]);
+ if (ret != 0) {
+ RTE_LOG(ERR, PIPELINE,
+ "line %u: parse_cb_ipv4vlan_rule"
+ " failed, error code: %d (%s)\n",
+ n, ret, strerror(-ret));
+ return ret;
+ }
+
+ keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
+
+ entries[n].action = RTE_PIPELINE_ACTION_PORT;
+ entries[n].port_id = port_out_id[i^1];
+ table_entries[n] = &entries[n];
+ table_entries_ptr[n] = &entries_ptr[n];
+ }
+
+ ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
+ (void **)key_array, table_entries, 5, key_found, table_entries_ptr);
+ if (ret < 0) {
+ rte_panic("Add entry bulk to table %u failed (%d)\n",
+ table_id[i], ret);
+ goto fail;
+ }
+ }
+
+ /* Delete bulk entries from tables */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_table_acl_rule_delete_params keys[5];
+ struct rte_table_acl_rule_delete_params *key_array[5];
+ struct rte_pipeline_table_entry *table_entries[5];
+ int key_found[5];
+
+ memset(table_entries, 0, sizeof(table_entries));
+
+ for (n = 0; n < 5; n++) {
+ memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
+ key_array[n] = &keys[n];
+
+ strlcpy(line, lines[n], sizeof(line));
+ printf("PARSING [%s]\n", line);
+
+ ret = parse_cb_ipv4_rule_del(line, &keys[n]);
+ if (ret != 0) {
+ RTE_LOG(ERR, PIPELINE,
+ "line %u: parse_cb_ipv4vlan_rule"
+ " failed, error code: %d (%s)\n",
+ n, ret, strerror(-ret));
+ return ret;
+ }
+ }
+
+ ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
+ (void **)key_array, 5, key_found, table_entries);
+ if (ret < 0) {
+ rte_panic("Delete bulk entries from table %u failed (%d)\n",
+ table_id[i], ret);
+ goto fail;
+ } else
+ printf("Bulk deleted rules.\n");
+ }
+
+ /* Add entries to tables */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_pipeline_table_entry table_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i^1]},
+ };
+ int key_found;
+ struct rte_pipeline_table_entry *entry_ptr;
+
+ memset(&rule_params, 0, sizeof(rule_params));
+ parser = parse_cb_ipv4_rule;
+
+ for (n = 1; n <= 5; n++) {
+ strlcpy(line, lines[n - 1], sizeof(line));
+ printf("PARSING [%s]\n", line);
+
+ ret = parser(line, &rule_params);
+ if (ret != 0) {
+ RTE_LOG(ERR, PIPELINE,
+ "line %u: parse_cb_ipv4vlan_rule"
+ " failed, error code: %d (%s)\n",
+ n, ret, strerror(-ret));
+ return ret;
+ }
+
+ rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
+
+ ret = rte_pipeline_table_entry_add(p, table_id[i],
+ &rule_params,
+ &table_entry, &key_found, &entry_ptr);
+ if (ret < 0) {
+ rte_panic("Add entry to table %u failed (%d)\n",
+ table_id[i], ret);
+ goto fail;
+ }
+ }
+
+ /* delete a few rules */
+ for (n = 2; n <= 3; n++) {
+ strlcpy(line, lines[n - 1], sizeof(line));
+ printf("PARSING [%s]\n", line);
+
+ ret = parser(line, &rule_params);
+ if (ret != 0) {
+ RTE_LOG(ERR, PIPELINE, "line %u: parse rule "
+ " failed, error code: %d (%s)\n",
+ n, ret, strerror(-ret));
+ return ret;
+ }
+
+ delete_params = (struct
+ rte_pipeline_table_acl_rule_delete_params *)
+ &(rule_params.field_value[0]);
+ ret = rte_pipeline_table_entry_delete(p, table_id[i],
+ delete_params, &key_found, NULL);
+ if (ret < 0) {
+ rte_panic("Add entry to table %u failed (%d)\n",
+ table_id[i], ret);
+ goto fail;
+ } else
+ printf("Deleted Rule.\n");
+ }
+
+
+ /* Try to add duplicates */
+ for (n = 1; n <= 5; n++) {
+ strlcpy(line, lines[n - 1], sizeof(line));
+ printf("PARSING [%s]\n", line);
+
+ ret = parser(line, &rule_params);
+ if (ret != 0) {
+ RTE_LOG(ERR, PIPELINE, "line %u: parse rule"
+ " failed, error code: %d (%s)\n",
+ n, ret, strerror(-ret));
+ return ret;
+ }
+
+ rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
+
+ ret = rte_pipeline_table_entry_add(p, table_id[i],
+ &rule_params,
+ &table_entry, &key_found, &entry_ptr);
+ if (ret < 0) {
+ rte_panic("Add entry to table %u failed (%d)\n",
+ table_id[i], ret);
+ goto fail;
+ }
+ }
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < N_PORTS ; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0) {
+ rte_panic("Pipeline consistency check failed\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+
+ return -1;
+}
+
+static int
+test_pipeline_single_filter(int expected_count)
+{
+ int i, j, ret, tx_count;
+ struct ipv4_5tuple five_tuple;
+
+ /* Allocate a few mbufs and manually insert into the rings. */
+ for (i = 0; i < N_PORTS; i++) {
+ for (j = 0; j < 8; j++) {
+ struct rte_mbuf *mbuf;
+
+ mbuf = rte_pktmbuf_alloc(pool);
+ if (mbuf == NULL)
+ /* this will cause test failure after cleanup
+ * of already enqueued mbufs, as the mbuf
+ * counts won't match */
+ break;
+ memset(rte_pktmbuf_mtod(mbuf, char *), 0x00,
+ sizeof(struct ipv4_5tuple));
+
+ five_tuple.proto = j;
+ five_tuple.ip_src = rte_bswap32(RTE_IPV4(192, 168, j, 1));
+ five_tuple.ip_dst = rte_bswap32(RTE_IPV4(10, 4, j, 1));
+ five_tuple.port_src = rte_bswap16(100 + j);
+ five_tuple.port_dst = rte_bswap16(200 + j);
+
+ memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple,
+ sizeof(struct ipv4_5tuple));
+ RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n",
+ __func__, i);
+ rte_ring_enqueue(rings_rx[i], mbuf);
+ }
+ }
+
+ /* Run pipeline once */
+ for (i = 0; i< N_PORTS; i++)
+ rte_pipeline_run(p);
+
+ rte_pipeline_flush(p);
+
+ tx_count = 0;
+
+ for (i = 0; i < N_PORTS; i++) {
+ void *objs[RING_TX_SIZE];
+ struct rte_mbuf *mbuf;
+
+ ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
+ if (ret <= 0) {
+ printf("Got no objects from ring %d - error code %d\n",
+ i, ret);
+ } else {
+ printf("Got %d object(s) from ring %d!\n", ret, i);
+ for (j = 0; j < ret; j++) {
+ mbuf = objs[j];
+ rte_hexdump(stdout, "mbuf",
+ rte_pktmbuf_mtod(mbuf, char *), 64);
+ rte_pktmbuf_free(mbuf);
+ }
+ tx_count += ret;
+ }
+ }
+
+ if (tx_count != expected_count) {
+ RTE_LOG(INFO, PIPELINE,
+ "%s: Unexpected packets for ACL test, "
+ "expected %d, got %d\n",
+ __func__, expected_count, tx_count);
+ goto fail;
+ }
+
+ rte_pipeline_free(p);
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+int
+test_table_acl(void)
+{
+
+
+ override_hit_mask = 0xFF; /* All packets are a hit */
+
+ setup_acl_pipeline();
+ if (test_pipeline_single_filter(10) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_table_acl.h b/src/spdk/dpdk/app/test/test_table_acl.h
new file mode 100644
index 000000000..a6ae7d283
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_acl.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+/* Test prototypes */
+int test_table_acl(void);
diff --git a/src/spdk/dpdk/app/test/test_table_combined.c b/src/spdk/dpdk/app/test/test_table_combined.c
new file mode 100644
index 000000000..f72b634bf
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_combined.c
@@ -0,0 +1,842 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <string.h>
+#include "test_table_combined.h"
+#include "test_table.h"
+#include <rte_table_lpm_ipv6.h>
+
+#define MAX_TEST_KEYS 128
+#define N_PACKETS 50
+
+enum check_table_result {
+ CHECK_TABLE_OK,
+ CHECK_TABLE_PORT_CONFIG,
+ CHECK_TABLE_PORT_ENABLE,
+ CHECK_TABLE_TABLE_CONFIG,
+ CHECK_TABLE_ENTRY_ADD,
+ CHECK_TABLE_DEFAULT_ENTRY_ADD,
+ CHECK_TABLE_CONNECT,
+ CHECK_TABLE_MANAGE_ERROR,
+ CHECK_TABLE_CONSISTENCY,
+ CHECK_TABLE_NO_TRAFFIC,
+ CHECK_TABLE_INVALID_PARAMETER,
+};
+
+struct table_packets {
+ uint32_t hit_packet[MAX_TEST_KEYS];
+ uint32_t miss_packet[MAX_TEST_KEYS];
+ uint32_t n_hit_packets;
+ uint32_t n_miss_packets;
+};
+
+combined_table_test table_tests_combined[] = {
+ test_table_lpm_combined,
+ test_table_lpm_ipv6_combined,
+ test_table_hash8lru,
+ test_table_hash8ext,
+ test_table_hash16lru,
+ test_table_hash16ext,
+ test_table_hash32lru,
+ test_table_hash32ext,
+ test_table_hash_cuckoo_combined,
+};
+
+unsigned n_table_tests_combined = RTE_DIM(table_tests_combined);
+
+/* Generic port tester function */
+static int
+test_table_type(struct rte_table_ops *table_ops, void *table_args,
+ void *key, struct table_packets *table_packets,
+ struct manage_ops *manage_ops, unsigned n_ops)
+{
+ uint32_t ring_in_id, table_id, ring_out_id, ring_out_2_id;
+ unsigned i;
+
+ RTE_SET_USED(manage_ops);
+ RTE_SET_USED(n_ops);
+ /* Create pipeline */
+ struct rte_pipeline_params pipeline_params = {
+ .name = "pipeline",
+ .socket_id = 0,
+ };
+
+ struct rte_pipeline *pipeline = rte_pipeline_create(&pipeline_params);
+
+ /* Create input ring */
+ struct rte_port_ring_reader_params ring_params_rx = {
+ .ring = RING_RX,
+ };
+
+ struct rte_port_ring_writer_params ring_params_tx = {
+ .ring = RING_RX,
+ .tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX,
+ };
+
+ struct rte_pipeline_port_in_params ring_in_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *)&ring_params_rx,
+ .f_action = NULL,
+ .burst_size = RTE_PORT_IN_BURST_SIZE_MAX,
+ };
+
+ if (rte_pipeline_port_in_create(pipeline, &ring_in_params,
+ &ring_in_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_PORT_CONFIG;
+ }
+
+ /* Create table */
+ struct rte_pipeline_table_params table_params = {
+ .ops = table_ops,
+ .arg_create = table_args,
+ .f_action_hit = NULL,
+ .f_action_miss = NULL,
+ .arg_ah = NULL,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(pipeline, &table_params,
+ &table_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_TABLE_CONFIG;
+ }
+
+ /* Create output ports */
+ ring_params_tx.ring = RING_TX;
+
+ struct rte_pipeline_port_out_params ring_out_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *)&ring_params_tx,
+ .f_action = NULL,
+ };
+
+ if (rte_pipeline_port_out_create(pipeline, &ring_out_params,
+ &ring_out_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_PORT_CONFIG;
+ }
+
+ ring_params_tx.ring = RING_TX_2;
+
+ if (rte_pipeline_port_out_create(pipeline, &ring_out_params,
+ &ring_out_2_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_PORT_CONFIG;
+ }
+
+ /* Add entry to the table */
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_DROP,
+ {.table_id = ring_out_id},
+ };
+
+ struct rte_pipeline_table_entry table_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.table_id = ring_out_id},
+ };
+
+ struct rte_pipeline_table_entry *default_entry_ptr, *entry_ptr;
+
+ int key_found;
+
+ if (rte_pipeline_table_default_entry_add(pipeline, table_id,
+ &default_entry, &default_entry_ptr) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_DEFAULT_ENTRY_ADD;
+ }
+
+ if (rte_pipeline_table_entry_add(pipeline, table_id,
+ key ? key : &table_entry, &table_entry, &key_found,
+ &entry_ptr) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_ENTRY_ADD;
+ }
+
+ /* Create connections and check consistency */
+ if (rte_pipeline_port_in_connect_to_table(pipeline, ring_in_id,
+ table_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_CONNECT;
+ }
+
+ if (rte_pipeline_port_in_enable(pipeline, ring_in_id) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_PORT_ENABLE;
+ }
+
+ if (rte_pipeline_check(pipeline) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_CONSISTENCY;
+ }
+
+
+
+ /* Flow test - All hits */
+ if (table_packets->n_hit_packets) {
+ for (i = 0; i < table_packets->n_hit_packets; i++)
+ RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
+
+ RUN_PIPELINE(pipeline);
+
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets,
+ table_packets->n_hit_packets);
+ }
+
+ /* Flow test - All misses */
+ if (table_packets->n_miss_packets) {
+ for (i = 0; i < table_packets->n_miss_packets; i++)
+ RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]);
+
+ RUN_PIPELINE(pipeline);
+
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0);
+ }
+
+ /* Flow test - Half hits, half misses */
+ if (table_packets->n_hit_packets && table_packets->n_miss_packets) {
+ for (i = 0; i < (table_packets->n_hit_packets) / 2; i++)
+ RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
+
+ for (i = 0; i < (table_packets->n_miss_packets) / 2; i++)
+ RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]);
+
+ RUN_PIPELINE(pipeline);
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets,
+ table_packets->n_hit_packets / 2);
+ }
+
+ /* Flow test - Single packet */
+ if (table_packets->n_hit_packets) {
+ RING_ENQUEUE(RING_RX, table_packets->hit_packet[0]);
+ RUN_PIPELINE(pipeline);
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 1);
+ }
+ if (table_packets->n_miss_packets) {
+ RING_ENQUEUE(RING_RX, table_packets->miss_packet[0]);
+ RUN_PIPELINE(pipeline);
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0);
+ }
+
+
+ /* Change table entry action */
+ printf("Change entry action\n");
+ table_entry.table_id = ring_out_2_id;
+
+ if (rte_pipeline_table_default_entry_add(pipeline, table_id,
+ &default_entry, &default_entry_ptr) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_ENTRY_ADD;
+ }
+
+ if (rte_pipeline_table_entry_add(pipeline, table_id,
+ key ? key : &table_entry, &table_entry, &key_found,
+ &entry_ptr) != 0) {
+ rte_pipeline_free(pipeline);
+ return -CHECK_TABLE_ENTRY_ADD;
+ }
+
+ /* Check that traffic destination has changed */
+ if (table_packets->n_hit_packets) {
+ for (i = 0; i < table_packets->n_hit_packets; i++)
+ RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
+
+ RUN_PIPELINE(pipeline);
+ VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 0);
+ VERIFY_TRAFFIC(RING_TX_2, table_packets->n_hit_packets,
+ table_packets->n_hit_packets);
+ }
+
+ printf("delete entry\n");
+ /* Delete table entry */
+ rte_pipeline_table_entry_delete(pipeline, table_id,
+ key ? key : &table_entry, &key_found, NULL);
+
+ rte_pipeline_free(pipeline);
+
+ return 0;
+}
+
+/* Table tests */
+int
+test_table_stub_combined(void)
+{
+ int status, i;
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < N_PACKETS; i++)
+ table_packets.hit_packet[i] = i;
+
+ table_packets.n_hit_packets = N_PACKETS;
+ table_packets.n_miss_packets = 0;
+
+ status = test_table_type(&rte_table_stub_ops, NULL, NULL,
+ &table_packets, NULL, 1);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ return 0;
+}
+
+int
+test_table_lpm_combined(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_lpm_params lpm_params = {
+ .name = "LPM",
+ .n_rules = 1 << 16,
+ .number_tbl8s = 1 << 8,
+ .flags = 0,
+ .entry_unique_size = 8,
+ .offset = APP_METADATA_OFFSET(0),
+ };
+
+ struct rte_table_lpm_key lpm_key = {
+ .ip = 0xadadadad,
+ .depth = 16,
+ };
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+
+ for (i = 0; i < N_PACKETS; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < N_PACKETS; i++)
+ table_packets.miss_packet[i] = 0xfefefefe;
+
+ table_packets.n_hit_packets = N_PACKETS;
+ table_packets.n_miss_packets = N_PACKETS;
+
+ status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
+ (void *)&lpm_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ lpm_params.n_rules = 0;
+
+ status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
+ (void *)&lpm_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ lpm_params.n_rules = 1 << 24;
+ lpm_key.depth = 0;
+
+ status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
+ (void *)&lpm_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_ENTRY_ADD);
+
+ lpm_key.depth = 33;
+
+ status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
+ (void *)&lpm_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_ENTRY_ADD);
+
+ return 0;
+}
+
+int
+test_table_lpm_ipv6_combined(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_lpm_ipv6_params lpm_ipv6_params = {
+ .name = "LPM",
+ .n_rules = 1 << 16,
+ .number_tbl8s = 1 << 13,
+ .entry_unique_size = 8,
+ .offset = APP_METADATA_OFFSET(32),
+ };
+
+ struct rte_table_lpm_ipv6_key lpm_ipv6_key = {
+ .depth = 16,
+ };
+ memset(lpm_ipv6_key.ip, 0xad, 16);
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < N_PACKETS; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < N_PACKETS; i++)
+ table_packets.miss_packet[i] = 0xadadadab;
+
+ table_packets.n_hit_packets = N_PACKETS;
+ table_packets.n_miss_packets = N_PACKETS;
+
+ status = test_table_type(&rte_table_lpm_ipv6_ops,
+ (void *)&lpm_ipv6_params,
+ (void *)&lpm_ipv6_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ lpm_ipv6_params.n_rules = 0;
+
+ status = test_table_type(&rte_table_lpm_ipv6_ops,
+ (void *)&lpm_ipv6_params,
+ (void *)&lpm_ipv6_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ lpm_ipv6_params.n_rules = 1 << 24;
+ lpm_ipv6_key.depth = 0;
+
+ status = test_table_type(&rte_table_lpm_ipv6_ops,
+ (void *)&lpm_ipv6_params,
+ (void *)&lpm_ipv6_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_ENTRY_ADD);
+
+ lpm_ipv6_key.depth = 129;
+ status = test_table_type(&rte_table_lpm_ipv6_ops,
+ (void *)&lpm_ipv6_params,
+ (void *)&lpm_ipv6_key, &table_packets, NULL, 0);
+ VERIFY(status, CHECK_TABLE_ENTRY_ADD);
+
+ return 0;
+}
+
+int
+test_table_hash8lru(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key8lru_params = {
+ .name = "TABLE",
+ .key_size = 8,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key8lru[8];
+ uint32_t *k8lru = (uint32_t *) key8lru;
+
+ memset(key8lru, 0, sizeof(key8lru));
+ k8lru[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xfefefefe;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key8_lru_ops,
+ (void *)&key8lru_params, (void *)key8lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key8lru_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key8_lru_ops,
+ (void *)&key8lru_params, (void *)key8lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key8lru_params.n_keys = 1<<16;
+ key8lru_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key8_lru_ops,
+ (void *)&key8lru_params, (void *)key8lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash16lru(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key16lru_params = {
+ .name = "TABLE",
+ .key_size = 16,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key16lru[16];
+ uint32_t *k16lru = (uint32_t *) key16lru;
+
+ memset(key16lru, 0, sizeof(key16lru));
+ k16lru[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xfefefefe;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key16_lru_ops,
+ (void *)&key16lru_params, (void *)key16lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key16lru_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key16_lru_ops,
+ (void *)&key16lru_params, (void *)key16lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key16lru_params.n_keys = 1<<16;
+ key16lru_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key16_lru_ops,
+ (void *)&key16lru_params, (void *)key16lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash32lru(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key32lru_params = {
+ .name = "TABLE",
+ .key_size = 32,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key32lru[32];
+ uint32_t *k32lru = (uint32_t *) key32lru;
+
+ memset(key32lru, 0, sizeof(key32lru));
+ k32lru[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xbdadadad;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key32_lru_ops,
+ (void *)&key32lru_params, (void *)key32lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key32lru_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key32_lru_ops,
+ (void *)&key32lru_params, (void *)key32lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key32lru_params.n_keys = 1<<16;
+ key32lru_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key32_lru_ops,
+ (void *)&key32lru_params, (void *)key32lru, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash8ext(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key8ext_params = {
+ .name = "TABLE",
+ .key_size = 8,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key8ext[8];
+ uint32_t *k8ext = (uint32_t *) key8ext;
+
+ memset(key8ext, 0, sizeof(key8ext));
+ k8ext[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xbdadadad;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key8_ext_ops,
+ (void *)&key8ext_params, (void *)key8ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key8ext_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key8_ext_ops,
+ (void *)&key8ext_params, (void *)key8ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key8ext_params.n_keys = 1<<16;
+ key8ext_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key8_ext_ops,
+ (void *)&key8ext_params, (void *)key8ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash16ext(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key16ext_params = {
+ .name = "TABLE",
+ .key_size = 16,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key16ext[16];
+ uint32_t *k16ext = (uint32_t *) key16ext;
+
+ memset(key16ext, 0, sizeof(key16ext));
+ k16ext[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xbdadadad;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key16_ext_ops,
+ (void *)&key16ext_params, (void *)key16ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key16ext_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key16_ext_ops,
+ (void *)&key16ext_params, (void *)key16ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key16ext_params.n_keys = 1<<16;
+ key16ext_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key16_ext_ops,
+ (void *)&key16ext_params, (void *)key16ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash32ext(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_params key32ext_params = {
+ .name = "TABLE",
+ .key_size = 32,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ uint8_t key32ext[32];
+ uint32_t *k32ext = (uint32_t *) key32ext;
+
+ memset(key32ext, 0, sizeof(key32ext));
+ k32ext[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xbdadadad;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_key32_ext_ops,
+ (void *)&key32ext_params, (void *)key32ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ key32ext_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_key32_ext_ops,
+ (void *)&key32ext_params, (void *)key32ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ key32ext_params.n_keys = 1<<16;
+ key32ext_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_key32_ext_ops,
+ (void *)&key32ext_params, (void *)key32ext, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
+
+int
+test_table_hash_cuckoo_combined(void)
+{
+ int status, i;
+
+ /* Traffic flow */
+ struct rte_table_hash_cuckoo_params cuckoo_params = {
+ .name = "TABLE",
+ .key_size = 32,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash_cuckoo,
+ .seed = 0,
+ };
+
+ uint8_t key_cuckoo[32];
+ uint32_t *kcuckoo = (uint32_t *) key_cuckoo;
+
+ memset(key_cuckoo, 0, sizeof(key_cuckoo));
+ kcuckoo[0] = 0xadadadad;
+
+ struct table_packets table_packets;
+
+ printf("--------------\n");
+ printf("RUNNING TEST - %s\n", __func__);
+ printf("--------------\n");
+ for (i = 0; i < 50; i++)
+ table_packets.hit_packet[i] = 0xadadadad;
+
+ for (i = 0; i < 50; i++)
+ table_packets.miss_packet[i] = 0xbdadadad;
+
+ table_packets.n_hit_packets = 50;
+ table_packets.n_miss_packets = 50;
+
+ status = test_table_type(&rte_table_hash_cuckoo_ops,
+ (void *)&cuckoo_params, (void *)key_cuckoo, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_OK);
+
+ /* Invalid parameters */
+ cuckoo_params.key_size = 0;
+
+ status = test_table_type(&rte_table_hash_cuckoo_ops,
+ (void *)&cuckoo_params, (void *)key_cuckoo, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ cuckoo_params.key_size = 32;
+ cuckoo_params.n_keys = 0;
+
+ status = test_table_type(&rte_table_hash_cuckoo_ops,
+ (void *)&cuckoo_params, (void *)key_cuckoo, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ cuckoo_params.n_keys = 1<<16;
+ cuckoo_params.f_hash = NULL;
+
+ status = test_table_type(&rte_table_hash_cuckoo_ops,
+ (void *)&cuckoo_params, (void *)key_cuckoo, &table_packets,
+ NULL, 0);
+ VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_table_combined.h b/src/spdk/dpdk/app/test/test_table_combined.h
new file mode 100644
index 000000000..d05866240
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_combined.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+/* Test prototypes */
+int test_table_stub_combined(void);
+int test_table_lpm_combined(void);
+int test_table_lpm_ipv6_combined(void);
+#ifdef RTE_LIBRTE_ACL
+int test_table_acl(void);
+#endif
+int test_table_hash8unoptimized(void);
+int test_table_hash8lru(void);
+int test_table_hash8ext(void);
+int test_table_hash16unoptimized(void);
+int test_table_hash16lru(void);
+int test_table_hash16ext(void);
+int test_table_hash32unoptimized(void);
+int test_table_hash32lru(void);
+int test_table_hash32ext(void);
+int test_table_hash_cuckoo_combined(void);
+
+/* Extern variables */
+typedef int (*combined_table_test)(void);
+
+extern combined_table_test table_tests_combined[];
+extern unsigned n_table_tests_combined;
diff --git a/src/spdk/dpdk/app/test/test_table_pipeline.c b/src/spdk/dpdk/app/test/test_table_pipeline.c
new file mode 100644
index 000000000..aabf4375d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_pipeline.c
@@ -0,0 +1,571 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <string.h>
+#include <rte_pipeline.h>
+#include <rte_log.h>
+#include <inttypes.h>
+#include <rte_hexdump.h>
+#include "test_table.h"
+#include "test_table_pipeline.h"
+
+#if 0
+
+static rte_pipeline_port_out_action_handler port_action_0x00
+ (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
+static rte_pipeline_port_out_action_handler port_action_0xFF
+ (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
+static rte_pipeline_port_out_action_handler port_action_stub
+ (struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
+
+
+rte_pipeline_port_out_action_handler port_action_0x00(struct rte_mbuf **pkts,
+ uint32_t n,
+ uint64_t *pkts_mask,
+ void *arg)
+{
+ RTE_SET_USED(pkts);
+ RTE_SET_USED(n);
+ RTE_SET_USED(arg);
+ printf("Port Action 0x00\n");
+ *pkts_mask = 0x00;
+ return 0;
+}
+
+rte_pipeline_port_out_action_handler port_action_0xFF(struct rte_mbuf **pkts,
+ uint32_t n,
+ uint64_t *pkts_mask,
+ void *arg)
+{
+ RTE_SET_USED(pkts);
+ RTE_SET_USED(n);
+ RTE_SET_USED(arg);
+ printf("Port Action 0xFF\n");
+ *pkts_mask = 0xFF;
+ return 0;
+}
+
+rte_pipeline_port_out_action_handler port_action_stub(struct rte_mbuf **pkts,
+ uint32_t n,
+ uint64_t *pkts_mask,
+ void *arg)
+{
+ RTE_SET_USED(pkts);
+ RTE_SET_USED(n);
+ RTE_SET_USED(pkts_mask);
+ RTE_SET_USED(arg);
+ printf("Port Action stub\n");
+ return 0;
+}
+
+#endif
+
+rte_pipeline_table_action_handler_hit
+table_action_0x00(struct rte_pipeline *p, struct rte_mbuf **pkts,
+ uint64_t pkts_mask, struct rte_pipeline_table_entry **entry, void *arg);
+
+rte_pipeline_table_action_handler_hit
+table_action_stub_hit(struct rte_pipeline *p, struct rte_mbuf **pkts,
+ uint64_t pkts_mask, struct rte_pipeline_table_entry **entry, void *arg);
+
+static int
+table_action_stub_miss(struct rte_pipeline *p, struct rte_mbuf **pkts,
+ uint64_t pkts_mask, struct rte_pipeline_table_entry *entry, void *arg);
+
+rte_pipeline_table_action_handler_hit
+table_action_0x00(__rte_unused struct rte_pipeline *p,
+ __rte_unused struct rte_mbuf **pkts,
+ uint64_t pkts_mask,
+ __rte_unused struct rte_pipeline_table_entry **entry,
+ __rte_unused void *arg)
+{
+ printf("Table Action, setting pkts_mask to 0x00\n");
+ pkts_mask = ~0x00;
+ rte_pipeline_ah_packet_drop(p, pkts_mask);
+ return 0;
+}
+
+rte_pipeline_table_action_handler_hit
+table_action_stub_hit(__rte_unused struct rte_pipeline *p,
+ __rte_unused struct rte_mbuf **pkts,
+ uint64_t pkts_mask,
+ __rte_unused struct rte_pipeline_table_entry **entry,
+ __rte_unused void *arg)
+{
+ printf("STUB Table Action Hit - doing nothing\n");
+ printf("STUB Table Action Hit - setting mask to 0x%"PRIx64"\n",
+ override_hit_mask);
+ pkts_mask = (~override_hit_mask) & 0x3;
+ rte_pipeline_ah_packet_drop(p, pkts_mask);
+ return 0;
+}
+
+static int
+table_action_stub_miss(struct rte_pipeline *p,
+ __rte_unused struct rte_mbuf **pkts,
+ uint64_t pkts_mask,
+ __rte_unused struct rte_pipeline_table_entry *entry,
+ __rte_unused void *arg)
+{
+ printf("STUB Table Action Miss - setting mask to 0x%"PRIx64"\n",
+ override_miss_mask);
+ pkts_mask = (~override_miss_mask) & 0x3;
+ rte_pipeline_ah_packet_drop(p, pkts_mask);
+ return 0;
+}
+
+enum e_test_type {
+ e_TEST_STUB = 0,
+ e_TEST_LPM,
+ e_TEST_LPM6,
+ e_TEST_HASH_LRU_8,
+ e_TEST_HASH_LRU_16,
+ e_TEST_HASH_LRU_32,
+ e_TEST_HASH_EXT_8,
+ e_TEST_HASH_EXT_16,
+ e_TEST_HASH_EXT_32
+};
+
+char pipeline_test_names[][64] = {
+ "Stub",
+ "LPM",
+ "LPMv6",
+ "8-bit LRU Hash",
+ "16-bit LRU Hash",
+ "32-bit LRU Hash",
+ "16-bit Ext Hash",
+ "8-bit Ext Hash",
+ "32-bit Ext Hash",
+ ""
+};
+
+
+static int
+cleanup_pipeline(void)
+{
+
+ rte_pipeline_free(p);
+
+ return 0;
+}
+
+
+static int check_pipeline_invalid_params(void);
+
+static int
+check_pipeline_invalid_params(void)
+{
+ struct rte_pipeline_params pipeline_params_1 = {
+ .name = NULL,
+ .socket_id = 0,
+ };
+ struct rte_pipeline_params pipeline_params_2 = {
+ .name = "PIPELINE",
+ .socket_id = -1,
+ };
+ struct rte_pipeline_params pipeline_params_3 = {
+ .name = "PIPELINE",
+ .socket_id = 127,
+ };
+
+ p = rte_pipeline_create(NULL);
+ if (p != NULL) {
+ RTE_LOG(INFO, PIPELINE,
+ "%s: configured pipeline with null params\n",
+ __func__);
+ goto fail;
+ }
+ p = rte_pipeline_create(&pipeline_params_1);
+ if (p != NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with NULL "
+ "name\n", __func__);
+ goto fail;
+ }
+
+ p = rte_pipeline_create(&pipeline_params_2);
+ if (p != NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid "
+ "socket\n", __func__);
+ goto fail;
+ }
+
+ if (rte_eal_has_hugepages()) {
+ p = rte_pipeline_create(&pipeline_params_3);
+ if (p != NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with "
+ "invalid socket\n", __func__);
+ goto fail;
+ }
+ }
+
+ /* Check pipeline consistency */
+ if (!rte_pipeline_check(p)) {
+ rte_panic("Pipeline consistency reported as OK\n");
+ goto fail;
+ }
+
+
+ return 0;
+fail:
+ return -1;
+}
+
+
+static int
+setup_pipeline(int test_type)
+{
+ int ret;
+ int i;
+ struct rte_pipeline_params pipeline_params = {
+ .name = "PIPELINE",
+ .socket_id = 0,
+ };
+
+ RTE_LOG(INFO, PIPELINE, "%s: **** Setting up %s test\n",
+ __func__, pipeline_test_names[test_type]);
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
+ __func__);
+ goto fail;
+ }
+
+ ret = rte_pipeline_free(p);
+ if (ret != 0) {
+ RTE_LOG(INFO, PIPELINE, "%s: Failed to free pipeline\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Pipeline configuration */
+ p = rte_pipeline_create(&pipeline_params);
+ if (p == NULL) {
+ RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
+ __func__);
+ goto fail;
+ }
+
+
+ /* Input port configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_port_ring_reader_params port_ring_params = {
+ .ring = rings_rx[i],
+ };
+
+ struct rte_pipeline_port_in_params port_params = {
+ .ops = &rte_port_ring_reader_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .burst_size = BURST_SIZE,
+ };
+
+ /* Put in action for some ports */
+ if (i)
+ port_params.f_action = NULL;
+
+ ret = rte_pipeline_port_in_create(p, &port_params,
+ &port_in_id[i]);
+ if (ret) {
+ rte_panic("Unable to configure input port %d, ret:%d\n",
+ i, ret);
+ goto fail;
+ }
+ }
+
+ /* output Port configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_port_ring_writer_params port_ring_params = {
+ .ring = rings_tx[i],
+ .tx_burst_sz = BURST_SIZE,
+ };
+
+ struct rte_pipeline_port_out_params port_params = {
+ .ops = &rte_port_ring_writer_ops,
+ .arg_create = (void *) &port_ring_params,
+ .f_action = NULL,
+ .arg_ah = NULL,
+ };
+
+ if (i)
+ port_params.f_action = port_out_action;
+
+ if (rte_pipeline_port_out_create(p, &port_params,
+ &port_out_id[i])) {
+ rte_panic("Unable to configure output port %d\n", i);
+ goto fail;
+ }
+ }
+
+ /* Table configuration */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_pipeline_table_params table_params = {
+ .ops = &rte_table_stub_ops,
+ .arg_create = NULL,
+ .f_action_hit = action_handler_hit,
+ .f_action_miss = action_handler_miss,
+ .action_data_size = 0,
+ };
+
+ if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
+ rte_panic("Unable to configure table %u\n", i);
+ goto fail;
+ }
+
+ if (connect_miss_action_to_table)
+ if (rte_pipeline_table_create(p, &table_params,
+ &table_id[i+2])) {
+ rte_panic("Unable to configure table %u\n", i);
+ goto fail;
+ }
+ }
+
+ for (i = 0; i < N_PORTS; i++)
+ if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
+ table_id[i])) {
+ rte_panic("Unable to connect input port %u to "
+ "table %u\n", port_in_id[i], table_id[i]);
+ goto fail;
+ }
+
+ /* Add entries to tables */
+ for (i = 0; i < N_PORTS; i++) {
+ struct rte_pipeline_table_entry default_entry = {
+ .action = (enum rte_pipeline_action)
+ table_entry_default_action,
+ {.port_id = port_out_id[i^1]},
+ };
+ struct rte_pipeline_table_entry *default_entry_ptr;
+
+ if (connect_miss_action_to_table) {
+ printf("Setting first table to output to next table\n");
+ default_entry.action = RTE_PIPELINE_ACTION_TABLE;
+ default_entry.table_id = table_id[i+2];
+ }
+
+ /* Add the default action for the table. */
+ ret = rte_pipeline_table_default_entry_add(p, table_id[i],
+ &default_entry, &default_entry_ptr);
+ if (ret < 0) {
+ rte_panic("Unable to add default entry to table %u "
+ "code %d\n", table_id[i], ret);
+ goto fail;
+ } else
+ printf("Added default entry to table id %d with "
+ "action %x\n",
+ table_id[i], default_entry.action);
+
+ if (connect_miss_action_to_table) {
+ /* We create a second table so the first can pass
+ traffic into it */
+ struct rte_pipeline_table_entry default_entry = {
+ .action = RTE_PIPELINE_ACTION_PORT,
+ {.port_id = port_out_id[i^1]},
+ };
+ printf("Setting secont table to output to port\n");
+
+ /* Add the default action for the table. */
+ ret = rte_pipeline_table_default_entry_add(p,
+ table_id[i+2],
+ &default_entry, &default_entry_ptr);
+ if (ret < 0) {
+ rte_panic("Unable to add default entry to "
+ "table %u code %d\n",
+ table_id[i], ret);
+ goto fail;
+ } else
+ printf("Added default entry to table id %d "
+ "with action %x\n",
+ table_id[i], default_entry.action);
+ }
+ }
+
+ /* Enable input ports */
+ for (i = 0; i < N_PORTS ; i++)
+ if (rte_pipeline_port_in_enable(p, port_in_id[i]))
+ rte_panic("Unable to enable input port %u\n",
+ port_in_id[i]);
+
+ /* Check pipeline consistency */
+ if (rte_pipeline_check(p) < 0) {
+ rte_panic("Pipeline consistency check failed\n");
+ goto fail;
+ } else
+ printf("Pipeline Consistency OK!\n");
+
+ return 0;
+fail:
+
+ return -1;
+}
+
+static int
+test_pipeline_single_filter(int test_type, int expected_count)
+{
+ int i;
+ int j;
+ int ret;
+ int tx_count;
+
+ RTE_LOG(INFO, PIPELINE, "%s: **** Running %s test\n",
+ __func__, pipeline_test_names[test_type]);
+ /* Run pipeline once */
+ for (i = 0; i < N_PORTS; i++)
+ rte_pipeline_run(p);
+
+
+ ret = rte_pipeline_flush(NULL);
+ if (ret != -EINVAL) {
+ RTE_LOG(INFO, PIPELINE,
+ "%s: No pipeline flush error NULL pipeline (%d)\n",
+ __func__, ret);
+ goto fail;
+ }
+
+ /*
+ * Allocate a few mbufs and manually insert into the rings. */
+ for (i = 0; i < N_PORTS; i++)
+ for (j = 0; j < N_PORTS; j++) {
+ struct rte_mbuf *m;
+ uint8_t *key;
+ uint32_t *k32;
+
+ m = rte_pktmbuf_alloc(pool);
+ if (m == NULL) {
+ rte_panic("Failed to alloc mbuf from pool\n");
+ return -1;
+ }
+ key = RTE_MBUF_METADATA_UINT8_PTR(m,
+ APP_METADATA_OFFSET(32));
+
+ k32 = (uint32_t *) key;
+ k32[0] = 0xadadadad >> (j % 2);
+
+ RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n",
+ __func__, i);
+ rte_ring_enqueue(rings_rx[i], m);
+ }
+
+ /* Run pipeline once */
+ for (i = 0; i < N_PORTS; i++)
+ rte_pipeline_run(p);
+
+ /*
+ * need to flush the pipeline, as there may be less hits than the burst
+ size and they will not have been flushed to the tx rings. */
+ rte_pipeline_flush(p);
+
+ /*
+ * Now we'll see what we got back on the tx rings. We should see whatever
+ * packets we had hits on that were destined for the output ports.
+ */
+ tx_count = 0;
+
+ for (i = 0; i < N_PORTS; i++) {
+ void *objs[RING_TX_SIZE];
+ struct rte_mbuf *mbuf;
+
+ ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
+ if (ret <= 0)
+ printf("Got no objects from ring %d - error code %d\n",
+ i, ret);
+ else {
+ printf("Got %d object(s) from ring %d!\n", ret, i);
+ for (j = 0; j < ret; j++) {
+ mbuf = objs[j];
+ rte_hexdump(stdout, "Object:",
+ rte_pktmbuf_mtod(mbuf, char *),
+ mbuf->data_len);
+ rte_pktmbuf_free(mbuf);
+ }
+ tx_count += ret;
+ }
+ }
+
+ if (tx_count != expected_count) {
+ RTE_LOG(INFO, PIPELINE,
+ "%s: Unexpected packets out for %s test, expected %d, "
+ "got %d\n", __func__, pipeline_test_names[test_type],
+ expected_count, tx_count);
+ goto fail;
+ }
+
+ cleanup_pipeline();
+
+ return 0;
+fail:
+ return -1;
+
+}
+
+int
+test_table_pipeline(void)
+{
+ /* TEST - All packets dropped */
+ action_handler_hit = NULL;
+ action_handler_miss = NULL;
+ table_entry_default_action = RTE_PIPELINE_ACTION_DROP;
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 0) < 0)
+ return -1;
+
+ /* TEST - All packets passed through */
+ table_entry_default_action = RTE_PIPELINE_ACTION_PORT;
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
+ return -1;
+
+ /* TEST - one packet per port */
+ action_handler_hit = NULL;
+ action_handler_miss = table_action_stub_miss;
+ table_entry_default_action = RTE_PIPELINE_ACTION_PORT;
+ override_miss_mask = 0x01; /* one packet per port */
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
+ return -1;
+
+ /* TEST - one packet per port */
+ override_miss_mask = 0x02; /*all per port */
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
+ return -1;
+
+ /* TEST - all packets per port */
+ override_miss_mask = 0x03; /*all per port */
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
+ return -1;
+
+ /*
+ * This test will set up two tables in the pipeline. the first table
+ * will forward to another table on miss, and the second table will
+ * forward to port.
+ */
+ connect_miss_action_to_table = 1;
+ table_entry_default_action = RTE_PIPELINE_ACTION_TABLE;
+ action_handler_hit = NULL; /* not for stub, hitmask always zero */
+ action_handler_miss = NULL;
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
+ return -1;
+ connect_miss_action_to_table = 0;
+
+ printf("TEST - two tables, hitmask override to 0x01\n");
+ connect_miss_action_to_table = 1;
+ action_handler_miss = table_action_stub_miss;
+ override_miss_mask = 0x01;
+ setup_pipeline(e_TEST_STUB);
+ if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
+ return -1;
+ connect_miss_action_to_table = 0;
+
+ if (check_pipeline_invalid_params()) {
+ RTE_LOG(INFO, PIPELINE, "%s: Check pipeline invalid params "
+ "failed.\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_table_pipeline.h b/src/spdk/dpdk/app/test/test_table_pipeline.h
new file mode 100644
index 000000000..d66d09d6f
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_pipeline.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+/* Test prototypes */
+int test_table_pipeline(void);
diff --git a/src/spdk/dpdk/app/test/test_table_ports.c b/src/spdk/dpdk/app/test/test_table_ports.c
new file mode 100644
index 000000000..d921b2e20
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_ports.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include "test_table_ports.h"
+#include "test_table.h"
+
+port_test port_tests[] = {
+ test_port_ring_reader,
+ test_port_ring_writer,
+};
+
+unsigned n_port_tests = RTE_DIM(port_tests);
+
+/* Port tests */
+int
+test_port_ring_reader(void)
+{
+ int status, i;
+ struct rte_port_ring_reader_params port_ring_reader_params;
+ void *port;
+
+ /* Invalid params */
+ port = rte_port_ring_reader_ops.f_create(NULL, 0);
+ if (port != NULL)
+ return -1;
+
+ status = rte_port_ring_reader_ops.f_free(port);
+ if (status >= 0)
+ return -2;
+
+ /* Create and free */
+ port_ring_reader_params.ring = RING_RX;
+ port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0);
+ if (port == NULL)
+ return -3;
+
+ status = rte_port_ring_reader_ops.f_free(port);
+ if (status != 0)
+ return -4;
+
+ /* -- Traffic RX -- */
+ int expected_pkts, received_pkts;
+ struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
+
+ port_ring_reader_params.ring = RING_RX;
+ port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0);
+
+ /* Single packet */
+ mbuf[0] = (void *)rte_pktmbuf_alloc(pool);
+
+ expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring,
+ mbuf, 1, NULL);
+ received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf, 1);
+
+ if (received_pkts < expected_pkts)
+ return -5;
+
+ rte_pktmbuf_free(res_mbuf[0]);
+
+ /* Multiple packets */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ mbuf[i] = rte_pktmbuf_alloc(pool);
+
+ expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring,
+ (void * const *) mbuf, RTE_PORT_IN_BURST_SIZE_MAX, NULL);
+ received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf,
+ RTE_PORT_IN_BURST_SIZE_MAX);
+
+ if (received_pkts < expected_pkts)
+ return -6;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(res_mbuf[i]);
+
+ return 0;
+}
+
+int
+test_port_ring_writer(void)
+{
+ int status, i;
+ struct rte_port_ring_writer_params port_ring_writer_params;
+ void *port;
+
+ /* Invalid params */
+ port = rte_port_ring_writer_ops.f_create(NULL, 0);
+ if (port != NULL)
+ return -1;
+
+ status = rte_port_ring_writer_ops.f_free(port);
+ if (status >= 0)
+ return -2;
+
+ port_ring_writer_params.ring = NULL;
+
+ port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
+ if (port != NULL)
+ return -3;
+
+ port_ring_writer_params.ring = RING_TX;
+ port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX + 1;
+
+ port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
+ if (port != NULL)
+ return -4;
+
+ /* Create and free */
+ port_ring_writer_params.ring = RING_TX;
+ port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX;
+
+ port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
+ if (port == NULL)
+ return -5;
+
+ status = rte_port_ring_writer_ops.f_free(port);
+ if (status != 0)
+ return -6;
+
+ /* -- Traffic TX -- */
+ int expected_pkts, received_pkts;
+ struct rte_mbuf *mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
+ struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
+
+ port_ring_writer_params.ring = RING_TX;
+ port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX;
+ port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
+
+ /* Single packet */
+ mbuf[0] = rte_pktmbuf_alloc(pool);
+
+ rte_port_ring_writer_ops.f_tx(port, mbuf[0]);
+ rte_port_ring_writer_ops.f_flush(port);
+ expected_pkts = 1;
+ received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
+ (void **)res_mbuf, port_ring_writer_params.tx_burst_sz, NULL);
+
+ if (received_pkts < expected_pkts)
+ return -7;
+
+ rte_pktmbuf_free(res_mbuf[0]);
+
+ /* Multiple packets */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
+ mbuf[i] = rte_pktmbuf_alloc(pool);
+ rte_port_ring_writer_ops.f_tx(port, mbuf[i]);
+ }
+
+ expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
+ received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
+ (void **)res_mbuf, port_ring_writer_params.tx_burst_sz, NULL);
+
+ if (received_pkts < expected_pkts)
+ return -8;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(res_mbuf[i]);
+
+ /* TX Bulk */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ mbuf[i] = rte_pktmbuf_alloc(pool);
+ rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-1);
+
+ expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
+ received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
+ (void **)res_mbuf, port_ring_writer_params.tx_burst_sz, NULL);
+
+ if (received_pkts < expected_pkts)
+ return -8;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(res_mbuf[i]);
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ mbuf[i] = rte_pktmbuf_alloc(pool);
+ rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-3);
+ rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)2);
+
+ expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
+ received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
+ (void **)res_mbuf, port_ring_writer_params.tx_burst_sz, NULL);
+
+ if (received_pkts < expected_pkts)
+ return -9;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(res_mbuf[i]);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_table_ports.h b/src/spdk/dpdk/app/test/test_table_ports.h
new file mode 100644
index 000000000..dfa611931
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_ports.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+/* Test prototypes */
+int test_port_ring_reader(void);
+int test_port_ring_writer(void);
+
+/* Extern variables */
+typedef int (*port_test)(void);
+
+extern port_test port_tests[];
+extern unsigned n_port_tests;
diff --git a/src/spdk/dpdk/app/test/test_table_tables.c b/src/spdk/dpdk/app/test/test_table_tables.c
new file mode 100644
index 000000000..1aa269f95
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_tables.c
@@ -0,0 +1,1053 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+#include <string.h>
+#include <rte_byteorder.h>
+#include <rte_table_lpm_ipv6.h>
+#include <rte_lru.h>
+#include <rte_cycles.h>
+#include "test_table_tables.h"
+#include "test_table.h"
+
+table_test table_tests[] = {
+ test_table_stub,
+ test_table_array,
+ test_table_lpm,
+ test_table_lpm_ipv6,
+ test_table_hash_lru,
+ test_table_hash_ext,
+ test_table_hash_cuckoo,
+};
+
+#define PREPARE_PACKET(mbuf, value) do { \
+ uint32_t *k32, *signature; \
+ uint8_t *key; \
+ mbuf = rte_pktmbuf_alloc(pool); \
+ signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, \
+ APP_METADATA_OFFSET(0)); \
+ key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, \
+ APP_METADATA_OFFSET(32)); \
+ memset(key, 0, 32); \
+ k32 = (uint32_t *) key; \
+ k32[0] = (value); \
+ *signature = pipeline_test_hash(key, NULL, 0, 0); \
+} while (0)
+
+unsigned n_table_tests = RTE_DIM(table_tests);
+
+/* Function prototypes */
+static int
+test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
+static int
+test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
+
+struct rte_bucket_4_8 {
+ /* Cache line 0 */
+ uint64_t signature;
+ uint64_t lru_list;
+ struct rte_bucket_4_8 *next;
+ uint64_t next_valid;
+ uint64_t key[4];
+ /* Cache line 1 */
+ uint8_t data[0];
+};
+
+#if RTE_TABLE_HASH_LRU_STRATEGY == 3
+uint64_t shuffles = 0xfffffffdfffbfff9ULL;
+#else
+uint64_t shuffles = 0x0003000200010000ULL;
+#endif
+
+static int test_lru_update(void)
+{
+ struct rte_bucket_4_8 b;
+ struct rte_bucket_4_8 *bucket;
+ uint32_t i;
+ uint64_t pos;
+ uint64_t iterations;
+ uint64_t j;
+ int poss;
+
+ printf("---------------------------\n");
+ printf("Testing lru_update macro...\n");
+ printf("---------------------------\n");
+ bucket = &b;
+ iterations = 10;
+#if RTE_TABLE_HASH_LRU_STRATEGY == 3
+ bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
+#else
+ bucket->lru_list = 0x0000000100020003ULL;
+#endif
+ poss = 0;
+ for (j = 0; j < iterations; j++)
+ for (i = 0; i < 9; i++) {
+ uint32_t idx = i >> 1;
+ lru_update(bucket, idx);
+ pos = lru_pos(bucket);
+ poss += pos;
+ printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
+ "pos=%"PRIx64"\n",
+ __func__, i, bucket->lru_list, i>>1, pos);
+ }
+
+ if (bucket->lru_list != shuffles) {
+ printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
+ PRIx64"\n",
+ __func__, i, bucket->lru_list, shuffles);
+ return -1;
+ }
+ printf("%s: output checksum of results =%d\n",
+ __func__, poss);
+#if 0
+ if (poss != 126) {
+ printf("%s: ERROR output checksum of results =%d expected %d\n",
+ __func__, poss, 126);
+ return -1;
+ }
+#endif
+
+ fflush(stdout);
+
+ uint64_t sc_start = rte_rdtsc();
+ iterations = 100000000;
+ poss = 0;
+ for (j = 0; j < iterations; j++) {
+ for (i = 0; i < 4; i++) {
+ lru_update(bucket, i);
+ pos |= bucket->lru_list;
+ }
+ }
+ uint64_t sc_end = rte_rdtsc();
+
+ printf("%s: output checksum of results =%llu\n",
+ __func__, (long long unsigned int)pos);
+ printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
+ __func__, sc_start, sc_end);
+ printf("\nlru_update: %lu cycles per loop iteration.\n\n",
+ (long unsigned int)((sc_end-sc_start)/(iterations*4)));
+
+ return 0;
+}
+
+/* Table tests */
+int
+test_table_stub(void)
+{
+ int i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+
+ /* Create */
+ table = rte_table_stub_ops.f_create(NULL, 0, 1);
+ if (table == NULL)
+ return -1;
+
+ /* Traffic flow */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0)
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ expected_mask = 0;
+ rte_table_stub_ops.f_lookup(table, mbufs, -1,
+ &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -2;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ return 0;
+}
+
+int
+test_table_array(void)
+{
+ int status, i;
+ uint64_t result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry1, entry2;
+ void *entry_ptr;
+ int key_found;
+
+ /* Initialize params and create tables */
+ struct rte_table_array_params array_params = {
+ .n_entries = 7,
+ .offset = APP_METADATA_OFFSET(1)
+ };
+
+ table = rte_table_array_ops.f_create(NULL, 0, 1);
+ if (table != NULL)
+ return -1;
+
+ array_params.n_entries = 0;
+
+ table = rte_table_array_ops.f_create(&array_params, 0, 1);
+ if (table != NULL)
+ return -2;
+
+ array_params.n_entries = 7;
+
+ table = rte_table_array_ops.f_create(&array_params, 0, 1);
+ if (table != NULL)
+ return -3;
+
+ array_params.n_entries = 1 << 24;
+ array_params.offset = APP_METADATA_OFFSET(1);
+
+ table = rte_table_array_ops.f_create(&array_params, 0, 1);
+ if (table == NULL)
+ return -4;
+
+ array_params.offset = APP_METADATA_OFFSET(32);
+
+ table = rte_table_array_ops.f_create(&array_params, 0, 1);
+ if (table == NULL)
+ return -5;
+
+ /* Free */
+ status = rte_table_array_ops.f_free(table);
+ if (status < 0)
+ return -6;
+
+ status = rte_table_array_ops.f_free(NULL);
+ if (status == 0)
+ return -7;
+
+ /* Add */
+ struct rte_table_array_key array_key_1 = {
+ .pos = 10,
+ };
+ struct rte_table_array_key array_key_2 = {
+ .pos = 20,
+ };
+ entry1 = 'A';
+ entry2 = 'B';
+
+ table = rte_table_array_ops.f_create(&array_params, 0, 1);
+ if (table == NULL)
+ return -8;
+
+ status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -9;
+
+ status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -10;
+
+ status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
+ &entry1, &key_found, &entry_ptr);
+ if (status != 0)
+ return -11;
+
+ /* Traffic flow */
+ status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
+ &entry2, &key_found, &entry_ptr);
+ if (status != 0)
+ return -12;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0)
+ PREPARE_PACKET(mbufs[i], 10);
+ else
+ PREPARE_PACKET(mbufs[i], 20);
+
+ rte_table_array_ops.f_lookup(table, mbufs, -1,
+ &result_mask, (void **)entries);
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0 && *entries[i] != 'A')
+ return -13;
+ else
+ if (i % 2 == 1 && *entries[i] != 'B')
+ return -13;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = rte_table_array_ops.f_free(table);
+
+ return 0;
+}
+
+int
+test_table_lpm(void)
+{
+ int status, i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry;
+ void *entry_ptr;
+ int key_found;
+ uint32_t entry_size = 1;
+
+ /* Initialize params and create tables */
+ struct rte_table_lpm_params lpm_params = {
+ .name = "LPM",
+ .n_rules = 1 << 24,
+ .number_tbl8s = 1 << 8,
+ .flags = 0,
+ .entry_unique_size = entry_size,
+ .offset = APP_METADATA_OFFSET(1)
+ };
+
+ table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
+ if (table != NULL)
+ return -1;
+
+ lpm_params.name = NULL;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -2;
+
+ lpm_params.name = "LPM";
+ lpm_params.n_rules = 0;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -3;
+
+ lpm_params.n_rules = 1 << 24;
+ lpm_params.offset = APP_METADATA_OFFSET(32);
+ lpm_params.entry_unique_size = 0;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -4;
+
+ lpm_params.entry_unique_size = entry_size + 1;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -5;
+
+ lpm_params.entry_unique_size = entry_size;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
+ if (table == NULL)
+ return -6;
+
+ /* Free */
+ status = rte_table_lpm_ops.f_free(table);
+ if (status < 0)
+ return -7;
+
+ status = rte_table_lpm_ops.f_free(NULL);
+ if (status == 0)
+ return -8;
+
+ /* Add */
+ struct rte_table_lpm_key lpm_key;
+ lpm_key.ip = 0xadadadad;
+
+ table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
+ if (table == NULL)
+ return -9;
+
+ status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -10;
+
+ status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -11;
+
+ status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -12;
+
+ lpm_key.depth = 0;
+ status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -13;
+
+ lpm_key.depth = 33;
+ status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -14;
+
+ lpm_key.depth = 16;
+ status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
+ &entry_ptr);
+ if (status != 0)
+ return -15;
+
+ /* Delete */
+ status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
+ if (status == 0)
+ return -16;
+
+ status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
+ if (status == 0)
+ return -17;
+
+ lpm_key.depth = 0;
+ status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
+ if (status == 0)
+ return -18;
+
+ lpm_key.depth = 33;
+ status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
+ if (status == 0)
+ return -19;
+
+ lpm_key.depth = 16;
+ status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
+ if (status != 0)
+ return -20;
+
+ status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
+ if (status != 0)
+ return -21;
+
+ /* Traffic flow */
+ entry = 'A';
+ status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
+ &entry_ptr);
+ if (status < 0)
+ return -22;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0) {
+ expected_mask |= (uint64_t)1 << i;
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ } else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ rte_table_lpm_ops.f_lookup(table, mbufs, -1,
+ &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -23;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = rte_table_lpm_ops.f_free(table);
+
+ return 0;
+}
+
+int
+test_table_lpm_ipv6(void)
+{
+ int status, i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry;
+ void *entry_ptr;
+ int key_found;
+ uint32_t entry_size = 1;
+
+ /* Initialize params and create tables */
+ struct rte_table_lpm_ipv6_params lpm_params = {
+ .name = "LPM",
+ .n_rules = 1 << 24,
+ .number_tbl8s = 1 << 18,
+ .entry_unique_size = entry_size,
+ .offset = APP_METADATA_OFFSET(32)
+ };
+
+ table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
+ if (table != NULL)
+ return -1;
+
+ lpm_params.name = NULL;
+
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -2;
+
+ lpm_params.name = "LPM";
+ lpm_params.n_rules = 0;
+
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -3;
+
+ lpm_params.n_rules = 1 << 24;
+ lpm_params.number_tbl8s = 0;
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -4;
+
+ lpm_params.number_tbl8s = 1 << 18;
+ lpm_params.entry_unique_size = 0;
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -5;
+
+ lpm_params.entry_unique_size = entry_size + 1;
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table != NULL)
+ return -6;
+
+ lpm_params.entry_unique_size = entry_size;
+ lpm_params.offset = APP_METADATA_OFFSET(32);
+
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table == NULL)
+ return -7;
+
+ /* Free */
+ status = rte_table_lpm_ipv6_ops.f_free(table);
+ if (status < 0)
+ return -8;
+
+ status = rte_table_lpm_ipv6_ops.f_free(NULL);
+ if (status == 0)
+ return -9;
+
+ /* Add */
+ struct rte_table_lpm_ipv6_key lpm_key;
+
+ lpm_key.ip[0] = 0xad;
+ lpm_key.ip[1] = 0xad;
+ lpm_key.ip[2] = 0xad;
+ lpm_key.ip[3] = 0xad;
+
+ table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
+ if (table == NULL)
+ return -10;
+
+ status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -11;
+
+ status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -12;
+
+ status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
+ &entry_ptr);
+ if (status == 0)
+ return -13;
+
+ lpm_key.depth = 0;
+ status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -14;
+
+ lpm_key.depth = 129;
+ status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -15;
+
+ lpm_key.depth = 16;
+ status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
+ &key_found, &entry_ptr);
+ if (status != 0)
+ return -16;
+
+ /* Delete */
+ status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
+ NULL);
+ if (status == 0)
+ return -17;
+
+ status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
+ if (status == 0)
+ return -18;
+
+ lpm_key.depth = 0;
+ status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
+ NULL);
+ if (status == 0)
+ return -19;
+
+ lpm_key.depth = 129;
+ status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
+ NULL);
+ if (status == 0)
+ return -20;
+
+ lpm_key.depth = 16;
+ status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
+ NULL);
+ if (status != 0)
+ return -21;
+
+ status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
+ NULL);
+ if (status != 0)
+ return -22;
+
+ /* Traffic flow */
+ entry = 'A';
+ status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
+ &key_found, &entry_ptr);
+ if (status < 0)
+ return -23;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0) {
+ expected_mask |= (uint64_t)1 << i;
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ } else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
+ &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -24;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = rte_table_lpm_ipv6_ops.f_free(table);
+
+ return 0;
+}
+
+static int
+test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
+{
+ int status, i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry;
+ void *entry_ptr;
+ int key_found;
+
+ /* Initialize params and create tables */
+ struct rte_table_hash_params hash_params = {
+ .name = "TABLE",
+ .key_size = key_size,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 10,
+ .n_buckets = 1 << 10,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ hash_params.n_keys = 0;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table != NULL)
+ return -1;
+
+ hash_params.n_keys = 1 << 10;
+ hash_params.f_hash = NULL;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table != NULL)
+ return -4;
+
+ hash_params.f_hash = pipeline_test_hash;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table == NULL)
+ return -5;
+
+ /* Free */
+ status = ops->f_free(table);
+ if (status < 0)
+ return -6;
+
+ status = ops->f_free(NULL);
+ if (status == 0)
+ return -7;
+
+ /* Add */
+ uint8_t key[32];
+ uint32_t *k32 = (uint32_t *) &key;
+
+ memset(key, 0, 32);
+ k32[0] = rte_be_to_cpu_32(0xadadadad);
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table == NULL)
+ return -8;
+
+ entry = 'A';
+ status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
+ if (status != 0)
+ return -9;
+
+ /* Delete */
+ status = ops->f_delete(table, &key, &key_found, NULL);
+ if (status != 0)
+ return -10;
+
+ status = ops->f_delete(table, &key, &key_found, NULL);
+ if (status != 0)
+ return -11;
+
+ /* Traffic flow */
+ entry = 'A';
+ status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
+ if (status < 0)
+ return -12;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0) {
+ expected_mask |= (uint64_t)1 << i;
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ } else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -13;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = ops->f_free(table);
+
+ return 0;
+}
+
+static int
+test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
+{
+ int status, i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry;
+ int key_found;
+ void *entry_ptr;
+
+ /* Initialize params and create tables */
+ struct rte_table_hash_params hash_params = {
+ .name = "TABLE",
+ .key_size = key_size,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 10,
+ .n_buckets = 1 << 10,
+ .f_hash = pipeline_test_hash,
+ .seed = 0,
+ };
+
+ hash_params.n_keys = 0;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table != NULL)
+ return -1;
+
+ hash_params.n_keys = 1 << 10;
+ hash_params.key_offset = APP_METADATA_OFFSET(1);
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table == NULL)
+ return -3;
+
+ hash_params.key_offset = APP_METADATA_OFFSET(32);
+ hash_params.f_hash = NULL;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table != NULL)
+ return -4;
+
+ hash_params.f_hash = pipeline_test_hash;
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table == NULL)
+ return -5;
+
+ /* Free */
+ status = ops->f_free(table);
+ if (status < 0)
+ return -6;
+
+ status = ops->f_free(NULL);
+ if (status == 0)
+ return -7;
+
+ /* Add */
+ uint8_t key[32];
+ uint32_t *k32 = (uint32_t *) &key;
+
+ memset(key, 0, 32);
+ k32[0] = rte_be_to_cpu_32(0xadadadad);
+
+ table = ops->f_create(&hash_params, 0, 1);
+ if (table == NULL)
+ return -8;
+
+ entry = 'A';
+ status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
+ if (status != 0)
+ return -9;
+
+ /* Delete */
+ status = ops->f_delete(table, &key, &key_found, NULL);
+ if (status != 0)
+ return -10;
+
+ status = ops->f_delete(table, &key, &key_found, NULL);
+ if (status != 0)
+ return -11;
+
+ /* Traffic flow */
+ entry = 'A';
+ status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
+ if (status < 0)
+ return -12;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0) {
+ expected_mask |= (uint64_t)1 << i;
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ } else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -13;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = ops->f_free(table);
+
+ return 0;
+}
+
+int
+test_table_hash_lru(void)
+{
+ int status;
+
+ status = test_table_hash_lru_generic(
+ &rte_table_hash_key8_lru_ops,
+ 8);
+ if (status < 0)
+ return status;
+
+ status = test_table_hash_lru_generic(
+ &rte_table_hash_key16_lru_ops,
+ 16);
+ if (status < 0)
+ return status;
+
+ status = test_table_hash_lru_generic(
+ &rte_table_hash_key32_lru_ops,
+ 32);
+ if (status < 0)
+ return status;
+
+ status = test_lru_update();
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+int
+test_table_hash_ext(void)
+{
+ int status;
+
+ status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
+ if (status < 0)
+ return status;
+
+ status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
+ if (status < 0)
+ return status;
+
+ status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+
+int
+test_table_hash_cuckoo(void)
+{
+ int status, i;
+ uint64_t expected_mask = 0, result_mask;
+ struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
+ void *table;
+ char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
+ char entry;
+ void *entry_ptr;
+ int key_found;
+ uint32_t entry_size = 1;
+
+ /* Initialize params and create tables */
+ struct rte_table_hash_cuckoo_params cuckoo_params = {
+ .name = "TABLE",
+ .key_size = 32,
+ .key_offset = APP_METADATA_OFFSET(32),
+ .key_mask = NULL,
+ .n_keys = 1 << 16,
+ .n_buckets = 1 << 16,
+ .f_hash = pipeline_test_hash_cuckoo,
+ .seed = 0,
+ };
+
+ table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
+ if (table != NULL)
+ return -1;
+
+ cuckoo_params.key_size = 0;
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
+ 0, entry_size);
+ if (table != NULL)
+ return -2;
+
+ cuckoo_params.key_size = 32;
+ cuckoo_params.n_keys = 0;
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
+ 0, entry_size);
+ if (table != NULL)
+ return -3;
+
+ cuckoo_params.n_keys = 1 << 24;
+ cuckoo_params.f_hash = NULL;
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
+ 0, entry_size);
+ if (table != NULL)
+ return -4;
+
+ cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
+ cuckoo_params.name = NULL;
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
+ 0, entry_size);
+ if (table != NULL)
+ return -5;
+
+ cuckoo_params.name = "CUCKOO";
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
+ 0, entry_size);
+ if (table == NULL)
+ return -6;
+
+ /* Free */
+ status = rte_table_hash_cuckoo_ops.f_free(table);
+ if (status < 0)
+ return -7;
+
+ status = rte_table_hash_cuckoo_ops.f_free(NULL);
+ if (status == 0)
+ return -8;
+
+ /* Add */
+ uint8_t key_cuckoo[32];
+ uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
+
+ memset(key_cuckoo, 0, 32);
+ kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
+
+ table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
+ if (table == NULL)
+ return -9;
+
+ entry = 'A';
+ status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
+ &entry, &key_found, &entry_ptr);
+ if (status == 0)
+ return -10;
+
+ status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
+ &key_found, &entry_ptr);
+ if (status == 0)
+ return -11;
+
+ status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
+ NULL, &key_found, &entry_ptr);
+ if (status == 0)
+ return -12;
+
+ status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
+ &entry, &key_found, &entry_ptr);
+ if (status != 0)
+ return -13;
+
+ status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
+ &entry, &key_found, &entry_ptr);
+ if (status != 0)
+ return -14;
+
+ /* Delete */
+ status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
+ &key_found, NULL);
+ if (status == 0)
+ return -15;
+
+ status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
+ &key_found, NULL);
+ if (status == 0)
+ return -16;
+
+ status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
+ &key_found, NULL);
+ if (status != 0)
+ return -17;
+
+ status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
+ &key_found, NULL);
+ if (status != -ENOENT)
+ return -18;
+
+ /* Traffic flow */
+ entry = 'A';
+ status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
+ &entry, &key_found,
+ &entry_ptr);
+ if (status < 0)
+ return -19;
+
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ if (i % 2 == 0) {
+ expected_mask |= (uint64_t)1 << i;
+ PREPARE_PACKET(mbufs[i], 0xadadadad);
+ } else
+ PREPARE_PACKET(mbufs[i], 0xadadadab);
+
+ rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
+ &result_mask, (void **)entries);
+ if (result_mask != expected_mask)
+ return -20;
+
+ /* Free resources */
+ for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
+ rte_pktmbuf_free(mbufs[i]);
+
+ status = rte_table_hash_cuckoo_ops.f_free(table);
+
+ return 0;
+}
diff --git a/src/spdk/dpdk/app/test/test_table_tables.h b/src/spdk/dpdk/app/test/test_table_tables.h
new file mode 100644
index 000000000..7570e9963
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_table_tables.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
+ */
+
+/* Test prototypes */
+int test_table_hash_cuckoo(void);
+int test_table_lpm(void);
+int test_table_lpm_ipv6(void);
+int test_table_array(void);
+#ifdef RTE_LIBRTE_ACL
+int test_table_acl(void);
+#endif
+int test_table_hash_unoptimized(void);
+int test_table_hash_lru(void);
+int test_table_hash_ext(void);
+int test_table_stub(void);
+
+/* Extern variables */
+typedef int (*table_test)(void);
+
+extern table_test table_tests[];
+extern unsigned n_table_tests;
diff --git a/src/spdk/dpdk/app/test/test_tailq.c b/src/spdk/dpdk/app/test/test_tailq.c
new file mode 100644
index 000000000..9520219b0
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_tailq.c
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_eal.h>
+#include <rte_string_fns.h>
+#include <rte_tailq.h>
+
+#include "test.h"
+
+#define do_return(...) do { \
+ printf("Error at %s, line %d: ", __func__, __LINE__); \
+ printf(__VA_ARGS__); \
+ return 1; \
+} while (0)
+
+static struct rte_tailq_elem rte_dummy_tailq = {
+ .name = "dummy",
+};
+EAL_REGISTER_TAILQ(rte_dummy_tailq)
+
+static struct rte_tailq_elem rte_dummy_dyn_tailq = {
+ .name = "dummy_dyn",
+};
+static struct rte_tailq_elem rte_dummy_dyn2_tailq = {
+ .name = "dummy_dyn",
+};
+
+static struct rte_tailq_entry d_elem;
+static struct rte_tailq_entry d_dyn_elem;
+
+static int
+test_tailq_early(void)
+{
+ struct rte_tailq_entry_head *d_head;
+
+ d_head = RTE_TAILQ_CAST(rte_dummy_tailq.head, rte_tailq_entry_head);
+ if (d_head == NULL)
+ do_return("Error %s has not been initialised\n",
+ rte_dummy_tailq.name);
+
+ /* check we can add an item to it */
+ TAILQ_INSERT_TAIL(d_head, &d_elem, next);
+
+ return 0;
+}
+
+static int
+test_tailq_create(void)
+{
+ struct rte_tailq_entry_head *d_head;
+
+ /* create a tailq and check its non-null (since we are post-eal init) */
+ if ((rte_eal_tailq_register(&rte_dummy_dyn_tailq) < 0) ||
+ (rte_dummy_dyn_tailq.head == NULL))
+ do_return("Error allocating %s\n", rte_dummy_dyn_tailq.name);
+
+ d_head = RTE_TAILQ_CAST(rte_dummy_dyn_tailq.head, rte_tailq_entry_head);
+
+ /* check we can add an item to it */
+ TAILQ_INSERT_TAIL(d_head, &d_dyn_elem, next);
+
+ if (strcmp(rte_dummy_dyn2_tailq.name, rte_dummy_dyn_tailq.name))
+ do_return("Error, something is wrong in the tailq test\n");
+
+ /* try allocating again, and check for failure */
+ if (!rte_eal_tailq_register(&rte_dummy_dyn2_tailq))
+ do_return("Error, registering the same tailq %s did not fail\n",
+ rte_dummy_dyn2_tailq.name);
+
+ return 0;
+}
+
+static int
+test_tailq_lookup(void)
+{
+ /* run successful test - check result is found */
+ struct rte_tailq_entry_head *d_head;
+ struct rte_tailq_entry *d_ptr;
+
+ d_head = RTE_TAILQ_LOOKUP(rte_dummy_tailq.name, rte_tailq_entry_head);
+ /* rte_dummy_tailq has been registered by EAL_REGISTER_TAILQ */
+ if (d_head == NULL ||
+ d_head != RTE_TAILQ_CAST(rte_dummy_tailq.head, rte_tailq_entry_head))
+ do_return("Error with tailq lookup\n");
+
+ TAILQ_FOREACH(d_ptr, d_head, next)
+ if (d_ptr != &d_elem)
+ do_return("Error with tailq returned from lookup - "
+ "expected element not found\n");
+
+ d_head = RTE_TAILQ_LOOKUP(rte_dummy_dyn_tailq.name, rte_tailq_entry_head);
+ /* rte_dummy_dyn_tailq has been registered by test_tailq_create */
+ if (d_head == NULL ||
+ d_head != RTE_TAILQ_CAST(rte_dummy_dyn_tailq.head, rte_tailq_entry_head))
+ do_return("Error with tailq lookup\n");
+
+ TAILQ_FOREACH(d_ptr, d_head, next)
+ if (d_ptr != &d_dyn_elem)
+ do_return("Error with tailq returned from lookup - "
+ "expected element not found\n");
+
+ /* now try a bad/error lookup */
+ d_head = RTE_TAILQ_LOOKUP("coucou", rte_tailq_entry_head);
+ if (d_head != NULL)
+ do_return("Error, lookup does not return NULL for bad tailq name\n");
+
+ return 0;
+}
+
+static int
+test_tailq(void)
+{
+ int ret = 0;
+ ret |= test_tailq_early();
+ ret |= test_tailq_create();
+ ret |= test_tailq_lookup();
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(tailq_autotest, test_tailq);
diff --git a/src/spdk/dpdk/app/test/test_telemetry_json.c b/src/spdk/dpdk/app/test/test_telemetry_json.c
new file mode 100644
index 000000000..90bbb3e8d
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_telemetry_json.c
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2020 Intel Corporation
+ */
+
+#include <string.h>
+
+#include "../../lib/librte_telemetry/telemetry_json.h"
+#include "test.h"
+
+static int
+test_basic_array(void)
+{
+ const char *expected = "[\"meaning of life\",42]";
+ char buf[1024];
+ int used = 0;
+
+ printf("%s: ", __func__);
+ used = rte_tel_json_empty_array(buf, sizeof(buf), used);
+ if (used != 2 || strcmp(buf, "[]"))
+ return -1;
+
+ used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
+ "meaning of life");
+ used = rte_tel_json_add_array_int(buf, sizeof(buf), used, 42);
+
+ printf("buf = '%s', expected = '%s'\n", buf, expected);
+ if (used != (int)strlen(expected))
+ return -1;
+ return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_basic_obj(void)
+{
+ const char *expected = "{\"weddings\":4,\"funerals\":1}";
+ char buf[1024];
+ int used = 0;
+
+ used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+ "weddings", 4);
+ used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+ "funerals", 1);
+
+ printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+ if (used != (int)strlen(expected))
+ return -1;
+ return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_overflow_array(void)
+{
+ static const char * const strs[] = {"Arsenal", "Chelsea", "Liverpool",
+ "Spurs"};
+ const char *expected = "[\"Arsenal\",\"Chelsea\"]";
+ char buf[25];
+ int i, used = 0;
+
+ for (i = 0; i < (int)RTE_DIM(strs); i++)
+ used = rte_tel_json_add_array_string(buf, sizeof(buf), used,
+ strs[i]);
+
+ printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+ if (buf[used - 1] != ']')
+ return -1;
+ if (used != (int)strlen(expected))
+ return -1;
+ return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_overflow_obj(void)
+{
+ static const char * const names[] = {"Italy", "Wales", "Scotland",
+ "Ireland", "England", "France"};
+ const int vals[RTE_DIM(names)] = {20, 61, 10, 40, 55, 35};
+ const char *expected = "{\"Italy\":20,\"Wales\":61}";
+ char buf[25];
+ int i, used = 0;
+
+ for (i = 0; i < (int)RTE_DIM(names); i++)
+ used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used,
+ names[i], vals[i]);
+
+ printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+ if (buf[used - 1] != '}')
+ return -1;
+ if (used != (int)strlen(expected))
+ return -1;
+ return strncmp(expected, buf, sizeof(buf));
+}
+
+static int
+test_large_array_element(void)
+{
+ static const char str[] = "A really long string to overflow buffer";
+ /* buffer should be unmodified so initial value and expected are same */
+ const char *expected = "ABC";
+ char buf[sizeof(str) - 5] = "ABC";
+ int used = 0;
+
+ used = rte_tel_json_add_array_string(buf, sizeof(buf), used, str);
+ printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+
+ return strlen(buf) != 0;
+}
+
+static int
+test_large_obj_element(void)
+{
+ static const char str[] = "A really long string to overflow buffer";
+ /* buffer should be unmodified so initial value and expected are same */
+ const char *expected = "XYZ";
+ char buf[sizeof(str) - 5] = "XYZ";
+ int used = 0;
+
+ used = rte_tel_json_add_obj_u64(buf, sizeof(buf), used, str, 0);
+ printf("%s: buf = '%s', expected = '%s'\n", __func__, buf, expected);
+
+ return strlen(buf) != 0;
+}
+
+static int
+test_telemetry_json(void)
+{
+ if (test_basic_array() < 0 ||
+ test_basic_obj() < 0 ||
+ test_overflow_array() < 0 ||
+ test_overflow_obj() < 0 ||
+ test_large_array_element() < 0 ||
++ test_large_obj_element() < 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(telemetry_json_autotest, test_telemetry_json);
diff --git a/src/spdk/dpdk/app/test/test_thash.c b/src/spdk/dpdk/app/test/test_thash.c
new file mode 100644
index 000000000..a6aadd1ef
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_thash.c
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2019 Vladimir Medvedkin <medvedkinv@gmail.com>
+ */
+
+#include <rte_common.h>
+#include <rte_eal.h>
+#include <rte_ip.h>
+
+#include "test.h"
+
+#include <rte_thash.h>
+
+struct test_thash_v4 {
+ uint32_t dst_ip;
+ uint32_t src_ip;
+ uint16_t dst_port;
+ uint16_t src_port;
+ uint32_t hash_l3;
+ uint32_t hash_l3l4;
+};
+
+struct test_thash_v6 {
+ uint8_t dst_ip[16];
+ uint8_t src_ip[16];
+ uint16_t dst_port;
+ uint16_t src_port;
+ uint32_t hash_l3;
+ uint32_t hash_l3l4;
+};
+
+/*From 82599 Datasheet 7.1.2.8.3 RSS Verification Suite*/
+struct test_thash_v4 v4_tbl[] = {
+{RTE_IPV4(161, 142, 100, 80), RTE_IPV4(66, 9, 149, 187),
+ 1766, 2794, 0x323e8fc2, 0x51ccc178},
+{RTE_IPV4(65, 69, 140, 83), RTE_IPV4(199, 92, 111, 2),
+ 4739, 14230, 0xd718262a, 0xc626b0ea},
+{RTE_IPV4(12, 22, 207, 184), RTE_IPV4(24, 19, 198, 95),
+ 38024, 12898, 0xd2d0a5de, 0x5c2b394a},
+{RTE_IPV4(209, 142, 163, 6), RTE_IPV4(38, 27, 205, 30),
+ 2217, 48228, 0x82989176, 0xafc7327f},
+{RTE_IPV4(202, 188, 127, 2), RTE_IPV4(153, 39, 163, 191),
+ 1303, 44251, 0x5d1809c5, 0x10e828a2},
+};
+
+struct test_thash_v6 v6_tbl[] = {
+/*3ffe:2501:200:3::1*/
+{{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x00, 0x03,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:2501:200:1fff::7*/
+{0x3f, 0xfe, 0x25, 0x01, 0x02, 0x00, 0x1f, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,},
+1766, 2794, 0x2cc18cd5, 0x40207d3d},
+/*ff02::1*/
+{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,},
+/*3ffe:501:8::260:97ff:fe40:efab*/
+{0x3f, 0xfe, 0x05, 0x01, 0x00, 0x08, 0x00, 0x00,
+0x02, 0x60, 0x97, 0xff, 0xfe, 0x40, 0xef, 0xab,},
+4739, 14230, 0x0f0c461c, 0xdde51bbf},
+/*fe80::200:f8ff:fe21:67cf*/
+{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+/*3ffe:1900:4545:3:200:f8ff:fe21:67cf*/
+{0x3f, 0xfe, 0x19, 0x00, 0x45, 0x45, 0x00, 0x03,
+0x02, 0x00, 0xf8, 0xff, 0xfe, 0x21, 0x67, 0xcf,},
+38024, 44251, 0x4b61e985, 0x02d1feef},
+};
+
+uint8_t default_rss_key[] = {
+0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,
+};
+
+static int
+test_thash(void)
+{
+ uint32_t i, j;
+ union rte_thash_tuple tuple;
+ uint32_t rss_l3, rss_l3l4;
+ uint8_t rss_key_be[RTE_DIM(default_rss_key)];
+ struct rte_ipv6_hdr ipv6_hdr;
+
+ /* Convert RSS key*/
+ rte_convert_rss_key((uint32_t *)&default_rss_key,
+ (uint32_t *)rss_key_be, RTE_DIM(default_rss_key));
+
+
+ for (i = 0; i < RTE_DIM(v4_tbl); i++) {
+ tuple.v4.src_addr = v4_tbl[i].src_ip;
+ tuple.v4.dst_addr = v4_tbl[i].dst_ip;
+ tuple.v4.sport = v4_tbl[i].src_port;
+ tuple.v4.dport = v4_tbl[i].dst_port;
+ /*Calculate hash with original key*/
+ rss_l3 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V4_L3_LEN, default_rss_key);
+ rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V4_L4_LEN, default_rss_key);
+ if ((rss_l3 != v4_tbl[i].hash_l3) ||
+ (rss_l3l4 != v4_tbl[i].hash_l3l4))
+ return -1;
+ /*Calculate hash with converted key*/
+ rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+ RTE_THASH_V4_L3_LEN, rss_key_be);
+ rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+ RTE_THASH_V4_L4_LEN, rss_key_be);
+ if ((rss_l3 != v4_tbl[i].hash_l3) ||
+ (rss_l3l4 != v4_tbl[i].hash_l3l4))
+ return -1;
+ }
+ for (i = 0; i < RTE_DIM(v6_tbl); i++) {
+ /*Fill ipv6 hdr*/
+ for (j = 0; j < RTE_DIM(ipv6_hdr.src_addr); j++)
+ ipv6_hdr.src_addr[j] = v6_tbl[i].src_ip[j];
+ for (j = 0; j < RTE_DIM(ipv6_hdr.dst_addr); j++)
+ ipv6_hdr.dst_addr[j] = v6_tbl[i].dst_ip[j];
+ /*Load and convert ipv6 address into tuple*/
+ rte_thash_load_v6_addrs(&ipv6_hdr, &tuple);
+ tuple.v6.sport = v6_tbl[i].src_port;
+ tuple.v6.dport = v6_tbl[i].dst_port;
+ /*Calculate hash with original key*/
+ rss_l3 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V6_L3_LEN, default_rss_key);
+ rss_l3l4 = rte_softrss((uint32_t *)&tuple,
+ RTE_THASH_V6_L4_LEN, default_rss_key);
+ if ((rss_l3 != v6_tbl[i].hash_l3) ||
+ (rss_l3l4 != v6_tbl[i].hash_l3l4))
+ return -1;
+ /*Calculate hash with converted key*/
+ rss_l3 = rte_softrss_be((uint32_t *)&tuple,
+ RTE_THASH_V6_L3_LEN, rss_key_be);
+ rss_l3l4 = rte_softrss_be((uint32_t *)&tuple,
+ RTE_THASH_V6_L4_LEN, rss_key_be);
+ if ((rss_l3 != v6_tbl[i].hash_l3) ||
+ (rss_l3l4 != v6_tbl[i].hash_l3l4))
+ return -1;
+ }
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(thash_autotest, test_thash);
diff --git a/src/spdk/dpdk/app/test/test_ticketlock.c b/src/spdk/dpdk/app/test/test_ticketlock.c
new file mode 100644
index 000000000..66ab3d1a0
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_ticketlock.c
@@ -0,0 +1,319 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2019 Arm Limited
+ */
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <unistd.h>
+
+#include <rte_atomic.h>
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_memory.h>
+#include <rte_per_lcore.h>
+#include <rte_ticketlock.h>
+
+#include "test.h"
+
+/*
+ * Ticketlock test
+ * =============
+ *
+ * - There is a global ticketlock and a table of ticketlocks (one per lcore).
+ *
+ * - The test function takes all of these locks and launches the
+ * ``test_ticketlock_per_core()`` function on each core (except the master).
+ *
+ * - The function takes the global lock, display something, then releases
+ * the global lock.
+ * - The function takes the per-lcore lock, display something, then releases
+ * the per-core lock.
+ *
+ * - The main function unlocks the per-lcore locks sequentially and
+ * waits between each lock. This triggers the display of a message
+ * for each core, in the correct order. The autotest script checks that
+ * this order is correct.
+ *
+ * - A load test is carried out, with all cores attempting to lock a single lock
+ * multiple times
+ */
+
+static rte_ticketlock_t tl, tl_try;
+static rte_ticketlock_t tl_tab[RTE_MAX_LCORE];
+static rte_ticketlock_recursive_t tlr;
+static unsigned int count;
+
+static rte_atomic32_t synchro;
+
+static int
+test_ticketlock_per_core(__rte_unused void *arg)
+{
+ rte_ticketlock_lock(&tl);
+ printf("Global lock taken on core %u\n", rte_lcore_id());
+ rte_ticketlock_unlock(&tl);
+
+ rte_ticketlock_lock(&tl_tab[rte_lcore_id()]);
+ printf("Hello from core %u !\n", rte_lcore_id());
+ rte_ticketlock_unlock(&tl_tab[rte_lcore_id()]);
+
+ return 0;
+}
+
+static int
+test_ticketlock_recursive_per_core(__rte_unused void *arg)
+{
+ unsigned int id = rte_lcore_id();
+
+ rte_ticketlock_recursive_lock(&tlr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, tlr.count);
+ rte_ticketlock_recursive_lock(&tlr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, tlr.count);
+ rte_ticketlock_recursive_lock(&tlr);
+ printf("Global recursive lock taken on core %u - count = %d\n",
+ id, tlr.count);
+
+ printf("Hello from within recursive locks from core %u !\n", id);
+
+ rte_ticketlock_recursive_unlock(&tlr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, tlr.count);
+ rte_ticketlock_recursive_unlock(&tlr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, tlr.count);
+ rte_ticketlock_recursive_unlock(&tlr);
+ printf("Global recursive lock released on core %u - count = %d\n",
+ id, tlr.count);
+
+ return 0;
+}
+
+static rte_ticketlock_t lk = RTE_TICKETLOCK_INITIALIZER;
+static uint64_t lcount __rte_cache_aligned;
+static uint64_t lcore_count[RTE_MAX_LCORE] __rte_cache_aligned;
+static uint64_t time_cost[RTE_MAX_LCORE];
+
+#define MAX_LOOP 10000
+
+static int
+load_loop_fn(void *func_param)
+{
+ uint64_t time_diff = 0, begin;
+ uint64_t hz = rte_get_timer_hz();
+ const int use_lock = *(int *)func_param;
+ const unsigned int lcore = rte_lcore_id();
+
+ /* wait synchro for slaves */
+ if (lcore != rte_get_master_lcore())
+ while (rte_atomic32_read(&synchro) == 0)
+ ;
+
+ begin = rte_rdtsc_precise();
+ while (lcore_count[lcore] < MAX_LOOP) {
+ if (use_lock)
+ rte_ticketlock_lock(&lk);
+ lcore_count[lcore]++;
+ lcount++;
+ if (use_lock)
+ rte_ticketlock_unlock(&lk);
+ }
+ time_diff = rte_rdtsc_precise() - begin;
+ time_cost[lcore] = time_diff * 1000000 / hz;
+ return 0;
+}
+
+static int
+test_ticketlock_perf(void)
+{
+ unsigned int i;
+ uint64_t tcount = 0;
+ uint64_t total_time = 0;
+ int lock = 0;
+ const unsigned int lcore = rte_lcore_id();
+
+ printf("\nTest with no lock on single core...\n");
+ load_loop_fn(&lock);
+ printf("Core [%u] cost time = %"PRIu64" us\n", lcore, time_cost[lcore]);
+ memset(lcore_count, 0, sizeof(lcore_count));
+ memset(time_cost, 0, sizeof(time_cost));
+
+ printf("\nTest with lock on single core...\n");
+ lock = 1;
+ load_loop_fn(&lock);
+ printf("Core [%u] cost time = %"PRIu64" us\n", lcore, time_cost[lcore]);
+ memset(lcore_count, 0, sizeof(lcore_count));
+ memset(time_cost, 0, sizeof(time_cost));
+
+ lcount = 0;
+ printf("\nTest with lock on %u cores...\n", rte_lcore_count());
+
+ /* Clear synchro and start slaves */
+ rte_atomic32_set(&synchro, 0);
+ rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER);
+
+ /* start synchro and launch test on master */
+ rte_atomic32_set(&synchro, 1);
+ load_loop_fn(&lock);
+
+ rte_eal_mp_wait_lcore();
+
+ RTE_LCORE_FOREACH(i) {
+ printf("Core [%u] cost time = %"PRIu64" us\n", i, time_cost[i]);
+ tcount += lcore_count[i];
+ total_time += time_cost[i];
+ }
+
+ if (tcount != lcount)
+ return -1;
+
+ printf("Total cost time = %"PRIu64" us\n", total_time);
+
+ return 0;
+}
+
+/*
+ * Use rte_ticketlock_trylock() to trylock a ticketlock object,
+ * If it could not lock the object successfully, it would
+ * return immediately and the variable of "count" would be
+ * increased by one per times. the value of "count" could be
+ * checked as the result later.
+ */
+static int
+test_ticketlock_try(__rte_unused void *arg)
+{
+ if (rte_ticketlock_trylock(&tl_try) == 0) {
+ rte_ticketlock_lock(&tl);
+ count++;
+ rte_ticketlock_unlock(&tl);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Test rte_eal_get_lcore_state() in addition to ticketlocks
+ * as we have "waiting" then "running" lcores.
+ */
+static int
+test_ticketlock(void)
+{
+ int ret = 0;
+ int i;
+
+ /* slave cores should be waiting: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+
+ rte_ticketlock_init(&tl);
+ rte_ticketlock_init(&tl_try);
+ rte_ticketlock_recursive_init(&tlr);
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_ticketlock_init(&tl_tab[i]);
+ }
+
+ rte_ticketlock_lock(&tl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_ticketlock_lock(&tl_tab[i]);
+ rte_eal_remote_launch(test_ticketlock_per_core, NULL, i);
+ }
+
+ /* slave cores should be busy: print it */
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ printf("lcore %d state: %d\n", i,
+ (int) rte_eal_get_lcore_state(i));
+ }
+ rte_ticketlock_unlock(&tl);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_ticketlock_unlock(&tl_tab[i]);
+ rte_delay_ms(10);
+ }
+
+ rte_eal_mp_wait_lcore();
+
+ rte_ticketlock_recursive_lock(&tlr);
+
+ /*
+ * Try to acquire a lock that we already own
+ */
+ if (!rte_ticketlock_recursive_trylock(&tlr)) {
+ printf("rte_ticketlock_recursive_trylock failed on a lock that "
+ "we already own\n");
+ ret = -1;
+ } else
+ rte_ticketlock_recursive_unlock(&tlr);
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_ticketlock_recursive_per_core,
+ NULL, i);
+ }
+ rte_ticketlock_recursive_unlock(&tlr);
+ rte_eal_mp_wait_lcore();
+
+ /*
+ * Test if it could return immediately from try-locking a locked object.
+ * Here it will lock the ticketlock object first, then launch all the
+ * slave lcores to trylock the same ticketlock object.
+ * All the slave lcores should give up try-locking a locked object and
+ * return immediately, and then increase the "count" initialized with
+ * zero by one per times.
+ * We can check if the "count" is finally equal to the number of all
+ * slave lcores to see if the behavior of try-locking a locked
+ * ticketlock object is correct.
+ */
+ if (rte_ticketlock_trylock(&tl_try) == 0)
+ return -1;
+
+ count = 0;
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_eal_remote_launch(test_ticketlock_try, NULL, i);
+ }
+ rte_eal_mp_wait_lcore();
+ rte_ticketlock_unlock(&tl_try);
+ if (rte_ticketlock_is_locked(&tl)) {
+ printf("ticketlock is locked but it should not be\n");
+ return -1;
+ }
+ rte_ticketlock_lock(&tl);
+ if (count != (rte_lcore_count() - 1))
+ ret = -1;
+
+ rte_ticketlock_unlock(&tl);
+
+ /*
+ * Test if it can trylock recursively.
+ * Use rte_ticketlock_recursive_trylock() to check if it can lock
+ * a ticketlock object recursively. Here it will try to lock a
+ * ticketlock object twice.
+ */
+ if (rte_ticketlock_recursive_trylock(&tlr) == 0) {
+ printf("It failed to do the first ticketlock_recursive_trylock "
+ "but it should able to do\n");
+ return -1;
+ }
+ if (rte_ticketlock_recursive_trylock(&tlr) == 0) {
+ printf("It failed to do the second ticketlock_recursive_trylock "
+ "but it should able to do\n");
+ return -1;
+ }
+ rte_ticketlock_recursive_unlock(&tlr);
+ rte_ticketlock_recursive_unlock(&tlr);
+
+ if (test_ticketlock_perf() < 0)
+ return -1;
+
+ return ret;
+}
+
+REGISTER_TEST_COMMAND(ticketlock_autotest, test_ticketlock);
diff --git a/src/spdk/dpdk/app/test/test_timer.c b/src/spdk/dpdk/app/test/test_timer.c
new file mode 100644
index 000000000..5933f56ed
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_timer.c
@@ -0,0 +1,600 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include "test.h"
+
+/*
+ * Timer
+ * =====
+ *
+ * #. Stress test 1.
+ *
+ * The objective of the timer stress tests is to check that there are no
+ * race conditions in list and status management. This test launches,
+ * resets and stops the timer very often on many cores at the same
+ * time.
+ *
+ * - Only one timer is used for this test.
+ * - On each core, the rte_timer_manage() function is called from the main
+ * loop every 3 microseconds.
+ * - In the main loop, the timer may be reset (randomly, with a
+ * probability of 0.5 %) 100 microseconds later on a random core, or
+ * stopped (with a probability of 0.5 % also).
+ * - In callback, the timer is can be reset (randomly, with a
+ * probability of 0.5 %) 100 microseconds later on the same core or
+ * on another core (same probability), or stopped (same
+ * probability).
+ *
+ * # Stress test 2.
+ *
+ * The objective of this test is similar to the first in that it attempts
+ * to find if there are any race conditions in the timer library. However,
+ * it is less complex in terms of operations performed and duration, as it
+ * is designed to have a predictable outcome that can be tested.
+ *
+ * - A set of timers is initialized for use by the test
+ * - All cores then simultaneously are set to schedule all the timers at
+ * the same time, so conflicts should occur.
+ * - Then there is a delay while we wait for the timers to expire
+ * - Then the master lcore calls timer_manage() and we check that all
+ * timers have had their callbacks called exactly once - no more no less.
+ * - Then we repeat the process, except after setting up the timers, we have
+ * all cores randomly reschedule them.
+ * - Again we check that the expected number of callbacks has occurred when
+ * we call timer-manage.
+ *
+ * #. Basic test.
+ *
+ * This test performs basic functional checks of the timers. The test
+ * uses four different timers that are loaded and stopped under
+ * specific conditions in specific contexts.
+ *
+ * - Four timers are used for this test.
+ * - On each core, the rte_timer_manage() function is called from main loop
+ * every 3 microseconds.
+ *
+ * The autotest python script checks that the behavior is correct:
+ *
+ * - timer0
+ *
+ * - At initialization, timer0 is loaded by the master core, on master core
+ * in "single" mode (time = 1 second).
+ * - In the first 19 callbacks, timer0 is reloaded on the same core,
+ * then, it is explicitly stopped at the 20th call.
+ * - At t=25s, timer0 is reloaded once by timer2.
+ *
+ * - timer1
+ *
+ * - At initialization, timer1 is loaded by the master core, on the
+ * master core in "single" mode (time = 2 seconds).
+ * - In the first 9 callbacks, timer1 is reloaded on another
+ * core. After the 10th callback, timer1 is not reloaded anymore.
+ *
+ * - timer2
+ *
+ * - At initialization, timer2 is loaded by the master core, on the
+ * master core in "periodical" mode (time = 1 second).
+ * - In the callback, when t=25s, it stops timer3 and reloads timer0
+ * on the current core.
+ *
+ * - timer3
+ *
+ * - At initialization, timer3 is loaded by the master core, on
+ * another core in "periodical" mode (time = 1 second).
+ * - It is stopped at t=25s by timer2.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+#include <math.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_timer.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+#include <rte_pause.h>
+
+#define TEST_DURATION_S 1 /* in seconds */
+#define NB_TIMER 4
+
+#define RTE_LOGTYPE_TESTTIMER RTE_LOGTYPE_USER3
+
+static volatile uint64_t end_time;
+static volatile int test_failed;
+
+struct mytimerinfo {
+ struct rte_timer tim;
+ unsigned id;
+ unsigned count;
+};
+
+static struct mytimerinfo mytiminfo[NB_TIMER];
+
+static void timer_basic_cb(struct rte_timer *tim, void *arg);
+
+static void
+mytimer_reset(struct mytimerinfo *timinfo, uint64_t ticks,
+ enum rte_timer_type type, unsigned tim_lcore,
+ rte_timer_cb_t fct)
+{
+ rte_timer_reset_sync(&timinfo->tim, ticks, type, tim_lcore,
+ fct, timinfo);
+}
+
+/* timer callback for stress tests */
+static void
+timer_stress_cb(__rte_unused struct rte_timer *tim,
+ __rte_unused void *arg)
+{
+ long r;
+ unsigned lcore_id = rte_lcore_id();
+ uint64_t hz = rte_get_timer_hz();
+
+ if (rte_timer_pending(tim))
+ return;
+
+ r = rte_rand();
+ if ((r & 0xff) == 0) {
+ mytimer_reset(&mytiminfo[0], hz, SINGLE, lcore_id,
+ timer_stress_cb);
+ }
+ else if ((r & 0xff) == 1) {
+ mytimer_reset(&mytiminfo[0], hz, SINGLE,
+ rte_get_next_lcore(lcore_id, 0, 1),
+ timer_stress_cb);
+ }
+ else if ((r & 0xff) == 2) {
+ rte_timer_stop(&mytiminfo[0].tim);
+ }
+}
+
+static int
+timer_stress_main_loop(__rte_unused void *arg)
+{
+ uint64_t hz = rte_get_timer_hz();
+ unsigned lcore_id = rte_lcore_id();
+ uint64_t cur_time;
+ int64_t diff = 0;
+ long r;
+
+ while (diff >= 0) {
+
+ /* call the timer handler on each core */
+ rte_timer_manage();
+
+ /* simulate the processing of a packet
+ * (1 us = 2000 cycles at 2 Ghz) */
+ rte_delay_us(1);
+
+ /* randomly stop or reset timer */
+ r = rte_rand();
+ lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
+ if ((r & 0xff) == 0) {
+ /* 100 us */
+ mytimer_reset(&mytiminfo[0], hz/10000, SINGLE, lcore_id,
+ timer_stress_cb);
+ }
+ else if ((r & 0xff) == 1) {
+ rte_timer_stop_sync(&mytiminfo[0].tim);
+ }
+ cur_time = rte_get_timer_cycles();
+ diff = end_time - cur_time;
+ }
+
+ lcore_id = rte_lcore_id();
+ RTE_LOG(INFO, TESTTIMER, "core %u finished\n", lcore_id);
+
+ return 0;
+}
+
+/* Need to synchronize slave lcores through multiple steps. */
+enum { SLAVE_WAITING = 1, SLAVE_RUN_SIGNAL, SLAVE_RUNNING, SLAVE_FINISHED };
+static rte_atomic16_t slave_state[RTE_MAX_LCORE];
+
+static void
+master_init_slaves(void)
+{
+ unsigned i;
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_atomic16_set(&slave_state[i], SLAVE_WAITING);
+ }
+}
+
+static void
+master_start_slaves(void)
+{
+ unsigned i;
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ rte_atomic16_set(&slave_state[i], SLAVE_RUN_SIGNAL);
+ }
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ while (rte_atomic16_read(&slave_state[i]) != SLAVE_RUNNING)
+ rte_pause();
+ }
+}
+
+static void
+master_wait_for_slaves(void)
+{
+ unsigned i;
+
+ RTE_LCORE_FOREACH_SLAVE(i) {
+ while (rte_atomic16_read(&slave_state[i]) != SLAVE_FINISHED)
+ rte_pause();
+ }
+}
+
+static void
+slave_wait_to_start(void)
+{
+ unsigned lcore_id = rte_lcore_id();
+
+ while (rte_atomic16_read(&slave_state[lcore_id]) != SLAVE_RUN_SIGNAL)
+ rte_pause();
+ rte_atomic16_set(&slave_state[lcore_id], SLAVE_RUNNING);
+}
+
+static void
+slave_finish(void)
+{
+ unsigned lcore_id = rte_lcore_id();
+
+ rte_atomic16_set(&slave_state[lcore_id], SLAVE_FINISHED);
+}
+
+
+static volatile int cb_count = 0;
+
+/* callback for second stress test. will only be called
+ * on master lcore */
+static void
+timer_stress2_cb(struct rte_timer *tim __rte_unused, void *arg __rte_unused)
+{
+ cb_count++;
+}
+
+#define NB_STRESS2_TIMERS 8192
+
+static int
+timer_stress2_main_loop(__rte_unused void *arg)
+{
+ static struct rte_timer *timers;
+ int i, ret;
+ uint64_t delay = rte_get_timer_hz() / 20;
+ unsigned lcore_id = rte_lcore_id();
+ unsigned master = rte_get_master_lcore();
+ int32_t my_collisions = 0;
+ static rte_atomic32_t collisions;
+
+ if (lcore_id == master) {
+ cb_count = 0;
+ test_failed = 0;
+ rte_atomic32_set(&collisions, 0);
+ master_init_slaves();
+ timers = rte_malloc(NULL, sizeof(*timers) * NB_STRESS2_TIMERS, 0);
+ if (timers == NULL) {
+ printf("Test Failed\n");
+ printf("- Cannot allocate memory for timers\n" );
+ test_failed = 1;
+ master_start_slaves();
+ goto cleanup;
+ }
+ for (i = 0; i < NB_STRESS2_TIMERS; i++)
+ rte_timer_init(&timers[i]);
+ master_start_slaves();
+ } else {
+ slave_wait_to_start();
+ if (test_failed)
+ goto cleanup;
+ }
+
+ /* have all cores schedule all timers on master lcore */
+ for (i = 0; i < NB_STRESS2_TIMERS; i++) {
+ ret = rte_timer_reset(&timers[i], delay, SINGLE, master,
+ timer_stress2_cb, NULL);
+ /* there will be collisions when multiple cores simultaneously
+ * configure the same timers */
+ if (ret != 0)
+ my_collisions++;
+ }
+ if (my_collisions != 0)
+ rte_atomic32_add(&collisions, my_collisions);
+
+ /* wait long enough for timers to expire */
+ rte_delay_ms(100);
+
+ /* all cores rendezvous */
+ if (lcore_id == master) {
+ master_wait_for_slaves();
+ } else {
+ slave_finish();
+ }
+
+ /* now check that we get the right number of callbacks */
+ if (lcore_id == master) {
+ my_collisions = rte_atomic32_read(&collisions);
+ if (my_collisions != 0)
+ printf("- %d timer reset collisions (OK)\n", my_collisions);
+ rte_timer_manage();
+ if (cb_count != NB_STRESS2_TIMERS) {
+ printf("Test Failed\n");
+ printf("- Stress test 2, part 1 failed\n");
+ printf("- Expected %d callbacks, got %d\n", NB_STRESS2_TIMERS,
+ cb_count);
+ test_failed = 1;
+ master_start_slaves();
+ goto cleanup;
+ }
+ cb_count = 0;
+
+ /* proceed */
+ master_start_slaves();
+ } else {
+ /* proceed */
+ slave_wait_to_start();
+ if (test_failed)
+ goto cleanup;
+ }
+
+ /* now test again, just stop and restart timers at random after init*/
+ for (i = 0; i < NB_STRESS2_TIMERS; i++)
+ rte_timer_reset(&timers[i], delay, SINGLE, master,
+ timer_stress2_cb, NULL);
+
+ /* pick random timer to reset, stopping them first half the time */
+ for (i = 0; i < 100000; i++) {
+ int r = rand() % NB_STRESS2_TIMERS;
+ if (i % 2)
+ rte_timer_stop(&timers[r]);
+ rte_timer_reset(&timers[r], delay, SINGLE, master,
+ timer_stress2_cb, NULL);
+ }
+
+ /* wait long enough for timers to expire */
+ rte_delay_ms(100);
+
+ /* now check that we get the right number of callbacks */
+ if (lcore_id == master) {
+ master_wait_for_slaves();
+
+ rte_timer_manage();
+ if (cb_count != NB_STRESS2_TIMERS) {
+ printf("Test Failed\n");
+ printf("- Stress test 2, part 2 failed\n");
+ printf("- Expected %d callbacks, got %d\n", NB_STRESS2_TIMERS,
+ cb_count);
+ test_failed = 1;
+ } else {
+ printf("Test OK\n");
+ }
+ }
+
+cleanup:
+ if (lcore_id == master) {
+ master_wait_for_slaves();
+ if (timers != NULL) {
+ rte_free(timers);
+ timers = NULL;
+ }
+ } else {
+ slave_finish();
+ }
+
+ return 0;
+}
+
+/* timer callback for basic tests */
+static void
+timer_basic_cb(struct rte_timer *tim, void *arg)
+{
+ struct mytimerinfo *timinfo = arg;
+ uint64_t hz = rte_get_timer_hz();
+ unsigned lcore_id = rte_lcore_id();
+ uint64_t cur_time = rte_get_timer_cycles();
+
+ if (rte_timer_pending(tim))
+ return;
+
+ timinfo->count ++;
+
+ RTE_LOG(INFO, TESTTIMER,
+ "%"PRIu64": callback id=%u count=%u on core %u\n",
+ cur_time, timinfo->id, timinfo->count, lcore_id);
+
+ /* reload timer 0 on same core */
+ if (timinfo->id == 0 && timinfo->count < 20) {
+ mytimer_reset(timinfo, hz, SINGLE, lcore_id, timer_basic_cb);
+ return;
+ }
+
+ /* reload timer 1 on next core */
+ if (timinfo->id == 1 && timinfo->count < 10) {
+ mytimer_reset(timinfo, hz*2, SINGLE,
+ rte_get_next_lcore(lcore_id, 0, 1),
+ timer_basic_cb);
+ return;
+ }
+
+ /* Explicitelly stop timer 0. Once stop() called, we can even
+ * erase the content of the structure: it is not referenced
+ * anymore by any code (in case of dynamic structure, it can
+ * be freed) */
+ if (timinfo->id == 0 && timinfo->count == 20) {
+
+ /* stop_sync() is not needed, because we know that the
+ * status of timer is only modified by this core */
+ rte_timer_stop(tim);
+ memset(tim, 0xAA, sizeof(struct rte_timer));
+ return;
+ }
+
+ /* stop timer3, and restart a new timer0 (it was removed 5
+ * seconds ago) for a single shot */
+ if (timinfo->id == 2 && timinfo->count == 25) {
+ rte_timer_stop_sync(&mytiminfo[3].tim);
+
+ /* need to reinit because structure was erased with 0xAA */
+ rte_timer_init(&mytiminfo[0].tim);
+ mytimer_reset(&mytiminfo[0], hz, SINGLE, lcore_id,
+ timer_basic_cb);
+ }
+}
+
+static int
+timer_basic_main_loop(__rte_unused void *arg)
+{
+ uint64_t hz = rte_get_timer_hz();
+ unsigned lcore_id = rte_lcore_id();
+ uint64_t cur_time;
+ int64_t diff = 0;
+
+ /* launch all timers on core 0 */
+ if (lcore_id == rte_get_master_lcore()) {
+ mytimer_reset(&mytiminfo[0], hz/4, SINGLE, lcore_id,
+ timer_basic_cb);
+ mytimer_reset(&mytiminfo[1], hz/2, SINGLE, lcore_id,
+ timer_basic_cb);
+ mytimer_reset(&mytiminfo[2], hz/4, PERIODICAL, lcore_id,
+ timer_basic_cb);
+ mytimer_reset(&mytiminfo[3], hz/4, PERIODICAL,
+ rte_get_next_lcore(lcore_id, 0, 1),
+ timer_basic_cb);
+ }
+
+ while (diff >= 0) {
+
+ /* call the timer handler on each core */
+ rte_timer_manage();
+
+ /* simulate the processing of a packet
+ * (3 us = 6000 cycles at 2 Ghz) */
+ rte_delay_us(3);
+
+ cur_time = rte_get_timer_cycles();
+ diff = end_time - cur_time;
+ }
+ RTE_LOG(INFO, TESTTIMER, "core %u finished\n", lcore_id);
+
+ return 0;
+}
+
+static int
+timer_sanity_check(void)
+{
+#ifdef RTE_LIBEAL_USE_HPET
+ if (eal_timer_source != EAL_TIMER_HPET) {
+ printf("Not using HPET, can't sanity check timer sources\n");
+ return 0;
+ }
+
+ const uint64_t t_hz = rte_get_tsc_hz();
+ const uint64_t h_hz = rte_get_hpet_hz();
+ printf("Hertz values: TSC = %"PRIu64", HPET = %"PRIu64"\n", t_hz, h_hz);
+
+ const uint64_t tsc_start = rte_get_tsc_cycles();
+ const uint64_t hpet_start = rte_get_hpet_cycles();
+ rte_delay_ms(100); /* delay 1/10 second */
+ const uint64_t tsc_end = rte_get_tsc_cycles();
+ const uint64_t hpet_end = rte_get_hpet_cycles();
+ printf("Measured cycles: TSC = %"PRIu64", HPET = %"PRIu64"\n",
+ tsc_end-tsc_start, hpet_end-hpet_start);
+
+ const double tsc_time = (double)(tsc_end - tsc_start)/t_hz;
+ const double hpet_time = (double)(hpet_end - hpet_start)/h_hz;
+ /* get the percentage that the times differ by */
+ const double time_diff = fabs(tsc_time - hpet_time)*100/tsc_time;
+ printf("Measured time: TSC = %.4f, HPET = %.4f\n", tsc_time, hpet_time);
+
+ printf("Elapsed time measured by TSC and HPET differ by %f%%\n",
+ time_diff);
+ if (time_diff > 0.1) {
+ printf("Error times differ by >0.1%%");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+static int
+test_timer(void)
+{
+ unsigned i;
+ uint64_t cur_time;
+ uint64_t hz;
+
+ if (rte_lcore_count() < 2) {
+ printf("Not enough cores for timer_autotest, expecting at least 2\n");
+ return TEST_SKIPPED;
+ }
+
+ /* sanity check our timer sources and timer config values */
+ if (timer_sanity_check() < 0) {
+ printf("Timer sanity checks failed\n");
+ return TEST_FAILED;
+ }
+
+ /* init timer */
+ for (i=0; i<NB_TIMER; i++) {
+ memset(&mytiminfo[i], 0, sizeof(struct mytimerinfo));
+ mytiminfo[i].id = i;
+ rte_timer_init(&mytiminfo[i].tim);
+ }
+
+ /* calculate the "end of test" time */
+ cur_time = rte_get_timer_cycles();
+ hz = rte_get_timer_hz();
+ end_time = cur_time + (hz * TEST_DURATION_S);
+
+ /* start other cores */
+ printf("Start timer stress tests\n");
+ rte_eal_mp_remote_launch(timer_stress_main_loop, NULL, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ /* stop timer 0 used for stress test */
+ rte_timer_stop_sync(&mytiminfo[0].tim);
+
+ /* run a second, slightly different set of stress tests */
+ printf("\nStart timer stress tests 2\n");
+ test_failed = 0;
+ rte_eal_mp_remote_launch(timer_stress2_main_loop, NULL, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+ if (test_failed)
+ return TEST_FAILED;
+
+ /* calculate the "end of test" time */
+ cur_time = rte_get_timer_cycles();
+ hz = rte_get_timer_hz();
+ end_time = cur_time + (hz * TEST_DURATION_S);
+
+ /* start other cores */
+ printf("\nStart timer basic tests\n");
+ rte_eal_mp_remote_launch(timer_basic_main_loop, NULL, CALL_MASTER);
+ rte_eal_mp_wait_lcore();
+
+ /* stop all timers */
+ for (i=0; i<NB_TIMER; i++) {
+ rte_timer_stop_sync(&mytiminfo[i].tim);
+ }
+
+ rte_timer_dump_stats(stdout);
+
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(timer_autotest, test_timer);
diff --git a/src/spdk/dpdk/app/test/test_timer_perf.c b/src/spdk/dpdk/app/test/test_timer_perf.c
new file mode 100644
index 000000000..0ede4b3e4
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_timer_perf.c
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include "test.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <rte_cycles.h>
+#include <rte_timer.h>
+#include <rte_common.h>
+#include <rte_lcore.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+#include <rte_pause.h>
+
+#define MAX_ITERATIONS 1000000
+
+int outstanding_count = 0;
+
+static void
+timer_cb(struct rte_timer *t __rte_unused, void *param __rte_unused)
+{
+ outstanding_count--;
+}
+
+#define DELAY_SECONDS 1
+
+#ifdef RTE_EXEC_ENV_LINUX
+#define do_delay() usleep(10)
+#else
+#define do_delay() rte_pause()
+#endif
+
+static int
+test_timer_perf(void)
+{
+ unsigned iterations = 100;
+ unsigned i;
+ struct rte_timer *tms;
+ uint64_t start_tsc, end_tsc, delay_start;
+ unsigned lcore_id = rte_lcore_id();
+
+ tms = rte_malloc(NULL, sizeof(*tms) * MAX_ITERATIONS, 0);
+
+ for (i = 0; i < MAX_ITERATIONS; i++)
+ rte_timer_init(&tms[i]);
+
+ const uint64_t ticks = rte_get_timer_hz() * DELAY_SECONDS;
+ const uint64_t ticks_per_ms = rte_get_tsc_hz()/1000;
+ const uint64_t ticks_per_us = ticks_per_ms/1000;
+
+ while (iterations <= MAX_ITERATIONS) {
+
+ printf("Appending %u timers\n", iterations);
+ start_tsc = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_timer_reset(&tms[i], ticks, SINGLE, lcore_id,
+ timer_cb, NULL);
+ end_tsc = rte_rdtsc();
+ printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations,
+ end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms));
+ printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n",
+ (end_tsc-start_tsc)/iterations,
+ ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us));
+ outstanding_count = iterations;
+ delay_start = rte_get_timer_cycles();
+ while (rte_get_timer_cycles() < delay_start + ticks)
+ do_delay();
+
+ start_tsc = rte_rdtsc();
+ while (outstanding_count)
+ rte_timer_manage();
+ end_tsc = rte_rdtsc();
+ printf("Time for %u callbacks: %"PRIu64" (%"PRIu64"ms), ", iterations,
+ end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms));
+ printf("Time per callback: %"PRIu64" (%"PRIu64"us)\n",
+ (end_tsc-start_tsc)/iterations,
+ ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us));
+
+ printf("Resetting %u timers\n", iterations);
+ start_tsc = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_timer_reset(&tms[i], rte_rand() % ticks, SINGLE, lcore_id,
+ timer_cb, NULL);
+ end_tsc = rte_rdtsc();
+ printf("Time for %u timers: %"PRIu64" (%"PRIu64"ms), ", iterations,
+ end_tsc-start_tsc, (end_tsc-start_tsc+ticks_per_ms/2)/(ticks_per_ms));
+ printf("Time per timer: %"PRIu64" (%"PRIu64"us)\n",
+ (end_tsc-start_tsc)/iterations,
+ ((end_tsc-start_tsc)/iterations+ticks_per_us/2)/(ticks_per_us));
+ outstanding_count = iterations;
+
+ delay_start = rte_get_timer_cycles();
+ while (rte_get_timer_cycles() < delay_start + ticks)
+ do_delay();
+
+ rte_timer_manage();
+ if (outstanding_count != 0) {
+ printf("Error: outstanding callback count = %d\n", outstanding_count);
+ return -1;
+ }
+
+ iterations *= 10;
+ printf("\n");
+ }
+
+ printf("All timers processed ok\n");
+
+ /* measure time to poll an empty timer list */
+ start_tsc = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_timer_manage();
+ end_tsc = rte_rdtsc();
+ printf("\nTime per rte_timer_manage with zero timers: %"PRIu64" cycles\n",
+ (end_tsc - start_tsc + iterations/2) / iterations);
+
+ /* measure time to poll a timer list with timers, but without
+ * calling any callbacks */
+ rte_timer_reset(&tms[0], ticks * 100, SINGLE, lcore_id,
+ timer_cb, NULL);
+ start_tsc = rte_rdtsc();
+ for (i = 0; i < iterations; i++)
+ rte_timer_manage();
+ end_tsc = rte_rdtsc();
+ printf("Time per rte_timer_manage with zero callbacks: %"PRIu64" cycles\n",
+ (end_tsc - start_tsc + iterations/2) / iterations);
+
+ rte_free(tms);
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(timer_perf_autotest, test_timer_perf);
diff --git a/src/spdk/dpdk/app/test/test_timer_racecond.c b/src/spdk/dpdk/app/test/test_timer_racecond.c
new file mode 100644
index 000000000..4fc917995
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_timer_racecond.c
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Akamai Technologies.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <rte_cycles.h>
+#include <rte_timer.h>
+#include <rte_common.h>
+#include <rte_lcore.h>
+#include <rte_random.h>
+#include <rte_malloc.h>
+#include <rte_pause.h>
+
+#ifdef RTE_EXEC_ENV_LINUX
+#define usec_delay(us) usleep(us)
+#else
+#define usec_delay(us) rte_delay_us(us)
+#endif
+
+#define BILLION (1UL << 30)
+
+#define TEST_DURATION_S 4 /* in seconds */
+#define N_TIMERS 50
+
+static struct rte_timer timer[N_TIMERS];
+static unsigned timer_lcore_id[N_TIMERS];
+
+static unsigned master;
+static volatile unsigned stop_slaves;
+
+static int reload_timer(struct rte_timer *tim);
+
+int timer_logtype_test;
+
+RTE_INIT(test_timer_init_log)
+{
+ timer_logtype_test = rte_log_register("test.timer");
+}
+
+static void
+timer_cb(struct rte_timer *tim, void *arg __rte_unused)
+{
+ /* Simulate slow callback function, 100 us. */
+ rte_delay_us(100);
+ if (tim == &timer[0])
+ rte_log(RTE_LOG_DEBUG, timer_logtype_test,
+ "------------------------------------------------\n");
+ rte_log(RTE_LOG_DEBUG, timer_logtype_test, "%s: core %u timer %"
+ PRIuPTR "\n", __func__, rte_lcore_id(), tim - timer);
+ (void)reload_timer(tim);
+}
+
+RTE_DEFINE_PER_LCORE(unsigned, n_reset_collisions);
+
+static int
+reload_timer(struct rte_timer *tim)
+{
+ /* Make timer expire roughly when the TSC hits the next BILLION
+ * multiple. Add in timer's index to make them expire in nearly
+ * sorted order. This makes all timers somewhat synchronized,
+ * firing ~2-3 times per second, assuming 2-3 GHz TSCs.
+ */
+ uint64_t ticks = BILLION - (rte_get_timer_cycles() % BILLION) +
+ (tim - timer);
+ int ret;
+
+ ret = rte_timer_reset(tim, ticks, PERIODICAL, master, timer_cb, NULL);
+ if (ret != 0) {
+ rte_log(RTE_LOG_DEBUG, timer_logtype_test,
+ "- core %u failed to reset timer %" PRIuPTR " (OK)\n",
+ rte_lcore_id(), tim - timer);
+ RTE_PER_LCORE(n_reset_collisions) += 1;
+ }
+ return ret;
+}
+
+static int
+slave_main_loop(__rte_unused void *arg)
+{
+ unsigned lcore_id = rte_lcore_id();
+ unsigned i;
+
+ RTE_PER_LCORE(n_reset_collisions) = 0;
+
+ printf("Starting main loop on core %u\n", lcore_id);
+
+ while (!stop_slaves) {
+ /* Wait until the timer manager is running.
+ * We know it's running when we see timer[0] NOT pending.
+ */
+ if (rte_timer_pending(&timer[0])) {
+ rte_pause();
+ continue;
+ }
+
+ /* Now, go cause some havoc!
+ * Reload our timers.
+ */
+ for (i = 0; i < N_TIMERS; i++) {
+ if (timer_lcore_id[i] == lcore_id)
+ (void)reload_timer(&timer[i]);
+ }
+ usec_delay(100*1000); /* sleep 100 ms */
+ }
+
+ if (RTE_PER_LCORE(n_reset_collisions) != 0) {
+ printf("- core %u, %u reset collisions (OK)\n",
+ lcore_id, RTE_PER_LCORE(n_reset_collisions));
+ }
+ return 0;
+}
+
+static int
+test_timer_racecond(void)
+{
+ int ret;
+ uint64_t hz;
+ uint64_t cur_time;
+ uint64_t end_time;
+ int64_t diff = 0;
+ unsigned lcore_id;
+ unsigned i;
+
+ master = lcore_id = rte_lcore_id();
+ hz = rte_get_timer_hz();
+
+ /* init and start timers */
+ for (i = 0; i < N_TIMERS; i++) {
+ rte_timer_init(&timer[i]);
+ ret = reload_timer(&timer[i]);
+ TEST_ASSERT(ret == 0, "reload_timer failed");
+
+ /* Distribute timers to slaves.
+ * Note that we assign timer[0] to the master.
+ */
+ timer_lcore_id[i] = lcore_id;
+ lcore_id = rte_get_next_lcore(lcore_id, 1, 1);
+ }
+
+ /* calculate the "end of test" time */
+ cur_time = rte_get_timer_cycles();
+ end_time = cur_time + (hz * TEST_DURATION_S);
+
+ /* start slave cores */
+ stop_slaves = 0;
+ printf("Start timer manage race condition test (%u seconds)\n",
+ TEST_DURATION_S);
+ rte_eal_mp_remote_launch(slave_main_loop, NULL, SKIP_MASTER);
+
+ while (diff >= 0) {
+ /* run the timers */
+ rte_timer_manage();
+
+ /* wait 100 ms */
+ usec_delay(100*1000);
+
+ cur_time = rte_get_timer_cycles();
+ diff = end_time - cur_time;
+ }
+
+ /* stop slave cores */
+ printf("Stopping timer manage race condition test\n");
+ stop_slaves = 1;
+ rte_eal_mp_wait_lcore();
+
+ /* stop timers */
+ for (i = 0; i < N_TIMERS; i++) {
+ ret = rte_timer_stop(&timer[i]);
+ TEST_ASSERT(ret == 0, "rte_timer_stop failed");
+ }
+
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(timer_racecond_autotest, test_timer_racecond);
diff --git a/src/spdk/dpdk/app/test/test_timer_secondary.c b/src/spdk/dpdk/app/test/test_timer_secondary.c
new file mode 100644
index 000000000..7a3bc873b
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_timer_secondary.c
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2019 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <rte_eal.h>
+#include <rte_lcore.h>
+#include <rte_debug.h>
+#include <rte_memzone.h>
+#include <rte_atomic.h>
+#include <rte_timer.h>
+#include <rte_cycles.h>
+#include <rte_mempool.h>
+#include <rte_random.h>
+
+#include "test.h"
+#include "process.h"
+
+#define NUM_TIMERS (1 << 20) /* ~1M timers */
+#define NUM_LCORES_NEEDED 3
+#define TEST_INFO_MZ_NAME "test_timer_info_mz"
+#define MSECPERSEC 1E3
+
+#define launch_proc(ARGV) process_dup(ARGV, RTE_DIM(ARGV), __func__)
+
+struct test_info {
+ unsigned int mstr_lcore;
+ unsigned int mgr_lcore;
+ unsigned int sec_lcore;
+ uint32_t timer_data_id;
+ volatile int expected_count;
+ volatile int expired_count;
+ struct rte_mempool *tim_mempool;
+ struct rte_timer *expired_timers[NUM_TIMERS];
+ int expired_timers_idx;
+ volatile int exit_flag;
+};
+
+static int
+timer_secondary_spawn_wait(unsigned int lcore)
+{
+ char coremask[10];
+#ifdef RTE_EXEC_ENV_LINUXAPP
+ char tmp[PATH_MAX] = {0};
+ char prefix[PATH_MAX] = {0};
+
+ get_current_prefix(tmp, sizeof(tmp));
+
+ snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
+#else
+ const char *prefix = "";
+#endif
+ char const *argv[] = {
+ prgname,
+ "-c", coremask,
+ "--proc-type=secondary",
+ prefix
+ };
+
+ snprintf(coremask, sizeof(coremask), "%x", (1 << lcore));
+
+ return launch_proc(argv);
+}
+
+static void
+handle_expired_timer(struct rte_timer *tim)
+{
+ struct test_info *test_info = tim->arg;
+
+ test_info->expired_count++;
+ test_info->expired_timers[test_info->expired_timers_idx++] = tim;
+}
+
+static int
+timer_manage_loop(void *arg)
+{
+#define TICK_MSECS 1
+ uint64_t tick_cycles = TICK_MSECS * rte_get_timer_hz() / MSECPERSEC;
+ uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
+ struct test_info *test_info = arg;
+
+ while (!test_info->exit_flag) {
+ cur_tsc = rte_rdtsc();
+ diff_tsc = cur_tsc - prev_tsc;
+
+ if (diff_tsc > tick_cycles) {
+ /* Scan timer list for expired timers */
+ rte_timer_alt_manage(test_info->timer_data_id,
+ NULL,
+ 0,
+ handle_expired_timer);
+
+ /* Return expired timer objects back to mempool */
+ rte_mempool_put_bulk(test_info->tim_mempool,
+ (void **)test_info->expired_timers,
+ test_info->expired_timers_idx);
+
+ test_info->expired_timers_idx = 0;
+
+ prev_tsc = cur_tsc;
+ }
+
+ rte_pause();
+ }
+
+ return 0;
+}
+
+int
+test_timer_secondary(void)
+{
+ int proc_type = rte_eal_process_type();
+ const struct rte_memzone *mz;
+ struct test_info *test_info;
+ int ret;
+
+ if (proc_type == RTE_PROC_PRIMARY) {
+ if (rte_lcore_count() < NUM_LCORES_NEEDED) {
+ printf("Not enough cores for test_timer_secondary, expecting at least %u\n",
+ NUM_LCORES_NEEDED);
+ return TEST_SKIPPED;
+ }
+
+ mz = rte_memzone_reserve(TEST_INFO_MZ_NAME, sizeof(*test_info),
+ SOCKET_ID_ANY, 0);
+ test_info = mz->addr;
+ TEST_ASSERT_NOT_NULL(test_info, "Couldn't allocate memory for "
+ "test data");
+
+ test_info->tim_mempool = rte_mempool_create("test_timer_mp",
+ NUM_TIMERS, sizeof(struct rte_timer), 0, 0,
+ NULL, NULL, NULL, NULL, rte_socket_id(), 0);
+
+ ret = rte_timer_data_alloc(&test_info->timer_data_id);
+ TEST_ASSERT_SUCCESS(ret, "Failed to allocate timer data "
+ "instance");
+
+ unsigned int *mstr_lcorep = &test_info->mstr_lcore;
+ unsigned int *mgr_lcorep = &test_info->mgr_lcore;
+ unsigned int *sec_lcorep = &test_info->sec_lcore;
+
+ *mstr_lcorep = rte_get_master_lcore();
+ *mgr_lcorep = rte_get_next_lcore(*mstr_lcorep, 1, 1);
+ *sec_lcorep = rte_get_next_lcore(*mgr_lcorep, 1, 1);
+
+ ret = rte_eal_remote_launch(timer_manage_loop,
+ (void *)test_info,
+ *mgr_lcorep);
+ TEST_ASSERT_SUCCESS(ret, "Failed to launch timer manage loop");
+
+ ret = timer_secondary_spawn_wait(*sec_lcorep);
+ TEST_ASSERT_SUCCESS(ret, "Secondary process execution failed");
+
+ rte_delay_ms(2000);
+
+ test_info->exit_flag = 1;
+ rte_eal_wait_lcore(*mgr_lcorep);
+
+#ifdef RTE_LIBRTE_TIMER_DEBUG
+ rte_timer_alt_dump_stats(test_info->timer_data_id, stdout);
+#endif
+
+ return test_info->expected_count == test_info->expired_count ?
+ TEST_SUCCESS : TEST_FAILED;
+
+ } else if (proc_type == RTE_PROC_SECONDARY) {
+ uint64_t ticks, timeout_ms;
+ struct rte_timer *tim;
+ int i;
+
+ mz = rte_memzone_lookup(TEST_INFO_MZ_NAME);
+ test_info = mz->addr;
+ TEST_ASSERT_NOT_NULL(test_info, "Couldn't lookup memzone for "
+ "test info");
+
+ for (i = 0; i < NUM_TIMERS; i++) {
+ rte_mempool_get(test_info->tim_mempool, (void **)&tim);
+
+ rte_timer_init(tim);
+
+ /* generate timeouts between 10 and 160 ms */
+ timeout_ms = ((rte_rand() & 0xF) + 1) * 10;
+ ticks = timeout_ms * rte_get_timer_hz() / MSECPERSEC;
+
+ ret = rte_timer_alt_reset(test_info->timer_data_id,
+ tim, ticks, SINGLE,
+ test_info->mgr_lcore, NULL,
+ test_info);
+ if (ret < 0)
+ return TEST_FAILED;
+
+ test_info->expected_count++;
+
+ /* randomly leave timer running or stop it */
+ if (rte_rand() & 1)
+ continue;
+
+ ret = rte_timer_alt_stop(test_info->timer_data_id,
+ tim);
+ if (ret == 0) {
+ test_info->expected_count--;
+ rte_mempool_put(test_info->tim_mempool,
+ (void *)tim);
+ }
+
+ }
+
+ return TEST_SUCCESS;
+ }
+
+ return TEST_FAILED;
+}
+
+REGISTER_TEST_COMMAND(timer_secondary_autotest, test_timer_secondary);
diff --git a/src/spdk/dpdk/app/test/test_trace.c b/src/spdk/dpdk/app/test/test_trace.c
new file mode 100644
index 000000000..ddcf416b2
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_trace.c
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include <rte_eal_trace.h>
+#include <rte_lcore.h>
+#include <rte_trace.h>
+
+#include "test.h"
+#include "test_trace.h"
+
+static int32_t
+test_trace_point_globbing(void)
+{
+ int rc;
+
+ rc = rte_trace_pattern("app.dpdk.test*", false);
+ if (rc != 1)
+ goto failed;
+
+ if (rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ rc = rte_trace_pattern("app.dpdk.test*", true);
+ if (rc != 1)
+ goto failed;
+
+ if (!rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ rc = rte_trace_pattern("invalid_testpoint.*", true);
+ if (rc != 0)
+ goto failed;
+
+ return TEST_SUCCESS;
+
+failed:
+ return TEST_FAILED;
+}
+
+static int32_t
+test_trace_point_regex(void)
+{
+ int rc;
+
+ rc = rte_trace_regexp("app.dpdk.test*", false);
+ if (rc != 1)
+ goto failed;
+
+ if (rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ rc = rte_trace_regexp("app.dpdk.test*", true);
+ if (rc != 1)
+ goto failed;
+
+ if (!rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ rc = rte_trace_regexp("invalid_testpoint.*", true);
+ if (rc != 0)
+ goto failed;
+
+ return TEST_SUCCESS;
+
+failed:
+ return TEST_FAILED;
+}
+
+static int32_t
+test_trace_point_disable_enable(void)
+{
+ int rc;
+
+ rc = rte_trace_point_disable(&__app_dpdk_test_tp);
+ if (rc < 0)
+ goto failed;
+
+ if (rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ rc = rte_trace_point_enable(&__app_dpdk_test_tp);
+ if (rc < 0)
+ goto failed;
+
+ if (!rte_trace_point_is_enabled(&__app_dpdk_test_tp))
+ goto failed;
+
+ /* Emit the trace */
+ app_dpdk_test_tp("app.dpdk.test.tp");
+ return TEST_SUCCESS;
+
+failed:
+ return TEST_FAILED;
+}
+
+static int
+test_trace_mode(void)
+{
+ enum rte_trace_mode current;
+
+ current = rte_trace_mode_get();
+
+ if (!rte_trace_is_enabled())
+ return TEST_SKIPPED;
+
+ rte_trace_mode_set(RTE_TRACE_MODE_DISCARD);
+ if (rte_trace_mode_get() != RTE_TRACE_MODE_DISCARD)
+ goto failed;
+
+ rte_trace_mode_set(RTE_TRACE_MODE_OVERWRITE);
+ if (rte_trace_mode_get() != RTE_TRACE_MODE_OVERWRITE)
+ goto failed;
+
+ rte_trace_mode_set(current);
+ return TEST_SUCCESS;
+
+failed:
+ return TEST_FAILED;
+
+}
+
+static int
+test_trace_points_lookup(void)
+{
+ rte_trace_point_t *trace;
+
+ trace = rte_trace_point_lookup("app.dpdk.test.tp");
+ if (trace == NULL)
+ goto fail;
+ trace = rte_trace_point_lookup("this_trace_point_does_not_exist");
+ if (trace != NULL)
+ goto fail;
+
+ return TEST_SUCCESS;
+fail:
+ return TEST_FAILED;
+}
+
+static int
+test_fp_trace_points(void)
+{
+ /* Emit the FP trace */
+ app_dpdk_test_fp();
+
+ return TEST_SUCCESS;
+}
+
+static int
+test_generic_trace_points(void)
+{
+ int tmp;
+
+ rte_eal_trace_generic_void();
+ rte_eal_trace_generic_u64(0x10000000000000);
+ rte_eal_trace_generic_u32(0x10000000);
+ rte_eal_trace_generic_u16(0xffee);
+ rte_eal_trace_generic_u8(0xc);
+ rte_eal_trace_generic_i64(-1234);
+ rte_eal_trace_generic_i32(-1234567);
+ rte_eal_trace_generic_i16(12);
+ rte_eal_trace_generic_i8(-3);
+ rte_eal_trace_generic_int(3333333);
+ rte_eal_trace_generic_long(333);
+ rte_eal_trace_generic_float(20.45);
+ rte_eal_trace_generic_double(20000.5000004);
+ rte_eal_trace_generic_ptr(&tmp);
+ rte_eal_trace_generic_str("my string");
+ RTE_EAL_TRACE_GENERIC_FUNC;
+
+ return TEST_SUCCESS;
+}
+
+static struct unit_test_suite trace_tests = {
+ .suite_name = "trace autotest",
+ .setup = NULL,
+ .teardown = NULL,
+ .unit_test_cases = {
+ TEST_CASE(test_trace_mode),
+ TEST_CASE(test_generic_trace_points),
+ TEST_CASE(test_fp_trace_points),
+ TEST_CASE(test_trace_point_disable_enable),
+ TEST_CASE(test_trace_point_globbing),
+ TEST_CASE(test_trace_point_regex),
+ TEST_CASE(test_trace_points_lookup),
+ TEST_CASES_END()
+ }
+};
+
+static int
+test_trace(void)
+{
+ return unit_test_suite_runner(&trace_tests);
+}
+
+REGISTER_TEST_COMMAND(trace_autotest, test_trace);
+
+static int
+test_trace_dump(void)
+{
+ rte_trace_dump(stdout);
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(trace_dump, test_trace_dump);
+
+static int
+test_trace_metadata_dump(void)
+{
+ return rte_trace_metadata_dump(stdout);
+}
+
+REGISTER_TEST_COMMAND(trace_metadata_dump, test_trace_metadata_dump);
diff --git a/src/spdk/dpdk/app/test/test_trace.h b/src/spdk/dpdk/app/test/test_trace.h
new file mode 100644
index 000000000..413842f60
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_trace.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+#include <rte_trace_point.h>
+
+RTE_TRACE_POINT(
+ app_dpdk_test_tp,
+ RTE_TRACE_POINT_ARGS(const char *str),
+ rte_trace_point_emit_string(str);
+)
+
+RTE_TRACE_POINT_FP(
+ app_dpdk_test_fp,
+ RTE_TRACE_POINT_ARGS(void),
+)
diff --git a/src/spdk/dpdk/app/test/test_trace_perf.c b/src/spdk/dpdk/app/test/test_trace_perf.c
new file mode 100644
index 000000000..50c7381b7
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_trace_perf.c
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include <rte_cycles.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_eal_trace.h>
+#include <rte_malloc.h>
+#include <rte_lcore.h>
+
+#include "test.h"
+#include "test_trace.h"
+
+struct test_data;
+
+struct lcore_data {
+ volatile bool done;
+ volatile bool started;
+ uint64_t total_cycles;
+ uint64_t total_calls;
+} __rte_cache_aligned;
+
+struct test_data {
+ unsigned int nb_workers;
+ struct lcore_data ldata[];
+} __rte_cache_aligned;
+
+#define STEP 100
+#define CENT_OPS(OP) do { \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+OP; OP; OP; OP; OP; OP; OP; OP; OP; OP; \
+} while (0)
+
+static void
+measure_perf(const char *str, struct test_data *data)
+{
+ uint64_t hz = rte_get_timer_hz();
+ uint64_t total_cycles = 0;
+ uint64_t total_calls = 0;
+ double cycles, ns;
+ unsigned int workers;
+
+ for (workers = 0; workers < data->nb_workers; workers++) {
+ total_cycles += data->ldata[workers].total_cycles;
+ total_calls += data->ldata[workers].total_calls;
+ }
+
+ cycles = total_calls ? (double)total_cycles / (double)total_calls : 0;
+ cycles /= STEP;
+ cycles /= 100; /* CENT_OPS */
+
+ ns = (cycles / (double)hz) * 1E9;
+ printf("%16s: cycles=%f ns=%f\n", str, cycles, ns);
+}
+
+static void
+wait_till_workers_are_ready(struct test_data *data)
+{
+ unsigned int workers;
+
+ for (workers = 0; workers < data->nb_workers; workers++)
+ while (!data->ldata[workers].started)
+ rte_pause();
+}
+
+static void
+signal_workers_to_finish(struct test_data *data)
+{
+ unsigned int workers;
+
+ for (workers = 0; workers < data->nb_workers; workers++) {
+ data->ldata[workers].done = 1;
+ rte_smp_wmb();
+ }
+}
+
+#define WORKER_DEFINE(func) \
+static void __rte_noinline \
+__worker_##func(struct lcore_data *ldata) \
+{ \
+ uint64_t start; \
+ int i; \
+ while (!ldata->done) { \
+ start = rte_get_timer_cycles(); \
+ for (i = 0; i < STEP; i++) \
+ CENT_OPS(func); \
+ ldata->total_cycles += rte_get_timer_cycles() - start; \
+ ldata->total_calls++; \
+ } \
+} \
+static int \
+worker_fn_##func(void *arg) \
+{ \
+ struct lcore_data *ldata = arg; \
+ ldata->started = 1; \
+ rte_smp_wmb(); \
+ __worker_##func(ldata); \
+ return 0; \
+}
+
+
+/* Test to find trace overhead */
+#define GENERIC_VOID rte_eal_trace_generic_void()
+#define GENERIC_U64 rte_eal_trace_generic_u64(0x120000)
+#define GENERIC_INT rte_eal_trace_generic_int(-34)
+#define GENERIC_FLOAT rte_eal_trace_generic_float(3.3f)
+#define GENERIC_DOUBLE rte_eal_trace_generic_double(3.66666)
+#define GENERIC_STR rte_eal_trace_generic_str("hello world")
+#define VOID_FP app_dpdk_test_fp()
+
+WORKER_DEFINE(GENERIC_VOID)
+WORKER_DEFINE(GENERIC_U64)
+WORKER_DEFINE(GENERIC_INT)
+WORKER_DEFINE(GENERIC_FLOAT)
+WORKER_DEFINE(GENERIC_DOUBLE)
+WORKER_DEFINE(GENERIC_STR)
+WORKER_DEFINE(VOID_FP)
+
+static void
+run_test(const char *str, lcore_function_t f, struct test_data *data, size_t sz)
+{
+ unsigned int id, worker = 0;
+
+ memset(data, 0, sz);
+ data->nb_workers = rte_lcore_count() - 1;
+ RTE_LCORE_FOREACH_SLAVE(id)
+ rte_eal_remote_launch(f, &data->ldata[worker++], id);
+
+ wait_till_workers_are_ready(data);
+ rte_delay_ms(100); /* Wait for some time to accumulate the stats */
+ measure_perf(str, data);
+ signal_workers_to_finish(data);
+
+ RTE_LCORE_FOREACH_SLAVE(id)
+ rte_eal_wait_lcore(id);
+}
+
+static int
+test_trace_perf(void)
+{
+ unsigned int nb_cores, nb_workers;
+ struct test_data *data;
+ size_t sz;
+
+ nb_cores = rte_lcore_count();
+ nb_workers = nb_cores - 1;
+ if (nb_cores < 2) {
+ printf("Need minimum two cores for testing\n");
+ return TEST_SKIPPED;
+ }
+
+ printf("Timer running at %5.2fMHz\n", rte_get_timer_hz()/1E6);
+ sz = sizeof(struct test_data);
+ sz += nb_workers * sizeof(struct lcore_data);
+
+ data = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
+ if (data == NULL) {
+ printf("Failed to allocate memory\n");
+ return TEST_FAILED;
+ }
+
+ run_test("void", worker_fn_GENERIC_VOID, data, sz);
+ run_test("u64", worker_fn_GENERIC_U64, data, sz);
+ run_test("int", worker_fn_GENERIC_INT, data, sz);
+ run_test("float", worker_fn_GENERIC_FLOAT, data, sz);
+ run_test("double", worker_fn_GENERIC_DOUBLE, data, sz);
+ run_test("string", worker_fn_GENERIC_STR, data, sz);
+ run_test("void_fp", worker_fn_VOID_FP, data, sz);
+
+ rte_free(data);
+ return TEST_SUCCESS;
+}
+
+REGISTER_TEST_COMMAND(trace_perf_autotest, test_trace_perf);
diff --git a/src/spdk/dpdk/app/test/test_trace_register.c b/src/spdk/dpdk/app/test/test_trace_register.c
new file mode 100644
index 000000000..b9372d3f9
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_trace_register.c
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include <rte_trace_point_register.h>
+
+#include "test_trace.h"
+
+/* Define trace points */
+RTE_TRACE_POINT_DEFINE(app_dpdk_test_tp);
+RTE_TRACE_POINT_DEFINE(app_dpdk_test_fp);
+
+RTE_INIT(register_valid_trace_points)
+{
+ RTE_TRACE_POINT_REGISTER(app_dpdk_test_tp, app.dpdk.test.tp);
+ RTE_TRACE_POINT_REGISTER(app_dpdk_test_fp, app.dpdk.test.fp);
+}
+
diff --git a/src/spdk/dpdk/app/test/test_version.c b/src/spdk/dpdk/app/test/test_version.c
new file mode 100644
index 000000000..1e1ff1865
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_version.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_version.h>
+
+#include "test.h"
+
+
+static int
+test_version(void)
+{
+ const char *version = rte_version();
+ if (version == NULL)
+ return -1;
+ printf("Version string: '%s'\n", version);
+ if (*version == '\0' ||
+ strncmp(version, RTE_VER_PREFIX, sizeof(RTE_VER_PREFIX)-1) != 0)
+ return -1;
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(version_autotest, test_version);
diff --git a/src/spdk/dpdk/app/test/test_xmmt_ops.h b/src/spdk/dpdk/app/test/test_xmmt_ops.h
new file mode 100644
index 000000000..8bcf0b261
--- /dev/null
+++ b/src/spdk/dpdk/app/test/test_xmmt_ops.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015 Cavium, Inc
+ */
+
+#ifndef _TEST_XMMT_OPS_H_
+#define _TEST_XMMT_OPS_H_
+
+#include <rte_vect.h>
+
+#if defined(RTE_ARCH_ARM) || defined(RTE_ARCH_ARM64)
+
+/* vect_* abstraction implementation using NEON */
+
+/* loads the xmm_t value from address p(does not need to be 16-byte aligned)*/
+#define vect_loadu_sil128(p) vld1q_s32((const int32_t *)p)
+
+/* sets the 4 signed 32-bit integer values and returns the xmm_t variable */
+static __rte_always_inline xmm_t
+vect_set_epi32(int i3, int i2, int i1, int i0)
+{
+ int32_t data[4] = {i0, i1, i2, i3};
+
+ return vld1q_s32(data);
+}
+
+#elif defined(RTE_ARCH_X86)
+
+/* vect_* abstraction implementation using SSE */
+
+/* loads the xmm_t value from address p(does not need to be 16-byte aligned)*/
+#define vect_loadu_sil128(p) _mm_loadu_si128(p)
+
+/* sets the 4 signed 32-bit integer values and returns the xmm_t variable */
+#define vect_set_epi32(i3, i2, i1, i0) _mm_set_epi32(i3, i2, i1, i0)
+
+#elif defined(RTE_ARCH_PPC_64)
+
+/* vect_* abstraction implementation using ALTIVEC */
+
+/* loads the xmm_t value from address p(does not need to be 16-byte aligned)*/
+#define vect_loadu_sil128(p) vec_ld(0, p)
+
+/* sets the 4 signed 32-bit integer values and returns the xmm_t variable */
+static __rte_always_inline xmm_t
+vect_set_epi32(int i3, int i2, int i1, int i0)
+{
+ xmm_t data = (xmm_t){i0, i1, i2, i3};
+
+ return data;
+}
+
+#endif
+
+#endif /* _TEST_XMMT_OPS_H_ */
diff --git a/src/spdk/dpdk/app/test/virtual_pmd.c b/src/spdk/dpdk/app/test/virtual_pmd.c
new file mode 100644
index 000000000..79156cb85
--- /dev/null
+++ b/src/spdk/dpdk/app/test/virtual_pmd.c
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#include <rte_mbuf.h>
+#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_memory.h>
+#include <rte_ring.h>
+
+#include "virtual_pmd.h"
+
+#define MAX_PKT_BURST 512
+
+static const char *virtual_ethdev_driver_name = "Virtual PMD";
+
+struct virtual_ethdev_private {
+ struct eth_dev_ops dev_ops;
+ struct rte_eth_stats eth_stats;
+
+ struct rte_ring *rx_queue;
+ struct rte_ring *tx_queue;
+
+ int tx_burst_fail_count;
+};
+
+struct virtual_ethdev_queue {
+ int port_id;
+ int queue_id;
+};
+
+static int
+virtual_ethdev_start_success(struct rte_eth_dev *eth_dev __rte_unused)
+{
+ eth_dev->data->dev_started = 1;
+
+ return 0;
+}
+
+static int
+virtual_ethdev_start_fail(struct rte_eth_dev *eth_dev __rte_unused)
+{
+ eth_dev->data->dev_started = 0;
+
+ return -1;
+}
+static void virtual_ethdev_stop(struct rte_eth_dev *eth_dev __rte_unused)
+{
+ void *pkt = NULL;
+ struct virtual_ethdev_private *prv = eth_dev->data->dev_private;
+
+ eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ eth_dev->data->dev_started = 0;
+ while (rte_ring_dequeue(prv->rx_queue, &pkt) != -ENOENT)
+ rte_pktmbuf_free(pkt);
+
+ while (rte_ring_dequeue(prv->tx_queue, &pkt) != -ENOENT)
+ rte_pktmbuf_free(pkt);
+}
+
+static void
+virtual_ethdev_close(struct rte_eth_dev *dev __rte_unused)
+{}
+
+static int
+virtual_ethdev_configure_success(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+virtual_ethdev_configure_fail(struct rte_eth_dev *dev __rte_unused)
+{
+ return -1;
+}
+
+static int
+virtual_ethdev_info_get(struct rte_eth_dev *dev __rte_unused,
+ struct rte_eth_dev_info *dev_info)
+{
+ dev_info->driver_name = virtual_ethdev_driver_name;
+ dev_info->max_mac_addrs = 1;
+
+ dev_info->max_rx_pktlen = (uint32_t)2048;
+
+ dev_info->max_rx_queues = (uint16_t)128;
+ dev_info->max_tx_queues = (uint16_t)512;
+
+ dev_info->min_rx_bufsize = 0;
+
+ return 0;
+}
+
+static int
+virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mb_pool __rte_unused)
+{
+ struct virtual_ethdev_queue *rx_q;
+
+ rx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
+ sizeof(struct virtual_ethdev_queue), 0, socket_id);
+
+ if (rx_q == NULL)
+ return -1;
+
+ rx_q->port_id = dev->data->port_id;
+ rx_q->queue_id = rx_queue_id;
+
+ dev->data->rx_queues[rx_queue_id] = rx_q;
+
+ return 0;
+}
+
+static int
+virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
+ uint16_t rx_queue_id __rte_unused, uint16_t nb_rx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_rxconf *rx_conf __rte_unused,
+ struct rte_mempool *mb_pool __rte_unused)
+{
+ return -1;
+}
+
+static int
+virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ struct virtual_ethdev_queue *tx_q;
+
+ tx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
+ sizeof(struct virtual_ethdev_queue), 0, socket_id);
+
+ if (tx_q == NULL)
+ return -1;
+
+ tx_q->port_id = dev->data->port_id;
+ tx_q->queue_id = tx_queue_id;
+
+ dev->data->tx_queues[tx_queue_id] = tx_q;
+
+ return 0;
+}
+
+static int
+virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
+ uint16_t tx_queue_id __rte_unused, uint16_t nb_tx_desc __rte_unused,
+ unsigned int socket_id __rte_unused,
+ const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+ return -1;
+}
+
+static void
+virtual_ethdev_rx_queue_release(void *q __rte_unused)
+{
+}
+
+static void
+virtual_ethdev_tx_queue_release(void *q __rte_unused)
+{
+}
+
+static int
+virtual_ethdev_link_update_success(struct rte_eth_dev *bonded_eth_dev,
+ int wait_to_complete __rte_unused)
+{
+ if (!bonded_eth_dev->data->dev_started)
+ bonded_eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+
+ return 0;
+}
+
+static int
+virtual_ethdev_link_update_fail(struct rte_eth_dev *bonded_eth_dev __rte_unused,
+ int wait_to_complete __rte_unused)
+{
+ return -1;
+}
+
+static int
+virtual_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+
+ if (stats)
+ rte_memcpy(stats, &dev_private->eth_stats, sizeof(*stats));
+
+ return 0;
+}
+
+static int
+virtual_ethdev_stats_reset(struct rte_eth_dev *dev)
+{
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ void *pkt = NULL;
+
+ while (rte_ring_dequeue(dev_private->tx_queue, &pkt) == -ENOBUFS)
+ rte_pktmbuf_free(pkt);
+
+ /* Reset internal statistics */
+ memset(&dev_private->eth_stats, 0, sizeof(dev_private->eth_stats));
+
+ return 0;
+}
+
+static int
+virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+virtual_ethdev_mac_address_set(__rte_unused struct rte_eth_dev *dev,
+ __rte_unused struct rte_ether_addr *addr)
+{
+ return 0;
+}
+
+static const struct eth_dev_ops virtual_ethdev_default_dev_ops = {
+ .dev_configure = virtual_ethdev_configure_success,
+ .dev_start = virtual_ethdev_start_success,
+ .dev_stop = virtual_ethdev_stop,
+ .dev_close = virtual_ethdev_close,
+ .dev_infos_get = virtual_ethdev_info_get,
+ .rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
+ .tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
+ .rx_queue_release = virtual_ethdev_rx_queue_release,
+ .tx_queue_release = virtual_ethdev_tx_queue_release,
+ .link_update = virtual_ethdev_link_update_success,
+ .mac_addr_set = virtual_ethdev_mac_address_set,
+ .stats_get = virtual_ethdev_stats_get,
+ .stats_reset = virtual_ethdev_stats_reset,
+ .promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
+ .promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
+};
+
+void
+virtual_ethdev_start_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
+
+ if (success)
+ dev_ops->dev_start = virtual_ethdev_start_success;
+ else
+ dev_ops->dev_start = virtual_ethdev_start_fail;
+
+}
+
+void
+virtual_ethdev_configure_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
+
+ if (success)
+ dev_ops->dev_configure = virtual_ethdev_configure_success;
+ else
+ dev_ops->dev_configure = virtual_ethdev_configure_fail;
+}
+
+void
+virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
+
+ if (success)
+ dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_success;
+ else
+ dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_fail;
+}
+
+void
+virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
+
+ if (success)
+ dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_success;
+ else
+ dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_fail;
+}
+
+void
+virtual_ethdev_link_update_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private = dev->data->dev_private;
+ struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
+
+ if (success)
+ dev_ops->link_update = virtual_ethdev_link_update_success;
+ else
+ dev_ops->link_update = virtual_ethdev_link_update_fail;
+}
+
+
+static uint16_t
+virtual_ethdev_rx_burst_success(void *queue __rte_unused,
+ struct rte_mbuf **bufs,
+ uint16_t nb_pkts)
+{
+ struct rte_eth_dev *vrtl_eth_dev;
+ struct virtual_ethdev_queue *pq_map;
+ struct virtual_ethdev_private *dev_private;
+
+ int rx_count, i;
+
+ pq_map = (struct virtual_ethdev_queue *)queue;
+ vrtl_eth_dev = &rte_eth_devices[pq_map->port_id];
+ dev_private = vrtl_eth_dev->data->dev_private;
+
+ rx_count = rte_ring_dequeue_burst(dev_private->rx_queue, (void **) bufs,
+ nb_pkts, NULL);
+
+ /* increments ipackets count */
+ dev_private->eth_stats.ipackets += rx_count;
+
+ /* increments ibytes count */
+ for (i = 0; i < rx_count; i++)
+ dev_private->eth_stats.ibytes += rte_pktmbuf_pkt_len(bufs[i]);
+
+ return rx_count;
+}
+
+static uint16_t
+virtual_ethdev_rx_burst_fail(void *queue __rte_unused,
+ struct rte_mbuf **bufs __rte_unused,
+ uint16_t nb_pkts __rte_unused)
+{
+ return 0;
+}
+
+static uint16_t
+virtual_ethdev_tx_burst_success(void *queue, struct rte_mbuf **bufs,
+ uint16_t nb_pkts)
+{
+ struct virtual_ethdev_queue *tx_q = queue;
+
+ struct rte_eth_dev *vrtl_eth_dev;
+ struct virtual_ethdev_private *dev_private;
+
+ int i;
+
+ vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
+ dev_private = vrtl_eth_dev->data->dev_private;
+
+ if (!vrtl_eth_dev->data->dev_link.link_status)
+ nb_pkts = 0;
+ else
+ nb_pkts = rte_ring_enqueue_burst(dev_private->tx_queue, (void **)bufs,
+ nb_pkts, NULL);
+
+ /* increment opacket count */
+ dev_private->eth_stats.opackets += nb_pkts;
+
+ /* increment obytes count */
+ for (i = 0; i < nb_pkts; i++)
+ dev_private->eth_stats.obytes += rte_pktmbuf_pkt_len(bufs[i]);
+
+ return nb_pkts;
+}
+
+static uint16_t
+virtual_ethdev_tx_burst_fail(void *queue, struct rte_mbuf **bufs,
+ uint16_t nb_pkts)
+{
+ struct rte_eth_dev *vrtl_eth_dev = NULL;
+ struct virtual_ethdev_queue *tx_q = NULL;
+ struct virtual_ethdev_private *dev_private = NULL;
+
+ int i;
+
+ tx_q = queue;
+ vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
+ dev_private = vrtl_eth_dev->data->dev_private;
+
+ if (dev_private->tx_burst_fail_count < nb_pkts) {
+ int successfully_txd = nb_pkts - dev_private->tx_burst_fail_count;
+
+ /* increment opacket count */
+ dev_private->eth_stats.opackets += successfully_txd;
+
+ /* free packets in burst */
+ for (i = 0; i < successfully_txd; i++) {
+ /* free packets in burst */
+ if (bufs[i] != NULL)
+ rte_pktmbuf_free(bufs[i]);
+
+ bufs[i] = NULL;
+ }
+
+ return successfully_txd;
+ }
+
+ return 0;
+}
+
+
+void
+virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ if (success)
+ vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
+ else
+ vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_fail;
+}
+
+
+void
+virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id, uint8_t success)
+{
+ struct virtual_ethdev_private *dev_private = NULL;
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ dev_private = vrtl_eth_dev->data->dev_private;
+
+ if (success)
+ vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
+ else
+ vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail;
+
+ dev_private->tx_burst_fail_count = 0;
+}
+
+void
+virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,
+ uint8_t packet_fail_count)
+{
+ struct virtual_ethdev_private *dev_private = NULL;
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+
+ dev_private = vrtl_eth_dev->data->dev_private;
+ dev_private->tx_burst_fail_count = packet_fail_count;
+}
+
+void
+virtual_ethdev_set_link_status(uint16_t port_id, uint8_t link_status)
+{
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ vrtl_eth_dev->data->dev_link.link_status = link_status;
+}
+
+void
+virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,
+ uint8_t link_status)
+{
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ vrtl_eth_dev->data->dev_link.link_status = link_status;
+
+ _rte_eth_dev_callback_process(vrtl_eth_dev, RTE_ETH_EVENT_INTR_LSC,
+ NULL);
+}
+
+int
+virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,
+ struct rte_mbuf **pkt_burst, int burst_length)
+{
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+ struct virtual_ethdev_private *dev_private =
+ vrtl_eth_dev->data->dev_private;
+
+ return rte_ring_enqueue_burst(dev_private->rx_queue, (void **)pkt_burst,
+ burst_length, NULL);
+}
+
+int
+virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,
+ struct rte_mbuf **pkt_burst, int burst_length)
+{
+ struct virtual_ethdev_private *dev_private;
+ struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
+
+ dev_private = vrtl_eth_dev->data->dev_private;
+ return rte_ring_dequeue_burst(dev_private->tx_queue, (void **)pkt_burst,
+ burst_length, NULL);
+}
+
+
+int
+virtual_ethdev_create(const char *name, struct rte_ether_addr *mac_addr,
+ uint8_t socket_id, uint8_t isr_support)
+{
+ struct rte_pci_device *pci_dev = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+ struct rte_pci_driver *pci_drv = NULL;
+ struct rte_pci_id *id_table = NULL;
+ struct virtual_ethdev_private *dev_private = NULL;
+ char name_buf[RTE_RING_NAMESIZE];
+
+
+ /* now do all data allocation - for eth_dev structure, dummy pci driver
+ * and internal (dev_private) data
+ */
+
+ pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
+ if (pci_dev == NULL)
+ goto err;
+
+ pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
+ if (pci_drv == NULL)
+ goto err;
+
+ id_table = rte_zmalloc_socket(name, sizeof(*id_table), 0, socket_id);
+ if (id_table == NULL)
+ goto err;
+ id_table->device_id = 0xBEEF;
+
+ dev_private = rte_zmalloc_socket(name, sizeof(*dev_private), 0, socket_id);
+ if (dev_private == NULL)
+ goto err;
+
+ snprintf(name_buf, sizeof(name_buf), "%s_rxQ", name);
+ dev_private->rx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
+ 0);
+ if (dev_private->rx_queue == NULL)
+ goto err;
+
+ snprintf(name_buf, sizeof(name_buf), "%s_txQ", name);
+ dev_private->tx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
+ 0);
+ if (dev_private->tx_queue == NULL)
+ goto err;
+
+ /* reserve an ethdev entry */
+ eth_dev = rte_eth_dev_allocate(name);
+ if (eth_dev == NULL)
+ goto err;
+
+ pci_dev->device.numa_node = socket_id;
+ pci_dev->device.name = eth_dev->data->name;
+ pci_drv->driver.name = virtual_ethdev_driver_name;
+ pci_drv->id_table = id_table;
+
+ if (isr_support)
+ pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC;
+ else
+ pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
+
+
+ eth_dev->device = &pci_dev->device;
+ eth_dev->device->driver = &pci_drv->driver;
+
+ eth_dev->data->nb_rx_queues = (uint16_t)1;
+ eth_dev->data->nb_tx_queues = (uint16_t)1;
+
+ eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_10G;
+ eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+
+ eth_dev->data->mac_addrs = rte_zmalloc(name, RTE_ETHER_ADDR_LEN, 0);
+ if (eth_dev->data->mac_addrs == NULL)
+ goto err;
+
+ memcpy(eth_dev->data->mac_addrs, mac_addr,
+ sizeof(*eth_dev->data->mac_addrs));
+
+ eth_dev->data->dev_started = 0;
+ eth_dev->data->promiscuous = 0;
+ eth_dev->data->scattered_rx = 0;
+ eth_dev->data->all_multicast = 0;
+
+ eth_dev->data->dev_private = dev_private;
+
+ /* Copy default device operation functions */
+ dev_private->dev_ops = virtual_ethdev_default_dev_ops;
+ eth_dev->dev_ops = &dev_private->dev_ops;
+
+ pci_dev->device.driver = &pci_drv->driver;
+ eth_dev->device = &pci_dev->device;
+
+ eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
+ eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
+
+ rte_eth_dev_probing_finish(eth_dev);
+
+ return eth_dev->data->port_id;
+
+err:
+ rte_free(pci_dev);
+ rte_free(pci_drv);
+ rte_free(id_table);
+ rte_free(dev_private);
+
+ return -1;
+}
diff --git a/src/spdk/dpdk/app/test/virtual_pmd.h b/src/spdk/dpdk/app/test/virtual_pmd.h
new file mode 100644
index 000000000..120b58b27
--- /dev/null
+++ b/src/spdk/dpdk/app/test/virtual_pmd.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef __VIRTUAL_ETHDEV_H_
+#define __VIRTUAL_ETHDEV_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_ether.h>
+
+int
+virtual_ethdev_init(void);
+
+int
+virtual_ethdev_create(const char *name, struct rte_ether_addr *mac_addr,
+ uint8_t socket_id, uint8_t isr_support);
+
+void
+virtual_ethdev_set_link_status(uint16_t port_id, uint8_t link_status);
+
+void
+virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,
+ uint8_t link_status);
+
+int
+virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,
+ struct rte_mbuf **pkts_burst, int burst_length);
+
+int
+virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,
+ struct rte_mbuf **pkt_burst, int burst_length);
+
+/** Control methods for the dev_ops functions pointer to control the behavior
+ * of the Virtual PMD */
+
+void
+virtual_ethdev_start_fn_set_success(uint16_t port_id, uint8_t success);
+
+void
+virtual_ethdev_stop_fn_set_success(uint16_t port_id, uint8_t success);
+
+void
+virtual_ethdev_configure_fn_set_success(uint16_t port_id, uint8_t success);
+
+void
+virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id,
+ uint8_t success);
+
+void
+virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id,
+ uint8_t success);
+
+void
+virtual_ethdev_link_update_fn_set_success(uint16_t port_id, uint8_t success);
+
+void
+virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id, uint8_t success);
+
+void
+virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id, uint8_t success);
+
+/* if a value greater than zero is set for packet_fail_count then virtual
+ * device tx burst function will fail that many packet from burst or all
+ * packets if packet_fail_count is greater than the number of packets in the
+ * burst */
+void
+virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,
+ uint8_t packet_fail_count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VIRTUAL_ETHDEV_H_ */